From ae498992645fbf241258bc55e4d28d39a20a5a38 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:20:23 -0400 Subject: [PATCH 001/296] feat: add backend package manager module and VPP board support Add PackageManagerModule for importing, listing, and uninstalling VPP packages. Extend HardwareModule to merge VPP boards into available boards list and support package-relative preview images. Add VPP fallback to CompilerModule's board runtime resolution. Co-Authored-By: Claude Opus 4.6 (1M context) --- package-lock.json | 12 +- package.json | 1 + .../editor/compiler/compiler-module.ts | 24 ++- .../editor/hardware/hardware-module.ts | 80 +++++++++- src/backend/editor/hardware/types.ts | 51 +++++-- src/backend/editor/package-manager/index.ts | 2 + .../package-manager/package-manager-module.ts | 141 ++++++++++++++++++ src/backend/editor/package-manager/types.ts | 109 ++++++++++++++ 8 files changed, 393 insertions(+), 27 deletions(-) create mode 100644 src/backend/editor/package-manager/index.ts create mode 100644 src/backend/editor/package-manager/package-manager-module.ts create mode 100644 src/backend/editor/package-manager/types.ts diff --git a/package-lock.json b/package-lock.json index 4d83d74c7..3002de80e 100644 --- a/package-lock.json +++ b/package-lock.json @@ -45,6 +45,7 @@ "electron-store": "^8.1.0", "electron-updater": "^6.1.4", "embla-carousel-react": "^8.0.0-rc17", + "extract-zip": "^2.0.1", "i18next": "^23.5.1", "immer": "^10.1.1", "lodash": "^4.17.21", @@ -10196,7 +10197,6 @@ "version": "2.10.3", "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, "license": "MIT", "optional": true, "dependencies": { @@ -11889,7 +11889,6 @@ "version": "0.2.13", "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-0.2.13.tgz", "integrity": "sha512-VO9Ht/+p3SN7SKWqcrgEzjGbRSJYTx+Q1pTQC0wrWqHx0vpJraQ6GtHx8tvcg1rlK1byhU5gccxgOgj7B0TDkQ==", - "dev": true, "license": "MIT", "engines": { "node": "*" @@ -14712,7 +14711,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "license": "MIT", "dependencies": { "once": "^1.4.0" @@ -15511,7 +15509,6 @@ "version": "2.0.1", "resolved": "https://registry.npmjs.org/extract-zip/-/extract-zip-2.0.1.tgz", "integrity": "sha512-GDhU9ntwuKyGXdZBUgTIe+vXnWj0fppUEtMDL0+idd5Sta8TGpHssn/eusA9mrPr9qNDym6SxAYZjNvCn/9RBg==", - "dev": true, "license": "BSD-2-Clause", "dependencies": { "debug": "^4.1.1", @@ -15632,7 +15629,6 @@ "version": "1.1.0", "resolved": "https://registry.npmjs.org/fd-slicer/-/fd-slicer-1.1.0.tgz", "integrity": "sha512-cE1qsB/VwyQozZ+q1dGxR8LBYNZeofhEdUNGSMbQD3Gw2lAzX9Zb3uIU6Ebc/Fmyjo9AWWfnn0AUCHqtevs/8g==", - "dev": true, "license": "MIT", "dependencies": { "pend": "~1.2.0" @@ -16079,7 +16075,6 @@ "version": "5.2.0", "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz", "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==", - "dev": true, "license": "MIT", "dependencies": { "pump": "^3.0.0" @@ -23216,7 +23211,6 @@ "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", - "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" @@ -23660,7 +23654,6 @@ "version": "1.2.0", "resolved": "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz", "integrity": "sha512-F3asv42UuXchdzt+xXqfW1OGlVBe+mxa2mqI0pg5yAHZPvFmY3Y6drSf/GQ1A86WgWEN9Kzh/WrgKa6iGcHXLg==", - "dev": true, "license": "MIT" }, "node_modules/picocolors": { @@ -24868,7 +24861,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "license": "MIT", "dependencies": { "end-of-stream": "^1.1.0", @@ -29495,7 +29487,6 @@ "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", - "dev": true, "license": "ISC" }, "node_modules/ws": { @@ -29667,7 +29658,6 @@ "version": "2.10.0", "resolved": "https://registry.npmjs.org/yauzl/-/yauzl-2.10.0.tgz", "integrity": "sha512-p4a9I6X6nu6IhoGmBqAcbJy1mlC4j27vEPZX9F4L4/vZT3Lyq1VkFHw/V/PUcB9Buo+DG3iHkT0x3Qya58zc3g==", - "dev": true, "license": "MIT", "dependencies": { "buffer-crc32": "~0.2.3", diff --git a/package.json b/package.json index a9958b33e..c97c370a6 100644 --- a/package.json +++ b/package.json @@ -67,6 +67,7 @@ "electron-store": "^8.1.0", "electron-updater": "^6.1.4", "embla-carousel-react": "^8.0.0-rc17", + "extract-zip": "^2.0.1", "i18next": "^23.5.1", "immer": "^10.1.1", "lodash": "^4.17.21", diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index 9c19d9a5a..0c14707c9 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -30,6 +30,7 @@ import { app as electronApp, dialog } from 'electron' import type { MessagePortMain } from 'electron/main' import JSZip from 'jszip' +import { PackageManagerModule } from '../package-manager' import { CreateXMLFile } from '../utils' import type { ArduinoCoreControl, HalsFile } from './types' import { FormatMacAddress } from './utils/formatters' @@ -183,7 +184,28 @@ class CompilerModule { async #getBoardRuntime(board: string) { const halsFileContent = await CompilerModule.readJSONFile(this.halsFilePath) - return halsFileContent[board]['compiler'] + if (halsFileContent[board]) { + return halsFileContent[board]['compiler'] + } + + // Fallback: check installed VPP packages for the board + try { + const packageManager = new PackageManagerModule() + const installed = packageManager.listInstalled() + for (const pkg of installed) { + const manifest = packageManager.getInstalledPackageManifest(pkg.packageId) + if (!manifest) continue + for (const device of manifest.devices) { + if (device.name === board) { + return device.target.type === 'runtime-v4' ? 'openplc-compiler' : 'arduino-cli' + } + } + } + } catch { + // ignore package manager errors + } + + throw new Error(`Board "${board}" not found in hals.json or installed VPP packages`) } #executeXml2st(args: string[]) { diff --git a/src/backend/editor/hardware/hardware-module.ts b/src/backend/editor/hardware/hardware-module.ts index 350ba3246..2485e8217 100644 --- a/src/backend/editor/hardware/hardware-module.ts +++ b/src/backend/editor/hardware/hardware-module.ts @@ -1,4 +1,5 @@ import { exec } from 'node:child_process' +import { existsSync } from 'node:fs' import { readFile } from 'node:fs/promises' import { join } from 'node:path' import { promisify } from 'node:util' @@ -6,6 +7,7 @@ import { promisify } from 'node:util' import { app as electronApp } from 'electron' import { produce } from 'immer' +import { PackageManagerModule } from '../package-manager' import type { AvailableBoards, HalsFile, SerialPort } from './types' // interface MethodsResult { @@ -182,13 +184,85 @@ class HardwareModule { }) }) } + // Merge boards from installed VPP packages + const mutableBoards: AvailableBoards = new Map(availableBoards) + await this.#mergeVppBoards(mutableBoards) + // Sort boards alphabetically by name - const sortedBoards: AvailableBoards = new Map([...availableBoards.entries()].sort(([a], [b]) => a.localeCompare(b))) + const sortedBoards: AvailableBoards = new Map([...mutableBoards.entries()].sort(([a], [b]) => a.localeCompare(b))) return sortedBoards } - async getBoardImagePreview(image: string) { - const imagePath = join(this.sourcesDirectoryPath, 'boards', 'previews', image) + async #mergeVppBoards(boards: AvailableBoards): Promise { + try { + const packageManager = new PackageManagerModule() + const installed = packageManager.listInstalled() + for (const pkg of installed) { + const manifest = packageManager.getInstalledPackageManifest(pkg.packageId) + if (!manifest) continue + + for (const device of manifest.devices) { + // Read all screen definitions + const screens: Record = {} + if (device.screens) { + for (const [screenName, screenFile] of Object.entries(device.screens)) { + const screenPath = join(pkg.path, screenFile) + if (existsSync(screenPath)) { + try { + screens[screenName] = await HardwareModule.readJSONFile(screenPath) + } catch { + /* ignore invalid screen */ + } + } + } + } + + // Map target type to compiler + const compiler = device.target.type === 'runtime-v4' ? 'openplc-compiler' : 'arduino-cli' + + boards.set(device.name, { + compiler, + core: device.target.core ?? '', + preview: device.preview, + specs: device.specs ?? {}, + pins: { + defaultDin: device.defaults?.pins?.defaultDin, + defaultDout: device.defaults?.pins?.defaultDout, + defaultAin: device.defaults?.pins?.defaultAin, + defaultAout: device.defaults?.pins?.defaultAout, + }, + vpp: { + packageId: manifest.package.id, + deviceId: device.id, + packagePath: pkg.path, + screens, + moduleSystem: device.moduleSystem + ? { + enabled: device.moduleSystem.enabled, + maxSlots: device.moduleSystem.maxSlots, + modules: device.moduleSystem.modules.map((m) => ({ + id: m.id, + name: m.name, + image: m.image, + io: m.io, + parameters: m.parameters, + addressMapping: m.addressMapping, + })), + } + : null, + }, + }) + } + } + } catch (err) { + console.error('Failed to load VPP packages:', err) + } + } + + async getBoardImagePreview(image: string, packagePath?: string) { + const imagePath = packagePath + ? join(packagePath, image) + : join(this.sourcesDirectoryPath, 'boards', 'previews', image) const imageBuffer = await readFile(imagePath) diff --git a/src/backend/editor/hardware/types.ts b/src/backend/editor/hardware/types.ts index 6d69ec4c1..607d398d9 100644 --- a/src/backend/editor/hardware/types.ts +++ b/src/backend/editor/hardware/types.ts @@ -60,6 +60,42 @@ const availableBoardsSchema = z.map( }), ) +// VPP module definition — describes an I/O module in a vendor backplane system +type VppModuleDefinition = { + id: string + name: string + image?: string + io: { + digitalInputs: number + digitalOutputs: number + analogInputs: number + analogOutputs: number + } + parameters?: Array<{ + id: string + name: string + type: string + options?: string[] + default?: unknown + min?: number + max?: number + }> + addressMapping?: unknown +} + +// VPP metadata attached to boards that come from installed VPP packages +type VppMetadata = { + packageId: string + deviceId: string + packagePath: string + screens: Record + moduleSystem: { + enabled: boolean + maxSlots: number + modules: VppModuleDefinition[] + } | null +} + // !! We're not able to infer the type of the Map directly from the schema, so we define it manually. // !! This is a workaround to ensure type safety when using the schema. type AvailableBoards = Map< @@ -68,17 +104,7 @@ type AvailableBoards = Map< compiler: string core: string preview: string - specs: { - CPU: string - RAM: string - Flash: string - DigitalPins: string - AnalogPins: string - PWMPins: string - WiFi: string - Bluetooth: string - Ethernet: string - } + specs: Record // Optional properties coreVersion?: string pins: { @@ -87,8 +113,9 @@ type AvailableBoards = Map< defaultDin?: string[] defaultDout?: string[] } + vpp?: VppMetadata } > export { availableBoardsSchema, BoardInfoSchema, HalsFileSchema, SerialPortSchema } -export type { AvailableBoards, BoardInfo, HalsFile, SerialPort } +export type { AvailableBoards, BoardInfo, HalsFile, SerialPort, VppMetadata, VppModuleDefinition } diff --git a/src/backend/editor/package-manager/index.ts b/src/backend/editor/package-manager/index.ts new file mode 100644 index 000000000..bc74408ef --- /dev/null +++ b/src/backend/editor/package-manager/index.ts @@ -0,0 +1,2 @@ +export { PackageManagerModule } from './package-manager-module' +export type { ImportResult, InstalledPackage, PackageManifest, PackageRegistry } from './types' diff --git a/src/backend/editor/package-manager/package-manager-module.ts b/src/backend/editor/package-manager/package-manager-module.ts new file mode 100644 index 000000000..4a0069fa7 --- /dev/null +++ b/src/backend/editor/package-manager/package-manager-module.ts @@ -0,0 +1,141 @@ +import { app } from 'electron' +import extract from 'extract-zip' +import { existsSync, mkdirSync, readFileSync, renameSync, rmSync, writeFileSync } from 'fs' +import { join } from 'path' + +import type { ImportResult, InstalledPackage, PackageManifest, PackageRegistry } from './types' + +class PackageManagerModule { + private packagesDir: string + private registryPath: string + + constructor() { + this.packagesDir = join(app.getPath('userData'), 'packages') + this.registryPath = join(this.packagesDir, 'registry.json') + mkdirSync(this.packagesDir, { recursive: true }) + } + + async importFromFile(vppFilePath: string): Promise { + try { + const tempDir = join(this.packagesDir, '_temp_import') + if (existsSync(tempDir)) { + rmSync(tempDir, { recursive: true }) + } + + await extract(vppFilePath, { dir: tempDir }) + + const manifestPath = join(tempDir, 'manifest.json') + if (!existsSync(manifestPath)) { + rmSync(tempDir, { recursive: true }) + return { success: false, error: 'Package does not contain a manifest.json file' } + } + + let manifest: PackageManifest + try { + manifest = JSON.parse(readFileSync(manifestPath, 'utf-8')) as PackageManifest + } catch { + rmSync(tempDir, { recursive: true }) + return { success: false, error: 'Invalid manifest.json format' } + } + + if (!manifest.package?.id || !manifest.devices?.length) { + rmSync(tempDir, { recursive: true }) + return { success: false, error: 'Manifest is missing required package.id or devices' } + } + + const packageId = manifest.package.id + const targetDir = join(this.packagesDir, packageId) + + if (existsSync(targetDir)) { + rmSync(targetDir, { recursive: true }) + } + + renameSync(tempDir, targetDir) + + const registry = this.readRegistry() + registry.packages[packageId] = { + version: manifest.package.version, + installedAt: new Date().toISOString(), + path: targetDir, + devices: manifest.devices.map((d) => d.id), + } + this.writeRegistry(registry) + + return { + success: true, + packageId, + packageName: manifest.package.name, + devices: manifest.devices.map((d) => d.name), + } + } catch (err) { + return { success: false, error: `Import failed: ${err instanceof Error ? err.message : String(err)}` } + } + } + + listInstalled(): InstalledPackage[] { + const registry = this.readRegistry() + return Object.entries(registry.packages).map(([packageId, info]) => ({ + packageId, + ...info, + })) + } + + uninstall(packageId: string): { success: boolean; error?: string } { + try { + const registry = this.readRegistry() + const pkg = registry.packages[packageId] + if (!pkg) { + return { success: false, error: `Package ${packageId} is not installed` } + } + + if (existsSync(pkg.path)) { + rmSync(pkg.path, { recursive: true }) + } + + delete registry.packages[packageId] + this.writeRegistry(registry) + + return { success: true } + } catch (err) { + return { success: false, error: `Uninstall failed: ${err instanceof Error ? err.message : String(err)}` } + } + } + + getInstalledPackageManifest(packageId: string): PackageManifest | null { + const registry = this.readRegistry() + const pkg = registry.packages[packageId] + if (!pkg) return null + + const manifestPath = join(pkg.path, 'manifest.json') + if (!existsSync(manifestPath)) return null + + try { + return JSON.parse(readFileSync(manifestPath, 'utf-8')) as PackageManifest + } catch { + return null + } + } + + getPackagePath(packageId: string): string | null { + const registry = this.readRegistry() + const pkg = registry.packages[packageId] + return pkg?.path ?? null + } + + private readRegistry(): PackageRegistry { + if (!existsSync(this.registryPath)) { + return { formatVersion: '1.0', packages: {} } + } + try { + return JSON.parse(readFileSync(this.registryPath, 'utf-8')) as PackageRegistry + } catch { + return { formatVersion: '1.0', packages: {} } + } + } + + private writeRegistry(registry: PackageRegistry): void { + writeFileSync(this.registryPath, JSON.stringify(registry, null, 2), 'utf-8') + } +} + +export { PackageManagerModule } diff --git a/src/backend/editor/package-manager/types.ts b/src/backend/editor/package-manager/types.ts new file mode 100644 index 000000000..ccfb28473 --- /dev/null +++ b/src/backend/editor/package-manager/types.ts @@ -0,0 +1,109 @@ +/** + * Backend-specific types for VPP package management. + * + * These types are used only by the PackageManagerModule (main process). + * Platform-agnostic types shared with the frontend live in + * src/middleware/shared/ports/types.ts. + */ + +type PackageManifest = { + formatVersion: string + package: { + id: string + name: string + version: string + vendor: { + name: string + url?: string + logo: string + } + description: string + license?: string + minEditorVersion?: string + } + devices: Array<{ + id: string + name: string + category?: string + preview: string + target: { + type: string + platform?: string + core?: string + } + specs?: Record + hal: { + type: string + pluginType?: string + pluginEntry?: string + configTemplate?: string + requirements?: string + source?: string + } + defaults?: { + runtimeIpAddress?: string + communicationPreferences?: { + enabledRTU?: boolean + enabledTCP?: boolean + } + pins?: { + defaultDin?: string[] + defaultDout?: string[] + defaultAin?: string[] + defaultAout?: string[] + } + } + screens?: Record + moduleSystem?: { + enabled: boolean + maxSlots: number + discoverySupported?: boolean + discoveryCommand?: string + modules: Array<{ + id: string + name: string + image?: string + io: { + digitalInputs: number + digitalOutputs: number + analogInputs: number + analogOutputs: number + } + parameters?: Array<{ + id: string + name: string + type: string + options?: string[] + default?: unknown + min?: number + max?: number + }> + addressMapping?: unknown + }> + } + }> +} + +type InstalledPackage = { + packageId: string + version: string + installedAt: string + path: string + devices: string[] +} + +type PackageRegistry = { + formatVersion: string + packages: Record> +} + +type ImportResult = { + success: boolean + canceled?: boolean + packageId?: string + packageName?: string + devices?: string[] + error?: string +} + +export type { ImportResult, InstalledPackage, PackageManifest, PackageRegistry } From 355982466f94fc115a0558cfc8ed8806c2734bae Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:22:45 -0400 Subject: [PATCH 002/296] feat: add VPP shared types, PackagePort interface, and editor adapter Add VPP domain types (VppMetadata, PackageManifest, InstalledPackage, IoMappingEntry, etc.) to shared port types. Create PackagePort interface for platform-agnostic package management. Create editor package adapter that delegates to IPC bridge. Extend DevicePort.getPreviewImage with optional packagePath. Add hasPackageManager capability flag. Wire packages port into editor platform. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../adapters/editor/device-adapter.ts | 4 +- .../adapters/editor/package-adapter.ts | 45 ++++++ src/middleware/editor-platform.ts | 2 + src/middleware/shared/ports/device-port.ts | 3 +- src/middleware/shared/ports/package-port.ts | 49 +++++++ .../shared/ports/platform-capabilities.ts | 7 + src/middleware/shared/ports/types.ts | 128 ++++++++++++++++++ .../shared/providers/platform-context.tsx | 4 + src/middleware/shared/providers/types.ts | 2 + 9 files changed, 241 insertions(+), 3 deletions(-) create mode 100644 src/middleware/adapters/editor/package-adapter.ts create mode 100644 src/middleware/shared/ports/package-port.ts diff --git a/src/middleware/adapters/editor/device-adapter.ts b/src/middleware/adapters/editor/device-adapter.ts index 14e5eff83..9e59afadf 100644 --- a/src/middleware/adapters/editor/device-adapter.ts +++ b/src/middleware/adapters/editor/device-adapter.ts @@ -35,8 +35,8 @@ export function createEditorDeviceAdapter(): DevicePort { return window.bridge.refreshCommunicationPorts() }, - getPreviewImage(imageName: string): Promise { - return window.bridge.getPreviewImage(imageName) + getPreviewImage(imageName: string, packagePath?: string): Promise { + return window.bridge.getPreviewImage(imageName, packagePath) }, } } diff --git a/src/middleware/adapters/editor/package-adapter.ts b/src/middleware/adapters/editor/package-adapter.ts new file mode 100644 index 000000000..6d4c8c1d4 --- /dev/null +++ b/src/middleware/adapters/editor/package-adapter.ts @@ -0,0 +1,45 @@ +/** + * Editor PackagePort adapter — delegates to Electron IPC bridge. + * + * Communicates with the main process PackageManagerModule for VPP + * package lifecycle operations (import, list, uninstall, manifest). + * + * IPC channels: + * packages:import-from-file (invoke) + * packages:list-installed (invoke) + * packages:uninstall (invoke) + * packages:get-manifest (invoke) + * packages:open-manager (on) + * packages:boards-updated (on) + */ + +import type { PackagePort } from '../../shared/ports/package-port' +import type { ImportResult, InstalledPackage, PackageManifest, Result, Unsubscribe } from '../../shared/ports/types' + +export function createEditorPackageAdapter(): PackagePort { + return { + importFromFile(): Promise { + return window.bridge.importPackageFromFile() + }, + + listInstalled(): Promise { + return window.bridge.listInstalledPackages() + }, + + uninstall(packageId: string): Promise { + return window.bridge.uninstallPackage(packageId) + }, + + getManifest(packageId: string): Promise { + return window.bridge.getPackageManifest(packageId) + }, + + onOpenManager(callback: () => void): Unsubscribe { + return window.bridge.onOpenPackageManager(callback) + }, + + onBoardsUpdated(callback: () => void): Unsubscribe { + return window.bridge.onBoardsUpdated(callback) + }, + } +} diff --git a/src/middleware/editor-platform.ts b/src/middleware/editor-platform.ts index feb611760..e4ba93c13 100644 --- a/src/middleware/editor-platform.ts +++ b/src/middleware/editor-platform.ts @@ -18,6 +18,7 @@ import { createEditorCompilerAdapter } from './adapters/editor/compiler-adapter' import { createEditorDebuggerAdapter } from './adapters/editor/debugger-adapter' import { createEditorDeviceAdapter } from './adapters/editor/device-adapter' import { createEditorOrchestratorAdapter } from './adapters/editor/orchestrator-adapter' +import { createEditorPackageAdapter } from './adapters/editor/package-adapter' import { createEditorProjectAdapter } from './adapters/editor/project-adapter' import { createEditorRuntimeAdapter } from './adapters/editor/runtime-adapter' import { createEditorSimulatorAdapter } from './adapters/editor/simulator-adapter' @@ -52,5 +53,6 @@ export const editorPorts: PlatformPorts = { window: createEditorWindowAdapter(), accelerator: createEditorAcceleratorAdapter(), theme: createEditorThemeAdapter(), + packages: createEditorPackageAdapter(), capabilities: { ...EDITOR_CAPABILITIES, isDevMode: process.env.NODE_ENV === 'development' }, } diff --git a/src/middleware/shared/ports/device-port.ts b/src/middleware/shared/ports/device-port.ts index 4ceb9e0b6..c6606533a 100644 --- a/src/middleware/shared/ports/device-port.ts +++ b/src/middleware/shared/ports/device-port.ts @@ -55,7 +55,8 @@ export interface DevicePort { /** * Get a board preview image for display in the UI. * Editor: loads image from local resources/ directory, returns base64 or file path. + * For VPP boards, loads from the package directory when packagePath is provided. * Web: returns URL to bundled image asset. */ - getPreviewImage(imageName: string): Promise + getPreviewImage(imageName: string, packagePath?: string): Promise } diff --git a/src/middleware/shared/ports/package-port.ts b/src/middleware/shared/ports/package-port.ts new file mode 100644 index 000000000..f147ee42b --- /dev/null +++ b/src/middleware/shared/ports/package-port.ts @@ -0,0 +1,49 @@ +/** + * PackagePort — Abstracts VPP (Vendor Plugin Package) management. + * + * Editor adapter: Delegates to main process PackageManagerModule which manages + * packages on the local filesystem ({userData}/packages/). + * Web adapter: Will delegate to a backend API for package management. + * + * ## Editor IPC methods replaced: + * - window.bridge.importPackageFromFile() + * - window.bridge.listInstalledPackages() + * - window.bridge.uninstallPackage() + * - window.bridge.getPackageManifest() + */ + +import type { ImportResult, InstalledPackage, PackageManifest, Result, Unsubscribe } from './types' + +export interface PackagePort { + /** + * Open a file picker and import a .vpp package file. + * Editor: shows native file dialog, extracts and registers the package. + * Web: uploads to backend for processing. + */ + importFromFile(): Promise + + /** + * List all installed VPP packages. + */ + listInstalled(): Promise + + /** + * Uninstall a VPP package by its ID. + */ + uninstall(packageId: string): Promise + + /** + * Get the full manifest of an installed package. + */ + getManifest(packageId: string): Promise + + /** + * Subscribe to the "open package manager" event (triggered from menu). + */ + onOpenManager(callback: () => void): Unsubscribe + + /** + * Subscribe to board list updates (triggered after package install/uninstall). + */ + onBoardsUpdated(callback: () => void): Unsubscribe +} diff --git a/src/middleware/shared/ports/platform-capabilities.ts b/src/middleware/shared/ports/platform-capabilities.ts index 06c9160b0..d03ca45d1 100644 --- a/src/middleware/shared/ports/platform-capabilities.ts +++ b/src/middleware/shared/ports/platform-capabilities.ts @@ -84,6 +84,11 @@ export interface PlatformCapabilities { */ hasDirectProgramUpload: boolean + // --- Packages --- + + /** True if the app supports installing/managing VPP board packages. */ + hasPackageManager: boolean + // --- Environment --- /** True when running in a development build (Vite DEV / webpack development mode). */ @@ -113,6 +118,7 @@ export const EDITOR_CAPABILITIES: PlatformCapabilities = { hasAIAssistant: false, hasProxiedRuntimeConnection: false, hasDirectProgramUpload: false, + hasPackageManager: true, isDevMode: false, } @@ -135,5 +141,6 @@ export const WEB_CAPABILITIES: PlatformCapabilities = { hasAIAssistant: true, hasProxiedRuntimeConnection: true, hasDirectProgramUpload: true, + hasPackageManager: false, isDevMode: false, } diff --git a/src/middleware/shared/ports/types.ts b/src/middleware/shared/ports/types.ts index 04117924f..b7160bd73 100644 --- a/src/middleware/shared/ports/types.ts +++ b/src/middleware/shared/ports/types.ts @@ -438,6 +438,134 @@ export interface BoardInfo { defaultDin?: string[] defaultDout?: string[] } + vpp?: VppMetadata +} + +// --------------------------------------------------------------------------- +// VPP (Vendor Plugin Package) +// --------------------------------------------------------------------------- + +export interface VppModuleDefinition { + id: string + name: string + image?: string + io: { + digitalInputs: number + digitalOutputs: number + analogInputs: number + analogOutputs: number + } + parameters?: Array<{ + id: string + name: string + type: string + options?: string[] + default?: unknown + min?: number + max?: number + }> + addressMapping?: unknown +} + +export interface VppMetadata { + packageId: string + deviceId: string + packagePath: string + screens: Record + moduleSystem: { + enabled: boolean + maxSlots: number + modules: VppModuleDefinition[] + } | null +} + +export interface PackageManifest { + formatVersion: string + package: { + id: string + name: string + version: string + vendor: { + name: string + url?: string + logo: string + } + description: string + license?: string + minEditorVersion?: string + } + devices: Array<{ + id: string + name: string + category?: string + preview: string + target: { + type: string + platform?: string + core?: string + } + specs?: Record + hal: { + type: string + pluginType?: string + pluginEntry?: string + configTemplate?: string + requirements?: string + source?: string + } + defaults?: { + runtimeIpAddress?: string + communicationPreferences?: { + enabledRTU?: boolean + enabledTCP?: boolean + } + pins?: { + defaultDin?: string[] + defaultDout?: string[] + defaultAin?: string[] + defaultAout?: string[] + } + } + screens?: Record + moduleSystem?: { + enabled: boolean + maxSlots: number + discoverySupported?: boolean + modules: VppModuleDefinition[] + } + }> +} + +export interface InstalledPackage { + packageId: string + version: string + installedAt: string + path: string + devices: string[] +} + +export interface ImportResult { + success: boolean + canceled?: boolean + packageId?: string + packageName?: string + devices?: string[] + error?: string +} + +export interface IoMappingEntry { + slot: number + moduleId: string + moduleName: string + channelName: string + channelType: string + dataType: string + iecAddress: string + alias: string +} + +export interface VendorIoMapping { + entries: IoMappingEntry[] } export interface CommunicationPort { diff --git a/src/middleware/shared/providers/platform-context.tsx b/src/middleware/shared/providers/platform-context.tsx index 51446b8a2..9bdc7219b 100644 --- a/src/middleware/shared/providers/platform-context.tsx +++ b/src/middleware/shared/providers/platform-context.tsx @@ -101,3 +101,7 @@ export function useCapabilities() { export function useAI() { return usePlatform().ai } + +export function usePackages() { + return usePlatform().packages +} diff --git a/src/middleware/shared/providers/types.ts b/src/middleware/shared/providers/types.ts index ada544f2e..05d301ecc 100644 --- a/src/middleware/shared/providers/types.ts +++ b/src/middleware/shared/providers/types.ts @@ -9,6 +9,7 @@ import type { CompilerPort } from '../ports/compiler-port' import type { DebuggerPort } from '../ports/debugger-port' import type { DevicePort } from '../ports/device-port' import type { OrchestratorPort } from '../ports/orchestrator-port' +import type { PackagePort } from '../ports/package-port' import type { PlatformCapabilities } from '../ports/platform-capabilities' import type { ProjectPort } from '../ports/project-port' import type { RuntimePort } from '../ports/runtime-port' @@ -30,5 +31,6 @@ export interface PlatformPorts { accelerator: AcceleratorPort theme: ThemePort capabilities: PlatformCapabilities + packages?: PackagePort ai?: AIPort } From 39381142fb4f2d5e2d1807166363529c4f30d5be Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:25:33 -0400 Subject: [PATCH 003/296] feat: add IPC bridge for package management and menu integration Add package manager IPC handlers in main process for import, list, uninstall, and manifest operations. Add corresponding renderer bridge methods. Update getPreviewImage to support optional packagePath for VPP boards. Add "Board Package Manager..." menu item to both Darwin and default menu templates. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/main/menu.ts | 10 +++++ src/main/modules/ipc/main.ts | 43 +++++++++++++++++-- src/main/modules/ipc/renderer.ts | 29 ++++++++++++- .../adapters/editor/package-adapter.ts | 10 +++-- 4 files changed, 84 insertions(+), 8 deletions(-) diff --git a/src/main/menu.ts b/src/main/menu.ts index 44efa68d9..504f32c4b 100644 --- a/src/main/menu.ts +++ b/src/main/menu.ts @@ -235,6 +235,11 @@ export default class MenuBuilder { accelerator: 'Cmd+U', enabled: false, }, + { type: 'separator' }, + { + label: 'Board Package Manager...', + click: () => this.mainWindow.webContents.send('packages:open-manager'), + }, ], } @@ -502,6 +507,11 @@ export default class MenuBuilder { accelerator: 'Ctrl+U', }, { type: 'separator' }, + { + label: 'Board Package Manager...', + click: () => this.mainWindow.webContents.send('packages:open-manager'), + }, + { type: 'separator' }, { label: i18n.t('menu:file.submenu.quit'), // role: 'quit', diff --git a/src/main/modules/ipc/main.ts b/src/main/modules/ipc/main.ts index 70dc8d958..653185d8f 100644 --- a/src/main/modules/ipc/main.ts +++ b/src/main/modules/ipc/main.ts @@ -5,7 +5,7 @@ import { CreateProjectFileProps } from '@root/types/IPC/project-service' import { PLCProjectData } from '@root/types/PLC/open-plc' import { RuntimeLogEntry } from '@root/types/PLC/runtime-logs' import type { IpcMainEvent, IpcMainInvokeEvent } from 'electron' -import { app, nativeTheme, shell } from 'electron' +import { app, dialog, nativeTheme, shell } from 'electron' import { readFile, realpathSync, stat, statSync, unwatchFile, watchFile } from 'fs' import type { IncomingHttpHeaders, IncomingMessage } from 'http' import https from 'https' @@ -15,6 +15,7 @@ import { platform } from 'process' import { MainIpcModule, MainIpcModuleConstructor } from '../../../backend/editor/contracts/types/modules/ipc/main' import { ModbusTcpClient } from '../../../backend/editor/modbus/modbus-client' import { ModbusRtuClient } from '../../../backend/editor/modbus/modbus-rtu-client' +import { PackageManagerModule } from '../../../backend/editor/package-manager' import { logger } from '../../../backend/editor/services' import { getProjectPath } from '../../../backend/editor/utils' import { WebSocketDebugClient } from '../../../backend/editor/websocket/websocket-debug-client' @@ -48,6 +49,8 @@ class MainProcessBridge implements MainIpcModule { private fileWatchers: Map = new Map() // avr8js ATmega2560 emulator instance for the built-in simulator private simulatorModule = new SimulatorModule() + // VPP package manager for board package operations + private packageManagerModule = new PackageManagerModule() constructor({ ipcMain, @@ -525,6 +528,12 @@ class MainProcessBridge implements MainIpcModule { this.registerHandle('hardware:refresh-communication-ports', this.handleHardwareRefreshCommunicationPorts) this.registerHandle('hardware:refresh-available-boards', this.handleHardwareRefreshAvailableBoards) + // ===================== PACKAGE MANAGER ===================== + this.registerHandle('packages:import-from-file', this.handlePackagesImportFromFile) + this.registerHandle('packages:list-installed', this.handlePackagesListInstalled) + this.registerHandle('packages:uninstall', this.handlePackagesUninstall) + this.registerHandle('packages:get-manifest', this.handlePackagesGetManifest) + // ===================== UTILITIES ===================== this.registerHandle('util:get-preview-image', this.handleUtilGetPreviewImage) this.ipcMain.on('util:log', this.handleUtilLog) @@ -816,9 +825,37 @@ class MainProcessBridge implements MainIpcModule { handleHardwareRefreshCommunicationPorts = async () => this.hardwareModule.getAvailableSerialPorts() handleHardwareRefreshAvailableBoards = async () => this.hardwareModule.getAvailableBoards() + // Package manager handlers + handlePackagesImportFromFile = async () => { + if (!this.mainWindow) return { success: false, error: 'No main window' } + const result = await dialog.showOpenDialog(this.mainWindow, { + title: 'Import Board Package', + filters: [{ name: 'VPP Package', extensions: ['vpp'] }], + properties: ['openFile'], + }) + if (result.canceled || result.filePaths.length === 0) { + return { success: false, canceled: true } + } + const importResult = await this.packageManagerModule.importFromFile(result.filePaths[0]) + if (importResult.success) { + this.mainWindow.webContents.send('packages:boards-updated') + } + return importResult + } + handlePackagesListInstalled = async () => this.packageManagerModule.listInstalled() + handlePackagesUninstall = async (_event: IpcMainInvokeEvent, packageId: string) => { + const result = this.packageManagerModule.uninstall(packageId) + if (result.success) { + this.mainWindow?.webContents.send('packages:boards-updated') + } + return result + } + handlePackagesGetManifest = async (_event: IpcMainInvokeEvent, packageId: string) => + this.packageManagerModule.getInstalledPackageManifest(packageId) + // Utility handlers - handleUtilGetPreviewImage = async (_event: IpcMainInvokeEvent, image: string) => - this.hardwareModule.getBoardImagePreview(image) + handleUtilGetPreviewImage = async (_event: IpcMainInvokeEvent, image: string, packagePath?: string) => + this.hardwareModule.getBoardImagePreview(image, packagePath) handleUtilLog = (_: IpcMainEvent, { level, message }: { level: 'info' | 'error'; message: string }) => { logger[level](message) } diff --git a/src/main/modules/ipc/renderer.ts b/src/main/modules/ipc/renderer.ts index 04da0fa1f..d77a0318b 100644 --- a/src/main/modules/ipc/renderer.ts +++ b/src/main/modules/ipc/renderer.ts @@ -229,8 +229,35 @@ const rendererProcessBridge = { refreshCommunicationPorts: (): Promise<{ name: string; address: string }[]> => ipcRenderer.invoke('hardware:refresh-communication-ports'), + // ===================== PACKAGE MANAGER METHODS ===================== + importPackageFromFile: (): Promise<{ + success: boolean + canceled?: boolean + packageId?: string + packageName?: string + devices?: string[] + error?: string + }> => ipcRenderer.invoke('packages:import-from-file'), + listInstalledPackages: (): Promise< + Array<{ packageId: string; version: string; installedAt: string; path: string; devices: string[] }> + > => ipcRenderer.invoke('packages:list-installed'), + uninstallPackage: (packageId: string): Promise<{ success: boolean; error?: string }> => + ipcRenderer.invoke('packages:uninstall', packageId), + getPackageManifest: (packageId: string): Promise => ipcRenderer.invoke('packages:get-manifest', packageId), + onOpenPackageManager: (callback: () => void) => { + const listener = () => callback() + ipcRenderer.on('packages:open-manager', listener) + return () => ipcRenderer.removeListener('packages:open-manager', listener) + }, + onBoardsUpdated: (callback: () => void) => { + const listener = () => callback() + ipcRenderer.on('packages:boards-updated', listener) + return () => ipcRenderer.removeListener('packages:boards-updated', listener) + }, + // ===================== UTILITY METHODS ===================== - getPreviewImage: (image: string): Promise => ipcRenderer.invoke('util:get-preview-image', image), + getPreviewImage: (image: string, packagePath?: string): Promise => + ipcRenderer.invoke('util:get-preview-image', image, packagePath), log: (level: 'info' | 'error', message: string) => ipcRenderer.send('util:log', { level, message }), readDebugFile: ( projectPath: string, diff --git a/src/middleware/adapters/editor/package-adapter.ts b/src/middleware/adapters/editor/package-adapter.ts index 6d4c8c1d4..5bb93ee17 100644 --- a/src/middleware/adapters/editor/package-adapter.ts +++ b/src/middleware/adapters/editor/package-adapter.ts @@ -26,12 +26,14 @@ export function createEditorPackageAdapter(): PackagePort { return window.bridge.listInstalledPackages() }, - uninstall(packageId: string): Promise { - return window.bridge.uninstallPackage(packageId) + async uninstall(packageId: string): Promise { + const result = await window.bridge.uninstallPackage(packageId) + if (result.success) return { success: true } as Result + return { success: false, error: result.error ?? 'Uninstall failed' } }, - getManifest(packageId: string): Promise { - return window.bridge.getPackageManifest(packageId) + async getManifest(packageId: string): Promise { + return (await window.bridge.getPackageManifest(packageId)) as PackageManifest | null }, onOpenManager(callback: () => void): Unsubscribe { From 872c413238dd7945193f11efab5de94097ec3585 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:27:31 -0400 Subject: [PATCH 004/296] feat: add VPP store types, editor models, and tab support Add vendorScreenData field to device configuration schema. Add setVendorScreenData action to device slice. Add plc-vendor-screen and plc-package-manager editor model variants. Add vendor-screen and package-manager tab element types with creation helpers. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/frontend/store/slices/device/slice.ts | 11 +++++++++++ src/frontend/store/slices/device/types.ts | 1 + src/frontend/store/slices/editor/types.ts | 13 +++++++++++++ src/frontend/store/slices/tabs/types.ts | 2 ++ src/frontend/store/slices/tabs/utils.ts | 16 ++++++++++++++++ src/middleware/shared/ports/types.ts | 1 + src/types/PLC/devices/configuration.ts | 1 + 7 files changed, 45 insertions(+) diff --git a/src/frontend/store/slices/device/slice.ts b/src/frontend/store/slices/device/slice.ts index e78582538..854895e6f 100644 --- a/src/frontend/store/slices/device/slice.ts +++ b/src/frontend/store/slices/device/slice.ts @@ -494,6 +494,16 @@ const createDeviceSlice: StateCreator = (setSt }), ) }, + setVendorScreenData: (persistenceKey, data): void => { + setState( + produce(({ deviceDefinitions }: DeviceSlice) => { + if (!deviceDefinitions.configuration.vendorScreenData) { + deviceDefinitions.configuration.vendorScreenData = {} + } + deviceDefinitions.configuration.vendorScreenData[persistenceKey] = data + }), + ) + }, }, }) @@ -506,6 +516,7 @@ function mergeDeviceConfigWithDefaults( communicationPort: provided.communicationPort ?? defaults.communicationPort, runtimeIpAddress: provided.runtimeIpAddress ?? defaults.runtimeIpAddress, compileOnly: provided.compileOnly ?? defaults.compileOnly, + vendorScreenData: provided.vendorScreenData ?? defaults.vendorScreenData, communicationConfiguration: { modbusRTU: { ...defaults.communicationConfiguration.modbusRTU, diff --git a/src/frontend/store/slices/device/types.ts b/src/frontend/store/slices/device/types.ts index f45594245..1590ef105 100644 --- a/src/frontend/store/slices/device/types.ts +++ b/src/frontend/store/slices/device/types.ts @@ -137,6 +137,7 @@ export type DeviceActions = { setIncludeTimingStatsInPolling: (include: boolean) => void setTemporaryDhcpIp: (ipAddress?: string) => void clearRuntimeConnection: () => void + setVendorScreenData: (persistenceKey: string, data: unknown) => void } // --------------------------------------------------------------------------- diff --git a/src/frontend/store/slices/editor/types.ts b/src/frontend/store/slices/editor/types.ts index 6c22dc9b2..9b108b41e 100644 --- a/src/frontend/store/slices/editor/types.ts +++ b/src/frontend/store/slices/editor/types.ts @@ -150,6 +150,19 @@ export type EditorModel = EditorModelBase & protocol: 'modbus-tcp' | 'ethernet-ip' | 'ethercat' | 'profinet' } } + | { + type: 'plc-vendor-screen' + meta: { + name: string + screenName: string + } + } + | { + type: 'plc-package-manager' + meta: { + name: string + } + } ) // --------------------------------------------------------------------------- diff --git a/src/frontend/store/slices/tabs/types.ts b/src/frontend/store/slices/tabs/types.ts index ec2ce28d8..6c614d9bc 100644 --- a/src/frontend/store/slices/tabs/types.ts +++ b/src/frontend/store/slices/tabs/types.ts @@ -14,6 +14,8 @@ export type TabsProps = { | { type: 'device'; derivation: 'configuration' | 'pin-mapping' | 'orchestrators' } | { type: 'server'; protocol: 'modbus-tcp' | 's7comm' | 'ethernet-ip' | 'opcua' } | { type: 'remote-device'; protocol: 'modbus-tcp' | 'ethernet-ip' | 'ethercat' | 'profinet' } + | { type: 'vendor-screen'; screenName: string } + | { type: 'package-manager' } configuration?: Record } diff --git a/src/frontend/store/slices/tabs/utils.ts b/src/frontend/store/slices/tabs/utils.ts index d03c612e9..ceb41a736 100644 --- a/src/frontend/store/slices/tabs/utils.ts +++ b/src/frontend/store/slices/tabs/utils.ts @@ -107,6 +107,16 @@ const CreateServerEditor = ( meta: { name, protocol }, }) +const CreateVendorScreenEditor = (name: string, screenName: string): EditorModel => ({ + type: 'plc-vendor-screen', + meta: { name, screenName }, +}) + +const CreatePackageManagerEditor = (name = 'Package Manager'): EditorModel => ({ + type: 'plc-package-manager', + meta: { name }, +}) + const CreateEditorObjectFromTab = (tab: TabsProps): EditorModel => { const { elementType, name } = tab switch (elementType.type) { @@ -126,6 +136,10 @@ const CreateEditorObjectFromTab = (tab: TabsProps): EditorModel => { return CreateRemoteDeviceEditor(name, elementType.protocol) case 'server': return CreateServerEditor(name, elementType.protocol) + case 'vendor-screen': + return CreateVendorScreenEditor(name, elementType.screenName) + case 'package-manager': + return CreatePackageManagerEditor(name) } } @@ -133,9 +147,11 @@ export { CreateDeviceEditor, CreateEditorModelObject, CreateEditorObjectFromTab, + CreatePackageManagerEditor, CreatePLCGraphicalObject, CreatePLCTextualObject, CreateRemoteDeviceEditor, CreateResourceEditor, CreateServerEditor, + CreateVendorScreenEditor, } diff --git a/src/middleware/shared/ports/types.ts b/src/middleware/shared/ports/types.ts index b7160bd73..a6558e8d9 100644 --- a/src/middleware/shared/ports/types.ts +++ b/src/middleware/shared/ports/types.ts @@ -612,6 +612,7 @@ export interface DeviceConfiguration { communicationPort: string runtimeIpAddress?: string compileOnly: boolean + vendorScreenData?: Record communicationConfiguration: { modbusRTU: ModbusRTUConfig modbusTCP: ModbusTCPConfig diff --git a/src/types/PLC/devices/configuration.ts b/src/types/PLC/devices/configuration.ts index c3087b189..09b49bdea 100644 --- a/src/types/PLC/devices/configuration.ts +++ b/src/types/PLC/devices/configuration.ts @@ -20,6 +20,7 @@ const deviceConfigurationSchema = z.object({ communicationPort: z.string(), runtimeIpAddress: z.string().optional(), compileOnly: z.boolean().default(false), + vendorScreenData: z.record(z.string(), z.unknown()).optional(), communicationConfiguration: z.object({ modbusRTU: z.object({ rtuInterface: z.enum(interfaceOptions), // This will be an enumerated that will be associated with the device board selected - Validation will be added further. From 15f0cd1f4d80b2624f53545007027284b8739088 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:28:14 -0400 Subject: [PATCH 005/296] feat: add IEC address allocation utility for vendor IO mapping Add frontend utility for collecting used IEC addresses across all IO sources (pins, remote devices, vendor modules) and generating next available addresses. Pure frontend code with no backend dependencies. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/frontend/utils/iec-address.ts | 69 +++++++++++++++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/frontend/utils/iec-address.ts diff --git a/src/frontend/utils/iec-address.ts b/src/frontend/utils/iec-address.ts new file mode 100644 index 000000000..7fac0af31 --- /dev/null +++ b/src/frontend/utils/iec-address.ts @@ -0,0 +1,69 @@ +/** + * IEC 61131-3 address utilities for global address allocation. + * + * Manages IEC address allocation across all IO sources: local pin mapping, + * remote devices (Modbus TCP IO groups), and vendor module IO mappings. + * This prevents address collisions when multiple IO sources coexist. + * + * Pure frontend utility — no backend or platform dependencies. + */ + +import type { DevicePin, VendorIoMapping } from '../../middleware/shared/ports/types' + +/** + * Collects all used IEC addresses across the entire project: + * local pin mapping, remote devices, and vendor module IO mappings. + */ +export function collectUsedIecAddresses( + pinMapping: DevicePin[], + remoteDevices: Array<{ modbusTcpConfig?: { ioGroups?: Array<{ ioPoints: Array<{ iecLocation: string }> }> } }>, + vendorIoMapping?: VendorIoMapping, +): Set { + const used = new Set() + + for (const pin of pinMapping) { + if (pin.address) used.add(pin.address) + } + + for (const device of remoteDevices) { + if (device.modbusTcpConfig?.ioGroups) { + for (const group of device.modbusTcpConfig.ioGroups) { + for (const point of group.ioPoints) { + used.add(point.iecLocation) + } + } + } + } + + if (vendorIoMapping?.entries) { + for (const entry of vendorIoMapping.entries) { + if (entry.iecAddress) used.add(entry.iecAddress) + } + } + + return used +} + +/** + * Generates the next available IEC address for a given prefix, + * skipping any addresses in the usedAddresses set. + * + * @param prefix - Address prefix (e.g., '%IX', '%QX', '%IW', '%QW') + * @param isBit - Whether to use bit addressing (prefix + byte.bit format) + * @param usedAddresses - Set of already-used addresses to skip + * @param startFrom - Optional starting offset + */ +export function generateIecAddress( + prefix: string, + isBit: boolean, + usedAddresses: Set, + startFrom?: number, +): string { + let current = startFrom ?? 0 + + while (true) { + const addr = isBit ? `${prefix}${Math.floor(current / 8)}.${current % 8}` : `${prefix}${current}` + if (!usedAddresses.has(addr)) return addr + current++ + } +} From 88c75b9a1dda868104dbdf27fe901ae9a96147e5 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:35:44 -0400 Subject: [PATCH 006/296] feat: add vendor screen and package manager frontend components Create VendorScreenRenderer with section renderer and layout components (module-slots, io-table, form, unsupported). Create PackageManagerEditor using usePlatform() hooks instead of direct IPC calls. Create VendorScreenEditor wrapper. All components use platform-agnostic imports for cross-platform reuse. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../configuration/vendor-screen/index.tsx | 66 +++++ .../vendor-screen/layouts/form-layout.tsx | 129 +++++++++ .../vendor-screen/layouts/io-table-layout.tsx | 262 ++++++++++++++++++ .../layouts/module-slots-layout.tsx | 156 +++++++++++ .../layouts/unsupported-layout.tsx | 13 + .../vendor-screen/section-renderer.tsx | 53 ++++ .../editor/package-manager/index.tsx | 224 +++++++++++++++ .../editor/vendor-screen/index.tsx | 29 ++ src/frontend/store/slices/workspace/types.ts | 2 + 9 files changed, 934 insertions(+) create mode 100644 src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/index.tsx create mode 100644 src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/form-layout.tsx create mode 100644 src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/io-table-layout.tsx create mode 100644 src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/module-slots-layout.tsx create mode 100644 src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/unsupported-layout.tsx create mode 100644 src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/section-renderer.tsx create mode 100644 src/frontend/components/_features/[workspace]/editor/package-manager/index.tsx create mode 100644 src/frontend/components/_features/[workspace]/editor/vendor-screen/index.tsx diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/index.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/index.tsx new file mode 100644 index 000000000..909fbd6c0 --- /dev/null +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/index.tsx @@ -0,0 +1,66 @@ +import { memo } from 'react' + +import { SectionRenderer } from './section-renderer' + +type ScreenSection = { + id: string + title: string + layout: string + collapsible?: boolean + collapsed?: boolean + maxSlots?: number + moduleSource?: string + fields?: unknown[] + actions?: unknown[] + persistence?: string +} + +type ScreenDefinition = { + sections: ScreenSection[] +} + +type ModuleDefinition = { + id: string + name: string + io: { digitalInputs: number; digitalOutputs: number; analogInputs: number; analogOutputs: number } + parameters?: Array<{ + id: string + name: string + type: string + options?: string[] + default?: unknown + min?: number + max?: number + }> + addressMapping?: unknown +} + +type ModuleSystem = { + enabled: boolean + maxSlots: number + modules: ModuleDefinition[] +} | null + +type VendorScreenRendererProps = { + screenDefinition: unknown + moduleSystem: ModuleSystem +} + +const VendorScreenRenderer = memo(function VendorScreenRenderer({ + screenDefinition, + moduleSystem, +}: VendorScreenRendererProps) { + const screen = screenDefinition as ScreenDefinition + if (!screen?.sections) return null + + return ( +
+ {screen.sections.map((section) => ( + + ))} +
+ ) +}) + +export { VendorScreenRenderer } +export type { ModuleDefinition, ModuleSystem, ScreenDefinition, ScreenSection } diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/form-layout.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/form-layout.tsx new file mode 100644 index 000000000..20b65e859 --- /dev/null +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/form-layout.tsx @@ -0,0 +1,129 @@ +import { Checkbox } from '@root/frontend/components/_atoms/checkbox' +import { Label } from '@root/frontend/components/_atoms/label' +import { Select, SelectContent, SelectItem, SelectTrigger } from '@root/frontend/components/_atoms/select' +import { useOpenPLCStore } from '@root/frontend/store' + +import type { ScreenSection } from '../index' + +type FieldDef = { + id: string + label: string + type: string + default?: unknown + min?: number + max?: number + step?: number + unit?: string + help?: string + options?: string[] | Array<{ value: string; label: string }> +} + +type FormLayoutProps = { + section: ScreenSection +} + +function FormLayout({ section }: FormLayoutProps) { + const fields = (section.fields ?? []) as FieldDef[] + + const vendorScreenData = useOpenPLCStore((s) => s.deviceDefinitions.configuration.vendorScreenData) + const setVendorScreenData = useOpenPLCStore((s) => s.deviceActions.setVendorScreenData) + const persistenceKey = section.persistence || section.id + + const storedValues = vendorScreenData?.[persistenceKey] as Record | undefined + const values: Record = {} + for (const field of fields) { + values[field.id] = storedValues?.[field.id] ?? (field.default as string | number | boolean) ?? '' + } + + const updateField = (id: string, value: string | number | boolean) => { + setVendorScreenData(persistenceKey, { ...storedValues, [id]: value }) + } + + return ( +
+ {fields.map((field) => ( +
+
+ {field.type === 'boolean' ? ( + <> + updateField(field.id, checked as boolean)} + className={ + values[field.id] === true + ? 'h-[14px] w-[14px] border-brand' + : 'h-[14px] w-[14px] border-neutral-300' + } + /> + + + ) : ( + <> + + {field.type === 'number' ? ( +
+ updateField(field.id, Number(e.target.value))} + className='flex h-[30px] w-24 items-center rounded-md border border-neutral-100 bg-white px-2 py-1 font-caption text-cp-sm font-medium text-neutral-850 outline-none focus:border-brand-medium-dark dark:border-neutral-850 dark:bg-neutral-950 dark:text-neutral-300' + /> + {field.unit && {field.unit}} +
+ ) : field.type === 'select' ? ( + + ) : ( + updateField(field.id, e.target.value)} + className='flex h-[30px] w-48 items-center rounded-md border border-neutral-100 bg-white px-2 py-1 font-caption text-cp-sm font-medium text-neutral-850 outline-none focus:border-brand-medium-dark dark:border-neutral-850 dark:bg-neutral-950 dark:text-neutral-300' + /> + )} + + )} +
+ {field.help && {field.help}} +
+ ))} +
+ ) +} + +export { FormLayout } diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/io-table-layout.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/io-table-layout.tsx new file mode 100644 index 000000000..d46d67945 --- /dev/null +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/io-table-layout.tsx @@ -0,0 +1,262 @@ +import { useOpenPLCStore } from '@root/frontend/store' +import { collectUsedIecAddresses, generateIecAddress } from '@root/frontend/utils/iec-address' +import type { IoMappingEntry, VendorIoMapping } from '@root/middleware/shared/ports/types' +import { useCallback, useEffect, useMemo, useRef, useState } from 'react' + +import type { ModuleSystem, ScreenSection } from '../index' + +type IoTableLayoutProps = { + section: ScreenSection + moduleSystem: ModuleSystem +} + +function IoTableLayout({ section, moduleSystem }: IoTableLayoutProps) { + const persistenceKey = section.persistence || section.id + const availableModules = moduleSystem?.modules ?? [] + + const getStoreState = useCallback(() => { + const state = useOpenPLCStore.getState() + const vsd = state.deviceDefinitions.configuration.vendorScreenData + const moduleConfig = vsd?.['module-configuration'] as { slots?: (string | null)[] } | undefined + const storedMapping = vsd?.[persistenceKey] as VendorIoMapping | undefined + return { + slots: moduleConfig?.slots ?? [], + storedMapping, + pinMapping: state.deviceDefinitions.pinMapping.pins, + remoteDevices: (state.project.data.remoteDevices ?? []) as Array<{ + modbusTcpConfig?: { ioGroups?: Array<{ ioPoints: Array<{ iecLocation: string }> }> } + }>, + } + }, [persistenceKey]) + + const setVendorScreenData = useOpenPLCStore((s) => s.deviceActions.setVendorScreenData) + + const moduleConfig = useOpenPLCStore( + (s) => + s.deviceDefinitions.configuration.vendorScreenData?.['module-configuration'] as + | { slots?: (string | null)[] } + | undefined, + ) + const slots = moduleConfig?.slots ?? [] + + const [entries, setEntries] = useState(() => { + const { storedMapping } = getStoreState() + return storedMapping?.entries ?? [] + }) + + const lastSlotsRef = useRef('') + + useEffect(() => { + const slotsKey = JSON.stringify(slots) + if (slotsKey === lastSlotsRef.current) return + lastSlotsRef.current = slotsKey + + const { pinMapping, remoteDevices, storedMapping } = getStoreState() + + const existingAliases = new Map() + const existingEntries = storedMapping?.entries ?? entries + for (const entry of existingEntries) { + if (entry.alias) { + existingAliases.set(`${entry.slot}:${entry.channelName}`, entry.alias) + } + } + + const usedAddresses = collectUsedIecAddresses(pinMapping, remoteDevices) + const newEntries: IoMappingEntry[] = [] + + for (let slotIndex = 0; slotIndex < slots.length; slotIndex++) { + const moduleId = slots[slotIndex] + if (!moduleId) continue + + const moduleDef = availableModules.find((m) => m.id === moduleId) + if (!moduleDef) continue + + const channels = ( + moduleDef as { + addressMapping?: { + channels?: Array<{ name: string; type: string; dataType: string; addressPrefix: string }> + } + } + ).addressMapping?.channels + + if (channels) { + for (const channel of channels) { + const isBit = channel.addressPrefix === '%IX' || channel.addressPrefix === '%QX' + const iecAddress = generateIecAddress(channel.addressPrefix, isBit, usedAddresses) + usedAddresses.add(iecAddress) + + const aliasKey = `${slotIndex + 1}:${channel.name}` + newEntries.push({ + slot: slotIndex + 1, + moduleId, + moduleName: moduleDef.name, + channelName: channel.name, + channelType: channel.type, + dataType: channel.dataType, + iecAddress, + alias: existingAliases.get(aliasKey) ?? '', + }) + } + } + } + + setEntries(newEntries) + setVendorScreenData(persistenceKey, { entries: newEntries }) + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [slots]) + + const handleAliasChange = (index: number, alias: string) => { + const updated = [...entries] + updated[index] = { ...updated[index], alias } + setEntries(updated) + setVendorScreenData(persistenceKey, { entries: updated }) + } + + const groups = useMemo(() => { + const map = new Map< + number, + { moduleName: string; moduleId: string; entries: Array } + >() + entries.forEach((entry, idx) => { + let group = map.get(entry.slot) + if (!group) { + group = { moduleName: entry.moduleName, moduleId: entry.moduleId, entries: [] } + map.set(entry.slot, group) + } + group.entries.push({ ...entry, globalIndex: idx }) + }) + return Array.from(map.entries()).sort(([a], [b]) => a - b) + }, [entries]) + + const [expandedSlots, setExpandedSlots] = useState>(() => new Set(groups.map(([slot]) => slot))) + + useEffect(() => { + setExpandedSlots((prev) => { + const next = new Set(prev) + for (const [slot] of groups) { + next.add(slot) + } + return next + }) + }, [groups]) + + const toggleSlot = (slot: number) => { + setExpandedSlots((prev) => { + const next = new Set(prev) + if (next.has(slot)) { + next.delete(slot) + } else { + next.add(slot) + } + return next + }) + } + + if (entries.length === 0) { + return ( +
+ No modules configured. Assign modules in Backplane Configuration to generate I/O mappings. +
+ ) + } + + return ( +
+ {groups.map(([slot, group]) => { + const isExpanded = expandedSlots.has(slot) + const ioCounts = { di: 0, do: 0, ai: 0, ao: 0 } + for (const e of group.entries) { + if (e.channelType === 'digitalInput') ioCounts.di++ + else if (e.channelType === 'digitalOutput') ioCounts.do++ + else if (e.channelType === 'analogInput') ioCounts.ai++ + else if (e.channelType === 'analogOutput') ioCounts.ao++ + } + const ioSummary: string[] = [] + if (ioCounts.di > 0) ioSummary.push(`${ioCounts.di} DI`) + if (ioCounts.do > 0) ioSummary.push(`${ioCounts.do} DO`) + if (ioCounts.ai > 0) ioSummary.push(`${ioCounts.ai} AI`) + if (ioCounts.ao > 0) ioSummary.push(`${ioCounts.ao} AO`) + + return ( +
+ + + {isExpanded && ( + + + + + + + + + + + {group.entries.map((entry) => ( + + + + + + + ))} + +
+ Channel + + Type + + IEC Address + + Alias +
+ {entry.channelName} + + {entry.channelType} + + {entry.iecAddress} + + handleAliasChange(entry.globalIndex, e.target.value)} + placeholder='Alias...' + className='h-[26px] w-full rounded border border-neutral-100 bg-white px-2 font-caption text-cp-sm text-neutral-850 outline-none placeholder:text-neutral-400 focus:border-brand-medium-dark dark:border-neutral-800 dark:bg-neutral-950 dark:text-neutral-300 dark:placeholder:text-neutral-600' + /> +
+ )} +
+ ) + })} +
+ ) +} + +export { IoTableLayout } diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/module-slots-layout.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/module-slots-layout.tsx new file mode 100644 index 000000000..74f33471a --- /dev/null +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/module-slots-layout.tsx @@ -0,0 +1,156 @@ +import { Select, SelectContent, SelectItem, SelectTrigger } from '@root/frontend/components/_atoms/select' +import { useOpenPLCStore } from '@root/frontend/store' +import { useMemo } from 'react' + +import type { ModuleSystem, ScreenSection } from '../index' + +type ModuleSlotsLayoutProps = { + section: ScreenSection + moduleSystem: ModuleSystem +} + +function ModuleSlotsLayout({ section, moduleSystem }: ModuleSlotsLayoutProps) { + const maxSlots = section.maxSlots || moduleSystem?.maxSlots || 8 + const availableModules = moduleSystem?.modules ?? [] + + const vendorScreenData = useOpenPLCStore((s) => s.deviceDefinitions.configuration.vendorScreenData) + const setVendorScreenData = useOpenPLCStore((s) => s.deviceActions.setVendorScreenData) + const persistenceKey = section.persistence || section.id + + const storedData = vendorScreenData?.[persistenceKey] as { slots?: (string | null)[] } | undefined + const slots = storedData?.slots ?? Array(maxSlots).fill(null) + + const handleSlotChange = (slotIndex: number, moduleId: string) => { + const next = [...slots] + next[slotIndex] = moduleId || null + setVendorScreenData(persistenceKey, { ...storedData, slots: next }) + } + + const handleClearAll = () => { + setVendorScreenData(persistenceKey, { ...storedData, slots: Array(maxSlots).fill(null) }) + } + + const ioSummary = useMemo(() => { + const totals = { di: 0, do: 0, ai: 0, ao: 0 } + for (const moduleId of slots) { + if (!moduleId) continue + const mod = availableModules.find((m) => m.id === moduleId) + if (!mod) continue + totals.di += mod.io.digitalInputs + totals.do += mod.io.digitalOutputs + totals.ai += mod.io.analogInputs + totals.ao += mod.io.analogOutputs + } + return totals + }, [slots, availableModules]) + + const hasAnyModule = slots.some((s) => s !== null) + + const getModuleIoLabel = (moduleId: string) => { + const mod = availableModules.find((m) => m.id === moduleId) + if (!mod) return '' + const parts: string[] = [] + if (mod.io.digitalInputs > 0) parts.push(`${mod.io.digitalInputs} DI`) + if (mod.io.digitalOutputs > 0) parts.push(`${mod.io.digitalOutputs} DO`) + if (mod.io.analogInputs > 0) parts.push(`${mod.io.analogInputs} AI`) + if (mod.io.analogOutputs > 0) parts.push(`${mod.io.analogOutputs} AO`) + return parts.join(', ') + } + + return ( +
+ {section.actions && ( +
+ {(section.actions as Array<{ id: string; label: string; type: string; action?: string }>).map((action) => { + if (action.type === 'local' && action.action === 'clear-module-slots') { + return ( + + ) + } + return null + })} +
+ )} + +
+ {slots.map((moduleId, idx) => ( +
+ Slot {idx + 1} + + {moduleId && ( + {getModuleIoLabel(moduleId)} + )} +
+ ))} +
+ + {hasAnyModule && ( +
+ Total I/O: + {ioSummary.di > 0 && ( + {ioSummary.di} DI + )} + {ioSummary.do > 0 && ( + {ioSummary.do} DO + )} + {ioSummary.ai > 0 && ( + {ioSummary.ai} AI + )} + {ioSummary.ao > 0 && ( + {ioSummary.ao} AO + )} +
+ )} +
+ ) +} + +export { ModuleSlotsLayout } diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/unsupported-layout.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/unsupported-layout.tsx new file mode 100644 index 000000000..f545a616a --- /dev/null +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/unsupported-layout.tsx @@ -0,0 +1,13 @@ +type UnsupportedLayoutProps = { + layoutType: string +} + +function UnsupportedLayout({ layoutType }: UnsupportedLayoutProps) { + return ( +
+ Layout type "{layoutType}" is not yet supported. +
+ ) +} + +export { UnsupportedLayout } diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/section-renderer.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/section-renderer.tsx new file mode 100644 index 000000000..995f3a50d --- /dev/null +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/section-renderer.tsx @@ -0,0 +1,53 @@ +import { useState } from 'react' + +import type { ModuleSystem, ScreenSection } from './index' +import { FormLayout } from './layouts/form-layout' +import { IoTableLayout } from './layouts/io-table-layout' +import { ModuleSlotsLayout } from './layouts/module-slots-layout' +import { UnsupportedLayout } from './layouts/unsupported-layout' + +type SectionRendererProps = { + section: ScreenSection + moduleSystem: ModuleSystem +} + +function SectionRenderer({ section, moduleSystem }: SectionRendererProps) { + const [collapsed, setCollapsed] = useState(section.collapsed ?? false) + + const renderLayout = () => { + switch (section.layout) { + case 'module-slots': + return + case 'io-table': + return + case 'form': + return + default: + return + } + } + + return ( +
+
section.collapsible && setCollapsed(!collapsed)} + > +

{section.title}

+ {section.collapsible && ( + + + + )} +
+ {!collapsed && renderLayout()} +
+ ) +} + +export { SectionRenderer } diff --git a/src/frontend/components/_features/[workspace]/editor/package-manager/index.tsx b/src/frontend/components/_features/[workspace]/editor/package-manager/index.tsx new file mode 100644 index 000000000..0d968dd27 --- /dev/null +++ b/src/frontend/components/_features/[workspace]/editor/package-manager/index.tsx @@ -0,0 +1,224 @@ +import * as Popover from '@radix-ui/react-popover' +import { MinusIcon } from '@root/frontend/assets/icons/interface/Minus' +import { PlusIcon } from '@root/frontend/assets/icons/interface/Plus' +import { useOpenPLCStore } from '@root/frontend/store' +import type { InstalledPackage, PackageManifest } from '@root/middleware/shared/ports/types' +import { usePackages } from '@root/middleware/shared/providers/platform-context' +import { useCallback, useEffect, useState } from 'react' + +const PackageManagerEditor = () => { + const packages = usePackages() + const [installedPackages, setInstalledPackages] = useState([]) + const [selectedPackageId, setSelectedPackageId] = useState(null) + const [selectedManifest, setSelectedManifest] = useState(null) + const [isPopoverOpen, setIsPopoverOpen] = useState(false) + const openModal = useOpenPLCStore((state) => state.modalActions.openModal) + + const refreshPackages = useCallback(async () => { + if (!packages) return + const result = await packages.listInstalled() + setInstalledPackages(result) + }, [packages]) + + useEffect(() => { + void refreshPackages() + }, [refreshPackages]) + + useEffect(() => { + if (!selectedPackageId || !packages) { + setSelectedManifest(null) + return + } + const fetchManifest = async () => { + const manifest = await packages.getManifest(selectedPackageId) + setSelectedManifest(manifest) + } + void fetchManifest() + }, [selectedPackageId, packages]) + + const handleImportFromFile = async () => { + if (!packages) return + setIsPopoverOpen(false) + const result = await packages.importFromFile() + if (result.success) { + await refreshPackages() + if (result.packageId) { + setSelectedPackageId(result.packageId) + } + } + } + + const handleImportFromInternet = () => { + setIsPopoverOpen(false) + openModal('debugger-message', { + type: 'info', + title: 'Coming Soon', + message: 'Online package browsing will be available in a future update.', + buttons: ['OK'], + onResponse: () => {}, + }) + } + + const handleUninstall = async () => { + if (!selectedPackageId || !packages) return + const result = await packages.uninstall(selectedPackageId) + if (result.success) { + setSelectedPackageId(null) + await refreshPackages() + } + } + + if (!packages) { + return ( +
+ Package management is not available on this platform. +
+ ) + } + + return ( +
+ {/* Left panel: Installed packages list */} +
+
+

Installed Packages

+
+ + + + + + + + + + + + + +
+
+ +
+ {installedPackages.length === 0 ? ( +
+ No packages installed. Click + to add a package. +
+ ) : ( + installedPackages.map((pkg) => ( + + )) + )} +
+
+ +
+ + {/* Right panel: Package details */} +
+ {selectedManifest ? ( + <> +

+ {selectedManifest.package.name} +

+
+ + + {selectedManifest.package.vendor.url && ( + + )} + + {selectedManifest.package.license && ( + + )} + +
+ Devices +
+ {selectedManifest.devices.map((device) => ( +
+ + {device.name} + + {device.category && ( + + ({device.category}) + + )} +
+ ))} +
+
+
+ + ) : ( +
+ Select a package to view details +
+ )} +
+
+ ) +} + +function DetailRow({ label, value }: { label: string; value: string }) { + return ( +
+ {label} + {value} +
+ ) +} + +export { PackageManagerEditor } diff --git a/src/frontend/components/_features/[workspace]/editor/vendor-screen/index.tsx b/src/frontend/components/_features/[workspace]/editor/vendor-screen/index.tsx new file mode 100644 index 000000000..e7663b883 --- /dev/null +++ b/src/frontend/components/_features/[workspace]/editor/vendor-screen/index.tsx @@ -0,0 +1,29 @@ +import { useOpenPLCStore } from '@root/frontend/store' + +import { VendorScreenRenderer } from '../device/configuration/vendor-screen' + +const VendorScreenEditor = () => { + const editor = useOpenPLCStore((s) => s.editor) + const screenName = editor.type === 'plc-vendor-screen' ? editor.meta.screenName : '' + const deviceBoard = useOpenPLCStore((s) => s.deviceDefinitions.configuration.deviceBoard) + const availableBoards = useOpenPLCStore((s) => s.deviceAvailableOptions.availableBoards) + const boardInfo = availableBoards.get(deviceBoard) + const screenDefinition = boardInfo?.vpp?.screens?.[screenName] ?? null + const moduleSystem = boardInfo?.vpp?.moduleSystem ?? null + + if (!screenDefinition) { + return ( +
+ Screen not available. Make sure a VPP board is selected. +
+ ) + } + + return ( +
+ +
+ ) +} + +export { VendorScreenEditor } diff --git a/src/frontend/store/slices/workspace/types.ts b/src/frontend/store/slices/workspace/types.ts index fd3c70f65..c4b8ffd56 100644 --- a/src/frontend/store/slices/workspace/types.ts +++ b/src/frontend/store/slices/workspace/types.ts @@ -34,6 +34,8 @@ export type WorkspaceProjectTreeLeafType = | 'resource' | 'server' | 'remote-device' + | 'vendor-screen' + | 'package-manager' | null // --------------------------------------------------------------------------- From 04ce3f7efa70930745794b930129a7a87f6860ad Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:39:21 -0400 Subject: [PATCH 007/296] feat: integrate VPP into tabs, project tree, and workspace routing Add vendor-screen and package-manager tab icons and type handling. Add vendor screen leaves to project tree when VPP board is selected. Route plc-vendor-screen and plc-package-manager editor types in workspace screen. Subscribe to package manager open/boards-updated events via packages port. Pass packagePath for VPP board previews. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/frontend/components/_atoms/tab/index.tsx | 29 +++++-------- .../editor/device/configuration/board.tsx | 4 +- .../_molecules/project-tree/index.tsx | 2 + .../_organisms/explorer/project.tsx | 23 +++++++++++ src/frontend/screens/workspace-screen.tsx | 41 ++++++++++++++++++- 5 files changed, 78 insertions(+), 21 deletions(-) diff --git a/src/frontend/components/_atoms/tab/index.tsx b/src/frontend/components/_atoms/tab/index.tsx index fdd4bbe3f..ae79ce83a 100644 --- a/src/frontend/components/_atoms/tab/index.tsx +++ b/src/frontend/components/_atoms/tab/index.tsx @@ -1,3 +1,4 @@ +import type React from 'react' import { ComponentPropsWithoutRef, useCallback } from 'react' import { CloseIcon } from '../../../assets/icons/interface/Close' @@ -30,7 +31,7 @@ type ITabProps = ComponentPropsWithoutRef<'div'> & { handleClickedTab: () => void } -const TabIcons = { +const TabIcons: Record = { ld: , sfc: , fbd: , @@ -47,6 +48,8 @@ const TabIcons = { orchestrators: , 'remote-device': , server: , + 'vendor-screen': , + 'package-manager': , } const Tab = (props: ITabProps) => { @@ -55,23 +58,7 @@ const Tab = (props: ITabProps) => { } = useOpenPLCStore() const { fileName, fileDerivation, currentTab, handleDeleteTab, handleClickedTab, ...res } = props - let languageOrDerivation: - | 'il' - | 'st' - | 'python' - | 'cpp' - | 'resource' - | 'ld' - | 'sfc' - | 'fbd' - | 'array' - | 'enumerated' - | 'structure' - | 'configuration' - | 'pin-mapping' - | 'orchestrators' - | 'remote-device' - | 'server' = 'il' + let languageOrDerivation: string = 'il' if (fileDerivation?.type === 'data-type' || fileDerivation?.type === 'device') { languageOrDerivation = fileDerivation?.derivation @@ -92,6 +79,12 @@ const Tab = (props: ITabProps) => { if (fileDerivation?.type === 'server') { languageOrDerivation = 'server' } + if (fileDerivation?.type === 'vendor-screen') { + languageOrDerivation = 'vendor-screen' + } + if (fileDerivation?.type === 'package-manager') { + languageOrDerivation = 'package-manager' + } const { file: associatedFile } = getFile({ name: fileName || '' }) const handleFileName = useCallback( diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx index feae4a5de..8bdedeccd 100644 --- a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx @@ -121,11 +121,11 @@ const Board = memo(function () { useEffect(() => { const fetchPreviewImage = async () => { const boardInfos = availableBoards.get(deviceBoard) - const imagePath = await device.getPreviewImage(boardInfos?.preview || 'generic.png') + const imagePath = await device.getPreviewImage(boardInfos?.preview || 'generic.png', boardInfos?.vpp?.packagePath) setPreviewImage(imagePath) } void fetchPreviewImage() - }, [deviceBoard, device]) + }, [deviceBoard, device, availableBoards]) const refreshCommunicationPorts = useCallback( async (e: React.MouseEvent) => { diff --git a/src/frontend/components/_molecules/project-tree/index.tsx b/src/frontend/components/_molecules/project-tree/index.tsx index 0e6136a57..25bcfa63d 100644 --- a/src/frontend/components/_molecules/project-tree/index.tsx +++ b/src/frontend/components/_molecules/project-tree/index.tsx @@ -256,6 +256,7 @@ type IProjectTreeLeafProps = ComponentPropsWithoutRef<'li'> & { | 'devOrchestrators' | 'server' | 'remoteDevice' + | 'vendorScreen' leafType: WorkspaceProjectTreeLeafType label?: string } @@ -277,6 +278,7 @@ const LeafSources = { devOrchestrators: { LeafIcon: OrchestratorIcon }, server: { LeafIcon: ServerIcon }, remoteDevice: { LeafIcon: RemoteDeviceIcon }, + vendorScreen: { LeafIcon: ConfigIcon }, } const ProjectTreeLeaf = ({ leafLang, leafType, label, onClick: handleLeafClick, ...res }: IProjectTreeLeafProps) => { const { diff --git a/src/frontend/components/_organisms/explorer/project.tsx b/src/frontend/components/_organisms/explorer/project.tsx index b4603f8d6..495b9af56 100644 --- a/src/frontend/components/_organisms/explorer/project.tsx +++ b/src/frontend/components/_organisms/explorer/project.tsx @@ -25,6 +25,12 @@ const Project = () => { searchQuery, } = useOpenPLCStore() + // Get VPP vendor screens from the currently selected board + const deviceBoard = useOpenPLCStore((s) => s.deviceDefinitions.configuration.deviceBoard) + const availableBoards = useOpenPLCStore((s) => s.deviceAvailableOptions.availableBoards) + const currentBoardInfo = availableBoards.get(deviceBoard) + const vendorScreens = currentBoardInfo?.vpp?.screens ? Object.keys(currentBoardInfo.vpp.screens) : [] + const handleCreateTab = ({ elementType, name, path, configuration: tabConfig }: TabsProps) => { const tabToBeCreated = { name, path, elementType, configuration: tabConfig } updateTabs(tabToBeCreated) @@ -272,6 +278,23 @@ const Project = () => { )} + {/* Vendor screens from VPP packages */} + {vendorScreens.map((screenName) => ( + s.toUpperCase())} + onClick={() => + handleCreateTab({ + name: screenName, + path: `/vendor-screen/${screenName}`, + elementType: { type: 'vendor-screen', screenName }, + }) + } + /> + ))} + {/* Project Servers tree branch */} {capabilities.hasLocalSerialPorts && ( diff --git a/src/frontend/screens/workspace-screen.tsx b/src/frontend/screens/workspace-screen.tsx index 0ae52fd0d..7e2be4979 100644 --- a/src/frontend/screens/workspace-screen.tsx +++ b/src/frontend/screens/workspace-screen.tsx @@ -2,7 +2,7 @@ import * as Tabs from '@radix-ui/react-tabs' import { useCallback, useEffect, useMemo, useRef, useState } from 'react' import { ImperativePanelHandle } from 'react-resizable-panels' -import { useCapabilities, useChatPanel, useDebugger, useDevice } from '../../middleware/shared/providers' +import { useCapabilities, useChatPanel, useDebugger, useDevice, usePlatform } from '../../middleware/shared/providers' import { ExitIcon } from '../assets/icons/interface/Exit' import { ClearConsoleButton } from '../components/_atoms/buttons/console/clear-console' import { DataTypeEditor } from '../components/_features/[workspace]/data-type' @@ -10,10 +10,12 @@ import { DeviceEditor } from '../components/_features/[workspace]/editor/device' import { RemoteDeviceEditor } from '../components/_features/[workspace]/editor/device/remote-device' import { GraphicalEditor } from '../components/_features/[workspace]/editor/graphical' import { MonacoEditor } from '../components/_features/[workspace]/editor/monaco' +import { PackageManagerEditor } from '../components/_features/[workspace]/editor/package-manager' import { ResourcesEditor } from '../components/_features/[workspace]/editor/resource-editor' import { ModbusServerEditor } from '../components/_features/[workspace]/editor/server/modbus-server' import { OpcUaServerEditor } from '../components/_features/[workspace]/editor/server/opcua-server' import { S7CommServerEditor } from '../components/_features/[workspace]/editor/server/s7comm-server' +import { VendorScreenEditor } from '../components/_features/[workspace]/editor/vendor-screen' import { Search } from '../components/_features/[workspace]/search' import { VariablesPanel } from '../components/_molecules/variables-panel' import { Console as ConsoleComponent } from '../components/_organisms/console' @@ -270,6 +272,41 @@ const WorkspaceScreen = () => { void loadAvailableBoards() }, [device, setAvailableOptions]) + // Subscribe to VPP package events via the packages port + const packagesPort = usePlatform().packages + useEffect(() => { + if (!packagesPort) return + + const unsubOpen = packagesPort.onOpenManager(() => { + const { tabsActions, editorActions } = useOpenPLCStore.getState() + const tab = { + name: 'Package Manager', + path: '/package-manager', + elementType: { type: 'package-manager' as const }, + } + tabsActions.updateTabs(tab) + const existing = editorActions.getEditorFromEditors(tab.name) + if (!existing) { + const model = { type: 'plc-package-manager' as const, meta: { name: 'Package Manager' } } + editorActions.addModel(model) + editorActions.setEditor(model) + } else { + editorActions.setEditor(existing) + } + }) + + const unsubBoards = packagesPort.onBoardsUpdated(() => { + void device.getAvailableBoards().then((boardsMap) => { + setAvailableOptions({ availableBoards: boardsMap }) + }) + }) + + return () => { + unsubOpen() + unsubBoards() + } + }, [packagesPort, device, setAvailableOptions]) + return (
@@ -340,6 +377,8 @@ const WorkspaceScreen = () => { )} {editor['type'] === 'plc-server' && editor.meta.protocol === 's7comm' && } {editor['type'] === 'plc-server' && editor.meta.protocol === 'opcua' && } + {editor['type'] === 'plc-vendor-screen' && } + {editor['type'] === 'plc-package-manager' && } {editor['type'] === 'plc-datatype' && (
{' '} From 36aa88fe4af348361d67ccafa34b3976d05eaf39 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:51:38 -0400 Subject: [PATCH 008/296] fix: address VPP integration issues from testing 1. Add "Install additional boards..." option at the end of the Device dropdown that opens the Package Manager tab. 2. Replace emoji icons in debugger-message modal with the existing WarningIcon SVG component. 3. Use screen names as-is from the manifest instead of applying camelCase splitting (they are already human-readable). 4. Add vendor IO mapping aliases to the POU variable location dropdown by creating buildVendorIoOptionGroups utility and vendorIoSelectors hook, integrated into both variables-table and global-variables-table. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../editor/device/configuration/board.tsx | 32 +++++++++++++++ .../global-variables-table/editable-cell.tsx | 9 +++-- .../variables-table/editable-cell.tsx | 9 +++-- .../_organisms/explorer/project.tsx | 2 +- .../modals/debugger-message-modal.tsx | 19 ++------- src/frontend/hooks/use-store-selectors.ts | 25 ++++++++++++ src/frontend/utils/remote-device-options.ts | 40 ++++++++++++++++++- 7 files changed, 112 insertions(+), 24 deletions(-) diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx index 8bdedeccd..7384d0373 100644 --- a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx @@ -157,6 +157,25 @@ const Board = memo(function () { const handleSetDeviceBoard = useCallback( (board: string) => { + if (board === '__install_additional_boards__') { + const { tabsActions, editorActions } = useOpenPLCStore.getState() + const tab = { + name: 'Package Manager', + path: '/package-manager', + elementType: { type: 'package-manager' as const }, + } + tabsActions.updateTabs(tab) + const existing = editorActions.getEditorFromEditors(tab.name) + if (!existing) { + const model = { type: 'plc-package-manager' as const, meta: { name: 'Package Manager' } } + editorActions.addModel(model) + editorActions.setEditor(model) + } else { + editorActions.setEditor(existing) + } + return + } + const normalizedBoard = board.split('[')[0].trim() if (connectionStatus === 'connected' && normalizedBoard !== deviceBoard) { @@ -378,6 +397,19 @@ const Board = memo(function () { ) })} + {capabilities.hasPackageManager && ( + <> +
+ + + Install additional boards... + + + + )}
diff --git a/src/frontend/components/_molecules/global-variables-table/editable-cell.tsx b/src/frontend/components/_molecules/global-variables-table/editable-cell.tsx index e5994023f..8e57efe62 100644 --- a/src/frontend/components/_molecules/global-variables-table/editable-cell.tsx +++ b/src/frontend/components/_molecules/global-variables-table/editable-cell.tsx @@ -3,12 +3,12 @@ import type { CellContext, RowData } from '@tanstack/react-table' import { useCallback, useEffect, useRef, useState } from 'react' import type { PLCGlobalVariable } from '../../../../middleware/shared/ports/types' -import { pinSelectors, remoteDeviceSelectors } from '../../../hooks/use-store-selectors' +import { pinSelectors, remoteDeviceSelectors, vendorIoSelectors } from '../../../hooks/use-store-selectors' import { useOpenPLCStore } from '../../../store' import type { ProjectResponse } from '../../../store/slices/project' import { cn } from '../../../utils/cn' import { isLegalIdentifier, sanitizeVariableInput } from '../../../utils/keywords' -import { buildRemoteDeviceOptionGroups } from '../../../utils/remote-device-options' +import { buildRemoteDeviceOptionGroups, buildVendorIoOptionGroups } from '../../../utils/remote-device-options' import { findAllReferencesToVariable, propagateVariableRename, @@ -286,6 +286,7 @@ const EditableLocationCell = ({ const { searchQuery } = useOpenPLCStore() const existingPins = pinSelectors.usePins() const remoteIOPoints = remoteDeviceSelectors.useRemoteDeviceIOPoints() + const vendorIoEntries = vendorIoSelectors.useVendorIoEntries() const [cellValue, setCellValue] = useState(initialValue ?? '') @@ -337,6 +338,7 @@ const EditableLocationCell = ({ })) const remoteGroups = buildRemoteDeviceOptionGroups(id, remoteIOPoints) + const vendorGroups = buildVendorIoOptionGroups(id, vendorIoEntries) return [ { label: 'Analog Inputs', options: ainPins }, @@ -344,8 +346,9 @@ const EditableLocationCell = ({ { label: 'Digital Inputs', options: dinPins }, { label: 'Digital Outputs', options: doutPins }, ...remoteGroups, + ...vendorGroups, ] - }, [id, existingPins, remoteIOPoints]) + }, [id, existingPins, remoteIOPoints, vendorIoEntries]) return editable ? ( { key={`vendor-${screenName}`} leafLang='vendorScreen' leafType='vendor-screen' - label={screenName.replace(/([A-Z])/g, ' $1').replace(/^./, (s) => s.toUpperCase())} + label={screenName} onClick={() => handleCreateTab({ name: screenName, diff --git a/src/frontend/components/_organisms/modals/debugger-message-modal.tsx b/src/frontend/components/_organisms/modals/debugger-message-modal.tsx index d12f9d65a..179aa6c76 100644 --- a/src/frontend/components/_organisms/modals/debugger-message-modal.tsx +++ b/src/frontend/components/_organisms/modals/debugger-message-modal.tsx @@ -1,3 +1,4 @@ +import { WarningIcon } from '../../../assets/icons/interface/Warning' import { useOpenPLCStore } from '../../../store' import { Modal, ModalContent, ModalTitle } from '../../_molecules/modal' @@ -25,20 +26,6 @@ const DebuggerMessageModal = () => { if (!modalData) return null - const getIcon = () => { - switch (modalData.type) { - case 'error': - return '❌' - case 'warning': - return '⚠️' - case 'question': - return '❓' - case 'info': - default: - return 'ℹ️' - } - } - return ( { }} > -
{getIcon()}
+
+ +
{modalData.title}

{modalData.message}

diff --git a/src/frontend/hooks/use-store-selectors.ts b/src/frontend/hooks/use-store-selectors.ts index 03b7c5e65..872b91b3e 100644 --- a/src/frontend/hooks/use-store-selectors.ts +++ b/src/frontend/hooks/use-store-selectors.ts @@ -1,5 +1,6 @@ import { useMemo } from 'react' +import type { IoMappingEntry, VendorIoMapping } from '../../middleware/shared/ports/types' import { useOpenPLCStore } from '../store' type RemoteDeviceIOPoint = { @@ -117,6 +118,29 @@ const remoteDeviceSelectors = { }, } +// ===================== Vendor IO selectors. ===================== +const vendorIoSelectors = { + useVendorIoEntries: (): IoMappingEntry[] => { + const vendorScreenData = useOpenPLCStore((state) => state.deviceDefinitions.configuration.vendorScreenData) + + return useMemo(() => { + if (!vendorScreenData) return [] + + // Look through all vendorScreenData keys for io-mapping entries + for (const [, value] of Object.entries(vendorScreenData)) { + const mapping = value as VendorIoMapping | undefined + if (mapping?.entries && Array.isArray(mapping.entries) && mapping.entries.length > 0) { + // Check if it looks like an IO mapping (has iecAddress field) + if ('iecAddress' in mapping.entries[0]) { + return mapping.entries + } + } + } + return [] + }, [vendorScreenData]) + }, +} + export { boardSelectors, communicationSelectors, @@ -127,6 +151,7 @@ export { rtuSelectors, staticHostSelectors, tcpSelectors, + vendorIoSelectors, } export type { RemoteDeviceIOPoint } diff --git a/src/frontend/utils/remote-device-options.ts b/src/frontend/utils/remote-device-options.ts index e4049514e..db29dcd9e 100644 --- a/src/frontend/utils/remote-device-options.ts +++ b/src/frontend/utils/remote-device-options.ts @@ -1,8 +1,10 @@ /** - * Utility functions for building remote device IO point options - * Used in location dropdowns for variable tables + * Utility functions for building remote device and vendor module IO point options. + * Used in location dropdowns for variable tables. */ +import type { IoMappingEntry } from '../../middleware/shared/ports/types' + export type RemoteDeviceIOPoint = { deviceName: string ioGroupName: string @@ -56,3 +58,37 @@ export function buildRemoteDeviceOptionGroups(cellId: string, remoteIOPoints: Re options, })) } + +/** + * Builds dropdown option groups from vendor module IO mapping entries. + * Groups entries by slot/module and only includes entries with aliases. + * + * @param cellId - Unique identifier for the cell (used to generate unique option IDs) + * @param entries - Array of vendor IO mapping entries from vendorScreenData + * @returns Array of dropdown groups, one per slot with aliased IO entries + */ +export function buildVendorIoOptionGroups(cellId: string, entries: IoMappingEntry[]): DropdownGroup[] { + const groupsBySlot = new Map() + + for (const entry of entries) { + if (!entry.alias) continue + + const groupKey = `Slot ${entry.slot}: ${entry.moduleName}` + let group = groupsBySlot.get(groupKey) + if (!group) { + group = [] + groupsBySlot.set(groupKey, group) + } + + group.push({ + id: `${cellId}-vendor-${entry.slot}-${entry.channelName}`, + value: entry.iecAddress, + label: `${entry.iecAddress} (${entry.alias})`, + }) + } + + return Array.from(groupsBySlot.entries()).map(([slotLabel, options]) => ({ + label: slotLabel, + options, + })) +} From 5f5d2120561ce14053a3621264f7e1780235ec31 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:54:21 -0400 Subject: [PATCH 009/296] fix: match "Install additional boards..." style with original branch Remove separator and dark mode color override to match the original VPP branch styling for the install boards dropdown option. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../editor/device/configuration/board.tsx | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx index 7384d0373..5d39b97c2 100644 --- a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx @@ -398,17 +398,14 @@ const Board = memo(function () { ) })} {capabilities.hasPackageManager && ( - <> -
- - - Install additional boards... - - - + + + Install additional boards... + + )} From 3e95369b604daa244687b025c634ad16bb5dc765 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 6 Apr 2026 15:55:20 -0400 Subject: [PATCH 010/296] fix: restore separator and add + prefix to install boards option Restore the border-t separator before the install option matching the original branch, and add a + prefix to the label text. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../editor/device/configuration/board.tsx | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx index 5d39b97c2..b86c585d2 100644 --- a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx @@ -398,14 +398,17 @@ const Board = memo(function () { ) })} {capabilities.hasPackageManager && ( - - - Install additional boards... - - + <> +
+ + + + Install additional boards... + + + )} From a93811a4d8a586c492d886a5fdf93bb29699d1ca Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Sun, 12 Apr 2026 10:00:18 -0400 Subject: [PATCH 011/296] docs: add debugger scalability analysis for large projects Detailed investigation of why compilation fails with large PLC projects (32K+ debug variables). Documents the root causes across the full pipeline (xml2st, MatIEC, runtime, editor) and proposes 6 fix strategies ranging from quick platform-aware limits to a full dynamic registration architecture. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/debugger-scalability-analysis.md | 1201 +++++++++++++++++++++++++ 1 file changed, 1201 insertions(+) create mode 100644 docs/debugger-scalability-analysis.md diff --git a/docs/debugger-scalability-analysis.md b/docs/debugger-scalability-analysis.md new file mode 100644 index 000000000..5e7338c71 --- /dev/null +++ b/docs/debugger-scalability-analysis.md @@ -0,0 +1,1201 @@ +# Debugger Scalability Analysis & Fix Strategies + +## Problem Statement + +OpenPLC Editor v4 fails to compile projects with large numbers of variables. A real-world user project with ~3,500 global variables and 16 program instances produces **32,774 debug variable entries**, generating a `debug.c` file of **33,186 lines** (~2.5 MB). Compilation fails on AVR targets with: + +``` +debug.c:32926:1: error: size of array is too large +``` + +The root cause is that the live debugger architecture requires a **compile-time static C array** (`debug_vars[]`) containing one entry per scalar variable in the entire project. Arrays are expanded element-by-element, and every internal member of every function block instance gets its own entry. This does not scale. + +--- + +## Architecture Overview + +### Current Compilation Pipeline + +``` +PLCopen XML ──→ xml2st ──→ Structured Text + debug.c ──→ MatIEC ──→ C files ──→ Runtime (gcc/arduino-cli) + │ │ + ├── VARIABLES.csv (generated by MatIEC) │ + └── debug.c (generated by xml2st) │ + └──→ POUS.h, POUS.inc, Config0.h, Res0.inc +``` + +### Current Debug Variable Flow + +1. **MatIEC** generates `VARIABLES.csv` — one line per scalar leaf variable in the entire program. Arrays are expanded to individual elements. Function block members are expanded recursively. + +2. **xml2st** (`ProjectController.py`) reads `VARIABLES.csv` and generates `debug.c` containing: + - `extern` declarations for all top-level variables + - A static `debug_vars[]` array: `{pointer_to_variable, type_enum}` per variable + - `get_var_count()`, `get_var_size()`, `get_var_addr()`, `force_var()`, `set_trace()` functions + +3. **Runtime** (`debug_handler.c`) exposes a Modbus-like debug protocol: + - `0x41 DEBUG_INFO` — returns variable count (uint16_t) + - `0x43 DEBUG_GET` — read a contiguous range of variables by index + - `0x44 DEBUG_GET_LIST` — read a list of specific variable indexes + - `0x42 DEBUG_SET` — force/unforce a variable by index + - `0x45 DEBUG_GET_MD5` — verify program hash match + +4. **Editor** (`workspace-screen.tsx`) polls only the variables currently visible on screen using `DEBUG_GET_LIST`, mapping composite keys (`programName:varName`) to debug indexes via the parsed `debug.c`. + +### Key Data Structures + +**Generated debug.c (compile-time):** +```c +static const struct { + void *ptr; + __IEC_types_enum type; +} debug_vars[] = { + {&(RES0__INSTANCE0.MOTOR_SPEED), INT_ENUM}, + {&(RES0__INSTANCE16.M_AIDATA.value.table[0]), INT_ENUM}, + {&(RES0__INSTANCE16.M_AIDATA.value.table[1]), INT_ENUM}, + // ... 32,774 entries total +}; +``` + +**Runtime protocol (uint16_t indexes):** +```c +uint16_t get_var_count(void); // max 65,535 +size_t get_var_size(size_t idx); +void *get_var_addr(size_t idx); +void force_var(size_t idx, bool forced, void *val); +``` + +--- + +## Detailed Failure Analysis + +### 1. Static Array Size Exceeds Compiler/Linker Limits + +The `debug_vars[]` array with 32,774 entries consumes: + +| Target | Pointer Size | Enum Size | Entry Size | Total Array | +|--------|-------------|-----------|------------|-------------| +| AVR (8-bit) | 2 bytes | 2 bytes | 4 bytes | **131 KB** | +| ARM (32-bit) | 4 bytes | 4 bytes | 8 bytes | **262 KB** | +| x86_64 | 8 bytes | 4+4 pad | 16 bytes | **524 KB** | + +On AVR (ATmega2560: 256 KB flash, 8 KB SRAM), a 131 KB static array exceeds what can fit in a single linker section or even in total flash alongside the actual PLC program. The compiler correctly rejects this. + +Even on desktop targets where memory is abundant, a 524 KB static array in the data segment is wasteful when the user may only be debugging a handful of variables at a time. + +### 2. Array Element Explosion + +The largest contributors to the 32,774 entries in the user's project: + +| Variable Path | Elements | % of Total | +|--------------|----------|------------| +| `INSTANCE16.M_AIDATA.value.table[0..3999]` | 4,000 | 12.2% | +| `INSTANCE16.O_AIDATA.value.table[0..3999]` | 4,000 | 12.2% | +| `INSTANCE5.M_FBUS` (struct array) | 2,970 | 9.1% | +| `INSTANCE3.M_FBBW` (struct array) | 2,090 | 6.4% | +| `INSTANCE13.M_FBANFORDERUNGWP_EZ` | 1,835 | 5.6% | +| `INSTANCE4.M_FBHZMITUS` | 1,580 | 4.8% | +| Other array expansions | ~2,000 | 6.1% | +| **Total array-expanded entries** | **~18,475** | **56.4%** | + +Over half the entries are just individual array elements that could be represented as a single entry with a base pointer + element count. + +### 3. Function Block Member Expansion + +MatIEC's VARIABLES.csv expands every member of every function block instance. A function block with 50 members instantiated in 10 programs generates 500 entries. Many of these are internal FB state that users never inspect directly. + +In the user's project, ~14,000 entries come from FB member expansion of 16 program instances, each containing multiple complex function blocks with dozens of I/O pins and internal variables. + +### 4. uint16_t Variable Count Cap + +The debug protocol uses `uint16_t` for: +- Variable count in `DEBUG_INFO` response (2 bytes) +- Variable indexes in `DEBUG_GET`, `DEBUG_SET`, `DEBUG_GET_LIST` requests +- `get_var_count()` return type + +This caps the system at **65,535 variables**. The user's project is already at 32,774 — a project with twice the complexity would silently overflow, causing memory corruption or incorrect variable reads. + +### 5. Editor-Side Regex Parsing + +The editor parses `debug.c` using: +```ts +const debugVarsMatch = content.match(/debug_vars\[\]\s*=\s*\{([\s\S]*?)\};/) +``` + +For a 2.5 MB file with 32K entries, this single regex capture group match is expensive. The subsequent per-entry regex iteration (`entryRegex.exec()`) runs 32K times. This adds noticeable delay to debugger connection setup. + +### 6. VARIDX_SIZE Protocol Limit + +The runtime's `debugGetTraceList()` uses a stack-allocated buffer: +```c +#define VARIDX_SIZE 256 +uint16_t varidx_array[VARIDX_SIZE]; +``` + +This limits a single `DEBUG_GET_LIST` request to 256 variable indexes. The editor handles this by batching, but it means multiple round-trips are needed when debugging many variables simultaneously. + +--- + +## Fix Strategies + +### Strategy A: Platform-Aware Generation (Quick Win) + +**Goal:** Unblock compilation for the user's project immediately by adapting debug.c generation to the target platform's constraints. + +#### Implementation Details + +**1. Add `--target` flag to xml2st's `--generate-debug` command:** + +In `xml2st/xml2st.py`, extend the argument parser: +```python +parser.add_argument( + '--generate-debug', + nargs='+', + metavar=('ST_FILE', 'CSV_FILE'), + type=str, + help='Paths to the ST file and the variables CSV file, optionally followed by --target ', +) +parser.add_argument( + '--target', + type=str, + default='linux', + choices=['linux', 'avr', 'arm', 'simulator'], + help='Target platform for debug generation (affects variable limits)', +) +``` + +**2. Define per-platform variable limits in `ProjectController.py`:** + +```python +PLATFORM_LIMITS = { + 'avr': { + 'max_debug_vars': 2048, # ~8KB on AVR (4 bytes/entry) + 'expand_arrays': False, # Collapse arrays to single entries + 'include_fb_internals': False, # Only program-level variables + }, + 'arm': { + 'max_debug_vars': 8192, + 'expand_arrays': False, + 'include_fb_internals': True, + }, + 'linux': { + 'max_debug_vars': 65535, + 'expand_arrays': True, + 'include_fb_internals': True, + }, + 'simulator': { + 'max_debug_vars': 65535, + 'expand_arrays': True, + 'include_fb_internals': True, + }, +} +``` + +**3. Filter variables during `Generate_plc_debug_cvars()`:** + +In `ProjectController.py`, modify the method to accept a `target` parameter and apply filtering: +```python +def Generate_plc_debug_cvars(self, target='linux'): + limits = PLATFORM_LIMITS.get(target, PLATFORM_LIMITS['linux']) + + # Filter based on platform limits + filtered_vars = self._DbgVariablesList + if not limits['include_fb_internals']: + filtered_vars = [v for v in filtered_vars if not self._is_fb_internal(v)] + if not limits['expand_arrays']: + filtered_vars = self._collapse_array_entries(filtered_vars) + if len(filtered_vars) > limits['max_debug_vars']: + # Prioritize: program variables > global variables > FB members + filtered_vars = self._prioritize_variables(filtered_vars, limits['max_debug_vars']) + + # Generate the array from filtered list + variable_decl_array = [ + f"{{&({v['C_path']}), {v['type']}{type_suffix[v['vartype']]}}}" + for v in filtered_vars + ] + # ... +``` + +**4. Update the compiler module in the editor** (`compiler-module.ts`) to pass the target platform when invoking xml2st: + +```typescript +const executeCommand = this.#executeXml2st([ + '--generate-debug', generatedSTFilePath, generatedVARIABLESFilePath, + '--target', targetPlatform, // 'avr', 'arm', 'linux', 'simulator' +]) +``` + +**5. Emit a compiler warning when variables are truncated:** + +```python +if len(filtered_vars) < len(self._DbgVariablesList): + total = len(self._DbgVariablesList) + kept = len(filtered_vars) + print(f"Warning: Debug variable count reduced from {total} to {kept} " + f"for target '{target}'. Some variables will not be available " + f"for live debugging.", file=sys.stderr) +``` + +#### Benefits + +| Metric | Before | After | +|--------|--------|-------| +| AVR compilation | **Fails** (array too large) | Succeeds (capped at 2,048 entries) | +| Debug.c size (AVR) | 33,186 lines / 2.5 MB | ~2,200 lines / ~160 KB | +| Static array memory (AVR) | 131 KB (exceeds flash) | ~8 KB (fits in flash) | +| Implementation effort | — | **Low** (~1-2 days) | +| Protocol changes required | — | None | +| Runtime changes required | — | None | + +#### Limitations + +- Reduces debugger functionality on constrained targets (fewer variables debuggable). +- Doesn't solve the fundamental scalability issue — just pushes the ceiling. +- Requires the editor to communicate target platform to xml2st. + +--- + +### Strategy B: Array Collapse (Medium Effort, High Impact) + +**Goal:** Reduce the variable count by 50-60% by representing arrays as single entries with metadata instead of expanding every element. + +#### Implementation Details + +**1. New debug_vars entry format for arrays:** + +Modify the `debug.c.j2` template to support a new entry type: + +```c +typedef struct { + void *ptr; + __IEC_types_enum type; +} debug_var_entry_t; + +typedef struct { + void *base_ptr; // Pointer to first element + __IEC_types_enum type; // Element type + uint16_t element_count; // Number of elements + uint16_t element_size; // sizeof(element_type) for address calculation +} debug_array_entry_t; + +// Regular variables (indexed 0 to scalar_count-1) +static const debug_var_entry_t debug_vars[] = { + {&(RES0__INSTANCE0.MOTOR_SPEED), INT_ENUM}, + // ... only scalar variables +}; + +// Array variables (separate table) +static const debug_array_entry_t debug_arrays[] = { + {&(RES0__INSTANCE16.M_AIDATA.value.table[0]), INT_ENUM, 4000, sizeof(INT)}, + {&(RES0__INSTANCE16.O_AIDATA.value.table[0]), INT_ENUM, 4000, sizeof(INT)}, + // ... one entry per array, not per element +}; + +#define SCALAR_VAR_COUNT 14299 +#define ARRAY_COUNT 42 +``` + +**2. Modify `ProjectController.py` to detect and group array entries:** + +In `GetIECProgramsAndVariables()`, after building `_DbgVariablesList`, post-process to detect contiguous array sequences: + +```python +def _collapse_arrays(self, var_list): + """Group consecutive array element entries into single array descriptors.""" + arrays = {} + scalars = [] + + for v in var_list: + # Detect array element pattern: path.value.table[N] + match = re.match(r'^(.+\.value\.table)\[(\d+)\]$', v['C_path']) + if match: + base = match.group(1) + idx = int(match.group(2)) + if base not in arrays: + arrays[base] = { + 'base_path': f'{base}[0]', + 'type': v['type'], + 'vartype': v['vartype'], + 'max_idx': idx, + } + else: + arrays[base]['max_idx'] = max(arrays[base]['max_idx'], idx) + else: + scalars.append(v) + + return scalars, [ + {'base_path': a['base_path'], 'type': a['type'], + 'count': a['max_idx'] + 1, 'vartype': a['vartype']} + for a in arrays.values() + ] +``` + +**3. New runtime accessor functions:** + +Add to the generated `debug.c`: + +```c +#define ARRAY_COUNT 42 + +void *get_array_element_addr(size_t array_idx, size_t element_idx) +{ + if (array_idx >= ARRAY_COUNT) + return NULL; + + const debug_array_entry_t *arr = &debug_arrays[array_idx]; + if (element_idx >= arr->element_count) + return NULL; + + // Compute element address: base + element_idx * element_size + uint8_t *base = (uint8_t *)arr->base_ptr; + + // Handle IEC wrapper types (__IEC_INT_t has {value, flags}) + // element_size accounts for the wrapper struct stride + return (void *)(base + element_idx * arr->element_size); +} + +size_t get_array_element_count(size_t array_idx) +{ + if (array_idx >= ARRAY_COUNT) return 0; + return debug_arrays[array_idx].element_count; +} + +size_t get_array_element_size(size_t array_idx) +{ + if (array_idx >= ARRAY_COUNT) return 0; + return debug_arrays[array_idx].element_size; +} +``` + +**4. Extend the debug protocol with a new function code:** + +```c +#define MB_FC_DEBUG_GET_ARRAY 0x46 // New function code + +// Request: [0x46] [array_idx: u16] [element_start: u16] [element_end: u16] +// Response: [0x46] [status] [tick: u32] [data_len: u16] [data...] +``` + +Update `debug_handler.c`: +```c +static void debugGetArrayElements(uint8_t *frame, size_t *frame_len, + uint16_t arrayIdx, uint16_t startEl, uint16_t endEl) +{ + uint16_t arrayCount = ext_get_array_count(); + if (arrayIdx >= arrayCount) { + *frame_len = 2; + frame[0] = MB_FC_DEBUG_GET_ARRAY; + frame[1] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; + return; + } + + size_t elSize = ext_get_array_element_size(arrayIdx); + uint16_t elCount = ext_get_array_element_count(arrayIdx); + + if (startEl >= elCount || endEl >= elCount || startEl > endEl) { + *frame_len = 2; + frame[0] = MB_FC_DEBUG_GET_ARRAY; + frame[1] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; + return; + } + + size_t responseSize = 0; + uint8_t *responsePtr = &frame[10]; + + for (uint16_t el = startEl; el <= endEl; el++) { + if ((responseSize + 10) + elSize > MAX_DEBUG_FRAME) break; + + void *addr = ext_get_array_element_addr(arrayIdx, el); + memcpy(responsePtr, addr, elSize); + responsePtr += elSize; + responseSize += elSize; + } + + *frame_len = 10 + responseSize; + frame[0] = MB_FC_DEBUG_GET_ARRAY; + frame[1] = MB_DEBUG_SUCCESS; + frame[2] = (uint8_t)(arrayIdx >> 8); + frame[3] = (uint8_t)(arrayIdx & 0xFF); + frame[4] = (uint8_t)((tick__ >> 24) & 0xFF); + frame[5] = (uint8_t)((tick__ >> 16) & 0xFF); + frame[6] = (uint8_t)((tick__ >> 8) & 0xFF); + frame[7] = (uint8_t)(tick__ & 0xFF); + frame[8] = (uint8_t)(responseSize >> 8); + frame[9] = (uint8_t)(responseSize & 0xFF); +} +``` + +**5. Update editor-side index mapping:** + +In `debugger-session.ts`, `buildVariableIndexMap()` already handles arrays specially (lines 71-98). Update it to use the new array protocol: + +```typescript +// For array variables, store a reference to the array debug index +// instead of individual element indexes +if (v.type.definition === 'array' && v.type.data) { + const arrayDebugIndex = findArrayDebugIndex(instance.name, v.name, parsed.arrays) + if (arrayDebugIndex !== null) { + // Store with a special prefix to distinguish from scalar indexes + const compositeKey = `${pou.data.name}:${v.name}` + indexMap.set(compositeKey, ARRAY_INDEX_FLAG | arrayDebugIndex) + // Individual element access: compositeKey[i] resolves at poll time + } +} +``` + +**6. Update the Modbus/WebSocket client classes:** + +Add a `getArrayElements()` method alongside the existing `getVariablesList()`: + +```typescript +async getArrayElements(arrayIndex: number, startElement: number, endElement: number): Promise<{ + success: boolean + tick?: number + data?: Buffer + error?: string +}> { + const functionCode = ModbusFunctionCode.DEBUG_GET_ARRAY + const request = Buffer.alloc(7) + request.writeUInt8(functionCode, 0) + request.writeUInt16BE(arrayIndex, 1) + request.writeUInt16BE(startElement, 3) + request.writeUInt16BE(endElement, 5) + // ... same response handling pattern as getVariablesList +} +``` + +#### Benefits + +| Metric | Before | After | +|--------|--------|-------| +| debug_vars[] entries | 32,774 | ~14,299 scalars + 42 array descriptors | +| debug.c file size | 2.5 MB | ~1.1 MB | +| Static array memory (AVR) | 131 KB | ~57 KB (scalars) + ~336 bytes (arrays) | +| Static array memory (x86_64) | 524 KB | ~229 KB + ~672 bytes | +| Variable count overhead | 56% from arrays | 0% from arrays | +| Array element debugging | Still works (new protocol) | Still works (computed addresses) | +| Implementation effort | — | **Medium** (~1-2 weeks, touches all 4 repos) | + +#### Limitations + +- Requires a protocol extension (new function code 0x46), meaning editor + runtime must be updated together. +- Only addresses array expansion — FB member expansion is still O(members * instances). +- The scalar array is still static and could still be large for FB-heavy projects. + +--- + +### Strategy C: FB Internal Variable Filtering (Medium Effort, High Impact) + +**Goal:** Reduce variable count by excluding function block internal state that users don't directly debug. + +#### Implementation Details + +**1. Classify variables by debuggability:** + +In `ProjectController.py`, add classification logic during `GetIECProgramsAndVariables()`: + +```python +def _classify_variable(self, attrs, parts): + """Classify a variable's debug priority. + + Returns: + 'program_direct' - Variable declared directly in a PROGRAM POU + 'global' - Global variable (CONFIG0 level) + 'fb_io' - Function block input/output pin + 'fb_internal' - Function block internal variable (VAR, VAR_TEMP) + 'external_dup' - VAR_EXTERNAL duplicate of a global (skip entirely) + """ + c_path = attrs['C_path'] + vartype = attrs['vartype'] + + # Global variables at CONFIG level + if parts[0].startswith('CONFIG') and not parts[1].startswith('RES'): + return 'global' + + # Variables inside resource programs + if len(parts) > 2: + # Check nesting depth: INSTANCE.VAR = program direct + # INSTANCE.FB_VAR.MEMBER = FB member + sub_parts = parts[2].split('.') + if len(sub_parts) == 1: + # Direct program variable (no dots after instance) + return 'program_direct' + elif vartype in ('IN', 'OUT'): + return 'fb_io' + else: + return 'fb_internal' + + return 'program_direct' +``` + +**2. Apply filtering based on target and variable priority:** + +```python +VARIABLE_PRIORITY = { + 'program_direct': 0, # Highest priority — always included + 'global': 1, + 'fb_io': 2, + 'fb_internal': 3, # Lowest priority — dropped first + 'external_dup': -1, # Never included +} + +def _filter_by_priority(self, var_list, max_count): + """Keep highest-priority variables up to max_count.""" + classified = [(self._classify_variable(v), v) for v in var_list] + classified = [(c, v) for c, v in classified if c != 'external_dup'] + classified.sort(key=lambda x: VARIABLE_PRIORITY[x[0]]) + + if len(classified) <= max_count: + return [v for _, v in classified] + + # Truncate from lowest priority + return [v for _, v in classified[:max_count]] +``` + +**3. Generate a variable catalog file alongside debug.c:** + +For variables excluded from the debug array, generate a `debug_catalog.json` that the editor can use to show users which variables are available for debugging and which were excluded: + +```python +def _generate_catalog(self, all_vars, included_vars, output_path): + """Generate a JSON catalog of all variables and their debug status.""" + included_paths = {v['C_path'] for v in included_vars} + catalog = [] + for v in all_vars: + catalog.append({ + 'iec_path': v.get('IEC_path', ''), + 'c_path': v['C_path'], + 'type': v['type'], + 'debuggable': v['C_path'] in included_paths, + 'reason': None if v['C_path'] in included_paths + else 'excluded_by_platform_limit', + }) + + with open(output_path, 'w') as f: + json.dump(catalog, f, indent=2) +``` + +The editor can display a warning icon next to non-debuggable variables in the variables panel. + +**4. Update `Generate_plc_debug_cvars()` to use the classifier:** + +```python +def Generate_plc_debug_cvars(self, target='linux', include_fb_internals=True): + if not self._DbgVariablesList and not self._VariablesList: + self.GetIECProgramsAndVariables() + + filtered = self._DbgVariablesList + if not include_fb_internals: + filtered = [ + v for v in filtered + if self._classify_variable(v, v['C_path'].split('.')) != 'fb_internal' + ] + + # Apply platform max + max_vars = PLATFORM_LIMITS.get(target, {}).get('max_debug_vars', 65535) + if len(filtered) > max_vars: + filtered = self._filter_by_priority(filtered, max_vars) + + # ... rest of generation +``` + +#### Benefits + +| Metric | Before | After (no FB internals) | +|--------|--------|------------------------| +| debug_vars[] entries | 32,774 | ~6,000-8,000 (estimated) | +| debug.c file size | 2.5 MB | ~500 KB | +| Static array memory (AVR) | 131 KB | ~24-32 KB | +| Debuggable variables | All (including useless internals) | Program vars + globals + FB I/O | +| Implementation effort | — | **Medium** (~3-5 days, mainly xml2st) | + +#### Limitations + +- Users who need to debug FB internal state lose access to those variables. +- Classification heuristics may misclassify in edge cases. +- Could be combined with Strategy B (array collapse) for maximum reduction. + +--- + +### Strategy D: Chunked Static Arrays (Low Effort, Fixes Compilation) + +**Goal:** Fix the compiler error without changing the debug protocol by splitting the single large array into multiple smaller arrays. + +#### Implementation Details + +**1. Modify the `debug.c.j2` template to emit chunked arrays:** + +```c +#define CHUNK_SIZE 1024 +#define VAR_COUNT {{ debug.vars | length }} +#define NUM_CHUNKS {{ ((debug.vars | length) + 1023) // 1024 }} + +{% for chunk_idx in range(num_chunks) %} +static const struct { + void *ptr; + __IEC_types_enum type; +} debug_vars_{{ chunk_idx }}[] = { +{%- for v in debug.vars[chunk_idx * 1024 : (chunk_idx + 1) * 1024] %} + {{ v }}, +{%- endfor %} +}; +{% endfor %} + +// Dispatch table +static const void *debug_chunks[] = { +{%- for chunk_idx in range(num_chunks) %} + (const void *)debug_vars_{{ chunk_idx }}, +{%- endfor %} +}; +``` + +**2. Update accessor functions to use chunked lookup:** + +```c +typedef struct { + void *ptr; + __IEC_types_enum type; +} debug_var_entry_t; + +static inline const debug_var_entry_t *get_debug_entry(size_t idx) { + if (idx >= VAR_COUNT) return NULL; + size_t chunk = idx / CHUNK_SIZE; + size_t offset = idx % CHUNK_SIZE; + const debug_var_entry_t *chunk_base = (const debug_var_entry_t *)debug_chunks[chunk]; + return &chunk_base[offset]; +} + +size_t get_var_size(size_t idx) +{ + const debug_var_entry_t *entry = get_debug_entry(idx); + if (!entry) return 0; + + switch (entry->type) { + {%- for t in debug.types -%} + // ... same switch cases as before + {%- endfor %} + default: return 0; + } +} + +void *get_var_addr(size_t idx) +{ + const debug_var_entry_t *entry = get_debug_entry(idx); + if (!entry) return NULL; + + switch (entry->type) { + // ... same switch cases as before + } +} +``` + +**3. Modify `ProjectController.py` to pass chunk metadata to the template:** + +```python +def Generate_embedded_plc_debugger(self, st_file, target='linux'): + dvars, externs, enums = self.Generate_plc_debug_cvars(target=target) + + CHUNK_SIZE = 1024 + num_chunks = (len(dvars) + CHUNK_SIZE - 1) // CHUNK_SIZE + + template = Environment(loader=self.__loader).get_template("debug.c.j2") + debug_text = template.render( + debug={ + 'externs': externs, + 'vars': dvars, + 'enums': enums, + 'types': list(set(a.split('_', 1)[0] for a in enums)), + 'md5': MD5, + 'chunk_size': CHUNK_SIZE, + 'num_chunks': num_chunks, + } + ) +``` + +**4. For AVR, place chunks in PROGMEM:** + +```c +#ifdef ARDUINO +// Store debug data in program memory (flash) instead of SRAM +#include + +{% for chunk_idx in range(num_chunks) %} +static const debug_var_entry_t debug_vars_{{ chunk_idx }}[] PROGMEM = { + // ... +}; +{% endfor %} + +// Override accessor to read from PROGMEM +static inline debug_var_entry_t read_debug_entry(size_t idx) { + debug_var_entry_t entry; + const debug_var_entry_t *chunk_base = (const debug_var_entry_t *) + pgm_read_ptr(&debug_chunks[idx / CHUNK_SIZE]); + memcpy_P(&entry, &chunk_base[idx % CHUNK_SIZE], sizeof(entry)); + return entry; +} +#endif +``` + +#### Benefits + +| Metric | Before | After | +|--------|--------|-------| +| AVR compilation | **Fails** | Succeeds (chunks < section limit) | +| Total memory usage | Same | Same (but distributed across sections) | +| AVR SRAM usage | 131 KB (impossible) | 0 KB (PROGMEM — flash only) | +| Protocol changes | — | None | +| Runtime changes | — | None | +| Editor changes | — | None | +| Implementation effort | — | **Low** (~2-3 days, xml2st template only) | + +#### Limitations + +- Doesn't reduce total memory consumption — just distributes it. +- PROGMEM access is slower (requires `pgm_read_*` on each access). +- AVR flash is still only 256 KB — the PLC program + debug data + libraries may still not fit. +- The fundamental O(n) array growth problem remains. + +--- + +### Strategy E: Dynamic Registration (Long-Term, Most Scalable) + +**Goal:** Replace the compile-time static array with runtime-dynamic variable registration, enabling the system to scale to arbitrary project sizes limited only by available memory. + +#### Implementation Details + +**1. Replace static array with a registration API:** + +New header `debug_registry.h` in the runtime: +```c +#ifndef DEBUG_REGISTRY_H +#define DEBUG_REGISTRY_H + +#include +#include +#include "iec_types_all.h" + +typedef struct { + void *ptr; + __IEC_types_enum type; +} debug_var_entry_t; + +typedef struct { + void *base_ptr; + __IEC_types_enum element_type; + uint32_t element_count; + uint16_t element_stride; // sizeof(__IEC_TYPE_t) for the wrapper type +} debug_array_entry_t; + +// Initialize the registry with expected capacity (avoids realloc churn) +int debug_registry_init(uint32_t expected_scalars, uint32_t expected_arrays); + +// Register individual variables (called from generated init function) +int debug_register_scalar(uint32_t idx, void *ptr, __IEC_types_enum type); +int debug_register_array(uint32_t idx, void *base_ptr, __IEC_types_enum type, + uint32_t count, uint16_t stride); + +// Accessors (used by debug_handler.c) +uint32_t debug_get_scalar_count(void); +uint32_t debug_get_array_count(void); + +size_t debug_get_var_size(uint32_t idx); +void *debug_get_var_addr(uint32_t idx); +void debug_force_var(uint32_t idx, bool forced, void *val); + +size_t debug_get_array_element_size(uint32_t array_idx); +void *debug_get_array_element_addr(uint32_t array_idx, uint32_t element); +uint32_t debug_get_array_element_count(uint32_t array_idx); + +// Cleanup +void debug_registry_free(void); + +#endif +``` + +**2. Implementation for Linux/desktop targets:** + +```c +// debug_registry.c +#include "debug_registry.h" +#include +#include + +static debug_var_entry_t *scalar_vars = NULL; +static uint32_t scalar_count = 0; +static uint32_t scalar_capacity = 0; + +static debug_array_entry_t *array_vars = NULL; +static uint32_t array_count = 0; +static uint32_t array_capacity = 0; + +int debug_registry_init(uint32_t expected_scalars, uint32_t expected_arrays) { + scalar_capacity = expected_scalars; + scalar_vars = (debug_var_entry_t *)calloc(expected_scalars, sizeof(debug_var_entry_t)); + if (!scalar_vars) return -1; + + array_capacity = expected_arrays; + array_vars = (debug_array_entry_t *)calloc(expected_arrays, sizeof(debug_array_entry_t)); + if (!array_vars) { + free(scalar_vars); + return -1; + } + return 0; +} + +int debug_register_scalar(uint32_t idx, void *ptr, __IEC_types_enum type) { + if (idx >= scalar_capacity) return -1; + scalar_vars[idx].ptr = ptr; + scalar_vars[idx].type = type; + if (idx >= scalar_count) scalar_count = idx + 1; + return 0; +} + +int debug_register_array(uint32_t idx, void *base_ptr, __IEC_types_enum type, + uint32_t count, uint16_t stride) { + if (idx >= array_capacity) return -1; + array_vars[idx].base_ptr = base_ptr; + array_vars[idx].element_type = type; + array_vars[idx].element_count = count; + array_vars[idx].element_stride = stride; + if (idx >= array_count) array_count = idx + 1; + return 0; +} + +uint32_t debug_get_scalar_count(void) { return scalar_count; } +uint32_t debug_get_array_count(void) { return array_count; } + +void *debug_get_var_addr(uint32_t idx) { + if (idx >= scalar_count) return NULL; + void *ptr = scalar_vars[idx].ptr; + // Same type-switch logic as current get_var_addr, but reading from heap + // ... +} + +void debug_registry_free(void) { + free(scalar_vars); scalar_vars = NULL; scalar_count = 0; + free(array_vars); array_vars = NULL; array_count = 0; +} +``` + +**3. Implementation for embedded targets (static pool, no malloc):** + +```c +// debug_registry_embedded.c — for AVR/ARM targets without heap +#include "debug_registry.h" + +// Compile-time pool sized from generated #defines +#ifndef DEBUG_MAX_SCALARS +#define DEBUG_MAX_SCALARS 2048 +#endif +#ifndef DEBUG_MAX_ARRAYS +#define DEBUG_MAX_ARRAYS 64 +#endif + +static debug_var_entry_t scalar_pool[DEBUG_MAX_SCALARS]; +static uint32_t scalar_count = 0; + +static debug_array_entry_t array_pool[DEBUG_MAX_ARRAYS]; +static uint32_t array_count = 0; + +int debug_registry_init(uint32_t expected_scalars, uint32_t expected_arrays) { + // Validate against pool sizes + if (expected_scalars > DEBUG_MAX_SCALARS || expected_arrays > DEBUG_MAX_ARRAYS) + return -1; + scalar_count = 0; + array_count = 0; + return 0; +} + +int debug_register_scalar(uint32_t idx, void *ptr, __IEC_types_enum type) { + if (idx >= DEBUG_MAX_SCALARS) return -1; + scalar_pool[idx].ptr = ptr; + scalar_pool[idx].type = type; + if (idx >= scalar_count) scalar_count = idx + 1; + return 0; +} +// ... same pattern for arrays +``` + +**4. Generated `debug.c` becomes a registration function:** + +```c +// debug.c — generated by xml2st +#include "debug_registry.h" +#include "POUS.h" + +char plc_program_md5[] = "{{ debug.md5 }}"; + +{{ debug.externs | join('\n') }} + +#define EXPECTED_SCALARS {{ debug.scalar_count }} +#define EXPECTED_ARRAYS {{ debug.array_count }} + +void debug_init(void) +{ + debug_registry_init(EXPECTED_SCALARS, EXPECTED_ARRAYS); + + // Scalar registrations +{% for v in debug.scalars %} + debug_register_scalar({{ v.idx }}, &({{ v.c_path }}), {{ v.type_enum }}); +{%- endfor %} + + // Array registrations +{% for a in debug.arrays %} + debug_register_array({{ a.idx }}, &({{ a.base_path }}), + {{ a.type_enum }}, {{ a.count }}, sizeof(__IEC_{{ a.base_type }}_t)); +{%- endfor %} +} +``` + +**5. Upgrade the debug protocol to uint32_t:** + +Update `debug_handler.c` to use 4-byte variable indexes: + +```c +// New protocol v2 — detected via MD5 handshake response +// Variable indexes are now uint32_t (4 bytes) instead of uint16_t (2 bytes) + +static void debugInfoV2(uint8_t *frame, size_t *frame_len) +{ + uint32_t scalarCount = debug_get_scalar_count(); + uint32_t arrayCount = debug_get_array_count(); + *frame_len = 9; + frame[0] = MB_FC_DEBUG_INFO; + frame[1] = 0x02; // Protocol version 2 + frame[2] = (uint8_t)(scalarCount >> 24); + frame[3] = (uint8_t)(scalarCount >> 16); + frame[4] = (uint8_t)(scalarCount >> 8); + frame[5] = (uint8_t)(scalarCount & 0xFF); + frame[6] = (uint8_t)(arrayCount >> 24); + frame[7] = (uint8_t)(arrayCount >> 16); + frame[8] = (uint8_t)(arrayCount >> 8); + frame[9] = (uint8_t)(arrayCount & 0xFF); +} +``` + +The editor can detect the protocol version from the `DEBUG_INFO` response length (3 bytes = v1, 9+ bytes = v2) and adapt its request format accordingly. + +**6. Update the editor's debug parser:** + +Instead of parsing a giant `debug_vars[]` array from the C source, generate a separate `debug_manifest.json` that the editor reads directly: + +```json +{ + "version": 2, + "md5": "fd4e363aaafc4482ee60244912f42d4b", + "scalars": [ + {"idx": 0, "path": "RES0__INSTANCE0.MOTOR_SPEED", "type": "INT"}, + {"idx": 1, "path": "RES0__INSTANCE0.MOTOR_ON", "type": "BOOL"} + ], + "arrays": [ + {"idx": 0, "path": "RES0__INSTANCE16.M_AIDATA", "type": "INT", "count": 4000}, + {"idx": 1, "path": "RES0__INSTANCE16.O_AIDATA", "type": "INT", "count": 4000} + ] +} +``` + +This eliminates the expensive regex parsing of a multi-MB C file and replaces it with a fast JSON parse. + +#### Benefits + +| Metric | Before | After | +|--------|--------|-------| +| Variable count limit | 65,535 (uint16_t) | 4,294,967,295 (uint32_t) | +| Memory allocation | Static (data segment) | Dynamic (heap) or pooled | +| AVR compilation | Fails at ~30K vars | Works up to pool limit | +| Linux/desktop scalability | Limited by section size | Limited only by RAM | +| Debug file parsing | Regex on 2.5 MB C file | JSON parse of manifest | +| Array memory efficiency | O(elements) | O(1) per array | +| Protocol compatibility | N/A | Backward-compatible with version detection | +| Implementation effort | — | **High** (~3-4 weeks, all 4 repos) | + +#### Limitations + +- Most complex to implement — touches all four repositories. +- Requires coordinated release of editor + runtime + xml2st. +- Protocol versioning adds complexity to connection negotiation. +- Embedded pool sizes still require tuning per platform. + +--- + +### Strategy F: Lazy Debug Registration (Future, Maximum Scalability) + +**Goal:** Only register variables for debugging when the editor actually requests them, making the runtime's debug footprint proportional to what the user is actively monitoring, not the total project size. + +#### Implementation Details + +This is an extension of Strategy E that adds **on-demand registration**: + +**1. Generate a string-indexed lookup table instead of pre-registered entries:** + +```c +// debug.c — generated +typedef struct { + const char *iec_path; // "RES0.INSTANCE0.MOTOR_SPEED" + void *(*resolve)(void); // Function that returns &variable + __IEC_types_enum type; + uint8_t is_array; + uint32_t array_count; // 0 for scalars +} debug_var_descriptor_t; + +// This table is const/PROGMEM — only stores metadata, not runtime state +static const debug_var_descriptor_t var_descriptors[] = { + {"RES0__INSTANCE0.MOTOR_SPEED", resolve_var_0, INT_ENUM, 0, 0}, + {"RES0__INSTANCE16.M_AIDATA", resolve_array_0, INT_ENUM, 1, 4000}, + // ... much smaller than current — one entry per logical variable +}; + +// Resolver functions (can be generated or use offsetof) +static void *resolve_var_0(void) { return &(RES0__INSTANCE0.MOTOR_SPEED); } +static void *resolve_array_0(void) { return &(RES0__INSTANCE16.M_AIDATA.value.table[0]); } +``` + +**2. Add a name-based registration protocol:** + +```c +#define MB_FC_DEBUG_SUBSCRIBE 0x47 // Subscribe to a variable by name hash +#define MB_FC_DEBUG_UNSUBSCRIBE 0x48 // Unsubscribe + +// The editor sends: [0x47] [name_hash: u32] [name_len: u16] [name: bytes] +// Runtime resolves the name, adds to active monitoring set +// Returns: [0x47] [status] [assigned_slot: u16] +``` + +The runtime maintains a small **active set** (e.g., 256-512 slots) of variables that are currently being monitored. The editor subscribes/unsubscribes as the user navigates between POUs. + +**3. Editor-side subscription management:** + +```typescript +class DebugSubscriptionManager { + private activeSubscriptions = new Map() // compositeKey → slot + private maxSlots = 256 + + async subscribe(compositeKey: string, varPath: string): Promise { + if (this.activeSubscriptions.has(compositeKey)) { + return this.activeSubscriptions.get(compositeKey)! + } + + // If at capacity, unsubscribe least recently used + if (this.activeSubscriptions.size >= this.maxSlots) { + await this.evictLRU() + } + + const slot = await window.bridge.debuggerSubscribe(varPath) + this.activeSubscriptions.set(compositeKey, slot) + return slot + } + + async onPouChanged(visibleKeys: Set): Promise { + // Unsubscribe variables no longer visible + for (const [key, slot] of this.activeSubscriptions) { + if (!visibleKeys.has(key)) { + await window.bridge.debuggerUnsubscribe(slot) + this.activeSubscriptions.delete(key) + } + } + // Subscribe newly visible variables + // ... + } +} +``` + +#### Benefits + +| Metric | Before | After | +|--------|--------|-------| +| Runtime debug memory | O(total_variables) | O(monitored_variables) | +| Monitored variable limit | 65,535 | Unlimited (swap in/out) | +| Connection setup time | Parse 32K entries | Instant (subscribe on demand) | +| Network bandwidth | Poll all subscribed each tick | Poll only active slots | +| Project size impact on debug | Linear | Constant (for a given view) | +| Implementation effort | — | **Very high** (~6-8 weeks) | + +#### Limitations + +- Most complex strategy — fundamentally changes the debug architecture. +- Subscription/unsubscription adds latency when switching between POUs. +- Name resolution at runtime requires string storage in flash/memory. +- Overkill for most projects; only needed for truly massive systems. + +--- + +## Recommended Implementation Plan + +### Phase 1 — Immediate Fix (Week 1-2) + +Combine **Strategy A** (platform-aware limits) and **Strategy D** (chunked arrays): + +1. Split the `debug_vars[]` static array into 1024-entry chunks in the Jinja template. +2. Add PROGMEM support for AVR targets. +3. Add `--target` flag to xml2st to apply platform-specific variable limits. +4. Update the editor's compiler module to pass the target platform. + +**Result:** User's project compiles on all targets. No protocol changes needed. + +### Phase 2 — Structural Improvement (Week 3-6) + +Implement **Strategy B** (array collapse) and **Strategy C** (FB filtering): + +1. Add array detection and collapse in `ProjectController.py`. +2. Add FB internal variable classification and filtering. +3. Extend the debug protocol with `0x46 DEBUG_GET_ARRAY`. +4. Update the editor's debug parser and polling logic. +5. Generate `debug_catalog.json` for the editor to show debuggability status. + +**Result:** 50-70% reduction in debug variable count. Arrays are first-class debug citizens. + +### Phase 3 — Scalable Architecture (Week 7-12) + +Implement **Strategy E** (dynamic registration): + +1. Create `debug_registry.c` with heap (Linux) and pool (embedded) backends. +2. Upgrade the debug protocol to v2 with uint32_t indexes. +3. Generate `debug_manifest.json` instead of parsing debug.c. +4. Add protocol version negotiation to the editor. + +**Result:** System scales to arbitrary project sizes. Protocol supports >65K variables. + +### Phase 4 — Future (Optional) + +Implement **Strategy F** (lazy registration) only if needed for extreme-scale projects: + +1. Add name-based subscription protocol. +2. Implement subscription manager in the editor. +3. Add LRU eviction for constrained targets. + +**Result:** O(1) runtime debug overhead regardless of project size. + +--- + +## Files Affected Across Repositories + +### xml2st +| File | Changes | +|------|---------| +| `xml2st.py` | Add `--target` argument, pass to debug generator | +| `ProjectController.py` | Array collapse, FB filtering, platform limits, catalog generation | +| `templates/debug.c.j2` | Chunked arrays, PROGMEM, registration function template | +| `templates/debug_manifest.json.j2` | New — JSON manifest for editor | + +### matiec +| File | Changes | +|------|---------| +| `stage4/generate_c/generate_c_vardecl.cc` | (Phase 3) Optional: emit array metadata in VARIABLES.csv instead of expanding elements | + +### openplc-runtime +| File | Changes | +|------|---------| +| `core/src/plc_app/debug_handler.c` | Protocol v2, array element access, uint32_t indexes | +| `core/src/plc_app/debug_handler.h` | Updated function signatures | +| `core/src/plc_app/debug_registry.c` | New — dynamic variable registration | +| `core/src/plc_app/debug_registry.h` | New — registration API | + +### openplc-editor +| File | Changes | +|------|---------| +| `src/main/modules/compiler/compiler-module.ts` | Pass target platform to xml2st | +| `src/utils/debug-parser.ts` | Support JSON manifest parsing | +| `src/renderer/utils/debugger-session.ts` | Array index handling, protocol v2 | +| `src/main/modules/modbus/modbus-client.ts` | Array element request method | +| `src/main/modules/websocket/websocket-debug-client.ts` | Array element request method | +| `src/renderer/screens/workspace-screen.tsx` | Array polling in debug loop | From 3fa5a15920062f14e04a1f6e9e14b84221d91d7e Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 12:41:02 -0400 Subject: [PATCH 012/296] docs: add STruC++ migration plan for replacing MatIEC compiler Comprehensive 8-phase migration plan covering the replacement of iec2c (MatIEC) with STruC++ for ST-to-C++ compilation, redesigning the debugger for scalability (hierarchical variable addressing instead of flat array expansion), and adapting both Arduino and Runtime v4 backends. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/strucpp-migration/00-overview.md | 144 +++++ .../01-strucpp-compiler-integration.md | 405 ++++++++++++ .../02-arduino-runtime-adaptation.md | 506 +++++++++++++++ .../03-debugger-variable-access.md | 580 ++++++++++++++++++ .../04-editor-compiler-module.md | 439 +++++++++++++ .../05-editor-frontend-debugger.md | 480 +++++++++++++++ .../06-runtime-v4-so-interface.md | 415 +++++++++++++ .../07-runtime-v4-thread-per-task.md | 420 +++++++++++++ .../08-runtime-v4-debug-handler.md | 363 +++++++++++ 9 files changed, 3752 insertions(+) create mode 100644 docs/strucpp-migration/00-overview.md create mode 100644 docs/strucpp-migration/01-strucpp-compiler-integration.md create mode 100644 docs/strucpp-migration/02-arduino-runtime-adaptation.md create mode 100644 docs/strucpp-migration/03-debugger-variable-access.md create mode 100644 docs/strucpp-migration/04-editor-compiler-module.md create mode 100644 docs/strucpp-migration/05-editor-frontend-debugger.md create mode 100644 docs/strucpp-migration/06-runtime-v4-so-interface.md create mode 100644 docs/strucpp-migration/07-runtime-v4-thread-per-task.md create mode 100644 docs/strucpp-migration/08-runtime-v4-debug-handler.md diff --git a/docs/strucpp-migration/00-overview.md b/docs/strucpp-migration/00-overview.md new file mode 100644 index 000000000..0995982c0 --- /dev/null +++ b/docs/strucpp-migration/00-overview.md @@ -0,0 +1,144 @@ +# STruC++ Migration: Overview + +## Problem Statement + +The OpenPLC Editor uses MatIEC (`iec2c`) to compile IEC 61131-3 Structured Text into C code, +and `xml2st` to generate debug infrastructure. This pipeline has two critical issues: + +1. **MatIEC is unmaintained**: The compiler is old, barely maintained, and has poor scalability. +2. **Debugger scalability**: The `debug.c` file generated by `xml2st` creates a flat `debug_vars[]` + array that expands every array element individually. A project with ~3,500 variables (many arrays) + can generate 30,000+ entries, exceeding memory limits on Arduino platforms and hitting the + `uint16_t` index ceiling (65,535). + +## Solution + +Replace `iec2c` (MatIEC) with **STruC++**, a modern IEC 61131-3 Structured Text to C++17 compiler +written in TypeScript. STruC++ is located at `~/Documents/Code/strucpp`. + +STruC++ solves both problems: +- It is actively developed with full CODESYS compatibility and OOP support +- Its `VarDescriptor` model does NOT expand arrays: one entry per array variable, not per element +- It is a TypeScript package that can be imported directly (`compile()`), no external binary needed +- Its `IECVar` wrapper provides built-in variable forcing for debugging + +## What Changes vs. What Stays + +### Unchanged + +| Component | Status | +|-----------|--------| +| `xml2st --generate-st` (XML to ST conversion) | Unchanged (separate effort on another branch) | +| XML generation from project JSON | Unchanged | +| `arduino-cli` compilation/upload | Unchanged (now compiles C++ instead of C) | +| HAL files (`resources/sources/hal/*.cpp`) | Unchanged (same buffer pointer interface) | +| Modbus slave communication | Unchanged (debug handler functions updated) | +| Frontend project data handling | Unchanged | +| POU preprocessing (Python/C++ wrappers) | Unchanged | + +### Replaced + +| Old Component | New Component | +|---------------|---------------| +| `iec2c` binary (ST to C) | STruC++ `compile()` (ST to C++17) | +| `xml2st --generate-debug` (debug.c) | New debug-map.json from STruC++ metadata | +| `xml2st --generate-gluevars` (glueVars.c) | New `generated_glue.hpp` from LocatedVar descriptors | +| MatIEC lib/ headers | STruC++ runtime headers (header-only C++17) | +| `Baremetal.ino` (C integration) | `StrucppBaremetal.ino` (C++ integration) | +| Flat debug_vars[] array | Hierarchical (program_idx, var_idx) addressing | +| Single `config_run__(tick)` | Per-program `run()` with GCD task scheduler | + +## Revised Pipeline + +``` + UNCHANGED REPLACED + +----------+ +------------------+ +project.json ----> | xml2st | ----> program.st | STruC++ compile()| ----> generated.cpp +(via XML gen) |--generate| | | generated.hpp + | -st | | + glue/debug gen | generated_glue.hpp + +----------+ +------------------+ debug-map.json + | + v + arduino-cli / g++ + (now compiles C++17) +``` + +## Phase Structure + +The migration is organized into 8 phases across two parts: + +### Part A: Arduino Target (Primary Focus) + +| Phase | Title | Description | +|-------|-------|-------------| +| 1 | [STruC++ Compiler Integration](01-strucpp-compiler-integration.md) | Add STruC++ as dependency, create compile wrapper | +| 2 | [Arduino Runtime Adaptation](02-arduino-runtime-adaptation.md) | New sketch, glue code, runtime headers | +| 3 | [Debugger Variable Access](03-debugger-variable-access.md) | Hierarchical debug system, protocol update | +| 4 | [Editor Compiler Module](04-editor-compiler-module.md) | Wire new pipeline into compiler-module.ts | +| 5 | [Editor Frontend Debugger](05-editor-frontend-debugger.md) | Update UI for debug-map.json and hierarchical refs | + +### Part B: OpenPLC Runtime v4 (Secondary) + +| Phase | Title | Description | +|-------|-------|-------------| +| 6 | [Runtime .so Interface](06-runtime-v4-so-interface.md) | C-linkage compatibility shims for existing runtime | +| 7 | [Thread-Per-Task Model](07-runtime-v4-thread-per-task.md) | Per-task pthreads instead of round-robin | +| 8 | [Runtime Debug Handler](08-runtime-v4-debug-handler.md) | Native hierarchical debug in runtime | + +## Dependency Graph + +``` +Phase 1 (STruC++ compiler wrapper) + | + +---> Phase 2 (Arduino glue generation + new sketch) + | | + | +---> Phase 3 (Debug arrays + protocol) + | | + | +---> Phase 4 (Compiler module wiring) + | | + | +---> Phase 5 (Frontend debugger) + | + +---> Phase 6 (v4_compat.cpp) + | + +---> Phase 7 (Thread-per-task) + | + +---> Phase 8 (Runtime debug handler) +``` + +The Arduino path (Phases 1-5) and Runtime v4 path (Phases 6-8) share only Phase 1. +After Phase 1 is complete, both paths can proceed independently. + +## Key Architectural Decisions + +### 1. Dual Pipeline Coexistence + +Both MatIEC and STruC++ pipelines coexist in the compiler module. A `"compiler_backend"` field +in `hals.json` per board determines which pipeline is used. This allows gradual migration -- +boards can be switched one at a time. + +### 2. IECVar and Forced Input Handling + +STruC++ wraps all variables in `IECVar` which has built-in forcing: +- `get()`: returns forced_value_ when forced, value_ otherwise +- `set(v)`: ignored when forced (prevents program from overwriting forced value) +- `force(v)`: sets both forced_value_ and value_ (so raw_ptr() readers see it too) +- `raw_ptr()`: returns &value_ for I/O driver binding + +For **input** variables, the HAL writes hardware values directly via `raw_ptr()`, overwriting +`value_`. Since `get()` returns `forced_value_` when forced, PLC logic is correct. But the debug +system needs a `strucpp_restore_forced_inputs()` call after HAL reads to ensure `value_` reflects +the forced state for any readers using `raw_ptr()`. + +### 3. No Array Expansion in Debug + +The fundamental scalability fix: arrays get ONE entry in the variable descriptor table, not one +per element. The debugger accesses individual array elements on-demand via offset calculations, +and the frontend lazily loads array elements when the user expands them in the variable tree. + +### 4. C++17 Requirement + +All Arduino boards need `-std=gnu++17` added to CXX compilation flags. This is supported by: +- Arduino AVR: GCC 7.3+ (bundled with Arduino IDE 2.x) +- ESP32: GCC 8+ (ESP-IDF toolchain) +- STM32: ARM GCC 10+ (STM32duino) +- RP2040: ARM GCC 10+ (Arduino Mbed OS) diff --git a/docs/strucpp-migration/01-strucpp-compiler-integration.md b/docs/strucpp-migration/01-strucpp-compiler-integration.md new file mode 100644 index 000000000..641f9c6f2 --- /dev/null +++ b/docs/strucpp-migration/01-strucpp-compiler-integration.md @@ -0,0 +1,405 @@ +# Phase 1: STruC++ Compiler Integration + +## Goal + +Replace the `iec2c` (MatIEC) binary with STruC++ `compile()` for ST-to-C++ compilation. The input +is `program.st` (already generated by xml2st, unchanged). The output is C++17 code +(`generated.cpp` + `generated.hpp`) plus metadata for downstream glue/debug generation. + +## Prerequisites + +- STruC++ repository at `~/Documents/Code/strucpp` +- STruC++ exposes a programmatic API: `compile(source: string, options?): CompileResult` +- No external binary needed -- runs as TypeScript in the same Node.js process + +## Step 1.1: Add STruC++ as npm Dependency + +**File to modify**: `package.json` + +```json +{ + "dependencies": { + "strucpp": "file:../strucpp" + } +} +``` + +Or if published to npm: `"strucpp": "^1.0.0"`. + +Since STruC++ is TypeScript and has only one runtime dependency (`chevrotain` parser framework), +it bundles cleanly into the Electron app. No native modules, no platform-specific code. + +## Step 1.2: Create STruC++ Compiler Wrapper + +**New file**: `src/backend/shared/utils/PLC/strucpp-compiler.ts` + +This module wraps the STruC++ `compile()` function and extracts the metadata needed for +downstream phases (glue code generation, debug map generation, task scheduling). + +### Public API + +```typescript +import { compile, type CompileResult, type CompileOptions } from 'strucpp' + +// ----- Input types ----- + +export interface STruCppCompileOptions { + /** Name for the generated header file (default: "generated.hpp") */ + headerFileName?: string + /** Enable debug info in output (default: true) */ + debug?: boolean + /** Enable ST-to-C++ line mapping (default: true) */ + lineMapping?: boolean + /** Paths to .stlib library archives to load */ + libraryPaths?: string[] +} + +// ----- Output types ----- + +export interface STruCppResult { + success: boolean + /** C++ implementation file content */ + cppCode: string + /** C++ header file content */ + headerCode: string + /** Compilation errors */ + errors: STruCppDiagnostic[] + /** Compilation warnings */ + warnings: STruCppDiagnostic[] + /** Task scheduling metadata (extracted from CONFIGURATION/RESOURCE/TASK) */ + taskIntervals: TaskInterval[] + /** Variable descriptors per program instance (for debug/glue generation) */ + variableDescriptors: ProgramVarDescriptor[] + /** Number of located variables in the generated code */ + locatedVarCount: number + /** The raw CompileResult from STruC++ (for advanced use) */ + rawResult: CompileResult +} + +export interface STruCppDiagnostic { + message: string + line: number + column: number + severity: 'error' | 'warning' +} + +export interface TaskInterval { + /** Instance name as declared in PROGRAM ... WITH task : Type */ + instanceName: string + /** The program POU type name */ + programType: string + /** Task interval in nanoseconds (e.g., 20000000 for T#20ms) */ + intervalNs: number + /** Task priority (from TASK declaration) */ + priority: number +} + +export interface ProgramVarDescriptor { + /** Program instance name (e.g., "instance0") */ + programInstanceName: string + /** Program POU type name (e.g., "Main") */ + programTypeName: string + /** Variables declared in this program */ + variables: VarEntry[] +} + +export interface VarEntry { + /** Variable name */ + name: string + /** IEC type tag: "BOOL", "INT", "DINT", "REAL", "LREAL", "TIME", "STRING", etc. */ + typeTag: string + /** Whether this variable is an array */ + isArray: boolean + /** Array dimensions (e.g., [100] for ARRAY[0..99], [3,4] for 2D array) */ + arrayDimensions?: number[] + /** Whether this variable is a struct/FB instance */ + isStruct?: boolean + /** For struct/FB: child fields */ + structFields?: VarEntry[] + /** C++ type name for code generation (e.g., "int16_t", "bool", "float") */ + cppTypeName: string + /** Byte size of a single element */ + size: number +} +``` + +### Implementation + +```typescript +export function compileWithSTruCpp( + stSource: string, + options?: Partial, +): STruCppResult { + const compileOpts: Partial = { + headerFileName: options?.headerFileName ?? 'generated.hpp', + debug: options?.debug ?? true, + lineMapping: options?.lineMapping ?? true, + libraryPaths: options?.libraryPaths, + } + + const result = compile(stSource, compileOpts) + + if (!result.success) { + return { + success: false, + cppCode: '', + headerCode: '', + errors: result.errors.map(mapDiagnostic), + warnings: result.warnings.map(mapDiagnostic), + taskIntervals: [], + variableDescriptors: [], + locatedVarCount: 0, + rawResult: result, + } + } + + // Extract task intervals from the project model + const taskIntervals = extractTaskIntervals(result.projectModel) + + // Extract variable descriptors from AST + symbol tables + const variableDescriptors = extractVariableDescriptors(result.ast, result.symbolTables, result.projectModel) + + // Count located variables + const locatedVarCount = countLocatedVars(result.ast, result.projectModel) + + return { + success: true, + cppCode: result.cppCode, + headerCode: result.headerCode, + errors: [], + warnings: result.warnings.map(mapDiagnostic), + taskIntervals, + variableDescriptors, + locatedVarCount, + rawResult: result, + } +} +``` + +### Metadata Extraction Functions + +#### `extractTaskIntervals(projectModel)` + +Walks `projectModel.configurations[].resources[].tasks[]` to extract: +- Task name and interval (nanoseconds) +- Program instances associated with each task +- Task priority + +```typescript +function extractTaskIntervals(projectModel: ProjectModel | undefined): TaskInterval[] { + if (!projectModel?.configurations?.length) { + // No CONFIGURATION: single default task at 20ms + return projectModel?.programs + ? Array.from(projectModel.programs.keys()).map(name => ({ + instanceName: name, + programType: name, + intervalNs: 20_000_000, // 20ms default + priority: 0, + })) + : [] + } + + const intervals: TaskInterval[] = [] + for (const config of projectModel.configurations) { + for (const resource of config.resources) { + for (const task of resource.tasks) { + for (const inst of task.programInstances) { + intervals.push({ + instanceName: inst.instanceName, + programType: inst.programType, + intervalNs: task.interval?.nanoseconds ?? 20_000_000, + priority: task.priority ?? 0, + }) + } + } + } + } + return intervals +} +``` + +#### `extractVariableDescriptors(ast, symbolTables, projectModel)` + +For each program instance, collects all VAR, VAR_INPUT, VAR_OUTPUT declarations: +- Resolves types to determine typeTag, size, array dimensions +- Identifies struct/FB instances and recursively collects their fields +- Does NOT expand arrays -- an `ARRAY[0..99] OF INT` becomes one VarEntry with + `isArray: true, arrayDimensions: [100]` + +This is the key function for scalability. The STruC++ `symbolTables` provide complete +type resolution information needed to build VarEntry objects. + +## Step 1.3: Utility -- GCD Computation + +**Add to**: `src/backend/shared/utils/PLC/strucpp-compiler.ts` + +The GCD of all task intervals determines the base scan cycle time for Arduino round-robin: + +```typescript +export function computeTaskGCD(intervals: TaskInterval[]): number { + if (intervals.length === 0) return 20_000_000 // 20ms default + let g = intervals[0].intervalNs + for (let i = 1; i < intervals.length; i++) { + g = gcd(g, intervals[i].intervalNs) + } + return g +} + +function gcd(a: number, b: number): number { + while (b !== 0) { + const t = b + b = a % b + a = t + } + return a +} +``` + +## Design Notes + +### Why a Wrapper Instead of Calling compile() Directly + +1. **Metadata extraction**: The raw `CompileResult` contains AST and symbol tables that need + traversal to produce the structured metadata needed for glue/debug generation. This logic + is non-trivial and should be encapsulated. + +2. **Stable interface**: If STruC++ API changes, only this wrapper needs updating. + +3. **100% shared**: This module has zero platform dependencies. It takes a string (ST source) + and returns a structured result. Both Electron and web editors use it identically. + +### What STruC++ compile() Actually Produces + +Given a `program.st` file like: +```iec +PROGRAM Main + VAR + counter : INT; + motor_speed AT %QW0 : INT; + sensor AT %IX0.0 : BOOL; + END_VAR + counter := counter + 1; + motor_speed := counter * 10; +END_PROGRAM + +CONFIGURATION Config0 + RESOURCE Res0 ON PLC + TASK task0(INTERVAL := T#20ms, PRIORITY := 0); + PROGRAM instance0 WITH task0 : Main; + END_RESOURCE +END_CONFIGURATION +``` + +STruC++ generates: + +**generated.hpp** (header): +```cpp +#pragma once +#include "iec_types.hpp" +namespace strucpp { + +class Program_Main : public ProgramBase { +public: + IEC_INT counter; + IEC_INT motor_speed; // AT %QW0 + IEC_BOOL sensor; // AT %IX0.0 + Program_Main(); + void run() override; +}; + +extern LocatedVar locatedVars[]; +extern constexpr uint32_t locatedVarsCount; + +class Configuration_Config0 { +public: + Program_Main instance0; + Configuration_Config0(); +}; + +} // namespace strucpp +``` + +**generated.cpp** (implementation): +```cpp +#include "generated.hpp" +namespace strucpp { + +LocatedVar locatedVars[2] = { + { LocatedArea::Output, LocatedSize::Word, 0, 0, {0,0,0}, nullptr }, + { LocatedArea::Input, LocatedSize::Bit, 0, 0, {0,0,0}, nullptr }, +}; +constexpr uint32_t locatedVarsCount = 2; + +Program_Main::Program_Main() : counter(0), motor_speed(0), sensor(false) { + locatedVars[0].pointer = motor_speed.raw_ptr(); + locatedVars[1].pointer = sensor.raw_ptr(); +} + +void Program_Main::run() { + counter = counter + 1; + motor_speed = counter * 10; +} + +Configuration_Config0::Configuration_Config0() {} + +} // namespace strucpp +``` + +### STruC++ Type Mapping Reference + +| IEC Type | C++ Type | `IECVar` Alias | Size | +|----------|----------|---------------|------| +| BOOL | `bool` | `IEC_BOOL` | 1 | +| SINT | `int8_t` | `IEC_SINT` | 1 | +| INT | `int16_t` | `IEC_INT` | 2 | +| DINT | `int32_t` | `IEC_DINT` | 4 | +| LINT | `int64_t` | `IEC_LINT` | 8 | +| USINT | `uint8_t` | `IEC_USINT` | 1 | +| UINT | `uint16_t` | `IEC_UINT` | 2 | +| UDINT | `uint32_t` | `IEC_UDINT` | 4 | +| ULINT | `uint64_t` | `IEC_ULINT` | 8 | +| BYTE | `uint8_t` | `IEC_BYTE` | 1 | +| WORD | `uint16_t` | `IEC_WORD` | 2 | +| DWORD | `uint32_t` | `IEC_DWORD` | 4 | +| LWORD | `uint64_t` | `IEC_LWORD` | 8 | +| REAL | `float` | `IEC_REAL` | 4 | +| LREAL | `double` | `IEC_LREAL` | 8 | +| TIME | `int64_t` | `IEC_TIME` | 8 | +| STRING(N) | `IECString` | `IEC_STRING` | N+1 | + +All types wrapped in `IECVar` which adds: `bool forced_` (1 byte) + `T forced_value_` +(same size as value). Total overhead per variable: `sizeof(T) + 1 + sizeof(T)`. + +## Testing Strategy + +1. **Unit test** `compileWithSTruCpp()` with a simple ST program: + - Verify `success === true` + - Verify `cppCode` and `headerCode` are non-empty + - Verify `taskIntervals` contains correct entries + - Verify `variableDescriptors` matches declared variables + +2. **Unit test** `extractTaskIntervals()`: + - Single task: `[{intervalNs: 20000000}]` + - Multiple tasks: `[{intervalNs: 20000000}, {intervalNs: 50000000}]` + - No CONFIGURATION (standalone programs): default 20ms + +3. **Unit test** `extractVariableDescriptors()`: + - Scalar variable: `{name: "counter", typeTag: "INT", isArray: false, size: 2}` + - Array: `{name: "speeds", typeTag: "INT", isArray: true, arrayDimensions: [100], size: 2}` + - Struct/FB instance: `{name: "fb1", isStruct: true, structFields: [...]}` + +4. **Unit test** `computeTaskGCD()`: + - GCD(20ms, 40ms) = 20ms + - GCD(20ms, 50ms) = 10ms + - GCD(20ms, 20ms) = 20ms + - Single task: interval itself + +5. **Integration test**: feed an actual `program.st` (from the sample project) and verify + compilation succeeds without errors. + +## Files Created/Modified + +| File | Action | +|------|--------| +| `package.json` | Add strucpp dependency | +| `src/backend/shared/utils/PLC/strucpp-compiler.ts` | **New** -- STruC++ wrapper | diff --git a/docs/strucpp-migration/02-arduino-runtime-adaptation.md b/docs/strucpp-migration/02-arduino-runtime-adaptation.md new file mode 100644 index 000000000..1463b5ff7 --- /dev/null +++ b/docs/strucpp-migration/02-arduino-runtime-adaptation.md @@ -0,0 +1,506 @@ +# Phase 2: Arduino Runtime C++ Adaptation + +## Goal + +Create the Arduino-side C++ runtime files that bridge STruC++ generated code with the existing +HAL (Hardware Abstraction Layer) and Modbus infrastructure. The HAL files and Modbus slave +implementation remain unchanged -- only the glue layer between them and the PLC program changes. + +## Prerequisites + +- Phase 1 complete (STruC++ compiler wrapper producing C++ code and metadata) +- STruC++ runtime headers available for bundling + +## Step 2.1: Bundle STruC++ Runtime Headers + +**New directory**: `resources/sources/StrucppRuntime/` + +Copy these header-only C++17 files from `strucpp/src/runtime/include/`: + +``` +iec_var.hpp -- IECVar template (forcing, raw_ptr) +iec_types.hpp -- IEC type aliases (IEC_INT, IEC_BOOL, etc.) +iec_located.hpp -- LocatedVar struct, LocatedArea/LocatedSize enums +iec_traits.hpp -- Type trait helpers +iec_array.hpp -- Array1D, Array2D, Array3D templates +iec_string.hpp -- IECString (stack-allocated, fixed-size) +iec_enum.hpp -- Enum type support +iec_struct.hpp -- Struct base helpers +iec_std_lib.hpp -- IEC standard functions (ABS, MIN, MAX, etc.) +iec_time.hpp -- TIME type operations +iec_date.hpp -- DATE type operations +iec_tod.hpp -- TIME_OF_DAY operations +iec_dt.hpp -- DATE_AND_TIME operations +iec_char.hpp -- CHAR/WCHAR types +iec_wstring.hpp -- WSTRING type +iec_memory.hpp -- Memory operation helpers +iec_retain.hpp -- Retain variable support +iec_pointer.hpp -- POINTER TO support +iec_ptr.hpp -- REF_TO support +iec_subrange.hpp -- Subrange type support +``` + +These are all **header-only** with no platform-specific code. They compile on any C++17 +toolchain including Arduino AVR GCC 7.3+. + +**Maintenance**: When STruC++ updates its runtime headers, this directory must be synced. +Consider a build script or git submodule for automation. + +## Step 2.2: Create New Arduino Sketch + +**New file**: `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` + +This sketch mirrors the structure of the existing `Baremetal.ino` (351 lines) but is adapted +for STruC++ generated C++ code. The key differences are: + +1. Includes `generated.hpp` and `generated_glue.hpp` instead of MatIEC C headers +2. Calls STruC++ init/run functions instead of `config_init__()` / `config_run__(tick)` +3. Adds `strucpp_restore_forced_inputs()` after HAL input reads +4. Uses GCD-based multi-task scheduler + +### Complete Sketch Structure + +```cpp +// StrucppBaremetal.ino + +// --- STruC++ generated files (per-project) --- +#include "generated.hpp" // Program classes, Configuration, LocatedVar[] +#include "generated_glue.hpp" // I/O binding, scheduler, debug arrays, MD5 + +// --- OpenPLC static files (unchanged from current runtime) --- +#include "openplc.h" // I/O buffer declarations +#include "debug.h" // Debug function declarations (updated for v2) +#include "ModbusSlave.h" // Modbus communication + +// --- Timing --- +extern unsigned long long common_ticktime__; // Defined in generated_glue.hpp +static unsigned long scan_cycle; +static unsigned long last_run; +static uint32_t __tick = 0; +static bool first_cycle = true; + +// ============================================================================= +// SETUP +// ============================================================================= +void setup() { + // 1. Initialize STruC++ Configuration (creates program instances) + strucpp_config_init(); + + // 2. Bind located variables to I/O buffer pointers + strucpp_bind_located_vars(); + + // 3. Initialize hardware (HAL -- unchanged) + hardwareInit(); + + // 4. Configure Modbus (unchanged from current Baremetal.ino) + #ifdef MODBUS_ENABLED + #if defined(MBSERIAL_IFACE) + mbconfig_serial_iface(); + #elif defined(MBTCP_IFACE) + mbconfig_ethernet_iface(); + #endif + init_mbregs(); + mapEmptyBuffers(); + #endif + + // 5. Set scan cycle from GCD of task intervals + setupCycleDelay(common_ticktime__); +} + +// ============================================================================= +// MAP EMPTY BUFFERS (for Modbus -- identical to current Baremetal.ino) +// ============================================================================= +void mapEmptyBuffers() { + // Exact same implementation as current Baremetal.ino lines 135-191 + // Maps unmapped I/O to Modbus registers + // No changes needed -- uses same openplc.h buffer pointers +} + +// ============================================================================= +// MODBUS TASK (identical to current Baremetal.ino) +// ============================================================================= +void modbusTask() { + // Exact same implementation as current Baremetal.ino lines 193-289 + // Syncs OpenPLC buffers <-> Modbus registers + // No changes needed +} + +// ============================================================================= +// PLC CYCLE TASK +// ============================================================================= +void plcCycleTask() { + // 1. Read hardware inputs into buffers (HAL -- unchanged) + updateInputBuffers(); + + // 2. Restore forced values for input variables + // (HAL writes directly to raw_ptr(), overwriting forced values) + strucpp_restore_forced_inputs(); + + // 3. Execute PLC logic via GCD-based multi-task scheduler + strucpp_config_run(__tick++); + + // 4. Write buffers to hardware outputs (HAL -- unchanged) + updateOutputBuffers(); + + // 5. Update time (same logic as current) + updateTime(); +} + +// ============================================================================= +// SCHEDULER (same structure as current, calls new task function) +// ============================================================================= +void scheduler() { + plcCycleTask(); + + #ifdef USE_ARDUINO_SKETCH + sketch_loop(); + #endif + + #ifdef MODBUS_ENABLED + modbusTask(); + #endif + + if (first_cycle) { + first_cycle = false; + scan_cycle = (unsigned long)(common_ticktime__ / 1000); + last_run = micros(); + } +} + +// ============================================================================= +// MAIN LOOP (identical timing logic to current Baremetal.ino) +// ============================================================================= +void loop() { + unsigned long now = micros(); + if ((now - last_run) >= scan_cycle) { + last_run = now; + scheduler(); + } + + #ifdef MODBUS_ENABLED + // Run extra Modbus cycles between PLC scans if time permits + if ((micros() - last_run) < (scan_cycle - 10000)) { + modbusTask(); + } + #endif + + #ifdef SIMULATOR_MODE + asm("sleep"); + #endif +} +``` + +### Key Differences from Current Baremetal.ino + +| Aspect | Current (Baremetal.ino) | New (StrucppBaremetal.ino) | +|--------|------------------------|--------------------------| +| Includes | `extern "C" { #include "openplc.h" }` | `#include "generated.hpp"` + `"generated_glue.hpp"` | +| Init | `config_init__()` + `glueVars()` | `strucpp_config_init()` + `strucpp_bind_located_vars()` | +| PLC run | `config_run__(__tick++)` | `strucpp_config_run(__tick++)` | +| Forced vars | Not handled at HAL level | `strucpp_restore_forced_inputs()` after `updateInputBuffers()` | +| Time | `updateTime()` from glueVars.c | `updateTime()` from generated_glue.hpp | +| Modbus | Unchanged | Unchanged | +| HAL | Unchanged | Unchanged | + +## Step 2.3: Arduino Glue Code Generator + +**New file**: `src/backend/shared/utils/PLC/generate-arduino-glue.ts` + +This TypeScript module generates `generated_glue.hpp` -- a per-project C++ header that contains +all the "glue" between STruC++ generated code and the Arduino runtime. + +### Public API + +```typescript +export interface ArduinoGlueInput { + /** Configuration class name from STruC++ output (e.g., "Config0") */ + configurationName: string + /** Task scheduling metadata from STruCppResult */ + taskIntervals: TaskInterval[] + /** Variable descriptors per program from STruCppResult */ + variableDescriptors: ProgramVarDescriptor[] + /** MD5 hash of the program.st source */ + md5Hash: string + /** Board memory class (determines buffer sizes) */ + boardMemoryClass: 'avr-small' | 'avr-large' | 'arm' | 'esp32' +} + +/** + * Generates the content of generated_glue.hpp. + * This is a pure function -- no file I/O, fully shared between Electron and web. + */ +export function generateArduinoGlue(input: ArduinoGlueInput): string +``` + +### Generated File Structure + +The output `generated_glue.hpp` contains these sections: + +#### Section 1: Configuration Singleton + +```cpp +#pragma once +#include "generated.hpp" +#include "openplc.h" + +using namespace strucpp; + +// --- Global Configuration instance --- +static Configuration_Config0 g_config; + +void strucpp_config_init() { + // Configuration constructor initializes all program instances + // Located variable pointers are set in program constructors +} +``` + +#### Section 2: I/O Buffer Binding + +```cpp +// --- Bind LocatedVar descriptors to OpenPLC I/O buffers --- +void strucpp_bind_located_vars() { + for (uint32_t i = 0; i < locatedVarsCount; ++i) { + LocatedVar& lv = locatedVars[i]; + if (!lv.pointer) continue; + + switch (lv.area) { + case LocatedArea::Input: + switch (lv.size) { + case LocatedSize::Bit: + bool_input[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; + break; + case LocatedSize::Byte: + // byte_input is only available on non-Arduino targets + // For Arduino, bytes are typically accessed via word-sized buffers + break; + case LocatedSize::Word: + int_input[lv.byte_index] = (IEC_UINT*)lv.pointer; + break; + case LocatedSize::DWord: + dint_input[lv.byte_index] = (IEC_UDINT*)lv.pointer; + break; + case LocatedSize::LWord: + lint_input[lv.byte_index] = (IEC_ULINT*)lv.pointer; + break; + } + break; + + case LocatedArea::Output: + switch (lv.size) { + case LocatedSize::Bit: + bool_output[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; + break; + case LocatedSize::Word: + int_output[lv.byte_index] = (IEC_UINT*)lv.pointer; + break; + case LocatedSize::DWord: + dint_output[lv.byte_index] = (IEC_UDINT*)lv.pointer; + break; + case LocatedSize::LWord: + lint_output[lv.byte_index] = (IEC_ULINT*)lv.pointer; + break; + } + break; + + case LocatedArea::Memory: + switch (lv.size) { + case LocatedSize::Word: + int_memory[lv.byte_index] = (IEC_UINT*)lv.pointer; + break; + case LocatedSize::DWord: + dint_memory[lv.byte_index] = (IEC_UDINT*)lv.pointer; + break; + case LocatedSize::LWord: + lint_memory[lv.byte_index] = (IEC_ULINT*)lv.pointer; + break; + } + break; + } + } +} +``` + +This function replaces the old `glueVars()` generated by xml2st. Instead of hardcoded +pointer assignments, it iterates the LocatedVar descriptor array that STruC++ generates. + +**How it works**: STruC++ generates a `locatedVars[]` array where each entry describes a +located variable's area (I/Q/M), size (X/B/W/D/L), byte index, and bit index. The program +constructor sets `locatedVars[i].pointer = variable.raw_ptr()`. This function then connects +those pointers to the OpenPLC buffer arrays. + +#### Section 3: GCD-Based Task Scheduler + +```cpp +// --- Multi-task round-robin scheduler --- +// Base tick = GCD of all task intervals +// Each task runs when: tick % divisor == 0 + +unsigned long long common_ticktime__ = 20000000ULL; // GCD in nanoseconds + +static ProgramBase* task_programs[] = { + &g_config.instance0, + &g_config.instance1, + // ... one per program instance +}; + +static const uint32_t task_divisors[] = { + 1, // instance0: 20ms / 20ms = every tick + 2, // instance1: 40ms / 20ms = every 2nd tick + // ... +}; + +static const size_t TASK_COUNT = 2; // number of tasks + +void strucpp_config_run(unsigned long tick) { + for (size_t i = 0; i < TASK_COUNT; ++i) { + if (task_divisors[i] == 0 || (tick % task_divisors[i]) == 0) { + task_programs[i]->run(); + } + } +} +``` + +**GCD computation example**: For tasks at T#20ms and T#50ms, GCD = 10ms. +Divisors: [2, 5]. Task0 runs at ticks 0,2,4,6,... Task1 at 0,5,10,... + +For a single-task project, this simplifies to calling `run()` every tick. + +#### Section 4: Forced Input Restoration + +```cpp +// --- Restore forced input values after HAL reads --- +// HAL writes directly to IECVar::value_ via raw_ptr(), overwriting forced values. +// This function restores value_ from forced_value_ for forced input variables. + +void strucpp_restore_forced_inputs() { + // Generated per-project for each located INPUT variable: + if (g_config.instance0.sensor.is_forced()) + *(bool*)locatedVars[1].pointer = g_config.instance0.sensor.get_forced_value(); + // ... repeat for each located input variable +} +``` + +**Why this is needed**: When a variable is forced (for debugging), `IECVar::force(v)` sets +both `forced_value_` and `value_` to `v`. The PLC program reads via `get()` which returns +`forced_value_`. But the HAL's `updateInputBuffers()` writes hardware readings directly to +`value_` via `raw_ptr()`. After HAL reads, `value_` contains the hardware reading (not the +forced value). Since `get()` returns `forced_value_`, PLC logic is correct. But any code +reading via `raw_ptr()` (including the debug system's value display) would see the hardware +value. This function ensures `value_` matches the forced state after HAL reads. + +For OUTPUT variables, this is not needed: `force()` sets `value_`, and `set()` is a no-op +when forced, so `value_` stays at the forced value through PLC cycles. The HAL reads from +`raw_ptr()` and writes the forced value to hardware. + +#### Section 5: Time Update and MD5 + +```cpp +// --- Time management --- +extern IEC_TIME __CURRENT_TIME; + +void updateTime() { + __CURRENT_TIME = __CURRENT_TIME + (int64_t)common_ticktime__; +} + +// --- Program MD5 hash --- +const char plc_program_md5[] = "a1b2c3d4e5f6..."; +``` + +#### Section 6: Debug Arrays (detailed in Phase 3) + +The debug pointer arrays are also generated in this file. See Phase 3 for details. + +## Step 2.4: C++17 Compilation Flag + +**File to modify**: `resources/sources/boards/hals.json` + +For every board entry, ensure CXX flags include `-std=gnu++17`: + +```json +{ + "Arduino Uno": { + "compiler": "arduino-cli", + "core": "arduino:avr", + "platform": "arduino:avr:uno", + "source": "uno_leonardo_nano_micro_zero.cpp", + "cxx_flags": ["-std=gnu++17", "-MMD", "-c"], + "compiler_backend": "strucpp", + ... + } +} +``` + +The `"compiler_backend": "strucpp"` field (default: `"matiec"` if absent) controls which +compilation pipeline the editor uses for this board. + +**C++17 support by platform**: + +| Platform | GCC Version | C++17 Support | +|----------|-------------|---------------| +| Arduino AVR | 7.3+ | Yes (bundled with Arduino IDE 2.x) | +| ESP32 | 8.4+ (ESP-IDF) | Yes | +| STM32 | 10+ (STM32duino) | Yes | +| RP2040 | 10+ (Arduino Mbed) | Yes | +| SAMD | 7.2+ | Yes | + +## Design Notes + +### Why Keep openplc.h Buffer Arrays + +The HAL files (`uno_leonardo_nano_micro_zero.cpp`, `esp32.cpp`, `mega_due.cpp`, etc.) use +`openplc.h` buffer pointer arrays: `bool_input[byte][bit]`, `int_input[index]`, etc. + +Rewriting all HAL files for STruC++ types would be a massive effort with no benefit. Instead, +the glue layer populates these same buffer pointers from STruC++ LocatedVar descriptors. +The HAL files see no difference. + +### Memory Layout: IECVar vs MatIEC __IEC_type_p + +| MatIEC | STruC++ | +|--------|---------| +| `__IEC_INT_p { int16_t value; int16_t fvalue; uint8_t flags; }` = 5 bytes | `IECVar { int16_t value_; bool forced_; int16_t forced_value_; }` = 5 bytes | +| `__IEC_BOOL_p { uint8_t value; uint8_t fvalue; uint8_t flags; }` = 3 bytes | `IECVar { bool value_; bool forced_; bool forced_value_; }` = 3 bytes | + +Memory overhead is essentially the same. + +### Board Memory Classes + +The buffer sizes in `openplc.h` vary by chip: + +| Class | Boards | Digital I/O | Analog I/O | Memory | +|-------|--------|-------------|------------|--------| +| avr-small | ATmega328P, ATmega168, ATmega32U4 | 8 DIN, 32 DOUT | 6 AIN, 32 AOUT | 0 | +| avr-large | ATmega2560, all others | 56 DIN/DOUT | 32 AIN/AOUT | 20 W/DW/LW | + +The glue generator uses this to validate located variable addresses don't exceed buffer limits. + +## Testing Strategy + +1. **Minimal project test**: Single program, one digital output (%QX0.0) + - Generate glue code + - Verify `bool_output[0][0]` is bound to the variable's `raw_ptr()` + - Compile with arduino-cli for Simulator target + +2. **Multi-task test**: Two tasks at T#20ms and T#40ms + - Verify `common_ticktime__ = 20000000` + - Verify `task_divisors = {1, 2}` + - Verify `TASK_COUNT = 2` + +3. **Forced input test**: Located input variable (%IX0.0) + - Force the variable, call `updateInputBuffers()` (simulated HAL write) + - Call `strucpp_restore_forced_inputs()` + - Verify `raw_ptr()` returns the forced value + +4. **HAL compatibility test**: Compile with each HAL file + - Verify no compilation errors + - Verify HAL functions (`hardwareInit`, `updateInputBuffers`, `updateOutputBuffers`) + are resolved correctly + +## Files Created/Modified + +| File | Action | +|------|--------| +| `resources/sources/StrucppRuntime/*.hpp` | **New** -- STruC++ runtime headers | +| `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` | **New** -- Arduino sketch | +| `src/backend/shared/utils/PLC/generate-arduino-glue.ts` | **New** -- Glue code generator | +| `resources/sources/boards/hals.json` | Modified -- add cxx_flags, compiler_backend | diff --git a/docs/strucpp-migration/03-debugger-variable-access.md b/docs/strucpp-migration/03-debugger-variable-access.md new file mode 100644 index 000000000..79383c4c6 --- /dev/null +++ b/docs/strucpp-migration/03-debugger-variable-access.md @@ -0,0 +1,580 @@ +# Phase 3: Debugger Variable Access System + +## Goal + +Replace the flat `debug_vars[]` array (which expands arrays element-by-element) with a +hierarchical `(program_idx, var_idx)` addressing scheme. This is the core fix for the +debugger scalability problem. + +## Prerequisites + +- Phase 1 (STruC++ compiler wrapper providing variable descriptors) +- Phase 2 (generated_glue.hpp structure for debug arrays) + +## The Scalability Problem + +### Current System (MatIEC + debug.c) + +The `debug.c` file generated by xml2st creates a flat array: + +```c +static const struct { void *ptr; __IEC_types_enum type; } debug_vars[] = { + {&(CONFIG0__INSTANCE0.counter), INT_ENUM}, + {&(CONFIG0__INSTANCE0.speeds.table[0]), INT_ENUM}, // ARRAY[0..99] expanded! + {&(CONFIG0__INSTANCE0.speeds.table[1]), INT_ENUM}, + // ... 98 more entries for this single array + {&(CONFIG0__INSTANCE0.speeds.table[99]), INT_ENUM}, +}; +#define VAR_COUNT 101 +``` + +For the reported project with ~3,500 variables (many arrays), this expands to 30,000+ entries: +- Each entry: 4 bytes (pointer) + 4 bytes (enum) = 8 bytes +- 30,000 entries = 240 KB of RAM just for the debug array +- ATmega2560 has 8 KB SRAM total +- Even on 32-bit platforms, this is a massive allocation + +### New System (STruC++ + hierarchical addressing) + +```cpp +// Program 0: 3 variables (counter + speeds array + timer) +// The 100-element array is ONE entry, not 100 +static void* g_prog0_ptrs[] = { + g_config.instance0.counter.raw_ptr(), // index 0: INT + &g_config.instance0.speeds, // index 1: ARRAY[0..99] OF INT (one entry!) + g_config.instance0.timer.raw_ptr(), // index 2: TIME +}; +// 3 entries instead of 102 +``` + +**Scalability win**: The sample project's `ST_GV_HMI_PLC_VARS` struct has 3,491 fields. +With arrays un-expanded, the actual descriptor count is dramatically smaller. Array elements +are accessed on-demand by the debugger using offset calculations. + +## Step 3.1: Debug Infrastructure in generated_glue.hpp + +The `generateArduinoGlue()` function from Phase 2 appends debug infrastructure to +`generated_glue.hpp`. This section details the exact generated code. + +### Per-Program Variable Arrays + +For each program instance, generate four parallel arrays: + +```cpp +// ========== Debug Infrastructure ========== + +// --- Program 0: "instance0" (type: Main) --- + +// Raw storage pointers (for reading variable values) +static void* g_prog0_ptrs[] = { + g_config.instance0.counter.raw_ptr(), // [0] INT, 2 bytes + g_config.instance0.running.raw_ptr(), // [1] BOOL, 1 byte + g_config.instance0.motor_speed.raw_ptr(), // [2] INT, 2 bytes + (void*)&g_config.instance0.speeds, // [3] ARRAY[0..99] OF INT +}; + +// Variable sizes (bytes per element) +static const uint8_t g_prog0_sizes[] = { 2, 1, 2, 2 }; + +// Type-erased get functions +// Return the correct value even when forced (uses IECVar::get() not raw_ptr) +typedef void (*debug_get_fn)(void*); +static const debug_get_fn g_prog0_get_fns[] = { + [](void* d) { *(int16_t*)d = g_config.instance0.counter.get(); }, + [](void* d) { *(bool*)d = g_config.instance0.running.get(); }, + [](void* d) { *(int16_t*)d = g_config.instance0.motor_speed.get(); }, + nullptr, // Array: use element access instead +}; + +// Type-erased force/unforce functions +typedef void (*debug_force_fn)(bool, void*); +static const debug_force_fn g_prog0_force_fns[] = { + [](bool f, void* v) { + if (f) g_config.instance0.counter.force(*(int16_t*)v); + else g_config.instance0.counter.unforce(); + }, + [](bool f, void* v) { + if (f) g_config.instance0.running.force(*(bool*)v); + else g_config.instance0.running.unforce(); + }, + [](bool f, void* v) { + if (f) g_config.instance0.motor_speed.force(*(int16_t*)v); + else g_config.instance0.motor_speed.unforce(); + }, + nullptr, // Array: force individual elements via element access +}; + +// Variable type tags (matches strucpp::VarTypeTag enum values) +static const uint8_t g_prog0_type_tags[] = { + 2, // INT + 0, // BOOL + 2, // INT + 2, // INT (array element type) +}; + +// Array dimension info (0 = scalar, >0 = total element count) +static const uint16_t g_prog0_array_sizes[] = { 0, 0, 0, 100 }; +``` + +### Master Index Arrays + +```cpp +// --- Master index (across all programs) --- + +static void** g_debug_ptrs[] = { g_prog0_ptrs }; +static const uint8_t* g_debug_sizes[] = { g_prog0_sizes }; +static const debug_get_fn* g_debug_get_fns[] = { g_prog0_get_fns }; +static const debug_force_fn* g_debug_force_fns[] = { g_prog0_force_fns }; +static const uint8_t* g_debug_type_tags[] = { g_prog0_type_tags }; +static const uint16_t* g_debug_array_sizes[] = { g_prog0_array_sizes }; + +static const uint16_t g_program_var_counts[] = { 4 }; // vars per program +static const uint8_t g_program_count = 1; +``` + +### Debug Access Functions + +```cpp +// --- Debug access API (called by Modbus handlers) --- + +uint8_t strucpp_get_program_count() { + return g_program_count; +} + +uint16_t strucpp_get_var_count(uint8_t prog_idx) { + if (prog_idx >= g_program_count) return 0; + return g_program_var_counts[prog_idx]; +} + +uint8_t strucpp_get_var_size(uint8_t prog_idx, uint16_t var_idx) { + if (prog_idx >= g_program_count) return 0; + if (var_idx >= g_program_var_counts[prog_idx]) return 0; + return g_debug_sizes[prog_idx][var_idx]; +} + +uint8_t strucpp_get_var_type_tag(uint8_t prog_idx, uint16_t var_idx) { + if (prog_idx >= g_program_count) return 0xFF; + if (var_idx >= g_program_var_counts[prog_idx]) return 0xFF; + return g_debug_type_tags[prog_idx][var_idx]; +} + +uint16_t strucpp_get_array_size(uint8_t prog_idx, uint16_t var_idx) { + if (prog_idx >= g_program_count) return 0; + if (var_idx >= g_program_var_counts[prog_idx]) return 0; + return g_debug_array_sizes[prog_idx][var_idx]; +} + +// Read a scalar variable's value (respects forcing via get()) +bool strucpp_get_var_value(uint8_t prog_idx, uint16_t var_idx, void* dest) { + if (prog_idx >= g_program_count) return false; + if (var_idx >= g_program_var_counts[prog_idx]) return false; + + debug_get_fn fn = g_debug_get_fns[prog_idx][var_idx]; + if (fn) { + fn(dest); + return true; + } + + // Fallback for arrays: read raw pointer (first element) + uint8_t sz = g_debug_sizes[prog_idx][var_idx]; + memcpy(dest, g_debug_ptrs[prog_idx][var_idx], sz); + return true; +} + +// Read an array element's value +bool strucpp_get_array_element(uint8_t prog_idx, uint16_t var_idx, + uint16_t elem_idx, void* dest) { + if (prog_idx >= g_program_count) return false; + if (var_idx >= g_program_var_counts[prog_idx]) return false; + + uint16_t arr_size = g_debug_array_sizes[prog_idx][var_idx]; + if (arr_size == 0 || elem_idx >= arr_size) return false; + + uint8_t elem_size = g_debug_sizes[prog_idx][var_idx]; + // IECVar-wrapped array elements: each element is an IECVar + // Layout: value_ (elem_size) + forced_ (1) + forced_value_ (elem_size) + // Total per element: elem_size * 2 + 1 + size_t iec_var_stride = elem_size * 2 + 1; + uint8_t* base = (uint8_t*)g_debug_ptrs[prog_idx][var_idx]; + // Read via value_ field (offset 0 within each IECVar element) + memcpy(dest, base + elem_idx * iec_var_stride, elem_size); + return true; +} + +// Force/unforce a scalar variable +bool strucpp_force_var(uint8_t prog_idx, uint16_t var_idx, + bool force, void* value) { + if (prog_idx >= g_program_count) return false; + if (var_idx >= g_program_var_counts[prog_idx]) return false; + + debug_force_fn fn = g_debug_force_fns[prog_idx][var_idx]; + if (!fn) return false; + fn(force, value); + return true; +} + +// Unforce all variables (reset all traces) +void strucpp_trace_reset() { + for (uint8_t p = 0; p < g_program_count; ++p) { + for (uint16_t v = 0; v < g_program_var_counts[p]; ++v) { + debug_force_fn fn = g_debug_force_fns[p][v]; + if (fn) fn(false, nullptr); + } + } +} +``` + +### Memory Budget + +For a project with 500 variables across 2 programs (typical for the problematic sample project +when arrays are NOT expanded): + +| Component | Per Variable | Total (500 vars) | +|-----------|-------------|-------------------| +| Pointer (g_prog*_ptrs) | 2-4 bytes | 1-2 KB | +| Size (g_prog*_sizes) | 1 byte | 500 bytes | +| Get function ptr | 2-4 bytes | 1-2 KB | +| Force function ptr | 2-4 bytes | 1-2 KB | +| Type tag | 1 byte | 500 bytes | +| Array size | 2 bytes | 1 KB | +| **Total on AVR (2-byte ptr)** | | **~5 KB** | +| **Total on 32-bit (4-byte ptr)** | | **~9 KB** | + +On ATmega2560 (8 KB SRAM): fits with ~3 KB remaining for stack and program variables. +On ESP32 (520 KB SRAM): trivially fits. + +Compare with current system: 30,000 entries * 8 bytes = 240 KB (does not fit on any Arduino). + +## Step 3.2: Modbus Debug Protocol Update + +The existing Modbus custom function codes (0x41-0x45) are preserved. Only the PDU payload +format changes. + +### Protocol Version Detection + +The editor detects the protocol version based on which debug file exists in build artifacts: +- `debug.c` present -> Protocol v1 (flat index, MatIEC) +- `debug-map.json` present -> Protocol v2 (hierarchical, STruC++) + +### Function Code 0x41: DEBUG_INFO + +**Request** (v1 and v2 identical): +``` +[0x41] +``` + +**Response v1** (current): +``` +[0x41] [0x7E] [var_count_hi:u8] [var_count_lo:u8] +``` + +**Response v2** (new): +``` +[0x41] [0x7E] [version:u8=2] [prog_count:u8] + [prog0_var_count_hi:u8] [prog0_var_count_lo:u8] + [prog1_var_count_hi:u8] [prog1_var_count_lo:u8] + ... +``` + +The `version` byte (value 2) distinguishes v2 from v1 responses. v1 responses will have +a value of 0 or 1 in this position (high byte of var_count, which is < 256 for small projects). + +### Function Code 0x42: DEBUG_SET (Force/Unforce) + +**Request v2**: +``` +[0x42] [prog_idx:u8] [var_idx_hi:u8] [var_idx_lo:u8] + [force_flag:u8] [value_len:u8] [value_bytes...] +``` + +- `force_flag`: 1 = force, 0 = unforce +- `value_bytes`: little-endian value to force (only when force_flag = 1) + +**Response v2**: +``` +[0x42] [status:u8] +``` +- `0x7E` = success +- `0x81` = invalid program/variable index +- `0x82` = type mismatch or array variable (use element forcing instead) + +### Function Code 0x43: DEBUG_GET (Range Read) + +**Request v2**: +``` +[0x43] [prog_idx:u8] [start_var:u16] [end_var:u16] +``` + +**Response v2**: +``` +[0x43] [0x7E] [tick:u32] [data_len:u16] [var_data...] +``` + +Variables are returned in order from `start_var` to `end_var`. Each variable's data is +its raw bytes (size determined by type). For array variables, only the first element is +returned in range reads; use function code 0x44 for specific elements. + +### Function Code 0x44: DEBUG_GET_LIST (Batch Read) + +**Request v2**: +``` +[0x44] [count:u16] + [prog_idx_0:u8] [var_idx_0:u16] [elem_idx_0:u16] + [prog_idx_1:u8] [var_idx_1:u16] [elem_idx_1:u16] + ... +``` + +- `elem_idx`: For scalar variables, use 0xFFFF (no element). For array elements, use the + element index. + +**Response v2**: +``` +[0x44] [0x7E] [tick:u32] [data_len:u16] [var_data...] +``` + +Each variable's data is concatenated in request order. Sizes are known by the editor +from the debug-map.json type information. + +### Function Code 0x45: DEBUG_GET_MD5 + +**Request v2** (unchanged from v1): +``` +[0x45] [endian_check_byte_1:u8] [endian_check_byte_2:u8] + [endian_check_byte_3:u8] [endian_check_byte_4:u8] +``` + +**Response v2** (unchanged from v1): +``` +[0x45] [0x7E] [md5_string:32bytes] [endian_echo:4bytes] +``` + +### Implementation Changes + +**File to modify**: `resources/sources/Baremetal/ModbusSlave.h` (and .cpp if separate) + +The debug handler functions need updating: + +```cpp +// Old signatures (MatIEC): +// extern "C" uint16_t get_var_count(void); +// extern "C" void* get_var_addr(size_t idx); +// extern "C" void set_trace(size_t idx, bool forced, void* val); + +// New: call strucpp_* functions from generated_glue.hpp +void debugInfo(uint8_t* frame, uint16_t* frameSize) { + frame[0] = 0x41; + frame[1] = 0x7E; + frame[2] = 2; // protocol version + frame[3] = strucpp_get_program_count(); + uint16_t offset = 4; + for (uint8_t p = 0; p < frame[3]; p++) { + uint16_t vc = strucpp_get_var_count(p); + frame[offset++] = vc >> 8; + frame[offset++] = vc & 0xFF; + } + *frameSize = offset; +} + +void debugSetTrace(uint8_t* frame, uint16_t* frameSize) { + uint8_t prog_idx = frame[1]; + uint16_t var_idx = (frame[2] << 8) | frame[3]; + bool force = frame[4] != 0; + uint8_t val_len = frame[5]; + void* val_ptr = &frame[6]; + + bool ok = strucpp_force_var(prog_idx, var_idx, force, force ? val_ptr : nullptr); + frame[0] = 0x42; + frame[1] = ok ? 0x7E : 0x81; + *frameSize = 2; +} + +void debugGetTraceList(uint8_t* frame, uint16_t frameLen, uint16_t* respSize) { + uint16_t count = (frame[1] << 8) | frame[2]; + uint8_t* resp = frame; // reuse buffer + resp[0] = 0x44; + resp[1] = 0x7E; + // tick at resp[2..5] + uint32_t tick = __tick; + memcpy(&resp[2], &tick, 4); + + uint16_t data_offset = 8; // skip header + uint16_t req_offset = 3; // skip count field + + for (uint16_t i = 0; i < count; i++) { + uint8_t prog_idx = frame[req_offset++]; + uint16_t var_idx = (frame[req_offset] << 8) | frame[req_offset + 1]; + req_offset += 2; + uint16_t elem_idx = (frame[req_offset] << 8) | frame[req_offset + 1]; + req_offset += 2; + + uint8_t sz = strucpp_get_var_size(prog_idx, var_idx); + + if (elem_idx == 0xFFFF) { + // Scalar read + strucpp_get_var_value(prog_idx, var_idx, &resp[data_offset]); + } else { + // Array element read + strucpp_get_array_element(prog_idx, var_idx, elem_idx, &resp[data_offset]); + } + data_offset += sz; + } + + // Write data length at resp[6..7] + uint16_t data_len = data_offset - 8; + resp[6] = data_len >> 8; + resp[7] = data_len & 0xFF; + *respSize = data_offset; +} +``` + +## Step 3.3: Debug Map File (debug-map.json) + +The compiler pipeline generates `debug-map.json` (written alongside build artifacts) to +replace `debug.c` as the editor's source of variable metadata. + +### Format + +```json +{ + "version": 2, + "md5": "a1b2c3d4e5f67890a1b2c3d4e5f67890", + "commonTicktimeNs": 20000000, + "programs": [ + { + "index": 0, + "instanceName": "instance0", + "programType": "Main", + "intervalNs": 20000000, + "vars": [ + { + "index": 0, + "name": "counter", + "type": "INT", + "typeTag": "INT", + "size": 2 + }, + { + "index": 1, + "name": "running", + "type": "BOOL", + "typeTag": "BOOL", + "size": 1 + }, + { + "index": 2, + "name": "motor_speed", + "type": "INT", + "typeTag": "INT", + "size": 2, + "location": "%QW0" + }, + { + "index": 3, + "name": "speeds", + "type": "ARRAY [0..99] OF INT", + "typeTag": "INT", + "size": 2, + "isArray": true, + "dimensions": [100] + }, + { + "index": 4, + "name": "fb_inst", + "type": "MyFB", + "isStruct": true, + "fields": [ + { "name": "output", "type": "REAL", "typeTag": "REAL", "size": 4 }, + { "name": "setpoint", "type": "INT", "typeTag": "INT", "size": 2 } + ] + } + ] + } + ] +} +``` + +### Generation + +**In `generate-arduino-glue.ts`** (extends Phase 2): + +```typescript +export function generateDebugMap( + variableDescriptors: ProgramVarDescriptor[], + taskIntervals: TaskInterval[], + md5Hash: string, + commonTicktimeNs: number, +): string { + const programs = variableDescriptors.map((prog, idx) => ({ + index: idx, + instanceName: prog.programInstanceName, + programType: prog.programTypeName, + intervalNs: taskIntervals.find(t => t.instanceName === prog.programInstanceName)?.intervalNs ?? 20_000_000, + vars: prog.variables.map((v, vidx) => ({ + index: vidx, + name: v.name, + type: v.isArray ? `ARRAY [0..${(v.arrayDimensions?.[0] ?? 1) - 1}] OF ${v.typeTag}` : v.typeTag, + typeTag: v.typeTag, + size: v.size, + ...(v.isArray && { isArray: true, dimensions: v.arrayDimensions }), + ...(v.isStruct && { isStruct: true, fields: v.structFields }), + })), + })) + + return JSON.stringify({ version: 2, md5: md5Hash, commonTicktimeNs, programs }, null, 2) +} +``` + +## Design Notes + +### Why Type-Erased Functions Instead of Templates + +Arduino AVR has no RTTI and limited template support. Using C function pointers (`void(*)(void*)`) +avoids virtual dispatch overhead and keeps the debug infrastructure simple. The lambdas in the +generated code are stateless and compile to regular function pointers. + +### Array Element Access Without Expansion + +When the editor user expands an array in the debug variable tree, the editor sends individual +`(prog_idx, var_idx, elem_idx)` read requests via function code 0x44. The device computes the +memory offset: `base_ptr + elem_idx * stride`. No pre-expansion needed. + +For forcing array elements, the force function operates on the IECVar wrapper of the specific +element. The array is stored as `Array1D, 0, 99>` in STruC++ output, so each +element has its own `force()`/`unforce()` capability. + +### Struct/FB Instance Variable Access + +For function block instances, the variables are flattened in the descriptor array: +- `fb_inst` itself is marked as `isStruct: true` with its fields listed +- The editor builds a tree: `program.fb_inst.output`, `program.fb_inst.setpoint` +- At the protocol level, each field gets its own var_idx (or is accessed via struct offset) + +The exact approach depends on how STruC++ lays out FB member variables. If FB members are +exposed as individual `IECVar` fields, each gets its own descriptor. If they're packed +in a struct, offset-based access is used. + +## Testing Strategy + +1. **Scalability test**: Compile the sample project (~3,500 variables, many arrays) + - Verify `debug-map.json` has significantly fewer entries than the old debug.c VAR_COUNT + - Verify arrays have `isArray: true` with `dimensions` (not expanded) + +2. **Protocol test** (simulator): + - Send 0x41, verify response contains program count and var counts + - Send 0x44 with scalar variable refs, verify correct values returned + - Send 0x44 with array element refs, verify correct element values + +3. **Force test** (simulator): + - Send 0x42 to force an INT variable to 42 + - Run PLC cycles + - Read the variable, verify it's still 42 + - Send 0x42 to unforce, verify it returns to computed value + +4. **Memory test**: Verify generated debug arrays fit within target platform RAM limits + +## Files Created/Modified + +| File | Action | +|------|--------| +| `src/backend/shared/utils/PLC/generate-arduino-glue.ts` | Extended -- debug arrays + debug-map.json | +| `resources/sources/Baremetal/ModbusSlave.h` | Modified -- debug handler functions | diff --git a/docs/strucpp-migration/04-editor-compiler-module.md b/docs/strucpp-migration/04-editor-compiler-module.md new file mode 100644 index 000000000..c9987451b --- /dev/null +++ b/docs/strucpp-migration/04-editor-compiler-module.md @@ -0,0 +1,439 @@ +# Phase 4: Editor Compiler Module Updates + +## Goal + +Wire the new STruC++ pipeline (Phases 1-3) into the editor's `compiler-module.ts`, replacing +the iec2c and xml2st debug/glue steps while preserving the existing MatIEC path for backward +compatibility. + +## Prerequisites + +- Phase 1 (strucpp-compiler.ts wrapper) +- Phase 2 (generate-arduino-glue.ts) +- Phase 3 (debug map generation and debug arrays in glue) + +## Primary File + +**`src/backend/editor/compiler/compiler-module.ts`** (~2,348 lines) + +This is the main compilation orchestrator. It currently handles the full pipeline from JSON +project data to uploaded firmware. The STruC++ pipeline adds new methods alongside existing +ones; both coexist. + +## Step 4.1: Pipeline Routing + +The entry point `compileProgram()` (line ~1377) determines which pipeline to use based on +the board's `compiler_backend` field in `hals.json`: + +```typescript +async compileProgram(args, _mainProcessPort, mainProcessBridge) { + const boardTarget = args[1] as string + const boardEntry = this.halsContent[boardTarget] + + if (boardEntry?.compiler_backend === 'strucpp') { + return this.compileArduinoWithSTruCpp(args, _mainProcessPort, mainProcessBridge) + } + // ... existing MatIEC pipeline +} +``` + +Similarly for `compileForDebugger()` (line ~2157): + +```typescript +async compileForDebugger(args, _mainProcessPort, mainProcessBridge) { + const boardTarget = args[1] as string + const boardEntry = this.halsContent[boardTarget] + + if (boardEntry?.compiler_backend === 'strucpp') { + return this.compileForDebuggerWithSTruCpp(args, _mainProcessPort, mainProcessBridge) + } + // ... existing MatIEC debug pipeline +} +``` + +## Step 4.2: New STruC++ Compilation Pipeline + +### Method: `compileArduinoWithSTruCpp()` + +```typescript +private async compileArduinoWithSTruCpp( + args: Array, + _mainProcessPort: MessagePortMain, + mainProcessBridge: MainProcessBridgeType, +): Promise { + const projectData = args[0] as PLCProjectData + const boardTarget = args[1] as string + const projectPath = args[2] as string + const compileOnly = args[3] as boolean + // ... extract other args + + const compilationPath = path.join(projectPath, 'build', boardTarget, 'src') + + try { + // === STEP 1: Create directories (unchanged) === + this.createBasicDirectories(projectPath, boardTarget) + this.postMessage(_mainProcessPort, 'info', 'Creating build directories...') + + // === STEP 2: Generate XML from JSON (unchanged) === + this.postMessage(_mainProcessPort, 'info', 'Generating IEC 61131-3 XML...') + await this.handleGenerateXMLfromJSON(projectData, compilationPath) + + // === STEP 3: xml2st --generate-st (unchanged) === + this.postMessage(_mainProcessPort, 'info', 'Transpiling XML to Structured Text...') + await this.handleTranspileXMLtoST(compilationPath) + // Result: program.st in compilationPath + + // === STEP 4: Copy STruC++ static files (NEW) === + this.postMessage(_mainProcessPort, 'info', 'Copying STruC++ runtime headers...') + this.copyStrucppStaticFiles(compilationPath) + + // === STEP 5: Compile ST to C++ with STruC++ (NEW - replaces iec2c) === + this.postMessage(_mainProcessPort, 'info', 'Compiling Structured Text to C++...') + const strucppResult = await this.handleCompileSTtoCpp(compilationPath) + if (!strucppResult.success) { + const errorMsg = strucppResult.errors.map(e => `Line ${e.line}: ${e.message}`).join('\n') + this.postMessage(_mainProcessPort, 'error', `STruC++ compilation failed:\n${errorMsg}`) + this.closePort(_mainProcessPort) + return + } + + // === STEP 6: Compute MD5 (NEW approach) === + const stContent = fs.readFileSync(path.join(compilationPath, 'program.st'), 'utf-8') + const md5Hash = crypto.createHash('md5').update(stContent).digest('hex') + + // === STEP 7: Generate glue + debug files (NEW - replaces xml2st debug/glue) === + this.postMessage(_mainProcessPort, 'info', 'Generating I/O binding and debug maps...') + await this.handleGenerateGlueAndDebug(strucppResult, projectData, compilationPath, md5Hash, boardTarget) + + // === STEP 8: Generate C++ blocks header/code (unchanged) === + this.postMessage(_mainProcessPort, 'info', 'Processing C++ blocks...') + await this.handleGenerateCBlocksHeader(projectData, compilationPath) + await this.handleGenerateCBlocksCode(projectData, compilationPath) + + // === STEP 9: Copy HAL file (unchanged) === + this.postMessage(_mainProcessPort, 'info', 'Configuring hardware abstraction...') + await this.handleGenerateArduinoCppFile(boardTarget, compilationPath) + + // === STEP 10: Generate defines.h (modified - reads stContent for library detection) === + this.postMessage(_mainProcessPort, 'info', 'Generating definitions...') + await this.handleGenerateDefinitionsFileSTruCpp(projectData, boardTarget, compilationPath, md5Hash, stContent) + + // === STEP 11-12: Arduino compilation (modified - adds -std=gnu++17) === + this.postMessage(_mainProcessPort, 'info', 'Installing Arduino core...') + await this.handleCoreInstallation(boardTarget) + await this.handleLibraryInstallation(boardTarget, compilationPath) + + this.postMessage(_mainProcessPort, 'info', 'Compiling Arduino program...') + await this.handleCompileArduinoProgramSTruCpp(boardTarget, compilationPath, compileOnly) + + // === STEP 13: Upload (unchanged) === + if (!compileOnly) { + this.postMessage(_mainProcessPort, 'info', 'Uploading firmware...') + await this.handleUploadProgram(boardTarget, compilationPath) + } + + this.postMessage(_mainProcessPort, 'info', 'Compilation successful!') + this.closePort(_mainProcessPort) + + } catch (error) { + this.postMessage(_mainProcessPort, 'error', `Compilation failed: ${getErrorMessage(error)}`) + this.closePort(_mainProcessPort) + } +} +``` + +## Step 4.3: New Private Methods + +### `copyStrucppStaticFiles()` + +```typescript +private copyStrucppStaticFiles(compilationPath: string): void { + const strucppRuntimeDir = path.join(this.resourcesPath, 'sources', 'StrucppRuntime') + const strucppBaremetalDir = path.join(this.resourcesPath, 'sources', 'StrucppBaremetal') + + // Copy runtime headers + const headers = fs.readdirSync(strucppRuntimeDir) + for (const file of headers) { + fs.copyFileSync( + path.join(strucppRuntimeDir, file), + path.join(compilationPath, file), + ) + } + + // Copy StrucppBaremetal.ino + fs.copyFileSync( + path.join(strucppBaremetalDir, 'StrucppBaremetal.ino'), + path.join(compilationPath, 'StrucppBaremetal.ino'), + ) +} +``` + +### `handleCompileSTtoCpp()` + +```typescript +private async handleCompileSTtoCpp(compilationPath: string): Promise { + const stFilePath = path.join(compilationPath, 'program.st') + const stSource = fs.readFileSync(stFilePath, 'utf-8') + + // Compile with STruC++ + const result = compileWithSTruCpp(stSource, { + headerFileName: 'generated.hpp', + debug: true, + lineMapping: true, + }) + + if (result.success) { + // Write generated files + fs.writeFileSync(path.join(compilationPath, 'generated.cpp'), result.cppCode) + fs.writeFileSync(path.join(compilationPath, 'generated.hpp'), result.headerCode) + } + + return result +} +``` + +### `handleGenerateGlueAndDebug()` + +```typescript +private async handleGenerateGlueAndDebug( + strucppResult: STruCppResult, + projectData: PLCProjectData, + compilationPath: string, + md5Hash: string, + boardTarget: string, +): Promise { + const boardEntry = this.halsContent[boardTarget] + const boardMemoryClass = this.getBoardMemoryClass(boardTarget) + + // Generate generated_glue.hpp (I/O binding + scheduler + debug arrays) + const glueCode = generateArduinoGlue({ + configurationName: projectData.configurations?.resource?.[0]?.name ?? 'Config0', + taskIntervals: strucppResult.taskIntervals, + variableDescriptors: strucppResult.variableDescriptors, + md5Hash, + boardMemoryClass, + }) + fs.writeFileSync(path.join(compilationPath, 'generated_glue.hpp'), glueCode) + + // Generate debug-map.json + const gcdNs = computeTaskGCD(strucppResult.taskIntervals) + const debugMap = generateDebugMap( + strucppResult.variableDescriptors, + strucppResult.taskIntervals, + md5Hash, + gcdNs, + ) + fs.writeFileSync(path.join(compilationPath, 'debug-map.json'), debugMap) +} +``` + +### `handleCompileArduinoProgramSTruCpp()` + +```typescript +private async handleCompileArduinoProgramSTruCpp( + boardTarget: string, + compilationPath: string, + compileOnly: boolean, +): Promise { + const boardEntry = this.halsContent[boardTarget] + + // Ensure -std=gnu++17 is in CXX flags + const cxxFlags = boardEntry.cxx_flags ? [...boardEntry.cxx_flags] : [] + if (!cxxFlags.some(f => f.includes('-std='))) { + cxxFlags.push('-std=gnu++17') + } + + // Build the arduino-cli compile command + // Same structure as current handleCompileArduinoProgram() but with C++17 flag + const buildProperties = [ + `compiler.cpp.extra_flags=${cxxFlags.join(' ')}`, + // ... other build properties (same as current) + ] + + await this.executeArduinoCliCommand([ + 'compile', + '--fqbn', boardEntry.platform, + '--build-property', buildProperties.join(';'), + '--export-binaries', + compilationPath, + ]) +} +``` + +### `handleGenerateDefinitionsFileSTruCpp()` + +Same as current `handleGenerateDefinitionsFile()` but: +- Receives `stContent` (program.st text) as parameter instead of reading from file +- Uses the same library detection logic (scanning for DS18B20, P1AM, etc.) +- Embeds MD5 hash from parameter instead of regex extraction +- No changes to pin mapping, Modbus config, or board defines + +## Step 4.4: Debug Compilation Pipeline + +### Method: `compileForDebuggerWithSTruCpp()` + +Simplified pipeline that produces debug metadata without full Arduino compilation: + +```typescript +private async compileForDebuggerWithSTruCpp( + args: Array, + _mainProcessPort: MessagePortMain, + mainProcessBridge: MainProcessBridgeType, +): Promise { + const projectData = args[0] as PLCProjectData + const boardTarget = args[1] as string + const projectPath = args[2] as string + const compilationPath = path.join(projectPath, 'build', boardTarget, 'src') + + try { + // Steps 1-3: Same as full compile (create dirs, XML, ST) + this.createBasicDirectories(projectPath, boardTarget) + await this.handleGenerateXMLfromJSON(projectData, compilationPath) + await this.handleTranspileXMLtoST(compilationPath) + + // Step 4: Compile ST to C++ (for variable metadata) + const strucppResult = await this.handleCompileSTtoCpp(compilationPath) + if (!strucppResult.success) { + this.postMessage(_mainProcessPort, 'error', 'STruC++ compilation failed') + this.closePort(_mainProcessPort) + return + } + + // Step 5: Compute MD5 + const stContent = fs.readFileSync(path.join(compilationPath, 'program.st'), 'utf-8') + const md5Hash = crypto.createHash('md5').update(stContent).digest('hex') + + // Step 6: Generate debug-map.json only (no glue code needed for debug) + const gcdNs = computeTaskGCD(strucppResult.taskIntervals) + const debugMap = generateDebugMap( + strucppResult.variableDescriptors, + strucppResult.taskIntervals, + md5Hash, + gcdNs, + ) + fs.writeFileSync(path.join(compilationPath, 'debug-map.json'), debugMap) + + // Step 7: Generate C blocks (for variable detection) + await this.handleGenerateCBlocksHeader(projectData, compilationPath) + await this.handleGenerateCBlocksCode(projectData, compilationPath) + + // Done -- no Arduino compilation needed + this.postMessage(_mainProcessPort, 'info', 'Debug compilation complete') + this.closePort(_mainProcessPort) + + } catch (error) { + this.postMessage(_mainProcessPort, 'error', `Debug compilation failed: ${getErrorMessage(error)}`) + this.closePort(_mainProcessPort) + } +} +``` + +## Step 4.5: IPC Bridge Updates + +### Read Debug Map + +The IPC bridge needs a new handler to read `debug-map.json`: + +**File to modify**: `src/main/modules/ipc/main.ts` + +```typescript +handleReadDebugMap = ( + _event: IpcMainEvent, + args: Array, +): Promise<{ success: boolean; content?: string; error?: string }> => { + const [projectPath, boardTarget] = args + const debugMapPath = path.join(projectPath, 'build', boardTarget, 'src', 'debug-map.json') + + if (!fs.existsSync(debugMapPath)) { + return { success: false, error: 'debug-map.json not found' } + } + + const content = fs.readFileSync(debugMapPath, 'utf-8') + return { success: true, content } +} +``` + +**File to modify**: `src/main/modules/preload/preload.ts` + +Expose the new handler: +```typescript +debuggerReadDebugMap: (projectPath: string, boardTarget: string) => + ipcRenderer.invoke('debugger:read-debug-map', [projectPath, boardTarget]) +``` + +## Step 4.6: Build Directory Structure + +### Old (MatIEC): +``` +build/{boardTarget}/src/ + plc.xml + program.st + lib/ <- MatIEC runtime headers + POUS.c <- MatIEC output + POUS.h + Res0.c + Config0.c + Config0.h + LOCATED_VARIABLES.h + glueVars.c <- xml2st output + debug.c <- xml2st output + VARIABLES.csv + c_blocks.h + c_blocks_code.cpp + arduino.cpp <- HAL file + defines.h + Baremetal.ino +``` + +### New (STruC++): +``` +build/{boardTarget}/src/ + plc.xml + program.st + iec_var.hpp <- STruC++ runtime headers + iec_types.hpp + iec_located.hpp + ... (other runtime headers) + generated.hpp <- STruC++ output + generated.cpp <- STruC++ output + generated_glue.hpp <- Glue generator output + debug-map.json <- Debug map + c_blocks.h + c_blocks_code.cpp + arduino.cpp <- HAL file (unchanged) + defines.h + openplc.h <- Buffer declarations (unchanged) + debug.h <- Debug function declarations (updated) + ModbusSlave.h <- Modbus + debug protocol (updated) + StrucppBaremetal.ino <- New Arduino sketch +``` + +## Testing Strategy + +1. **End-to-end Arduino compile**: Simple ST project through full pipeline + - Verify all generated files are present in build directory + - Verify arduino-cli compiles without errors + - Verify firmware binary is produced + +2. **End-to-end debug compile**: Same project through debug pipeline + - Verify debug-map.json is generated + - Verify it contains correct variable metadata + - Verify no arduino-cli invocation (faster) + +3. **Pipeline routing**: Test that MatIEC boards still use old pipeline + - Set `compiler_backend: "matiec"` (or absent) in hals.json + - Verify old debug.c and glueVars.c are generated + +4. **Error handling**: Test STruC++ compilation error propagation + - Feed invalid ST code + - Verify error messages reach the frontend via MessagePort + +5. **Regression**: All existing compiler-module.spec.ts tests pass unchanged + +## Files Created/Modified + +| File | Action | +|------|--------| +| `src/backend/editor/compiler/compiler-module.ts` | Modified -- add STruC++ pipeline methods | +| `src/main/modules/ipc/main.ts` | Modified -- add debug map read handler | +| `src/main/modules/preload/preload.ts` | Modified -- expose debug map reader | diff --git a/docs/strucpp-migration/05-editor-frontend-debugger.md b/docs/strucpp-migration/05-editor-frontend-debugger.md new file mode 100644 index 000000000..3197fb425 --- /dev/null +++ b/docs/strucpp-migration/05-editor-frontend-debugger.md @@ -0,0 +1,480 @@ +# Phase 5: Editor Frontend Debugger Updates + +## Goal + +Update the editor's debugger frontend to support both the legacy flat-index protocol (v1, +MatIEC) and the new hierarchical protocol (v2, STruC++). The UI should parse `debug-map.json`, +build a hierarchical variable tree, and use `(program_idx, var_idx)` addressing for variable +reads and writes. + +## Prerequisites + +- Phase 3 (debug-map.json format, Modbus protocol v2) +- Phase 4 (IPC bridge for reading debug-map.json) + +## Step 5.1: New Debug Map Parser + +**File to modify**: `src/frontend/utils/debug-parser.ts` + +Add `parseDebugMapV2()` alongside the existing `parseDebugVariables()` (which parses debug.c). + +```typescript +// ----- Types for debug-map.json (Protocol v2) ----- + +export interface DebugMapV2 { + version: 2 + md5: string + commonTicktimeNs: number + programs: DebugMapProgram[] +} + +export interface DebugMapProgram { + index: number + instanceName: string + programType: string + intervalNs: number + vars: DebugMapVariable[] +} + +export interface DebugMapVariable { + index: number + name: string + type: string + typeTag: string + size: number + location?: string // e.g., "%QW0" for located variables + isArray?: boolean + dimensions?: number[] // e.g., [100] for ARRAY[0..99] + isStruct?: boolean + fields?: DebugMapVariable[] +} + +// ----- Reference type for hierarchical addressing ----- + +export interface DebugVarRef { + programIdx: number + varIdx: number + elementIdx?: number // For array elements (omit for scalars) +} + +// ----- Parser ----- + +export function parseDebugMapV2(jsonContent: string): DebugMapV2 { + const raw = JSON.parse(jsonContent) + + if (raw.version !== 2) { + throw new Error(`Unsupported debug map version: ${raw.version}`) + } + + return raw as DebugMapV2 +} + +// ----- Existing functions (unchanged) ----- +// export function parseDebugVariables(content: string): DebugVariableEntry[] +// export function parseDebugData(content: string): ParsedDebugData +``` + +## Step 5.2: Update Variable Ref Map Builder + +**File to modify**: `src/frontend/utils/debugger-session.ts` + +Add a function that builds the variable reference map from `DebugMapV2`. This maps composite +keys (used by the variable tree UI) to `DebugVarRef` objects. + +```typescript +/** + * Build a variable reference map from debug-map.json (protocol v2). + * Maps composite keys (e.g., "instance0.counter") to DebugVarRef objects. + */ +export function buildVariableRefMapV2( + debugMap: DebugMapV2, +): Map { + const refMap = new Map() + + for (const program of debugMap.programs) { + const progPrefix = program.instanceName + + for (const variable of program.vars) { + const key = `${progPrefix}.${variable.name}` + + refMap.set(key, { + programIdx: program.index, + varIdx: variable.index, + }) + + // For arrays: also register element keys + if (variable.isArray && variable.dimensions) { + const totalElements = variable.dimensions.reduce((a, b) => a * b, 1) + for (let elem = 0; elem < totalElements; elem++) { + refMap.set(`${key}[${elem}]`, { + programIdx: program.index, + varIdx: variable.index, + elementIdx: elem, + }) + } + } + + // For structs: register field keys + if (variable.isStruct && variable.fields) { + for (const field of variable.fields) { + refMap.set(`${key}.${field.name}`, { + programIdx: program.index, + varIdx: variable.index, + // Struct field access: var_idx points to the struct, field offset computed at runtime + }) + } + } + } + } + + return refMap +} +``` + +## Step 5.3: Update Debugger Port Interface + +**File to modify**: `src/middleware/shared/ports/debugger-port.ts` + +The debugger port needs to support both v1 (flat index) and v2 (hierarchical) protocols. + +```typescript +// Add to existing types: +export { DebugVarRef } from '@utils/debug-parser' + +// The port interface methods are updated to accept both ref types: +export interface DebuggerPort { + // ... existing methods ... + + /** + * Read variable values (protocol v2 - hierarchical). + * Falls back to flat index for v1 targets. + */ + getVariablesList(refs: DebugVarRef[]): Promise + + /** + * Force/unforce a variable (protocol v2 - hierarchical). + */ + setVariable(ref: DebugVarRef, force: boolean, valueBuffer?: Uint8Array): Promise + + /** + * Read the debug map file (protocol v2). + * Returns null if debug-map.json doesn't exist (v1 target). + */ + readDebugMap(projectPath: string, boardTarget: string): Promise +} +``` + +## Step 5.4: Update Debug Tree Builder + +**File to modify**: `src/frontend/utils/debug-tree-builder.ts` + +Add the ability to build the debug variable tree from `DebugMapV2`. The tree structure matches +what the UI expects but is built from the new hierarchical format. + +Key improvement: **arrays appear as single expandable nodes** instead of being pre-expanded +into individual entries. When the user clicks to expand an array, the UI generates child +nodes on-demand and requests their values individually. + +```typescript +/** + * Build debug tree from debug-map.json (protocol v2). + * Arrays are NOT pre-expanded -- they appear as single nodes. + */ +export function buildDebugTreeV2( + debugMap: DebugMapV2, + pous: PLCPou[], +): Map { + const tree = new Map() + + for (const program of debugMap.programs) { + const progKey = program.instanceName + + // Program root node + tree.set(progKey, { + key: progKey, + name: program.instanceName, + type: 'program', + children: [], + }) + + for (const variable of program.vars) { + const varKey = `${progKey}.${variable.name}` + + const node: DebugTreeNode = { + key: varKey, + name: variable.name, + type: variable.isArray ? 'array' : variable.isStruct ? 'struct' : 'scalar', + dataType: variable.type, + typeTag: variable.typeTag, + size: variable.size, + ref: { programIdx: program.index, varIdx: variable.index }, + } + + if (variable.isArray && variable.dimensions) { + // Array node: children are generated lazily when expanded + node.arrayDimensions = variable.dimensions + node.childCount = variable.dimensions.reduce((a, b) => a * b, 1) + node.lazyChildren = true // Don't generate child nodes yet + } + + if (variable.isStruct && variable.fields) { + // Struct node: children are the fields + node.children = variable.fields.map(field => ({ + key: `${varKey}.${field.name}`, + name: field.name, + type: 'scalar', + dataType: field.type, + typeTag: field.typeTag, + size: field.size, + ref: { programIdx: program.index, varIdx: variable.index }, + })) + } + + tree.set(varKey, node) + } + } + + return tree +} + +/** + * Generate child nodes for a lazy array node (called when user expands the array). + */ +export function expandArrayNode( + parentNode: DebugTreeNode, +): DebugTreeNode[] { + if (!parentNode.arrayDimensions || !parentNode.ref) return [] + + const totalElements = parentNode.arrayDimensions.reduce((a, b) => a * b, 1) + const children: DebugTreeNode[] = [] + + for (let i = 0; i < totalElements; i++) { + children.push({ + key: `${parentNode.key}[${i}]`, + name: `[${i}]`, + type: 'scalar', + dataType: parentNode.typeTag ?? parentNode.dataType, + size: parentNode.size, + ref: { + programIdx: parentNode.ref.programIdx, + varIdx: parentNode.ref.varIdx, + elementIdx: i, + }, + }) + } + + return children +} +``` + +## Step 5.5: Update Debug Session Hook + +**File to modify**: `src/frontend/hooks/useDebugSession.ts` + +The debug session hook orchestrates the connection between the editor and the target device. +It needs to detect the protocol version and use the appropriate parser. + +```typescript +// In the connect/start function: +async function startDebugSession(projectPath: string, boardTarget: string) { + // 1. Try to read debug-map.json (protocol v2) + const debugMap = await debuggerPort.readDebugMap(projectPath, boardTarget) + + if (debugMap) { + // Protocol v2: hierarchical addressing + setDebugProtocolVersion(2) + const refMap = buildVariableRefMapV2(debugMap) + setDebugVariableIndexes(refMap) + const tree = buildDebugTreeV2(debugMap, projectData.pous) + setDebugVariableTree(tree) + setDebugMd5(debugMap.md5) + } else { + // Protocol v1: fall back to debug.c parsing (legacy) + const debugFile = await debuggerPort.readDebugFile(projectPath, boardTarget) + if (debugFile) { + setDebugProtocolVersion(1) + const variables = parseDebugVariables(debugFile) + // ... existing v1 tree building logic + } + } + + // 2. Connect to target (unchanged) + await debuggerPort.connect(config) + + // 3. Verify MD5 match (unchanged in concept, uses new MD5) + const runtimeMd5 = await debuggerPort.verifyMd5(debugMd5, config) + if (!runtimeMd5.match) { + setDebugMd5Mismatch(true) + } + + // 4. Start polling (see Step 5.7) +} +``` + +## Step 5.6: Update Workspace Store + +**File to modify**: `src/frontend/store/slices/workspace/types.ts` + +```typescript +export interface WorkspaceState { + // ... existing fields ... + + /** Debug protocol version: 1 = flat index (MatIEC), 2 = hierarchical (STruC++) */ + debugProtocolVersion: 1 | 2 + + /** Variable indexes: DebugVarRef for v2, number for v1 */ + debugVariableIndexes: Map + + // ... rest unchanged +} +``` + +**File to modify**: `src/frontend/store/slices/workspace/slice.ts` + +Add actions: +```typescript +setDebugProtocolVersion: (version: 1 | 2) => void +``` + +## Step 5.7: Update Debug Polling + +**File to modify**: `src/frontend/hooks/useDebugPolling.ts` + +The polling hook needs to handle both protocols: + +```typescript +// In the polling function: +async function pollVariables() { + const visibleVarKeys = getVisibleVariableKeys() // from scroll position + const protocolVersion = useStore.getState().debugProtocolVersion + const indexes = useStore.getState().debugVariableIndexes + + if (protocolVersion === 2) { + // Collect DebugVarRef objects for visible variables + const refs: DebugVarRef[] = visibleVarKeys + .map(key => indexes.get(key)) + .filter((ref): ref is DebugVarRef => ref !== undefined && typeof ref !== 'number') + + const result = await debuggerPort.getVariablesList(refs) + // Update variable values in store... + + } else { + // Legacy v1: flat indices + const flatIndexes: number[] = visibleVarKeys + .map(key => indexes.get(key)) + .filter((idx): idx is number => typeof idx === 'number') + + const result = await debuggerPort.getVariablesList( + flatIndexes.map(idx => ({ programIdx: 0, varIdx: idx })), + ) + // Update variable values in store... + } +} +``` + +## Step 5.8: Update Debugger Adapter + +**File to modify**: `src/middleware/adapters/editor/debugger-adapter.ts` + +The adapter translates port calls into IPC bridge calls: + +```typescript +async getVariablesList(refs: DebugVarRef[]): Promise { + // Encode refs into the format expected by the main process Modbus client + return await window.bridge.debuggerGetVariablesList(refs) +} + +async setVariable(ref: DebugVarRef, force: boolean, valueBuffer?: Uint8Array): Promise { + return await window.bridge.debuggerSetVariable(ref, force, valueBuffer) +} + +async readDebugMap(projectPath: string, boardTarget: string): Promise { + const result = await window.bridge.debuggerReadDebugMap(projectPath, boardTarget) + if (!result.success || !result.content) return null + return parseDebugMapV2(result.content) +} +``` + +## Step 5.9: Update Variable Force Dialog + +The force variable dialog needs to work with `DebugVarRef` instead of flat indices: + +```typescript +// When user clicks "Force Variable" on a variable in the tree: +async function handleForceVariable(varKey: string, value: Uint8Array) { + const ref = debugVariableIndexes.get(varKey) + if (!ref || typeof ref === 'number') { + // v1 legacy path + await debuggerPort.setVariable({ programIdx: 0, varIdx: ref as number }, true, value) + } else { + // v2 hierarchical path + await debuggerPort.setVariable(ref, true, value) + } +} +``` + +## Design Notes + +### Lazy Array Expansion + +In the current system, arrays are pre-expanded in `debug.c`, so the variable tree shows all +elements immediately. With the new system, arrays appear as a single node. When expanded: + +1. `expandArrayNode()` generates child nodes with `elementIdx` in their `DebugVarRef` +2. The polling hook requests values for visible child nodes +3. Only visible elements are fetched (windowed rendering) + +For a 10,000-element array, this means reading ~20-50 elements at a time (visible in the scroll +viewport) instead of all 10,000. + +### Backward Compatibility + +The v1 path is preserved for: +- MatIEC-compiled boards (compiler_backend: "matiec" in hals.json) +- Runtime v3 targets +- Runtime v4 targets that haven't been updated to Phase 8 + +The protocol version detection is automatic based on which debug file exists. + +### Struct/FB Instance Deep Access + +For struct fields and FB instance variables: +- The debug-map.json lists fields under the parent variable +- The tree builder creates nested nodes +- The debug protocol accesses fields via the parent var_idx + field offset +- The exact mechanism depends on STruC++ struct memory layout (IECVar-wrapped fields) + +## Testing Strategy + +1. **Variable tree building**: Parse a debug-map.json with scalars, arrays, and structs + - Verify tree has correct hierarchy + - Verify arrays are single nodes (not expanded) + - Verify expandArrayNode generates correct children + +2. **Protocol detection**: Test with both debug.c and debug-map.json present/absent + - Only debug.c -> v1 + - Only debug-map.json -> v2 + - Both present -> v2 takes priority + +3. **Variable polling**: Connect to simulator, verify values update in real time + - Scalar variables show correct values + - Array elements show correct values when expanded + - Forced variables show forced value (not hardware value) + +4. **Force/unforce**: Force a variable, verify it stays forced through cycles + +5. **Regression**: All existing debug tests pass for v1 targets + +## Files Created/Modified + +| File | Action | +|------|--------| +| `src/frontend/utils/debug-parser.ts` | Modified -- add DebugMapV2 types and parser | +| `src/frontend/utils/debugger-session.ts` | Modified -- add buildVariableRefMapV2() | +| `src/frontend/utils/debug-tree-builder.ts` | Modified -- add buildDebugTreeV2(), expandArrayNode() | +| `src/middleware/shared/ports/debugger-port.ts` | Modified -- DebugVarRef, updated signatures | +| `src/frontend/hooks/useDebugSession.ts` | Modified -- protocol detection | +| `src/frontend/hooks/useDebugPolling.ts` | Modified -- v2 polling path | +| `src/frontend/store/slices/workspace/types.ts` | Modified -- debugProtocolVersion | +| `src/frontend/store/slices/workspace/slice.ts` | Modified -- new actions | +| `src/middleware/adapters/editor/debugger-adapter.ts` | Modified -- v2 transport | diff --git a/docs/strucpp-migration/06-runtime-v4-so-interface.md b/docs/strucpp-migration/06-runtime-v4-so-interface.md new file mode 100644 index 000000000..eafbca55f --- /dev/null +++ b/docs/strucpp-migration/06-runtime-v4-so-interface.md @@ -0,0 +1,415 @@ +# Phase 6: Runtime v4 .so Interface + +## Goal + +Generate a C++ shared library (`.so`) that exports the same C-linkage symbols the existing +OpenPLC Runtime v4 expects via `dlsym()`, but is implemented using STruC++ generated code. +This allows the runtime to load STruC++ programs without any modification to the runtime's +core C code (initially). + +## Prerequisites + +- Phase 1 (STruC++ compiler wrapper) +- Runtime v4 codebase at `~/Documents/Code/openplc-runtime` + +## Current Runtime Symbol Interface + +The runtime's `image_tables.c:symbols_init()` resolves these symbols from the loaded `.so`: + +```c +// Program lifecycle +void (*ext_config_init__)(void); +void (*ext_config_run__)(unsigned long); +void (*ext_glueVars)(void); +void (*ext_updateTime)(void); +unsigned long long *ext_common_ticktime__; + +// Buffer binding (v4 extended) +void (*ext_setBufferPointers_v4)( + IEC_BOOL *[][8], IEC_BOOL *[][8], // bool_input, bool_output + IEC_BYTE *[], IEC_BYTE *[], // byte_input, byte_output + IEC_UINT *[], IEC_UINT *[], // int_input, int_output + IEC_UDINT *[], IEC_UDINT *[], // dint_input, dint_output + IEC_ULINT *[], IEC_ULINT *[], // lint_input, lint_output + IEC_UINT *[], IEC_UDINT *[], // int_memory, dint_memory + IEC_ULINT *[], // lint_memory + IEC_BOOL *[][8] // bool_memory +); + +// Debug interface +uint16_t (*ext_get_var_count)(void); +size_t (*ext_get_var_size)(size_t); +void *(*ext_get_var_addr)(size_t); +void (*ext_set_trace)(size_t, bool, void*); +void (*ext_trace_reset)(void); +void (*ext_set_endianness)(uint8_t); +char *ext_plc_program_md5; +``` + +## Step 6.1: Create v4 Compatibility Code Generator + +**New file**: `src/backend/shared/utils/PLC/generate-v4-compat.ts` + +This module generates `v4_compat.cpp` -- a C++ file that wraps STruC++ generated code with +the C-linkage symbols the runtime expects. + +### Public API + +```typescript +export interface V4CompatInput { + /** Configuration class name from STruC++ (e.g., "Config0") */ + configurationName: string + /** Task intervals for GCD scheduler */ + taskIntervals: TaskInterval[] + /** Variable descriptors for debug interface */ + variableDescriptors: ProgramVarDescriptor[] + /** MD5 hash of program.st */ + md5Hash: string +} + +export function generateV4Compat(input: V4CompatInput): string +``` + +### Generated v4_compat.cpp Structure + +```cpp +// v4_compat.cpp +// C-linkage compatibility shim for OpenPLC Runtime v4 +// Generated by openplc-editor -- do not edit manually + +#include "generated.hpp" +#include +#include + +using namespace strucpp; + +// ============================================================================= +// Configuration singleton +// ============================================================================= + +static Configuration_Config0 g_config; + +// ============================================================================= +// Buffer pointer storage (set by runtime via setBufferPointers_v4) +// ============================================================================= + +#define BUFFER_SIZE 1024 + +static IEC_BOOL (*saved_bool_input)[8] = nullptr; +static IEC_BOOL (*saved_bool_output)[8] = nullptr; +static IEC_BYTE *saved_byte_input = nullptr; +static IEC_BYTE *saved_byte_output = nullptr; +static IEC_UINT *saved_int_input = nullptr; +static IEC_UINT *saved_int_output = nullptr; +static IEC_UDINT *saved_dint_input = nullptr; +static IEC_UDINT *saved_dint_output = nullptr; +static IEC_ULINT *saved_lint_input = nullptr; +static IEC_ULINT *saved_lint_output = nullptr; +static IEC_UINT *saved_int_memory = nullptr; +static IEC_UDINT *saved_dint_memory = nullptr; +static IEC_ULINT *saved_lint_memory = nullptr; +static IEC_BOOL (*saved_bool_memory)[8] = nullptr; + +// ============================================================================= +// C-linkage exports: Program lifecycle +// ============================================================================= + +extern "C" void config_init__(void) { + // Configuration constructor already ran (static initialization) + // Explicit init call for any post-construction setup +} + +extern "C" void config_run__(unsigned long tick) { + // GCD-based multi-task scheduler (same as Arduino version) + static const uint32_t task_divisors[] = { /* generated per-project */ }; + static ProgramBase* task_programs[] = { /* generated per-project */ }; + static const size_t TASK_COUNT = /* N */; + + for (size_t i = 0; i < TASK_COUNT; ++i) { + if (task_divisors[i] == 0 || (tick % task_divisors[i]) == 0) { + task_programs[i]->run(); + } + } +} + +extern "C" unsigned long long common_ticktime__ = /* GCD nanoseconds */; + +extern "C" void updateTime(void) { + // Same as Arduino: increment __CURRENT_TIME by common_ticktime__ +} + +// ============================================================================= +// C-linkage exports: Buffer binding +// ============================================================================= + +extern "C" void setBufferPointers_v4( + IEC_BOOL *bi[][8], IEC_BOOL *bo[][8], + IEC_BYTE *byi[], IEC_BYTE *byo[], + IEC_UINT *ii[], IEC_UINT *io[], + IEC_UDINT *di[], IEC_UDINT *do_[], + IEC_ULINT *li[], IEC_ULINT *lo[], + IEC_UINT *im[], IEC_UDINT *dm[], + IEC_ULINT *lm[], + IEC_BOOL *bm[][8] +) { + // Store runtime buffer pointers for glueVars to use + saved_bool_input = (IEC_BOOL(*)[8])bi; + saved_bool_output = (IEC_BOOL(*)[8])bo; + // ... store all pointers +} + +extern "C" void glueVars(void) { + // Walk LocatedVar[] and bind to runtime's image table buffers + // Same logic as Arduino strucpp_bind_located_vars() but uses saved_* pointers + // instead of the openplc.h global arrays + + for (uint32_t i = 0; i < locatedVarsCount; ++i) { + LocatedVar& lv = locatedVars[i]; + if (!lv.pointer) continue; + + switch (lv.area) { + case LocatedArea::Input: + switch (lv.size) { + case LocatedSize::Bit: + saved_bool_input[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; + break; + case LocatedSize::Word: + saved_int_input[lv.byte_index] = (IEC_UINT*)lv.pointer; + break; + case LocatedSize::DWord: + saved_dint_input[lv.byte_index] = (IEC_UDINT*)lv.pointer; + break; + case LocatedSize::LWord: + saved_lint_input[lv.byte_index] = (IEC_ULINT*)lv.pointer; + break; + } + break; + case LocatedArea::Output: + // ... symmetric + break; + case LocatedArea::Memory: + // ... int_memory, dint_memory, lint_memory, bool_memory + break; + } + } +} + +// ============================================================================= +// C-linkage exports: Debug interface (flat-index compatibility) +// ============================================================================= + +// Pre-computed flat-to-hierarchical index table +// Maps flat index -> (program_idx, var_idx) without array expansion +struct FlatVarEntry { + uint8_t prog_idx; + uint16_t var_idx; + uint8_t size; + void* ptr; // raw_ptr() for reading + void (*get_fn)(void*); // type-erased get() for forced-safe reading + void (*force_fn)(bool, void*); // type-erased force/unforce +}; + +static const FlatVarEntry flat_var_table[] = { + // Generated per-project: one entry per variable (NOT per array element) + { 0, 0, 2, &g_config.instance0.counter, + [](void* d) { *(int16_t*)d = g_config.instance0.counter.get(); }, + [](bool f, void* v) { f ? g_config.instance0.counter.force(*(int16_t*)v) + : g_config.instance0.counter.unforce(); } + }, + // ... +}; + +static const uint16_t FLAT_VAR_COUNT = /* total vars across all programs */; + +extern "C" uint16_t get_var_count(void) { + return FLAT_VAR_COUNT; +} + +extern "C" size_t get_var_size(size_t idx) { + if (idx >= FLAT_VAR_COUNT) return 0; + return flat_var_table[idx].size; +} + +extern "C" void* get_var_addr(size_t idx) { + if (idx >= FLAT_VAR_COUNT) return nullptr; + return flat_var_table[idx].ptr; +} + +extern "C" void set_trace(size_t idx, bool forced, void* val) { + if (idx >= FLAT_VAR_COUNT) return; + if (flat_var_table[idx].force_fn) { + flat_var_table[idx].force_fn(forced, val); + } +} + +extern "C" void trace_reset(void) { + for (uint16_t i = 0; i < FLAT_VAR_COUNT; ++i) { + if (flat_var_table[i].force_fn) { + flat_var_table[i].force_fn(false, nullptr); + } + } +} + +extern "C" void set_endianness(uint8_t value) { + // STruC++ uses native endianness; this is a no-op for local debugging + // For remote debugging, endianness is handled at the protocol level + (void)value; +} + +extern "C" char plc_program_md5[] = "/* generated MD5 hash */"; +``` + +### Key Design: Flat-to-Hierarchical Index Table + +The runtime's `debug_handler.c` uses flat indices (`get_var_addr(idx)`). The `flat_var_table[]` +provides backward compatibility: + +- One entry per variable (NOT per array element) -- the scalability fix +- Flat index = sequential numbering across all program variables +- Program 0 vars: indices 0..N0-1 +- Program 1 vars: indices N0..N0+N1-1 +- etc. + +This is smaller than the MatIEC debug_vars[] because arrays are not expanded. But it still +provides the flat index interface that `debug_handler.c` expects. + +## Step 6.2: Update compile.sh + +**File to modify**: `openplc-runtime/scripts/compile.sh` + +The compilation script needs to handle C++ files: + +```bash +#!/bin/bash + +# Detect if STruC++ files exist +if [ -f "core/generated/generated.cpp" ]; then + echo "Compiling STruC++ generated code..." + + # Compile generated.cpp + g++ -std=c++17 -w -O3 -fPIC \ + -I "core/generated" \ + -c "core/generated/generated.cpp" \ + -o "$BUILD_DIR/generated.o" + + # Compile v4_compat.cpp + g++ -std=c++17 -w -O3 -fPIC \ + -I "core/generated" \ + -c "core/generated/v4_compat.cpp" \ + -o "$BUILD_DIR/v4_compat.o" + + # Compile c_blocks_code.cpp (unchanged) + g++ -std=c++17 -w -O3 -fPIC \ + -I "core/generated" \ + -c "core/generated/c_blocks_code.cpp" \ + -o "$BUILD_DIR/c_blocks_code.o" + + # Link into shared library + g++ -std=c++17 -w -O3 -fPIC -shared \ + -o "$BUILD_DIR/new_libplc.so" \ + "$BUILD_DIR/generated.o" \ + "$BUILD_DIR/v4_compat.o" \ + "$BUILD_DIR/c_blocks_code.o" \ + -lpthread + +else + echo "Compiling MatIEC generated code..." + # ... existing MatIEC compilation (unchanged) +fi +``` + +## Step 6.3: Update Editor Upload Path + +**File to modify**: `src/backend/editor/compiler/compiler-module.ts` + +When compiling for Runtime v4 with STruC++, the uploaded zip contains different files: + +### Old zip contents (MatIEC): +``` +Config0.c, Config0.h, Res0.c, POUS.c, POUS.h +debug.c, glueVars.c, LOCATED_VARIABLES.h +c_blocks.h, c_blocks_code.cpp +lib/ (MatIEC headers) +``` + +### New zip contents (STruC++): +``` +generated.cpp, generated.hpp +v4_compat.cpp +c_blocks.h, c_blocks_code.cpp +iec_var.hpp, iec_types.hpp, iec_located.hpp (STruC++ runtime headers) +... (other STruC++ runtime headers) +``` + +The `handleUploadToRuntime` method is updated to package the correct files based on +`compiler_backend`. + +## Step 6.4: Configuration File Generation + +The editor also generates configuration files for Runtime v4 upload: +- `conf/modbus_slaves.json` +- `conf/modbus_masters.json` +- `conf/s7comm.json` +- `conf/opcua.json` + +These are unchanged -- they're independent of the compiler backend. + +## Design Notes + +### Why C-Linkage Compatibility (Not Native C++ Interface) + +The runtime's core code (`plc_state_manager.c`, `debug_handler.c`, `image_tables.c`) is +written in C. Changing these to call C++ methods would require significant refactoring. +The C-linkage shim provides a clean adapter pattern: + +``` +Runtime (C) --dlsym--> C-linkage symbols --calls--> STruC++ C++ classes +``` + +This allows the runtime to work with both MatIEC (C) and STruC++ (C++) programs without +any conditional compilation or runtime detection in the C code. + +### Debug Variable Count Reduction + +With MatIEC: `get_var_count()` returns the expanded count (30,000+ for large projects). +With STruC++: `get_var_count()` returns the un-expanded count (maybe 500 for the same project). + +The runtime's `debug_handler.c` uses `get_var_count()` to validate index bounds. Since the +new count is smaller, all existing bounds checks remain valid. + +The editor knows the correct count from `debug-map.json` and only requests valid indices. + +### Thread Safety of Static Configuration + +The `g_config` static instance is created during `.so` loading (before `config_run__` is +called). All program instances within it are initialized at construction time. The runtime +calls `config_init__` from the PLC cycle thread, which is single-threaded at that point. + +## Testing Strategy + +1. **Symbol resolution**: Load the generated `.so` with `dlopen()` and verify all expected + symbols are present via `dlsym()` + +2. **Simple program**: Upload a counter program to Runtime v4 + - Verify PLC starts running (status API returns RUNNING) + - Verify scan cycle timing is correct + +3. **Variable access**: Connect debugger to Runtime v4 + - Read variables via debug handler + - Verify correct values returned + - Force a variable, verify persistence + +4. **Buffer binding**: Verify located variables are correctly bound to image tables + - Write to a Modbus register + - Verify the PLC program reads the correct value + +5. **Backward compatibility**: Upload a MatIEC-compiled program + - Verify runtime still loads and runs it correctly + +## Files Created/Modified + +| File | Action | +|------|--------| +| `src/backend/shared/utils/PLC/generate-v4-compat.ts` | **New** -- v4 compatibility generator | +| `openplc-runtime/scripts/compile.sh` | Modified -- C++17 compilation support | +| `src/backend/editor/compiler/compiler-module.ts` | Modified -- v4 upload path | diff --git a/docs/strucpp-migration/07-runtime-v4-thread-per-task.md b/docs/strucpp-migration/07-runtime-v4-thread-per-task.md new file mode 100644 index 000000000..f1d0bd101 --- /dev/null +++ b/docs/strucpp-migration/07-runtime-v4-thread-per-task.md @@ -0,0 +1,420 @@ +# Phase 7: Thread-Per-Task Model for Runtime v4 + +## Goal + +Replace the single-threaded round-robin task execution in Runtime v4 with a thread-per-task +model. Each PLC task gets its own POSIX thread with SCHED_FIFO real-time priority matching the +task's declared priority. This is only for Runtime v4 (Linux); Arduino retains round-robin. + +## Prerequisites + +- Phase 6 (v4_compat.cpp with C-linkage interface) +- Runtime v4 codebase at `~/Documents/Code/openplc-runtime` + +## Current Architecture + +The runtime currently has a single PLC cycle thread (`plc_cycle_thread` in `plc_state_manager.c`): + +```c +// Current: single thread runs everything +while (plc_state == PLC_STATE_RUNNING) { + scan_cycle_time_start(); + plugin_mutex_take(&buffer_mutex); + journal_apply_and_clear(); + plugin_driver_cycle_start(plugin_driver); + ext_config_run__(tick__++); // Runs ALL tasks sequentially + ext_updateTime(); + plugin_driver_cycle_end(plugin_driver); + plugin_mutex_give(&buffer_mutex); + scan_cycle_time_end(); + sleep_until(&timer_start); +} +``` + +This works but has limitations: +- All tasks share the same cycle time (common_ticktime__, which is the GCD) +- Fast tasks are delayed by slow tasks (no preemption) +- No priority differentiation between tasks + +## New Architecture + +Each task gets its own thread: + +``` +Thread 0 (Task "fast", T#10ms, Priority 10): + loop: + mutex_take(buffer_mutex) + run_task(0) // calls program0.run() + mutex_give(buffer_mutex) + sleep_until(next_10ms) + +Thread 1 (Task "slow", T#100ms, Priority 5): + loop: + mutex_take(buffer_mutex) + run_task(1) // calls program1.run() + mutex_give(buffer_mutex) + sleep_until(next_100ms) +``` + +## Step 7.1: New .so Symbols + +**File to modify**: `src/backend/shared/utils/PLC/generate-v4-compat.ts` (from Phase 6) + +Add new optional symbols to `v4_compat.cpp`: + +```cpp +// ============================================================================= +// Optional per-task interface (for thread-per-task runtime) +// ============================================================================= + +extern "C" size_t strucpp_get_task_count(void) { + return TASK_COUNT; // number of tasks in CONFIGURATION +} + +extern "C" int64_t strucpp_get_task_interval_ns(size_t task_idx) { + if (task_idx >= TASK_COUNT) return 0; + static const int64_t intervals[] = { + 10000000LL, // Task 0: T#10ms + 100000000LL, // Task 1: T#100ms + }; + return intervals[task_idx]; +} + +extern "C" int strucpp_get_task_priority(size_t task_idx) { + if (task_idx >= TASK_COUNT) return 0; + static const int priorities[] = { + 10, // Task 0 priority + 5, // Task 1 priority + }; + return priorities[task_idx]; +} + +extern "C" void strucpp_run_task(size_t task_idx) { + if (task_idx >= TASK_COUNT) return; + task_programs[task_idx]->run(); +} + +// Signal that this .so supports per-task threading +extern "C" const uint32_t strucpp_capabilities = 0x0001; // bit 0 = per-task +``` + +## Step 7.2: Runtime Per-Task Thread Spawning + +**File to modify**: `openplc-runtime/core/src/plc_app/plc_state_manager.c` + +### Symbol Resolution + +Add new optional symbol resolution in `symbols_init()` (or a new function): + +```c +// Optional STruC++ per-task symbols +static size_t (*ext_strucpp_get_task_count)(void) = NULL; +static int64_t (*ext_strucpp_get_task_interval_ns)(size_t) = NULL; +static int (*ext_strucpp_get_task_priority)(size_t) = NULL; +static void (*ext_strucpp_run_task)(size_t) = NULL; + +void symbols_init_strucpp(PluginManager* pm) { + ext_strucpp_get_task_count = plugin_manager_get_func(pm, ..., "strucpp_get_task_count"); + ext_strucpp_get_task_interval_ns = plugin_manager_get_func(pm, ..., "strucpp_get_task_interval_ns"); + ext_strucpp_get_task_priority = plugin_manager_get_func(pm, ..., "strucpp_get_task_priority"); + ext_strucpp_run_task = plugin_manager_get_func(pm, ..., "strucpp_run_task"); +} + +bool has_strucpp_per_task(void) { + return ext_strucpp_get_task_count != NULL + && ext_strucpp_get_task_interval_ns != NULL + && ext_strucpp_get_task_priority != NULL + && ext_strucpp_run_task != NULL; +} +``` + +### Thread Creation + +In `load_plc_program()`, after symbol resolution: + +```c +void load_plc_program(PluginManager* pm) { + if (!plugin_manager_load(pm)) { + log_error("Failed to load PLC program"); + return; + } + + plc_state = PLC_STATE_INIT; + + // Standard initialization + symbols_init(pm); + symbols_init_strucpp(pm); // Try to resolve optional symbols + + ext_config_init__(); + ext_glueVars(); + + plugin_mutex_take(&buffer_mutex); + image_tables_fill_null_pointers(); + plugin_mutex_give(&buffer_mutex); + + if (has_strucpp_per_task()) { + // NEW: Per-task threading model + size_t task_count = ext_strucpp_get_task_count(); + log_info("STruC++ per-task mode: %zu tasks", task_count); + + plc_task_threads = calloc(task_count, sizeof(pthread_t)); + plc_task_count = task_count; + + for (size_t i = 0; i < task_count; i++) { + TaskThreadArgs* args = malloc(sizeof(TaskThreadArgs)); + args->task_idx = i; + args->interval_ns = ext_strucpp_get_task_interval_ns(i); + args->priority = ext_strucpp_get_task_priority(i); + args->plugin_driver = plugin_driver; + + pthread_create(&plc_task_threads[i], NULL, plc_task_thread, args); + } + } else { + // LEGACY: Single-thread model (MatIEC or single-task STruC++) + pthread_create(&plc_thread, NULL, plc_cycle_thread, pm); + } +} +``` + +### Per-Task Thread Function + +```c +typedef struct { + size_t task_idx; + int64_t interval_ns; + int priority; + PluginDriver* plugin_driver; +} TaskThreadArgs; + +static void* plc_task_thread(void* arg) { + TaskThreadArgs* task = (TaskThreadArgs*)arg; + + // Record thread ID for crash handler + log_info("Task %zu thread started (interval: %lld ns, priority: %d)", + task->task_idx, task->interval_ns, task->priority); + + // Set real-time priority + struct sched_param param; + param.sched_priority = task->priority; + if (pthread_setschedparam(pthread_self(), SCHED_FIFO, ¶m) != 0) { + log_warn("Could not set SCHED_FIFO priority %d for task %zu", + task->priority, task->task_idx); + } + + // Lock memory to prevent page faults + lock_memory(); + + // Install crash signal handlers (same as plc_cycle_thread) + install_crash_handlers(); + + // Initialize timing + struct timespec next_wakeup; + clock_gettime(CLOCK_MONOTONIC, &next_wakeup); + + uint32_t local_tick = 0; + volatile int holding_mutex = 0; + + // Set jump point for crash recovery + if (sigsetjmp(crash_jmp_buf, 1) != 0) { + // Crash recovery + if (holding_mutex) { + holding_mutex = 0; + plugin_mutex_give(&task->plugin_driver->buffer_mutex); + } + log_error("Task %zu crashed (signal %d), entering ERROR state", + task->task_idx, crash_sig); + plc_state = PLC_STATE_ERROR; + free(task); + return NULL; + } + + // Main execution loop + while (plc_state == PLC_STATE_RUNNING) { + // Acquire mutex (priority-inheriting) + holding_mutex = 1; + plugin_mutex_take(&task->plugin_driver->buffer_mutex); + + // Execute this task's program(s) + ext_strucpp_run_task(task->task_idx); + + // Update time if this is the highest-priority (first) task + if (task->task_idx == 0) { + ext_updateTime(); + atomic_store(&plc_heartbeat, time(NULL)); + } + + // Release mutex + plugin_mutex_give(&task->plugin_driver->buffer_mutex); + holding_mutex = 0; + + // Sleep until next period + next_wakeup.tv_nsec += task->interval_ns; + while (next_wakeup.tv_nsec >= 1000000000LL) { + next_wakeup.tv_nsec -= 1000000000LL; + next_wakeup.tv_sec++; + } + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &next_wakeup, NULL); + + local_tick++; + } + + log_info("Task %zu thread stopped after %u ticks", task->task_idx, local_tick); + free(task); + return NULL; +} +``` + +### Thread Cleanup on Stop + +```c +void stop_plc_program(void) { + plc_state = PLC_STATE_STOPPING; + + if (plc_task_count > 0) { + // Per-task model: join all task threads + for (size_t i = 0; i < plc_task_count; i++) { + pthread_join(plc_task_threads[i], NULL); + } + free(plc_task_threads); + plc_task_threads = NULL; + plc_task_count = 0; + } else { + // Single-thread model: join the one thread + pthread_join(plc_thread, NULL); + } + + plc_state = PLC_STATE_STOPPED; +} +``` + +## Step 7.3: Plugin Integration + +Plugins (`plugin_driver_cycle_start`, `plugin_driver_cycle_end`) currently run inside the +single PLC cycle thread. With per-task threads, we need to decide when plugins run: + +**Option A** (recommended): Plugins run in the highest-priority task's thread only. +- `cycle_start` is called before the first task's `run()` +- `cycle_end` is called after the first task's `run()` +- Other tasks only acquire the mutex, run their program, and release + +**Option B**: Plugins run in a separate dedicated thread. +- More complex, requires a third mutex coordination point + +Going with Option A: + +```c +// In plc_task_thread, when task->task_idx == 0: +plugin_mutex_take(&task->plugin_driver->buffer_mutex); + +if (task->task_idx == 0) { + journal_apply_and_clear(); + plugin_driver_cycle_start(task->plugin_driver); +} + +ext_strucpp_run_task(task->task_idx); + +if (task->task_idx == 0) { + ext_updateTime(); + plugin_driver_cycle_end(task->plugin_driver); + atomic_store(&plc_heartbeat, time(NULL)); +} + +plugin_mutex_give(&task->plugin_driver->buffer_mutex); +``` + +## Global Variable Synchronization + +### The Problem + +Different tasks may share global variables declared in `VAR_GLOBAL` of the CONFIGURATION. +With per-task threads, concurrent access to these variables must be synchronized. + +### The Solution: buffer_mutex + +The existing `buffer_mutex` (with `PTHREAD_PRIO_INHERIT`) already provides synchronization: + +1. Each task thread acquires `buffer_mutex` before running its program +2. Tasks execute one at a time (mutex serializes execution) +3. Between executions, tasks sleep (no mutex held) + +This means tasks don't truly run in parallel during their computation phase. The parallelism +comes from: +- **Different sleep periods**: A 10ms task wakes up 10x more often than a 100ms task +- **Independent timing**: Each task has its own clock, not tied to a GCD base tick +- **Priority scheduling**: SCHED_FIFO ensures the highest-priority waiting task runs first + +For most PLC applications, task execution time is much smaller than the cycle period (e.g., +1ms execution in a 10ms cycle). The mutex serialization adds negligible overhead. + +### Future Optimization: Fine-Grained Locking + +For applications where true parallel execution is needed: +1. Each global variable gets its own read-write lock +2. Tasks acquire read locks for variables they read, write locks for variables they write +3. Lock ordering prevents deadlocks + +This is a significant optimization that can be added later without changing the .so interface. + +## Design Notes + +### SCHED_FIFO Priority Mapping + +IEC 61131-3 TASK priority values are integers where higher = more important. Linux SCHED_FIFO +priorities are also integers where higher = more important (range 1-99). The mapping is direct: + +```c +int linux_priority = task->priority; +if (linux_priority < 1) linux_priority = 1; +if (linux_priority > 99) linux_priority = 99; +``` + +### Watchdog Integration + +Only the highest-priority task (task 0) updates the `plc_heartbeat` atomic variable. The +watchdog monitors this to detect PLC stalls. If any task thread crashes, the crash handler +sets `plc_state = PLC_STATE_ERROR`, causing all task threads to exit their loops. + +### Backward Compatibility + +The `has_strucpp_per_task()` check ensures: +- MatIEC .so files (no `strucpp_get_task_count` symbol): use single-thread model +- STruC++ single-task .so files: use single-thread model (1 task, no benefit from threading) +- STruC++ multi-task .so files: use per-task threading + +The single-thread model remains the default and is fully preserved. + +## Testing Strategy + +1. **Dual-task test**: Two tasks at T#10ms and T#100ms + - Verify both threads are created + - Verify each runs at its configured interval (within 10% tolerance) + - Verify no deadlock after 10,000 cycles + +2. **Priority test**: High-priority task should preempt low-priority task's sleep + - Create tasks with priorities 10 and 5 + - Verify SCHED_FIFO is set (check `/proc/[pid]/sched`) + +3. **Global variable test**: Two tasks sharing a global variable + - Task 1 writes a counter + - Task 2 reads the counter + - Verify no torn reads (counter is always a valid value) + +4. **Crash recovery**: Introduce a deliberate SIGFPE in task 1 + - Verify task 1 thread catches the signal + - Verify PLC transitions to ERROR state + - Verify task 0 thread also stops + +5. **Single-task fallback**: Upload a single-task program + - Verify single-thread model is used (no per-task threads) + +6. **MatIEC fallback**: Upload a MatIEC-compiled program + - Verify single-thread model is used + +## Files Created/Modified + +| File | Action | +|------|--------| +| `src/backend/shared/utils/PLC/generate-v4-compat.ts` | Modified -- add per-task symbols | +| `openplc-runtime/core/src/plc_app/plc_state_manager.c` | Modified -- per-task thread spawning | +| `openplc-runtime/core/src/plc_app/plc_state_manager.h` | Modified -- new data structures | +| `openplc-runtime/core/src/plc_app/image_tables.c` | Modified -- resolve new symbols | diff --git a/docs/strucpp-migration/08-runtime-v4-debug-handler.md b/docs/strucpp-migration/08-runtime-v4-debug-handler.md new file mode 100644 index 000000000..8719ea253 --- /dev/null +++ b/docs/strucpp-migration/08-runtime-v4-debug-handler.md @@ -0,0 +1,363 @@ +# Phase 8: Runtime v4 Native Hierarchical Debug + +## Goal + +Update the Runtime v4's `debug_handler.c` to natively use hierarchical `(program_idx, var_idx)` +addressing when communicating with the editor, eliminating the flat-index lookup table from +Phase 6. This is the final cleanup phase -- it can be done after Phase 6 is stable. + +## Prerequisites + +- Phase 6 (v4_compat.cpp with working C-linkage debug interface) +- Phase 5 (editor frontend supporting protocol v2) + +## Current State After Phase 6 + +Phase 6 provides backward-compatible debug access through `flat_var_table[]`: + +``` +Editor (v2 protocol) <--> Editor adapter (converts v2 -> v1) <--> Runtime debug_handler (v1) + | + flat_var_table (v4_compat.cpp) + | + STruC++ IECVar variables +``` + +This works but has an unnecessary translation layer. Phase 8 removes it: + +``` +Editor (v2 protocol) <--> Runtime debug_handler (v2) <--> STruC++ IECVar variables +``` + +## Step 8.1: New .so Debug Symbols + +**File to modify**: `src/backend/shared/utils/PLC/generate-v4-compat.ts` + +Add hierarchical debug symbols to `v4_compat.cpp`: + +```cpp +// ============================================================================= +// Hierarchical debug interface (native v2 protocol) +// ============================================================================= + +extern "C" uint8_t strucpp_get_program_count(void) { + return PROGRAM_COUNT; +} + +extern "C" uint16_t strucpp_get_var_count_for_program(uint8_t prog_idx) { + if (prog_idx >= PROGRAM_COUNT) return 0; + return program_var_counts[prog_idx]; +} + +extern "C" uint8_t strucpp_get_var_size_h(uint8_t prog_idx, uint16_t var_idx) { + if (prog_idx >= PROGRAM_COUNT) return 0; + if (var_idx >= program_var_counts[prog_idx]) return 0; + return debug_sizes[prog_idx][var_idx]; +} + +extern "C" bool strucpp_get_var_value(uint8_t prog_idx, uint16_t var_idx, void* dest) { + if (prog_idx >= PROGRAM_COUNT) return false; + if (var_idx >= program_var_counts[prog_idx]) return false; + + debug_get_fn fn = debug_get_fns[prog_idx][var_idx]; + if (fn) { + fn(dest); + return true; + } + // Array: copy first element + memcpy(dest, debug_ptrs[prog_idx][var_idx], debug_sizes[prog_idx][var_idx]); + return true; +} + +extern "C" bool strucpp_get_array_element(uint8_t prog_idx, uint16_t var_idx, + uint16_t elem_idx, void* dest) { + if (prog_idx >= PROGRAM_COUNT) return false; + if (var_idx >= program_var_counts[prog_idx]) return false; + uint16_t arr_size = debug_array_sizes[prog_idx][var_idx]; + if (arr_size == 0 || elem_idx >= arr_size) return false; + + uint8_t elem_size = debug_sizes[prog_idx][var_idx]; + size_t stride = elem_size * 2 + 1; // IECVar stride + uint8_t* base = (uint8_t*)debug_ptrs[prog_idx][var_idx]; + memcpy(dest, base + elem_idx * stride, elem_size); + return true; +} + +extern "C" bool strucpp_set_var_trace(uint8_t prog_idx, uint16_t var_idx, + bool forced, void* val) { + if (prog_idx >= PROGRAM_COUNT) return false; + if (var_idx >= program_var_counts[prog_idx]) return false; + + debug_force_fn fn = debug_force_fns[prog_idx][var_idx]; + if (!fn) return false; + fn(forced, val); + return true; +} + +extern "C" uint16_t strucpp_get_array_size(uint8_t prog_idx, uint16_t var_idx) { + if (prog_idx >= PROGRAM_COUNT) return 0; + if (var_idx >= program_var_counts[prog_idx]) return 0; + return debug_array_sizes[prog_idx][var_idx]; +} +``` + +## Step 8.2: Update Runtime Symbol Resolution + +**File to modify**: `openplc-runtime/core/src/plc_app/image_tables.c` + +Add optional symbol resolution for hierarchical debug: + +```c +// Optional STruC++ hierarchical debug symbols +static uint8_t (*ext_strucpp_get_program_count)(void) = NULL; +static uint16_t (*ext_strucpp_get_var_count_for_program)(uint8_t) = NULL; +static uint8_t (*ext_strucpp_get_var_size_h)(uint8_t, uint16_t) = NULL; +static bool (*ext_strucpp_get_var_value)(uint8_t, uint16_t, void*) = NULL; +static bool (*ext_strucpp_get_array_element)(uint8_t, uint16_t, uint16_t, void*) = NULL; +static bool (*ext_strucpp_set_var_trace)(uint8_t, uint16_t, bool, void*) = NULL; +static uint16_t (*ext_strucpp_get_array_size)(uint8_t, uint16_t) = NULL; + +void symbols_init_strucpp_debug(PluginManager* pm) { + *(void**)&ext_strucpp_get_program_count = + plugin_manager_get_func(pm, ..., "strucpp_get_program_count"); + *(void**)&ext_strucpp_get_var_count_for_program = + plugin_manager_get_func(pm, ..., "strucpp_get_var_count_for_program"); + *(void**)&ext_strucpp_get_var_size_h = + plugin_manager_get_func(pm, ..., "strucpp_get_var_size_h"); + *(void**)&ext_strucpp_get_var_value = + plugin_manager_get_func(pm, ..., "strucpp_get_var_value"); + *(void**)&ext_strucpp_get_array_element = + plugin_manager_get_func(pm, ..., "strucpp_get_array_element"); + *(void**)&ext_strucpp_set_var_trace = + plugin_manager_get_func(pm, ..., "strucpp_set_var_trace"); + *(void**)&ext_strucpp_get_array_size = + plugin_manager_get_func(pm, ..., "strucpp_get_array_size"); +} + +bool has_strucpp_debug(void) { + return ext_strucpp_get_program_count != NULL; +} +``` + +## Step 8.3: Update Debug Handler + +**File to modify**: `openplc-runtime/core/src/plc_app/debug_handler.c` + +The `process_debug_data()` function dispatches debug commands. Update it to detect v2 +protocol and use hierarchical symbols: + +```c +int process_debug_data(uint8_t* frame, uint16_t frame_len, uint8_t* resp, uint16_t* resp_len) { + uint8_t function_code = frame[0]; + + // Detect protocol version from request format + // v2 requests have a version byte or different structure + + if (has_strucpp_debug()) { + return process_debug_data_v2(frame, frame_len, resp, resp_len); + } else { + return process_debug_data_v1(frame, frame_len, resp, resp_len); + } +} + +// --- Protocol v2 handler --- +int process_debug_data_v2(uint8_t* frame, uint16_t frame_len, + uint8_t* resp, uint16_t* resp_len) { + uint8_t function_code = frame[0]; + + switch (function_code) { + case 0x41: // DEBUG_INFO + return debugInfoV2(resp, resp_len); + + case 0x42: // DEBUG_SET + return debugSetTraceV2(frame, frame_len, resp, resp_len); + + case 0x43: // DEBUG_GET (range) + return debugGetTraceV2(frame, frame_len, resp, resp_len); + + case 0x44: // DEBUG_GET_LIST (batch) + return debugGetTraceListV2(frame, frame_len, resp, resp_len); + + case 0x45: // DEBUG_GET_MD5 + return debugGetMd5(frame, frame_len, resp, resp_len); // Unchanged + + default: + resp[0] = function_code; + resp[1] = 0x81; // Error + *resp_len = 2; + return -1; + } +} + +// --- v2 handler implementations --- + +int debugInfoV2(uint8_t* resp, uint16_t* resp_len) { + resp[0] = 0x41; + resp[1] = 0x7E; // Success + resp[2] = 2; // Protocol version + uint8_t prog_count = ext_strucpp_get_program_count(); + resp[3] = prog_count; + + uint16_t offset = 4; + for (uint8_t p = 0; p < prog_count; p++) { + uint16_t vc = ext_strucpp_get_var_count_for_program(p); + resp[offset++] = (vc >> 8) & 0xFF; + resp[offset++] = vc & 0xFF; + } + *resp_len = offset; + return 0; +} + +int debugSetTraceV2(uint8_t* frame, uint16_t frame_len, + uint8_t* resp, uint16_t* resp_len) { + if (frame_len < 6) { + resp[0] = 0x42; + resp[1] = 0x81; + *resp_len = 2; + return -1; + } + + uint8_t prog_idx = frame[1]; + uint16_t var_idx = ((uint16_t)frame[2] << 8) | frame[3]; + bool force = frame[4] != 0; + uint8_t val_len = frame[5]; + void* val_ptr = (val_len > 0) ? &frame[6] : NULL; + + bool ok = ext_strucpp_set_var_trace(prog_idx, var_idx, force, val_ptr); + + resp[0] = 0x42; + resp[1] = ok ? 0x7E : 0x81; + *resp_len = 2; + return ok ? 0 : -1; +} + +int debugGetTraceListV2(uint8_t* frame, uint16_t frame_len, + uint8_t* resp, uint16_t* resp_len) { + uint16_t count = ((uint16_t)frame[1] << 8) | frame[2]; + + resp[0] = 0x44; + resp[1] = 0x7E; + + // Tick counter + extern uint32_t tick__; + memcpy(&resp[2], &tick__, 4); + + uint16_t data_offset = 8; // After header + uint16_t req_offset = 3; // After count field + + for (uint16_t i = 0; i < count && req_offset + 5 <= frame_len; i++) { + uint8_t prog_idx = frame[req_offset++]; + uint16_t var_idx = ((uint16_t)frame[req_offset] << 8) | frame[req_offset + 1]; + req_offset += 2; + uint16_t elem_idx = ((uint16_t)frame[req_offset] << 8) | frame[req_offset + 1]; + req_offset += 2; + + uint8_t sz = ext_strucpp_get_var_size_h(prog_idx, var_idx); + + if (elem_idx == 0xFFFF) { + // Scalar read + ext_strucpp_get_var_value(prog_idx, var_idx, &resp[data_offset]); + } else { + // Array element read + ext_strucpp_get_array_element(prog_idx, var_idx, elem_idx, &resp[data_offset]); + } + data_offset += sz; + + // Prevent buffer overflow + if (data_offset > 1400) break; // Leave room for CRC/framing + } + + // Data length + uint16_t data_len = data_offset - 8; + resp[6] = (data_len >> 8) & 0xFF; + resp[7] = data_len & 0xFF; + + *resp_len = data_offset; + return 0; +} +``` + +## Step 8.4: WebSocket Debug Transport + +The Runtime v4 also supports WebSocket-based debugging (used by the editor's WebSocket +transport). The WebSocket handler in the runtime's Python webserver (`app.py`) currently +forwards debug commands to the PLC core via the Unix socket. + +This path remains unchanged -- the debug PDU format change is transparent to the WebSocket +transport layer since it treats the PDU as opaque bytes. + +## Design Notes + +### Protocol Detection: v1 vs v2 + +The `has_strucpp_debug()` check is sufficient because: +- MatIEC .so files: don't export `strucpp_get_program_count` -> v1 +- STruC++ .so files: always export it -> v2 + +There's no ambiguity. The editor and runtime must agree on the protocol version. The editor +detects it from `debug-map.json` (v2) vs `debug.c` (v1). The runtime detects it from +symbol availability. Both detection methods are deterministic and consistent. + +### Removing the Flat-Index Table + +After Phase 8 is deployed, the `flat_var_table[]` in `v4_compat.cpp` becomes dead code for +runtime targets (it's still used by the Arduino path in Phase 6's backward-compatible debug +layer). It can be conditionally compiled: + +```cpp +#ifndef OPENPLC_RUNTIME_V4_NATIVE_DEBUG +// Flat index table for backward compatibility +static const FlatVarEntry flat_var_table[] = { ... }; +extern "C" uint16_t get_var_count(void) { ... } +// ... +#endif +``` + +The old flat-index symbols (`get_var_count`, `get_var_addr`, etc.) should still be exported +for backward compatibility with older runtimes, but they can also use the hierarchical +internal implementation to avoid maintaining two code paths. + +### Buffer Size Limits + +Modbus PDUs have a maximum size (typically 256 bytes for RTU, 65535 for TCP). The batch +read handler (`debugGetTraceListV2`) must check that the response doesn't exceed the buffer: + +```c +if (data_offset > 1400) break; // Conservative limit +``` + +The editor should limit batch request sizes accordingly (e.g., request at most 50 variables +per batch for RTU, 200+ for TCP/WebSocket). + +## Testing Strategy + +1. **v2 protocol end-to-end**: Editor (Phase 5) connects to Runtime v4 (Phase 8) + - Read scalar variables, verify correct values + - Read array elements, verify correct values + - Force a variable, verify persistence + - Unforce, verify return to computed value + +2. **Large project test**: Upload the sample project (~3,500 variables) + - Verify debugInfoV2 returns correct program/variable counts + - Verify batch reads of 50 variables complete in < 100ms + +3. **Array scalability test**: Project with ARRAY[0..9999] OF INT + - Verify only requested elements are transmitted + - Verify no memory overflow in debug handler + +4. **MatIEC fallback**: Upload a MatIEC-compiled program + - Verify v1 debug handler is used + - Verify all existing debug functionality works + +5. **Mixed editor/runtime versions**: Old editor + new runtime, new editor + old runtime + - Verify graceful fallback to the common protocol version + +## Files Created/Modified + +| File | Action | +|------|--------| +| `src/backend/shared/utils/PLC/generate-v4-compat.ts` | Modified -- add hierarchical debug symbols | +| `openplc-runtime/core/src/plc_app/debug_handler.c` | Modified -- v2 protocol handling | +| `openplc-runtime/core/src/plc_app/debug_handler.h` | Modified -- new function declarations | +| `openplc-runtime/core/src/plc_app/image_tables.c` | Modified -- resolve hierarchical symbols | +| `openplc-runtime/core/src/plc_app/image_tables.h` | Modified -- new extern declarations | From f5ca2479cc044dbc3799eaf74906acd0114a31ea Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 12:55:59 -0400 Subject: [PATCH 013/296] docs: update STruC++ dependency strategy to use binary-versions.json Replace fragile file:../strucpp approach with the same download mechanism used for matiec and xml2st: version tracked in binary-versions.json, downloaded from GitHub Releases via scripts/download-binaries.ts. Runtime headers come from the same release artifact as the compiler, ensuring strict version coupling. No local copies stored in the repo. Also documents required changes to STruC++ release workflow (add npm pack step to produce .tgz artifact). Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/strucpp-migration/00-overview.md | 9 + .../01-strucpp-compiler-integration.md | 256 +++++++++++++++++- .../02-arduino-runtime-adaptation.md | 62 +++-- .../04-editor-compiler-module.md | 16 +- .../06-runtime-v4-so-interface.md | 6 +- 5 files changed, 306 insertions(+), 43 deletions(-) diff --git a/docs/strucpp-migration/00-overview.md b/docs/strucpp-migration/00-overview.md index 0995982c0..ef62704eb 100644 --- a/docs/strucpp-migration/00-overview.md +++ b/docs/strucpp-migration/00-overview.md @@ -142,3 +142,12 @@ All Arduino boards need `-std=gnu++17` added to CXX compilation flags. This is s - ESP32: GCC 8+ (ESP-IDF toolchain) - STM32: ARM GCC 10+ (STM32duino) - RP2040: ARM GCC 10+ (Arduino Mbed OS) + +### 5. Dependency Management + +STruC++ is managed through the same `binary-versions.json` + `scripts/download-binaries.ts` +mechanism used for xml2st and matiec. The STruC++ release produces an npm tarball (`.tgz`) +that is downloaded from GitHub Releases and installed via `npm install`. This provides both +the TypeScript compiler (in `node_modules`) and the C++ runtime headers (extracted to +`resources/strucpp/`). No local copies, no `file:` dependencies, no manual syncing. Version +changes are a one-line edit to `binary-versions.json`. See Phase 1 for full details. diff --git a/docs/strucpp-migration/01-strucpp-compiler-integration.md b/docs/strucpp-migration/01-strucpp-compiler-integration.md index 641f9c6f2..4f3ca0855 100644 --- a/docs/strucpp-migration/01-strucpp-compiler-integration.md +++ b/docs/strucpp-migration/01-strucpp-compiler-integration.md @@ -8,26 +8,252 @@ is `program.st` (already generated by xml2st, unchanged). The output is C++17 co ## Prerequisites -- STruC++ repository at `~/Documents/Code/strucpp` +- STruC++ repository at `github.com/Autonomy-Logic/STruCpp` with tagged releases - STruC++ exposes a programmatic API: `compile(source: string, options?): CompileResult` - No external binary needed -- runs as TypeScript in the same Node.js process -## Step 1.1: Add STruC++ as npm Dependency +## Step 1.1: STruC++ Dependency Strategy -**File to modify**: `package.json` +STruC++ is unique compared to matiec and xml2st: it is both a **TypeScript library** (imported +via `compile()`) and a provider of **C++ runtime headers** (needed for Arduino compilation). +Both artifacts must be strictly version-coupled and managed through the same mechanism the +editor already uses for external tools. + +### Principles + +1. **No `file:` dependencies** -- fragile, breaks CI, requires local checkout +2. **No manually-copied runtime headers** -- they must travel with the compiler version +3. **Single version source of truth** -- `binary-versions.json` tracks the STruC++ version +4. **Same download mechanism** -- `scripts/download-binaries.ts` handles setup +5. **Works identically in local dev and CI/CD** + +### Release Strategy Changes in STruC++ + +**Repository**: `Autonomy-Logic/STruCpp` + +The existing release workflow already produces platform-specific archives with the standalone +binary + runtime headers + libs. We need to add **one additional artifact**: an npm-compatible +tarball (`.tgz`) that can be installed into `node_modules`. + +**New step in `.github/workflows/release.yml`** (add to one of the build jobs, e.g., linux-x64): + +```yaml + - name: Create npm tarball + run: | + npm version "$VERSION" --no-git-tag-version --allow-same-version + npm run build + npm pack + mv strucpp-*.tgz strucpp-$VERSION.tgz + + - uses: actions/upload-artifact@v4 + with: + name: strucpp-npm + path: strucpp-$VERSION.tgz +``` + +And in the `create-release` job, add it to the release assets: +```yaml + cp artifacts/strucpp-npm/strucpp-*.tgz release/ +``` + +The `.tgz` contains everything the editor needs: +- `dist/` -- compiled JavaScript (the `compile()` API) +- `src/runtime/include/` -- C++ runtime headers (`iec_var.hpp`, `iec_types.hpp`, etc.) +- `src/runtime/repl/` -- REPL headers (for future use) +- `libs/` -- standard function block libraries (`.stlib` files) +- `package.json` -- metadata including version + +This is standard npm packaging -- the `"files"` field in STruC++'s `package.json` already +includes these directories. + +### Version Tracking in OpenPLC Editor + +**File to modify**: `binary-versions.json` ```json { - "dependencies": { - "strucpp": "file:../strucpp" + "xml2st": { + "version": "v4.0.3", + "repository": "Autonomy-Logic/xml2st" + }, + "matiec": { + "version": "v4.0.11", + "repository": "Autonomy-Logic/matiec" + }, + "strucpp": { + "version": "v0.2.2", + "repository": "Autonomy-Logic/STruCpp" } } ``` -Or if published to npm: `"strucpp": "^1.0.0"`. +Version bumps are a one-line change, auditable in git, and automatically picked up by +the download script. + +### Download Script Extension + +**File to modify**: `scripts/download-binaries.ts` + +Add a `downloadStrucpp()` function following the same pattern as `downloadMatiec()`: + +```typescript +// New constant +const STRUCPP_DIR = path.join(ROOT_DIR, 'resources', 'strucpp') + +async function downloadStrucpp(tool: ToolEntry): Promise { + // The npm tarball is platform-independent (pure TypeScript + headers) + const version = tool.version.replace(/^v/, '') // "v0.2.2" -> "0.2.2" + const url = `https://github.com/${tool.repository}/releases/download/${tool.version}/strucpp-${version}.tgz` + + console.log(` Downloading strucpp ${tool.version}...`) + const tmpDir = fs.mkdtempSync(path.join(RESOURCES_DIR, '.tmp-strucpp-')) + + try { + // Download the npm tarball + const tgzPath = path.join(tmpDir, 'strucpp.tgz') + await downloadToFile(url, tgzPath) + + // Install into node_modules via npm + // This makes `import { compile } from 'strucpp'` work + execSync(`npm install "${tgzPath}" --save-exact`, { + cwd: ROOT_DIR, + stdio: 'pipe', + }) + + // Also extract runtime headers to a known location for Arduino compilation. + // These are copies FROM the npm package, NOT separate files. + // The compiler module reads them from here during build. + rmrf(STRUCPP_DIR) + const extractDir = path.join(tmpDir, 'extracted') + extractTarGz(tgzPath, extractDir) + + // npm pack creates: package/src/runtime/include/, package/libs/, etc. + const packageDir = path.join(extractDir, 'package') + fs.mkdirSync(STRUCPP_DIR, { recursive: true }) + + // Copy runtime headers + const runtimeIncludeDir = path.join(packageDir, 'src', 'runtime', 'include') + if (fs.existsSync(runtimeIncludeDir)) { + copyRecursive(runtimeIncludeDir, path.join(STRUCPP_DIR, 'runtime', 'include')) + } + + // Copy .stlib libraries + const libsDir = path.join(packageDir, 'libs') + if (fs.existsSync(libsDir)) { + copyRecursive(libsDir, path.join(STRUCPP_DIR, 'libs')) + } + + console.log(` strucpp ${tool.version} installed.`) + } finally { + rmrf(tmpDir) + } +} +``` + +The key insight: `npm install ` installs the package into `node_modules/strucpp/` which +makes `import { compile } from 'strucpp'` work. Additionally, the headers and libs are +extracted to `resources/strucpp/` for the compiler module to copy into build directories +during Arduino compilation. + +**Cache check** -- add `needsStrucpp()` following the same pattern: + +```typescript +function needsStrucpp(versions: BinaryVersions, cached: CacheMetadata | null): boolean { + // Check if node_modules/strucpp exists and matches version + const pkgJsonPath = path.join(ROOT_DIR, 'node_modules', 'strucpp', 'package.json') + if (!fs.existsSync(pkgJsonPath)) return true -Since STruC++ is TypeScript and has only one runtime dependency (`chevrotain` parser framework), -it bundles cleanly into the Electron app. No native modules, no platform-specific code. + const installed = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')) + const expected = versions.strucpp.version.replace(/^v/, '') + if (installed.version !== expected) return true + + // Check if runtime headers exist + if (!fs.existsSync(path.join(STRUCPP_DIR, 'runtime', 'include', 'iec_types.hpp'))) return true + + return false +} +``` + +**Note**: Unlike matiec (which is platform-specific), strucpp is platform-independent. The +download runs once regardless of platform/arch. + +### Git Ignore + +**File to modify**: `.gitignore` + +```gitignore +# STruC++ (downloaded by scripts/download-binaries.ts) +resources/strucpp/ +``` + +The `node_modules/strucpp` entry is already covered by the blanket `node_modules/` ignore. + +### How the Compiler Module Finds STruC++ Assets + +At compile time, the compiler module needs two things: + +1. **The TypeScript compiler** -- standard import: + ```typescript + import { compile } from 'strucpp' + ``` + This works because `npm install ` puts it in `node_modules`. + +2. **C++ runtime headers** -- resolved from the downloaded location: + ```typescript + const STRUCPP_RUNTIME_DIR = path.join(ROOT_DIR, 'resources', 'strucpp', 'runtime', 'include') + ``` + These are copied to the build directory alongside the generated `.cpp`/`.hpp` files. + +3. **Standard libraries (.stlib)** -- resolved similarly: + ```typescript + const STRUCPP_LIBS_DIR = path.join(ROOT_DIR, 'resources', 'strucpp', 'libs') + ``` + Passed to `compile()` via the `libraryPaths` option. + +### CI/CD Integration + +The CI workflow already calls `npm ci` (which triggers `postinstall` -> `download-binaries.ts`). +With the strucpp addition, the download script automatically: +1. Reads `binary-versions.json` for the strucpp version +2. Downloads the `.tgz` from GitHub Releases +3. Installs it via `npm install` +4. Extracts runtime headers to `resources/strucpp/` + +No CI workflow changes needed beyond the existing cache invalidation (already keyed on +`binary-versions.json` hash). + +### Directory Layout After Setup + +``` +openplc-editor/ +├── binary-versions.json # Tracks v0.2.2 +├── node_modules/strucpp/ # TypeScript compiler (npm install) +│ ├── dist/ # Compiled JS +│ ├── src/runtime/include/ # C++ headers (also in node_modules) +│ ├── libs/ # .stlib files (also in node_modules) +│ └── package.json # Version: 0.2.2 +├── resources/strucpp/ # Extracted for compiler module access +│ ├── runtime/include/ # C++ headers (copied to build dirs) +│ │ ├── iec_var.hpp +│ │ ├── iec_types.hpp +│ │ ├── iec_located.hpp +│ │ └── ... (19 header files) +│ └── libs/ # .stlib archives +│ ├── iec-standard-fb.stlib +│ └── oscat-basic.stlib +└── resources/bin/{platform}/{arch}/ # Other binaries (unchanged) +``` + +### Version Upgrade Workflow + +To upgrade STruC++ to a new version: + +1. Update `binary-versions.json`: change `"version": "v0.3.0"` +2. Run `npm run setup:binaries` (or just `npm run dev` which triggers it via prestart) +3. The script downloads the new `.tgz`, updates `node_modules/strucpp`, and refreshes + `resources/strucpp/` with the matching runtime headers +4. Commit `binary-versions.json` (one-line change) +5. CI picks it up automatically ## Step 1.2: Create STruC++ Compiler Wrapper @@ -399,7 +625,17 @@ All types wrapped in `IECVar` which adds: `bool forced_` (1 byte) + `T forced ## Files Created/Modified +### In openplc-editor + +| File | Action | +|------|--------| +| `binary-versions.json` | Add strucpp entry with version and repository | +| `scripts/download-binaries.ts` | Add `downloadStrucpp()` and `needsStrucpp()` | +| `.gitignore` | Add `resources/strucpp/` | +| `src/backend/shared/utils/PLC/strucpp-compiler.ts` | **New** -- STruC++ compile() wrapper | + +### In STruCpp (separate repository) + | File | Action | |------|--------| -| `package.json` | Add strucpp dependency | -| `src/backend/shared/utils/PLC/strucpp-compiler.ts` | **New** -- STruC++ wrapper | +| `.github/workflows/release.yml` | Add `npm pack` step to produce `.tgz` artifact | diff --git a/docs/strucpp-migration/02-arduino-runtime-adaptation.md b/docs/strucpp-migration/02-arduino-runtime-adaptation.md index 1463b5ff7..872b346ca 100644 --- a/docs/strucpp-migration/02-arduino-runtime-adaptation.md +++ b/docs/strucpp-migration/02-arduino-runtime-adaptation.md @@ -11,40 +11,46 @@ implementation remain unchanged -- only the glue layer between them and the PLC - Phase 1 complete (STruC++ compiler wrapper producing C++ code and metadata) - STruC++ runtime headers available for bundling -## Step 2.1: Bundle STruC++ Runtime Headers +## Step 2.1: STruC++ Runtime Headers (from downloaded release) -**New directory**: `resources/sources/StrucppRuntime/` - -Copy these header-only C++17 files from `strucpp/src/runtime/include/`: +The C++ runtime headers are **NOT** stored in this repository. They are downloaded alongside +the STruC++ compiler by `scripts/download-binaries.ts` (see Phase 1 dependency strategy) +and placed at: ``` -iec_var.hpp -- IECVar template (forcing, raw_ptr) -iec_types.hpp -- IEC type aliases (IEC_INT, IEC_BOOL, etc.) -iec_located.hpp -- LocatedVar struct, LocatedArea/LocatedSize enums -iec_traits.hpp -- Type trait helpers -iec_array.hpp -- Array1D, Array2D, Array3D templates -iec_string.hpp -- IECString (stack-allocated, fixed-size) -iec_enum.hpp -- Enum type support -iec_struct.hpp -- Struct base helpers -iec_std_lib.hpp -- IEC standard functions (ABS, MIN, MAX, etc.) -iec_time.hpp -- TIME type operations -iec_date.hpp -- DATE type operations -iec_tod.hpp -- TIME_OF_DAY operations -iec_dt.hpp -- DATE_AND_TIME operations -iec_char.hpp -- CHAR/WCHAR types -iec_wstring.hpp -- WSTRING type -iec_memory.hpp -- Memory operation helpers -iec_retain.hpp -- Retain variable support -iec_pointer.hpp -- POINTER TO support -iec_ptr.hpp -- REF_TO support -iec_subrange.hpp -- Subrange type support +resources/strucpp/runtime/include/ + iec_var.hpp -- IECVar template (forcing, raw_ptr) + iec_types.hpp -- IEC type aliases (IEC_INT, IEC_BOOL, etc.) + iec_located.hpp -- LocatedVar struct, LocatedArea/LocatedSize enums + iec_traits.hpp -- Type trait helpers + iec_array.hpp -- Array1D, Array2D, Array3D templates + iec_string.hpp -- IECString (stack-allocated, fixed-size) + iec_enum.hpp -- Enum type support + iec_struct.hpp -- Struct base helpers + iec_std_lib.hpp -- IEC standard functions (ABS, MIN, MAX, etc.) + iec_time.hpp -- TIME type operations + iec_date.hpp -- DATE type operations + iec_tod.hpp -- TIME_OF_DAY operations + iec_dt.hpp -- DATE_AND_TIME operations + iec_char.hpp -- CHAR/WCHAR types + iec_wstring.hpp -- WSTRING type + iec_memory.hpp -- Memory operation helpers + iec_retain.hpp -- Retain variable support + iec_pointer.hpp -- POINTER TO support + iec_ptr.hpp -- REF_TO support + iec_subrange.hpp -- Subrange type support ``` +This directory is `.gitignore`'d and populated automatically during setup. The headers are +**strictly version-coupled** with the STruC++ compiler -- both come from the same release +artifact (the `.tgz` tarball). Upgrading the version in `binary-versions.json` automatically +refreshes both the TypeScript compiler in `node_modules` and the C++ headers here. + These are all **header-only** with no platform-specific code. They compile on any C++17 toolchain including Arduino AVR GCC 7.3+. -**Maintenance**: When STruC++ updates its runtime headers, this directory must be synced. -Consider a build script or git submodule for automation. +This follows the same pattern as MatIEC's `resources/sources/MatIEC/lib/` directory, which +is also downloaded from the matiec release and `.gitignore`'d. ## Step 2.2: Create New Arduino Sketch @@ -500,7 +506,9 @@ The glue generator uses this to validate located variable addresses don't exceed | File | Action | |------|--------| -| `resources/sources/StrucppRuntime/*.hpp` | **New** -- STruC++ runtime headers | | `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` | **New** -- Arduino sketch | | `src/backend/shared/utils/PLC/generate-arduino-glue.ts` | **New** -- Glue code generator | | `resources/sources/boards/hals.json` | Modified -- add cxx_flags, compiler_backend | + +Note: Runtime headers are NOT stored in this repo. They come from `resources/strucpp/runtime/include/` +which is downloaded by `scripts/download-binaries.ts` (see Phase 1). diff --git a/docs/strucpp-migration/04-editor-compiler-module.md b/docs/strucpp-migration/04-editor-compiler-module.md index c9987451b..df22409dc 100644 --- a/docs/strucpp-migration/04-editor-compiler-module.md +++ b/docs/strucpp-migration/04-editor-compiler-module.md @@ -148,10 +148,16 @@ private async compileArduinoWithSTruCpp( ```typescript private copyStrucppStaticFiles(compilationPath: string): void { - const strucppRuntimeDir = path.join(this.resourcesPath, 'sources', 'StrucppRuntime') + // Runtime headers -- downloaded by scripts/download-binaries.ts, NOT stored in repo + const strucppRuntimeDir = path.join(this.resourcesPath, 'strucpp', 'runtime', 'include') const strucppBaremetalDir = path.join(this.resourcesPath, 'sources', 'StrucppBaremetal') - // Copy runtime headers + // Copy C++ runtime headers to build directory + if (!fs.existsSync(strucppRuntimeDir)) { + throw new Error( + 'STruC++ runtime headers not found. Run "npm run setup:binaries" to download them.', + ) + } const headers = fs.readdirSync(strucppRuntimeDir) for (const file of headers) { fs.copyFileSync( @@ -160,7 +166,7 @@ private copyStrucppStaticFiles(compilationPath: string): void { ) } - // Copy StrucppBaremetal.ino + // Copy StrucppBaremetal.ino (this IS stored in the repo) fs.copyFileSync( path.join(strucppBaremetalDir, 'StrucppBaremetal.ino'), path.join(compilationPath, 'StrucppBaremetal.ino'), @@ -390,8 +396,8 @@ build/{boardTarget}/src/ build/{boardTarget}/src/ plc.xml program.st - iec_var.hpp <- STruC++ runtime headers - iec_types.hpp + iec_var.hpp <- Copied from resources/strucpp/runtime/include/ (downloaded) + iec_types.hpp <- (NOT stored in repo -- comes from STruC++ release) iec_located.hpp ... (other runtime headers) generated.hpp <- STruC++ output diff --git a/docs/strucpp-migration/06-runtime-v4-so-interface.md b/docs/strucpp-migration/06-runtime-v4-so-interface.md index eafbca55f..c797cab1f 100644 --- a/docs/strucpp-migration/06-runtime-v4-so-interface.md +++ b/docs/strucpp-migration/06-runtime-v4-so-interface.md @@ -337,10 +337,14 @@ lib/ (MatIEC headers) generated.cpp, generated.hpp v4_compat.cpp c_blocks.h, c_blocks_code.cpp -iec_var.hpp, iec_types.hpp, iec_located.hpp (STruC++ runtime headers) +iec_var.hpp, iec_types.hpp, iec_located.hpp (copied from resources/strucpp/runtime/include/) ... (other STruC++ runtime headers) ``` +The headers are copied from `resources/strucpp/runtime/include/` (downloaded by +`scripts/download-binaries.ts`, NOT stored in the repo). They are strictly version-coupled +with the STruC++ compiler that produced the generated code. + The `handleUploadToRuntime` method is updated to package the correct files based on `compiler_backend`. From dbd9885121fd65631a9e294fcc064760b074354a Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 13:55:29 -0400 Subject: [PATCH 014/296] feat: add STruC++ dependency infrastructure (Phase 1) - Add strucpp v0.2.4 entry to binary-versions.json - Extend scripts/download-binaries.ts to download the STruC++ npm tarball from GitHub Releases, install it into node_modules, and extract runtime headers + .stlib libraries to resources/strucpp/ - Add resources/strucpp/ to .gitignore - Update Phase 1 docs to reflect simplified approach: no compile wrapper needed, editor calls compile() directly, Arduino runtime navigates STruC++ structures dynamically Co-Authored-By: Claude Opus 4.6 (1M context) --- .gitignore | 1 + binary-versions.json | 4 + docs/strucpp-migration/00-overview.md | 28 +- .../01-strucpp-compiler-integration.md | 609 +++--------------- scripts/download-binaries.ts | 116 +++- 5 files changed, 214 insertions(+), 544 deletions(-) diff --git a/.gitignore b/.gitignore index f5439159e..049f7f845 100644 --- a/.gitignore +++ b/.gitignore @@ -61,6 +61,7 @@ resources/bin/**/iec2iec.exe resources/bin/.binary-metadata.json resources/bin/**/.binary-metadata.json resources/sources/MatIEC/lib/ +resources/strucpp/ # Playwright /test-results/ diff --git a/binary-versions.json b/binary-versions.json index 11bfcee60..9c4c50a88 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -6,5 +6,9 @@ "matiec": { "version": "v4.0.11", "repository": "Autonomy-Logic/matiec" + }, + "strucpp": { + "version": "v0.2.4", + "repository": "Autonomy-Logic/STruCpp" } } diff --git a/docs/strucpp-migration/00-overview.md b/docs/strucpp-migration/00-overview.md index ef62704eb..b6f3435e4 100644 --- a/docs/strucpp-migration/00-overview.md +++ b/docs/strucpp-migration/00-overview.md @@ -51,18 +51,22 @@ STruC++ solves both problems: ## Revised Pipeline ``` - UNCHANGED REPLACED - +----------+ +------------------+ -project.json ----> | xml2st | ----> program.st | STruC++ compile()| ----> generated.cpp -(via XML gen) |--generate| | | generated.hpp - | -st | | + glue/debug gen | generated_glue.hpp - +----------+ +------------------+ debug-map.json - | - v - arduino-cli / g++ - (now compiles C++17) + UNCHANGED REPLACED + +----------+ +------------------+ +project.json ----> | xml2st | --> prog.st| STruC++ compile()| --> generated.cpp +(via XML gen) |--generate| | | generated.hpp + | -st | +------------------+ + +----------+ | + v + arduino-cli / g++ + (now compiles C++17) ``` +No glue code generator is needed. The Arduino runtime is **static C++ code** that navigates +STruC++ generated structures dynamically: it walks `locatedVars[]` to bind I/O, walks the +`Configuration` class to discover tasks and programs, and computes `common_ticktime__` from +task intervals -- all at runtime, same code for every project. + ## Phase Structure The migration is organized into 8 phases across two parts: @@ -71,8 +75,8 @@ The migration is organized into 8 phases across two parts: | Phase | Title | Description | |-------|-------|-------------| -| 1 | [STruC++ Compiler Integration](01-strucpp-compiler-integration.md) | Add STruC++ as dependency, create compile wrapper | -| 2 | [Arduino Runtime Adaptation](02-arduino-runtime-adaptation.md) | New sketch, glue code, runtime headers | +| 1 | [STruC++ Compiler Integration](01-strucpp-compiler-integration.md) | Dependency infrastructure: version tracking, download, setup | +| 2 | [Arduino Runtime Adaptation](02-arduino-runtime-adaptation.md) | Static Arduino sketch navigating STruC++ structures | | 3 | [Debugger Variable Access](03-debugger-variable-access.md) | Hierarchical debug system, protocol update | | 4 | [Editor Compiler Module](04-editor-compiler-module.md) | Wire new pipeline into compiler-module.ts | | 5 | [Editor Frontend Debugger](05-editor-frontend-debugger.md) | Update UI for debug-map.json and hierarchical refs | diff --git a/docs/strucpp-migration/01-strucpp-compiler-integration.md b/docs/strucpp-migration/01-strucpp-compiler-integration.md index 4f3ca0855..c248d8589 100644 --- a/docs/strucpp-migration/01-strucpp-compiler-integration.md +++ b/docs/strucpp-migration/01-strucpp-compiler-integration.md @@ -2,17 +2,22 @@ ## Goal -Replace the `iec2c` (MatIEC) binary with STruC++ `compile()` for ST-to-C++ compilation. The input -is `program.st` (already generated by xml2st, unchanged). The output is C++17 code -(`generated.cpp` + `generated.hpp`) plus metadata for downstream glue/debug generation. +Set up the infrastructure to use STruC++ as a dependency in the OpenPLC Editor. This phase +focuses exclusively on the dependency management: version tracking, automated download from +GitHub Releases, and making the STruC++ `compile()` API and C++ runtime headers available +to the editor. + +The editor will call `compile()` directly from `compiler-module.ts` -- no wrapper module +is needed. The Arduino runtime navigates STruC++ generated structures dynamically (located +variables, configuration, tasks, programs) so no glue code generator is needed either. ## Prerequisites - STruC++ repository at `github.com/Autonomy-Logic/STruCpp` with tagged releases +- STruC++ release workflow produces an npm tarball (`.tgz`) as a release artifact - STruC++ exposes a programmatic API: `compile(source: string, options?): CompileResult` -- No external binary needed -- runs as TypeScript in the same Node.js process -## Step 1.1: STruC++ Dependency Strategy +## Dependency Strategy STruC++ is unique compared to matiec and xml2st: it is both a **TypeScript library** (imported via `compile()`) and a provider of **C++ runtime headers** (needed for Arduino compilation). @@ -27,48 +32,21 @@ editor already uses for external tools. 4. **Same download mechanism** -- `scripts/download-binaries.ts` handles setup 5. **Works identically in local dev and CI/CD** -### Release Strategy Changes in STruC++ - -**Repository**: `Autonomy-Logic/STruCpp` - -The existing release workflow already produces platform-specific archives with the standalone -binary + runtime headers + libs. We need to add **one additional artifact**: an npm-compatible -tarball (`.tgz`) that can be installed into `node_modules`. - -**New step in `.github/workflows/release.yml`** (add to one of the build jobs, e.g., linux-x64): +### Release Artifact from STruC++ -```yaml - - name: Create npm tarball - run: | - npm version "$VERSION" --no-git-tag-version --allow-same-version - npm run build - npm pack - mv strucpp-*.tgz strucpp-$VERSION.tgz +The STruC++ release workflow (`release.yml`) includes a `build-npm` job that runs `npm pack` +to produce a platform-independent `.tgz` tarball. This tarball contains everything: - - uses: actions/upload-artifact@v4 - with: - name: strucpp-npm - path: strucpp-$VERSION.tgz -``` - -And in the `create-release` job, add it to the release assets: -```yaml - cp artifacts/strucpp-npm/strucpp-*.tgz release/ -``` - -The `.tgz` contains everything the editor needs: - `dist/` -- compiled JavaScript (the `compile()` API) - `src/runtime/include/` -- C++ runtime headers (`iec_var.hpp`, `iec_types.hpp`, etc.) -- `src/runtime/repl/` -- REPL headers (for future use) - `libs/` -- standard function block libraries (`.stlib` files) - `package.json` -- metadata including version -This is standard npm packaging -- the `"files"` field in STruC++'s `package.json` already -includes these directories. +The `.tgz` is uploaded as a release asset alongside the platform-specific binaries. -### Version Tracking in OpenPLC Editor +### Version Tracking -**File to modify**: `binary-versions.json` +**File**: `binary-versions.json` ```json { @@ -81,162 +59,65 @@ includes these directories. "repository": "Autonomy-Logic/matiec" }, "strucpp": { - "version": "v0.2.2", + "version": "v0.2.4", "repository": "Autonomy-Logic/STruCpp" } } ``` -Version bumps are a one-line change, auditable in git, and automatically picked up by -the download script. - -### Download Script Extension - -**File to modify**: `scripts/download-binaries.ts` - -Add a `downloadStrucpp()` function following the same pattern as `downloadMatiec()`: - -```typescript -// New constant -const STRUCPP_DIR = path.join(ROOT_DIR, 'resources', 'strucpp') - -async function downloadStrucpp(tool: ToolEntry): Promise { - // The npm tarball is platform-independent (pure TypeScript + headers) - const version = tool.version.replace(/^v/, '') // "v0.2.2" -> "0.2.2" - const url = `https://github.com/${tool.repository}/releases/download/${tool.version}/strucpp-${version}.tgz` - - console.log(` Downloading strucpp ${tool.version}...`) - const tmpDir = fs.mkdtempSync(path.join(RESOURCES_DIR, '.tmp-strucpp-')) - - try { - // Download the npm tarball - const tgzPath = path.join(tmpDir, 'strucpp.tgz') - await downloadToFile(url, tgzPath) - - // Install into node_modules via npm - // This makes `import { compile } from 'strucpp'` work - execSync(`npm install "${tgzPath}" --save-exact`, { - cwd: ROOT_DIR, - stdio: 'pipe', - }) - - // Also extract runtime headers to a known location for Arduino compilation. - // These are copies FROM the npm package, NOT separate files. - // The compiler module reads them from here during build. - rmrf(STRUCPP_DIR) - const extractDir = path.join(tmpDir, 'extracted') - extractTarGz(tgzPath, extractDir) - - // npm pack creates: package/src/runtime/include/, package/libs/, etc. - const packageDir = path.join(extractDir, 'package') - fs.mkdirSync(STRUCPP_DIR, { recursive: true }) - - // Copy runtime headers - const runtimeIncludeDir = path.join(packageDir, 'src', 'runtime', 'include') - if (fs.existsSync(runtimeIncludeDir)) { - copyRecursive(runtimeIncludeDir, path.join(STRUCPP_DIR, 'runtime', 'include')) - } - - // Copy .stlib libraries - const libsDir = path.join(packageDir, 'libs') - if (fs.existsSync(libsDir)) { - copyRecursive(libsDir, path.join(STRUCPP_DIR, 'libs')) - } - - console.log(` strucpp ${tool.version} installed.`) - } finally { - rmrf(tmpDir) - } -} -``` +Version bumps are a one-line change, auditable in git. -The key insight: `npm install ` installs the package into `node_modules/strucpp/` which -makes `import { compile } from 'strucpp'` work. Additionally, the headers and libs are -extracted to `resources/strucpp/` for the compiler module to copy into build directories -during Arduino compilation. +### Download Script -**Cache check** -- add `needsStrucpp()` following the same pattern: +**File**: `scripts/download-binaries.ts` -```typescript -function needsStrucpp(versions: BinaryVersions, cached: CacheMetadata | null): boolean { - // Check if node_modules/strucpp exists and matches version - const pkgJsonPath = path.join(ROOT_DIR, 'node_modules', 'strucpp', 'package.json') - if (!fs.existsSync(pkgJsonPath)) return true +The existing download script is extended with `downloadStrucpp()` and `needsStrucpp()`. - const installed = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')) - const expected = versions.strucpp.version.replace(/^v/, '') - if (installed.version !== expected) return true +**Download flow:** +1. Download the `.tgz` from GitHub Releases +2. Run `npm install --save-exact` to install into `node_modules/strucpp/` + (makes `import { compile } from 'strucpp'` work) +3. Extract runtime headers to `resources/strucpp/runtime/include/` +4. Extract `.stlib` libraries to `resources/strucpp/libs/` +5. Write cache metadata to `resources/strucpp/.strucpp-metadata.json` - // Check if runtime headers exist - if (!fs.existsSync(path.join(STRUCPP_DIR, 'runtime', 'include', 'iec_types.hpp'))) return true +**Cache invalidation:** +- Checks `node_modules/strucpp/package.json` version against `binary-versions.json` +- Checks `resources/strucpp/runtime/include/iec_types.hpp` exists +- Checks `.strucpp-metadata.json` version matches +- If any check fails, re-downloads (replacing all local files) +- `--force` flag bypasses all cache checks - return false -} -``` - -**Note**: Unlike matiec (which is platform-specific), strucpp is platform-independent. The -download runs once regardless of platform/arch. +**Key difference from matiec/xml2st**: STruC++ is platform-independent (pure TypeScript + +header-only C++), so it downloads once regardless of platform/arch. ### Git Ignore -**File to modify**: `.gitignore` +**File**: `.gitignore` ```gitignore -# STruC++ (downloaded by scripts/download-binaries.ts) resources/strucpp/ ``` The `node_modules/strucpp` entry is already covered by the blanket `node_modules/` ignore. -### How the Compiler Module Finds STruC++ Assets - -At compile time, the compiler module needs two things: - -1. **The TypeScript compiler** -- standard import: - ```typescript - import { compile } from 'strucpp' - ``` - This works because `npm install ` puts it in `node_modules`. - -2. **C++ runtime headers** -- resolved from the downloaded location: - ```typescript - const STRUCPP_RUNTIME_DIR = path.join(ROOT_DIR, 'resources', 'strucpp', 'runtime', 'include') - ``` - These are copied to the build directory alongside the generated `.cpp`/`.hpp` files. - -3. **Standard libraries (.stlib)** -- resolved similarly: - ```typescript - const STRUCPP_LIBS_DIR = path.join(ROOT_DIR, 'resources', 'strucpp', 'libs') - ``` - Passed to `compile()` via the `libraryPaths` option. - -### CI/CD Integration - -The CI workflow already calls `npm ci` (which triggers `postinstall` -> `download-binaries.ts`). -With the strucpp addition, the download script automatically: -1. Reads `binary-versions.json` for the strucpp version -2. Downloads the `.tgz` from GitHub Releases -3. Installs it via `npm install` -4. Extracts runtime headers to `resources/strucpp/` - -No CI workflow changes needed beyond the existing cache invalidation (already keyed on -`binary-versions.json` hash). - ### Directory Layout After Setup ``` openplc-editor/ -├── binary-versions.json # Tracks v0.2.2 +├── binary-versions.json # Tracks v0.2.4 ├── node_modules/strucpp/ # TypeScript compiler (npm install) │ ├── dist/ # Compiled JS │ ├── src/runtime/include/ # C++ headers (also in node_modules) │ ├── libs/ # .stlib files (also in node_modules) -│ └── package.json # Version: 0.2.2 +│ └── package.json # Version: 0.2.4 ├── resources/strucpp/ # Extracted for compiler module access +│ ├── .strucpp-metadata.json # Cache: {"strucpp": "v0.2.4"} │ ├── runtime/include/ # C++ headers (copied to build dirs) │ │ ├── iec_var.hpp │ │ ├── iec_types.hpp │ │ ├── iec_located.hpp +│ │ ├── iec_std_lib.hpp │ │ └── ... (19 header files) │ └── libs/ # .stlib archives │ ├── iec-standard-fb.stlib @@ -244,384 +125,46 @@ openplc-editor/ └── resources/bin/{platform}/{arch}/ # Other binaries (unchanged) ``` -### Version Upgrade Workflow - -To upgrade STruC++ to a new version: - -1. Update `binary-versions.json`: change `"version": "v0.3.0"` -2. Run `npm run setup:binaries` (or just `npm run dev` which triggers it via prestart) -3. The script downloads the new `.tgz`, updates `node_modules/strucpp`, and refreshes - `resources/strucpp/` with the matching runtime headers -4. Commit `binary-versions.json` (one-line change) -5. CI picks it up automatically - -## Step 1.2: Create STruC++ Compiler Wrapper - -**New file**: `src/backend/shared/utils/PLC/strucpp-compiler.ts` - -This module wraps the STruC++ `compile()` function and extracts the metadata needed for -downstream phases (glue code generation, debug map generation, task scheduling). - -### Public API - -```typescript -import { compile, type CompileResult, type CompileOptions } from 'strucpp' - -// ----- Input types ----- - -export interface STruCppCompileOptions { - /** Name for the generated header file (default: "generated.hpp") */ - headerFileName?: string - /** Enable debug info in output (default: true) */ - debug?: boolean - /** Enable ST-to-C++ line mapping (default: true) */ - lineMapping?: boolean - /** Paths to .stlib library archives to load */ - libraryPaths?: string[] -} - -// ----- Output types ----- - -export interface STruCppResult { - success: boolean - /** C++ implementation file content */ - cppCode: string - /** C++ header file content */ - headerCode: string - /** Compilation errors */ - errors: STruCppDiagnostic[] - /** Compilation warnings */ - warnings: STruCppDiagnostic[] - /** Task scheduling metadata (extracted from CONFIGURATION/RESOURCE/TASK) */ - taskIntervals: TaskInterval[] - /** Variable descriptors per program instance (for debug/glue generation) */ - variableDescriptors: ProgramVarDescriptor[] - /** Number of located variables in the generated code */ - locatedVarCount: number - /** The raw CompileResult from STruC++ (for advanced use) */ - rawResult: CompileResult -} - -export interface STruCppDiagnostic { - message: string - line: number - column: number - severity: 'error' | 'warning' -} - -export interface TaskInterval { - /** Instance name as declared in PROGRAM ... WITH task : Type */ - instanceName: string - /** The program POU type name */ - programType: string - /** Task interval in nanoseconds (e.g., 20000000 for T#20ms) */ - intervalNs: number - /** Task priority (from TASK declaration) */ - priority: number -} - -export interface ProgramVarDescriptor { - /** Program instance name (e.g., "instance0") */ - programInstanceName: string - /** Program POU type name (e.g., "Main") */ - programTypeName: string - /** Variables declared in this program */ - variables: VarEntry[] -} - -export interface VarEntry { - /** Variable name */ - name: string - /** IEC type tag: "BOOL", "INT", "DINT", "REAL", "LREAL", "TIME", "STRING", etc. */ - typeTag: string - /** Whether this variable is an array */ - isArray: boolean - /** Array dimensions (e.g., [100] for ARRAY[0..99], [3,4] for 2D array) */ - arrayDimensions?: number[] - /** Whether this variable is a struct/FB instance */ - isStruct?: boolean - /** For struct/FB: child fields */ - structFields?: VarEntry[] - /** C++ type name for code generation (e.g., "int16_t", "bool", "float") */ - cppTypeName: string - /** Byte size of a single element */ - size: number -} -``` - -### Implementation - -```typescript -export function compileWithSTruCpp( - stSource: string, - options?: Partial, -): STruCppResult { - const compileOpts: Partial = { - headerFileName: options?.headerFileName ?? 'generated.hpp', - debug: options?.debug ?? true, - lineMapping: options?.lineMapping ?? true, - libraryPaths: options?.libraryPaths, - } - - const result = compile(stSource, compileOpts) - - if (!result.success) { - return { - success: false, - cppCode: '', - headerCode: '', - errors: result.errors.map(mapDiagnostic), - warnings: result.warnings.map(mapDiagnostic), - taskIntervals: [], - variableDescriptors: [], - locatedVarCount: 0, - rawResult: result, - } - } - - // Extract task intervals from the project model - const taskIntervals = extractTaskIntervals(result.projectModel) - - // Extract variable descriptors from AST + symbol tables - const variableDescriptors = extractVariableDescriptors(result.ast, result.symbolTables, result.projectModel) - - // Count located variables - const locatedVarCount = countLocatedVars(result.ast, result.projectModel) - - return { - success: true, - cppCode: result.cppCode, - headerCode: result.headerCode, - errors: [], - warnings: result.warnings.map(mapDiagnostic), - taskIntervals, - variableDescriptors, - locatedVarCount, - rawResult: result, - } -} -``` - -### Metadata Extraction Functions - -#### `extractTaskIntervals(projectModel)` - -Walks `projectModel.configurations[].resources[].tasks[]` to extract: -- Task name and interval (nanoseconds) -- Program instances associated with each task -- Task priority - -```typescript -function extractTaskIntervals(projectModel: ProjectModel | undefined): TaskInterval[] { - if (!projectModel?.configurations?.length) { - // No CONFIGURATION: single default task at 20ms - return projectModel?.programs - ? Array.from(projectModel.programs.keys()).map(name => ({ - instanceName: name, - programType: name, - intervalNs: 20_000_000, // 20ms default - priority: 0, - })) - : [] - } - - const intervals: TaskInterval[] = [] - for (const config of projectModel.configurations) { - for (const resource of config.resources) { - for (const task of resource.tasks) { - for (const inst of task.programInstances) { - intervals.push({ - instanceName: inst.instanceName, - programType: inst.programType, - intervalNs: task.interval?.nanoseconds ?? 20_000_000, - priority: task.priority ?? 0, - }) - } - } - } - } - return intervals -} -``` - -#### `extractVariableDescriptors(ast, symbolTables, projectModel)` - -For each program instance, collects all VAR, VAR_INPUT, VAR_OUTPUT declarations: -- Resolves types to determine typeTag, size, array dimensions -- Identifies struct/FB instances and recursively collects their fields -- Does NOT expand arrays -- an `ARRAY[0..99] OF INT` becomes one VarEntry with - `isArray: true, arrayDimensions: [100]` - -This is the key function for scalability. The STruC++ `symbolTables` provide complete -type resolution information needed to build VarEntry objects. - -## Step 1.3: Utility -- GCD Computation - -**Add to**: `src/backend/shared/utils/PLC/strucpp-compiler.ts` - -The GCD of all task intervals determines the base scan cycle time for Arduino round-robin: - -```typescript -export function computeTaskGCD(intervals: TaskInterval[]): number { - if (intervals.length === 0) return 20_000_000 // 20ms default - let g = intervals[0].intervalNs - for (let i = 1; i < intervals.length; i++) { - g = gcd(g, intervals[i].intervalNs) - } - return g -} - -function gcd(a: number, b: number): number { - while (b !== 0) { - const t = b - b = a % b - a = t - } - return a -} -``` - -## Design Notes - -### Why a Wrapper Instead of Calling compile() Directly +### How the Compiler Module Uses STruC++ -1. **Metadata extraction**: The raw `CompileResult` contains AST and symbol tables that need - traversal to produce the structured metadata needed for glue/debug generation. This logic - is non-trivial and should be encapsulated. +In later phases, `compiler-module.ts` will: -2. **Stable interface**: If STruC++ API changes, only this wrapper needs updating. +1. **Import the compiler** -- `import { compile } from 'strucpp'` (standard Node.js import) +2. **Call compile() directly** -- pass the ST source string, get C++ code back. No wrapper needed. +3. **Copy runtime headers** -- from `resources/strucpp/runtime/include/` to the build directory +4. **Pass library paths** -- `resources/strucpp/libs/` to `compile()` via the `libraryPaths` option -3. **100% shared**: This module has zero platform dependencies. It takes a string (ST source) - and returns a structured result. Both Electron and web editors use it identically. +### Why No Compile Wrapper -### What STruC++ compile() Actually Produces +The STruC++ `compile()` API returns everything the editor needs directly: +- `cppCode` / `headerCode` -- the generated C++ files +- `projectModel` -- task intervals, program instances (accessible from generated code) +- `errors` / `warnings` -- diagnostics -Given a `program.st` file like: -```iec -PROGRAM Main - VAR - counter : INT; - motor_speed AT %QW0 : INT; - sensor AT %IX0.0 : BOOL; - END_VAR - counter := counter + 1; - motor_speed := counter * 10; -END_PROGRAM +The Arduino runtime navigates STruC++ structures dynamically at C++ level: +- `locatedVars[]` array for I/O binding (just a for loop) +- `ConfigurationInstance` → `ResourceInstance` → `TaskInstance` for task scheduling +- `ProgramBase::run()` for executing each program +- `common_ticktime__` computed from task intervals at runtime -CONFIGURATION Config0 - RESOURCE Res0 ON PLC - TASK task0(INTERVAL := T#20ms, PRIORITY := 0); - PROGRAM instance0 WITH task0 : Main; - END_RESOURCE -END_CONFIGURATION -``` +No TypeScript glue code generator or metadata extraction wrapper is needed. -STruC++ generates: - -**generated.hpp** (header): -```cpp -#pragma once -#include "iec_types.hpp" -namespace strucpp { - -class Program_Main : public ProgramBase { -public: - IEC_INT counter; - IEC_INT motor_speed; // AT %QW0 - IEC_BOOL sensor; // AT %IX0.0 - Program_Main(); - void run() override; -}; - -extern LocatedVar locatedVars[]; -extern constexpr uint32_t locatedVarsCount; - -class Configuration_Config0 { -public: - Program_Main instance0; - Configuration_Config0(); -}; - -} // namespace strucpp -``` - -**generated.cpp** (implementation): -```cpp -#include "generated.hpp" -namespace strucpp { - -LocatedVar locatedVars[2] = { - { LocatedArea::Output, LocatedSize::Word, 0, 0, {0,0,0}, nullptr }, - { LocatedArea::Input, LocatedSize::Bit, 0, 0, {0,0,0}, nullptr }, -}; -constexpr uint32_t locatedVarsCount = 2; - -Program_Main::Program_Main() : counter(0), motor_speed(0), sensor(false) { - locatedVars[0].pointer = motor_speed.raw_ptr(); - locatedVars[1].pointer = sensor.raw_ptr(); -} +### Version Upgrade Workflow -void Program_Main::run() { - counter = counter + 1; - motor_speed = counter * 10; -} +To upgrade STruC++ to a new version: -Configuration_Config0::Configuration_Config0() {} +1. Update `binary-versions.json`: change `"version": "v0.3.0"` +2. Run `npm run setup:binaries` (or `npm run dev` which triggers it via prestart) +3. The script downloads the new `.tgz`, updates `node_modules/strucpp`, and refreshes + `resources/strucpp/` with the matching runtime headers +4. Commit `binary-versions.json` (one-line change) +5. CI picks it up automatically -} // namespace strucpp -``` +### CI/CD Integration -### STruC++ Type Mapping Reference - -| IEC Type | C++ Type | `IECVar` Alias | Size | -|----------|----------|---------------|------| -| BOOL | `bool` | `IEC_BOOL` | 1 | -| SINT | `int8_t` | `IEC_SINT` | 1 | -| INT | `int16_t` | `IEC_INT` | 2 | -| DINT | `int32_t` | `IEC_DINT` | 4 | -| LINT | `int64_t` | `IEC_LINT` | 8 | -| USINT | `uint8_t` | `IEC_USINT` | 1 | -| UINT | `uint16_t` | `IEC_UINT` | 2 | -| UDINT | `uint32_t` | `IEC_UDINT` | 4 | -| ULINT | `uint64_t` | `IEC_ULINT` | 8 | -| BYTE | `uint8_t` | `IEC_BYTE` | 1 | -| WORD | `uint16_t` | `IEC_WORD` | 2 | -| DWORD | `uint32_t` | `IEC_DWORD` | 4 | -| LWORD | `uint64_t` | `IEC_LWORD` | 8 | -| REAL | `float` | `IEC_REAL` | 4 | -| LREAL | `double` | `IEC_LREAL` | 8 | -| TIME | `int64_t` | `IEC_TIME` | 8 | -| STRING(N) | `IECString` | `IEC_STRING` | N+1 | - -All types wrapped in `IECVar` which adds: `bool forced_` (1 byte) + `T forced_value_` -(same size as value). Total overhead per variable: `sizeof(T) + 1 + sizeof(T)`. - -## Testing Strategy - -1. **Unit test** `compileWithSTruCpp()` with a simple ST program: - - Verify `success === true` - - Verify `cppCode` and `headerCode` are non-empty - - Verify `taskIntervals` contains correct entries - - Verify `variableDescriptors` matches declared variables - -2. **Unit test** `extractTaskIntervals()`: - - Single task: `[{intervalNs: 20000000}]` - - Multiple tasks: `[{intervalNs: 20000000}, {intervalNs: 50000000}]` - - No CONFIGURATION (standalone programs): default 20ms - -3. **Unit test** `extractVariableDescriptors()`: - - Scalar variable: `{name: "counter", typeTag: "INT", isArray: false, size: 2}` - - Array: `{name: "speeds", typeTag: "INT", isArray: true, arrayDimensions: [100], size: 2}` - - Struct/FB instance: `{name: "fb1", isStruct: true, structFields: [...]}` - -4. **Unit test** `computeTaskGCD()`: - - GCD(20ms, 40ms) = 20ms - - GCD(20ms, 50ms) = 10ms - - GCD(20ms, 20ms) = 20ms - - Single task: interval itself - -5. **Integration test**: feed an actual `program.st` (from the sample project) and verify - compilation succeeds without errors. +The CI workflow already calls `npm ci` (which triggers `postinstall` -> `download-binaries.ts`). +The download script automatically handles strucpp alongside xml2st and matiec. No CI workflow +changes needed beyond the existing cache invalidation (keyed on `binary-versions.json` hash). ## Files Created/Modified @@ -632,10 +175,18 @@ All types wrapped in `IECVar` which adds: `bool forced_` (1 byte) + `T forced | `binary-versions.json` | Add strucpp entry with version and repository | | `scripts/download-binaries.ts` | Add `downloadStrucpp()` and `needsStrucpp()` | | `.gitignore` | Add `resources/strucpp/` | -| `src/backend/shared/utils/PLC/strucpp-compiler.ts` | **New** -- STruC++ compile() wrapper | ### In STruCpp (separate repository) | File | Action | |------|--------| -| `.github/workflows/release.yml` | Add `npm pack` step to produce `.tgz` artifact | +| `.github/workflows/release.yml` | Add `build-npm` job to produce `.tgz` artifact | + +## Testing + +1. Run `npm run setup:binaries` -- verify strucpp downloads and installs +2. Verify `node_modules/strucpp/package.json` has the correct version +3. Verify `resources/strucpp/runtime/include/iec_types.hpp` exists +4. Verify `resources/strucpp/libs/iec-standard-fb.stlib` exists +5. Change version in `binary-versions.json`, re-run -- verify it re-downloads +6. Run with `--force` -- verify it re-downloads even when cached diff --git a/scripts/download-binaries.ts b/scripts/download-binaries.ts index 5ca6f91fb..beb6953a2 100644 --- a/scripts/download-binaries.ts +++ b/scripts/download-binaries.ts @@ -1,5 +1,5 @@ /** - * Download external tool binaries (xml2st, matiec) from GitHub Releases. + * Download external tool binaries (xml2st, matiec, strucpp) from GitHub Releases. * * Usage: * ts-node scripts/download-binaries.ts [--platform ] [--arch ] [--force] @@ -23,6 +23,7 @@ interface ToolEntry { interface BinaryVersions { xml2st: ToolEntry matiec: ToolEntry + strucpp: ToolEntry } interface CacheMetadata { @@ -32,6 +33,10 @@ interface CacheMetadata { arch: string } +interface StrucppCacheMetadata { + strucpp: string +} + type Platform = 'darwin' | 'linux' | 'win32' type Arch = 'x64' | 'arm64' @@ -43,6 +48,8 @@ const ROOT_DIR = path.resolve(__dirname, '..') const VERSIONS_FILE = path.join(ROOT_DIR, 'binary-versions.json') const RESOURCES_DIR = path.join(ROOT_DIR, 'resources') const MATIEC_LIB_DIR = path.join(RESOURCES_DIR, 'sources', 'MatIEC', 'lib') +const STRUCPP_DIR = path.join(RESOURCES_DIR, 'strucpp') +const STRUCPP_CACHE_FILE = path.join(STRUCPP_DIR, '.strucpp-metadata.json') function binDir(platform: Platform, arch: Arch): string { return path.join(RESOURCES_DIR, 'bin', platform, arch) @@ -99,6 +106,16 @@ function getCachedMetadata(platform: Platform, arch: Arch): CacheMetadata | null } } +function getStrucppCachedMetadata(): StrucppCacheMetadata | null { + if (!fs.existsSync(STRUCPP_CACHE_FILE)) return null + + try { + return JSON.parse(fs.readFileSync(STRUCPP_CACHE_FILE, 'utf-8')) as StrucppCacheMetadata + } catch { + return null + } +} + function needsXml2st(versions: BinaryVersions, cached: CacheMetadata | null, platform: Platform, arch: Arch): boolean { const dir = binDir(platform, arch) const isWindows = platform === 'win32' @@ -126,6 +143,28 @@ function needsMatiec(versions: BinaryVersions, cached: CacheMetadata | null, pla return false } +function needsStrucpp(versions: BinaryVersions, strucppCached: StrucppCacheMetadata | null): boolean { + // Check if runtime headers exist + if (!fs.existsSync(path.join(STRUCPP_DIR, 'runtime', 'include', 'iec_types.hpp'))) return true + + // Check if node_modules/strucpp exists with the correct version + const pkgJsonPath = path.join(ROOT_DIR, 'node_modules', 'strucpp', 'package.json') + if (!fs.existsSync(pkgJsonPath)) return true + + try { + const installed = JSON.parse(fs.readFileSync(pkgJsonPath, 'utf-8')) + const expected = versions.strucpp.version.replace(/^v/, '') + if (installed.version !== expected) return true + } catch { + return true + } + + // Check cached version + if (!strucppCached || strucppCached.strucpp !== versions.strucpp.version) return true + + return false +} + function writeCache(versions: BinaryVersions, platform: Platform, arch: Arch): void { const data: CacheMetadata = { xml2st: versions.xml2st.version, @@ -137,6 +176,14 @@ function writeCache(versions: BinaryVersions, platform: Platform, arch: Arch): v fs.writeFileSync(cacheFile(platform, arch), JSON.stringify(data, null, 2) + '\n') } +function writeStrucppCache(versions: BinaryVersions): void { + const data: StrucppCacheMetadata = { + strucpp: versions.strucpp.version, + } + fs.mkdirSync(STRUCPP_DIR, { recursive: true }) + fs.writeFileSync(STRUCPP_CACHE_FILE, JSON.stringify(data, null, 2) + '\n') +} + // --------------------------------------------------------------------------- // Download helpers // --------------------------------------------------------------------------- @@ -305,6 +352,59 @@ async function downloadMatiec( } } +// --------------------------------------------------------------------------- +// strucpp download and extraction +// --------------------------------------------------------------------------- + +async function downloadStrucpp(tool: ToolEntry): Promise { + // The npm tarball is platform-independent (pure TypeScript + C++ headers) + const version = tool.version.replace(/^v/, '') + const url = `https://github.com/${tool.repository}/releases/download/${tool.version}/strucpp-${version}.tgz` + + console.log(` Downloading strucpp ${tool.version}...`) + const tmpDir = fs.mkdtempSync(path.join(RESOURCES_DIR, '.tmp-strucpp-')) + + try { + const tgzPath = path.join(tmpDir, 'strucpp.tgz') + await downloadToFile(url, tgzPath) + + // Install into node_modules via npm so `import { compile } from 'strucpp'` works + console.log(` Installing strucpp ${tool.version} into node_modules...`) + execSync(`npm install "${tgzPath}" --save-exact`, { + cwd: ROOT_DIR, + stdio: 'pipe', + }) + + // Extract runtime headers and libs to resources/strucpp/ for the compiler module. + // The npm tarball extracts to a package/ directory. + const extractDir = path.join(tmpDir, 'extracted') + extractTarGz(tgzPath, extractDir) + const packageDir = path.join(extractDir, 'package') + + // Clear previous version + const runtimeDest = path.join(STRUCPP_DIR, 'runtime', 'include') + const libsDest = path.join(STRUCPP_DIR, 'libs') + rmrf(runtimeDest) + rmrf(libsDest) + + // Copy runtime headers + const runtimeSrc = path.join(packageDir, 'src', 'runtime', 'include') + if (fs.existsSync(runtimeSrc)) { + copyRecursive(runtimeSrc, runtimeDest) + } + + // Copy .stlib libraries + const libsSrc = path.join(packageDir, 'libs') + if (fs.existsSync(libsSrc)) { + copyRecursive(libsSrc, libsDest) + } + + console.log(` strucpp ${tool.version} installed.`) + } finally { + rmrf(tmpDir) + } +} + // --------------------------------------------------------------------------- // Main // --------------------------------------------------------------------------- @@ -325,11 +425,13 @@ async function main(): Promise { fs.mkdirSync(targetBinDir, { recursive: true }) const cached = force ? null : getCachedMetadata(platform, arch) + const strucppCached = force ? null : getStrucppCachedMetadata() const downloadXml2stNeeded = force || needsXml2st(versions, cached, platform, arch) const downloadMatiecNeeded = force || needsMatiec(versions, cached, platform, arch) + const downloadStrucppNeeded = force || needsStrucpp(versions, strucppCached) - if (!downloadXml2stNeeded && !downloadMatiecNeeded) { - console.log(`[download-binaries] Binaries up to date for ${platform}-${arch}, skipping.`) + if (!downloadXml2stNeeded && !downloadMatiecNeeded && !downloadStrucppNeeded) { + console.log(`[download-binaries] All tools up to date, skipping.`) return } @@ -345,6 +447,14 @@ async function main(): Promise { console.log(` matiec ${versions.matiec.version} already installed, skipping.`) } + // strucpp is platform-independent — only download once regardless of platform/arch + if (downloadStrucppNeeded) { + await downloadStrucpp(versions.strucpp) + writeStrucppCache(versions) + } else { + console.log(` strucpp ${versions.strucpp.version} already installed, skipping.`) + } + writeCache(versions, platform, arch) console.log(`[download-binaries] Done.`) } From 5b673e28163d5d6485df7fb861fca15aec916a5f Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 13:59:16 -0400 Subject: [PATCH 015/296] docs: update phases 2, 4, 6 for no-glue static runtime design Remove all references to the TypeScript glue code generator and compile wrapper. The new design is simpler: - Phase 2: Arduino sketch is fully static C++ that navigates STruC++ structures dynamically (locatedVars[], ConfigurationInstance, etc.) - Phase 4: compiler-module.ts calls compile() directly, no wrapper - Phase 6: v4_compat.cpp is a static shim, same philosophy Configuration name is always Config0 (hardcoded by OpenPLC), so the sketch can instantiate Configuration_Config0 directly. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../02-arduino-runtime-adaptation.md | 565 ++++++------------ .../04-editor-compiler-module.md | 398 +++--------- .../06-runtime-v4-so-interface.md | 36 +- 3 files changed, 287 insertions(+), 712 deletions(-) diff --git a/docs/strucpp-migration/02-arduino-runtime-adaptation.md b/docs/strucpp-migration/02-arduino-runtime-adaptation.md index 872b346ca..34595eff9 100644 --- a/docs/strucpp-migration/02-arduino-runtime-adaptation.md +++ b/docs/strucpp-migration/02-arduino-runtime-adaptation.md @@ -2,269 +2,118 @@ ## Goal -Create the Arduino-side C++ runtime files that bridge STruC++ generated code with the existing -HAL (Hardware Abstraction Layer) and Modbus infrastructure. The HAL files and Modbus slave -implementation remain unchanged -- only the glue layer between them and the PLC program changes. +Create a static Arduino sketch that works with STruC++ generated C++ code. The sketch +navigates STruC++ runtime structures dynamically -- it walks `locatedVars[]` for I/O binding, +walks the `Configuration` class for task discovery and scheduling, and computes +`common_ticktime__` from task intervals. The same sketch code works for every project. + +No glue code generator is needed. No per-project code generation beyond what STruC++ already +produces (`generated.cpp` + `generated.hpp`). ## Prerequisites -- Phase 1 complete (STruC++ compiler wrapper producing C++ code and metadata) -- STruC++ runtime headers available for bundling +- Phase 1 complete (STruC++ dependency infrastructure) +- STruC++ runtime headers available at `resources/strucpp/runtime/include/` -## Step 2.1: STruC++ Runtime Headers (from downloaded release) +## Key STruC++ Runtime Types -The C++ runtime headers are **NOT** stored in this repository. They are downloaded alongside -the STruC++ compiler by `scripts/download-binaries.ts` (see Phase 1 dependency strategy) -and placed at: +The Arduino sketch uses these types from `iec_std_lib.hpp` (all in `namespace strucpp`): +**`ProgramBase`** -- base class for all program instances: +```cpp +struct ProgramBase { + virtual void run() = 0; +}; ``` -resources/strucpp/runtime/include/ - iec_var.hpp -- IECVar template (forcing, raw_ptr) - iec_types.hpp -- IEC type aliases (IEC_INT, IEC_BOOL, etc.) - iec_located.hpp -- LocatedVar struct, LocatedArea/LocatedSize enums - iec_traits.hpp -- Type trait helpers - iec_array.hpp -- Array1D, Array2D, Array3D templates - iec_string.hpp -- IECString (stack-allocated, fixed-size) - iec_enum.hpp -- Enum type support - iec_struct.hpp -- Struct base helpers - iec_std_lib.hpp -- IEC standard functions (ABS, MIN, MAX, etc.) - iec_time.hpp -- TIME type operations - iec_date.hpp -- DATE type operations - iec_tod.hpp -- TIME_OF_DAY operations - iec_dt.hpp -- DATE_AND_TIME operations - iec_char.hpp -- CHAR/WCHAR types - iec_wstring.hpp -- WSTRING type - iec_memory.hpp -- Memory operation helpers - iec_retain.hpp -- Retain variable support - iec_pointer.hpp -- POINTER TO support - iec_ptr.hpp -- REF_TO support - iec_subrange.hpp -- Subrange type support -``` - -This directory is `.gitignore`'d and populated automatically during setup. The headers are -**strictly version-coupled** with the STruC++ compiler -- both come from the same release -artifact (the `.tgz` tarball). Upgrading the version in `binary-versions.json` automatically -refreshes both the TypeScript compiler in `node_modules` and the C++ headers here. - -These are all **header-only** with no platform-specific code. They compile on any C++17 -toolchain including Arduino AVR GCC 7.3+. - -This follows the same pattern as MatIEC's `resources/sources/MatIEC/lib/` directory, which -is also downloaded from the matiec release and `.gitignore`'d. - -## Step 2.2: Create New Arduino Sketch - -**New file**: `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` - -This sketch mirrors the structure of the existing `Baremetal.ino` (351 lines) but is adapted -for STruC++ generated C++ code. The key differences are: - -1. Includes `generated.hpp` and `generated_glue.hpp` instead of MatIEC C headers -2. Calls STruC++ init/run functions instead of `config_init__()` / `config_run__(tick)` -3. Adds `strucpp_restore_forced_inputs()` after HAL input reads -4. Uses GCD-based multi-task scheduler - -### Complete Sketch Structure +**`TaskInstance`** -- describes a task's scheduling and programs: ```cpp -// StrucppBaremetal.ino - -// --- STruC++ generated files (per-project) --- -#include "generated.hpp" // Program classes, Configuration, LocatedVar[] -#include "generated_glue.hpp" // I/O binding, scheduler, debug arrays, MD5 - -// --- OpenPLC static files (unchanged from current runtime) --- -#include "openplc.h" // I/O buffer declarations -#include "debug.h" // Debug function declarations (updated for v2) -#include "ModbusSlave.h" // Modbus communication - -// --- Timing --- -extern unsigned long long common_ticktime__; // Defined in generated_glue.hpp -static unsigned long scan_cycle; -static unsigned long last_run; -static uint32_t __tick = 0; -static bool first_cycle = true; - -// ============================================================================= -// SETUP -// ============================================================================= -void setup() { - // 1. Initialize STruC++ Configuration (creates program instances) - strucpp_config_init(); - - // 2. Bind located variables to I/O buffer pointers - strucpp_bind_located_vars(); - - // 3. Initialize hardware (HAL -- unchanged) - hardwareInit(); - - // 4. Configure Modbus (unchanged from current Baremetal.ino) - #ifdef MODBUS_ENABLED - #if defined(MBSERIAL_IFACE) - mbconfig_serial_iface(); - #elif defined(MBTCP_IFACE) - mbconfig_ethernet_iface(); - #endif - init_mbregs(); - mapEmptyBuffers(); - #endif - - // 5. Set scan cycle from GCD of task intervals - setupCycleDelay(common_ticktime__); -} - -// ============================================================================= -// MAP EMPTY BUFFERS (for Modbus -- identical to current Baremetal.ino) -// ============================================================================= -void mapEmptyBuffers() { - // Exact same implementation as current Baremetal.ino lines 135-191 - // Maps unmapped I/O to Modbus registers - // No changes needed -- uses same openplc.h buffer pointers -} - -// ============================================================================= -// MODBUS TASK (identical to current Baremetal.ino) -// ============================================================================= -void modbusTask() { - // Exact same implementation as current Baremetal.ino lines 193-289 - // Syncs OpenPLC buffers <-> Modbus registers - // No changes needed -} +struct TaskInstance { + const char* name; + int64_t interval_ns; // Execution interval in nanoseconds + int32_t priority; // Higher = more important + ProgramBase** programs; // Array of program instances + size_t program_count; +}; +``` -// ============================================================================= -// PLC CYCLE TASK -// ============================================================================= -void plcCycleTask() { - // 1. Read hardware inputs into buffers (HAL -- unchanged) - updateInputBuffers(); +**`ResourceInstance`** -- describes a resource and its tasks: +```cpp +struct ResourceInstance { + const char* name; + const char* processor; + TaskInstance* tasks; + size_t task_count; +}; +``` - // 2. Restore forced values for input variables - // (HAL writes directly to raw_ptr(), overwriting forced values) - strucpp_restore_forced_inputs(); +**`ConfigurationInstance`** -- base class for configuration (generated code inherits from this): +```cpp +struct ConfigurationInstance { + virtual const char* get_name() const = 0; + virtual ResourceInstance* get_resources() = 0; + virtual size_t get_resource_count() const = 0; +}; +``` - // 3. Execute PLC logic via GCD-based multi-task scheduler - strucpp_config_run(__tick++); +**`LocatedVar`** (from `iec_located.hpp`) -- describes a located variable's I/O binding: +```cpp +struct LocatedVar { + LocatedArea area; // Input, Output, or Memory + LocatedSize size; // Bit, Byte, Word, DWord, or LWord + uint16_t byte_index; + uint8_t bit_index; + uint8_t _reserved[3]; + void* pointer; // Points to IECVar::value_ via raw_ptr() +}; +``` - // 4. Write buffers to hardware outputs (HAL -- unchanged) - updateOutputBuffers(); +The generated code always names the configuration class `Configuration_Config0` (OpenPLC +always uses `Config0` as the configuration name -- this is not user-configurable). - // 5. Update time (same logic as current) - updateTime(); -} +## Step 2.1: STruC++ Runtime Headers -// ============================================================================= -// SCHEDULER (same structure as current, calls new task function) -// ============================================================================= -void scheduler() { - plcCycleTask(); +The C++ runtime headers are **NOT** stored in this repository. They are downloaded alongside +the STruC++ compiler by `scripts/download-binaries.ts` (see Phase 1) and placed at +`resources/strucpp/runtime/include/`. This directory is `.gitignore`'d. - #ifdef USE_ARDUINO_SKETCH - sketch_loop(); - #endif +At compile time, the compiler module copies these headers to the build directory alongside +the generated `.cpp`/`.hpp` files. - #ifdef MODBUS_ENABLED - modbusTask(); - #endif +## Step 2.2: Create New Arduino Sketch - if (first_cycle) { - first_cycle = false; - scan_cycle = (unsigned long)(common_ticktime__ / 1000); - last_run = micros(); - } -} +**New file**: `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` -// ============================================================================= -// MAIN LOOP (identical timing logic to current Baremetal.ino) -// ============================================================================= -void loop() { - unsigned long now = micros(); - if ((now - last_run) >= scan_cycle) { - last_run = now; - scheduler(); - } +This is a **static** sketch -- the same code for every project. It dynamically discovers +the project structure from STruC++ runtime types at `setup()` time. - #ifdef MODBUS_ENABLED - // Run extra Modbus cycles between PLC scans if time permits - if ((micros() - last_run) < (scan_cycle - 10000)) { - modbusTask(); - } - #endif +### Sketch Architecture - #ifdef SIMULATOR_MODE - asm("sleep"); - #endif -} ``` - -### Key Differences from Current Baremetal.ino - -| Aspect | Current (Baremetal.ino) | New (StrucppBaremetal.ino) | -|--------|------------------------|--------------------------| -| Includes | `extern "C" { #include "openplc.h" }` | `#include "generated.hpp"` + `"generated_glue.hpp"` | -| Init | `config_init__()` + `glueVars()` | `strucpp_config_init()` + `strucpp_bind_located_vars()` | -| PLC run | `config_run__(__tick++)` | `strucpp_config_run(__tick++)` | -| Forced vars | Not handled at HAL level | `strucpp_restore_forced_inputs()` after `updateInputBuffers()` | -| Time | `updateTime()` from glueVars.c | `updateTime()` from generated_glue.hpp | -| Modbus | Unchanged | Unchanged | -| HAL | Unchanged | Unchanged | - -## Step 2.3: Arduino Glue Code Generator - -**New file**: `src/backend/shared/utils/PLC/generate-arduino-glue.ts` - -This TypeScript module generates `generated_glue.hpp` -- a per-project C++ header that contains -all the "glue" between STruC++ generated code and the Arduino runtime. - -### Public API - -```typescript -export interface ArduinoGlueInput { - /** Configuration class name from STruC++ output (e.g., "Config0") */ - configurationName: string - /** Task scheduling metadata from STruCppResult */ - taskIntervals: TaskInterval[] - /** Variable descriptors per program from STruCppResult */ - variableDescriptors: ProgramVarDescriptor[] - /** MD5 hash of the program.st source */ - md5Hash: string - /** Board memory class (determines buffer sizes) */ - boardMemoryClass: 'avr-small' | 'avr-large' | 'arm' | 'esp32' -} - -/** - * Generates the content of generated_glue.hpp. - * This is a pure function -- no file I/O, fully shared between Electron and web. - */ -export function generateArduinoGlue(input: ArduinoGlueInput): string +setup(): + 1. Configuration_Config0 constructed (static global) + 2. Walk locatedVars[] → bind to openplc.h buffer pointers + 3. Walk config.get_resources() → discover tasks, programs, intervals + 4. Compute GCD of all task intervals → common_ticktime__ + 5. Compute per-task divisors for round-robin scheduling + 6. Init hardware (HAL) + Modbus (unchanged from current) + +loop(): + 1. Wait for scan cycle timer + 2. updateInputBuffers() (HAL -- unchanged) + 3. For each task: if tick % divisor == 0, call program->run() + 4. updateOutputBuffers() (HAL -- unchanged) + 5. updateTime() + 6. modbusTask() if time permits (unchanged) ``` -### Generated File Structure - -The output `generated_glue.hpp` contains these sections: +### Key Functions in the Sketch -#### Section 1: Configuration Singleton +#### I/O Binding (replaces `glueVars()`) ```cpp -#pragma once -#include "generated.hpp" -#include "openplc.h" - -using namespace strucpp; - -// --- Global Configuration instance --- -static Configuration_Config0 g_config; - -void strucpp_config_init() { - // Configuration constructor initializes all program instances - // Located variable pointers are set in program constructors -} -``` - -#### Section 2: I/O Buffer Binding - -```cpp -// --- Bind LocatedVar descriptors to OpenPLC I/O buffers --- -void strucpp_bind_located_vars() { +void bindLocatedVars() { + using namespace strucpp; for (uint32_t i = 0; i < locatedVarsCount; ++i) { LocatedVar& lv = locatedVars[i]; if (!lv.pointer) continue; @@ -275,10 +124,6 @@ void strucpp_bind_located_vars() { case LocatedSize::Bit: bool_input[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; break; - case LocatedSize::Byte: - // byte_input is only available on non-Arduino targets - // For Arduino, bytes are typically accessed via word-sized buffers - break; case LocatedSize::Word: int_input[lv.byte_index] = (IEC_UINT*)lv.pointer; break; @@ -288,139 +133,119 @@ void strucpp_bind_located_vars() { case LocatedSize::LWord: lint_input[lv.byte_index] = (IEC_ULINT*)lv.pointer; break; + default: break; } break; - case LocatedArea::Output: - switch (lv.size) { - case LocatedSize::Bit: - bool_output[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; - break; - case LocatedSize::Word: - int_output[lv.byte_index] = (IEC_UINT*)lv.pointer; - break; - case LocatedSize::DWord: - dint_output[lv.byte_index] = (IEC_UDINT*)lv.pointer; - break; - case LocatedSize::LWord: - lint_output[lv.byte_index] = (IEC_ULINT*)lv.pointer; - break; - } + // symmetric to Input with bool_output, int_output, etc. break; - case LocatedArea::Memory: - switch (lv.size) { - case LocatedSize::Word: - int_memory[lv.byte_index] = (IEC_UINT*)lv.pointer; - break; - case LocatedSize::DWord: - dint_memory[lv.byte_index] = (IEC_UDINT*)lv.pointer; - break; - case LocatedSize::LWord: - lint_memory[lv.byte_index] = (IEC_ULINT*)lv.pointer; - break; - } + // int_memory, dint_memory, lint_memory break; } } } ``` -This function replaces the old `glueVars()` generated by xml2st. Instead of hardcoded -pointer assignments, it iterates the LocatedVar descriptor array that STruC++ generates. - -**How it works**: STruC++ generates a `locatedVars[]` array where each entry describes a -located variable's area (I/Q/M), size (X/B/W/D/L), byte index, and bit index. The program -constructor sets `locatedVars[i].pointer = variable.raw_ptr()`. This function then connects -those pointers to the OpenPLC buffer arrays. - -#### Section 3: GCD-Based Task Scheduler +#### Task Discovery and GCD Computation ```cpp -// --- Multi-task round-robin scheduler --- -// Base tick = GCD of all task intervals -// Each task runs when: tick % divisor == 0 - -unsigned long long common_ticktime__ = 20000000ULL; // GCD in nanoseconds - -static ProgramBase* task_programs[] = { - &g_config.instance0, - &g_config.instance1, - // ... one per program instance -}; - -static const uint32_t task_divisors[] = { - 1, // instance0: 20ms / 20ms = every tick - 2, // instance1: 40ms / 20ms = every 2nd tick - // ... -}; +// Storage for discovered task scheduling info +static strucpp::ProgramBase** all_programs = nullptr; +static uint32_t* task_divisors = nullptr; +static size_t total_programs = 0; +unsigned long long common_ticktime__ = 20000000ULL; // default 20ms + +uint64_t gcd(uint64_t a, uint64_t b) { + while (b) { uint64_t t = b; b = a % b; a = t; } + return a; +} -static const size_t TASK_COUNT = 2; // number of tasks +void discoverTasks(strucpp::ConfigurationInstance& config) { + // First pass: count total programs and compute GCD + uint64_t gcd_ns = 0; + size_t prog_count = 0; + + auto* resources = config.get_resources(); + for (size_t r = 0; r < config.get_resource_count(); ++r) { + for (size_t t = 0; t < resources[r].task_count; ++t) { + auto& task = resources[r].tasks[t]; + prog_count += task.program_count; + uint64_t interval = task.interval_ns > 0 ? task.interval_ns : 20000000ULL; + gcd_ns = (gcd_ns == 0) ? interval : gcd(gcd_ns, interval); + } + } -void strucpp_config_run(unsigned long tick) { - for (size_t i = 0; i < TASK_COUNT; ++i) { - if (task_divisors[i] == 0 || (tick % task_divisors[i]) == 0) { - task_programs[i]->run(); + if (gcd_ns == 0) gcd_ns = 20000000ULL; + common_ticktime__ = gcd_ns; + + // Second pass: build flat program array with divisors + all_programs = new strucpp::ProgramBase*[prog_count]; + task_divisors = new uint32_t[prog_count]; + total_programs = prog_count; + + size_t idx = 0; + for (size_t r = 0; r < config.get_resource_count(); ++r) { + for (size_t t = 0; t < resources[r].task_count; ++t) { + auto& task = resources[r].tasks[t]; + uint64_t interval = task.interval_ns > 0 ? task.interval_ns : gcd_ns; + uint32_t divisor = (uint32_t)(interval / gcd_ns); + for (size_t p = 0; p < task.program_count; ++p) { + all_programs[idx] = task.programs[p]; + task_divisors[idx] = divisor; + idx++; + } } } } ``` -**GCD computation example**: For tasks at T#20ms and T#50ms, GCD = 10ms. -Divisors: [2, 5]. Task0 runs at ticks 0,2,4,6,... Task1 at 0,5,10,... - -For a single-task project, this simplifies to calling `run()` every tick. - -#### Section 4: Forced Input Restoration +#### PLC Cycle Execution ```cpp -// --- Restore forced input values after HAL reads --- -// HAL writes directly to IECVar::value_ via raw_ptr(), overwriting forced values. -// This function restores value_ from forced_value_ for forced input variables. - -void strucpp_restore_forced_inputs() { - // Generated per-project for each located INPUT variable: - if (g_config.instance0.sensor.is_forced()) - *(bool*)locatedVars[1].pointer = g_config.instance0.sensor.get_forced_value(); - // ... repeat for each located input variable +void plcCycleTask() { + updateInputBuffers(); + // Run each program according to its task divisor + for (size_t i = 0; i < total_programs; ++i) { + if (task_divisors[i] == 0 || (__tick % task_divisors[i]) == 0) { + all_programs[i]->run(); + } + } + __tick++; + updateOutputBuffers(); + updateTime(); } ``` -**Why this is needed**: When a variable is forced (for debugging), `IECVar::force(v)` sets -both `forced_value_` and `value_` to `v`. The PLC program reads via `get()` which returns -`forced_value_`. But the HAL's `updateInputBuffers()` writes hardware readings directly to -`value_` via `raw_ptr()`. After HAL reads, `value_` contains the hardware reading (not the -forced value). Since `get()` returns `forced_value_`, PLC logic is correct. But any code -reading via `raw_ptr()` (including the debug system's value display) would see the hardware -value. This function ensures `value_` matches the forced state after HAL reads. - -For OUTPUT variables, this is not needed: `force()` sets `value_`, and `set()` is a no-op -when forced, so `value_` stays at the forced value through PLC cycles. The HAL reads from -`raw_ptr()` and writes the forced value to hardware. - -#### Section 5: Time Update and MD5 - -```cpp -// --- Time management --- -extern IEC_TIME __CURRENT_TIME; +### Key Differences from Current Baremetal.ino -void updateTime() { - __CURRENT_TIME = __CURRENT_TIME + (int64_t)common_ticktime__; -} +| Aspect | Current (Baremetal.ino) | New (StrucppBaremetal.ino) | +|--------|------------------------|--------------------------| +| Includes | `extern "C" { #include "openplc.h" }` | `#include "generated.hpp"` | +| Init | `config_init__()` + `glueVars()` | Static `Configuration_Config0` + `bindLocatedVars()` + `discoverTasks()` | +| PLC run | Single `config_run__(__tick++)` | Per-program `run()` with divisor check | +| Task scheduling | All tasks at same rate | GCD-based round-robin per task | +| Time | `common_ticktime__` from generated code | `common_ticktime__` computed at runtime | +| Modbus | Unchanged | Unchanged | +| HAL | Unchanged | Unchanged | -// --- Program MD5 hash --- -const char plc_program_md5[] = "a1b2c3d4e5f6..."; -``` +### What Changes in openplc.h -#### Section 6: Debug Arrays (detailed in Phase 3) +The current `openplc.h` declares MatIEC-specific functions (`config_init__`, `config_run__`, +`glueVars`, `updateTime`). For STruC++, these are no longer needed -- the sketch handles +everything directly. The sketch needs a version of `openplc.h` that only has: +- IEC type definitions (`IEC_BOOL`, `IEC_INT`, etc.) +- Buffer pointer declarations (`bool_input`, `int_output`, etc.) +- Buffer size macros (`MAX_DIGITAL_INPUT`, etc.) +- HAL function declarations (`hardwareInit`, `updateInputBuffers`, `updateOutputBuffers`) -The debug pointer arrays are also generated in this file. See Phase 3 for details. +The MatIEC-specific declarations should be guarded or removed in the STruC++ variant. -## Step 2.4: C++17 Compilation Flag +## Step 2.3: C++17 Compilation Flag **File to modify**: `resources/sources/boards/hals.json` -For every board entry, ensure CXX flags include `-std=gnu++17`: +Add `-std=gnu++17` to CXX flags and `"compiler_backend": "strucpp"` field per board: ```json { @@ -436,9 +261,6 @@ For every board entry, ensure CXX flags include `-std=gnu++17`: } ``` -The `"compiler_backend": "strucpp"` field (default: `"matiec"` if absent) controls which -compilation pipeline the editor uses for this board. - **C++17 support by platform**: | Platform | GCC Version | C++17 Support | @@ -451,64 +273,63 @@ compilation pipeline the editor uses for this board. ## Design Notes +### Why the Sketch is Fully Static + +Every project produces the same C++ structures (`ConfigurationInstance`, `TaskInstance`, +`ProgramBase`, `LocatedVar`). The sketch navigates these structures with generic loops. +Nothing is project-specific except: +- The Configuration class name: always `Configuration_Config0` (hardcoded by OpenPLC) +- The `generated.hpp`/`generated.cpp` files: included, not generated by the sketch + ### Why Keep openplc.h Buffer Arrays The HAL files (`uno_leonardo_nano_micro_zero.cpp`, `esp32.cpp`, `mega_due.cpp`, etc.) use `openplc.h` buffer pointer arrays: `bool_input[byte][bit]`, `int_input[index]`, etc. -Rewriting all HAL files for STruC++ types would be a massive effort with no benefit. Instead, -the glue layer populates these same buffer pointers from STruC++ LocatedVar descriptors. -The HAL files see no difference. +Rewriting all HAL files for STruC++ types would be a massive effort with no benefit. The +sketch's `bindLocatedVars()` populates these same buffer pointers from STruC++ `LocatedVar` +descriptors. The HAL files see no difference. ### Memory Layout: IECVar vs MatIEC __IEC_type_p | MatIEC | STruC++ | |--------|---------| | `__IEC_INT_p { int16_t value; int16_t fvalue; uint8_t flags; }` = 5 bytes | `IECVar { int16_t value_; bool forced_; int16_t forced_value_; }` = 5 bytes | -| `__IEC_BOOL_p { uint8_t value; uint8_t fvalue; uint8_t flags; }` = 3 bytes | `IECVar { bool value_; bool forced_; bool forced_value_; }` = 3 bytes | Memory overhead is essentially the same. -### Board Memory Classes - -The buffer sizes in `openplc.h` vary by chip: +### Dynamic Memory in discoverTasks() -| Class | Boards | Digital I/O | Analog I/O | Memory | -|-------|--------|-------------|------------|--------| -| avr-small | ATmega328P, ATmega168, ATmega32U4 | 8 DIN, 32 DOUT | 6 AIN, 32 AOUT | 0 | -| avr-large | ATmega2560, all others | 56 DIN/DOUT | 32 AIN/AOUT | 20 W/DW/LW | +The `discoverTasks()` function uses `new` to allocate the program pointer and divisor arrays. +This happens once at `setup()` time and the arrays live for the lifetime of the program. On +Arduino, this is acceptable since: +- It happens once (not in the scan loop) +- The total size is small (a few pointers per task) +- The memory is never freed (matches Arduino's typical pattern) -The glue generator uses this to validate located variable addresses don't exceed buffer limits. +For boards with very tight memory (ATmega328P), the total overhead is ~8 bytes per program +instance (pointer + divisor). ## Testing Strategy 1. **Minimal project test**: Single program, one digital output (%QX0.0) - - Generate glue code - Verify `bool_output[0][0]` is bound to the variable's `raw_ptr()` - Compile with arduino-cli for Simulator target 2. **Multi-task test**: Two tasks at T#20ms and T#40ms - - Verify `common_ticktime__ = 20000000` - - Verify `task_divisors = {1, 2}` - - Verify `TASK_COUNT = 2` - -3. **Forced input test**: Located input variable (%IX0.0) - - Force the variable, call `updateInputBuffers()` (simulated HAL write) - - Call `strucpp_restore_forced_inputs()` - - Verify `raw_ptr()` returns the forced value + - Verify GCD computation: `common_ticktime__ = 20000000` + - Verify divisors: `[1, 2]` + - Verify task1 runs every cycle, task2 every other cycle -4. **HAL compatibility test**: Compile with each HAL file - - Verify no compilation errors - - Verify HAL functions (`hardwareInit`, `updateInputBuffers`, `updateOutputBuffers`) - are resolved correctly +3. **HAL compatibility test**: Compile with each major HAL file + - Verify no compilation errors with STruC++ C++17 code ## Files Created/Modified | File | Action | |------|--------| -| `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` | **New** -- Arduino sketch | -| `src/backend/shared/utils/PLC/generate-arduino-glue.ts` | **New** -- Glue code generator | +| `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` | **New** -- static Arduino sketch | | `resources/sources/boards/hals.json` | Modified -- add cxx_flags, compiler_backend | -Note: Runtime headers are NOT stored in this repo. They come from `resources/strucpp/runtime/include/` -which is downloaded by `scripts/download-binaries.ts` (see Phase 1). +Note: Runtime headers come from `resources/strucpp/runtime/include/` (downloaded, Phase 1). +No glue code generator. No per-project code generation. diff --git a/docs/strucpp-migration/04-editor-compiler-module.md b/docs/strucpp-migration/04-editor-compiler-module.md index df22409dc..ac919a6c2 100644 --- a/docs/strucpp-migration/04-editor-compiler-module.md +++ b/docs/strucpp-migration/04-editor-compiler-module.md @@ -2,28 +2,26 @@ ## Goal -Wire the new STruC++ pipeline (Phases 1-3) into the editor's `compiler-module.ts`, replacing -the iec2c and xml2st debug/glue steps while preserving the existing MatIEC path for backward -compatibility. +Wire the STruC++ compilation into `compiler-module.ts`: read `program.st`, call `compile()` +directly, write the generated C++ files, copy runtime headers, and invoke `arduino-cli` with +C++17 flags. No wrapper module, no glue code generator -- just direct integration. ## Prerequisites -- Phase 1 (strucpp-compiler.ts wrapper) -- Phase 2 (generate-arduino-glue.ts) -- Phase 3 (debug map generation and debug arrays in glue) +- Phase 1 (STruC++ installed in node_modules, runtime headers at resources/strucpp/) +- Phase 2 (static StrucppBaremetal.ino sketch) ## Primary File **`src/backend/editor/compiler/compiler-module.ts`** (~2,348 lines) -This is the main compilation orchestrator. It currently handles the full pipeline from JSON -project data to uploaded firmware. The STruC++ pipeline adds new methods alongside existing -ones; both coexist. +This is the main compilation orchestrator. The STruC++ pipeline adds new methods alongside +the existing MatIEC ones; both coexist. ## Step 4.1: Pipeline Routing -The entry point `compileProgram()` (line ~1377) determines which pipeline to use based on -the board's `compiler_backend` field in `hals.json`: +The entry point `compileProgram()` determines which pipeline to use based on the board's +`compiler_backend` field in `hals.json`: ```typescript async compileProgram(args, _mainProcessPort, mainProcessBridge) { @@ -37,138 +35,82 @@ async compileProgram(args, _mainProcessPort, mainProcessBridge) { } ``` -Similarly for `compileForDebugger()` (line ~2157): - -```typescript -async compileForDebugger(args, _mainProcessPort, mainProcessBridge) { - const boardTarget = args[1] as string - const boardEntry = this.halsContent[boardTarget] - - if (boardEntry?.compiler_backend === 'strucpp') { - return this.compileForDebuggerWithSTruCpp(args, _mainProcessPort, mainProcessBridge) - } - // ... existing MatIEC debug pipeline -} -``` - ## Step 4.2: New STruC++ Compilation Pipeline ### Method: `compileArduinoWithSTruCpp()` ```typescript -private async compileArduinoWithSTruCpp( - args: Array, - _mainProcessPort: MessagePortMain, - mainProcessBridge: MainProcessBridgeType, -): Promise { +private async compileArduinoWithSTruCpp(args, _mainProcessPort, mainProcessBridge) { const projectData = args[0] as PLCProjectData const boardTarget = args[1] as string const projectPath = args[2] as string const compileOnly = args[3] as boolean - // ... extract other args const compilationPath = path.join(projectPath, 'build', boardTarget, 'src') try { // === STEP 1: Create directories (unchanged) === this.createBasicDirectories(projectPath, boardTarget) - this.postMessage(_mainProcessPort, 'info', 'Creating build directories...') // === STEP 2: Generate XML from JSON (unchanged) === - this.postMessage(_mainProcessPort, 'info', 'Generating IEC 61131-3 XML...') await this.handleGenerateXMLfromJSON(projectData, compilationPath) // === STEP 3: xml2st --generate-st (unchanged) === - this.postMessage(_mainProcessPort, 'info', 'Transpiling XML to Structured Text...') await this.handleTranspileXMLtoST(compilationPath) // Result: program.st in compilationPath - // === STEP 4: Copy STruC++ static files (NEW) === - this.postMessage(_mainProcessPort, 'info', 'Copying STruC++ runtime headers...') - this.copyStrucppStaticFiles(compilationPath) + // === STEP 4: Copy STruC++ files (NEW) === + this.copyStrucppFiles(compilationPath) // === STEP 5: Compile ST to C++ with STruC++ (NEW - replaces iec2c) === - this.postMessage(_mainProcessPort, 'info', 'Compiling Structured Text to C++...') - const strucppResult = await this.handleCompileSTtoCpp(compilationPath) - if (!strucppResult.success) { - const errorMsg = strucppResult.errors.map(e => `Line ${e.line}: ${e.message}`).join('\n') - this.postMessage(_mainProcessPort, 'error', `STruC++ compilation failed:\n${errorMsg}`) - this.closePort(_mainProcessPort) - return - } - - // === STEP 6: Compute MD5 (NEW approach) === - const stContent = fs.readFileSync(path.join(compilationPath, 'program.st'), 'utf-8') - const md5Hash = crypto.createHash('md5').update(stContent).digest('hex') - - // === STEP 7: Generate glue + debug files (NEW - replaces xml2st debug/glue) === - this.postMessage(_mainProcessPort, 'info', 'Generating I/O binding and debug maps...') - await this.handleGenerateGlueAndDebug(strucppResult, projectData, compilationPath, md5Hash, boardTarget) + await this.handleCompileSTtoCpp(compilationPath) - // === STEP 8: Generate C++ blocks header/code (unchanged) === - this.postMessage(_mainProcessPort, 'info', 'Processing C++ blocks...') + // === STEP 6: Generate C++ blocks header/code (unchanged) === await this.handleGenerateCBlocksHeader(projectData, compilationPath) await this.handleGenerateCBlocksCode(projectData, compilationPath) - // === STEP 9: Copy HAL file (unchanged) === - this.postMessage(_mainProcessPort, 'info', 'Configuring hardware abstraction...') + // === STEP 7: Copy HAL file (unchanged) === await this.handleGenerateArduinoCppFile(boardTarget, compilationPath) - // === STEP 10: Generate defines.h (modified - reads stContent for library detection) === - this.postMessage(_mainProcessPort, 'info', 'Generating definitions...') - await this.handleGenerateDefinitionsFileSTruCpp(projectData, boardTarget, compilationPath, md5Hash, stContent) + // === STEP 8: Generate defines.h (unchanged in structure) === + await this.handleGenerateDefinitionsFile(projectData, boardTarget, compilationPath) - // === STEP 11-12: Arduino compilation (modified - adds -std=gnu++17) === - this.postMessage(_mainProcessPort, 'info', 'Installing Arduino core...') + // === STEP 9: Arduino compilation (adds -std=gnu++17) === await this.handleCoreInstallation(boardTarget) await this.handleLibraryInstallation(boardTarget, compilationPath) + await this.handleCompileArduinoProgram(boardTarget, compilationPath, compileOnly) - this.postMessage(_mainProcessPort, 'info', 'Compiling Arduino program...') - await this.handleCompileArduinoProgramSTruCpp(boardTarget, compilationPath, compileOnly) - - // === STEP 13: Upload (unchanged) === + // === STEP 10: Upload (unchanged) === if (!compileOnly) { - this.postMessage(_mainProcessPort, 'info', 'Uploading firmware...') await this.handleUploadProgram(boardTarget, compilationPath) } - - this.postMessage(_mainProcessPort, 'info', 'Compilation successful!') - this.closePort(_mainProcessPort) - } catch (error) { - this.postMessage(_mainProcessPort, 'error', `Compilation failed: ${getErrorMessage(error)}`) - this.closePort(_mainProcessPort) + // error handling... } } ``` ## Step 4.3: New Private Methods -### `copyStrucppStaticFiles()` +### `copyStrucppFiles()` + +Copies the static Arduino sketch and STruC++ runtime headers to the build directory: ```typescript -private copyStrucppStaticFiles(compilationPath: string): void { - // Runtime headers -- downloaded by scripts/download-binaries.ts, NOT stored in repo - const strucppRuntimeDir = path.join(this.resourcesPath, 'strucpp', 'runtime', 'include') - const strucppBaremetalDir = path.join(this.resourcesPath, 'sources', 'StrucppBaremetal') - - // Copy C++ runtime headers to build directory - if (!fs.existsSync(strucppRuntimeDir)) { - throw new Error( - 'STruC++ runtime headers not found. Run "npm run setup:binaries" to download them.', - ) +private copyStrucppFiles(compilationPath: string): void { + // Runtime headers (downloaded by scripts/download-binaries.ts) + const runtimeDir = path.join(this.resourcesPath, 'strucpp', 'runtime', 'include') + if (!fs.existsSync(runtimeDir)) { + throw new Error('STruC++ runtime headers not found. Run "npm run setup:binaries".') } - const headers = fs.readdirSync(strucppRuntimeDir) - for (const file of headers) { - fs.copyFileSync( - path.join(strucppRuntimeDir, file), - path.join(compilationPath, file), - ) + for (const file of fs.readdirSync(runtimeDir)) { + fs.copyFileSync(path.join(runtimeDir, file), path.join(compilationPath, file)) } - // Copy StrucppBaremetal.ino (this IS stored in the repo) + // Static sketch (stored in the repo) + const sketchDir = path.join(this.resourcesPath, 'sources', 'StrucppBaremetal') fs.copyFileSync( - path.join(strucppBaremetalDir, 'StrucppBaremetal.ino'), + path.join(sketchDir, 'StrucppBaremetal.ino'), path.join(compilationPath, 'StrucppBaremetal.ino'), ) } @@ -176,270 +118,94 @@ private copyStrucppStaticFiles(compilationPath: string): void { ### `handleCompileSTtoCpp()` +Reads `program.st` and calls STruC++ `compile()` directly -- no wrapper: + ```typescript -private async handleCompileSTtoCpp(compilationPath: string): Promise { - const stFilePath = path.join(compilationPath, 'program.st') - const stSource = fs.readFileSync(stFilePath, 'utf-8') +import { compile } from 'strucpp' + +private async handleCompileSTtoCpp(compilationPath: string): Promise { + const stSource = fs.readFileSync(path.join(compilationPath, 'program.st'), 'utf-8') - // Compile with STruC++ - const result = compileWithSTruCpp(stSource, { + const libsDir = path.join(this.resourcesPath, 'strucpp', 'libs') + const result = compile(stSource, { headerFileName: 'generated.hpp', debug: true, lineMapping: true, + libraryPaths: fs.existsSync(libsDir) ? [libsDir] : [], }) - if (result.success) { - // Write generated files - fs.writeFileSync(path.join(compilationPath, 'generated.cpp'), result.cppCode) - fs.writeFileSync(path.join(compilationPath, 'generated.hpp'), result.headerCode) + if (!result.success) { + const msgs = result.errors.map(e => `Line ${e.line}: ${e.message}`).join('\n') + throw new Error(`STruC++ compilation failed:\n${msgs}`) } - return result -} -``` - -### `handleGenerateGlueAndDebug()` - -```typescript -private async handleGenerateGlueAndDebug( - strucppResult: STruCppResult, - projectData: PLCProjectData, - compilationPath: string, - md5Hash: string, - boardTarget: string, -): Promise { - const boardEntry = this.halsContent[boardTarget] - const boardMemoryClass = this.getBoardMemoryClass(boardTarget) - - // Generate generated_glue.hpp (I/O binding + scheduler + debug arrays) - const glueCode = generateArduinoGlue({ - configurationName: projectData.configurations?.resource?.[0]?.name ?? 'Config0', - taskIntervals: strucppResult.taskIntervals, - variableDescriptors: strucppResult.variableDescriptors, - md5Hash, - boardMemoryClass, - }) - fs.writeFileSync(path.join(compilationPath, 'generated_glue.hpp'), glueCode) - - // Generate debug-map.json - const gcdNs = computeTaskGCD(strucppResult.taskIntervals) - const debugMap = generateDebugMap( - strucppResult.variableDescriptors, - strucppResult.taskIntervals, - md5Hash, - gcdNs, - ) - fs.writeFileSync(path.join(compilationPath, 'debug-map.json'), debugMap) -} -``` - -### `handleCompileArduinoProgramSTruCpp()` - -```typescript -private async handleCompileArduinoProgramSTruCpp( - boardTarget: string, - compilationPath: string, - compileOnly: boolean, -): Promise { - const boardEntry = this.halsContent[boardTarget] - - // Ensure -std=gnu++17 is in CXX flags - const cxxFlags = boardEntry.cxx_flags ? [...boardEntry.cxx_flags] : [] - if (!cxxFlags.some(f => f.includes('-std='))) { - cxxFlags.push('-std=gnu++17') - } - - // Build the arduino-cli compile command - // Same structure as current handleCompileArduinoProgram() but with C++17 flag - const buildProperties = [ - `compiler.cpp.extra_flags=${cxxFlags.join(' ')}`, - // ... other build properties (same as current) - ] - - await this.executeArduinoCliCommand([ - 'compile', - '--fqbn', boardEntry.platform, - '--build-property', buildProperties.join(';'), - '--export-binaries', - compilationPath, - ]) -} -``` - -### `handleGenerateDefinitionsFileSTruCpp()` - -Same as current `handleGenerateDefinitionsFile()` but: -- Receives `stContent` (program.st text) as parameter instead of reading from file -- Uses the same library detection logic (scanning for DS18B20, P1AM, etc.) -- Embeds MD5 hash from parameter instead of regex extraction -- No changes to pin mapping, Modbus config, or board defines - -## Step 4.4: Debug Compilation Pipeline - -### Method: `compileForDebuggerWithSTruCpp()` - -Simplified pipeline that produces debug metadata without full Arduino compilation: - -```typescript -private async compileForDebuggerWithSTruCpp( - args: Array, - _mainProcessPort: MessagePortMain, - mainProcessBridge: MainProcessBridgeType, -): Promise { - const projectData = args[0] as PLCProjectData - const boardTarget = args[1] as string - const projectPath = args[2] as string - const compilationPath = path.join(projectPath, 'build', boardTarget, 'src') - - try { - // Steps 1-3: Same as full compile (create dirs, XML, ST) - this.createBasicDirectories(projectPath, boardTarget) - await this.handleGenerateXMLfromJSON(projectData, compilationPath) - await this.handleTranspileXMLtoST(compilationPath) - - // Step 4: Compile ST to C++ (for variable metadata) - const strucppResult = await this.handleCompileSTtoCpp(compilationPath) - if (!strucppResult.success) { - this.postMessage(_mainProcessPort, 'error', 'STruC++ compilation failed') - this.closePort(_mainProcessPort) - return - } - - // Step 5: Compute MD5 - const stContent = fs.readFileSync(path.join(compilationPath, 'program.st'), 'utf-8') - const md5Hash = crypto.createHash('md5').update(stContent).digest('hex') - - // Step 6: Generate debug-map.json only (no glue code needed for debug) - const gcdNs = computeTaskGCD(strucppResult.taskIntervals) - const debugMap = generateDebugMap( - strucppResult.variableDescriptors, - strucppResult.taskIntervals, - md5Hash, - gcdNs, - ) - fs.writeFileSync(path.join(compilationPath, 'debug-map.json'), debugMap) - - // Step 7: Generate C blocks (for variable detection) - await this.handleGenerateCBlocksHeader(projectData, compilationPath) - await this.handleGenerateCBlocksCode(projectData, compilationPath) - - // Done -- no Arduino compilation needed - this.postMessage(_mainProcessPort, 'info', 'Debug compilation complete') - this.closePort(_mainProcessPort) - - } catch (error) { - this.postMessage(_mainProcessPort, 'error', `Debug compilation failed: ${getErrorMessage(error)}`) - this.closePort(_mainProcessPort) - } + fs.writeFileSync(path.join(compilationPath, 'generated.cpp'), result.cppCode) + fs.writeFileSync(path.join(compilationPath, 'generated.hpp'), result.headerCode) } ``` -## Step 4.5: IPC Bridge Updates +That's it. No metadata extraction, no glue generation. The Arduino sketch handles +everything dynamically from the generated C++ structures. -### Read Debug Map +### Arduino Compilation Flag -The IPC bridge needs a new handler to read `debug-map.json`: +The `handleCompileArduinoProgram` method (or the hals.json entry) must ensure +`-std=gnu++17` is in the CXX flags. This can be done by: +- Adding it to hals.json for each board, or +- Injecting it programmatically when `compiler_backend === 'strucpp'` -**File to modify**: `src/main/modules/ipc/main.ts` - -```typescript -handleReadDebugMap = ( - _event: IpcMainEvent, - args: Array, -): Promise<{ success: boolean; content?: string; error?: string }> => { - const [projectPath, boardTarget] = args - const debugMapPath = path.join(projectPath, 'build', boardTarget, 'src', 'debug-map.json') - - if (!fs.existsSync(debugMapPath)) { - return { success: false, error: 'debug-map.json not found' } - } - - const content = fs.readFileSync(debugMapPath, 'utf-8') - return { success: true, content } -} -``` - -**File to modify**: `src/main/modules/preload/preload.ts` - -Expose the new handler: -```typescript -debuggerReadDebugMap: (projectPath: string, boardTarget: string) => - ipcRenderer.invoke('debugger:read-debug-map', [projectPath, boardTarget]) -``` - -## Step 4.6: Build Directory Structure +## Step 4.4: Build Directory Structure ### Old (MatIEC): ``` build/{boardTarget}/src/ - plc.xml - program.st + plc.xml, program.st lib/ <- MatIEC runtime headers - POUS.c <- MatIEC output - POUS.h - Res0.c - Config0.c - Config0.h + POUS.c, POUS.h <- MatIEC output + Res0.c, Config0.c, Config0.h LOCATED_VARIABLES.h glueVars.c <- xml2st output debug.c <- xml2st output VARIABLES.csv - c_blocks.h - c_blocks_code.cpp - arduino.cpp <- HAL file - defines.h + c_blocks.h, c_blocks_code.cpp + arduino.cpp, defines.h Baremetal.ino ``` ### New (STruC++): ``` build/{boardTarget}/src/ - plc.xml - program.st - iec_var.hpp <- Copied from resources/strucpp/runtime/include/ (downloaded) - iec_types.hpp <- (NOT stored in repo -- comes from STruC++ release) - iec_located.hpp - ... (other runtime headers) - generated.hpp <- STruC++ output - generated.cpp <- STruC++ output - generated_glue.hpp <- Glue generator output - debug-map.json <- Debug map - c_blocks.h - c_blocks_code.cpp - arduino.cpp <- HAL file (unchanged) - defines.h - openplc.h <- Buffer declarations (unchanged) - debug.h <- Debug function declarations (updated) - ModbusSlave.h <- Modbus + debug protocol (updated) - StrucppBaremetal.ino <- New Arduino sketch + plc.xml, program.st + iec_var.hpp, iec_types.hpp, iec_located.hpp, iec_std_lib.hpp, ... + <- Copied from resources/strucpp/runtime/include/ + generated.hpp <- STruC++ compile() output + generated.cpp <- STruC++ compile() output + c_blocks.h, c_blocks_code.cpp + arduino.cpp, defines.h + openplc.h <- Buffer declarations (adapted for STruC++) + StrucppBaremetal.ino <- Static sketch ``` +No glue files. No debug files (debugger is a separate phase). The sketch and generated +code together are self-contained. + ## Testing Strategy -1. **End-to-end Arduino compile**: Simple ST project through full pipeline - - Verify all generated files are present in build directory - - Verify arduino-cli compiles without errors +1. **End-to-end compile**: Simple ST project through the full pipeline + - Verify `generated.cpp` and `generated.hpp` are produced + - Verify arduino-cli compiles without errors for the Simulator target - Verify firmware binary is produced -2. **End-to-end debug compile**: Same project through debug pipeline - - Verify debug-map.json is generated - - Verify it contains correct variable metadata - - Verify no arduino-cli invocation (faster) - -3. **Pipeline routing**: Test that MatIEC boards still use old pipeline - - Set `compiler_backend: "matiec"` (or absent) in hals.json - - Verify old debug.c and glueVars.c are generated +2. **Pipeline routing**: MatIEC boards still use old pipeline + - Board with `compiler_backend: "matiec"` (or absent) → old debug.c/glueVars.c path + - Board with `compiler_backend: "strucpp"` → new STruC++ path -4. **Error handling**: Test STruC++ compilation error propagation - - Feed invalid ST code - - Verify error messages reach the frontend via MessagePort +3. **Error handling**: Invalid ST code → STruC++ errors propagated to UI -5. **Regression**: All existing compiler-module.spec.ts tests pass unchanged +4. **Regression**: All existing compiler tests pass for MatIEC boards ## Files Created/Modified | File | Action | |------|--------| -| `src/backend/editor/compiler/compiler-module.ts` | Modified -- add STruC++ pipeline methods | -| `src/main/modules/ipc/main.ts` | Modified -- add debug map read handler | -| `src/main/modules/preload/preload.ts` | Modified -- expose debug map reader | +| `src/backend/editor/compiler/compiler-module.ts` | Modified -- add STruC++ pipeline | diff --git a/docs/strucpp-migration/06-runtime-v4-so-interface.md b/docs/strucpp-migration/06-runtime-v4-so-interface.md index c797cab1f..ac03a65e9 100644 --- a/docs/strucpp-migration/06-runtime-v4-so-interface.md +++ b/docs/strucpp-migration/06-runtime-v4-so-interface.md @@ -9,7 +9,7 @@ core C code (initially). ## Prerequisites -- Phase 1 (STruC++ compiler wrapper) +- Phase 1 (STruC++ dependency infrastructure) - Runtime v4 codebase at `~/Documents/Code/openplc-runtime` ## Current Runtime Symbol Interface @@ -46,31 +46,19 @@ void (*ext_set_endianness)(uint8_t); char *ext_plc_program_md5; ``` -## Step 6.1: Create v4 Compatibility Code Generator +## Step 6.1: v4 Compatibility Shim -**New file**: `src/backend/shared/utils/PLC/generate-v4-compat.ts` +A `v4_compat.cpp` file wraps STruC++ generated code with the C-linkage symbols the runtime +expects. Following the same philosophy as the Arduino sketch, this should be as static as +possible, navigating STruC++ structures dynamically rather than requiring per-project code +generation. However, since the runtime resolves symbols via `dlsym()` with a fixed C ABI, +a thin shim with `extern "C"` functions is needed. -This module generates `v4_compat.cpp` -- a C++ file that wraps STruC++ generated code with -the C-linkage symbols the runtime expects. +Since `Configuration_Config0` is always the configuration name (hardcoded by OpenPLC), +the shim can be mostly static -- the same approach as the Arduino sketch. It walks +`ConfigurationInstance::get_resources()` dynamically for task/program discovery. -### Public API - -```typescript -export interface V4CompatInput { - /** Configuration class name from STruC++ (e.g., "Config0") */ - configurationName: string - /** Task intervals for GCD scheduler */ - taskIntervals: TaskInterval[] - /** Variable descriptors for debug interface */ - variableDescriptors: ProgramVarDescriptor[] - /** MD5 hash of program.st */ - md5Hash: string -} - -export function generateV4Compat(input: V4CompatInput): string -``` - -### Generated v4_compat.cpp Structure +### v4_compat.cpp Structure ```cpp // v4_compat.cpp @@ -414,6 +402,6 @@ calls `config_init__` from the PLC cycle thread, which is single-threaded at tha | File | Action | |------|--------| -| `src/backend/shared/utils/PLC/generate-v4-compat.ts` | **New** -- v4 compatibility generator | +| `resources/sources/StrucppRuntime/v4_compat.cpp` | **New** -- static C-linkage shim | | `openplc-runtime/scripts/compile.sh` | Modified -- C++17 compilation support | | `src/backend/editor/compiler/compiler-module.ts` | Modified -- v4 upload path | From d88683b0128ce20b2025bd2d941c9814d0052c25 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 15:40:39 -0400 Subject: [PATCH 016/296] docs: reorganize phases for code-generation-first approach Reorder phases so the editor compiler pipeline (code generation) comes before the Arduino runtime (code consumption). This lets us validate STruC++ output before building the runtime against it. New phase order: Phase 1: STruC++ dependency infrastructure (done) Phase 2: Editor compiler pipeline (wire compile() into compiler-module) Phase 3: Arduino runtime adaptation (sketch + openplc.h) Phase 4: Debugger (deferred) Phase 5-7: Runtime v4 (renumbered from 6-8) Also fix download-binaries.ts to use --no-save when installing strucpp to avoid polluting package.json with temp paths. Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/strucpp-migration/00-overview.md | 76 +-- ...dule.md => 02-editor-compiler-pipeline.md} | 145 +++-- ...on.md => 03-arduino-runtime-adaptation.md} | 77 +-- .../03-debugger-variable-access.md | 580 ------------------ docs/strucpp-migration/04-debugger.md | 56 ++ .../05-editor-frontend-debugger.md | 480 --------------- ...rface.md => 05-runtime-v4-so-interface.md} | 2 +- ...sk.md => 06-runtime-v4-thread-per-task.md} | 8 +- ...dler.md => 07-runtime-v4-debug-handler.md} | 20 +- scripts/download-binaries.ts | 2 +- 10 files changed, 223 insertions(+), 1223 deletions(-) rename docs/strucpp-migration/{04-editor-compiler-module.md => 02-editor-compiler-pipeline.md} (51%) rename docs/strucpp-migration/{02-arduino-runtime-adaptation.md => 03-arduino-runtime-adaptation.md} (81%) delete mode 100644 docs/strucpp-migration/03-debugger-variable-access.md create mode 100644 docs/strucpp-migration/04-debugger.md delete mode 100644 docs/strucpp-migration/05-editor-frontend-debugger.md rename docs/strucpp-migration/{06-runtime-v4-so-interface.md => 05-runtime-v4-so-interface.md} (99%) rename docs/strucpp-migration/{07-runtime-v4-thread-per-task.md => 06-runtime-v4-thread-per-task.md} (98%) rename docs/strucpp-migration/{08-runtime-v4-debug-handler.md => 07-runtime-v4-debug-handler.md} (95%) diff --git a/docs/strucpp-migration/00-overview.md b/docs/strucpp-migration/00-overview.md index b6f3435e4..74c184d5b 100644 --- a/docs/strucpp-migration/00-overview.md +++ b/docs/strucpp-migration/00-overview.md @@ -32,7 +32,7 @@ STruC++ solves both problems: | XML generation from project JSON | Unchanged | | `arduino-cli` compilation/upload | Unchanged (now compiles C++ instead of C) | | HAL files (`resources/sources/hal/*.cpp`) | Unchanged (same buffer pointer interface) | -| Modbus slave communication | Unchanged (debug handler functions updated) | +| Modbus slave communication | Unchanged (debug handler functions updated later) | | Frontend project data handling | Unchanged | | POU preprocessing (Python/C++ wrappers) | Unchanged | @@ -41,11 +41,10 @@ STruC++ solves both problems: | Old Component | New Component | |---------------|---------------| | `iec2c` binary (ST to C) | STruC++ `compile()` (ST to C++17) | -| `xml2st --generate-debug` (debug.c) | New debug-map.json from STruC++ metadata | -| `xml2st --generate-gluevars` (glueVars.c) | New `generated_glue.hpp` from LocatedVar descriptors | +| `xml2st --generate-debug` (debug.c) | Deferred -- redesigned in Phase 4 | +| `xml2st --generate-gluevars` (glueVars.c) | Not needed -- sketch walks `locatedVars[]` dynamically | | MatIEC lib/ headers | STruC++ runtime headers (header-only C++17) | | `Baremetal.ino` (C integration) | `StrucppBaremetal.ino` (C++ integration) | -| Flat debug_vars[] array | Hierarchical (program_idx, var_idx) addressing | | Single `config_run__(tick)` | Per-program `run()` with GCD task scheduler | ## Revised Pipeline @@ -69,49 +68,54 @@ task intervals -- all at runtime, same code for every project. ## Phase Structure -The migration is organized into 8 phases across two parts: +Implementation follows this order -- code generation first, then the runtime that consumes it. ### Part A: Arduino Target (Primary Focus) | Phase | Title | Description | |-------|-------|-------------| | 1 | [STruC++ Compiler Integration](01-strucpp-compiler-integration.md) | Dependency infrastructure: version tracking, download, setup | -| 2 | [Arduino Runtime Adaptation](02-arduino-runtime-adaptation.md) | Static Arduino sketch navigating STruC++ structures | -| 3 | [Debugger Variable Access](03-debugger-variable-access.md) | Hierarchical debug system, protocol update | -| 4 | [Editor Compiler Module](04-editor-compiler-module.md) | Wire new pipeline into compiler-module.ts | -| 5 | [Editor Frontend Debugger](05-editor-frontend-debugger.md) | Update UI for debug-map.json and hierarchical refs | +| 2 | [Editor Compiler Pipeline](02-editor-compiler-pipeline.md) | Wire `compile()` into compiler-module.ts, generate C++ from ST | +| 3 | [Arduino Runtime Adaptation](03-arduino-runtime-adaptation.md) | Static sketch that navigates STruC++ structures dynamically | +| 4 | [Debugger](04-debugger.md) | Deferred -- redesign when runtime is stable | ### Part B: OpenPLC Runtime v4 (Secondary) | Phase | Title | Description | |-------|-------|-------------| -| 6 | [Runtime .so Interface](06-runtime-v4-so-interface.md) | C-linkage compatibility shims for existing runtime | -| 7 | [Thread-Per-Task Model](07-runtime-v4-thread-per-task.md) | Per-task pthreads instead of round-robin | -| 8 | [Runtime Debug Handler](08-runtime-v4-debug-handler.md) | Native hierarchical debug in runtime | +| 5 | [Runtime .so Interface](05-runtime-v4-so-interface.md) | C-linkage compatibility shims for existing runtime | +| 6 | [Thread-Per-Task Model](06-runtime-v4-thread-per-task.md) | Per-task pthreads instead of round-robin | +| 7 | [Runtime Debug Handler](07-runtime-v4-debug-handler.md) | Native hierarchical debug in runtime | + +### Rationale for Phase Order + +**Phase 2 before Phase 3**: We wire the compilation pipeline first so that STruC++ generates +`generated.cpp` and `generated.hpp` from `program.st`. The arduino-cli compilation will fail +at this point (the Arduino sketch isn't ready), but we can validate that the C++ code generation +works correctly. This gives us concrete output to design the Arduino runtime against. + +**Phase 4 deferred**: The debugger is complex and benefits from being designed after the +runtime is working. By the time we reach Phase 4, we'll have a better understanding of what +the runtime actually needs and can design a cleaner debugger approach. ## Dependency Graph ``` -Phase 1 (STruC++ compiler wrapper) +Phase 1 (STruC++ dependency infrastructure) | - +---> Phase 2 (Arduino glue generation + new sketch) + +---> Phase 2 (Editor compiler pipeline -- generates C++) | | - | +---> Phase 3 (Debug arrays + protocol) + | +---> Phase 3 (Arduino runtime -- compiles and runs C++) | | - | +---> Phase 4 (Compiler module wiring) - | | - | +---> Phase 5 (Frontend debugger) + | +---> Phase 4 (Debugger -- deferred) | - +---> Phase 6 (v4_compat.cpp) + +---> Phase 5 (Runtime v4 .so interface) | - +---> Phase 7 (Thread-per-task) + +---> Phase 6 (Thread-per-task) | - +---> Phase 8 (Runtime debug handler) + +---> Phase 7 (Runtime v4 debug handler) ``` -The Arduino path (Phases 1-5) and Runtime v4 path (Phases 6-8) share only Phase 1. -After Phase 1 is complete, both paths can proceed independently. - ## Key Architectural Decisions ### 1. Dual Pipeline Coexistence @@ -120,7 +124,18 @@ Both MatIEC and STruC++ pipelines coexist in the compiler module. A `"compiler_b in `hals.json` per board determines which pipeline is used. This allows gradual migration -- boards can be switched one at a time. -### 2. IECVar and Forced Input Handling +### 2. Static Arduino Runtime (No Glue Code Generator) + +The Arduino sketch is fully static C++ code. It navigates STruC++ runtime structures at +`setup()` time using the same generic algorithm for every project: +- `Configuration_Config0` (always this name -- hardcoded by OpenPLC) +- `ConfigurationInstance::get_resources()` → `ResourceInstance::tasks` → `TaskInstance` +- `locatedVars[]` array for I/O binding +- `ProgramBase::run()` for execution + +No TypeScript code generator produces per-project C++ glue code. + +### 3. IECVar and Forced Input Handling STruC++ wraps all variables in `IECVar` which has built-in forcing: - `get()`: returns forced_value_ when forced, value_ otherwise @@ -128,17 +143,6 @@ STruC++ wraps all variables in `IECVar` which has built-in forcing: - `force(v)`: sets both forced_value_ and value_ (so raw_ptr() readers see it too) - `raw_ptr()`: returns &value_ for I/O driver binding -For **input** variables, the HAL writes hardware values directly via `raw_ptr()`, overwriting -`value_`. Since `get()` returns `forced_value_` when forced, PLC logic is correct. But the debug -system needs a `strucpp_restore_forced_inputs()` call after HAL reads to ensure `value_` reflects -the forced state for any readers using `raw_ptr()`. - -### 3. No Array Expansion in Debug - -The fundamental scalability fix: arrays get ONE entry in the variable descriptor table, not one -per element. The debugger accesses individual array elements on-demand via offset calculations, -and the frontend lazily loads array elements when the user expands them in the variable tree. - ### 4. C++17 Requirement All Arduino boards need `-std=gnu++17` added to CXX compilation flags. This is supported by: diff --git a/docs/strucpp-migration/04-editor-compiler-module.md b/docs/strucpp-migration/02-editor-compiler-pipeline.md similarity index 51% rename from docs/strucpp-migration/04-editor-compiler-module.md rename to docs/strucpp-migration/02-editor-compiler-pipeline.md index ac919a6c2..cc8d939f8 100644 --- a/docs/strucpp-migration/04-editor-compiler-module.md +++ b/docs/strucpp-migration/02-editor-compiler-pipeline.md @@ -1,15 +1,20 @@ -# Phase 4: Editor Compiler Module Updates +# Phase 2: Editor Compiler Pipeline ## Goal -Wire the STruC++ compilation into `compiler-module.ts`: read `program.st`, call `compile()` -directly, write the generated C++ files, copy runtime headers, and invoke `arduino-cli` with -C++17 flags. No wrapper module, no glue code generator -- just direct integration. +Wire STruC++ `compile()` into `compiler-module.ts` so that when a board uses the STruC++ +backend, the editor reads `program.st`, compiles it to C++, and writes `generated.cpp` + +`generated.hpp` to the build directory. This validates that the code generation pipeline +works end-to-end. + +At this stage, the `arduino-cli` compilation step will fail because the Arduino runtime +(sketch, adapted `openplc.h`) is not yet ready for STruC++ output. That's expected -- the +goal is to verify C++ code generation, not a compilable firmware. Phase 3 addresses the +runtime. ## Prerequisites -- Phase 1 (STruC++ installed in node_modules, runtime headers at resources/strucpp/) -- Phase 2 (static StrucppBaremetal.ino sketch) +- Phase 1 complete (STruC++ installed in `node_modules`, runtime headers at `resources/strucpp/`) ## Primary File @@ -18,10 +23,10 @@ C++17 flags. No wrapper module, no glue code generator -- just direct integratio This is the main compilation orchestrator. The STruC++ pipeline adds new methods alongside the existing MatIEC ones; both coexist. -## Step 4.1: Pipeline Routing +## Step 2.1: Pipeline Routing -The entry point `compileProgram()` determines which pipeline to use based on the board's -`compiler_backend` field in `hals.json`: +Add a `"compiler_backend"` field to `hals.json` board entries. The entry point +`compileProgram()` checks this field to route to the appropriate pipeline: ```typescript async compileProgram(args, _mainProcessPort, mainProcessBridge) { @@ -31,11 +36,16 @@ async compileProgram(args, _mainProcessPort, mainProcessBridge) { if (boardEntry?.compiler_backend === 'strucpp') { return this.compileArduinoWithSTruCpp(args, _mainProcessPort, mainProcessBridge) } - // ... existing MatIEC pipeline + // ... existing MatIEC pipeline (unchanged) } ``` -## Step 4.2: New STruC++ Compilation Pipeline +**File to modify**: `resources/sources/boards/hals.json` + +Add `"compiler_backend": "strucpp"` to boards being migrated. Boards without this field (or +with `"matiec"`) continue using the existing pipeline. + +## Step 2.2: New STruC++ Compilation Pipeline ### Method: `compileArduinoWithSTruCpp()` @@ -59,28 +69,31 @@ private async compileArduinoWithSTruCpp(args, _mainProcessPort, mainProcessBridg await this.handleTranspileXMLtoST(compilationPath) // Result: program.st in compilationPath - // === STEP 4: Copy STruC++ files (NEW) === - this.copyStrucppFiles(compilationPath) + // === STEP 4: Copy STruC++ runtime headers to build dir (NEW) === + this.copyStrucppRuntimeHeaders(compilationPath) // === STEP 5: Compile ST to C++ with STruC++ (NEW - replaces iec2c) === - await this.handleCompileSTtoCpp(compilationPath) + this.handleCompileSTtoCpp(compilationPath) - // === STEP 6: Generate C++ blocks header/code (unchanged) === + // === STEP 6: Copy Arduino sketch + static files (NEW) === + this.copyStrucppSketchFiles(compilationPath) + + // === STEP 7: Generate C++ blocks header/code (unchanged) === await this.handleGenerateCBlocksHeader(projectData, compilationPath) await this.handleGenerateCBlocksCode(projectData, compilationPath) - // === STEP 7: Copy HAL file (unchanged) === + // === STEP 8: Copy HAL file (unchanged) === await this.handleGenerateArduinoCppFile(boardTarget, compilationPath) - // === STEP 8: Generate defines.h (unchanged in structure) === + // === STEP 9: Generate defines.h (unchanged in structure) === await this.handleGenerateDefinitionsFile(projectData, boardTarget, compilationPath) - // === STEP 9: Arduino compilation (adds -std=gnu++17) === + // === STEP 10: Arduino compilation (adds -std=gnu++17) === await this.handleCoreInstallation(boardTarget) await this.handleLibraryInstallation(boardTarget, compilationPath) await this.handleCompileArduinoProgram(boardTarget, compilationPath, compileOnly) - // === STEP 10: Upload (unchanged) === + // === STEP 11: Upload (unchanged) === if (!compileOnly) { await this.handleUploadProgram(boardTarget, compilationPath) } @@ -90,15 +103,14 @@ private async compileArduinoWithSTruCpp(args, _mainProcessPort, mainProcessBridg } ``` -## Step 4.3: New Private Methods +## Step 2.3: New Private Methods -### `copyStrucppFiles()` +### `copyStrucppRuntimeHeaders()` -Copies the static Arduino sketch and STruC++ runtime headers to the build directory: +Copies the STruC++ C++ runtime headers to the build directory: ```typescript -private copyStrucppFiles(compilationPath: string): void { - // Runtime headers (downloaded by scripts/download-binaries.ts) +private copyStrucppRuntimeHeaders(compilationPath: string): void { const runtimeDir = path.join(this.resourcesPath, 'strucpp', 'runtime', 'include') if (!fs.existsSync(runtimeDir)) { throw new Error('STruC++ runtime headers not found. Run "npm run setup:binaries".') @@ -106,24 +118,31 @@ private copyStrucppFiles(compilationPath: string): void { for (const file of fs.readdirSync(runtimeDir)) { fs.copyFileSync(path.join(runtimeDir, file), path.join(compilationPath, file)) } +} +``` + +### `copyStrucppSketchFiles()` - // Static sketch (stored in the repo) +Copies the static Arduino sketch and OpenPLC support files to the build directory: + +```typescript +private copyStrucppSketchFiles(compilationPath: string): void { const sketchDir = path.join(this.resourcesPath, 'sources', 'StrucppBaremetal') - fs.copyFileSync( - path.join(sketchDir, 'StrucppBaremetal.ino'), - path.join(compilationPath, 'StrucppBaremetal.ino'), - ) + // Copy all files from the StrucppBaremetal directory + for (const file of fs.readdirSync(sketchDir)) { + fs.copyFileSync(path.join(sketchDir, file), path.join(compilationPath, file)) + } } ``` ### `handleCompileSTtoCpp()` -Reads `program.st` and calls STruC++ `compile()` directly -- no wrapper: +Reads `program.st` and calls STruC++ `compile()` directly: ```typescript import { compile } from 'strucpp' -private async handleCompileSTtoCpp(compilationPath: string): Promise { +private handleCompileSTtoCpp(compilationPath: string): void { const stSource = fs.readFileSync(path.join(compilationPath, 'program.st'), 'utf-8') const libsDir = path.join(this.resourcesPath, 'strucpp', 'libs') @@ -144,17 +163,36 @@ private async handleCompileSTtoCpp(compilationPath: string): Promise { } ``` -That's it. No metadata extraction, no glue generation. The Arduino sketch handles -everything dynamically from the generated C++ structures. +### C++17 Compilation Flag + +The `handleCompileArduinoProgram` method must ensure `-std=gnu++17` is in the CXX flags +when `compiler_backend === 'strucpp'`. This can be done by: +- Adding `"-std=gnu++17"` to `cxx_flags` in hals.json for each board, or +- Injecting it programmatically in the STruC++ pipeline path + +## Step 2.4: hals.json Changes + +**File to modify**: `resources/sources/boards/hals.json` -### Arduino Compilation Flag +For boards being migrated, add: +```json +{ + "compiler_backend": "strucpp", + "cxx_flags": ["-std=gnu++17", "-MMD", "-c"] +} +``` -The `handleCompileArduinoProgram` method (or the hals.json entry) must ensure -`-std=gnu++17` is in the CXX flags. This can be done by: -- Adding it to hals.json for each board, or -- Injecting it programmatically when `compiler_backend === 'strucpp'` +**C++17 support by platform**: -## Step 4.4: Build Directory Structure +| Platform | GCC Version | C++17 Support | +|----------|-------------|---------------| +| Arduino AVR | 7.3+ | Yes (bundled with Arduino IDE 2.x) | +| ESP32 | 8.4+ (ESP-IDF) | Yes | +| STM32 | 10+ (STM32duino) | Yes | +| RP2040 | 10+ (Arduino Mbed) | Yes | +| SAMD | 7.2+ | Yes | + +## Step 2.5: Build Directory Structure ### Old (MatIEC): ``` @@ -164,8 +202,7 @@ build/{boardTarget}/src/ POUS.c, POUS.h <- MatIEC output Res0.c, Config0.c, Config0.h LOCATED_VARIABLES.h - glueVars.c <- xml2st output - debug.c <- xml2st output + glueVars.c, debug.c <- xml2st output VARIABLES.csv c_blocks.h, c_blocks_code.cpp arduino.cpp, defines.h @@ -182,25 +219,22 @@ build/{boardTarget}/src/ generated.cpp <- STruC++ compile() output c_blocks.h, c_blocks_code.cpp arduino.cpp, defines.h - openplc.h <- Buffer declarations (adapted for STruC++) - StrucppBaremetal.ino <- Static sketch + openplc.h <- Buffer declarations (adapted for STruC++ in Phase 3) + StrucppBaremetal.ino <- Static sketch (from Phase 3) ``` -No glue files. No debug files (debugger is a separate phase). The sketch and generated -code together are self-contained. - ## Testing Strategy -1. **End-to-end compile**: Simple ST project through the full pipeline - - Verify `generated.cpp` and `generated.hpp` are produced - - Verify arduino-cli compiles without errors for the Simulator target - - Verify firmware binary is produced +1. **Code generation**: Compile a simple ST project through the pipeline + - Verify `generated.cpp` and `generated.hpp` are produced in the build directory + - Verify the generated code contains expected classes (`Configuration_Config0`, program classes) + - The `arduino-cli` step is expected to fail until Phase 3 provides the sketch -2. **Pipeline routing**: MatIEC boards still use old pipeline - - Board with `compiler_backend: "matiec"` (or absent) → old debug.c/glueVars.c path - - Board with `compiler_backend: "strucpp"` → new STruC++ path +2. **Pipeline routing**: Verify MatIEC boards are unaffected + - Board without `compiler_backend` field → old pipeline produces `POUS.c`, `Config0.c`, etc. + - Board with `compiler_backend: "strucpp"` → new pipeline produces `generated.cpp`, `generated.hpp` -3. **Error handling**: Invalid ST code → STruC++ errors propagated to UI +3. **Error handling**: Invalid ST code → STruC++ errors propagated to the UI console 4. **Regression**: All existing compiler tests pass for MatIEC boards @@ -208,4 +242,5 @@ code together are self-contained. | File | Action | |------|--------| -| `src/backend/editor/compiler/compiler-module.ts` | Modified -- add STruC++ pipeline | +| `src/backend/editor/compiler/compiler-module.ts` | Modified -- add STruC++ pipeline methods | +| `resources/sources/boards/hals.json` | Modified -- add `compiler_backend` and `cxx_flags` | diff --git a/docs/strucpp-migration/02-arduino-runtime-adaptation.md b/docs/strucpp-migration/03-arduino-runtime-adaptation.md similarity index 81% rename from docs/strucpp-migration/02-arduino-runtime-adaptation.md rename to docs/strucpp-migration/03-arduino-runtime-adaptation.md index 34595eff9..b8235088e 100644 --- a/docs/strucpp-migration/02-arduino-runtime-adaptation.md +++ b/docs/strucpp-migration/03-arduino-runtime-adaptation.md @@ -1,19 +1,19 @@ -# Phase 2: Arduino Runtime C++ Adaptation +# Phase 3: Arduino Runtime Adaptation ## Goal -Create a static Arduino sketch that works with STruC++ generated C++ code. The sketch -navigates STruC++ runtime structures dynamically -- it walks `locatedVars[]` for I/O binding, -walks the `Configuration` class for task discovery and scheduling, and computes +Create a static Arduino sketch that works with the STruC++ generated C++ files produced by +Phase 2. The sketch navigates STruC++ runtime structures dynamically -- it walks `locatedVars[]` +for I/O binding, walks the `Configuration` class for task discovery and scheduling, and computes `common_ticktime__` from task intervals. The same sketch code works for every project. -No glue code generator is needed. No per-project code generation beyond what STruC++ already -produces (`generated.cpp` + `generated.hpp`). +After this phase, the full pipeline works end-to-end: `program.st` → `compile()` → +`generated.cpp` + `generated.hpp` → `arduino-cli` → firmware binary. ## Prerequisites - Phase 1 complete (STruC++ dependency infrastructure) -- STruC++ runtime headers available at `resources/strucpp/runtime/include/` +- Phase 2 complete (compiler pipeline generates `generated.cpp` + `generated.hpp`) ## Key STruC++ Runtime Types @@ -71,16 +71,7 @@ struct LocatedVar { The generated code always names the configuration class `Configuration_Config0` (OpenPLC always uses `Config0` as the configuration name -- this is not user-configurable). -## Step 2.1: STruC++ Runtime Headers - -The C++ runtime headers are **NOT** stored in this repository. They are downloaded alongside -the STruC++ compiler by `scripts/download-binaries.ts` (see Phase 1) and placed at -`resources/strucpp/runtime/include/`. This directory is `.gitignore`'d. - -At compile time, the compiler module copies these headers to the build directory alongside -the generated `.cpp`/`.hpp` files. - -## Step 2.2: Create New Arduino Sketch +## Step 3.1: Create New Arduino Sketch **New file**: `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` @@ -229,7 +220,7 @@ void plcCycleTask() { | Modbus | Unchanged | Unchanged | | HAL | Unchanged | Unchanged | -### What Changes in openplc.h +## Step 3.2: Adapt openplc.h The current `openplc.h` declares MatIEC-specific functions (`config_init__`, `config_run__`, `glueVars`, `updateTime`). For STruC++, these are no longer needed -- the sketch handles @@ -241,36 +232,6 @@ everything directly. The sketch needs a version of `openplc.h` that only has: The MatIEC-specific declarations should be guarded or removed in the STruC++ variant. -## Step 2.3: C++17 Compilation Flag - -**File to modify**: `resources/sources/boards/hals.json` - -Add `-std=gnu++17` to CXX flags and `"compiler_backend": "strucpp"` field per board: - -```json -{ - "Arduino Uno": { - "compiler": "arduino-cli", - "core": "arduino:avr", - "platform": "arduino:avr:uno", - "source": "uno_leonardo_nano_micro_zero.cpp", - "cxx_flags": ["-std=gnu++17", "-MMD", "-c"], - "compiler_backend": "strucpp", - ... - } -} -``` - -**C++17 support by platform**: - -| Platform | GCC Version | C++17 Support | -|----------|-------------|---------------| -| Arduino AVR | 7.3+ | Yes (bundled with Arduino IDE 2.x) | -| ESP32 | 8.4+ (ESP-IDF) | Yes | -| STM32 | 10+ (STM32duino) | Yes | -| RP2040 | 10+ (Arduino Mbed) | Yes | -| SAMD | 7.2+ | Yes | - ## Design Notes ### Why the Sketch is Fully Static @@ -312,16 +273,21 @@ instance (pointer + divisor). ## Testing Strategy -1. **Minimal project test**: Single program, one digital output (%QX0.0) - - Verify `bool_output[0][0]` is bound to the variable's `raw_ptr()` - - Compile with arduino-cli for Simulator target +1. **End-to-end compile**: Simple ST project through the full pipeline + - Phase 2 generates `generated.cpp` and `generated.hpp` + - This phase's sketch + adapted `openplc.h` make `arduino-cli` succeed + - Verify firmware binary is produced + +2. **Simulator test**: Run on the ATmega2560 simulator + - Verify scan cycle runs + - Verify located variables are bound to I/O buffers -2. **Multi-task test**: Two tasks at T#20ms and T#40ms +3. **Multi-task test**: Two tasks at T#20ms and T#40ms - Verify GCD computation: `common_ticktime__ = 20000000` - Verify divisors: `[1, 2]` - Verify task1 runs every cycle, task2 every other cycle -3. **HAL compatibility test**: Compile with each major HAL file +4. **HAL compatibility test**: Compile with each major HAL file - Verify no compilation errors with STruC++ C++17 code ## Files Created/Modified @@ -329,7 +295,6 @@ instance (pointer + divisor). | File | Action | |------|--------| | `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` | **New** -- static Arduino sketch | -| `resources/sources/boards/hals.json` | Modified -- add cxx_flags, compiler_backend | +| `resources/sources/arduino/openplc.h` | Modified -- guard or remove MatIEC-specific declarations | -Note: Runtime headers come from `resources/strucpp/runtime/include/` (downloaded, Phase 1). -No glue code generator. No per-project code generation. +Note: Runtime headers come from `resources/strucpp/runtime/include/` (downloaded in Phase 1). diff --git a/docs/strucpp-migration/03-debugger-variable-access.md b/docs/strucpp-migration/03-debugger-variable-access.md deleted file mode 100644 index 79383c4c6..000000000 --- a/docs/strucpp-migration/03-debugger-variable-access.md +++ /dev/null @@ -1,580 +0,0 @@ -# Phase 3: Debugger Variable Access System - -## Goal - -Replace the flat `debug_vars[]` array (which expands arrays element-by-element) with a -hierarchical `(program_idx, var_idx)` addressing scheme. This is the core fix for the -debugger scalability problem. - -## Prerequisites - -- Phase 1 (STruC++ compiler wrapper providing variable descriptors) -- Phase 2 (generated_glue.hpp structure for debug arrays) - -## The Scalability Problem - -### Current System (MatIEC + debug.c) - -The `debug.c` file generated by xml2st creates a flat array: - -```c -static const struct { void *ptr; __IEC_types_enum type; } debug_vars[] = { - {&(CONFIG0__INSTANCE0.counter), INT_ENUM}, - {&(CONFIG0__INSTANCE0.speeds.table[0]), INT_ENUM}, // ARRAY[0..99] expanded! - {&(CONFIG0__INSTANCE0.speeds.table[1]), INT_ENUM}, - // ... 98 more entries for this single array - {&(CONFIG0__INSTANCE0.speeds.table[99]), INT_ENUM}, -}; -#define VAR_COUNT 101 -``` - -For the reported project with ~3,500 variables (many arrays), this expands to 30,000+ entries: -- Each entry: 4 bytes (pointer) + 4 bytes (enum) = 8 bytes -- 30,000 entries = 240 KB of RAM just for the debug array -- ATmega2560 has 8 KB SRAM total -- Even on 32-bit platforms, this is a massive allocation - -### New System (STruC++ + hierarchical addressing) - -```cpp -// Program 0: 3 variables (counter + speeds array + timer) -// The 100-element array is ONE entry, not 100 -static void* g_prog0_ptrs[] = { - g_config.instance0.counter.raw_ptr(), // index 0: INT - &g_config.instance0.speeds, // index 1: ARRAY[0..99] OF INT (one entry!) - g_config.instance0.timer.raw_ptr(), // index 2: TIME -}; -// 3 entries instead of 102 -``` - -**Scalability win**: The sample project's `ST_GV_HMI_PLC_VARS` struct has 3,491 fields. -With arrays un-expanded, the actual descriptor count is dramatically smaller. Array elements -are accessed on-demand by the debugger using offset calculations. - -## Step 3.1: Debug Infrastructure in generated_glue.hpp - -The `generateArduinoGlue()` function from Phase 2 appends debug infrastructure to -`generated_glue.hpp`. This section details the exact generated code. - -### Per-Program Variable Arrays - -For each program instance, generate four parallel arrays: - -```cpp -// ========== Debug Infrastructure ========== - -// --- Program 0: "instance0" (type: Main) --- - -// Raw storage pointers (for reading variable values) -static void* g_prog0_ptrs[] = { - g_config.instance0.counter.raw_ptr(), // [0] INT, 2 bytes - g_config.instance0.running.raw_ptr(), // [1] BOOL, 1 byte - g_config.instance0.motor_speed.raw_ptr(), // [2] INT, 2 bytes - (void*)&g_config.instance0.speeds, // [3] ARRAY[0..99] OF INT -}; - -// Variable sizes (bytes per element) -static const uint8_t g_prog0_sizes[] = { 2, 1, 2, 2 }; - -// Type-erased get functions -// Return the correct value even when forced (uses IECVar::get() not raw_ptr) -typedef void (*debug_get_fn)(void*); -static const debug_get_fn g_prog0_get_fns[] = { - [](void* d) { *(int16_t*)d = g_config.instance0.counter.get(); }, - [](void* d) { *(bool*)d = g_config.instance0.running.get(); }, - [](void* d) { *(int16_t*)d = g_config.instance0.motor_speed.get(); }, - nullptr, // Array: use element access instead -}; - -// Type-erased force/unforce functions -typedef void (*debug_force_fn)(bool, void*); -static const debug_force_fn g_prog0_force_fns[] = { - [](bool f, void* v) { - if (f) g_config.instance0.counter.force(*(int16_t*)v); - else g_config.instance0.counter.unforce(); - }, - [](bool f, void* v) { - if (f) g_config.instance0.running.force(*(bool*)v); - else g_config.instance0.running.unforce(); - }, - [](bool f, void* v) { - if (f) g_config.instance0.motor_speed.force(*(int16_t*)v); - else g_config.instance0.motor_speed.unforce(); - }, - nullptr, // Array: force individual elements via element access -}; - -// Variable type tags (matches strucpp::VarTypeTag enum values) -static const uint8_t g_prog0_type_tags[] = { - 2, // INT - 0, // BOOL - 2, // INT - 2, // INT (array element type) -}; - -// Array dimension info (0 = scalar, >0 = total element count) -static const uint16_t g_prog0_array_sizes[] = { 0, 0, 0, 100 }; -``` - -### Master Index Arrays - -```cpp -// --- Master index (across all programs) --- - -static void** g_debug_ptrs[] = { g_prog0_ptrs }; -static const uint8_t* g_debug_sizes[] = { g_prog0_sizes }; -static const debug_get_fn* g_debug_get_fns[] = { g_prog0_get_fns }; -static const debug_force_fn* g_debug_force_fns[] = { g_prog0_force_fns }; -static const uint8_t* g_debug_type_tags[] = { g_prog0_type_tags }; -static const uint16_t* g_debug_array_sizes[] = { g_prog0_array_sizes }; - -static const uint16_t g_program_var_counts[] = { 4 }; // vars per program -static const uint8_t g_program_count = 1; -``` - -### Debug Access Functions - -```cpp -// --- Debug access API (called by Modbus handlers) --- - -uint8_t strucpp_get_program_count() { - return g_program_count; -} - -uint16_t strucpp_get_var_count(uint8_t prog_idx) { - if (prog_idx >= g_program_count) return 0; - return g_program_var_counts[prog_idx]; -} - -uint8_t strucpp_get_var_size(uint8_t prog_idx, uint16_t var_idx) { - if (prog_idx >= g_program_count) return 0; - if (var_idx >= g_program_var_counts[prog_idx]) return 0; - return g_debug_sizes[prog_idx][var_idx]; -} - -uint8_t strucpp_get_var_type_tag(uint8_t prog_idx, uint16_t var_idx) { - if (prog_idx >= g_program_count) return 0xFF; - if (var_idx >= g_program_var_counts[prog_idx]) return 0xFF; - return g_debug_type_tags[prog_idx][var_idx]; -} - -uint16_t strucpp_get_array_size(uint8_t prog_idx, uint16_t var_idx) { - if (prog_idx >= g_program_count) return 0; - if (var_idx >= g_program_var_counts[prog_idx]) return 0; - return g_debug_array_sizes[prog_idx][var_idx]; -} - -// Read a scalar variable's value (respects forcing via get()) -bool strucpp_get_var_value(uint8_t prog_idx, uint16_t var_idx, void* dest) { - if (prog_idx >= g_program_count) return false; - if (var_idx >= g_program_var_counts[prog_idx]) return false; - - debug_get_fn fn = g_debug_get_fns[prog_idx][var_idx]; - if (fn) { - fn(dest); - return true; - } - - // Fallback for arrays: read raw pointer (first element) - uint8_t sz = g_debug_sizes[prog_idx][var_idx]; - memcpy(dest, g_debug_ptrs[prog_idx][var_idx], sz); - return true; -} - -// Read an array element's value -bool strucpp_get_array_element(uint8_t prog_idx, uint16_t var_idx, - uint16_t elem_idx, void* dest) { - if (prog_idx >= g_program_count) return false; - if (var_idx >= g_program_var_counts[prog_idx]) return false; - - uint16_t arr_size = g_debug_array_sizes[prog_idx][var_idx]; - if (arr_size == 0 || elem_idx >= arr_size) return false; - - uint8_t elem_size = g_debug_sizes[prog_idx][var_idx]; - // IECVar-wrapped array elements: each element is an IECVar - // Layout: value_ (elem_size) + forced_ (1) + forced_value_ (elem_size) - // Total per element: elem_size * 2 + 1 - size_t iec_var_stride = elem_size * 2 + 1; - uint8_t* base = (uint8_t*)g_debug_ptrs[prog_idx][var_idx]; - // Read via value_ field (offset 0 within each IECVar element) - memcpy(dest, base + elem_idx * iec_var_stride, elem_size); - return true; -} - -// Force/unforce a scalar variable -bool strucpp_force_var(uint8_t prog_idx, uint16_t var_idx, - bool force, void* value) { - if (prog_idx >= g_program_count) return false; - if (var_idx >= g_program_var_counts[prog_idx]) return false; - - debug_force_fn fn = g_debug_force_fns[prog_idx][var_idx]; - if (!fn) return false; - fn(force, value); - return true; -} - -// Unforce all variables (reset all traces) -void strucpp_trace_reset() { - for (uint8_t p = 0; p < g_program_count; ++p) { - for (uint16_t v = 0; v < g_program_var_counts[p]; ++v) { - debug_force_fn fn = g_debug_force_fns[p][v]; - if (fn) fn(false, nullptr); - } - } -} -``` - -### Memory Budget - -For a project with 500 variables across 2 programs (typical for the problematic sample project -when arrays are NOT expanded): - -| Component | Per Variable | Total (500 vars) | -|-----------|-------------|-------------------| -| Pointer (g_prog*_ptrs) | 2-4 bytes | 1-2 KB | -| Size (g_prog*_sizes) | 1 byte | 500 bytes | -| Get function ptr | 2-4 bytes | 1-2 KB | -| Force function ptr | 2-4 bytes | 1-2 KB | -| Type tag | 1 byte | 500 bytes | -| Array size | 2 bytes | 1 KB | -| **Total on AVR (2-byte ptr)** | | **~5 KB** | -| **Total on 32-bit (4-byte ptr)** | | **~9 KB** | - -On ATmega2560 (8 KB SRAM): fits with ~3 KB remaining for stack and program variables. -On ESP32 (520 KB SRAM): trivially fits. - -Compare with current system: 30,000 entries * 8 bytes = 240 KB (does not fit on any Arduino). - -## Step 3.2: Modbus Debug Protocol Update - -The existing Modbus custom function codes (0x41-0x45) are preserved. Only the PDU payload -format changes. - -### Protocol Version Detection - -The editor detects the protocol version based on which debug file exists in build artifacts: -- `debug.c` present -> Protocol v1 (flat index, MatIEC) -- `debug-map.json` present -> Protocol v2 (hierarchical, STruC++) - -### Function Code 0x41: DEBUG_INFO - -**Request** (v1 and v2 identical): -``` -[0x41] -``` - -**Response v1** (current): -``` -[0x41] [0x7E] [var_count_hi:u8] [var_count_lo:u8] -``` - -**Response v2** (new): -``` -[0x41] [0x7E] [version:u8=2] [prog_count:u8] - [prog0_var_count_hi:u8] [prog0_var_count_lo:u8] - [prog1_var_count_hi:u8] [prog1_var_count_lo:u8] - ... -``` - -The `version` byte (value 2) distinguishes v2 from v1 responses. v1 responses will have -a value of 0 or 1 in this position (high byte of var_count, which is < 256 for small projects). - -### Function Code 0x42: DEBUG_SET (Force/Unforce) - -**Request v2**: -``` -[0x42] [prog_idx:u8] [var_idx_hi:u8] [var_idx_lo:u8] - [force_flag:u8] [value_len:u8] [value_bytes...] -``` - -- `force_flag`: 1 = force, 0 = unforce -- `value_bytes`: little-endian value to force (only when force_flag = 1) - -**Response v2**: -``` -[0x42] [status:u8] -``` -- `0x7E` = success -- `0x81` = invalid program/variable index -- `0x82` = type mismatch or array variable (use element forcing instead) - -### Function Code 0x43: DEBUG_GET (Range Read) - -**Request v2**: -``` -[0x43] [prog_idx:u8] [start_var:u16] [end_var:u16] -``` - -**Response v2**: -``` -[0x43] [0x7E] [tick:u32] [data_len:u16] [var_data...] -``` - -Variables are returned in order from `start_var` to `end_var`. Each variable's data is -its raw bytes (size determined by type). For array variables, only the first element is -returned in range reads; use function code 0x44 for specific elements. - -### Function Code 0x44: DEBUG_GET_LIST (Batch Read) - -**Request v2**: -``` -[0x44] [count:u16] - [prog_idx_0:u8] [var_idx_0:u16] [elem_idx_0:u16] - [prog_idx_1:u8] [var_idx_1:u16] [elem_idx_1:u16] - ... -``` - -- `elem_idx`: For scalar variables, use 0xFFFF (no element). For array elements, use the - element index. - -**Response v2**: -``` -[0x44] [0x7E] [tick:u32] [data_len:u16] [var_data...] -``` - -Each variable's data is concatenated in request order. Sizes are known by the editor -from the debug-map.json type information. - -### Function Code 0x45: DEBUG_GET_MD5 - -**Request v2** (unchanged from v1): -``` -[0x45] [endian_check_byte_1:u8] [endian_check_byte_2:u8] - [endian_check_byte_3:u8] [endian_check_byte_4:u8] -``` - -**Response v2** (unchanged from v1): -``` -[0x45] [0x7E] [md5_string:32bytes] [endian_echo:4bytes] -``` - -### Implementation Changes - -**File to modify**: `resources/sources/Baremetal/ModbusSlave.h` (and .cpp if separate) - -The debug handler functions need updating: - -```cpp -// Old signatures (MatIEC): -// extern "C" uint16_t get_var_count(void); -// extern "C" void* get_var_addr(size_t idx); -// extern "C" void set_trace(size_t idx, bool forced, void* val); - -// New: call strucpp_* functions from generated_glue.hpp -void debugInfo(uint8_t* frame, uint16_t* frameSize) { - frame[0] = 0x41; - frame[1] = 0x7E; - frame[2] = 2; // protocol version - frame[3] = strucpp_get_program_count(); - uint16_t offset = 4; - for (uint8_t p = 0; p < frame[3]; p++) { - uint16_t vc = strucpp_get_var_count(p); - frame[offset++] = vc >> 8; - frame[offset++] = vc & 0xFF; - } - *frameSize = offset; -} - -void debugSetTrace(uint8_t* frame, uint16_t* frameSize) { - uint8_t prog_idx = frame[1]; - uint16_t var_idx = (frame[2] << 8) | frame[3]; - bool force = frame[4] != 0; - uint8_t val_len = frame[5]; - void* val_ptr = &frame[6]; - - bool ok = strucpp_force_var(prog_idx, var_idx, force, force ? val_ptr : nullptr); - frame[0] = 0x42; - frame[1] = ok ? 0x7E : 0x81; - *frameSize = 2; -} - -void debugGetTraceList(uint8_t* frame, uint16_t frameLen, uint16_t* respSize) { - uint16_t count = (frame[1] << 8) | frame[2]; - uint8_t* resp = frame; // reuse buffer - resp[0] = 0x44; - resp[1] = 0x7E; - // tick at resp[2..5] - uint32_t tick = __tick; - memcpy(&resp[2], &tick, 4); - - uint16_t data_offset = 8; // skip header - uint16_t req_offset = 3; // skip count field - - for (uint16_t i = 0; i < count; i++) { - uint8_t prog_idx = frame[req_offset++]; - uint16_t var_idx = (frame[req_offset] << 8) | frame[req_offset + 1]; - req_offset += 2; - uint16_t elem_idx = (frame[req_offset] << 8) | frame[req_offset + 1]; - req_offset += 2; - - uint8_t sz = strucpp_get_var_size(prog_idx, var_idx); - - if (elem_idx == 0xFFFF) { - // Scalar read - strucpp_get_var_value(prog_idx, var_idx, &resp[data_offset]); - } else { - // Array element read - strucpp_get_array_element(prog_idx, var_idx, elem_idx, &resp[data_offset]); - } - data_offset += sz; - } - - // Write data length at resp[6..7] - uint16_t data_len = data_offset - 8; - resp[6] = data_len >> 8; - resp[7] = data_len & 0xFF; - *respSize = data_offset; -} -``` - -## Step 3.3: Debug Map File (debug-map.json) - -The compiler pipeline generates `debug-map.json` (written alongside build artifacts) to -replace `debug.c` as the editor's source of variable metadata. - -### Format - -```json -{ - "version": 2, - "md5": "a1b2c3d4e5f67890a1b2c3d4e5f67890", - "commonTicktimeNs": 20000000, - "programs": [ - { - "index": 0, - "instanceName": "instance0", - "programType": "Main", - "intervalNs": 20000000, - "vars": [ - { - "index": 0, - "name": "counter", - "type": "INT", - "typeTag": "INT", - "size": 2 - }, - { - "index": 1, - "name": "running", - "type": "BOOL", - "typeTag": "BOOL", - "size": 1 - }, - { - "index": 2, - "name": "motor_speed", - "type": "INT", - "typeTag": "INT", - "size": 2, - "location": "%QW0" - }, - { - "index": 3, - "name": "speeds", - "type": "ARRAY [0..99] OF INT", - "typeTag": "INT", - "size": 2, - "isArray": true, - "dimensions": [100] - }, - { - "index": 4, - "name": "fb_inst", - "type": "MyFB", - "isStruct": true, - "fields": [ - { "name": "output", "type": "REAL", "typeTag": "REAL", "size": 4 }, - { "name": "setpoint", "type": "INT", "typeTag": "INT", "size": 2 } - ] - } - ] - } - ] -} -``` - -### Generation - -**In `generate-arduino-glue.ts`** (extends Phase 2): - -```typescript -export function generateDebugMap( - variableDescriptors: ProgramVarDescriptor[], - taskIntervals: TaskInterval[], - md5Hash: string, - commonTicktimeNs: number, -): string { - const programs = variableDescriptors.map((prog, idx) => ({ - index: idx, - instanceName: prog.programInstanceName, - programType: prog.programTypeName, - intervalNs: taskIntervals.find(t => t.instanceName === prog.programInstanceName)?.intervalNs ?? 20_000_000, - vars: prog.variables.map((v, vidx) => ({ - index: vidx, - name: v.name, - type: v.isArray ? `ARRAY [0..${(v.arrayDimensions?.[0] ?? 1) - 1}] OF ${v.typeTag}` : v.typeTag, - typeTag: v.typeTag, - size: v.size, - ...(v.isArray && { isArray: true, dimensions: v.arrayDimensions }), - ...(v.isStruct && { isStruct: true, fields: v.structFields }), - })), - })) - - return JSON.stringify({ version: 2, md5: md5Hash, commonTicktimeNs, programs }, null, 2) -} -``` - -## Design Notes - -### Why Type-Erased Functions Instead of Templates - -Arduino AVR has no RTTI and limited template support. Using C function pointers (`void(*)(void*)`) -avoids virtual dispatch overhead and keeps the debug infrastructure simple. The lambdas in the -generated code are stateless and compile to regular function pointers. - -### Array Element Access Without Expansion - -When the editor user expands an array in the debug variable tree, the editor sends individual -`(prog_idx, var_idx, elem_idx)` read requests via function code 0x44. The device computes the -memory offset: `base_ptr + elem_idx * stride`. No pre-expansion needed. - -For forcing array elements, the force function operates on the IECVar wrapper of the specific -element. The array is stored as `Array1D, 0, 99>` in STruC++ output, so each -element has its own `force()`/`unforce()` capability. - -### Struct/FB Instance Variable Access - -For function block instances, the variables are flattened in the descriptor array: -- `fb_inst` itself is marked as `isStruct: true` with its fields listed -- The editor builds a tree: `program.fb_inst.output`, `program.fb_inst.setpoint` -- At the protocol level, each field gets its own var_idx (or is accessed via struct offset) - -The exact approach depends on how STruC++ lays out FB member variables. If FB members are -exposed as individual `IECVar` fields, each gets its own descriptor. If they're packed -in a struct, offset-based access is used. - -## Testing Strategy - -1. **Scalability test**: Compile the sample project (~3,500 variables, many arrays) - - Verify `debug-map.json` has significantly fewer entries than the old debug.c VAR_COUNT - - Verify arrays have `isArray: true` with `dimensions` (not expanded) - -2. **Protocol test** (simulator): - - Send 0x41, verify response contains program count and var counts - - Send 0x44 with scalar variable refs, verify correct values returned - - Send 0x44 with array element refs, verify correct element values - -3. **Force test** (simulator): - - Send 0x42 to force an INT variable to 42 - - Run PLC cycles - - Read the variable, verify it's still 42 - - Send 0x42 to unforce, verify it returns to computed value - -4. **Memory test**: Verify generated debug arrays fit within target platform RAM limits - -## Files Created/Modified - -| File | Action | -|------|--------| -| `src/backend/shared/utils/PLC/generate-arduino-glue.ts` | Extended -- debug arrays + debug-map.json | -| `resources/sources/Baremetal/ModbusSlave.h` | Modified -- debug handler functions | diff --git a/docs/strucpp-migration/04-debugger.md b/docs/strucpp-migration/04-debugger.md new file mode 100644 index 000000000..f06b3aef5 --- /dev/null +++ b/docs/strucpp-migration/04-debugger.md @@ -0,0 +1,56 @@ +# Phase 4: Debugger + +## Status: Deferred + +This phase is intentionally deferred until after Phase 3 (Arduino runtime) is working and +stable. The debugger is complex and benefits from being designed with concrete knowledge of +how the runtime actually operates with STruC++ generated code. + +## Why Deferred + +1. **Better design context**: After Phases 2-3, we'll have a working STruC++ compilation and + execution pipeline. The runtime's actual structure, memory layout, and variable access + patterns will be concrete rather than theoretical. + +2. **Avoid premature complexity**: Earlier iterations of this plan included a TypeScript glue + code generator, compile wrapper, and hierarchical debug protocol. All of these were cut in + favor of a simpler static runtime approach. The debugger will likely benefit from similar + simplification once we see the full picture. + +3. **MatIEC debugger still works**: For boards using `compiler_backend: "matiec"`, the existing + debug.c / VARIABLES.csv / Modbus protocol v1 debugger continues to function unchanged. + +## Known Requirements + +When this phase is picked up, it will need to address: + +### Core Problem +The current `debug.c` (generated by xml2st) creates a flat `debug_vars[]` array that expands +every array element individually. This causes 30,000+ entries for projects with ~3,500 +variables (many arrays), exceeding Arduino memory limits. + +### STruC++ Capabilities +- `IECVar` has built-in `force()` / `unforce()` / `is_forced()` / `get()` methods +- `VarDescriptor` arrays (used by the REPL) provide per-program variable metadata without + array expansion +- `ProgramBase` subclasses expose all variables as typed members +- `locatedVars[]` descriptors provide I/O variable metadata + +### What Needs to be Designed +- **Variable listing**: How the editor discovers what variables exist (replaces VARIABLES.csv) +- **Variable addressing**: How the editor references specific variables for read/force + (replaces flat debug index) +- **Protocol**: How variable data is exchanged between editor and device (replaces Modbus + custom function codes 0x41-0x45, or adapts them) +- **Array access**: How array elements are accessed without pre-expansion +- **Frontend**: How the debug variable tree is built and populated + +### Previous Analysis (for reference) +The earlier analysis in this migration plan explored: +- Hierarchical `(program_idx, var_idx)` addressing +- `debug-map.json` as a replacement for `debug.c` +- Lazy array element loading in the frontend +- Type-erased debug pointer arrays on the Arduino side + +These ideas may still be relevant but should be re-evaluated against the actual working +runtime before implementation. diff --git a/docs/strucpp-migration/05-editor-frontend-debugger.md b/docs/strucpp-migration/05-editor-frontend-debugger.md deleted file mode 100644 index 3197fb425..000000000 --- a/docs/strucpp-migration/05-editor-frontend-debugger.md +++ /dev/null @@ -1,480 +0,0 @@ -# Phase 5: Editor Frontend Debugger Updates - -## Goal - -Update the editor's debugger frontend to support both the legacy flat-index protocol (v1, -MatIEC) and the new hierarchical protocol (v2, STruC++). The UI should parse `debug-map.json`, -build a hierarchical variable tree, and use `(program_idx, var_idx)` addressing for variable -reads and writes. - -## Prerequisites - -- Phase 3 (debug-map.json format, Modbus protocol v2) -- Phase 4 (IPC bridge for reading debug-map.json) - -## Step 5.1: New Debug Map Parser - -**File to modify**: `src/frontend/utils/debug-parser.ts` - -Add `parseDebugMapV2()` alongside the existing `parseDebugVariables()` (which parses debug.c). - -```typescript -// ----- Types for debug-map.json (Protocol v2) ----- - -export interface DebugMapV2 { - version: 2 - md5: string - commonTicktimeNs: number - programs: DebugMapProgram[] -} - -export interface DebugMapProgram { - index: number - instanceName: string - programType: string - intervalNs: number - vars: DebugMapVariable[] -} - -export interface DebugMapVariable { - index: number - name: string - type: string - typeTag: string - size: number - location?: string // e.g., "%QW0" for located variables - isArray?: boolean - dimensions?: number[] // e.g., [100] for ARRAY[0..99] - isStruct?: boolean - fields?: DebugMapVariable[] -} - -// ----- Reference type for hierarchical addressing ----- - -export interface DebugVarRef { - programIdx: number - varIdx: number - elementIdx?: number // For array elements (omit for scalars) -} - -// ----- Parser ----- - -export function parseDebugMapV2(jsonContent: string): DebugMapV2 { - const raw = JSON.parse(jsonContent) - - if (raw.version !== 2) { - throw new Error(`Unsupported debug map version: ${raw.version}`) - } - - return raw as DebugMapV2 -} - -// ----- Existing functions (unchanged) ----- -// export function parseDebugVariables(content: string): DebugVariableEntry[] -// export function parseDebugData(content: string): ParsedDebugData -``` - -## Step 5.2: Update Variable Ref Map Builder - -**File to modify**: `src/frontend/utils/debugger-session.ts` - -Add a function that builds the variable reference map from `DebugMapV2`. This maps composite -keys (used by the variable tree UI) to `DebugVarRef` objects. - -```typescript -/** - * Build a variable reference map from debug-map.json (protocol v2). - * Maps composite keys (e.g., "instance0.counter") to DebugVarRef objects. - */ -export function buildVariableRefMapV2( - debugMap: DebugMapV2, -): Map { - const refMap = new Map() - - for (const program of debugMap.programs) { - const progPrefix = program.instanceName - - for (const variable of program.vars) { - const key = `${progPrefix}.${variable.name}` - - refMap.set(key, { - programIdx: program.index, - varIdx: variable.index, - }) - - // For arrays: also register element keys - if (variable.isArray && variable.dimensions) { - const totalElements = variable.dimensions.reduce((a, b) => a * b, 1) - for (let elem = 0; elem < totalElements; elem++) { - refMap.set(`${key}[${elem}]`, { - programIdx: program.index, - varIdx: variable.index, - elementIdx: elem, - }) - } - } - - // For structs: register field keys - if (variable.isStruct && variable.fields) { - for (const field of variable.fields) { - refMap.set(`${key}.${field.name}`, { - programIdx: program.index, - varIdx: variable.index, - // Struct field access: var_idx points to the struct, field offset computed at runtime - }) - } - } - } - } - - return refMap -} -``` - -## Step 5.3: Update Debugger Port Interface - -**File to modify**: `src/middleware/shared/ports/debugger-port.ts` - -The debugger port needs to support both v1 (flat index) and v2 (hierarchical) protocols. - -```typescript -// Add to existing types: -export { DebugVarRef } from '@utils/debug-parser' - -// The port interface methods are updated to accept both ref types: -export interface DebuggerPort { - // ... existing methods ... - - /** - * Read variable values (protocol v2 - hierarchical). - * Falls back to flat index for v1 targets. - */ - getVariablesList(refs: DebugVarRef[]): Promise - - /** - * Force/unforce a variable (protocol v2 - hierarchical). - */ - setVariable(ref: DebugVarRef, force: boolean, valueBuffer?: Uint8Array): Promise - - /** - * Read the debug map file (protocol v2). - * Returns null if debug-map.json doesn't exist (v1 target). - */ - readDebugMap(projectPath: string, boardTarget: string): Promise -} -``` - -## Step 5.4: Update Debug Tree Builder - -**File to modify**: `src/frontend/utils/debug-tree-builder.ts` - -Add the ability to build the debug variable tree from `DebugMapV2`. The tree structure matches -what the UI expects but is built from the new hierarchical format. - -Key improvement: **arrays appear as single expandable nodes** instead of being pre-expanded -into individual entries. When the user clicks to expand an array, the UI generates child -nodes on-demand and requests their values individually. - -```typescript -/** - * Build debug tree from debug-map.json (protocol v2). - * Arrays are NOT pre-expanded -- they appear as single nodes. - */ -export function buildDebugTreeV2( - debugMap: DebugMapV2, - pous: PLCPou[], -): Map { - const tree = new Map() - - for (const program of debugMap.programs) { - const progKey = program.instanceName - - // Program root node - tree.set(progKey, { - key: progKey, - name: program.instanceName, - type: 'program', - children: [], - }) - - for (const variable of program.vars) { - const varKey = `${progKey}.${variable.name}` - - const node: DebugTreeNode = { - key: varKey, - name: variable.name, - type: variable.isArray ? 'array' : variable.isStruct ? 'struct' : 'scalar', - dataType: variable.type, - typeTag: variable.typeTag, - size: variable.size, - ref: { programIdx: program.index, varIdx: variable.index }, - } - - if (variable.isArray && variable.dimensions) { - // Array node: children are generated lazily when expanded - node.arrayDimensions = variable.dimensions - node.childCount = variable.dimensions.reduce((a, b) => a * b, 1) - node.lazyChildren = true // Don't generate child nodes yet - } - - if (variable.isStruct && variable.fields) { - // Struct node: children are the fields - node.children = variable.fields.map(field => ({ - key: `${varKey}.${field.name}`, - name: field.name, - type: 'scalar', - dataType: field.type, - typeTag: field.typeTag, - size: field.size, - ref: { programIdx: program.index, varIdx: variable.index }, - })) - } - - tree.set(varKey, node) - } - } - - return tree -} - -/** - * Generate child nodes for a lazy array node (called when user expands the array). - */ -export function expandArrayNode( - parentNode: DebugTreeNode, -): DebugTreeNode[] { - if (!parentNode.arrayDimensions || !parentNode.ref) return [] - - const totalElements = parentNode.arrayDimensions.reduce((a, b) => a * b, 1) - const children: DebugTreeNode[] = [] - - for (let i = 0; i < totalElements; i++) { - children.push({ - key: `${parentNode.key}[${i}]`, - name: `[${i}]`, - type: 'scalar', - dataType: parentNode.typeTag ?? parentNode.dataType, - size: parentNode.size, - ref: { - programIdx: parentNode.ref.programIdx, - varIdx: parentNode.ref.varIdx, - elementIdx: i, - }, - }) - } - - return children -} -``` - -## Step 5.5: Update Debug Session Hook - -**File to modify**: `src/frontend/hooks/useDebugSession.ts` - -The debug session hook orchestrates the connection between the editor and the target device. -It needs to detect the protocol version and use the appropriate parser. - -```typescript -// In the connect/start function: -async function startDebugSession(projectPath: string, boardTarget: string) { - // 1. Try to read debug-map.json (protocol v2) - const debugMap = await debuggerPort.readDebugMap(projectPath, boardTarget) - - if (debugMap) { - // Protocol v2: hierarchical addressing - setDebugProtocolVersion(2) - const refMap = buildVariableRefMapV2(debugMap) - setDebugVariableIndexes(refMap) - const tree = buildDebugTreeV2(debugMap, projectData.pous) - setDebugVariableTree(tree) - setDebugMd5(debugMap.md5) - } else { - // Protocol v1: fall back to debug.c parsing (legacy) - const debugFile = await debuggerPort.readDebugFile(projectPath, boardTarget) - if (debugFile) { - setDebugProtocolVersion(1) - const variables = parseDebugVariables(debugFile) - // ... existing v1 tree building logic - } - } - - // 2. Connect to target (unchanged) - await debuggerPort.connect(config) - - // 3. Verify MD5 match (unchanged in concept, uses new MD5) - const runtimeMd5 = await debuggerPort.verifyMd5(debugMd5, config) - if (!runtimeMd5.match) { - setDebugMd5Mismatch(true) - } - - // 4. Start polling (see Step 5.7) -} -``` - -## Step 5.6: Update Workspace Store - -**File to modify**: `src/frontend/store/slices/workspace/types.ts` - -```typescript -export interface WorkspaceState { - // ... existing fields ... - - /** Debug protocol version: 1 = flat index (MatIEC), 2 = hierarchical (STruC++) */ - debugProtocolVersion: 1 | 2 - - /** Variable indexes: DebugVarRef for v2, number for v1 */ - debugVariableIndexes: Map - - // ... rest unchanged -} -``` - -**File to modify**: `src/frontend/store/slices/workspace/slice.ts` - -Add actions: -```typescript -setDebugProtocolVersion: (version: 1 | 2) => void -``` - -## Step 5.7: Update Debug Polling - -**File to modify**: `src/frontend/hooks/useDebugPolling.ts` - -The polling hook needs to handle both protocols: - -```typescript -// In the polling function: -async function pollVariables() { - const visibleVarKeys = getVisibleVariableKeys() // from scroll position - const protocolVersion = useStore.getState().debugProtocolVersion - const indexes = useStore.getState().debugVariableIndexes - - if (protocolVersion === 2) { - // Collect DebugVarRef objects for visible variables - const refs: DebugVarRef[] = visibleVarKeys - .map(key => indexes.get(key)) - .filter((ref): ref is DebugVarRef => ref !== undefined && typeof ref !== 'number') - - const result = await debuggerPort.getVariablesList(refs) - // Update variable values in store... - - } else { - // Legacy v1: flat indices - const flatIndexes: number[] = visibleVarKeys - .map(key => indexes.get(key)) - .filter((idx): idx is number => typeof idx === 'number') - - const result = await debuggerPort.getVariablesList( - flatIndexes.map(idx => ({ programIdx: 0, varIdx: idx })), - ) - // Update variable values in store... - } -} -``` - -## Step 5.8: Update Debugger Adapter - -**File to modify**: `src/middleware/adapters/editor/debugger-adapter.ts` - -The adapter translates port calls into IPC bridge calls: - -```typescript -async getVariablesList(refs: DebugVarRef[]): Promise { - // Encode refs into the format expected by the main process Modbus client - return await window.bridge.debuggerGetVariablesList(refs) -} - -async setVariable(ref: DebugVarRef, force: boolean, valueBuffer?: Uint8Array): Promise { - return await window.bridge.debuggerSetVariable(ref, force, valueBuffer) -} - -async readDebugMap(projectPath: string, boardTarget: string): Promise { - const result = await window.bridge.debuggerReadDebugMap(projectPath, boardTarget) - if (!result.success || !result.content) return null - return parseDebugMapV2(result.content) -} -``` - -## Step 5.9: Update Variable Force Dialog - -The force variable dialog needs to work with `DebugVarRef` instead of flat indices: - -```typescript -// When user clicks "Force Variable" on a variable in the tree: -async function handleForceVariable(varKey: string, value: Uint8Array) { - const ref = debugVariableIndexes.get(varKey) - if (!ref || typeof ref === 'number') { - // v1 legacy path - await debuggerPort.setVariable({ programIdx: 0, varIdx: ref as number }, true, value) - } else { - // v2 hierarchical path - await debuggerPort.setVariable(ref, true, value) - } -} -``` - -## Design Notes - -### Lazy Array Expansion - -In the current system, arrays are pre-expanded in `debug.c`, so the variable tree shows all -elements immediately. With the new system, arrays appear as a single node. When expanded: - -1. `expandArrayNode()` generates child nodes with `elementIdx` in their `DebugVarRef` -2. The polling hook requests values for visible child nodes -3. Only visible elements are fetched (windowed rendering) - -For a 10,000-element array, this means reading ~20-50 elements at a time (visible in the scroll -viewport) instead of all 10,000. - -### Backward Compatibility - -The v1 path is preserved for: -- MatIEC-compiled boards (compiler_backend: "matiec" in hals.json) -- Runtime v3 targets -- Runtime v4 targets that haven't been updated to Phase 8 - -The protocol version detection is automatic based on which debug file exists. - -### Struct/FB Instance Deep Access - -For struct fields and FB instance variables: -- The debug-map.json lists fields under the parent variable -- The tree builder creates nested nodes -- The debug protocol accesses fields via the parent var_idx + field offset -- The exact mechanism depends on STruC++ struct memory layout (IECVar-wrapped fields) - -## Testing Strategy - -1. **Variable tree building**: Parse a debug-map.json with scalars, arrays, and structs - - Verify tree has correct hierarchy - - Verify arrays are single nodes (not expanded) - - Verify expandArrayNode generates correct children - -2. **Protocol detection**: Test with both debug.c and debug-map.json present/absent - - Only debug.c -> v1 - - Only debug-map.json -> v2 - - Both present -> v2 takes priority - -3. **Variable polling**: Connect to simulator, verify values update in real time - - Scalar variables show correct values - - Array elements show correct values when expanded - - Forced variables show forced value (not hardware value) - -4. **Force/unforce**: Force a variable, verify it stays forced through cycles - -5. **Regression**: All existing debug tests pass for v1 targets - -## Files Created/Modified - -| File | Action | -|------|--------| -| `src/frontend/utils/debug-parser.ts` | Modified -- add DebugMapV2 types and parser | -| `src/frontend/utils/debugger-session.ts` | Modified -- add buildVariableRefMapV2() | -| `src/frontend/utils/debug-tree-builder.ts` | Modified -- add buildDebugTreeV2(), expandArrayNode() | -| `src/middleware/shared/ports/debugger-port.ts` | Modified -- DebugVarRef, updated signatures | -| `src/frontend/hooks/useDebugSession.ts` | Modified -- protocol detection | -| `src/frontend/hooks/useDebugPolling.ts` | Modified -- v2 polling path | -| `src/frontend/store/slices/workspace/types.ts` | Modified -- debugProtocolVersion | -| `src/frontend/store/slices/workspace/slice.ts` | Modified -- new actions | -| `src/middleware/adapters/editor/debugger-adapter.ts` | Modified -- v2 transport | diff --git a/docs/strucpp-migration/06-runtime-v4-so-interface.md b/docs/strucpp-migration/05-runtime-v4-so-interface.md similarity index 99% rename from docs/strucpp-migration/06-runtime-v4-so-interface.md rename to docs/strucpp-migration/05-runtime-v4-so-interface.md index ac03a65e9..3355eb230 100644 --- a/docs/strucpp-migration/06-runtime-v4-so-interface.md +++ b/docs/strucpp-migration/05-runtime-v4-so-interface.md @@ -1,4 +1,4 @@ -# Phase 6: Runtime v4 .so Interface +# Phase 5: Runtime v4 .so Interface ## Goal diff --git a/docs/strucpp-migration/07-runtime-v4-thread-per-task.md b/docs/strucpp-migration/06-runtime-v4-thread-per-task.md similarity index 98% rename from docs/strucpp-migration/07-runtime-v4-thread-per-task.md rename to docs/strucpp-migration/06-runtime-v4-thread-per-task.md index f1d0bd101..fd3b35bf9 100644 --- a/docs/strucpp-migration/07-runtime-v4-thread-per-task.md +++ b/docs/strucpp-migration/06-runtime-v4-thread-per-task.md @@ -1,4 +1,4 @@ -# Phase 7: Thread-Per-Task Model for Runtime v4 +# Phase 6: Thread-Per-Task Model for Runtime v4 ## Goal @@ -8,7 +8,7 @@ task's declared priority. This is only for Runtime v4 (Linux); Arduino retains r ## Prerequisites -- Phase 6 (v4_compat.cpp with C-linkage interface) +- Phase 5 (v4_compat.cpp with C-linkage interface) - Runtime v4 codebase at `~/Documents/Code/openplc-runtime` ## Current Architecture @@ -56,9 +56,9 @@ Thread 1 (Task "slow", T#100ms, Priority 5): sleep_until(next_100ms) ``` -## Step 7.1: New .so Symbols +## Step 6.1: New .so Symbols -**File to modify**: `src/backend/shared/utils/PLC/generate-v4-compat.ts` (from Phase 6) +**File to modify**: `v4_compat.cpp` (from Phase 5) Add new optional symbols to `v4_compat.cpp`: diff --git a/docs/strucpp-migration/08-runtime-v4-debug-handler.md b/docs/strucpp-migration/07-runtime-v4-debug-handler.md similarity index 95% rename from docs/strucpp-migration/08-runtime-v4-debug-handler.md rename to docs/strucpp-migration/07-runtime-v4-debug-handler.md index 8719ea253..74dc22297 100644 --- a/docs/strucpp-migration/08-runtime-v4-debug-handler.md +++ b/docs/strucpp-migration/07-runtime-v4-debug-handler.md @@ -1,19 +1,19 @@ -# Phase 8: Runtime v4 Native Hierarchical Debug +# Phase 7: Runtime v4 Native Hierarchical Debug ## Goal Update the Runtime v4's `debug_handler.c` to natively use hierarchical `(program_idx, var_idx)` addressing when communicating with the editor, eliminating the flat-index lookup table from -Phase 6. This is the final cleanup phase -- it can be done after Phase 6 is stable. +Phase 5. This is the final cleanup phase -- it can be done after Phase 5 is stable. ## Prerequisites -- Phase 6 (v4_compat.cpp with working C-linkage debug interface) -- Phase 5 (editor frontend supporting protocol v2) +- Phase 5 (v4_compat.cpp with working C-linkage debug interface) +- Phase 4 (debugger design -- at least the protocol portion) -## Current State After Phase 6 +## Current State After Phase 5 -Phase 6 provides backward-compatible debug access through `flat_var_table[]`: +Phase 5 provides backward-compatible debug access through `flat_var_table[]`: ``` Editor (v2 protocol) <--> Editor adapter (converts v2 -> v1) <--> Runtime debug_handler (v1) @@ -23,7 +23,7 @@ Editor (v2 protocol) <--> Editor adapter (converts v2 -> v1) <--> Runtime debug_ STruC++ IECVar variables ``` -This works but has an unnecessary translation layer. Phase 8 removes it: +This works but has an unnecessary translation layer. Phase 7 removes it: ``` Editor (v2 protocol) <--> Runtime debug_handler (v2) <--> STruC++ IECVar variables @@ -300,8 +300,8 @@ symbol availability. Both detection methods are deterministic and consistent. ### Removing the Flat-Index Table -After Phase 8 is deployed, the `flat_var_table[]` in `v4_compat.cpp` becomes dead code for -runtime targets (it's still used by the Arduino path in Phase 6's backward-compatible debug +After Phase 7 is deployed, the `flat_var_table[]` in `v4_compat.cpp` becomes dead code for +runtime targets (it's still used by the Arduino path in Phase 5's backward-compatible debug layer). It can be conditionally compiled: ```cpp @@ -331,7 +331,7 @@ per batch for RTU, 200+ for TCP/WebSocket). ## Testing Strategy -1. **v2 protocol end-to-end**: Editor (Phase 5) connects to Runtime v4 (Phase 8) +1. **v2 protocol end-to-end**: Editor (Phase 4) connects to Runtime v4 (Phase 7) - Read scalar variables, verify correct values - Read array elements, verify correct values - Force a variable, verify persistence diff --git a/scripts/download-binaries.ts b/scripts/download-binaries.ts index beb6953a2..c92dd9e2b 100644 --- a/scripts/download-binaries.ts +++ b/scripts/download-binaries.ts @@ -370,7 +370,7 @@ async function downloadStrucpp(tool: ToolEntry): Promise { // Install into node_modules via npm so `import { compile } from 'strucpp'` works console.log(` Installing strucpp ${tool.version} into node_modules...`) - execSync(`npm install "${tgzPath}" --save-exact`, { + execSync(`npm install "${tgzPath}" --no-save`, { cwd: ROOT_DIR, stdio: 'pipe', }) From ae4ced3aed208d6bb98b66bee0a79d955dc162ed Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 17:42:16 -0400 Subject: [PATCH 017/296] docs: remove MatIEC coexistence -- clean break, STruC++ only Update all phases to reflect that this branch fully replaces MatIEC with no backward compatibility: - Phase 2: Remove dual pipeline routing and compiler_backend field. MatIEC pipeline is deleted, not preserved alongside STruC++. - Phase 3: openplc.h MatIEC declarations are removed, not guarded. - Phase 4: Debugger designed from clean slate, no old format support. - Phase 5: compile.sh has no MatIEC fallback branch. - Phase 6: No legacy single-thread model for MatIEC .so files. - Phase 7: No flat-index backward compatibility layer. - Overview: Replace "Dual Pipeline Coexistence" with "Full Replacement". Co-Authored-By: Claude Opus 4.6 (1M context) --- docs/strucpp-migration/00-overview.md | 9 +- .../02-editor-compiler-pipeline.md | 187 +++++++----------- .../03-arduino-runtime-adaptation.md | 21 +- docs/strucpp-migration/04-debugger.md | 5 +- .../05-runtime-v4-so-interface.md | 40 +--- .../06-runtime-v4-thread-per-task.md | 18 +- .../07-runtime-v4-debug-handler.md | 31 +-- 7 files changed, 109 insertions(+), 202 deletions(-) diff --git a/docs/strucpp-migration/00-overview.md b/docs/strucpp-migration/00-overview.md index 74c184d5b..a4b553cad 100644 --- a/docs/strucpp-migration/00-overview.md +++ b/docs/strucpp-migration/00-overview.md @@ -118,11 +118,12 @@ Phase 1 (STruC++ dependency infrastructure) ## Key Architectural Decisions -### 1. Dual Pipeline Coexistence +### 1. Full Replacement (No MatIEC Coexistence) -Both MatIEC and STruC++ pipelines coexist in the compiler module. A `"compiler_backend"` field -in `hals.json` per board determines which pipeline is used. This allows gradual migration -- -boards can be switched one at a time. +This branch is a clean break from MatIEC. The existing iec2c pipeline is fully removed and +replaced by STruC++. There is no `"compiler_backend"` routing, no dual pipeline, no backward +compatibility with MatIEC-generated code. All boards compile through STruC++ exclusively. +MatIEC-specific code (`config_init__`, `config_run__`, `glueVars`, `debug.c`, etc.) is deleted. ### 2. Static Arduino Runtime (No Glue Code Generator) diff --git a/docs/strucpp-migration/02-editor-compiler-pipeline.md b/docs/strucpp-migration/02-editor-compiler-pipeline.md index cc8d939f8..67089914e 100644 --- a/docs/strucpp-migration/02-editor-compiler-pipeline.md +++ b/docs/strucpp-migration/02-editor-compiler-pipeline.md @@ -2,15 +2,14 @@ ## Goal -Wire STruC++ `compile()` into `compiler-module.ts` so that when a board uses the STruC++ -backend, the editor reads `program.st`, compiles it to C++, and writes `generated.cpp` + -`generated.hpp` to the build directory. This validates that the code generation pipeline -works end-to-end. +Replace the iec2c (MatIEC) compilation step in `compiler-module.ts` with STruC++ `compile()`. +The editor reads `program.st`, compiles it to C++, and writes `generated.cpp` + `generated.hpp` +to the build directory. The existing MatIEC pipeline is removed entirely -- no coexistence, +no routing, no backward compatibility. At this stage, the `arduino-cli` compilation step will fail because the Arduino runtime (sketch, adapted `openplc.h`) is not yet ready for STruC++ output. That's expected -- the -goal is to verify C++ code generation, not a compilable firmware. Phase 3 addresses the -runtime. +goal is to verify C++ code generation. Phase 3 addresses the runtime. ## Prerequisites @@ -20,86 +19,67 @@ runtime. **`src/backend/editor/compiler/compiler-module.ts`** (~2,348 lines) -This is the main compilation orchestrator. The STruC++ pipeline adds new methods alongside -the existing MatIEC ones; both coexist. +The existing MatIEC pipeline steps (iec2c invocation, xml2st debug/glue generation) are +replaced by STruC++ calls. Dead MatIEC code is removed. -## Step 2.1: Pipeline Routing +## Step 2.1: Remove MatIEC Pipeline -Add a `"compiler_backend"` field to `hals.json` board entries. The entry point -`compileProgram()` checks this field to route to the appropriate pipeline: - -```typescript -async compileProgram(args, _mainProcessPort, mainProcessBridge) { - const boardTarget = args[1] as string - const boardEntry = this.halsContent[boardTarget] - - if (boardEntry?.compiler_backend === 'strucpp') { - return this.compileArduinoWithSTruCpp(args, _mainProcessPort, mainProcessBridge) - } - // ... existing MatIEC pipeline (unchanged) -} -``` - -**File to modify**: `resources/sources/boards/hals.json` - -Add `"compiler_backend": "strucpp"` to boards being migrated. Boards without this field (or -with `"matiec"`) continue using the existing pipeline. +Delete or replace the following methods/steps in `compiler-module.ts`: +- `handleTranspileSTtoC()` (iec2c binary invocation) -- replaced by `handleCompileSTtoCpp()` +- `handleGenerateDebugFiles()` (xml2st --generate-debug) -- removed (debugger is Phase 4) +- `handleGenerateGlueVars()` (xml2st --generate-gluevars) -- removed (sketch handles I/O binding) +- `handlePatchGeneratedFiles()` (renames .c to .inc for unity build) -- removed (not needed for C++) +- MD5 extraction from program.st comments -- replaced by direct hash of program.st content +- References to `iec2c` binary path resolution -- removed +- MatIEC lib/ directory copying -- replaced by STruC++ runtime header copying ## Step 2.2: New STruC++ Compilation Pipeline -### Method: `compileArduinoWithSTruCpp()` +The `compileProgram()` method is refactored to use STruC++ directly: ```typescript -private async compileArduinoWithSTruCpp(args, _mainProcessPort, mainProcessBridge) { - const projectData = args[0] as PLCProjectData - const boardTarget = args[1] as string - const projectPath = args[2] as string - const compileOnly = args[3] as boolean - - const compilationPath = path.join(projectPath, 'build', boardTarget, 'src') - - try { - // === STEP 1: Create directories (unchanged) === - this.createBasicDirectories(projectPath, boardTarget) +// The pipeline steps: +try { + // === STEP 1: Create directories (unchanged) === + this.createBasicDirectories(projectPath, boardTarget) - // === STEP 2: Generate XML from JSON (unchanged) === - await this.handleGenerateXMLfromJSON(projectData, compilationPath) + // === STEP 2: Generate XML from JSON (unchanged) === + await this.handleGenerateXMLfromJSON(projectData, compilationPath) - // === STEP 3: xml2st --generate-st (unchanged) === - await this.handleTranspileXMLtoST(compilationPath) - // Result: program.st in compilationPath + // === STEP 3: xml2st --generate-st (unchanged) === + await this.handleTranspileXMLtoST(compilationPath) + // Result: program.st in compilationPath - // === STEP 4: Copy STruC++ runtime headers to build dir (NEW) === - this.copyStrucppRuntimeHeaders(compilationPath) + // === STEP 4: Copy STruC++ runtime headers to build dir === + this.copyStrucppRuntimeHeaders(compilationPath) - // === STEP 5: Compile ST to C++ with STruC++ (NEW - replaces iec2c) === - this.handleCompileSTtoCpp(compilationPath) + // === STEP 5: Compile ST to C++ with STruC++ (replaces iec2c) === + this.handleCompileSTtoCpp(compilationPath) - // === STEP 6: Copy Arduino sketch + static files (NEW) === - this.copyStrucppSketchFiles(compilationPath) + // === STEP 6: Copy Arduino sketch + static files === + this.copyStrucppSketchFiles(compilationPath) - // === STEP 7: Generate C++ blocks header/code (unchanged) === - await this.handleGenerateCBlocksHeader(projectData, compilationPath) - await this.handleGenerateCBlocksCode(projectData, compilationPath) + // === STEP 7: Generate C++ blocks header/code (unchanged) === + await this.handleGenerateCBlocksHeader(projectData, compilationPath) + await this.handleGenerateCBlocksCode(projectData, compilationPath) - // === STEP 8: Copy HAL file (unchanged) === - await this.handleGenerateArduinoCppFile(boardTarget, compilationPath) + // === STEP 8: Copy HAL file (unchanged) === + await this.handleGenerateArduinoCppFile(boardTarget, compilationPath) - // === STEP 9: Generate defines.h (unchanged in structure) === - await this.handleGenerateDefinitionsFile(projectData, boardTarget, compilationPath) + // === STEP 9: Generate defines.h (unchanged in structure) === + await this.handleGenerateDefinitionsFile(projectData, boardTarget, compilationPath) - // === STEP 10: Arduino compilation (adds -std=gnu++17) === - await this.handleCoreInstallation(boardTarget) - await this.handleLibraryInstallation(boardTarget, compilationPath) - await this.handleCompileArduinoProgram(boardTarget, compilationPath, compileOnly) + // === STEP 10: Arduino compilation (with -std=gnu++17) === + await this.handleCoreInstallation(boardTarget) + await this.handleLibraryInstallation(boardTarget, compilationPath) + await this.handleCompileArduinoProgram(boardTarget, compilationPath, compileOnly) - // === STEP 11: Upload (unchanged) === - if (!compileOnly) { - await this.handleUploadProgram(boardTarget, compilationPath) - } - } catch (error) { - // error handling... + // === STEP 11: Upload (unchanged) === + if (!compileOnly) { + await this.handleUploadProgram(boardTarget, compilationPath) } +} catch (error) { + // error handling... } ``` @@ -128,7 +108,6 @@ Copies the static Arduino sketch and OpenPLC support files to the build director ```typescript private copyStrucppSketchFiles(compilationPath: string): void { const sketchDir = path.join(this.resourcesPath, 'sources', 'StrucppBaremetal') - // Copy all files from the StrucppBaremetal directory for (const file of fs.readdirSync(sketchDir)) { fs.copyFileSync(path.join(sketchDir, file), path.join(compilationPath, file)) } @@ -165,51 +144,34 @@ private handleCompileSTtoCpp(compilationPath: string): void { ### C++17 Compilation Flag -The `handleCompileArduinoProgram` method must ensure `-std=gnu++17` is in the CXX flags -when `compiler_backend === 'strucpp'`. This can be done by: -- Adding `"-std=gnu++17"` to `cxx_flags` in hals.json for each board, or -- Injecting it programmatically in the STruC++ pipeline path +All boards now require `-std=gnu++17`. This is added to `cxx_flags` in `hals.json` for +every board entry. ## Step 2.4: hals.json Changes **File to modify**: `resources/sources/boards/hals.json` -For boards being migrated, add: -```json -{ - "compiler_backend": "strucpp", - "cxx_flags": ["-std=gnu++17", "-MMD", "-c"] -} -``` +- Add `"cxx_flags": ["-std=gnu++17", "-MMD", "-c"]` to all board entries +- Remove any MatIEC-specific fields if present -**C++17 support by platform**: +No `"compiler_backend"` field is needed -- all boards use STruC++ exclusively. -| Platform | GCC Version | C++17 Support | -|----------|-------------|---------------| -| Arduino AVR | 7.3+ | Yes (bundled with Arduino IDE 2.x) | -| ESP32 | 8.4+ (ESP-IDF) | Yes | -| STM32 | 10+ (STM32duino) | Yes | -| RP2040 | 10+ (Arduino Mbed) | Yes | -| SAMD | 7.2+ | Yes | +## Step 2.5: Clean Up MatIEC References -## Step 2.5: Build Directory Structure +Remove or update these across the codebase: +- Binary path resolution for `iec2c` in `compiler-module.ts` +- `matiec` entry from `binary-versions.json` (no longer downloaded) +- MatIEC download logic from `scripts/download-binaries.ts` +- `resources/sources/MatIEC/` directory references +- Any `#executeIec2cBinaryPath` or similar methods +- References to `POUS.c`, `Res0.c`, `Config0.c`, `LOCATED_VARIABLES.h`, `glueVars.c`, `debug.c` -### Old (MatIEC): -``` -build/{boardTarget}/src/ - plc.xml, program.st - lib/ <- MatIEC runtime headers - POUS.c, POUS.h <- MatIEC output - Res0.c, Config0.c, Config0.h - LOCATED_VARIABLES.h - glueVars.c, debug.c <- xml2st output - VARIABLES.csv - c_blocks.h, c_blocks_code.cpp - arduino.cpp, defines.h - Baremetal.ino -``` +Note: `matiec` and `iec2c` references in the `binary-versions.json` and download script +should be removed since they are no longer used. The xml2st binary is still needed for +XML-to-ST conversion. + +## Step 2.6: Build Directory Structure -### New (STruC++): ``` build/{boardTarget}/src/ plc.xml, program.st @@ -227,20 +189,19 @@ build/{boardTarget}/src/ 1. **Code generation**: Compile a simple ST project through the pipeline - Verify `generated.cpp` and `generated.hpp` are produced in the build directory - - Verify the generated code contains expected classes (`Configuration_Config0`, program classes) + - Verify the generated code contains expected classes (`Configuration_Config0`, programs) - The `arduino-cli` step is expected to fail until Phase 3 provides the sketch -2. **Pipeline routing**: Verify MatIEC boards are unaffected - - Board without `compiler_backend` field → old pipeline produces `POUS.c`, `Config0.c`, etc. - - Board with `compiler_backend: "strucpp"` → new pipeline produces `generated.cpp`, `generated.hpp` - -3. **Error handling**: Invalid ST code → STruC++ errors propagated to the UI console +2. **Error handling**: Invalid ST code → STruC++ errors propagated to the UI console -4. **Regression**: All existing compiler tests pass for MatIEC boards +3. **No MatIEC remnants**: Verify no references to iec2c, POUS.c, glueVars.c remain in the + compilation path ## Files Created/Modified | File | Action | |------|--------| -| `src/backend/editor/compiler/compiler-module.ts` | Modified -- add STruC++ pipeline methods | -| `resources/sources/boards/hals.json` | Modified -- add `compiler_backend` and `cxx_flags` | +| `src/backend/editor/compiler/compiler-module.ts` | Modified -- replace MatIEC pipeline with STruC++ | +| `resources/sources/boards/hals.json` | Modified -- add `cxx_flags` to all boards | +| `binary-versions.json` | Modified -- remove matiec entry | +| `scripts/download-binaries.ts` | Modified -- remove matiec download logic | diff --git a/docs/strucpp-migration/03-arduino-runtime-adaptation.md b/docs/strucpp-migration/03-arduino-runtime-adaptation.md index b8235088e..f0f8efebe 100644 --- a/docs/strucpp-migration/03-arduino-runtime-adaptation.md +++ b/docs/strucpp-migration/03-arduino-runtime-adaptation.md @@ -220,18 +220,18 @@ void plcCycleTask() { | Modbus | Unchanged | Unchanged | | HAL | Unchanged | Unchanged | -## Step 3.2: Adapt openplc.h +## Step 3.2: Clean Up openplc.h The current `openplc.h` declares MatIEC-specific functions (`config_init__`, `config_run__`, -`glueVars`, `updateTime`). For STruC++, these are no longer needed -- the sketch handles -everything directly. The sketch needs a version of `openplc.h` that only has: +`glueVars`, `updateTime`, `common_ticktime__`). These are all removed since the sketch handles +everything directly through STruC++ runtime types. + +What remains in `openplc.h`: - IEC type definitions (`IEC_BOOL`, `IEC_INT`, etc.) - Buffer pointer declarations (`bool_input`, `int_output`, etc.) - Buffer size macros (`MAX_DIGITAL_INPUT`, etc.) - HAL function declarations (`hardwareInit`, `updateInputBuffers`, `updateOutputBuffers`) -The MatIEC-specific declarations should be guarded or removed in the STruC++ variant. - ## Design Notes ### Why the Sketch is Fully Static @@ -251,13 +251,12 @@ Rewriting all HAL files for STruC++ types would be a massive effort with no bene sketch's `bindLocatedVars()` populates these same buffer pointers from STruC++ `LocatedVar` descriptors. The HAL files see no difference. -### Memory Layout: IECVar vs MatIEC __IEC_type_p +### Memory Layout: IECVar -| MatIEC | STruC++ | -|--------|---------| -| `__IEC_INT_p { int16_t value; int16_t fvalue; uint8_t flags; }` = 5 bytes | `IECVar { int16_t value_; bool forced_; int16_t forced_value_; }` = 5 bytes | +Each variable is wrapped in `IECVar`: +`IECVar { int16_t value_; bool forced_; int16_t forced_value_; }` = 5 bytes. -Memory overhead is essentially the same. +This is comparable to the old MatIEC `__IEC_INT_p` (5 bytes). No significant memory overhead. ### Dynamic Memory in discoverTasks() @@ -295,6 +294,6 @@ instance (pointer + divisor). | File | Action | |------|--------| | `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` | **New** -- static Arduino sketch | -| `resources/sources/arduino/openplc.h` | Modified -- guard or remove MatIEC-specific declarations | +| `resources/sources/arduino/openplc.h` | Modified -- remove MatIEC-specific declarations | Note: Runtime headers come from `resources/strucpp/runtime/include/` (downloaded in Phase 1). diff --git a/docs/strucpp-migration/04-debugger.md b/docs/strucpp-migration/04-debugger.md index f06b3aef5..c011ae188 100644 --- a/docs/strucpp-migration/04-debugger.md +++ b/docs/strucpp-migration/04-debugger.md @@ -17,8 +17,9 @@ how the runtime actually operates with STruC++ generated code. favor of a simpler static runtime approach. The debugger will likely benefit from similar simplification once we see the full picture. -3. **MatIEC debugger still works**: For boards using `compiler_backend: "matiec"`, the existing - debug.c / VARIABLES.csv / Modbus protocol v1 debugger continues to function unchanged. +3. **Clean slate**: Since MatIEC is fully removed, the debugger can be designed from scratch + without backward compatibility constraints. No need to support the old debug.c format or + flat-index protocol. ## Known Requirements diff --git a/docs/strucpp-migration/05-runtime-v4-so-interface.md b/docs/strucpp-migration/05-runtime-v4-so-interface.md index 3355eb230..3bd4ed917 100644 --- a/docs/strucpp-migration/05-runtime-v4-so-interface.md +++ b/docs/strucpp-migration/05-runtime-v4-so-interface.md @@ -250,7 +250,7 @@ extern "C" char plc_program_md5[] = "/* generated MD5 hash */"; ### Key Design: Flat-to-Hierarchical Index Table The runtime's `debug_handler.c` uses flat indices (`get_var_addr(idx)`). The `flat_var_table[]` -provides backward compatibility: +provides this flat interface on top of the hierarchical STruC++ structures: - One entry per variable (NOT per array element) -- the scalability fix - Flat index = sequential numbering across all program variables @@ -300,27 +300,16 @@ if [ -f "core/generated/generated.cpp" ]; then "$BUILD_DIR/c_blocks_code.o" \ -lpthread -else - echo "Compiling MatIEC generated code..." - # ... existing MatIEC compilation (unchanged) -fi ``` -## Step 6.3: Update Editor Upload Path +The MatIEC fallback branch is removed. All programs compile as C++17. -**File to modify**: `src/backend/editor/compiler/compiler-module.ts` +## Step 5.3: Update Editor Upload Path -When compiling for Runtime v4 with STruC++, the uploaded zip contains different files: +**File to modify**: `src/backend/editor/compiler/compiler-module.ts` -### Old zip contents (MatIEC): -``` -Config0.c, Config0.h, Res0.c, POUS.c, POUS.h -debug.c, glueVars.c, LOCATED_VARIABLES.h -c_blocks.h, c_blocks_code.cpp -lib/ (MatIEC headers) -``` +The uploaded zip contains STruC++ files only: -### New zip contents (STruC++): ``` generated.cpp, generated.hpp v4_compat.cpp @@ -333,9 +322,6 @@ The headers are copied from `resources/strucpp/runtime/include/` (downloaded by `scripts/download-binaries.ts`, NOT stored in the repo). They are strictly version-coupled with the STruC++ compiler that produced the generated code. -The `handleUploadToRuntime` method is updated to package the correct files based on -`compiler_backend`. - ## Step 6.4: Configuration File Generation The editor also generates configuration files for Runtime v4 upload: @@ -358,18 +344,7 @@ The C-linkage shim provides a clean adapter pattern: Runtime (C) --dlsym--> C-linkage symbols --calls--> STruC++ C++ classes ``` -This allows the runtime to work with both MatIEC (C) and STruC++ (C++) programs without -any conditional compilation or runtime detection in the C code. - -### Debug Variable Count Reduction - -With MatIEC: `get_var_count()` returns the expanded count (30,000+ for large projects). -With STruC++: `get_var_count()` returns the un-expanded count (maybe 500 for the same project). - -The runtime's `debug_handler.c` uses `get_var_count()` to validate index bounds. Since the -new count is smaller, all existing bounds checks remain valid. - -The editor knows the correct count from `debug-map.json` and only requests valid indices. +This allows the runtime to load STruC++ C++ programs without rewriting its core C code. ### Thread Safety of Static Configuration @@ -395,8 +370,7 @@ calls `config_init__` from the PLC cycle thread, which is single-threaded at tha - Write to a Modbus register - Verify the PLC program reads the correct value -5. **Backward compatibility**: Upload a MatIEC-compiled program - - Verify runtime still loads and runs it correctly +5. **No MatIEC remnants**: Verify compile.sh has no MatIEC fallback path ## Files Created/Modified diff --git a/docs/strucpp-migration/06-runtime-v4-thread-per-task.md b/docs/strucpp-migration/06-runtime-v4-thread-per-task.md index fd3b35bf9..5b3cb45d6 100644 --- a/docs/strucpp-migration/06-runtime-v4-thread-per-task.md +++ b/docs/strucpp-migration/06-runtime-v4-thread-per-task.md @@ -169,9 +169,6 @@ void load_plc_program(PluginManager* pm) { pthread_create(&plc_task_threads[i], NULL, plc_task_thread, args); } - } else { - // LEGACY: Single-thread model (MatIEC or single-task STruC++) - pthread_create(&plc_thread, NULL, plc_cycle_thread, pm); } } ``` @@ -374,14 +371,10 @@ Only the highest-priority task (task 0) updates the `plc_heartbeat` atomic varia watchdog monitors this to detect PLC stalls. If any task thread crashes, the crash handler sets `plc_state = PLC_STATE_ERROR`, causing all task threads to exit their loops. -### Backward Compatibility - -The `has_strucpp_per_task()` check ensures: -- MatIEC .so files (no `strucpp_get_task_count` symbol): use single-thread model -- STruC++ single-task .so files: use single-thread model (1 task, no benefit from threading) -- STruC++ multi-task .so files: use per-task threading +### Single-Task Optimization -The single-thread model remains the default and is fully preserved. +For single-task projects (only one task in the configuration), the runtime spawns one thread. +This is functionally identical to the old single-thread model but uses the same code path. ## Testing Strategy @@ -407,14 +400,11 @@ The single-thread model remains the default and is fully preserved. 5. **Single-task fallback**: Upload a single-task program - Verify single-thread model is used (no per-task threads) -6. **MatIEC fallback**: Upload a MatIEC-compiled program - - Verify single-thread model is used - ## Files Created/Modified | File | Action | |------|--------| -| `src/backend/shared/utils/PLC/generate-v4-compat.ts` | Modified -- add per-task symbols | +| `v4_compat.cpp` | Modified -- add per-task symbols | | `openplc-runtime/core/src/plc_app/plc_state_manager.c` | Modified -- per-task thread spawning | | `openplc-runtime/core/src/plc_app/plc_state_manager.h` | Modified -- new data structures | | `openplc-runtime/core/src/plc_app/image_tables.c` | Modified -- resolve new symbols | diff --git a/docs/strucpp-migration/07-runtime-v4-debug-handler.md b/docs/strucpp-migration/07-runtime-v4-debug-handler.md index 74dc22297..74689d87f 100644 --- a/docs/strucpp-migration/07-runtime-v4-debug-handler.md +++ b/docs/strucpp-migration/07-runtime-v4-debug-handler.md @@ -291,31 +291,14 @@ transport layer since it treats the PDU as opaque bytes. ### Protocol Detection: v1 vs v2 The `has_strucpp_debug()` check is sufficient because: -- MatIEC .so files: don't export `strucpp_get_program_count` -> v1 -- STruC++ .so files: always export it -> v2 - -There's no ambiguity. The editor and runtime must agree on the protocol version. The editor -detects it from `debug-map.json` (v2) vs `debug.c` (v1). The runtime detects it from -symbol availability. Both detection methods are deterministic and consistent. +Since MatIEC is fully removed, there is no v1/v2 protocol detection needed. All .so files +are STruC++ and export the hierarchical debug symbols. ### Removing the Flat-Index Table -After Phase 7 is deployed, the `flat_var_table[]` in `v4_compat.cpp` becomes dead code for -runtime targets (it's still used by the Arduino path in Phase 5's backward-compatible debug -layer). It can be conditionally compiled: - -```cpp -#ifndef OPENPLC_RUNTIME_V4_NATIVE_DEBUG -// Flat index table for backward compatibility -static const FlatVarEntry flat_var_table[] = { ... }; -extern "C" uint16_t get_var_count(void) { ... } -// ... -#endif -``` - -The old flat-index symbols (`get_var_count`, `get_var_addr`, etc.) should still be exported -for backward compatibility with older runtimes, but they can also use the hierarchical -internal implementation to avoid maintaining two code paths. +After Phase 7 is deployed, the `flat_var_table[]` in `v4_compat.cpp` can be removed entirely +since the runtime natively uses the hierarchical symbols. The old flat-index functions +(`get_var_count`, `get_var_addr`, etc.) are deleted. ### Buffer Size Limits @@ -345,9 +328,7 @@ per batch for RTU, 200+ for TCP/WebSocket). - Verify only requested elements are transmitted - Verify no memory overflow in debug handler -4. **MatIEC fallback**: Upload a MatIEC-compiled program - - Verify v1 debug handler is used - - Verify all existing debug functionality works +4. **No legacy remnants**: Verify no flat-index debug functions remain in the .so 5. **Mixed editor/runtime versions**: Old editor + new runtime, new editor + old runtime - Verify graceful fallback to the common protocol version From 2a857a0b6a5b28e739fdf187eb044176b50d2fe7 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 17:57:29 -0400 Subject: [PATCH 018/296] feat: replace MatIEC (iec2c) with STruC++ compilation pipeline Replace the iec2c binary invocation with STruC++ compile() for ST-to-C++ compilation. This is a clean break -- no dual pipeline, no backward compatibility with MatIEC. Changes: - compiler-module.ts: Remove handleTranspileSTtoC (iec2c), handleGenerateDebugFiles, handleGenerateGlueVars, handlePatchGeneratedFiles, checkIec2cAvailability. Add handleCompileSTtoCpp using STruC++ compile(). Update copyStaticFiles to copy STruC++ runtime headers. MD5 hash computed directly from program.st content. - binary-versions.json: Remove matiec entry - download-binaries.ts: Remove matiec download logic - compiler-adapter.ts: Update inferStage for STruC++ messages - jest.config.json: Add transformIgnorePatterns for strucpp ESM - Tests updated: all 37 tests pass Co-Authored-By: Claude Opus 4.6 (1M context) --- binary-versions.json | 4 - jest.config.json | 5 +- scripts/download-binaries.ts | 91 +--- .../editor/compiler/compiler-module.spec.ts | 3 +- .../editor/compiler/compiler-module.ts | 401 +++++------------- .../editor/__tests__/compiler-adapter.test.ts | 10 +- .../adapters/editor/compiler-adapter.ts | 4 +- 7 files changed, 130 insertions(+), 388 deletions(-) diff --git a/binary-versions.json b/binary-versions.json index 9c4c50a88..cde2bc220 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -3,10 +3,6 @@ "version": "v4.0.3", "repository": "Autonomy-Logic/xml2st" }, - "matiec": { - "version": "v4.0.11", - "repository": "Autonomy-Logic/matiec" - }, "strucpp": { "version": "v0.2.4", "repository": "Autonomy-Logic/STruCpp" diff --git a/jest.config.json b/jest.config.json index 838fa223c..14fcbb24e 100644 --- a/jest.config.json +++ b/jest.config.json @@ -18,8 +18,11 @@ "/src/**/?(*.)+(spec|test).(ts|tsx)", "/src/**/__tests__/**/*.(ts|tsx)" ], + "transformIgnorePatterns": [ + "node_modules/(?!strucpp)" + ], "transform": { - "\\.(ts|tsx)$": [ + "\\.(ts|tsx|js|jsx)$": [ "ts-jest", { "tsconfig": "tsconfig.json" diff --git a/scripts/download-binaries.ts b/scripts/download-binaries.ts index c92dd9e2b..598ce2088 100644 --- a/scripts/download-binaries.ts +++ b/scripts/download-binaries.ts @@ -1,5 +1,5 @@ /** - * Download external tool binaries (xml2st, matiec, strucpp) from GitHub Releases. + * Download external tool binaries (xml2st, strucpp) from GitHub Releases. * * Usage: * ts-node scripts/download-binaries.ts [--platform ] [--arch ] [--force] @@ -22,13 +22,11 @@ interface ToolEntry { interface BinaryVersions { xml2st: ToolEntry - matiec: ToolEntry strucpp: ToolEntry } interface CacheMetadata { xml2st: string - matiec: string platform: string arch: string } @@ -47,7 +45,6 @@ type Arch = 'x64' | 'arm64' const ROOT_DIR = path.resolve(__dirname, '..') const VERSIONS_FILE = path.join(ROOT_DIR, 'binary-versions.json') const RESOURCES_DIR = path.join(ROOT_DIR, 'resources') -const MATIEC_LIB_DIR = path.join(RESOURCES_DIR, 'sources', 'MatIEC', 'lib') const STRUCPP_DIR = path.join(RESOURCES_DIR, 'strucpp') const STRUCPP_CACHE_FILE = path.join(STRUCPP_DIR, '.strucpp-metadata.json') @@ -131,18 +128,6 @@ function needsXml2st(versions: BinaryVersions, cached: CacheMetadata | null, pla return false } -function needsMatiec(versions: BinaryVersions, cached: CacheMetadata | null, platform: Platform, arch: Arch): boolean { - const dir = binDir(platform, arch) - const isWindows = platform === 'win32' - - const iec2cPath = path.join(dir, isWindows ? 'iec2c.exe' : 'iec2c') - - if (!fs.existsSync(iec2cPath)) return true - if (!cached || cached.matiec !== versions.matiec.version) return true - - return false -} - function needsStrucpp(versions: BinaryVersions, strucppCached: StrucppCacheMetadata | null): boolean { // Check if runtime headers exist if (!fs.existsSync(path.join(STRUCPP_DIR, 'runtime', 'include', 'iec_types.hpp'))) return true @@ -168,7 +153,6 @@ function needsStrucpp(versions: BinaryVersions, strucppCached: StrucppCacheMetad function writeCache(versions: BinaryVersions, platform: Platform, arch: Arch): void { const data: CacheMetadata = { xml2st: versions.xml2st.version, - matiec: versions.matiec.version, platform, arch, } @@ -288,70 +272,6 @@ async function downloadXml2st( } } -// --------------------------------------------------------------------------- -// matiec download and extraction -// --------------------------------------------------------------------------- - -async function downloadMatiec( - tool: ToolEntry, - platform: Platform, - arch: Arch, - targetBinDir: string, -): Promise { - const isWindows = platform === 'win32' - const ext = isWindows ? 'zip' : 'tar.gz' - const url = `https://github.com/${tool.repository}/releases/download/${tool.version}/matiec-${platform}-${arch}.${ext}` - - console.log(` Downloading matiec ${tool.version} for ${platform}-${arch}...`) - const tmpDir = fs.mkdtempSync(path.join(RESOURCES_DIR, '.tmp-matiec-')) - - try { - const archivePath = path.join(tmpDir, `matiec.${ext}`) - await downloadToFile(url, archivePath) - - const extractDir = path.join(tmpDir, 'extracted') - if (isWindows) { - extractZip(archivePath, extractDir) - } else { - extractTarGz(archivePath, extractDir) - } - - const extractedToolDir = path.join(extractDir, 'matiec') - - // Copy iec2c binary - const iec2cName = isWindows ? 'iec2c.exe' : 'iec2c' - const iec2cSrc = path.join(extractedToolDir, iec2cName) - const iec2cDest = path.join(targetBinDir, iec2cName) - fs.copyFileSync(iec2cSrc, iec2cDest) - if (!isWindows) { - fs.chmodSync(iec2cDest, 0o755) - } - - // Copy iec2iec binary if present - const iec2iecName = isWindows ? 'iec2iec.exe' : 'iec2iec' - const iec2iecSrc = path.join(extractedToolDir, iec2iecName) - if (fs.existsSync(iec2iecSrc)) { - const iec2iecDest = path.join(targetBinDir, iec2iecName) - fs.copyFileSync(iec2iecSrc, iec2iecDest) - if (!isWindows) { - fs.chmodSync(iec2iecDest, 0o755) - } - } - - // Copy lib/ to resources/sources/MatIEC/lib/ - // Only do this once (for the first platform/arch downloaded), since lib/ is platform-independent - const libSrc = path.join(extractedToolDir, 'lib') - if (fs.existsSync(libSrc)) { - rmrf(MATIEC_LIB_DIR) - copyRecursive(libSrc, MATIEC_LIB_DIR) - } - - console.log(` matiec ${tool.version} installed.`) - } finally { - rmrf(tmpDir) - } -} - // --------------------------------------------------------------------------- // strucpp download and extraction // --------------------------------------------------------------------------- @@ -427,10 +347,9 @@ async function main(): Promise { const cached = force ? null : getCachedMetadata(platform, arch) const strucppCached = force ? null : getStrucppCachedMetadata() const downloadXml2stNeeded = force || needsXml2st(versions, cached, platform, arch) - const downloadMatiecNeeded = force || needsMatiec(versions, cached, platform, arch) const downloadStrucppNeeded = force || needsStrucpp(versions, strucppCached) - if (!downloadXml2stNeeded && !downloadMatiecNeeded && !downloadStrucppNeeded) { + if (!downloadXml2stNeeded && !downloadStrucppNeeded) { console.log(`[download-binaries] All tools up to date, skipping.`) return } @@ -441,12 +360,6 @@ async function main(): Promise { console.log(` xml2st ${versions.xml2st.version} already installed, skipping.`) } - if (downloadMatiecNeeded) { - await downloadMatiec(versions.matiec, platform, arch, targetBinDir) - } else { - console.log(` matiec ${versions.matiec.version} already installed, skipping.`) - } - // strucpp is platform-independent — only download once regardless of platform/arch if (downloadStrucppNeeded) { await downloadStrucpp(versions.strucpp) diff --git a/src/backend/editor/compiler/compiler-module.spec.ts b/src/backend/editor/compiler/compiler-module.spec.ts index 8c293bb41..0e935fc4a 100644 --- a/src/backend/editor/compiler/compiler-module.spec.ts +++ b/src/backend/editor/compiler/compiler-module.spec.ts @@ -42,7 +42,8 @@ describe('CompilerModule', () => { expect(typeof compilerModule.arduinoCliConfigurationFilePath).toBe('string') expect(Array.isArray(compilerModule.arduinoCliBaseParameters)).toBe(true) expect(typeof compilerModule.xml2stBinaryPath).toBe('string') - expect(typeof compilerModule.iec2cBinaryPath).toBe('string') + expect(typeof compilerModule.strucppRuntimeDir).toBe('string') + expect(typeof compilerModule.strucppLibsDir).toBe('string') }) it('getHostHardwareInfo should return a string containing hardware info', () => { diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index 73a000836..7b9eefe5b 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -1,6 +1,7 @@ import { exec, spawn } from 'node:child_process' +import crypto from 'node:crypto' import { promises as fs } from 'node:fs' -import { cp, mkdir, readFile, writeFile } from 'node:fs/promises' +import { cp, mkdir, readFile, readdir, writeFile } from 'node:fs/promises' import type { IncomingMessage } from 'node:http' import https from 'node:https' import os from 'node:os' @@ -8,6 +9,10 @@ import path from 'node:path' import { join } from 'node:path' import { promisify } from 'node:util' +// strucpp is loaded lazily because it uses ESM features (import.meta) that are +// incompatible with Jest's CJS transform. The actual import happens in handleCompileSTtoCpp(). +type StrucppCompile = typeof import('strucpp')['compile'] + import { getRuntimeHttpsOptions } from '@root/backend/editor/utils/runtime-https-config' import type { DeviceConfiguration, DevicePin } from '@root/backend/shared/types/PLC/devices' import type { PLCProjectData } from '@root/backend/shared/types/PLC/open-plc' @@ -58,7 +63,8 @@ class CompilerModule { xml2stBinaryPath: string - iec2cBinaryPath: string + strucppRuntimeDir: string + strucppLibsDir: string // ############################################################################ // =========================== Static properties ============================== @@ -106,7 +112,8 @@ class CompilerModule { this.xml2stBinaryPath = this.#constructXml2stBinaryPath() - this.iec2cBinaryPath = this.#constructIec2cBinaryPath() + this.strucppRuntimeDir = this.#constructStrucppRuntimeDir() + this.strucppLibsDir = this.#constructStrucppLibsDir() } // ############################################################################ @@ -177,8 +184,23 @@ class CompilerModule { return join(this.binaryDirectoryPath, 'xml2st', CompilerModule.HOST_PLATFORM === 'darwin' ? 'xml2st' : '') } - #constructIec2cBinaryPath(): string { - return join(this.binaryDirectoryPath, 'iec2c') + #constructStrucppRuntimeDir(): string { + return join( + CompilerModule.DEVELOPMENT_MODE ? process.cwd() : process.resourcesPath, + CompilerModule.DEVELOPMENT_MODE ? 'resources' : '', + 'strucpp', + 'runtime', + 'include', + ) + } + + #constructStrucppLibsDir(): string { + return join( + CompilerModule.DEVELOPMENT_MODE ? process.cwd() : process.resourcesPath, + CompilerModule.DEVELOPMENT_MODE ? 'resources' : '', + 'strucpp', + 'libs', + ) } async #getBoardRuntime(board: string) { @@ -254,26 +276,15 @@ class CompilerModule { return { success: true, data: VersionString } } - async checkIec2cAvailability(): Promise> { - let binaryPath = this.iec2cBinaryPath - const executeCommand = promisify(exec) - - if (CompilerModule.HOST_PLATFORM === 'win32') { - // INFO: On Windows, we need to add the .exe extension to the binary path. - binaryPath += '.exe' - } - // INFO: We use the version command to check if the iec2c is available. - // INFO: If the command is not available, it will throw an error. - const { stdout, stderr } = await executeCommand(`"${binaryPath}" -v`) - if (stderr) { - throw new Error(`IEC2C not available: ${stderr}`) + checkStrucppAvailability(): MethodsResult { + try { + // Lazy import — strucpp uses ESM features incompatible with Jest's CJS transform + // eslint-disable-next-line @typescript-eslint/no-require-imports + const { getVersion } = require('strucpp') as { getVersion: () => string } + return { success: true, data: getVersion() } + } catch { + throw new Error('STruC++ not available. Run "npm run setup:binaries" to install it.') } - - const firstLine = stdout.split('\n')[0] // Get the first line of the output - const lineAsArray = firstLine.split(' ') // Split the line by spaces - const version = lineAsArray[lineAsArray.length - 1] // The version is the last element in the array - - return { success: true, data: version } } async getArduinoInstalledCores() { @@ -334,37 +345,34 @@ class CompilerModule { // INFO: This method is a placeholder for copying static files. async copyStaticFiles(compilationPath: string, boardTarget: string): Promise> { let result: MethodsResult = { success: false } - let filesToCopy: Promise[] = [] + const sourceTargetFolderPath = join(compilationPath, 'src') const staticArduinoFilesPath = join(this.sourceDirectoryPath, 'arduino') - const staticBaremetalFilesPath = join(this.sourceDirectoryPath, 'Baremetal') - const staticMatIECLibraryFilesPath = join(this.sourceDirectoryPath, 'MatIEC', 'lib') + const staticBaremetalFilesPath = join(this.sourceDirectoryPath, 'StrucppBaremetal') - const sourceTargetFolderPath = join(compilationPath, 'src') + let filesToCopy: Promise[] if (boardTarget !== 'openplc-compiler') { + // Arduino targets: copy Arduino support files, STruC++ headers, and sketch filesToCopy = [ cp(staticArduinoFilesPath, sourceTargetFolderPath, { recursive: true }), - cp(staticMatIECLibraryFilesPath, join(sourceTargetFolderPath, 'lib'), { recursive: true }), + this.copyStrucppRuntimeHeaders(sourceTargetFolderPath), cp(staticBaremetalFilesPath, join(compilationPath, 'examples', 'Baremetal'), { recursive: true }), ] } else { - // INFO: If the board target is OpenPLC, we copy the MatIEC library files and C/C++ block templates. + // OpenPLC Runtime targets: copy STruC++ headers and C/C++ block templates const cBlocksHeaderPath = join(this.sourceDirectoryPath, 'arduino', 'c_blocks.h') - const cBlocksCodePath = join(this.sourceDirectoryPath, 'Baremetal', 'c_blocks_code.cpp') + const cBlocksCodePath = join(this.sourceDirectoryPath, 'StrucppBaremetal', 'c_blocks_code.cpp') filesToCopy = [ - cp(staticMatIECLibraryFilesPath, join(sourceTargetFolderPath, 'lib'), { recursive: true }), + this.copyStrucppRuntimeHeaders(sourceTargetFolderPath), cp(cBlocksHeaderPath, join(sourceTargetFolderPath, 'c_blocks.h')), cp(cBlocksCodePath, join(sourceTargetFolderPath, 'c_blocks_code.cpp')), ] } try { - // Implement the logic to copy static build files. - const results = await Promise.all(filesToCopy) - if (results.every((res) => res === undefined)) { - result = { success: true, data: 'Static build files available' } - } + await Promise.all(filesToCopy) + result = { success: true, data: 'Static build files available' } } catch (error) { throw new Error(`Error copying static files: ${error as string}`) } @@ -372,6 +380,23 @@ class CompilerModule { return result } + /** + * Copy STruC++ C++ runtime headers to the target directory. + * These headers are downloaded by scripts/download-binaries.ts from the STruC++ release. + */ + private async copyStrucppRuntimeHeaders(targetDir: string): Promise { + const runtimeDir = this.strucppRuntimeDir + try { + await fs.access(runtimeDir) + } catch { + throw new Error( + `STruC++ runtime headers not found at ${runtimeDir}. Run "npm run setup:binaries" to download them.`, + ) + } + const files = await readdir(runtimeDir) + await Promise.all(files.map((file) => cp(join(runtimeDir, file), join(targetDir, file)))) + } + // +++++++++++++++++++++++++++ Compilation Methods +++++++++++++++++++++++++++++ async handleGenerateXMLfromJSON(sourceTargetFolderPath: string, jsonData: PLCProjectData) { @@ -422,112 +447,61 @@ class CompilerModule { }) } - async handleTranspileSTtoC( - generatedSTFilePath: string, - handleOutputData: (chunk: Buffer | string, logLevel?: 'info' | 'error') => void, - ) { - // As the iec2c binary generates the C files in the same directory as the binary location, - // we need to set the target directory for the output files accordingly with the generated ST file path. - const targetDirectoryForOutput = join(generatedSTFilePath.replace('program.st', '')) - - let binaryPath = this.iec2cBinaryPath - if (CompilerModule.HOST_PLATFORM === 'win32') { - // INFO: On Windows, we need to add the .exe extension to the binary path. - binaryPath += '.exe' - } - - return new Promise>((resolve, reject) => { - const executeCommand = spawn(binaryPath, ['-f', '-p', '-i', '-l', generatedSTFilePath], { - cwd: targetDirectoryForOutput, - }) - - let stderrData = '' - - // INFO: We use the iec2c command to transpile the ST file to C. - executeCommand.stdout?.on('data', (data: Buffer) => { - handleOutputData(data) - }) - executeCommand.stderr?.on('data', (data: Buffer) => { - stderrData += data.toString() - }) - - executeCommand.on('close', (code) => { - if (code === 0) { - handleOutputData(`C files generated at: ${targetDirectoryForOutput}`, 'info') - resolve({ - success: true, - }) - } else { - reject(new Error(`iec2c process exited with code ${code}\n${stderrData}`)) - } - }) - }) - } - - async handleGenerateDebugFiles( + async handleCompileSTtoCpp( sourceTargetFolderPath: string, handleOutputData: (chunk: Buffer | string, logLevel?: 'info' | 'error') => void, - ) { - const generatedSTFilePath = join(sourceTargetFolderPath, 'program.st') // Assuming the XML file is named 'program.st' - const generatedVARIABLESFilePath = join(sourceTargetFolderPath, 'VARIABLES.csv') // Assuming the VARIABLES file is named 'VARIABLES.csv' + ): Promise<{ md5Hash: string }> { + const stFilePath = join(sourceTargetFolderPath, 'program.st') + const stSource = await readFile(stFilePath, { encoding: 'utf8' }) - return new Promise>((resolve, reject) => { - const executeCommand = this.#executeXml2st(['--generate-debug', generatedSTFilePath, generatedVARIABLESFilePath]) + handleOutputData('Compiling Structured Text to C++ with STruC++...', 'info') - let stderrData = '' + // Lazy import to avoid ESM/CJS issues at module load time (Jest compatibility) + // eslint-disable-next-line @typescript-eslint/no-require-imports + const { compile: strucppCompile } = require('strucpp') as { compile: StrucppCompile } - // INFO: We use the xml2st command to generate debug files. - executeCommand.stdout?.on('data', (data: Buffer) => { - handleOutputData(data) - }) - executeCommand.stderr?.on('data', (data: Buffer) => { - stderrData += data.toString() - }) + const libsDir = this.strucppLibsDir + let libraryPaths: string[] = [] + try { + await fs.access(libsDir) + libraryPaths = [libsDir] + } catch { + // No libs directory available, compile without libraries + } - executeCommand.on('close', (code) => { - if (code === 0) { - handleOutputData(`Debug files generated at: ${sourceTargetFolderPath}`, 'info') - resolve({ - success: true, - }) - } else { - reject(new Error(`xml2st process exited with code ${code}\n${stderrData}`)) - } - }) + const result = strucppCompile(stSource, { + headerFileName: 'generated.hpp', + debug: true, + lineMapping: true, + libraryPaths, }) - } - async handleGenerateGlueVars( - sourceTargetFolderPath: string, - handleOutputData: (chunk: Buffer | string, logLevel?: 'info' | 'error') => void, - ) { - const generatedLocatedVariablesFilePath = join(sourceTargetFolderPath, 'LOCATED_VARIABLES.h') + if (!result.success) { + const msgs = result.errors.map((e) => `Line ${e.line}: ${e.message}`).join('\n') + throw new Error(`STruC++ compilation failed:\n${msgs}`) + } - return new Promise>((resolve, reject) => { - const executeCommand = this.#executeXml2st(['--generate-gluevars', generatedLocatedVariablesFilePath]) + for (const warn of result.warnings) { + handleOutputData(`Warning at line ${warn.line}: ${warn.message}`, 'info') + } - let stderrData = '' + await writeFile(join(sourceTargetFolderPath, 'generated.cpp'), result.cppCode, { encoding: 'utf8' }) + await writeFile(join(sourceTargetFolderPath, 'generated.hpp'), result.headerCode, { encoding: 'utf8' }) - executeCommand.stdout?.on('data', (data: Buffer) => { - handleOutputData(data) - }) - executeCommand.stderr?.on('data', (data: Buffer) => { - stderrData += data.toString() - }) + handleOutputData(`C++ files generated at: ${sourceTargetFolderPath}`, 'info') - executeCommand.on('close', (code) => { - if (code === 0) { - handleOutputData(`Glue vars generated at: ${sourceTargetFolderPath}`, 'info') - resolve({ - success: true, - }) - } else { - reject(new Error(`xml2st process exited with code ${code}\n${stderrData}`)) - } - }) - }) + // Compute MD5 hash directly from the ST source + const md5Hash = crypto.createHash('md5').update(stSource).digest('hex') + handleOutputData(`Program MD5: ${md5Hash}`, 'info') + + return { md5Hash } } + // Debug file generation and glue variable generation are no longer needed. + // STruC++ generates located variable descriptors (locatedVars[]) in the C++ output, + // and the Arduino sketch walks them dynamically for I/O binding. + // The debugger will be redesigned in Phase 4. + // TODO: This method is used to update the index of the Arduino core. // We should validate if this is necessary and if it works correctly. async handleCoreUpdateIndex(handleOutputData: HandleOutputDataCallback) { @@ -890,34 +864,9 @@ class CompilerModule { } } - async handlePatchGeneratedFiles(compilationPath: string, handleOutputData: HandleOutputDataCallback) { - const pousCFilePath = join(compilationPath, 'src', 'POUS.c') - const res0FilePath = join(compilationPath, 'src', 'Res0.c') - const config0FilePath = join(compilationPath, 'src', 'Config0.c') - - const pousCContent = await readFile(pousCFilePath, { encoding: 'utf8' }) - const patchedPousCContent = `#include "POUS.h"\n#include "Config0.h"\n\n${pousCContent}` - await writeFile(pousCFilePath, patchedPousCContent, { encoding: 'utf8' }) - - const res0FileContent = await readFile(res0FilePath, { encoding: 'utf8' }) - - const patchedRes0FileContent = res0FileContent.replaceAll('#include "POUS.c"', '#include "POUS.h"\n') - - await writeFile(res0FilePath, patchedRes0FileContent, { encoding: 'utf8' }) - handleOutputData('Required files patched', 'info') - - // Unity build: Rename .c files to .inc so Arduino build system doesn't compile them separately. - // These files are #included by glueVars.c as a single compilation unit to avoid - // duplicate static function definitions that cause binary size bloat. - const pousIncFilePath = join(compilationPath, 'src', 'POUS.inc') - const res0IncFilePath = join(compilationPath, 'src', 'Res0.inc') - const config0IncFilePath = join(compilationPath, 'src', 'Config0.inc') - - await fs.rename(pousCFilePath, pousIncFilePath) - await fs.rename(res0FilePath, res0IncFilePath) - await fs.rename(config0FilePath, config0IncFilePath) - handleOutputData('Files renamed to .inc for unity build', 'info') - } + // handlePatchGeneratedFiles is no longer needed. + // STruC++ generates clean C++ files (generated.cpp + generated.hpp) that don't require + // patching or unity build renaming. async handleGenerateArduinoCppFile(projectPath: string, boardTarget: string) { let result: MethodsResult = { success: false } @@ -1451,12 +1400,12 @@ class CompilerModule { _mainProcessPort.postMessage({ logLevel: 'info', message: 'Checking tools availability...' }) try { - const [arduinoCliCheckResult, iec2cCheckResult] = await Promise.all([ + const [arduinoCliCheckResult, strucppCheckResult] = await Promise.all([ this.checkArduinoCliAvailability(), - this.checkIec2cAvailability(), + Promise.resolve(this.checkStrucppAvailability()), ]) _mainProcessPort.postMessage({ - message: `Arduino CLI available at version ${arduinoCliCheckResult.data}\nIEC2C available at version ${iec2cCheckResult.data}`, + message: `Arduino CLI available at version ${arduinoCliCheckResult.data}\nSTruC++ available at version ${strucppCheckResult.data}`, }) } catch (_error) { _mainProcessPort.postMessage({ @@ -1531,76 +1480,12 @@ class CompilerModule { return } - // Step 4: Generate C code from ST - const generatedSTFilePath = join(sourceTargetFolderPath, 'program.st') // Assuming the ST file is named 'program.st' - try { - await this.handleTranspileSTtoC(generatedSTFilePath, (data, logLevel) => { - _mainProcessPort.postMessage({ logLevel, message: data }) - }) - } catch (error) { - _mainProcessPort.postMessage({ - logLevel: 'error', - message: typeof error === 'string' ? error : error instanceof Error ? error.message : JSON.stringify(error), - }) - _mainProcessPort.postMessage({ - logLevel: 'error', - message: 'Stopping compilation process.', - }) - _mainProcessPort.close() - return - } - - // Step 5: Generate debug files - try { - await this.handleGenerateDebugFiles(sourceTargetFolderPath, (data, logLevel) => { - _mainProcessPort.postMessage({ logLevel, message: data }) - }) - } catch (error) { - _mainProcessPort.postMessage({ - logLevel: 'error', - message: typeof error === 'string' ? error : error instanceof Error ? error.message : JSON.stringify(error), - }) - _mainProcessPort.postMessage({ - logLevel: 'error', - message: 'Stopping compilation process.', - }) - _mainProcessPort.close() - return - } - - try { - const fs = await import('fs/promises') - const programStPath = join(sourceTargetFolderPath, 'program.st') - const programStContent = await fs.readFile(programStPath, 'utf-8') - const md5Pattern = /\(\*DBG:char md5\[\] = "([a-fA-F0-9]{32})";?\*\)/ - const match = programStContent.match(md5Pattern) - - if (match && match[1]) { - buildMD5Hash = match[1] - _mainProcessPort.postMessage({ - logLevel: 'info', - message: `Extracted MD5 hash from program.st: ${buildMD5Hash}`, - }) - } else { - _mainProcessPort.postMessage({ - logLevel: 'warn', - message: 'Could not extract MD5 from program.st, continuing without MD5', - }) - buildMD5Hash = null - } - } catch (error) { - _mainProcessPort.postMessage({ - logLevel: 'error', - message: `Error extracting MD5 from program.st: ${error as string}`, - }) - buildMD5Hash = null - } - - // Step 6: Generate glue vars + // Step 4: Compile ST to C++ with STruC++ (replaces iec2c + debug + glue generation) try { - await this.handleGenerateGlueVars(sourceTargetFolderPath, (data, logLevel) => { + const { md5Hash } = await this.handleCompileSTtoCpp(sourceTargetFolderPath, (data, logLevel) => { _mainProcessPort.postMessage({ logLevel, message: data }) }) + buildMD5Hash = md5Hash } catch (error) { _mainProcessPort.postMessage({ logLevel: 'error', @@ -1986,25 +1871,7 @@ class CompilerModule { return } - // Step 7: Handle patch files - try { - await this.handlePatchGeneratedFiles(compilationPath, (data, logLevel) => { - _mainProcessPort.postMessage({ logLevel, message: data }) - }) - } catch (error) { - _mainProcessPort.postMessage({ - logLevel: 'error', - message: typeof error === 'string' ? error : error instanceof Error ? error.message : JSON.stringify(error), - }) - _mainProcessPort.postMessage({ - logLevel: 'error', - message: 'Stopping compilation process.', - }) - _mainProcessPort.close() - return - } - - // Step 8: Handle core installation + // Step 5: Handle core installation _mainProcessPort.postMessage({ logLevel: 'info', message: 'Handling core installation...' }) try { await this.handleCoreInstallation(boardCore, (data, logLevel) => { @@ -2175,9 +2042,9 @@ class CompilerModule { }) try { - const iec2cCheckResult = await this.checkIec2cAvailability() + const strucppCheckResult = this.checkStrucppAvailability() _mainProcessPort.postMessage({ - message: `IEC2C available at version ${iec2cCheckResult.data}`, + message: `STruC++ available at version ${strucppCheckResult.data}`, }) } catch (_error) { _mainProcessPort.postMessage({ @@ -2244,43 +2111,9 @@ class CompilerModule { return } - const generatedSTFilePath = join(sourceTargetFolderPath, 'program.st') - try { - await this.handleTranspileSTtoC(generatedSTFilePath, (data, logLevel) => { - _mainProcessPort.postMessage({ logLevel, message: data }) - }) - } catch (error) { - _mainProcessPort.postMessage({ - logLevel: 'error', - message: typeof error === 'string' ? error : error instanceof Error ? error.message : JSON.stringify(error), - }) - _mainProcessPort.postMessage({ - logLevel: 'error', - message: 'Stopping debug compilation process.', - }) - _mainProcessPort.close() - return - } - - try { - await this.handleGenerateDebugFiles(sourceTargetFolderPath, (data, logLevel) => { - _mainProcessPort.postMessage({ logLevel, message: data }) - }) - } catch (error) { - _mainProcessPort.postMessage({ - logLevel: 'error', - message: typeof error === 'string' ? error : error instanceof Error ? error.message : JSON.stringify(error), - }) - _mainProcessPort.postMessage({ - logLevel: 'error', - message: 'Stopping debug compilation process.', - }) - _mainProcessPort.close() - return - } - + // Compile ST to C++ with STruC++ (replaces iec2c + debug + glue generation) try { - await this.handleGenerateGlueVars(sourceTargetFolderPath, (data, logLevel) => { + await this.handleCompileSTtoCpp(sourceTargetFolderPath, (data, logLevel) => { _mainProcessPort.postMessage({ logLevel, message: data }) }) } catch (error) { diff --git a/src/middleware/adapters/editor/__tests__/compiler-adapter.test.ts b/src/middleware/adapters/editor/__tests__/compiler-adapter.test.ts index ab23cd705..49f6f61ee 100644 --- a/src/middleware/adapters/editor/__tests__/compiler-adapter.test.ts +++ b/src/middleware/adapters/editor/__tests__/compiler-adapter.test.ts @@ -156,14 +156,10 @@ describe('inferStage', () => { expect(inferStage('Transpiling program')).toBe('st') }) - it('detects C stage', () => { - expect(inferStage('Running iec2c compiler')).toBe('c') + it('detects C/C++ stage', () => { + expect(inferStage('Compiling Structured Text to C++ with STruC++')).toBe('c') expect(inferStage('Generating C code')).toBe('c') - expect(inferStage('Generating c code output')).toBe('c') - }) - - it('detects glue stage', () => { - expect(inferStage('Generating glue variables')).toBe('glue') + expect(inferStage('C++ files generated at: /tmp/build')).toBe('c') }) it('detects arduino stage', () => { diff --git a/src/middleware/adapters/editor/compiler-adapter.ts b/src/middleware/adapters/editor/compiler-adapter.ts index 44e627aa2..2b14382e5 100644 --- a/src/middleware/adapters/editor/compiler-adapter.ts +++ b/src/middleware/adapters/editor/compiler-adapter.ts @@ -92,9 +92,9 @@ function decodeMessage(raw: unknown): string { function inferStage(message: string): CompileProgressEvent['stage'] { const lower = message.toLowerCase() if (lower.includes('xml') || lower.includes('generating xml')) return 'xml' + // C++ check before ST — STruC++ messages like "Compiling ST to C++" contain both keywords + if (lower.includes('struc++') || lower.includes('c++') || lower.includes('c code')) return 'c' if (lower.includes('structured text') || lower.includes('.st') || lower.includes('transpil')) return 'st' - if (lower.includes('iec2c') || lower.includes('generating c') || lower.includes('c code')) return 'c' - if (lower.includes('glue')) return 'glue' if (lower.includes('arduino') || lower.includes('compiling') || lower.includes('uploading')) return 'arduino' return 'st' } From a66e568623ac96f0be41f9d9f63a0b073e3b440b Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 22:15:08 -0400 Subject: [PATCH 019/296] docs: move deferred Phase 2 tasks into Phase 3 Add hals.json cxx_flags update and end-to-end compilation test to Phase 3 docs, since both require the Arduino sketch to exist. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../03-arduino-runtime-adaptation.md | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/docs/strucpp-migration/03-arduino-runtime-adaptation.md b/docs/strucpp-migration/03-arduino-runtime-adaptation.md index f0f8efebe..78ac7dcc0 100644 --- a/docs/strucpp-migration/03-arduino-runtime-adaptation.md +++ b/docs/strucpp-migration/03-arduino-runtime-adaptation.md @@ -270,6 +270,16 @@ Arduino, this is acceptable since: For boards with very tight memory (ATmega328P), the total overhead is ~8 bytes per program instance (pointer + divisor). +## Step 3.3: Add `-std=gnu++17` to hals.json + +**File to modify**: `resources/sources/boards/hals.json` + +Add `"cxx_flags": ["-std=gnu++17", "-MMD", "-c"]` to all board entries. This is required +for arduino-cli to compile the STruC++ C++17 output. + +(Deferred from Phase 2 since it's only needed once the sketch exists and arduino-cli +actually compiles the STruC++ output.) + ## Testing Strategy 1. **End-to-end compile**: Simple ST project through the full pipeline @@ -289,11 +299,18 @@ instance (pointer + divisor). 4. **HAL compatibility test**: Compile with each major HAL file - Verify no compilation errors with STruC++ C++17 code +5. **End-to-end code generation test**: Verify the full pipeline from `program.st` through + STruC++ `compile()` to `generated.cpp`/`generated.hpp` in the build directory, followed + by a successful `arduino-cli` compilation producing a firmware binary. + (Deferred from Phase 2 -- code generation was validated via unit tests, but the full + arduino-cli round-trip requires the sketch and adapted openplc.h from this phase.) + ## Files Created/Modified | File | Action | |------|--------| | `resources/sources/StrucppBaremetal/StrucppBaremetal.ino` | **New** -- static Arduino sketch | | `resources/sources/arduino/openplc.h` | Modified -- remove MatIEC-specific declarations | +| `resources/sources/boards/hals.json` | Modified -- add `-std=gnu++17` to `cxx_flags` | Note: Runtime headers come from `resources/strucpp/runtime/include/` (downloaded in Phase 1). From 2a3cb528e865b4dbe052a521429bc7561ac25819 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 22:32:08 -0400 Subject: [PATCH 020/296] fix: skip StrucppBaremetal copy if sketch dir doesn't exist yet The Arduino sketch is a Phase 3 artifact. The pipeline should not fail at the static file copy step -- it should proceed through STruC++ compilation and only fail at arduino-cli (which requires the sketch). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../editor/compiler/compiler-module.ts | 29 ++++++++++--------- 1 file changed, 16 insertions(+), 13 deletions(-) diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index 7b9eefe5b..c5d9cb6ae 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -344,40 +344,43 @@ class CompilerModule { // INFO: This method is a placeholder for copying static files. async copyStaticFiles(compilationPath: string, boardTarget: string): Promise> { - let result: MethodsResult = { success: false } const sourceTargetFolderPath = join(compilationPath, 'src') const staticArduinoFilesPath = join(this.sourceDirectoryPath, 'arduino') const staticBaremetalFilesPath = join(this.sourceDirectoryPath, 'StrucppBaremetal') - let filesToCopy: Promise[] + const filesToCopy: Promise[] = [] if (boardTarget !== 'openplc-compiler') { - // Arduino targets: copy Arduino support files, STruC++ headers, and sketch - filesToCopy = [ + // Arduino targets: copy Arduino support files and STruC++ runtime headers + filesToCopy.push( cp(staticArduinoFilesPath, sourceTargetFolderPath, { recursive: true }), this.copyStrucppRuntimeHeaders(sourceTargetFolderPath), - cp(staticBaremetalFilesPath, join(compilationPath, 'examples', 'Baremetal'), { recursive: true }), - ] + ) + // Copy sketch if available (created in Phase 3) + try { + await fs.access(staticBaremetalFilesPath) + filesToCopy.push( + cp(staticBaremetalFilesPath, join(compilationPath, 'examples', 'Baremetal'), { recursive: true }), + ) + } catch { + // StrucppBaremetal sketch not yet available -- Phase 3 will create it + } } else { // OpenPLC Runtime targets: copy STruC++ headers and C/C++ block templates const cBlocksHeaderPath = join(this.sourceDirectoryPath, 'arduino', 'c_blocks.h') - const cBlocksCodePath = join(this.sourceDirectoryPath, 'StrucppBaremetal', 'c_blocks_code.cpp') - filesToCopy = [ + filesToCopy.push( this.copyStrucppRuntimeHeaders(sourceTargetFolderPath), cp(cBlocksHeaderPath, join(sourceTargetFolderPath, 'c_blocks.h')), - cp(cBlocksCodePath, join(sourceTargetFolderPath, 'c_blocks_code.cpp')), - ] + ) } try { await Promise.all(filesToCopy) - result = { success: true, data: 'Static build files available' } + return { success: true, data: 'Static build files available' } } catch (error) { throw new Error(`Error copying static files: ${error as string}`) } - - return result } /** From 3d964e6c077358d41a3edc4bb47424b3dfecfab3 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 22:38:08 -0400 Subject: [PATCH 021/296] fix: use STruC++ {external} syntax for embedded C/C++ code Replace MatIEC's {{ ... }} embedded C syntax with STruC++'s {external ... } pragma in both Python and C++ POU code generators. STruC++ uses {external ... } to pass C/C++ code through AS-IS to the generated output. The content inside is identical -- only the delimiter syntax changes. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/frontend/utils/cpp/generateSTCode.ts | 20 ++++++++++---------- src/frontend/utils/python/generateSTCode.ts | 12 ++++++------ 2 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/frontend/utils/cpp/generateSTCode.ts b/src/frontend/utils/cpp/generateSTCode.ts index 109513bc5..fd6be3f05 100644 --- a/src/frontend/utils/cpp/generateSTCode.ts +++ b/src/frontend/utils/cpp/generateSTCode.ts @@ -13,8 +13,8 @@ type STCodeGenerationParams = { /** * Generate flat temporary array declarations for array variables. - * iec2c wraps each element in __IEC_TYPE_t (value + flags), so we need - * flat IEC_TYPE arrays for C code that expects contiguous typed elements. + * STruC++ wraps each element in IECVar (value + forced flag + forced value), so we need + * flat arrays for C code that expects contiguous typed elements. */ const generateFlatArrayDeclarations = (arrayVariables: PLCVariable[]): string => { let code = '' @@ -94,22 +94,22 @@ const generateSTCode = (params: STCodeGenerationParams): string => { const outputCopyBack = generateOutputArrayCopyBack(outputVariables) - let stCode = `{{ + let stCode = `{external ${structName} vars; -${flatArrayDecl}${flatArrayCopiesIn}${variableAssignments}}} +${flatArrayDecl}${flatArrayCopiesIn}${variableAssignments}} if hasBeenInitialized = False then -{{ +{external ${setupFunctionName}(&vars); -}} +} hasBeenInitialized := True; end_if; -{{ +{external ${loopFunctionName}(&vars); -}}` +}` if (outputCopyBack) { - stCode += `\n{{ -${outputCopyBack}}}` + stCode += `\n{external +${outputCopyBack}}` } return stCode diff --git a/src/frontend/utils/python/generateSTCode.ts b/src/frontend/utils/python/generateSTCode.ts index e3f0999ca..ce19ae954 100644 --- a/src/frontend/utils/python/generateSTCode.ts +++ b/src/frontend/utils/python/generateSTCode.ts @@ -115,7 +115,7 @@ const generateSTCode = (params: STCodeGenerationParams): string => { .replace(/\n/g, '\\n"\n "') const stCode = `(* Type definitions *) -{{ +{external typedef uint8_t IEC_BOOL; typedef int8_t IEC_SINT; typedef int16_t IEC_INT; @@ -140,10 +140,10 @@ const generateSTCode = (params: STCodeGenerationParams): string => { } IEC_STRING; ${cStructs} -}} +} if first_run = false then - {{ + {external pid_t pid = getpid(); void *shm_in_ptr = NULL; void *shm_out_ptr = NULL; @@ -162,10 +162,10 @@ if first_run = false then data__->SHM_IN_PTR.value = (uint64_t)shm_in_ptr; data__->SHM_OUT_PTR.value = (uint64_t)shm_out_ptr; - }} + } first_run := true; else - {{ + {external void *shm_in_ptr = (void *)data__->SHM_IN_PTR.value; void *shm_out_ptr = (void *)data__->SHM_OUT_PTR.value; @@ -180,7 +180,7 @@ else return; } -${inputCopyCode}${outputCopyCode} }} +${inputCopyCode}${outputCopyCode} } end_if;` return stCode From 6622a73b2891c4856d85bfbb4096c99f3829ce9b Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 22:49:28 -0400 Subject: [PATCH 022/296] feat: add Arduino runtime for STruC++ (Phase 3) - Create StrucppBaremetal.ino: static sketch that dynamically navigates STruC++ runtime structures -- walks locatedVars[] for I/O binding, discovers tasks via Configuration/Resource/Task, computes GCD for scan cycle timing, schedules programs with per-task divisors. - Clean up openplc.h: remove MatIEC-specific declarations (config_init__, config_run__, glueVars, updateTime, common_ticktime__). Keep IEC types, buffer pointers, buffer size macros, and HAL functions. - Add -std=gnu++17 to cxx_flags for all 62 boards in hals.json. Co-Authored-By: Claude Opus 4.6 (1M context) --- .../StrucppBaremetal/StrucppBaremetal.ino | 453 ++++++++++++++ resources/sources/arduino/openplc.h | 23 +- resources/sources/boards/hals.json | 556 ++++++++++++++---- 3 files changed, 908 insertions(+), 124 deletions(-) create mode 100644 resources/sources/StrucppBaremetal/StrucppBaremetal.ino diff --git a/resources/sources/StrucppBaremetal/StrucppBaremetal.ino b/resources/sources/StrucppBaremetal/StrucppBaremetal.ino new file mode 100644 index 000000000..482749334 --- /dev/null +++ b/resources/sources/StrucppBaremetal/StrucppBaremetal.ino @@ -0,0 +1,453 @@ +// StrucppBaremetal.ino -- OpenPLC Arduino runtime for STruC++ generated code. +// +// This is a STATIC sketch -- the same code for every project. It dynamically +// discovers the project structure from STruC++ runtime types at setup() time: +// - Walks locatedVars[] to bind I/O to openplc.h buffer pointers +// - Walks Configuration → Resource → Task to discover programs and intervals +// - Computes GCD of task intervals for the scan cycle base tick +// - Schedules programs round-robin with per-task divisors + +#include "generated.hpp" +#include "openplc.h" +#include "defines.h" + +#ifdef MODBUS_ENABLED +#include "ModbusSlave.h" +#endif + +// Include WiFi lib to turn off WiFi radio on ESP32/ESP8266 if not using WiFi +#ifndef MBTCP + #if defined(BOARD_ESP8266) + #include + #elif defined(BOARD_ESP32) + #include + #endif +#endif + +// --------------------------------------------------------------------------- +// STruC++ Configuration instance (always Config0 in OpenPLC) +// --------------------------------------------------------------------------- +static strucpp::Configuration_Config0 g_config; + +// --------------------------------------------------------------------------- +// Task scheduling state (populated by discoverTasks) +// --------------------------------------------------------------------------- +static strucpp::ProgramBase** all_programs = nullptr; +static uint32_t* task_divisors = nullptr; +static size_t total_programs = 0; +unsigned long long common_ticktime__ = 20000000ULL; // default 20ms, overwritten by discoverTasks + +// --------------------------------------------------------------------------- +// Scan cycle timing +// --------------------------------------------------------------------------- +uint32_t __tick = 0; +unsigned long scan_cycle; +unsigned long last_run = 0; +bool first_cycle = false; + +// --------------------------------------------------------------------------- +// Module includes and external sketch support +// --------------------------------------------------------------------------- +#include "arduino_libs.h" + +#ifdef USE_ARDUINO_SKETCH + #include "ext/arduino_sketch.h" +#endif + +extern uint8_t pinMask_DIN[]; +extern uint8_t pinMask_AIN[]; +extern uint8_t pinMask_DOUT[]; +extern uint8_t pinMask_AOUT[]; + +// --------------------------------------------------------------------------- +// GCD utility +// --------------------------------------------------------------------------- +static uint64_t gcd(uint64_t a, uint64_t b) { + while (b) { uint64_t t = b; b = a % b; a = t; } + return a; +} + +// --------------------------------------------------------------------------- +// I/O Binding: walk locatedVars[] and bind to openplc.h buffer pointers +// --------------------------------------------------------------------------- +void bindLocatedVars() { + using namespace strucpp; + for (uint32_t i = 0; i < locatedVarsCount; ++i) { + LocatedVar& lv = locatedVars[i]; + if (!lv.pointer) continue; + + switch (lv.area) { + case LocatedArea::Input: + switch (lv.size) { + case LocatedSize::Bit: + bool_input[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; + break; + case LocatedSize::Word: + int_input[lv.byte_index] = (IEC_UINT*)lv.pointer; + break; +#if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) + case LocatedSize::DWord: + // dint_input not available on all boards + break; + case LocatedSize::LWord: + // lint_input not available on all boards + break; +#endif + default: break; + } + break; + + case LocatedArea::Output: + switch (lv.size) { + case LocatedSize::Bit: + bool_output[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; + break; + case LocatedSize::Word: + int_output[lv.byte_index] = (IEC_UINT*)lv.pointer; + break; +#if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) + case LocatedSize::DWord: + // dint_output not available on all boards + break; + case LocatedSize::LWord: + // lint_output not available on all boards + break; +#endif + default: break; + } + break; + + case LocatedArea::Memory: +#if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) + switch (lv.size) { + case LocatedSize::Word: + int_memory[lv.byte_index] = (IEC_UINT*)lv.pointer; + break; + case LocatedSize::DWord: + dint_memory[lv.byte_index] = (IEC_UDINT*)lv.pointer; + break; + case LocatedSize::LWord: + lint_memory[lv.byte_index] = (IEC_ULINT*)lv.pointer; + break; + default: break; + } +#endif + break; + } + } +} + +// --------------------------------------------------------------------------- +// Task Discovery: walk Configuration → Resource → Task to find programs +// --------------------------------------------------------------------------- +void discoverTasks() { + // First pass: count programs and compute GCD of intervals + uint64_t gcd_ns = 0; + size_t prog_count = 0; + + auto* resources = g_config.get_resources(); + for (size_t r = 0; r < g_config.get_resource_count(); ++r) { + for (size_t t = 0; t < resources[r].task_count; ++t) { + auto& task = resources[r].tasks[t]; + prog_count += task.program_count; + uint64_t interval = task.interval_ns > 0 ? task.interval_ns : 20000000ULL; + gcd_ns = (gcd_ns == 0) ? interval : gcd(gcd_ns, interval); + } + } + + if (gcd_ns == 0) gcd_ns = 20000000ULL; + common_ticktime__ = gcd_ns; + + // Second pass: build flat arrays of programs and their divisors + all_programs = new strucpp::ProgramBase*[prog_count]; + task_divisors = new uint32_t[prog_count]; + total_programs = prog_count; + + size_t idx = 0; + for (size_t r = 0; r < g_config.get_resource_count(); ++r) { + for (size_t t = 0; t < resources[r].task_count; ++t) { + auto& task = resources[r].tasks[t]; + uint64_t interval = task.interval_ns > 0 ? task.interval_ns : gcd_ns; + uint32_t divisor = (uint32_t)(interval / gcd_ns); + for (size_t p = 0; p < task.program_count; ++p) { + all_programs[idx] = task.programs[p]; + task_divisors[idx] = divisor; + idx++; + } + } + } +} + +// --------------------------------------------------------------------------- +// Time update +// --------------------------------------------------------------------------- +void updateTime() { + extern int64_t __CURRENT_TIME_NS; + __CURRENT_TIME_NS += (int64_t)common_ticktime__; +} + +// --------------------------------------------------------------------------- +// Scan cycle delay setup +// --------------------------------------------------------------------------- +void setupCycleDelay(unsigned long long cycle_time) { + scan_cycle = (uint32_t)(cycle_time / 1000); + last_run = micros(); +} + +// ============================================================================= +// SETUP +// ============================================================================= +void setup() { + // Turn off WiFi radio on ESP32/ESP8266 if not using WiFi + #ifndef MBTCP + #if defined(BOARD_ESP8266) || defined(BOARD_ESP32) + WiFi.mode(WIFI_OFF); + #endif + #endif + + // Bind located variables to I/O buffer pointers + bindLocatedVars(); + + // Discover tasks and compute scheduling + discoverTasks(); + + // Initialize hardware (HAL -- unchanged) + hardwareInit(); + + #ifdef MODBUS_ENABLED + #ifdef MBSERIAL + #ifdef MBSERIAL_TXPIN + // Disable TX pin from OpenPLC hardware layer + for (int i = 0; i < NUM_DISCRETE_INPUT; i++) { + if (pinMask_DIN[i] == MBSERIAL_TXPIN) pinMask_DIN[i] = 255; + } + for (int i = 0; i < NUM_ANALOG_INPUT; i++) { + if (pinMask_AIN[i] == MBSERIAL_TXPIN) pinMask_AIN[i] = 255; + } + for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++) { + if (pinMask_DOUT[i] == MBSERIAL_TXPIN) pinMask_DOUT[i] = 255; + } + for (int i = 0; i < NUM_ANALOG_OUTPUT; i++) { + if (pinMask_AOUT[i] == MBSERIAL_TXPIN) pinMask_AOUT[i] = 255; + } + MBSERIAL_IFACE.begin(MBSERIAL_BAUD); + mbconfig_serial_iface(&MBSERIAL_IFACE, MBSERIAL_BAUD, MBSERIAL_TXPIN); + #else + MBSERIAL_IFACE.begin(MBSERIAL_BAUD); + mbconfig_serial_iface(&MBSERIAL_IFACE, MBSERIAL_BAUD, -1); + #endif + modbus.slaveid = MBSERIAL_SLAVE; + #endif + + #ifdef MBTCP + uint8_t mac[] = { MBTCP_MAC }; + uint8_t ip[] = { MBTCP_IP }; + uint8_t dns[] = { MBTCP_DNS }; + uint8_t gateway[] = { MBTCP_GATEWAY }; + uint8_t subnet[] = { MBTCP_SUBNET }; + + if (sizeof(ip)/sizeof(uint8_t) < 4) + mbconfig_ethernet_iface(mac, NULL, NULL, NULL, NULL); + else if (sizeof(dns)/sizeof(uint8_t) < 4) + mbconfig_ethernet_iface(mac, ip, NULL, NULL, NULL); + else if (sizeof(gateway)/sizeof(uint8_t) < 4) + mbconfig_ethernet_iface(mac, ip, dns, NULL, NULL); + else if (sizeof(subnet)/sizeof(uint8_t) < 4) + mbconfig_ethernet_iface(mac, ip, dns, gateway, NULL); + else + mbconfig_ethernet_iface(mac, ip, dns, gateway, subnet); + #endif + + init_mbregs(MAX_ANALOG_OUTPUT + MAX_MEMORY_WORD, MAX_MEMORY_DWORD, MAX_MEMORY_LWORD, MAX_DIGITAL_OUTPUT, MAX_ANALOG_INPUT, MAX_DIGITAL_INPUT); + mapEmptyBuffers(); + #endif + + setupCycleDelay(common_ticktime__); + + #ifdef USE_ARDUINO_SKETCH + sketch_setup(); + #endif +} + +// ============================================================================= +// MAP EMPTY BUFFERS (for Modbus -- identical to current Baremetal.ino) +// ============================================================================= +#ifdef MODBUS_ENABLED +void mapEmptyBuffers() { + for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) { + if (bool_output[i/8][i%8] == NULL) { + bool_output[i/8][i%8] = (IEC_BOOL *)malloc(sizeof(IEC_BOOL)); + *bool_output[i/8][i%8] = 0; + } + } + for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) { + if (int_output[i] == NULL) { + int_output[i] = (IEC_UINT *)(modbus.holding + i); + } + } + for (int i = 0; i < MAX_DIGITAL_INPUT; i++) { + if (bool_input[i/8][i%8] == NULL) { + bool_input[i/8][i%8] = (IEC_BOOL *)malloc(sizeof(IEC_BOOL)); + *bool_input[i/8][i%8] = 0; + } + } + for (int i = 0; i < MAX_ANALOG_INPUT; i++) { + if (int_input[i] == NULL) { + int_input[i] = (IEC_UINT *)(modbus.input_regs + i); + } + } + #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) + for (int i = 0; i < MAX_MEMORY_WORD; i++) { + if (int_memory[i] == NULL) { + int_memory[i] = (IEC_UINT *)(modbus.holding + MAX_ANALOG_OUTPUT + i); + } + } + for (int i = 0; i < MAX_MEMORY_DWORD; i++) { + if (dint_memory[i] == NULL) { + dint_memory[i] = (IEC_UDINT *)(modbus.dint_memory + i); + } + } + for (int i = 0; i < MAX_MEMORY_LWORD; i++) { + if (lint_memory[i] == NULL) { + lint_memory[i] = (IEC_ULINT *)(modbus.lint_memory + i); + } + } + #endif +} + +// ============================================================================= +// MODBUS TASK (identical to current Baremetal.ino) +// ============================================================================= +void modbusTask() { + // Sync OpenPLC Buffers with Modbus Buffers + for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) { + if (bool_output[i/8][i%8] != NULL) { + write_discrete(i, COILS, (bool)*bool_output[i/8][i%8]); + } + } + for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) { + if (int_output[i] != NULL) { + modbus.holding[i] = *int_output[i]; + } + } + for (int i = 0; i < MAX_DIGITAL_INPUT; i++) { + if (bool_input[i/8][i%8] != NULL) { + write_discrete(i, INPUTSTATUS, (bool)*bool_input[i/8][i%8]); + } + } + for (int i = 0; i < MAX_ANALOG_INPUT; i++) { + if (int_input[i] != NULL) { + modbus.input_regs[i] = *int_input[i]; + } + } + #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) + for (int i = 0; i < MAX_MEMORY_WORD; i++) { + if (int_memory[i] != NULL) { + modbus.holding[i + MAX_ANALOG_OUTPUT] = *int_memory[i]; + } + } + for (int i = 0; i < MAX_MEMORY_DWORD; i++) { + if (dint_memory[i] != NULL) { + modbus.dint_memory[i] = *dint_memory[i]; + } + } + for (int i = 0; i < MAX_MEMORY_LWORD; i++) { + if (lint_memory[i] != NULL) { + modbus.lint_memory[i] = *lint_memory[i]; + } + } + #endif + + // Read changes from clients + mbtask(); + + // Write changes back to OpenPLC Buffers + for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) { + if (bool_output[i/8][i%8] != NULL) { + *bool_output[i/8][i%8] = get_discrete(i, COILS); + } + } + for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) { + if (int_output[i] != NULL) { + *int_output[i] = modbus.holding[i]; + } + } + #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) + for (int i = 0; i < MAX_MEMORY_WORD; i++) { + if (int_memory[i] != NULL) { + *int_memory[i] = modbus.holding[i + MAX_ANALOG_OUTPUT]; + } + } + for (int i = 0; i < MAX_MEMORY_DWORD; i++) { + if (dint_memory[i] != NULL) { + *dint_memory[i] = modbus.dint_memory[i]; + } + } + for (int i = 0; i < MAX_MEMORY_LWORD; i++) { + if (lint_memory[i] != NULL) { + *lint_memory[i] = modbus.lint_memory[i]; + } + } + #endif +} +#endif + +// ============================================================================= +// PLC CYCLE TASK +// ============================================================================= +void plcCycleTask() { + updateInputBuffers(); + + // Run each program according to its task divisor + for (size_t i = 0; i < total_programs; ++i) { + if (task_divisors[i] == 0 || (__tick % task_divisors[i]) == 0) { + all_programs[i]->run(); + } + } + __tick++; + + updateOutputBuffers(); + updateTime(); +} + +// ============================================================================= +// SCHEDULER +// ============================================================================= +void scheduler() { + plcCycleTask(); + + #ifdef USE_ARDUINO_SKETCH + sketch_loop(); + #endif + + #ifdef MODBUS_ENABLED + modbusTask(); + #endif + + if (!first_cycle) { + first_cycle = true; + // Recalculate last_run to avoid time drift on the first cycle + last_run = micros() - scan_cycle; + } +} + +// ============================================================================= +// MAIN LOOP +// ============================================================================= +void loop() { + if ((micros() - last_run) >= scan_cycle) { + scheduler(); + last_run += scan_cycle; + } + + #ifdef MODBUS_ENABLED + // Only run Modbus task again if we have at least 10ms gap until the next cycle + if ((micros() - last_run) >= 10000) { + modbusTask(); + } + #endif + + #ifdef SIMULATOR_MODE + __asm volatile("sleep"); + #endif +} diff --git a/resources/sources/arduino/openplc.h b/resources/sources/arduino/openplc.h index 1c8bc4972..b82032b52 100644 --- a/resources/sources/arduino/openplc.h +++ b/resources/sources/arduino/openplc.h @@ -63,30 +63,9 @@ extern IEC_ULINT *lint_memory[MAX_MEMORY_LWORD]; #endif -//MatIEC Compiler -void config_run__(unsigned long tick); -void config_init__(void); - -//Common task timer -extern unsigned long long common_ticktime__; -#define DELAY_TIME 20 - -//glueVars.c -void updateTime(); -void glueVars(); - -//OpenPLC Buffers -//Booleans - -//extern IEC_BOOL buffer_bool_input[MAX_DIGITAL_INPUT/8][8]; -//extern IEC_BOOL buffer_bool_output[MAX_DIGITAL_OUTPUT/8][8]; -//extern IEC_UINT buffer_int_input[MAX_ANALOG_INPUT]; -//extern IEC_UINT buffer_int_output[MAX_ANALOG_OUTPUT]; - //Hardware Layer void hardwareInit(); void updateInputBuffers(); void updateOutputBuffers(); -void setupCycleDelay(unsigned long long cycle_time); -void cycleDelay(); + #endif diff --git a/resources/sources/boards/hals.json b/resources/sources/boards/hals.json index f905da3b8..5da092200 100644 --- a/resources/sources/boards/hals.json +++ b/resources/sources/boards/hals.json @@ -2,8 +2,15 @@ "OpenPLC Simulator": { "compiler": "simulator", "core": "arduino:avr", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "ld_flags": ["-Wl,--defsym,__DATA_REGION_LENGTH__=0xFE00", "-Wl,--defsym,__stack=0x80FFFF"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "ld_flags": [ + "-Wl,--defsym,__DATA_REGION_LENGTH__=0xFE00", + "-Wl,--defsym,__stack=0x80FFFF" + ], "default_ain": "A0, A1, A2, A3, A4, A5, A6, A7", "default_aout": "2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13", "default_din": "62, 63, 64, 65, 66, 67, 68, 69, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 42, 44, 46, 48, 50, 52", @@ -22,7 +29,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Due (native USB port)": { "compiler": "arduino-cli", @@ -44,7 +54,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Due (programming port)": { "compiler": "arduino-cli", @@ -66,7 +79,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Edge Control": { "compiler": "arduino-cli", @@ -88,7 +104,10 @@ "WiFi": "Yes - requires Arduino MKR board", "Bluetooth": "Yes", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Giga": { "compiler": "arduino-cli", @@ -111,7 +130,10 @@ "WiFi": "Yes", "Bluetooth": "Yes", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Leonardo": { "compiler": "arduino-cli", @@ -133,7 +155,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Mega": { "compiler": "arduino-cli", @@ -155,7 +180,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Micro": { "compiler": "arduino-cli", @@ -177,7 +205,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Nano": { "compiler": "arduino-cli", @@ -199,7 +230,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Nano ESP32": { "compiler": "arduino-cli", @@ -208,7 +242,9 @@ "default_aout": "9, 10, 11", "default_din": "2, 3, 4, 5, 6", "default_dout": "7, 8, 12, 13", - "define": ["BOARD_PORTENTA"], + "define": [ + "BOARD_PORTENTA" + ], "platform": "esp32:esp32:nano_nora", "preview": "generic.png", "source": "esp32.cpp", @@ -222,7 +258,10 @@ "WiFi": "Yes", "Bluetooth": "Yes", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Opta": { "compiler": "arduino-cli", @@ -245,7 +284,10 @@ "WiFi": "Yes - on the Opta WiFi model", "Bluetooth": "Yes - on the Opta WiFi model", "Ethernet": "Yes" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Uno": { "compiler": "arduino-cli", @@ -267,7 +309,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Uno R4": { "compiler": "arduino-cli", @@ -289,7 +334,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Uno R4 WiFi": { "compiler": "arduino-cli", @@ -312,7 +360,10 @@ "WiFi": "Yes", "Bluetooth": "Yes", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Uno Q": { "compiler": "arduino-cli", @@ -334,7 +385,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Zero (native USB port)": { "compiler": "arduino-cli", @@ -356,7 +410,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Arduino Zero (programming port)": { "compiler": "arduino-cli", @@ -378,7 +435,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Blackpill STM32-F411CE (DFU STM32 Bootloader)": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", @@ -389,7 +449,11 @@ "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9", "default_dout": "PB10, PB12, PB13, PB14, PB15, PC13, PC14, PC15", "define": "BOARD_STM32_F411CE", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "extra_libraries": [], "platform": "STMicroelectronics:stm32:GenF4:pnum=BLACKPILL_F411CE,upload_method=dfuMethod,usb=CDCgen", "preview": "generic.png", @@ -404,7 +468,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Blackpill STM32-F411CE (HID Bootloader 2.2)": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", @@ -415,7 +482,11 @@ "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9", "default_dout": "PB10, PB12, PB13, PB14, PB15, PC13, PC14, PC15", "define": "BOARD_STM32_F411CE", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "extra_libraries": [], "platform": "STMicroelectronics:stm32:GenF4:pnum=BLACKPILL_F411CE,upload_method=hidMethod,usb=CDCgen", "preview": "generic.png", @@ -430,7 +501,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Blackpill STM32-F411CE (SWD Programmer)": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", @@ -441,7 +515,11 @@ "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9", "default_dout": "PB10, PB12, PB13, PB14, PB15, PC13, PC14, PC15", "define": "BOARD_STM32_F411CE", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "extra_libraries": [], "platform": "STMicroelectronics:stm32:GenF4:pnum=BLACKPILL_F411CE,upload_method=swdMethod,usb=CDCgen", "preview": "generic.png", @@ -456,7 +534,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Blackpill STM32-F411CE (Serial Programmer)": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", @@ -467,7 +548,11 @@ "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9", "default_dout": "PB10, PB12, PB13, PB14, PB15, PC13, PC14, PC15", "define": "BOARD_STM32_F411CE", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "extra_libraries": [], "platform": "STMicroelectronics:stm32:GenF4:pnum=BLACKPILL_F411CE,upload_method=serialMethod,usb=CDCgen", "preview": "generic.png", @@ -482,7 +567,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Bluepill STM32-F103CB (DFU STM32 Bootloader)": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", @@ -493,7 +581,11 @@ "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9, PB10", "default_dout": "PB11, PB12, PB13, PB14, PB15, PC13, PC14, PC15", "define": "BOARD_STM32_F103CB", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "extra_libraries": [], "platform": "STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8,upload_method=dfuMethod,usb=CDCgen", "preview": "generic.png", @@ -508,7 +600,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Bluepill STM32-F103CB (HID Bootloader 2.2)": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", @@ -519,7 +614,11 @@ "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9, PB10", "default_dout": "PB11, PB12, PB13, PB14, PB15, PC13, PC14, PC15", "define": "BOARD_STM32_F103CB", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "extra_libraries": [], "platform": "STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8,upload_method=hidMethod,usb=CDCgen", "preview": "generic.png", @@ -534,7 +633,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Bluepill STM32-F103CB (SWD Programmer)": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", @@ -545,7 +647,11 @@ "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9, PB10", "default_dout": "PB11, PB12, PB13, PB14, PB15, PC13, PC14, PC15", "define": "BOARD_STM32_F103CB", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "extra_libraries": [], "platform": "STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8,upload_method=swdMethod,usb=CDCgen", "preview": "generic.png", @@ -560,7 +666,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Bluepill STM32-F103CB (Serial Programmer)": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", @@ -571,7 +680,11 @@ "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9, PB10", "default_dout": "PB11, PB12, PB13, PB14, PB15, PC13, PC14, PC15", "define": "BOARD_STM32_F103CB", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "extra_libraries": [], "platform": "STMicroelectronics:stm32:GenF1:pnum=BLUEPILL_F103C8,upload_method=serialMethod,usb=CDCgen", "preview": "generic.png", @@ -586,7 +699,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "CONTROLLINO MAXI": { "board_manager_url": "https://raw.githubusercontent.com/CONTROLLINO-PLC/CONTROLLINO_Library/master/Boards/package_ControllinoHardware_index.json", @@ -610,7 +726,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "Yes" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "CONTROLLINO MAXI Automation": { "board_manager_url": "https://raw.githubusercontent.com/CONTROLLINO-PLC/CONTROLLINO_Library/master/Boards/package_ControllinoHardware_index.json", @@ -634,7 +753,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "Yes" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "CONTROLLINO MEGA": { "board_manager_url": "https://raw.githubusercontent.com/CONTROLLINO-PLC/CONTROLLINO_Library/master/Boards/package_ControllinoHardware_index.json", @@ -658,7 +780,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "Yes" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "CONTROLLINO MICRO": { "board_manager_url": "https://github.com/CONTROLLINO-PLC/controllino_rp2/releases/download/global/package_controllino_rp2_index.json", @@ -682,7 +807,10 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "Yes" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "CONTROLLINO MINI": { "board_manager_url": "https://raw.githubusercontent.com/CONTROLLINO-PLC/CONTROLLINO_Library/master/Boards/package_ControllinoHardware_index.json", @@ -706,14 +834,25 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "ESP32 Generic": { "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "34, 35, 36, 39", "default_aout": "25, 26", "default_din": "17, 18, 19, 21, 22, 23, 27, 32, 33", @@ -739,8 +878,16 @@ "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "34, 35, 36, 39", "default_aout": "25, 26", "default_din": "17, 18, 19, 21, 22, 23, 27, 32, 33", @@ -766,8 +913,16 @@ "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "34, 35, 36, 39", "default_aout": "25, 26", "default_din": "18, 19, 21, 22, 23, 27, 32, 33", @@ -793,8 +948,16 @@ "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "34, 35, 36, 39", "default_aout": "25, 26", "default_din": "17, 18, 19, 21, 22, 23, 27, 32, 33", @@ -820,8 +983,16 @@ "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "0, 1, 2, 3", "default_aout": "18, 19, 20, 21", "default_din": "4, 5, 10, 11", @@ -847,8 +1018,16 @@ "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "34, 35, 36, 39", "default_aout": "25, 26", "default_din": "17, 18, 19, 21, 22, 23, 27, 32, 33", @@ -874,8 +1053,16 @@ "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "34, 35, 36, 39", "default_aout": "25, 26", "default_din": "17, 18, 19, 21, 22, 23, 27, 32, 33", @@ -901,8 +1088,16 @@ "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "1, 2, 3, 4", "default_aout": "36, 37", "default_din": "6, 7, 8, 9", @@ -928,7 +1123,11 @@ "board_manager_url": "https://arduino.esp8266.com/stable/package_esp8266com_index.json", "compiler": "arduino-cli", "core": "esp8266:esp8266", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A0", "default_aout": "D8", "default_din": "D4, D5, D6, D7", @@ -948,13 +1147,20 @@ "WiFi": "Yes", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "ESP8266 NodeMCU": { "board_manager_url": "https://arduino.esp8266.com/stable/package_esp8266com_index.json", "compiler": "arduino-cli", "core": "esp8266:esp8266", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A0", "default_aout": "D8", "default_din": "D4, D5, D6, D7", @@ -974,13 +1180,20 @@ "WiFi": "Yes", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "FX3U-14M / LE3U-14M": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", "compiler": "arduino-cli", "core": "STMicroelectronics:stm32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A0, A1, A2, A3", "default_aout": "2, 3, 4, 5", "default_din": "A4, A5, A6, A7, A8, A9, 18, 19", @@ -999,13 +1212,20 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "WS3U-14Mx": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", "compiler": "arduino-cli", "core": "STMicroelectronics:stm32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "PA1, PA3, PC4, PC5, PC0, PC1", "default_aout": "PA4, PA5", "default_din": "PB13, PB14, PB11, PB12, PE15, PB10, PE13, PE14", @@ -1024,13 +1244,20 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "FX3U-24MR / DollaTek": { "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", "compiler": "arduino-cli", "core": "STMicroelectronics:stm32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "PA1, PA3, PC4, PC5, PC0, PC1", "default_aout": "PA4, PA5", "default_din": "PB13, PB14, PB11, PB12, PE15, PB10, PE13, PE14, PE11, PE12, PE9, PE10, PE7, PE8", @@ -1053,13 +1280,20 @@ "user_ain": "PA1, PA3, PC4, PC5, PC0, PC1", "user_aout": "PA4, PA5", "user_din": "PB13, PB14, PB11, PB12, PE15, PB10, PE13, PE14, PE11, PE12, PE9, PE10, PE7, PE8", - "user_dout": "PC9, PC8, PA8, PA0, PB3, PD12, PB15, PA7, PA6, PA2" + "user_dout": "PC9, PC8, PA8, PA0, PB3, PD12, PB15, PA7, PA6, PA2", + "cxx_flags": [ + "-std=gnu++17" + ] }, "Iruino VEA": { "board_manager_url": "https://raw.githubusercontent.com/VEA-SRL/IRUINO_Library/main/package_vea_index.json", "compiler": "arduino-cli", "core": "iruino:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A0, A1", "default_aout": "", "default_din": "I0, I1, I2, I3, I4,I5, I6, I7", @@ -1079,12 +1313,19 @@ "WiFi": "Yes", "Bluetooth": "Yes", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Mkr WiFi": { "compiler": "arduino-cli", "core": "arduino:samd", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A1, A2, A3, A4, A5, A6", "default_aout": "6, 15", "default_din": "0, 1, 2, 3, 4, 5", @@ -1103,12 +1344,19 @@ "WiFi": "Yes", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Mkr Zero": { "compiler": "arduino-cli", "core": "arduino:samd", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A1, A2, A3, A4, A5, A6", "default_aout": "6, 15", "default_din": "0, 1, 2, 3, 4, 5", @@ -1126,12 +1374,19 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Nano 33 BLE": { "compiler": "arduino-cli", "core": "arduino:mbed_nano", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "15, 16, 17, 18, 19, 20, 21", "default_aout": "9, 14", "default_din": "2, 3, 4, 5, 6", @@ -1149,12 +1404,19 @@ "WiFi": "No", "Bluetooth": "Yes", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Nano 33 IoT": { "core": "arduino:samd", "compiler": "arduino-cli", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "15, 16, 17, 18, 19, 20, 21", "default_aout": "9, 14", "default_din": "2, 3, 4, 5, 6", @@ -1173,12 +1435,19 @@ "WiFi": "Yes", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Nano Every": { "compiler": "arduino-cli", "core": "arduino:megaavr", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "15, 16, 17, 18, 19, 20, 21", "default_aout": "9, 14", "default_din": "2, 3, 4, 5, 6", @@ -1196,12 +1465,19 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Nano RP2040 Connect": { "compiler": "arduino-cli", "core": "arduino:mbed_nano", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A1, A2, A3", "default_aout": "14", "default_din": "2, 3, 4, 5, 6, 7", @@ -1220,20 +1496,33 @@ "WiFi": "Yes", "Bluetooth": "Yes", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "OpenPLC Runtime v4": { "compiler": "openplc-compiler", - "preview": "generic.png" + "preview": "generic.png", + "cxx_flags": [ + "-std=gnu++17" + ] }, "OpenPLC Runtime v3": { "compiler": "openplc-compiler", - "preview": "generic.png" + "preview": "generic.png", + "cxx_flags": [ + "-std=gnu++17" + ] }, "P1AM-100": { "compiler": "arduino-cli", "core": "arduino:samd", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A1, A2, A5, A6", "default_aout": "A0", "default_din": "31, 0, 1, 2, 3, 4", @@ -1251,13 +1540,20 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "Yes with Ethernet module" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "P1AM-200": { "board_manager_url": "https://raw.githubusercontent.com/facts-engineering/facts-engineering.github.io/master/package_productivity-P1AM-boardmanagermodule_index.json", "compiler": "arduino-cli", "core": "FACTS:samd", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "A1, A2, A5, A6", "default_aout": "A0", "default_din": "31, 0, 1, 2, 3, 4", @@ -1276,12 +1572,19 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "Yes with Ethernet module" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Portenta Machine Control H7": { "compiler": "arduino-cli", "core": "arduino:mbed_portenta", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "0, 1, 2", "default_aout": "0, 1, 2, 3", "default_din": "DIN_READ_CH_PIN_00, DIN_READ_CH_PIN_01, DIN_READ_CH_PIN_02, DIN_READ_CH_PIN_03, DIN_READ_CH_PIN_04, DIN_READ_CH_PIN_05, DIN_READ_CH_PIN_06, DIN_READ_CH_PIN_07", @@ -1300,17 +1603,27 @@ "WiFi": "Yes", "Bluetooth": "Yes", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Raspberry Pi": { "compiler": "openplc-compiler", - "preview": "raspberry-pi.png" + "preview": "raspberry-pi.png", + "cxx_flags": [ + "-std=gnu++17" + ] }, "Raspberry Pico": { "board_manager_url": "https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json", "compiler": "arduino-cli", "core": "rp2040:rp2040", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "26, 27, 28", "default_aout": "4,5", "default_din": "6, 7, 8, 9, 10, 11, 12, 13", @@ -1329,13 +1642,20 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Raspberry Pico 2": { "board_manager_url": "https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json", "compiler": "arduino-cli", "core": "rp2040:rp2040", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "26, 27, 28", "default_aout": "4,5", "default_din": "6, 7, 8, 9, 10, 11, 12, 13", @@ -1354,14 +1674,21 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Raspberry Pico 2 (RISCV)": { "arch": "riscv", "board_manager_url": "https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json", "compiler": "arduino-cli", "core": "rp2040:rp2040", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "26, 27, 28", "default_aout": "4,5", "default_din": "6, 7, 8, 9, 10, 11, 12, 13", @@ -1380,13 +1707,20 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "Raspberry Pico W": { "board_manager_url": "https://github.com/earlephilhower/arduino-pico/releases/download/global/package_rp2040_index.json", "compiler": "arduino-cli", "core": "rp2040:rp2040", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "26, 27, 28", "default_aout": "4,5", "default_din": "6, 7, 8, 9, 10, 11, 12, 13", @@ -1406,14 +1740,25 @@ "WiFi": "Yes", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] }, "SEQUENT-ESP32-PI": { "board_manager_url": "https://espressif.github.io/arduino-esp32/package_esp32_index.json", "compiler": "arduino-cli", "core": "esp32:esp32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], - "cxx_flags": ["-MMD", "-c"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], + "cxx_flags": [ + "-std=gnu++17", + "-MMD", + "-c" + ], "default_ain": "34, 35", "default_aout": "25", "default_din": "27, 32", @@ -1439,7 +1784,11 @@ "board_manager_url": "https://github.com/stm32duino/BoardManagerFiles/raw/main/package_stmicroelectronics_index.json", "compiler": "arduino-cli", "core": "STMicroelectronics:stm32", - "c_flags": ["-MMD", "-c", "-Wno-incompatible-pointer-types"], + "c_flags": [ + "-MMD", + "-c", + "-Wno-incompatible-pointer-types" + ], "default_ain": "PA0, PA1, PA4, PA5, PA6, PA7", "default_aout": "PB0, PB1", "default_din": "PA8, PA11, PA12, PB3, PB4, PB5, PB8, PB9", @@ -1459,6 +1808,9 @@ "WiFi": "No", "Bluetooth": "No", "Ethernet": "No" - } + }, + "cxx_flags": [ + "-std=gnu++17" + ] } } From 2305825b2d617d7674df160a8a89d2e3242ea2ef Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 23:02:41 -0400 Subject: [PATCH 023/296] chore: bump strucpp to v0.2.5 (AVR compatibility fix) v0.2.5 adds iec_platform.hpp shim so runtime headers use instead of on AVR targets where C++ standard library wrappers are not available. Co-Authored-By: Claude Opus 4.6 (1M context) --- binary-versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binary-versions.json b/binary-versions.json index cde2bc220..1a9359b42 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -4,7 +4,7 @@ "repository": "Autonomy-Logic/xml2st" }, "strucpp": { - "version": "v0.2.4", + "version": "v0.2.5", "repository": "Autonomy-Logic/STruCpp" } } From 3ed6597321423dc53077a79b2ecac339596647e1 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 23:34:44 -0400 Subject: [PATCH 024/296] feat: add avr-libstdcpp for C++ stdlib on AVR targets AVR GCC doesn't ship C++ standard library headers (, , , etc.) that STruC++ runtime headers require. Bundle avr-libstdcpp (GPLv3, header-only, from modm-io/avr-libstdcpp) and add -isystem include path for AVR boards during compilation. STruC++ runtime headers stay standard-compliant -- the AVR compatibility is handled entirely at the editor build pipeline level. Also bump strucpp to v0.2.6 (reverted AVR-specific changes from runtime). Co-Authored-By: Claude Opus 4.6 (1M context) --- binary-versions.json | 2 +- .../.github/workflows/compile_examples.yml | 34 + resources/sources/avr-libstdcpp/.gitignore | 2 + resources/sources/avr-libstdcpp/COPYING.MPLv2 | 373 ++ resources/sources/avr-libstdcpp/COPYING3 | 674 ++ resources/sources/avr-libstdcpp/README.md | 359 + .../sources/avr-libstdcpp/include/algorithm | 67 + resources/sources/avr-libstdcpp/include/any | 626 ++ resources/sources/avr-libstdcpp/include/array | 451 ++ .../sources/avr-libstdcpp/include/atomic | 1552 +++++ .../include/backward/backward_warning.h | 56 + .../avr-libstdcpp/include/backward/binders.h | 182 + .../avr-libstdcpp/include/backward/hash_fun.h | 170 + .../avr-libstdcpp/include/backward/hash_map | 599 ++ .../avr-libstdcpp/include/backward/hash_set | 569 ++ .../include/backward/hashtable.h | 1166 ++++ resources/sources/avr-libstdcpp/include/bit | 371 ++ .../avr-libstdcpp/include/bits/algorithmfwd.h | 963 +++ .../avr-libstdcpp/include/bits/alloc_traits.h | 743 +++ .../include/bits/allocated_ptr.h | 104 + .../avr-libstdcpp/include/bits/allocator.h | 323 + .../avr-libstdcpp/include/bits/atomic_base.h | 1724 +++++ .../include/bits/atomic_lockfree_defines.h | 66 + .../include/bits/boost_concept_check.h | 794 +++ .../include/bits/c++0x_warning.h | 37 + .../avr-libstdcpp/include/bits/c++allocator.h | 59 + .../avr-libstdcpp/include/bits/c++config.h | 2074 ++++++ .../avr-libstdcpp/include/bits/char_traits.h | 943 +++ .../avr-libstdcpp/include/bits/charconv.h | 106 + .../include/bits/concept_check.h | 81 + .../include/bits/cpp_type_traits.h | 551 ++ .../include/bits/cxxabi_forced.h | 60 + .../include/bits/cxxabi_init_exception.h | 80 + .../avr-libstdcpp/include/bits/deque.tcc | 1216 ++++ .../include/bits/enable_special_members.h | 312 + .../avr-libstdcpp/include/bits/erase_if.h | 72 + .../include/bits/error_constants.h | 180 + .../include/bits/exception_defines.h | 47 + .../avr-libstdcpp/include/bits/forward_list.h | 1514 +++++ .../include/bits/forward_list.tcc | 517 ++ .../avr-libstdcpp/include/bits/functexcept.h | 114 + .../include/bits/functional_hash.h | 280 + .../avr-libstdcpp/include/bits/gslice.h | 185 + .../avr-libstdcpp/include/bits/gslice_array.h | 223 + .../avr-libstdcpp/include/bits/hash_bytes.h | 59 + .../avr-libstdcpp/include/bits/hashtable.h | 2228 +++++++ .../include/bits/hashtable_policy.h | 2107 ++++++ .../include/bits/indirect_array.h | 212 + .../avr-libstdcpp/include/bits/invoke.h | 163 + .../include/bits/iterator_concepts.h | 911 +++ .../avr-libstdcpp/include/bits/list.tcc | 633 ++ .../avr-libstdcpp/include/bits/mask_array.h | 213 + .../avr-libstdcpp/include/bits/memoryfwd.h | 82 + .../sources/avr-libstdcpp/include/bits/move.h | 224 + .../avr-libstdcpp/include/bits/node_handle.h | 299 + .../include/bits/parse_numbers.h | 294 + .../avr-libstdcpp/include/bits/postypes.h | 253 + .../include/bits/predefined_ops.h | 405 ++ .../avr-libstdcpp/include/bits/ptr_traits.h | 211 + .../avr-libstdcpp/include/bits/random.h | 5183 +++++++++++++++ .../avr-libstdcpp/include/bits/random.tcc | 2193 ++++++ .../avr-libstdcpp/include/bits/range_access.h | 1148 ++++ .../avr-libstdcpp/include/bits/range_cmp.h | 195 + .../avr-libstdcpp/include/bits/ranges_algo.h | 3792 +++++++++++ .../include/bits/ranges_algobase.h | 597 ++ .../include/bits/ranges_uninitialized.h | 574 ++ .../avr-libstdcpp/include/bits/refwrap.h | 401 ++ .../avr-libstdcpp/include/bits/slice_array.h | 284 + .../avr-libstdcpp/include/bits/std_abs.h | 111 + .../avr-libstdcpp/include/bits/std_function.h | 728 ++ .../avr-libstdcpp/include/bits/std_mutex.h | 176 + .../avr-libstdcpp/include/bits/stl_algo.h | 5884 +++++++++++++++++ .../avr-libstdcpp/include/bits/stl_algobase.h | 1959 ++++++ .../avr-libstdcpp/include/bits/stl_bvector.h | 1363 ++++ .../include/bits/stl_construct.h | 256 + .../avr-libstdcpp/include/bits/stl_deque.h | 2330 +++++++ .../avr-libstdcpp/include/bits/stl_function.h | 1395 ++++ .../avr-libstdcpp/include/bits/stl_heap.h | 583 ++ .../avr-libstdcpp/include/bits/stl_iterator.h | 2238 +++++++ .../include/bits/stl_iterator_base_funcs.h | 239 + .../include/bits/stl_iterator_base_types.h | 271 + .../avr-libstdcpp/include/bits/stl_list.h | 2127 ++++++ .../avr-libstdcpp/include/bits/stl_map.h | 1568 +++++ .../avr-libstdcpp/include/bits/stl_multimap.h | 1233 ++++ .../avr-libstdcpp/include/bits/stl_multiset.h | 1075 +++ .../avr-libstdcpp/include/bits/stl_numeric.h | 413 ++ .../avr-libstdcpp/include/bits/stl_pair.h | 586 ++ .../avr-libstdcpp/include/bits/stl_queue.h | 753 +++ .../include/bits/stl_raw_storage_iter.h | 123 + .../avr-libstdcpp/include/bits/stl_relops.h | 133 + .../avr-libstdcpp/include/bits/stl_set.h | 1086 +++ .../avr-libstdcpp/include/bits/stl_stack.h | 392 ++ .../avr-libstdcpp/include/bits/stl_tempbuf.h | 284 + .../avr-libstdcpp/include/bits/stl_tree.h | 2644 ++++++++ .../include/bits/stl_uninitialized.h | 1041 +++ .../avr-libstdcpp/include/bits/stl_vector.h | 1985 ++++++ .../include/bits/string_view.tcc | 229 + .../include/bits/uniform_int_dist.h | 395 ++ .../avr-libstdcpp/include/bits/unique_lock.h | 243 + .../avr-libstdcpp/include/bits/unique_ptr.h | 995 +++ .../include/bits/unordered_map.h | 2171 ++++++ .../include/bits/unordered_set.h | 1783 +++++ .../include/bits/uses_allocator.h | 195 + .../include/bits/valarray_after.h | 556 ++ .../include/bits/valarray_array.h | 677 ++ .../include/bits/valarray_array.tcc | 244 + .../include/bits/valarray_before.h | 758 +++ .../avr-libstdcpp/include/bits/vector.tcc | 1008 +++ .../sources/avr-libstdcpp/include/bitset | 1245 ++++ .../sources/avr-libstdcpp/include/cassert | 44 + .../sources/avr-libstdcpp/include/ccomplex | 42 + .../sources/avr-libstdcpp/include/cctype | 94 + .../sources/avr-libstdcpp/include/cerrno | 52 + resources/sources/avr-libstdcpp/include/cfenv | 84 + .../sources/avr-libstdcpp/include/cfloat | 56 + .../sources/avr-libstdcpp/include/chrono | 1131 ++++ .../sources/avr-libstdcpp/include/cinttypes | 55 + .../sources/avr-libstdcpp/include/ciso646 | 38 + .../sources/avr-libstdcpp/include/climits | 59 + resources/sources/avr-libstdcpp/include/cmath | 1924 ++++++ .../sources/avr-libstdcpp/include/compare | 919 +++ .../sources/avr-libstdcpp/include/complex | 1931 ++++++ .../sources/avr-libstdcpp/include/concepts | 367 + .../sources/avr-libstdcpp/include/coroutine | 303 + .../sources/avr-libstdcpp/include/csetjmp | 61 + .../sources/avr-libstdcpp/include/csignal | 57 + .../sources/avr-libstdcpp/include/cstdalign | 44 + .../sources/avr-libstdcpp/include/cstdarg | 58 + .../sources/avr-libstdcpp/include/cstdbool | 44 + .../sources/avr-libstdcpp/include/cstddef | 181 + .../sources/avr-libstdcpp/include/cstdint | 91 + .../sources/avr-libstdcpp/include/cstdio | 192 + .../sources/avr-libstdcpp/include/cstdlib | 201 + .../sources/avr-libstdcpp/include/cstring | 126 + .../sources/avr-libstdcpp/include/ctgmath | 44 + resources/sources/avr-libstdcpp/include/ctime | 84 + .../sources/avr-libstdcpp/include/cuchar | 77 + .../sources/avr-libstdcpp/include/cwchar | 306 + .../sources/avr-libstdcpp/include/cwctype | 110 + .../avr-libstdcpp/include/debug/assertions.h | 68 + .../avr-libstdcpp/include/debug/debug.h | 137 + .../avr-libstdcpp/include/debug/formatter.h | 593 ++ .../avr-libstdcpp/include/debug/functions.h | 470 ++ .../include/debug/helper_functions.h | 315 + .../avr-libstdcpp/include/debug/macros.h | 471 ++ .../avr-libstdcpp/include/decimal/decimal | 494 ++ .../avr-libstdcpp/include/decimal/decimal.h | 469 ++ resources/sources/avr-libstdcpp/include/deque | 119 + .../avr-libstdcpp/include/ext/algorithm | 596 ++ .../include/ext/aligned_buffer.h | 125 + .../avr-libstdcpp/include/ext/alloc_traits.h | 171 + .../avr-libstdcpp/include/ext/atomicity.h | 116 + .../sources/avr-libstdcpp/include/ext/cmath | 152 + .../avr-libstdcpp/include/ext/functional | 422 ++ .../avr-libstdcpp/include/ext/hash_map | 599 ++ .../avr-libstdcpp/include/ext/hash_set | 569 ++ .../avr-libstdcpp/include/ext/iterator | 116 + .../include/ext/malloc_allocator.h | 199 + .../sources/avr-libstdcpp/include/ext/memory | 200 + .../avr-libstdcpp/include/ext/new_allocator.h | 198 + .../sources/avr-libstdcpp/include/ext/numeric | 152 + .../include/ext/numeric_traits.h | 148 + .../include/ext/pod_char_traits.h | 198 + .../sources/avr-libstdcpp/include/ext/rb_tree | 93 + .../sources/avr-libstdcpp/include/ext/slist | 1082 +++ .../avr-libstdcpp/include/ext/type_traits.h | 221 + .../avr-libstdcpp/include/ext/typelist.h | 538 ++ .../avr-libstdcpp/include/forward_list | 87 + .../sources/avr-libstdcpp/include/functional | 1280 ++++ .../avr-libstdcpp/include/initializer_list | 109 + .../sources/avr-libstdcpp/include/iterator | 70 + .../sources/avr-libstdcpp/include/limits | 1893 ++++++ resources/sources/avr-libstdcpp/include/list | 109 + resources/sources/avr-libstdcpp/include/map | 109 + .../sources/avr-libstdcpp/include/memory | 404 ++ resources/sources/avr-libstdcpp/include/mutex | 746 +++ resources/sources/avr-libstdcpp/include/new | 193 + .../sources/avr-libstdcpp/include/numbers | 208 + .../sources/avr-libstdcpp/include/numeric | 699 ++ .../sources/avr-libstdcpp/include/optional | 1238 ++++ resources/sources/avr-libstdcpp/include/queue | 66 + .../sources/avr-libstdcpp/include/random | 54 + .../sources/avr-libstdcpp/include/ranges | 3561 ++++++++++ resources/sources/avr-libstdcpp/include/ratio | 576 ++ .../avr-libstdcpp/include/scoped_allocator | 519 ++ resources/sources/avr-libstdcpp/include/set | 105 + .../avr-libstdcpp/include/shared_mutex | 855 +++ resources/sources/avr-libstdcpp/include/span | 462 ++ resources/sources/avr-libstdcpp/include/stack | 63 + .../sources/avr-libstdcpp/include/string_view | 758 +++ resources/sources/avr-libstdcpp/include/tuple | 1764 +++++ .../sources/avr-libstdcpp/include/type_traits | 3774 +++++++++++ .../avr-libstdcpp/include/unordered_map | 101 + .../avr-libstdcpp/include/unordered_set | 100 + .../sources/avr-libstdcpp/include/utility | 538 ++ .../sources/avr-libstdcpp/include/valarray | 1253 ++++ .../sources/avr-libstdcpp/include/variant | 1775 +++++ .../sources/avr-libstdcpp/include/vector | 129 + .../sources/avr-libstdcpp/include/version | 231 + .../editor/compiler/compiler-module.ts | 9 +- 200 files changed, 128399 insertions(+), 2 deletions(-) create mode 100644 resources/sources/avr-libstdcpp/.github/workflows/compile_examples.yml create mode 100644 resources/sources/avr-libstdcpp/.gitignore create mode 100644 resources/sources/avr-libstdcpp/COPYING.MPLv2 create mode 100644 resources/sources/avr-libstdcpp/COPYING3 create mode 100644 resources/sources/avr-libstdcpp/README.md create mode 100644 resources/sources/avr-libstdcpp/include/algorithm create mode 100644 resources/sources/avr-libstdcpp/include/any create mode 100644 resources/sources/avr-libstdcpp/include/array create mode 100644 resources/sources/avr-libstdcpp/include/atomic create mode 100644 resources/sources/avr-libstdcpp/include/backward/backward_warning.h create mode 100644 resources/sources/avr-libstdcpp/include/backward/binders.h create mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_fun.h create mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_map create mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_set create mode 100644 resources/sources/avr-libstdcpp/include/backward/hashtable.h create mode 100644 resources/sources/avr-libstdcpp/include/bit create mode 100644 resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/alloc_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/atomic_base.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/c++allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/c++config.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/char_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/charconv.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/concept_check.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/deque.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/enable_special_members.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/erase_if.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/error_constants.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/exception_defines.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/forward_list.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/forward_list.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/functexcept.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/functional_hash.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/gslice.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/gslice_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/hash_bytes.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/hashtable.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/indirect_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/invoke.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/list.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/mask_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/memoryfwd.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/move.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/node_handle.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/parse_numbers.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/postypes.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/predefined_ops.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/ptr_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/random.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/random.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/range_access.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/range_cmp.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_algo.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/refwrap.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/slice_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/std_abs.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/std_function.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/std_mutex.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_algo.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_algobase.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_bvector.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_construct.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_deque.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_function.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_heap.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_list.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_map.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_multimap.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_multiset.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_numeric.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_pair.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_queue.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_relops.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_set.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_stack.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_tree.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_vector.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/string_view.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/unique_lock.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/unique_ptr.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/unordered_map.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/unordered_set.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/uses_allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_after.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_before.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/vector.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bitset create mode 100644 resources/sources/avr-libstdcpp/include/cassert create mode 100644 resources/sources/avr-libstdcpp/include/ccomplex create mode 100644 resources/sources/avr-libstdcpp/include/cctype create mode 100644 resources/sources/avr-libstdcpp/include/cerrno create mode 100644 resources/sources/avr-libstdcpp/include/cfenv create mode 100644 resources/sources/avr-libstdcpp/include/cfloat create mode 100644 resources/sources/avr-libstdcpp/include/chrono create mode 100644 resources/sources/avr-libstdcpp/include/cinttypes create mode 100644 resources/sources/avr-libstdcpp/include/ciso646 create mode 100644 resources/sources/avr-libstdcpp/include/climits create mode 100644 resources/sources/avr-libstdcpp/include/cmath create mode 100644 resources/sources/avr-libstdcpp/include/compare create mode 100644 resources/sources/avr-libstdcpp/include/complex create mode 100644 resources/sources/avr-libstdcpp/include/concepts create mode 100644 resources/sources/avr-libstdcpp/include/coroutine create mode 100644 resources/sources/avr-libstdcpp/include/csetjmp create mode 100644 resources/sources/avr-libstdcpp/include/csignal create mode 100644 resources/sources/avr-libstdcpp/include/cstdalign create mode 100644 resources/sources/avr-libstdcpp/include/cstdarg create mode 100644 resources/sources/avr-libstdcpp/include/cstdbool create mode 100644 resources/sources/avr-libstdcpp/include/cstddef create mode 100644 resources/sources/avr-libstdcpp/include/cstdint create mode 100644 resources/sources/avr-libstdcpp/include/cstdio create mode 100644 resources/sources/avr-libstdcpp/include/cstdlib create mode 100644 resources/sources/avr-libstdcpp/include/cstring create mode 100644 resources/sources/avr-libstdcpp/include/ctgmath create mode 100644 resources/sources/avr-libstdcpp/include/ctime create mode 100644 resources/sources/avr-libstdcpp/include/cuchar create mode 100644 resources/sources/avr-libstdcpp/include/cwchar create mode 100644 resources/sources/avr-libstdcpp/include/cwctype create mode 100644 resources/sources/avr-libstdcpp/include/debug/assertions.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/debug.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/formatter.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/functions.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/helper_functions.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/macros.h create mode 100644 resources/sources/avr-libstdcpp/include/decimal/decimal create mode 100644 resources/sources/avr-libstdcpp/include/decimal/decimal.h create mode 100644 resources/sources/avr-libstdcpp/include/deque create mode 100644 resources/sources/avr-libstdcpp/include/ext/algorithm create mode 100644 resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/alloc_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/atomicity.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/cmath create mode 100644 resources/sources/avr-libstdcpp/include/ext/functional create mode 100644 resources/sources/avr-libstdcpp/include/ext/hash_map create mode 100644 resources/sources/avr-libstdcpp/include/ext/hash_set create mode 100644 resources/sources/avr-libstdcpp/include/ext/iterator create mode 100644 resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/memory create mode 100644 resources/sources/avr-libstdcpp/include/ext/new_allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/numeric create mode 100644 resources/sources/avr-libstdcpp/include/ext/numeric_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/rb_tree create mode 100644 resources/sources/avr-libstdcpp/include/ext/slist create mode 100644 resources/sources/avr-libstdcpp/include/ext/type_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/typelist.h create mode 100644 resources/sources/avr-libstdcpp/include/forward_list create mode 100644 resources/sources/avr-libstdcpp/include/functional create mode 100644 resources/sources/avr-libstdcpp/include/initializer_list create mode 100644 resources/sources/avr-libstdcpp/include/iterator create mode 100644 resources/sources/avr-libstdcpp/include/limits create mode 100644 resources/sources/avr-libstdcpp/include/list create mode 100644 resources/sources/avr-libstdcpp/include/map create mode 100644 resources/sources/avr-libstdcpp/include/memory create mode 100644 resources/sources/avr-libstdcpp/include/mutex create mode 100644 resources/sources/avr-libstdcpp/include/new create mode 100644 resources/sources/avr-libstdcpp/include/numbers create mode 100644 resources/sources/avr-libstdcpp/include/numeric create mode 100644 resources/sources/avr-libstdcpp/include/optional create mode 100644 resources/sources/avr-libstdcpp/include/queue create mode 100644 resources/sources/avr-libstdcpp/include/random create mode 100644 resources/sources/avr-libstdcpp/include/ranges create mode 100644 resources/sources/avr-libstdcpp/include/ratio create mode 100644 resources/sources/avr-libstdcpp/include/scoped_allocator create mode 100644 resources/sources/avr-libstdcpp/include/set create mode 100644 resources/sources/avr-libstdcpp/include/shared_mutex create mode 100644 resources/sources/avr-libstdcpp/include/span create mode 100644 resources/sources/avr-libstdcpp/include/stack create mode 100644 resources/sources/avr-libstdcpp/include/string_view create mode 100644 resources/sources/avr-libstdcpp/include/tuple create mode 100644 resources/sources/avr-libstdcpp/include/type_traits create mode 100644 resources/sources/avr-libstdcpp/include/unordered_map create mode 100644 resources/sources/avr-libstdcpp/include/unordered_set create mode 100644 resources/sources/avr-libstdcpp/include/utility create mode 100644 resources/sources/avr-libstdcpp/include/valarray create mode 100644 resources/sources/avr-libstdcpp/include/variant create mode 100644 resources/sources/avr-libstdcpp/include/vector create mode 100644 resources/sources/avr-libstdcpp/include/version diff --git a/binary-versions.json b/binary-versions.json index 1a9359b42..0e1292f63 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -4,7 +4,7 @@ "repository": "Autonomy-Logic/xml2st" }, "strucpp": { - "version": "v0.2.5", + "version": "v0.2.6", "repository": "Autonomy-Logic/STruCpp" } } diff --git a/resources/sources/avr-libstdcpp/.github/workflows/compile_examples.yml b/resources/sources/avr-libstdcpp/.github/workflows/compile_examples.yml new file mode 100644 index 000000000..0dc094c14 --- /dev/null +++ b/resources/sources/avr-libstdcpp/.github/workflows/compile_examples.yml @@ -0,0 +1,34 @@ +name: Compile Examples + +on: + push: + branches: + - '**' + pull_request: + +jobs: + unittests-linux-generic: + runs-on: ubuntu-latest + container: + image: ghcr.io/modm-ext/modm-build-avr:latest + + strategy: + fail-fast: false + matrix: + standard: [ c++17, c++20 ] + + steps: + - name: Check out repository + uses: actions/checkout@v4 + + - name: Check environment + run: | + env + which avr-g++ + avr-g++ --version + + - name: Compile Examples + run: | + for example in $(find examples/ | grep Makefile); do + (cd $(dirname $example) && make -j4 STD=${{ matrix.standard }}) + done diff --git a/resources/sources/avr-libstdcpp/.gitignore b/resources/sources/avr-libstdcpp/.gitignore new file mode 100644 index 000000000..886e04000 --- /dev/null +++ b/resources/sources/avr-libstdcpp/.gitignore @@ -0,0 +1,2 @@ +examples/**/build + diff --git a/resources/sources/avr-libstdcpp/COPYING.MPLv2 b/resources/sources/avr-libstdcpp/COPYING.MPLv2 new file mode 100644 index 000000000..d0a1fa148 --- /dev/null +++ b/resources/sources/avr-libstdcpp/COPYING.MPLv2 @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/resources/sources/avr-libstdcpp/COPYING3 b/resources/sources/avr-libstdcpp/COPYING3 new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/COPYING3 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/resources/sources/avr-libstdcpp/README.md b/resources/sources/avr-libstdcpp/README.md new file mode 100644 index 000000000..0fff5319b --- /dev/null +++ b/resources/sources/avr-libstdcpp/README.md @@ -0,0 +1,359 @@ +# avr-libstdcpp: libstdc++ port for avr-gcc +[![Build Status](https://github.com/modm-io/avr-libstdcpp/actions/workflows/compile_examples.yml/badge.svg)](https://github.com/modm-io/avr-libstdcpp/actions) +================== + +`avr-libstdcpp` is a partial, non-fully-tested +implementation of the C++ standard library and its STL. +It is intended to be used with `avr-gcc`. + +Many features of modern C++11,14,17 and 20 are supported. + +`avr-gcc` does not have a complete C++ standard library nor does it include an STL implementation. +The `avr-libstdcpp` port (even though not-fully-tested +and only partially full/complete) will, nonetheless, +be useful for those interested in making more comprehensive utilization +of C++, including its standard library, with a modern `avr-gcc` compiler. + +## Historical origins + +The `avr-libstdcpp` library traces its own origins to existing +GNU/GCC C++ standard library implementation(s), themselves targeting +embedded systems. This work is essentially an even-more +_embedded_-_friendly_ adaptation of the aforementioned work. + +The `avr-libstdcpp` port began in 2018 with an initial import +of a GNU/GCC-based C++ standard library from GCC 8. +A second import of a GNU/GCC-based C++ standard library from GCC 10 +in 2020 modernized the port to include many contemporary C++20 features. + +## Using the library + +- Add the `avr-libstdcpp/include` path to the standard `-isystem` (or `-I`) include path(s) of the compiler on the command line. +- Upon doing this, include standard library headers in the usual way (i.e., `#include `, `#include `, `#include `, etc.). +- There are also several source files located in the [src directory](./src). Some of these may potentially be needed. +- For instance, when doing floating-point mathematical calculations with the `` library, the file [`math.cc`](./src/math.cc) located [here](./src) needs to be added as a normal source file to your project. + + +For straightforward header-only use, for example, +simply add the `-isystem` (or alternatively the `-I`) include path +to your particular location of `avr-libstdcpp/include` on the command line... + +```sh +avr-g++ -O2 -x c++ -isystem /my_path/avr-libstdcpp/include -mmcu=atmega328p test.cpp -o test.elf +``` + +... and seamlessly use standard library headers in your code. + +```cpp +#include +#include + +std::array a { 1, 2, 3 }; + +int main() +{ + // 6 + auto sum = std::accumulate(a.cbegin(), a.cend(), 0); + + static_cast(sum); +} +``` + +Additional straightforward code samples exercising standard library usage +can be found in the [examples](./examples) folder. + +## Using the library with MICROCHIP's ATMEL Studio + +`avr-libstdcpp` can be successfully used with MICROCHIP's ATMEL Studio. +The include path of the headers needs to be added to the project settings in the normal way. +Add also any of the necessary source files, as described in the section above. + +This is an advanced use of `avr-libstdcpp` in combination with MICROCHIP's ATMEL Studio +because the underlying GCC compiler used with ATMEL Studio also needs to be +upgraded to a much more modern one than the `avr-gcc` 5 +delivered in the standard installation of this studio. + +An [informative thread](https://github.com/modm-io/avr-libstdcpp/issues/17#issuecomment-1098241768) +provides a few more details on how to use `avr-libstdcpp` with MICROCHIP's ATMEL Studio. + +## Guidance for tiny bare-metal systems + +### Very helpful go-to libraries + +In general the C++ standard library is intended +to be written and implemented in a resource-sensitive +fashion. This includes efforts to save on both +memory as well as run-time. +In fact, C++ standard library functions and algorithms +have, in general, been specifically written and tuned by +the library authors with efficiency aspects in mind. +In particular, library components compile reliably and quickly +and also lend themselves well to compiler optimization. + +Some library components, however, are particularly well-suited +for bare-metal microcontroller programming. +These can be exceptionally helpful when used properly and sensibly +in tiny bare-metal microcontroller environments. + +A subjective list of these the libraries/headers +and their main uses includes, but is not limited to,: + +- `` for containers having known, fixed size. +- `` for standard algorithms such as sorting, minimax, sequential operations, etc. +- `` for projects requiring floating-point mathematical functions such as `std::sin()`, `std::exp()`, `std::frexp()` and many more. For some mathematical uses, it might be necessary to include [`math.cc`](./src/math.cc) in your project. This source file is located [here](./src). +- `` which defines integral types having specified widths residing within `namespace std` like `std::uint8_t`. +- `` offering compile-time query of numeric limits of built-in types. +- `` featuring a collection of useful numeric algorithms such as `std::accumulate()`, etc. +- `` for compile-time decisions based on types. + +With these libraries alone, the entire project can benefit +from a great deal of the standard library's power without compromising +in any way on performance or sleek memory footprint. +This is because these libaries are typically lean, fast and require no additional storage. + +The following non-trivial, real-world example, for instance, +wraps instances of an overly-simplified LED class abstraction +as object-references in an `std::array`. +Once stored, the application exercises the LED's toggle +function in an algorithmic loop with `toggle()`-method call +expressed via lambda function. + +```cpp +#include +#include +#include + +class led +{ +public: + led() = default; + + auto toggle() -> void { } +}; + +led led0; +led led1; +led led2; + +using led_ref_type = std::reference_wrapper; + +std::array led_refs = +{ + led0, + led1, + led2 +}; + +int main() +{ + for(;;) + { + std::for_each(led_refs.begin(), + led_refs.end(), + [](led& lr) { lr.toggle(); }); + } +} +``` + +This nifty little example is terse, expressive and powerful. +It makes use of parts of ``, `` and `` +to greatly simplify the programming within a non-trivial +microcontroller situation. + +This example is key because it combines the domains +of object-oriented programming with the templated +algorithms and wrappers of the STL to assist +in our microcontroller world. + +### Libraries requiring more design considerations + +Some C++ library and STL artifacts, however, +require more careful design considerations +regarding memory allocation and management. + +Consider, for instance, `std::vector` from the `` library. +Vector creates a flexibly-sized array-like collection +of items of any kind, depending on the template parameter. + +For instance: + +```cpp +#include + +// A vector of 3 integers. +std::vector v { 1, 2, 3 }; +``` + +See also the [main.cpp](./examples/vector/main.cpp) file +in the [./examples/vector](./examples/vector) directory. + +This vector requires storage for three integers which, +on the `avr-gcc` platform is 6 bytes. The storage is managed +through vector's _second_, less well-known template parameter. +In other words, + +```cpp +namespace std { + +// Forward declaration of the vector template class. +template> +class vector; + +} +``` + +Using containers requires memory allocation with a so-called allocator. +If none is specified, as in our code snippet, the default allocator +from namespace `std` for the templated type `T` of the vector is +automatically selected. + +Good embeddable self-written custom allocators are essential for +using such containers so that memory could be managed with +a self-written memory pool, an off-chip memory device, etc. +A common selection is a pool of static memory creating a so-called +_ring_ _allocator_. This is an intermetiate/advanced topic +which will refine STL use _on_ _the_ _metal_ and +also allow for flexible template use in these resource-sensitive +realms. + +## Notable adaptions and limitations + +Some parts of the C++ standard library are not well suited for +tiny bare-metal systems. These include some memory-intensive +and/or hardware-intensive library artifacts. + +`avr-libstdcpp` has the following known adaptions and limitations. + +- **I/O streaming and RTTI:** I/O streaming and run-time type information (RTTI) are known +to be resource-intensive and could be disruptive on tiny +embedded platforms. An effort has been made to essentially +remove both these library dependencies and their +associated codes. + +- **exceptions:** Exceptions are also difficult to efficiently +implement on tiny embedded platforms and this library port avoids using exceptions. +The headers `` and ``, their dependencies, +and their directly relevant code sequences have been removed. +Simple mechanisms such as those found in `` +and ``, however, remain mostly available. + +- **``:** The `` library is being handled +specifically in the draft of +[avr-libstdcpp/pull/36](https://github.com/modm-io/avr-libstdcpp/pull/36). + +- **``:** There is no source of entropy whatsoever on these platforms +in their standard configuration. So `std::random_device` +has been removed. + +- **Hashing:** Hashing has been optimized for tiny architectures and uses a rudimentary 16-bit CRC algorithm. + +- **``:** Only certain judiciously selected clock functions from the `` library are implemented. +These include `std::chrono::high_resolution_clock` and `std::chrono::steady_clock`. When using +these clocks, it is required to implement the clock's static method +`now()` in a project-specific fashion. This is because +the library's authors can not in a generic way implement any +microcontroller-specific clock(s) since this requires detailed knowledge +of the underlying microcontroller peripherie. + +- **`int`, `size_t`, `ptrdiff_t` and the like:** Data types such as +`int`, and `size_t` and `ptrdiff_t` (which are aliased to +`unsigned`/`signed` versions of `int`) +are generally limited to 16-bits in width +on tiny `avr-gcc` platforms. Although this is a compiler attribute, +it has strong influence on the library (particularly the STL) +implementation because these data types are used copiously therein. +This compiler attribute limits ranges, indexes, etc. to 16-bits. +With the compiler switch `-mint8`, the built-in type `int` +is only 8 bits wide and extreme range limitations +are expected to make STL use tricky. + +- **``:** In `avr-gcc` 10 and higher, the built-in data types +`double` and `long double` can be either 32 or 64 bits in width. +The widths depend on the compiler command line options `-mdouble=32` +(alternatively `-mdouble=64`) and/or `-mlong-double=32` +(alternatively `-mlong-double=64`). Standard floating-point +`` functions such as `std::sin()`, `std::cos()`, +`std::exp()` and the like will, therefore, have input and output +widths according to these command line options. + +## C++20 `constexpr` support + +The following is a rather advanced, highly useful topic. +When using C++20, `constexpr` construction, assignment and evaluation +of various algorithms can and often will be generally +compile-time constant (i.e, via consistent use of C++20 `constexpr`-ness). + +As a result of this, STL algorithms that use compile-time constant inputs are, in fact, +evaluated at compile time in C++20. This lets us perform a strong, +purposeful shift of algorithmic complexity _to_-_the_-_left_. +In other words, we shift algorithmic complexity _into_ the compile-time +stage of code development and _away from_ the precious RAM-ROM-space/cycles +of the compiled running code. + +In the following code, for instance, we revisit the `std::array`/`` +example from above. The variation below exhibits complete compile-time +evaluation of the algorithmic result. + +To take the deep dive in this topic, follow all the useful compile-time +preprocessor symbols such as +`__cpp_lib_constexpr_algorithms`, `__cpp_lib_constexpr_numeric`, and many more +in [feature testing](https://en.cppreference.com/w/cpp/feature_test). + +```cpp +#include +#include + +#if (defined(__cpp_lib_constexpr_numeric) && (__cpp_lib_constexpr_numeric>=201911L)) +#define MODM_CONSTEXPR constexpr +#define MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR 1 +#else +#define MODM_CONSTEXPR +#define MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR 0 +#endif + +MODM_CONSTEXPR std::array a { 1, 2, 3 }; + +int main() +{ + // 6 + auto MODM_CONSTEXPR sum = std::accumulate(a.cbegin(), a.cend(), 0); + + #if (MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR == 1) + static_assert(sum == 6, "Error: Unexpected std::accumulate result!"); + #endif + + return (sum == 6 ? 0 : -1); +} +``` + +See also the [numeric.cpp](./examples/numeric/numeric.cpp) file +in the [/examples/numeric](./examples/numeric) directory. + +## Additional details + +`avr-libstdcpp` is intended for a modern `avr-gcc` +such as the port available in the [modm-io project](https://github.com/modm-io/avr-gcc) +repository. Tests show usability for `avr-gcc` 7 through 15. + +This library has been checked for compatibility on `avr-gcc` +with language standards C++11,14,17,20,23 and 2c. + +Using the port way back to `avr-gcc` 5 does not work +at the moment with today's form of the checked-in library, +and `avr-gcc` 7 or higher is required. +This is because the very old compiler lexical parsers are not capable +of properly handling some of the library's template code. +See also [avr-libstdcpp/issues/15](https://github.com/modm-io/avr-libstdcpp/issues/15) +which is closed and includes justification for its closure. + +## Licensing + +The library source files in [`src/`](./src/) +and the library include files in [`include/` and its subfolders](./include/) +(with two exceptions for the sources, as mentioned below) +are licensed under [GNU General Public License Version 3](./COPYING3) or higher. + +All of the [example codes](./examples/) and also two library source files +(namely `functexcept.cc` and `math.cc` in [`src/`](./src/)) +are subject to the terms of the [Mozilla Public License Version 2.0](./COPYING.MPLv2). diff --git a/resources/sources/avr-libstdcpp/include/algorithm b/resources/sources/avr-libstdcpp/include/algorithm new file mode 100644 index 000000000..8000e3218 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/algorithm @@ -0,0 +1,67 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/algorithm + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ALGORITHM +#define _GLIBCXX_ALGORITHM 1 + +#pragma GCC system_header + +#include // UK-300. +#include +#include +#if __cplusplus > 201703L +# include +#endif + +#endif /* _GLIBCXX_ALGORITHM */ diff --git a/resources/sources/avr-libstdcpp/include/any b/resources/sources/avr-libstdcpp/include/any new file mode 100644 index 000000000..39fc77082 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/any @@ -0,0 +1,626 @@ +// -*- C++ -*- + +// Copyright (C) 2014-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/any + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ANY +#define _GLIBCXX_ANY 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#if __cpp_rtti +#include +#else +namespace std +{ + class type_info; +} +#endif // __cpp_rtti + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + +#define __cpp_lib_any 201606L + + /** + * @brief A type-safe container of any type. + * + * An @c any object's state is either empty or it stores a contained object + * of CopyConstructible type. + */ + class any + { + // Holds either pointer to a heap object or the contained object itself. + union _Storage + { + constexpr _Storage() : _M_ptr{nullptr} {} + + // Prevent trivial copies of this type, buffer might hold a non-POD. + _Storage(const _Storage&) = delete; + _Storage& operator=(const _Storage&) = delete; + + void* _M_ptr; + aligned_storage::type _M_buffer; + }; + + template, + bool _Fits = (sizeof(_Tp) <= sizeof(_Storage)) + && (alignof(_Tp) <= alignof(_Storage))> + using _Internal = std::integral_constant; + + template + struct _Manager_internal; // uses small-object optimization + + template + struct _Manager_external; // creates contained object on the heap + + template + using _Manager = conditional_t<_Internal<_Tp>::value, + _Manager_internal<_Tp>, + _Manager_external<_Tp>>; + + template> + using _Decay_if_not_any = enable_if_t, _VTp>; + + /// Emplace with an object created from @p __args as the contained object. + template > + void __do_emplace(_Args&&... __args) + { + reset(); + _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); + _M_manager = &_Mgr::_S_manage; + } + + /// Emplace with an object created from @p __il and @p __args as + /// the contained object. + template > + void __do_emplace(initializer_list<_Up> __il, _Args&&... __args) + { + reset(); + _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); + _M_manager = &_Mgr::_S_manage; + } + + template + using __any_constructible + = enable_if<__and_, + is_constructible<_Tp, _Args...>>::value, + _Res>; + + template + using __any_constructible_t + = typename __any_constructible::type; + + template + using __emplace_t + = typename __any_constructible<_VTp&, _VTp, _Args...>::type; + + public: + // construct/destruct + + /// Default constructor, creates an empty object. + constexpr any() noexcept : _M_manager(nullptr) { } + + /// Copy constructor, copies the state of @p __other + any(const any& __other) + { + if (!__other.has_value()) + _M_manager = nullptr; + else + { + _Arg __arg; + __arg._M_any = this; + __other._M_manager(_Op_clone, &__other, &__arg); + } + } + + /** + * @brief Move constructor, transfer the state from @p __other + * + * @post @c !__other.has_value() (this postcondition is a GNU extension) + */ + any(any&& __other) noexcept + { + if (!__other.has_value()) + _M_manager = nullptr; + else + { + _Arg __arg; + __arg._M_any = this; + __other._M_manager(_Op_xfer, &__other, &__arg); + } + } + + /// Construct with a copy of @p __value as the contained object. + template , + typename _Mgr = _Manager<_VTp>, + enable_if_t::value + && !__is_in_place_type<_VTp>::value, bool> = true> + any(_Tp&& __value) + : _M_manager(&_Mgr::_S_manage) + { + _Mgr::_S_create(_M_storage, std::forward<_Tp>(__value)); + } + + /// Construct with an object created from @p __args as the contained object. + template , + typename _Mgr = _Manager<_VTp>, + __any_constructible_t<_VTp, _Args&&...> = false> + explicit + any(in_place_type_t<_Tp>, _Args&&... __args) + : _M_manager(&_Mgr::_S_manage) + { + _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); + } + + /// Construct with an object created from @p __il and @p __args as + /// the contained object. + template , typename _Mgr = _Manager<_VTp>, + __any_constructible_t<_VTp, initializer_list<_Up>, + _Args&&...> = false> + explicit + any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) + : _M_manager(&_Mgr::_S_manage) + { + _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); + } + + /// Destructor, calls @c reset() + ~any() { reset(); } + + // assignments + + /// Copy the state of another object. + any& + operator=(const any& __rhs) + { + *this = any(__rhs); + return *this; + } + + /** + * @brief Move assignment operator + * + * @post @c !__rhs.has_value() (not guaranteed for other implementations) + */ + any& + operator=(any&& __rhs) noexcept + { + if (!__rhs.has_value()) + reset(); + else if (this != &__rhs) + { + reset(); + _Arg __arg; + __arg._M_any = this; + __rhs._M_manager(_Op_xfer, &__rhs, &__arg); + } + return *this; + } + + /// Store a copy of @p __rhs as the contained object. + template + enable_if_t>::value, any&> + operator=(_Tp&& __rhs) + { + *this = any(std::forward<_Tp>(__rhs)); + return *this; + } + + /// Emplace with an object created from @p __args as the contained object. + template + __emplace_t, _Args...> + emplace(_Args&&... __args) + { + using _VTp = decay_t<_Tp>; + __do_emplace<_VTp>(std::forward<_Args>(__args)...); + any::_Arg __arg; + this->_M_manager(any::_Op_access, this, &__arg); + return *static_cast<_VTp*>(__arg._M_obj); + } + + /// Emplace with an object created from @p __il and @p __args as + /// the contained object. + template + __emplace_t, initializer_list<_Up>, _Args&&...> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + using _VTp = decay_t<_Tp>; + __do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...); + any::_Arg __arg; + this->_M_manager(any::_Op_access, this, &__arg); + return *static_cast<_VTp*>(__arg._M_obj); + } + + // modifiers + + /// If not empty, destroy the contained object. + void reset() noexcept + { + if (has_value()) + { + _M_manager(_Op_destroy, this, nullptr); + _M_manager = nullptr; + } + } + + /// Exchange state with another object. + void swap(any& __rhs) noexcept + { + if (!has_value() && !__rhs.has_value()) + return; + + if (has_value() && __rhs.has_value()) + { + if (this == &__rhs) + return; + + any __tmp; + _Arg __arg; + __arg._M_any = &__tmp; + __rhs._M_manager(_Op_xfer, &__rhs, &__arg); + __arg._M_any = &__rhs; + _M_manager(_Op_xfer, this, &__arg); + __arg._M_any = this; + __tmp._M_manager(_Op_xfer, &__tmp, &__arg); + } + else + { + any* __empty = !has_value() ? this : &__rhs; + any* __full = !has_value() ? &__rhs : this; + _Arg __arg; + __arg._M_any = __empty; + __full->_M_manager(_Op_xfer, __full, &__arg); + } + } + + // observers + + /// Reports whether there is a contained object or not. + bool has_value() const noexcept { return _M_manager != nullptr; } + +#if __cpp_rtti + /// The @c typeid of the contained object, or @c typeid(void) if empty. + const type_info& type() const noexcept + { + if (!has_value()) + return typeid(void); + _Arg __arg; + _M_manager(_Op_get_type_info, this, &__arg); + return *__arg._M_typeinfo; + } +#endif + + template + static constexpr bool __is_valid_cast() + { return __or_, is_copy_constructible<_Tp>>::value; } + + private: + enum _Op { + _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer + }; + + union _Arg + { + void* _M_obj; + const std::type_info* _M_typeinfo; + any* _M_any; + }; + + void (*_M_manager)(_Op, const any*, _Arg*); + _Storage _M_storage; + + template + friend void* __any_caster(const any* __any); + + // Manage in-place contained object. + template + struct _Manager_internal + { + static void + _S_manage(_Op __which, const any* __anyp, _Arg* __arg); + + template + static void + _S_create(_Storage& __storage, _Up&& __value) + { + void* __addr = &__storage._M_buffer; + ::new (__addr) _Tp(std::forward<_Up>(__value)); + } + + template + static void + _S_create(_Storage& __storage, _Args&&... __args) + { + void* __addr = &__storage._M_buffer; + ::new (__addr) _Tp(std::forward<_Args>(__args)...); + } + }; + + // Manage external contained object. + template + struct _Manager_external + { + static void + _S_manage(_Op __which, const any* __anyp, _Arg* __arg); + + template + static void + _S_create(_Storage& __storage, _Up&& __value) + { + __storage._M_ptr = new _Tp(std::forward<_Up>(__value)); + } + template + static void + _S_create(_Storage& __storage, _Args&&... __args) + { + __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...); + } + }; + }; + + /// Exchange the states of two @c any objects. + inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); } + + /// Create an any holding a @c _Tp constructed from @c __args. + template + any make_any(_Args&&... __args) + { + return any(in_place_type<_Tp>, std::forward<_Args>(__args)...); + } + + /// Create an any holding a @c _Tp constructed from @c __il and @c __args. + template + any make_any(initializer_list<_Up> __il, _Args&&... __args) + { + return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...); + } + + /** + * @brief Access the contained object. + * + * @tparam _ValueType A const-reference or CopyConstructible type. + * @param __any The object to access. + * @return The contained object. + * @throw bad_any_cast If + * __any.type() != typeid(remove_reference_t<_ValueType>) + * + */ + template + inline _ValueType any_cast(const any& __any) + { + using _Up = __remove_cvref_t<_ValueType>; + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + static_assert(is_constructible_v<_ValueType, const _Up&>, + "Template argument must be constructible from a const value."); + auto __p = any_cast<_Up>(&__any); + if (__p) + return static_cast<_ValueType>(*__p); + __throw_bad_any_cast(); + } + + /** + * @brief Access the contained object. + * + * @tparam _ValueType A reference or CopyConstructible type. + * @param __any The object to access. + * @return The contained object. + * @throw bad_any_cast If + * __any.type() != typeid(remove_reference_t<_ValueType>) + * + * + * @{ + */ + template + inline _ValueType any_cast(any& __any) + { + using _Up = __remove_cvref_t<_ValueType>; + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + static_assert(is_constructible_v<_ValueType, _Up&>, + "Template argument must be constructible from an lvalue."); + auto __p = any_cast<_Up>(&__any); + if (__p) + return static_cast<_ValueType>(*__p); + __throw_bad_any_cast(); + } + + template + inline _ValueType any_cast(any&& __any) + { + using _Up = __remove_cvref_t<_ValueType>; + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + static_assert(is_constructible_v<_ValueType, _Up>, + "Template argument must be constructible from an rvalue."); + auto __p = any_cast<_Up>(&__any); + if (__p) + return static_cast<_ValueType>(std::move(*__p)); + __throw_bad_any_cast(); + } + // @} + + /// @cond undocumented + template + void* __any_caster(const any* __any) + { + // any_cast returns non-null if __any->type() == typeid(T) and + // typeid(T) ignores cv-qualifiers so remove them: + using _Up = remove_cv_t<_Tp>; + // The contained value has a decayed type, so if decay_t is not U, + // then it's not possible to have a contained value of type U: + if constexpr (!is_same_v, _Up>) + return nullptr; + // Only copy constructible types can be used for contained values: + else if constexpr (!is_copy_constructible_v<_Up>) + return nullptr; + // First try comparing function addresses, which works without RTTI + else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage +#if __cpp_rtti + || __any->type() == typeid(_Tp) +#endif + ) + { + any::_Arg __arg; + __any->_M_manager(any::_Op_access, __any, &__arg); + return __arg._M_obj; + } + return nullptr; + } + /// @endcond + + /** + * @brief Access the contained object. + * + * @tparam _ValueType The type of the contained object. + * @param __any A pointer to the object to access. + * @return The address of the contained object if + * __any != nullptr && __any.type() == typeid(_ValueType) + * , otherwise a null pointer. + * + * @{ + */ + template + inline const _ValueType* any_cast(const any* __any) noexcept + { + if constexpr (is_object_v<_ValueType>) + if (__any) + return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); + return nullptr; + } + + template + inline _ValueType* any_cast(any* __any) noexcept + { + if constexpr (is_object_v<_ValueType>) + if (__any) + return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); + return nullptr; + } + // @} + + template + void + any::_Manager_internal<_Tp>:: + _S_manage(_Op __which, const any* __any, _Arg* __arg) + { + // The contained object is in _M_storage._M_buffer + auto __ptr = reinterpret_cast(&__any->_M_storage._M_buffer); + switch (__which) + { + case _Op_access: + __arg->_M_obj = const_cast<_Tp*>(__ptr); + break; + case _Op_get_type_info: +#if __cpp_rtti + __arg->_M_typeinfo = &typeid(_Tp); +#endif + break; + case _Op_clone: + ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); + __arg->_M_any->_M_manager = __any->_M_manager; + break; + case _Op_destroy: + __ptr->~_Tp(); + break; + case _Op_xfer: + ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp + (std::move(*const_cast<_Tp*>(__ptr))); + __ptr->~_Tp(); + __arg->_M_any->_M_manager = __any->_M_manager; + const_cast(__any)->_M_manager = nullptr; + break; + } + } + + template + void + any::_Manager_external<_Tp>:: + _S_manage(_Op __which, const any* __any, _Arg* __arg) + { + // The contained object is *_M_storage._M_ptr + auto __ptr = static_cast(__any->_M_storage._M_ptr); + switch (__which) + { + case _Op_access: + __arg->_M_obj = const_cast<_Tp*>(__ptr); + break; + case _Op_get_type_info: +#if __cpp_rtti + __arg->_M_typeinfo = &typeid(_Tp); +#endif + break; + case _Op_clone: + __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr); + __arg->_M_any->_M_manager = __any->_M_manager; + break; + case _Op_destroy: + delete __ptr; + break; + case _Op_xfer: + __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr; + __arg->_M_any->_M_manager = __any->_M_manager; + const_cast(__any)->_M_manager = nullptr; + break; + } + } + + /// @} + + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing an + // any into a variant. + template<> + struct _Never_valueless_alt + : std::true_type + { }; + } // namespace __detail::__variant + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 +#endif // _GLIBCXX_ANY diff --git a/resources/sources/avr-libstdcpp/include/array b/resources/sources/avr-libstdcpp/include/array new file mode 100644 index 000000000..3bb6f48c4 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/array @@ -0,0 +1,451 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/array + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ARRAY +#define _GLIBCXX_ARRAY 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + struct __array_traits + { + typedef _Tp _Type[_Nm]; + typedef __is_swappable<_Tp> _Is_swappable; + typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable; + + static constexpr _Tp& + _S_ref(const _Type& __t, std::size_t __n) noexcept + { return const_cast<_Tp&>(__t[__n]); } + + static constexpr _Tp* + _S_ptr(const _Type& __t) noexcept + { return const_cast<_Tp*>(__t); } + }; + + template + struct __array_traits<_Tp, 0> + { + struct _Type { }; + typedef true_type _Is_swappable; + typedef true_type _Is_nothrow_swappable; + + static constexpr _Tp& + _S_ref(const _Type&, std::size_t) noexcept + { return *static_cast<_Tp*>(nullptr); } + + static constexpr _Tp* + _S_ptr(const _Type&) noexcept + { return nullptr; } + }; + + /** + * @brief A standard container for storing a fixed size sequence of elements. + * + * @ingroup sequences + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence. + * + * Sets support random access iterators. + * + * @tparam Tp Type of element. Required to be a complete type. + * @tparam Nm Number of elements. + */ + template + struct array + { + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + // Support for zero-sized arrays mandatory. + typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type; + typename _AT_Type::_Type _M_elems; + + // No explicit construct/copy/destroy for aggregate type. + + // DR 776. + _GLIBCXX20_CONSTEXPR void + fill(const value_type& __u) + { std::fill_n(begin(), size(), __u); } + + _GLIBCXX20_CONSTEXPR void + swap(array& __other) + noexcept(_AT_Type::_Is_nothrow_swappable::value) + { std::swap_ranges(begin(), end(), __other.begin()); } + + // Iterators. + _GLIBCXX17_CONSTEXPR iterator + begin() noexcept + { return iterator(data()); } + + _GLIBCXX17_CONSTEXPR const_iterator + begin() const noexcept + { return const_iterator(data()); } + + _GLIBCXX17_CONSTEXPR iterator + end() noexcept + { return iterator(data() + _Nm); } + + _GLIBCXX17_CONSTEXPR const_iterator + end() const noexcept + { return const_iterator(data() + _Nm); } + + _GLIBCXX17_CONSTEXPR reverse_iterator + rbegin() noexcept + { return reverse_iterator(end()); } + + _GLIBCXX17_CONSTEXPR const_reverse_iterator + rbegin() const noexcept + { return const_reverse_iterator(end()); } + + _GLIBCXX17_CONSTEXPR reverse_iterator + rend() noexcept + { return reverse_iterator(begin()); } + + _GLIBCXX17_CONSTEXPR const_reverse_iterator + rend() const noexcept + { return const_reverse_iterator(begin()); } + + _GLIBCXX17_CONSTEXPR const_iterator + cbegin() const noexcept + { return const_iterator(data()); } + + _GLIBCXX17_CONSTEXPR const_iterator + cend() const noexcept + { return const_iterator(data() + _Nm); } + + _GLIBCXX17_CONSTEXPR const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + _GLIBCXX17_CONSTEXPR const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } + + // Capacity. + constexpr size_type + size() const noexcept { return _Nm; } + + constexpr size_type + max_size() const noexcept { return _Nm; } + + _GLIBCXX_NODISCARD constexpr bool + empty() const noexcept { return size() == 0; } + + // Element access. + _GLIBCXX17_CONSTEXPR reference + operator[](size_type __n) noexcept + { return _AT_Type::_S_ref(_M_elems, __n); } + + constexpr const_reference + operator[](size_type __n) const noexcept + { return _AT_Type::_S_ref(_M_elems, __n); } + + _GLIBCXX17_CONSTEXPR reference + at(size_type __n) + { + if (__n >= _Nm) + std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " + ">= _Nm (which is %zu)"), + __n, _Nm); + return _AT_Type::_S_ref(_M_elems, __n); + } + + constexpr const_reference + at(size_type __n) const + { + // Result of conditional expression must be an lvalue so use + // boolean ? lvalue : (throw-expr, lvalue) + return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n) + : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " + ">= _Nm (which is %zu)"), + __n, _Nm), + _AT_Type::_S_ref(_M_elems, 0)); + } + + _GLIBCXX17_CONSTEXPR reference + front() noexcept + { return *begin(); } + + constexpr const_reference + front() const noexcept + { return _AT_Type::_S_ref(_M_elems, 0); } + + _GLIBCXX17_CONSTEXPR reference + back() noexcept + { return _Nm ? *(end() - 1) : *end(); } + + constexpr const_reference + back() const noexcept + { + return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) + : _AT_Type::_S_ref(_M_elems, 0); + } + + _GLIBCXX17_CONSTEXPR pointer + data() noexcept + { return _AT_Type::_S_ptr(_M_elems); } + + _GLIBCXX17_CONSTEXPR const_pointer + data() const noexcept + { return _AT_Type::_S_ptr(_M_elems); } + }; + +#if __cpp_deduction_guides >= 201606 + template + array(_Tp, _Up...) + -> array && ...), _Tp>, + 1 + sizeof...(_Up)>; +#endif + + // Array comparisons. + template + _GLIBCXX20_CONSTEXPR + inline bool + operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return std::equal(__one.begin(), __one.end(), __two.begin()); } + +#if __cpp_lib_three_way_comparison && __cpp_lib_concepts + template + constexpr __detail::__synth3way_t<_Tp> + operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) + { +#ifdef __cpp_lib_is_constant_evaluated + if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value) + if (!std::is_constant_evaluated()) + { + constexpr size_t __n = _Nm * sizeof(_Tp); + return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0; + } +#endif + + for (size_t __i = 0; __i < _Nm; ++__i) + { + auto __c = __detail::__synth3way(__a[__i], __b[__i]); + if (__c != 0) + return __c; + } + return strong_ordering::equal; + } +#else + template + _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one == __two); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) + { + return std::lexicographical_compare(__a.begin(), __a.end(), + __b.begin(), __b.end()); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return __two < __one; } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one > __two); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one < __two); } +#endif // three_way_comparison && concepts + + // Specialized algorithms. + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if< + _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value + >::type +#else + void +#endif + swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) + noexcept(noexcept(__one.swap(__two))) + { __one.swap(__two); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + typename enable_if< + !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type + swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete; +#endif + + template + constexpr _Tp& + get(array<_Tp, _Nm>& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: + _S_ref(__arr._M_elems, _Int); + } + + template + constexpr _Tp&& + get(array<_Tp, _Nm>&& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); + } + + template + constexpr const _Tp& + get(const array<_Tp, _Nm>& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: + _S_ref(__arr._M_elems, _Int); + } + + template + constexpr const _Tp&& + get(const array<_Tp, _Nm>&& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); + } + +#if __cplusplus > 201703L +#define __cpp_lib_to_array 201907L + + template + constexpr array, sizeof...(_Idx)> + __to_array(_Tp (&__a)[sizeof...(_Idx)], index_sequence<_Idx...>) + { + if constexpr (_Move) + return {{std::move(__a[_Idx])...}}; + else + return {{__a[_Idx]...}}; + } + + template + constexpr array, _Nm> + to_array(_Tp (&__a)[_Nm]) + noexcept(is_nothrow_constructible_v<_Tp, _Tp&>) + { + static_assert(!is_array_v<_Tp>); + static_assert(is_constructible_v<_Tp, _Tp&>); + if constexpr (is_constructible_v<_Tp, _Tp&>) + return _GLIBCXX_STD_C::__to_array(__a, make_index_sequence<_Nm>{}); + __builtin_unreachable(); // FIXME: see PR c++/91388 + } + + template + constexpr array, _Nm> + to_array(_Tp (&&__a)[_Nm]) + noexcept(is_nothrow_move_constructible_v<_Tp>) + { + static_assert(!is_array_v<_Tp>); + static_assert(is_move_constructible_v<_Tp>); + if constexpr (is_move_constructible_v<_Tp>) + return _GLIBCXX_STD_C::__to_array<1>(__a, make_index_sequence<_Nm>{}); + __builtin_unreachable(); // FIXME: see PR c++/91388 + } +#endif // C++20 + +_GLIBCXX_END_NAMESPACE_CONTAINER +} // namespace std + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Tuple interface to class template array. + + /// tuple_size + template + struct tuple_size; + + /// Partial specialization for std::array + template + struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>> + : public integral_constant { }; + + /// tuple_element + template + struct tuple_element; + + /// Partial specialization for std::array + template + struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>> + { + static_assert(_Int < _Nm, "index is out of bounds"); + typedef _Tp type; + }; + + template + struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#endif // C++11 + +#endif // _GLIBCXX_ARRAY diff --git a/resources/sources/avr-libstdcpp/include/atomic b/resources/sources/avr-libstdcpp/include/atomic new file mode 100644 index 000000000..a455286a7 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/atomic @@ -0,0 +1,1552 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/atomic + * This is a Standard C++ Library header. + */ + +// Based on "C++ Atomic Types and Operations" by Hans Boehm and Lawrence Crowl. +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html + +#ifndef _GLIBCXX_ATOMIC +#define _GLIBCXX_ATOMIC 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup atomics + * @{ + */ + +#if __cplusplus >= 201703L +# define __cpp_lib_atomic_is_always_lock_free 201603 +#endif + + template + struct atomic; + + /// atomic + // NB: No operators or fetch-operations for this type. + template<> + struct atomic + { + using value_type = bool; + + private: + __atomic_base _M_base; + + public: + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(bool __i) noexcept : _M_base(__i) { } + + bool + operator=(bool __i) noexcept + { return _M_base.operator=(__i); } + + bool + operator=(bool __i) volatile noexcept + { return _M_base.operator=(__i); } + + operator bool() const noexcept + { return _M_base.load(); } + + operator bool() const volatile noexcept + { return _M_base.load(); } + + bool + is_lock_free() const noexcept { return _M_base.is_lock_free(); } + + bool + is_lock_free() const volatile noexcept { return _M_base.is_lock_free(); } + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2; +#endif + + void + store(bool __i, memory_order __m = memory_order_seq_cst) noexcept + { _M_base.store(__i, __m); } + + void + store(bool __i, memory_order __m = memory_order_seq_cst) volatile noexcept + { _M_base.store(__i, __m); } + + bool + load(memory_order __m = memory_order_seq_cst) const noexcept + { return _M_base.load(__m); } + + bool + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return _M_base.load(__m); } + + bool + exchange(bool __i, memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.exchange(__i, __m); } + + bool + exchange(bool __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.exchange(__i, __m); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m); } + }; + +#if __cplusplus <= 201703L +# define _GLIBCXX20_INIT(I) +#else +# define _GLIBCXX20_INIT(I) = I +#endif + + /** + * @brief Generic atomic type, primary class template. + * + * @tparam _Tp Type to be made atomic, must be trivially copyable. + */ + template + struct atomic + { + using value_type = _Tp; + + private: + // Align 1/2/4/8/16-byte types to at least their size. + static constexpr int _S_min_alignment + = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 + ? 0 : sizeof(_Tp); + + static constexpr int _S_alignment + = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); + + alignas(_S_alignment) _Tp _M_i _GLIBCXX20_INIT(_Tp()); + + static_assert(__is_trivially_copyable(_Tp), + "std::atomic requires a trivially copyable type"); + + static_assert(sizeof(_Tp) > 0, + "Incomplete or zero-sized types are not supported"); + + public: + atomic() = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(_Tp __i) noexcept : _M_i(__i) { } + + operator _Tp() const noexcept + { return load(); } + + operator _Tp() const volatile noexcept + { return load(); } + + _Tp + operator=(_Tp __i) noexcept + { store(__i); return __i; } + + _Tp + operator=(_Tp __i) volatile noexcept + { store(__i); return __i; } + + bool + is_lock_free() const noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + bool + is_lock_free() const volatile noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_M_i), 0); +#endif + + void + store(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept + { __atomic_store(std::__addressof(_M_i), std::__addressof(__i), int(__m)); } + + void + store(_Tp __i, memory_order __m = memory_order_seq_cst) volatile noexcept + { __atomic_store(std::__addressof(_M_i), std::__addressof(__i), int(__m)); } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); + return *__ptr; + } + + _Tp + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); + return *__ptr; + } + + _Tp + exchange(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_exchange(std::__addressof(_M_i), std::__addressof(__i), + __ptr, int(__m)); + return *__ptr; + } + + _Tp + exchange(_Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_exchange(std::__addressof(_M_i), std::__addressof(__i), + __ptr, int(__m)); + return *__ptr; + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) noexcept + { + return __atomic_compare_exchange(std::__addressof(_M_i), + std::__addressof(__e), + std::__addressof(__i), + true, int(__s), int(__f)); + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) volatile noexcept + { + return __atomic_compare_exchange(std::__addressof(_M_i), + std::__addressof(__e), + std::__addressof(__i), + true, int(__s), int(__f)); + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) noexcept + { return compare_exchange_weak(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return compare_exchange_weak(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) noexcept + { + return __atomic_compare_exchange(std::__addressof(_M_i), + std::__addressof(__e), + std::__addressof(__i), + false, int(__s), int(__f)); + } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) volatile noexcept + { + return __atomic_compare_exchange(std::__addressof(_M_i), + std::__addressof(__e), + std::__addressof(__i), + false, int(__s), int(__f)); + } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) noexcept + { return compare_exchange_strong(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return compare_exchange_strong(__e, __i, __m, + __cmpexch_failure_order(__m)); } + }; +#undef _GLIBCXX20_INIT + + /// Partial specialization for pointer types. + template + struct atomic<_Tp*> + { + using value_type = _Tp*; + using difference_type = ptrdiff_t; + + typedef _Tp* __pointer_type; + typedef __atomic_base<_Tp*> __base_type; + __base_type _M_b; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__pointer_type __p) noexcept : _M_b(__p) { } + + operator __pointer_type() const noexcept + { return __pointer_type(_M_b); } + + operator __pointer_type() const volatile noexcept + { return __pointer_type(_M_b); } + + __pointer_type + operator=(__pointer_type __p) noexcept + { return _M_b.operator=(__p); } + + __pointer_type + operator=(__pointer_type __p) volatile noexcept + { return _M_b.operator=(__p); } + + __pointer_type + operator++(int) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b++; + } + + __pointer_type + operator++(int) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b++; + } + + __pointer_type + operator--(int) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b--; + } + + __pointer_type + operator--(int) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b--; + } + + __pointer_type + operator++() noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return ++_M_b; + } + + __pointer_type + operator++() volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return ++_M_b; + } + + __pointer_type + operator--() noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return --_M_b; + } + + __pointer_type + operator--() volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return --_M_b; + } + + __pointer_type + operator+=(ptrdiff_t __d) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator+=(__d); + } + + __pointer_type + operator+=(ptrdiff_t __d) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator+=(__d); + } + + __pointer_type + operator-=(ptrdiff_t __d) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator-=(__d); + } + + __pointer_type + operator-=(ptrdiff_t __d) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator-=(__d); + } + + bool + is_lock_free() const noexcept + { return _M_b.is_lock_free(); } + + bool + is_lock_free() const volatile noexcept + { return _M_b.is_lock_free(); } + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; +#endif + + void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_b.store(__p, __m); } + + void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_b.store(__p, __m); } + + __pointer_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { return _M_b.load(__m); } + + __pointer_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return _M_b.load(__m); } + + __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_b.exchange(__p, __m); } + + __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_b.exchange(__p, __m); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, memory_order __m2) noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_weak(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_weak(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, memory_order __m2) noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) noexcept + { + return _M_b.compare_exchange_strong(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return _M_b.compare_exchange_strong(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_add(__d, __m); + } + + __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_add(__d, __m); + } + + __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_sub(__d, __m); + } + + __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_sub(__d, __m); + } + }; + + + /// Explicit specialization for char. + template<> + struct atomic : __atomic_base + { + typedef char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for signed char. + template<> + struct atomic : __atomic_base + { + typedef signed char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept= default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned char. + template<> + struct atomic : __atomic_base + { + typedef unsigned char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept= default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for short. + template<> + struct atomic : __atomic_base + { + typedef short __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned short. + template<> + struct atomic : __atomic_base + { + typedef unsigned short __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for int. + template<> + struct atomic : __atomic_base + { + typedef int __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned int. + template<> + struct atomic : __atomic_base + { + typedef unsigned int __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for long. + template<> + struct atomic : __atomic_base + { + typedef long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned long. + template<> + struct atomic : __atomic_base + { + typedef unsigned long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for long long. + template<> + struct atomic : __atomic_base + { + typedef long long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned long long. + template<> + struct atomic : __atomic_base + { + typedef unsigned long long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for wchar_t. + template<> + struct atomic : __atomic_base + { + typedef wchar_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_WCHAR_T_LOCK_FREE == 2; +#endif + }; + +#ifdef _GLIBCXX_USE_CHAR8_T + /// Explicit specialization for char8_t. + template<> + struct atomic : __atomic_base + { + typedef char8_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus > 201402L + static constexpr bool is_always_lock_free = ATOMIC_CHAR8_T_LOCK_FREE == 2; +#endif + }; +#endif + + /// Explicit specialization for char16_t. + template<> + struct atomic : __atomic_base + { + typedef char16_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR16_T_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for char32_t. + template<> + struct atomic : __atomic_base + { + typedef char32_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR32_T_LOCK_FREE == 2; +#endif + }; + + + /// atomic_bool + typedef atomic atomic_bool; + + /// atomic_char + typedef atomic atomic_char; + + /// atomic_schar + typedef atomic atomic_schar; + + /// atomic_uchar + typedef atomic atomic_uchar; + + /// atomic_short + typedef atomic atomic_short; + + /// atomic_ushort + typedef atomic atomic_ushort; + + /// atomic_int + typedef atomic atomic_int; + + /// atomic_uint + typedef atomic atomic_uint; + + /// atomic_long + typedef atomic atomic_long; + + /// atomic_ulong + typedef atomic atomic_ulong; + + /// atomic_llong + typedef atomic atomic_llong; + + /// atomic_ullong + typedef atomic atomic_ullong; + + /// atomic_wchar_t + typedef atomic atomic_wchar_t; + +#ifdef _GLIBCXX_USE_CHAR8_T + /// atomic_char8_t + typedef atomic atomic_char8_t; +#endif + + /// atomic_char16_t + typedef atomic atomic_char16_t; + + /// atomic_char32_t + typedef atomic atomic_char32_t; + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2441. Exact-width atomic typedefs should be provided + + /// atomic_int8_t + typedef atomic atomic_int8_t; + + /// atomic_uint8_t + typedef atomic atomic_uint8_t; + + /// atomic_int16_t + typedef atomic atomic_int16_t; + + /// atomic_uint16_t + typedef atomic atomic_uint16_t; + + /// atomic_int32_t + typedef atomic atomic_int32_t; + + /// atomic_uint32_t + typedef atomic atomic_uint32_t; + + /// atomic_int64_t + typedef atomic atomic_int64_t; + + /// atomic_uint64_t + typedef atomic atomic_uint64_t; + + + /// atomic_int_least8_t + typedef atomic atomic_int_least8_t; + + /// atomic_uint_least8_t + typedef atomic atomic_uint_least8_t; + + /// atomic_int_least16_t + typedef atomic atomic_int_least16_t; + + /// atomic_uint_least16_t + typedef atomic atomic_uint_least16_t; + + /// atomic_int_least32_t + typedef atomic atomic_int_least32_t; + + /// atomic_uint_least32_t + typedef atomic atomic_uint_least32_t; + + /// atomic_int_least64_t + typedef atomic atomic_int_least64_t; + + /// atomic_uint_least64_t + typedef atomic atomic_uint_least64_t; + + + /// atomic_int_fast8_t + typedef atomic atomic_int_fast8_t; + + /// atomic_uint_fast8_t + typedef atomic atomic_uint_fast8_t; + + /// atomic_int_fast16_t + typedef atomic atomic_int_fast16_t; + + /// atomic_uint_fast16_t + typedef atomic atomic_uint_fast16_t; + + /// atomic_int_fast32_t + typedef atomic atomic_int_fast32_t; + + /// atomic_uint_fast32_t + typedef atomic atomic_uint_fast32_t; + + /// atomic_int_fast64_t + typedef atomic atomic_int_fast64_t; + + /// atomic_uint_fast64_t + typedef atomic atomic_uint_fast64_t; +#endif + + + /// atomic_intptr_t + typedef atomic atomic_intptr_t; + + /// atomic_uintptr_t + typedef atomic atomic_uintptr_t; + + /// atomic_size_t + typedef atomic atomic_size_t; + + /// atomic_ptrdiff_t + typedef atomic atomic_ptrdiff_t; + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + /// atomic_intmax_t + typedef atomic atomic_intmax_t; + + /// atomic_uintmax_t + typedef atomic atomic_uintmax_t; +#endif + + // Function definitions, atomic_flag operations. + inline bool + atomic_flag_test_and_set_explicit(atomic_flag* __a, + memory_order __m) noexcept + { return __a->test_and_set(__m); } + + inline bool + atomic_flag_test_and_set_explicit(volatile atomic_flag* __a, + memory_order __m) noexcept + { return __a->test_and_set(__m); } + + inline void + atomic_flag_clear_explicit(atomic_flag* __a, memory_order __m) noexcept + { __a->clear(__m); } + + inline void + atomic_flag_clear_explicit(volatile atomic_flag* __a, + memory_order __m) noexcept + { __a->clear(__m); } + + inline bool + atomic_flag_test_and_set(atomic_flag* __a) noexcept + { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } + + inline bool + atomic_flag_test_and_set(volatile atomic_flag* __a) noexcept + { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } + + inline void + atomic_flag_clear(atomic_flag* __a) noexcept + { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } + + inline void + atomic_flag_clear(volatile atomic_flag* __a) noexcept + { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } + + + template + using __atomic_val_t = typename atomic<_Tp>::value_type; + template + using __atomic_diff_t = typename atomic<_Tp>::difference_type; + + // [atomics.nonmembers] Non-member functions. + // Function templates generally applicable to atomic types. + template + inline bool + atomic_is_lock_free(const atomic<_ITp>* __a) noexcept + { return __a->is_lock_free(); } + + template + inline bool + atomic_is_lock_free(const volatile atomic<_ITp>* __a) noexcept + { return __a->is_lock_free(); } + + template + inline void + atomic_init(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { __a->store(__i, memory_order_relaxed); } + + template + inline void + atomic_init(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { __a->store(__i, memory_order_relaxed); } + + template + inline void + atomic_store_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { __a->store(__i, __m); } + + template + inline void + atomic_store_explicit(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { __a->store(__i, __m); } + + template + inline _ITp + atomic_load_explicit(const atomic<_ITp>* __a, memory_order __m) noexcept + { return __a->load(__m); } + + template + inline _ITp + atomic_load_explicit(const volatile atomic<_ITp>* __a, + memory_order __m) noexcept + { return __a->load(__m); } + + template + inline _ITp + atomic_exchange_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->exchange(__i, __m); } + + template + inline _ITp + atomic_exchange_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->exchange(__i, __m); } + + template + inline bool + atomic_compare_exchange_weak_explicit(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_weak_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_strong_explicit(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_strong_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } + + + template + inline void + atomic_store(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { atomic_store_explicit(__a, __i, memory_order_seq_cst); } + + template + inline void + atomic_store(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { atomic_store_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_load(const atomic<_ITp>* __a) noexcept + { return atomic_load_explicit(__a, memory_order_seq_cst); } + + template + inline _ITp + atomic_load(const volatile atomic<_ITp>* __a) noexcept + { return atomic_load_explicit(__a, memory_order_seq_cst); } + + template + inline _ITp + atomic_exchange(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_exchange(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } + + template + inline bool + atomic_compare_exchange_weak(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_weak(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_strong(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_strong(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + // Function templates for atomic_integral and atomic_pointer operations only. + // Some operations (and, or, xor) are only available for atomic integrals, + // which is implemented by taking a parameter of type __atomic_base<_ITp>*. + + template + inline _ITp + atomic_fetch_add_explicit(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_add(__i, __m); } + + template + inline _ITp + atomic_fetch_add_explicit(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_add(__i, __m); } + + template + inline _ITp + atomic_fetch_sub_explicit(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_sub(__i, __m); } + + template + inline _ITp + atomic_fetch_sub_explicit(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_sub(__i, __m); } + + template + inline _ITp + atomic_fetch_and_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_and(__i, __m); } + + template + inline _ITp + atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_and(__i, __m); } + + template + inline _ITp + atomic_fetch_or_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_or(__i, __m); } + + template + inline _ITp + atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_or(__i, __m); } + + template + inline _ITp + atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_xor(__i, __m); } + + template + inline _ITp + atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_xor(__i, __m); } + + template + inline _ITp + atomic_fetch_add(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_add(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_sub(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_sub(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_and(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_and(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_or(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_or(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_xor(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_xor(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } + +#if __cplusplus > 201703L +#define __cpp_lib_atomic_float 201711L + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(float __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; + + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(double __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; + + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(long double __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; + +#define __cpp_lib_atomic_ref 201806L + + /// Class template to provide atomic operations on a non-atomic variable. + template + struct atomic_ref : __atomic_ref<_Tp> + { + explicit + atomic_ref(_Tp& __t) noexcept : __atomic_ref<_Tp>(__t) + { } + + atomic_ref& operator=(const atomic_ref&) = delete; + + atomic_ref(const atomic_ref&) = default; + + using __atomic_ref<_Tp>::operator=; + }; + +#endif // C++2a + + // @} group atomics + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _GLIBCXX_ATOMIC diff --git a/resources/sources/avr-libstdcpp/include/backward/backward_warning.h b/resources/sources/avr-libstdcpp/include/backward/backward_warning.h new file mode 100644 index 000000000..94347de40 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/backward_warning.h @@ -0,0 +1,56 @@ +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file backward/backward_warning.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _BACKWARD_BACKWARD_WARNING_H +#define _BACKWARD_BACKWARD_WARNING_H 1 + +#ifdef __DEPRECATED +#warning \ + This file includes at least one deprecated or antiquated header which \ + may be removed without further notice at a future date. Please use a \ + non-deprecated interface with equivalent functionality instead. For a \ + listing of replacement headers and interfaces, consult the file \ + backward_warning.h. To disable this warning use -Wno-deprecated. + +/* + A list of valid replacements is as follows: + + Use: Instead of: + , unordered_set , hash_set + , unordered_multiset , hash_multiset + , unordered_map , hash_map + , unordered_multimap , hash_multimap + , bind , binder1st + , bind , binder2nd + , bind , bind1st + , bind , bind2nd + , unique_ptr , auto_ptr +*/ + +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/binders.h b/resources/sources/avr-libstdcpp/include/backward/binders.h new file mode 100644 index 000000000..8c2c00d78 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/binders.h @@ -0,0 +1,182 @@ +// Functor implementations -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file backward/binders.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _BACKWARD_BINDERS_H +#define _BACKWARD_BINDERS_H 1 + +// Suppress deprecated warning for this file. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // 20.3.6 binders + /** @defgroup binders Binder Classes + * @ingroup functors + * + * Binders turn functions/functors with two arguments into functors + * with a single argument, storing an argument to be applied later. + * For example, a variable @c B of type @c binder1st is constructed + * from a functor @c f and an argument @c x. Later, B's @c + * operator() is called with a single argument @c y. The return + * value is the value of @c f(x,y). @c B can be @a called with + * various arguments (y1, y2, ...) and will in turn call @c + * f(x,y1), @c f(x,y2), ... + * + * The function @c bind1st is provided to save some typing. It takes the + * function and an argument as parameters, and returns an instance of + * @c binder1st. + * + * The type @c binder2nd and its creator function @c bind2nd do the same + * thing, but the stored argument is passed as the second parameter instead + * of the first, e.g., @c bind2nd(std::minus(),1.3) will create a + * functor whose @c operator() accepts a floating-point number, subtracts + * 1.3 from it, and returns the result. (If @c bind1st had been used, + * the functor would perform 1.3 - x instead. + * + * Creator-wrapper functions like @c bind1st are intended to be used in + * calling algorithms. Their return values will be temporary objects. + * (The goal is to not require you to type names like + * @c std::binder1st> for declaring a variable to hold the + * return value from @c bind1st(std::plus(),5). + * + * These become more useful when combined with the composition functions. + * + * These functions are deprecated in C++11 and can be replaced by + * @c std::bind (or @c std::tr1::bind) which is more powerful and flexible, + * supporting functions with any number of arguments. Uses of @c bind1st + * can be replaced by @c std::bind(f, x, std::placeholders::_1) and + * @c bind2nd by @c std::bind(f, std::placeholders::_1, x). + * @{ + */ + /// One of the @link binders binder functors@endlink. + template + class binder1st + : public unary_function + { + protected: + _Operation op; + typename _Operation::first_argument_type value; + + public: + binder1st(const _Operation& __x, + const typename _Operation::first_argument_type& __y) + : op(__x), value(__y) { } + + typename _Operation::result_type + operator()(const typename _Operation::second_argument_type& __x) const + { return op(value, __x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 109. Missing binders for non-const sequence elements + typename _Operation::result_type + operator()(typename _Operation::second_argument_type& __x) const + { return op(value, __x); } + } _GLIBCXX_DEPRECATED; + + /// One of the @link binders binder functors@endlink. + template + inline binder1st<_Operation> + bind1st(const _Operation& __fn, const _Tp& __x) + { + typedef typename _Operation::first_argument_type _Arg1_type; + return binder1st<_Operation>(__fn, _Arg1_type(__x)); + } + + /// One of the @link binders binder functors@endlink. + template + class binder2nd + : public unary_function + { + protected: + _Operation op; + typename _Operation::second_argument_type value; + + public: + binder2nd(const _Operation& __x, + const typename _Operation::second_argument_type& __y) + : op(__x), value(__y) { } + + typename _Operation::result_type + operator()(const typename _Operation::first_argument_type& __x) const + { return op(__x, value); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 109. Missing binders for non-const sequence elements + typename _Operation::result_type + operator()(typename _Operation::first_argument_type& __x) const + { return op(__x, value); } + } _GLIBCXX_DEPRECATED; + + /// One of the @link binders binder functors@endlink. + template + inline binder2nd<_Operation> + bind2nd(const _Operation& __fn, const _Tp& __x) + { + typedef typename _Operation::second_argument_type _Arg2_type; + return binder2nd<_Operation>(__fn, _Arg2_type(__x)); + } + /** @} */ + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#pragma GCC diagnostic pop + +#endif /* _BACKWARD_BINDERS_H */ diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_fun.h b/resources/sources/avr-libstdcpp/include/backward/hash_fun.h new file mode 100644 index 000000000..5d19f979a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/hash_fun.h @@ -0,0 +1,170 @@ +// 'struct hash' from SGI -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_fun.h + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_FUN_H +#define _BACKWARD_HASH_FUN_H 1 + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::size_t; + + template + struct hash { }; + + inline size_t + __stl_hash_string(const char* __s) + { + unsigned long __h = 0; + for ( ; *__s; ++__s) + __h = 5 * __h + *__s; + return size_t(__h); + } + + template<> + struct hash + { + size_t + operator()(const char* __s) const + { return __stl_hash_string(__s); } + }; + + template<> + struct hash + { + size_t + operator()(const char* __s) const + { return __stl_hash_string(__s); } + }; + + template<> + struct hash + { + size_t + operator()(char __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned char __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned char __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(short __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned short __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(int __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned int __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(long __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned long __x) const + { return __x; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_map b/resources/sources/avr-libstdcpp/include/backward/hash_map new file mode 100644 index 000000000..93db70d56 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/hash_map @@ -0,0 +1,599 @@ +// Hashing map implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_map + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_MAP +#define _BACKWARD_HASH_MAP 1 + +#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH +#include +#endif + +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::equal_to; + using std::allocator; + using std::pair; + using std::_Select1st; + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> > + class hash_map + { + private: + typedef hashtable,_Key, _HashFn, + _Select1st >, + _EqualKey, _Alloc> _Ht; + + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_map() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_map(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_map(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_map(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_map& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&, + const hash_map<_K1, _T1, _HF, _EqK, _Al>&); + + iterator + begin() + { return _M_ht.begin(); } + + iterator + end() + { return _M_ht.end(); } + + const_iterator + begin() const + { return _M_ht.begin(); } + + const_iterator + end() const + { return _M_ht.end(); } + + pair + insert(const value_type& __obj) + { return _M_ht.insert_unique(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f, __l); } + + pair + insert_noresize(const value_type& __obj) + { return _M_ht.insert_unique_noresize(__obj); } + + iterator + find(const key_type& __key) + { return _M_ht.find(__key); } + + const_iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + _Tp& + operator[](const key_type& __key) + { return _M_ht.find_or_insert(value_type(__key, _Tp())).second; } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + {return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { return __hm1._M_ht == __hm2._M_ht; } + + template + inline bool + operator!=(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { return !(__hm1 == __hm2); } + + template + inline void + swap(hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { __hm1.swap(__hm2); } + + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Key>, + class _Alloc = allocator<_Tp> > + class hash_multimap + { + // concept requirements + __glibcxx_class_requires(_Key, _SGIAssignableConcept) + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFn, size_t, _Key, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Key, _Key, _BinaryPredicateConcept) + + private: + typedef hashtable, _Key, _HashFn, + _Select1st >, _EqualKey, _Alloc> + _Ht; + + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_multimap() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_multimap(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_multimap(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_multimap(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_multimap& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator==(const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&, + const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&); + + iterator + begin() + { return _M_ht.begin(); } + + iterator + end() + { return _M_ht.end(); } + + const_iterator + begin() const + { return _M_ht.begin(); } + + const_iterator + end() const + { return _M_ht.end(); } + + iterator + insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } + + iterator + insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator + find(const key_type& __key) + { return _M_ht.find(__key); } + + const_iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + { return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, + const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) + { return __hm1._M_ht == __hm2._M_ht; } + + template + inline bool + operator!=(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, + const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) + { return !(__hm1 == __hm2); } + + template + inline void + swap(hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { __hm1.swap(__hm2); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that it will work for hash_map + // and hash_multimap. + template + class insert_iterator<__gnu_cxx::hash_map<_Key, _Tp, _HashFn, + _EqKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc> + _Container; + _Container* container; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + + template + class insert_iterator<__gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, + _EqKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc> + _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_set b/resources/sources/avr-libstdcpp/include/backward/hash_set new file mode 100644 index 000000000..0b99302af --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/hash_set @@ -0,0 +1,569 @@ +// Hashing set implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_set + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_SET +#define _BACKWARD_HASH_SET 1 + +#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH +#include +#endif + +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::equal_to; + using std::allocator; + using std::pair; + using std::_Identity; + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Value>, + class _Alloc = allocator<_Value> > + class hash_set + { + // concept requirements + __glibcxx_class_requires(_Value, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) + + typedef __alloc_traits<_Alloc> _Alloc_traits; + + private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_set() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_set(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_set(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_set(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_set& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator==(const hash_set<_Val, _HF, _EqK, _Al>&, + const hash_set<_Val, _HF, _EqK, _Al>&); + + iterator + begin() const + { return _M_ht.begin(); } + + iterator + end() const + { return _M_ht.end(); } + + pair + insert(const value_type& __obj) + { + pair __p = _M_ht.insert_unique(__obj); + return pair(__p.first, __p.second); + } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f, __l); } + + pair + insert_noresize(const value_type& __obj) + { + pair __p + = _M_ht.insert_unique_noresize(__obj); + return pair(__p.first, __p.second); + } + + iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + {return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return __hs1._M_ht == __hs2._M_ht; } + + template + inline bool + operator!=(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return !(__hs1 == __hs2); } + + template + inline void + swap(hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { __hs1.swap(__hs2); } + + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Value>, + class _Alloc = allocator<_Value> > + class hash_multiset + { + // concept requirements + __glibcxx_class_requires(_Value, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) + + private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_multiset() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_multiset(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_multiset(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_multiset(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_multiset& hs) + { _M_ht.swap(hs._M_ht); } + + template + friend bool + operator==(const hash_multiset<_Val, _HF, _EqK, _Al>&, + const hash_multiset<_Val, _HF, _EqK, _Al>&); + + iterator + begin() const + { return _M_ht.begin(); } + + iterator + end() const + { return _M_ht.end(); } + + iterator + insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } + + iterator + insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + { return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return __hs1._M_ht == __hs2._M_ht; } + + template + inline bool + operator!=(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return !(__hs1 == __hs2); } + + template + inline void + swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { __hs1.swap(__hs2); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that it will work for hash_set + // and hash_multiset. + template + class insert_iterator<__gnu_cxx::hash_set<_Value, _HashFcn, + _EqualKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc> + _Container; + _Container* container; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + + template + class insert_iterator<__gnu_cxx::hash_multiset<_Value, _HashFcn, + _EqualKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_multiset<_Value, _HashFcn, _EqualKey, _Alloc> + _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hashtable.h b/resources/sources/avr-libstdcpp/include/backward/hashtable.h new file mode 100644 index 000000000..1779fa44d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/hashtable.h @@ -0,0 +1,1166 @@ +// Hashtable implementation used by containers -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hashtable.h + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASHTABLE_H +#define _BACKWARD_HASHTABLE_H 1 + +// Hashtable class, used to implement the hashed associative containers +// hash_set, hash_map, hash_multiset, and hash_multimap. + +#include +#include +#include +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + struct _Hashtable_node + { + _Hashtable_node* _M_next; + _Val _M_val; + }; + + template > + class hashtable; + + template + struct _Hashtable_iterator; + + template + struct _Hashtable_const_iterator; + + template + struct _Hashtable_iterator + { + typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> + _Hashtable; + typedef _Hashtable_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + const_iterator; + typedef _Hashtable_node<_Val> _Node; + typedef std::forward_iterator_tag iterator_category; + typedef _Val value_type; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef _Val& reference; + typedef _Val* pointer; + + _Node* _M_cur; + _Hashtable* _M_ht; + + _Hashtable_iterator(_Node* __n, _Hashtable* __tab) + : _M_cur(__n), _M_ht(__tab) { } + + _Hashtable_iterator() { } + + reference + operator*() const + { return _M_cur->_M_val; } + + pointer + operator->() const + { return &(operator*()); } + + iterator& + operator++(); + + iterator + operator++(int); + + bool + operator==(const iterator& __it) const + { return _M_cur == __it._M_cur; } + + bool + operator!=(const iterator& __it) const + { return _M_cur != __it._M_cur; } + }; + + template + struct _Hashtable_const_iterator + { + typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> + _Hashtable; + typedef _Hashtable_iterator<_Val,_Key,_HashFcn, + _ExtractKey,_EqualKey,_Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + const_iterator; + typedef _Hashtable_node<_Val> _Node; + + typedef std::forward_iterator_tag iterator_category; + typedef _Val value_type; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef const _Val& reference; + typedef const _Val* pointer; + + const _Node* _M_cur; + const _Hashtable* _M_ht; + + _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab) + : _M_cur(__n), _M_ht(__tab) { } + + _Hashtable_const_iterator() { } + + _Hashtable_const_iterator(const iterator& __it) + : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { } + + reference + operator*() const + { return _M_cur->_M_val; } + + pointer + operator->() const + { return &(operator*()); } + + const_iterator& + operator++(); + + const_iterator + operator++(int); + + bool + operator==(const const_iterator& __it) const + { return _M_cur == __it._M_cur; } + + bool + operator!=(const const_iterator& __it) const + { return _M_cur != __it._M_cur; } + }; + + // Note: assumes long is at least 32 bits. + enum { _S_num_primes = 29 }; + + template + struct _Hashtable_prime_list + { + static const _PrimeType __stl_prime_list[_S_num_primes]; + + static const _PrimeType* + _S_get_prime_list(); + }; + + template const _PrimeType + _Hashtable_prime_list<_PrimeType>::__stl_prime_list[_S_num_primes] = + { + 5ul, 53ul, 97ul, 193ul, 389ul, + 769ul, 1543ul, 3079ul, 6151ul, 12289ul, + 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, + 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, + 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, + 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul + }; + + template inline const _PrimeType* + _Hashtable_prime_list<_PrimeType>::_S_get_prime_list() + { + return __stl_prime_list; + } + + inline unsigned long + __stl_next_prime(unsigned long __n) + { + const unsigned long* __first = _Hashtable_prime_list::_S_get_prime_list(); + const unsigned long* __last = __first + (int)_S_num_primes; + const unsigned long* pos = std::lower_bound(__first, __last, __n); + return pos == __last ? *(__last - 1) : *pos; + } + + // Forward declaration of operator==. + template + class hashtable; + + template + bool + operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, + const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2); + + // Hashtables handle allocators a bit differently than other + // containers do. If we're using standard-conforming allocators, then + // a hashtable unconditionally has a member variable to hold its + // allocator, even if it so happens that all instances of the + // allocator type are identical. This is because, for hashtables, + // this extra storage is negligible. Additionally, a base class + // wouldn't serve any other purposes; it wouldn't, for example, + // simplify the exception-handling code. + template + class hashtable + { + public: + typedef _Key key_type; + typedef _Val value_type; + typedef _HashFcn hasher; + typedef _EqualKey key_equal; + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + hasher + hash_funct() const + { return _M_hash; } + + key_equal + key_eq() const + { return _M_equals; } + + private: + typedef _Hashtable_node<_Val> _Node; + + public: + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind::other allocator_type; + + allocator_type + get_allocator() const + { return _M_node_allocator; } + + private: + typedef __gnu_cxx::__alloc_traits _Alloc_traits; + typedef typename _Alloc_traits::template rebind<_Node>::other + _Node_Alloc; + typedef typename _Alloc_traits::template rebind<_Node*>::other + _Nodeptr_Alloc; + typedef std::vector<_Node*, _Nodeptr_Alloc> _Vector_type; + + _Node_Alloc _M_node_allocator; + + _Node* + _M_get_node() + { return _M_node_allocator.allocate(1); } + + void + _M_put_node(_Node* __p) + { _M_node_allocator.deallocate(__p, 1); } + + private: + hasher _M_hash; + key_equal _M_equals; + _ExtractKey _M_get_key; + _Vector_type _M_buckets; + size_type _M_num_elements; + + public: + typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, + _EqualKey, _Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, + _EqualKey, _Alloc> + const_iterator; + + friend struct + _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>; + + friend struct + _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, + _EqualKey, _Alloc>; + + public: + hashtable(size_type __n, const _HashFcn& __hf, + const _EqualKey& __eql, const _ExtractKey& __ext, + const allocator_type& __a = allocator_type()) + : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), + _M_get_key(__ext), _M_buckets(__a), _M_num_elements(0) + { _M_initialize_buckets(__n); } + + hashtable(size_type __n, const _HashFcn& __hf, + const _EqualKey& __eql, + const allocator_type& __a = allocator_type()) + : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), + _M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0) + { _M_initialize_buckets(__n); } + + hashtable(const hashtable& __ht) + : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash), + _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key), + _M_buckets(__ht.get_allocator()), _M_num_elements(0) + { _M_copy_from(__ht); } + + hashtable& + operator= (const hashtable& __ht) + { + if (&__ht != this) + { + clear(); + _M_hash = __ht._M_hash; + _M_equals = __ht._M_equals; + _M_get_key = __ht._M_get_key; + _M_copy_from(__ht); + } + return *this; + } + + ~hashtable() + { clear(); } + + size_type + size() const + { return _M_num_elements; } + + size_type + max_size() const + { return size_type(-1); } + + _GLIBCXX_NODISCARD bool + empty() const + { return size() == 0; } + + void + swap(hashtable& __ht) + { + std::swap(_M_hash, __ht._M_hash); + std::swap(_M_equals, __ht._M_equals); + std::swap(_M_get_key, __ht._M_get_key); + _M_buckets.swap(__ht._M_buckets); + std::swap(_M_num_elements, __ht._M_num_elements); + } + + iterator + begin() + { + for (size_type __n = 0; __n < _M_buckets.size(); ++__n) + if (_M_buckets[__n]) + return iterator(_M_buckets[__n], this); + return end(); + } + + iterator + end() + { return iterator(0, this); } + + const_iterator + begin() const + { + for (size_type __n = 0; __n < _M_buckets.size(); ++__n) + if (_M_buckets[__n]) + return const_iterator(_M_buckets[__n], this); + return end(); + } + + const_iterator + end() const + { return const_iterator(0, this); } + + template + friend bool + operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&, + const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&); + + public: + size_type + bucket_count() const + { return _M_buckets.size(); } + + size_type + max_bucket_count() const + { return _Hashtable_prime_list:: + _S_get_prime_list()[(int)_S_num_primes - 1]; + } + + size_type + elems_in_bucket(size_type __bucket) const + { + size_type __result = 0; + for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next) + __result += 1; + return __result; + } + + std::pair + insert_unique(const value_type& __obj) + { + resize(_M_num_elements + 1); + return insert_unique_noresize(__obj); + } + + iterator + insert_equal(const value_type& __obj) + { + resize(_M_num_elements + 1); + return insert_equal_noresize(__obj); + } + + std::pair + insert_unique_noresize(const value_type& __obj); + + iterator + insert_equal_noresize(const value_type& __obj); + + template + void + insert_unique(_InputIterator __f, _InputIterator __l) + { insert_unique(__f, __l, std::__iterator_category(__f)); } + + template + void + insert_equal(_InputIterator __f, _InputIterator __l) + { insert_equal(__f, __l, std::__iterator_category(__f)); } + + template + void + insert_unique(_InputIterator __f, _InputIterator __l, + std::input_iterator_tag) + { + for ( ; __f != __l; ++__f) + insert_unique(*__f); + } + + template + void + insert_equal(_InputIterator __f, _InputIterator __l, + std::input_iterator_tag) + { + for ( ; __f != __l; ++__f) + insert_equal(*__f); + } + + template + void + insert_unique(_ForwardIterator __f, _ForwardIterator __l, + std::forward_iterator_tag) + { + size_type __n = std::distance(__f, __l); + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_unique_noresize(*__f); + } + + template + void + insert_equal(_ForwardIterator __f, _ForwardIterator __l, + std::forward_iterator_tag) + { + size_type __n = std::distance(__f, __l); + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_equal_noresize(*__f); + } + + reference + find_or_insert(const value_type& __obj); + + iterator + find(const key_type& __key) + { + size_type __n = _M_bkt_num_key(__key); + _Node* __first; + for (__first = _M_buckets[__n]; + __first && !_M_equals(_M_get_key(__first->_M_val), __key); + __first = __first->_M_next) + { } + return iterator(__first, this); + } + + const_iterator + find(const key_type& __key) const + { + size_type __n = _M_bkt_num_key(__key); + const _Node* __first; + for (__first = _M_buckets[__n]; + __first && !_M_equals(_M_get_key(__first->_M_val), __key); + __first = __first->_M_next) + { } + return const_iterator(__first, this); + } + + size_type + count(const key_type& __key) const + { + const size_type __n = _M_bkt_num_key(__key); + size_type __result = 0; + + for (const _Node* __cur = _M_buckets[__n]; __cur; + __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), __key)) + ++__result; + return __result; + } + + std::pair + equal_range(const key_type& __key); + + std::pair + equal_range(const key_type& __key) const; + + size_type + erase(const key_type& __key); + + void + erase(const iterator& __it); + + void + erase(iterator __first, iterator __last); + + void + erase(const const_iterator& __it); + + void + erase(const_iterator __first, const_iterator __last); + + void + resize(size_type __num_elements_hint); + + void + clear(); + + private: + size_type + _M_next_size(size_type __n) const + { return __stl_next_prime(__n); } + + void + _M_initialize_buckets(size_type __n) + { + const size_type __n_buckets = _M_next_size(__n); + _M_buckets.reserve(__n_buckets); + _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0); + _M_num_elements = 0; + } + + size_type + _M_bkt_num_key(const key_type& __key) const + { return _M_bkt_num_key(__key, _M_buckets.size()); } + + size_type + _M_bkt_num(const value_type& __obj) const + { return _M_bkt_num_key(_M_get_key(__obj)); } + + size_type + _M_bkt_num_key(const key_type& __key, std::size_t __n) const + { return _M_hash(__key) % __n; } + + size_type + _M_bkt_num(const value_type& __obj, std::size_t __n) const + { return _M_bkt_num_key(_M_get_key(__obj), __n); } + + _Node* + _M_new_node(const value_type& __obj) + { + _Node* __n = _M_get_node(); + __n->_M_next = 0; + __try + { + allocator_type __a = this->get_allocator(); + _Alloc_traits::construct(__a, &__n->_M_val, __obj); + return __n; + } + __catch(...) + { + _M_put_node(__n); + __throw_exception_again; + } + } + + void + _M_delete_node(_Node* __n) + { + allocator_type __a = this->get_allocator(); + _Alloc_traits::destroy(__a, &__n->_M_val); + _M_put_node(__n); + } + + void + _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last); + + void + _M_erase_bucket(const size_type __n, _Node* __last); + + void + _M_copy_from(const hashtable& __ht); + }; + + template + _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& + _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: + operator++() + { + const _Node* __old = _M_cur; + _M_cur = _M_cur->_M_next; + if (!_M_cur) + { + size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); + while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) + _M_cur = _M_ht->_M_buckets[__bucket]; + } + return *this; + } + + template + inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> + _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: + operator++(int) + { + iterator __tmp = *this; + ++*this; + return __tmp; + } + + template + _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& + _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: + operator++() + { + const _Node* __old = _M_cur; + _M_cur = _M_cur->_M_next; + if (!_M_cur) + { + size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); + while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) + _M_cur = _M_ht->_M_buckets[__bucket]; + } + return *this; + } + + template + inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> + _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: + operator++(int) + { + const_iterator __tmp = *this; + ++*this; + return __tmp; + } + + template + bool + operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, + const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) + { + typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node; + + if (__ht1._M_buckets.size() != __ht2._M_buckets.size()) + return false; + + for (std::size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) + { + _Node* __cur1 = __ht1._M_buckets[__n]; + _Node* __cur2 = __ht2._M_buckets[__n]; + // Check same length of lists + for (; __cur1 && __cur2; + __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next) + { } + if (__cur1 || __cur2) + return false; + // Now check one's elements are in the other + for (__cur1 = __ht1._M_buckets[__n] ; __cur1; + __cur1 = __cur1->_M_next) + { + bool _found__cur1 = false; + for (__cur2 = __ht2._M_buckets[__n]; + __cur2; __cur2 = __cur2->_M_next) + { + if (__cur1->_M_val == __cur2->_M_val) + { + _found__cur1 = true; + break; + } + } + if (!_found__cur1) + return false; + } + } + return true; + } + + template + inline bool + operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, + const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) + { return !(__ht1 == __ht2); } + + template + inline void + swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1, + hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) + { __ht1.swap(__ht2); } + + template + std::pair::iterator, + bool> + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + insert_unique_noresize(const value_type& __obj) + { + const size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) + return std::pair(iterator(__cur, this), false); + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return std::pair(iterator(__tmp, this), true); + } + + template + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + insert_equal_noresize(const value_type& __obj) + { + const size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) + { + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __cur->_M_next; + __cur->_M_next = __tmp; + ++_M_num_elements; + return iterator(__tmp, this); + } + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return iterator(__tmp, this); + } + + template + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + find_or_insert(const value_type& __obj) + { + resize(_M_num_elements + 1); + + size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) + return __cur->_M_val; + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return __tmp->_M_val; + } + + template + std::pair::iterator, + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator> + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + equal_range(const key_type& __key) + { + typedef std::pair _Pii; + const size_type __n = _M_bkt_num_key(__key); + + for (_Node* __first = _M_buckets[__n]; __first; + __first = __first->_M_next) + if (_M_equals(_M_get_key(__first->_M_val), __key)) + { + for (_Node* __cur = __first->_M_next; __cur; + __cur = __cur->_M_next) + if (!_M_equals(_M_get_key(__cur->_M_val), __key)) + return _Pii(iterator(__first, this), iterator(__cur, this)); + for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) + if (_M_buckets[__m]) + return _Pii(iterator(__first, this), + iterator(_M_buckets[__m], this)); + return _Pii(iterator(__first, this), end()); + } + return _Pii(end(), end()); + } + + template + std::pair< + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator, + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator> + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + equal_range(const key_type& __key) const + { + typedef std::pair _Pii; + const size_type __n = _M_bkt_num_key(__key); + + for (const _Node* __first = _M_buckets[__n]; __first; + __first = __first->_M_next) + { + if (_M_equals(_M_get_key(__first->_M_val), __key)) + { + for (const _Node* __cur = __first->_M_next; __cur; + __cur = __cur->_M_next) + if (!_M_equals(_M_get_key(__cur->_M_val), __key)) + return _Pii(const_iterator(__first, this), + const_iterator(__cur, this)); + for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) + if (_M_buckets[__m]) + return _Pii(const_iterator(__first, this), + const_iterator(_M_buckets[__m], this)); + return _Pii(const_iterator(__first, this), end()); + } + } + return _Pii(end(), end()); + } + + template + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(const key_type& __key) + { + const size_type __n = _M_bkt_num_key(__key); + _Node* __first = _M_buckets[__n]; + _Node* __saved_slot = 0; + size_type __erased = 0; + + if (__first) + { + _Node* __cur = __first; + _Node* __next = __cur->_M_next; + while (__next) + { + if (_M_equals(_M_get_key(__next->_M_val), __key)) + { + if (&_M_get_key(__next->_M_val) != &__key) + { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + __next = __cur->_M_next; + ++__erased; + --_M_num_elements; + } + else + { + __saved_slot = __cur; + __cur = __next; + __next = __cur->_M_next; + } + } + else + { + __cur = __next; + __next = __cur->_M_next; + } + } + bool __delete_first = _M_equals(_M_get_key(__first->_M_val), __key); + if (__saved_slot) + { + __next = __saved_slot->_M_next; + __saved_slot->_M_next = __next->_M_next; + _M_delete_node(__next); + ++__erased; + --_M_num_elements; + } + if (__delete_first) + { + _M_buckets[__n] = __first->_M_next; + _M_delete_node(__first); + ++__erased; + --_M_num_elements; + } + } + return __erased; + } + + template + void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(const iterator& __it) + { + _Node* __p = __it._M_cur; + if (__p) + { + const size_type __n = _M_bkt_num(__p->_M_val); + _Node* __cur = _M_buckets[__n]; + + if (__cur == __p) + { + _M_buckets[__n] = __cur->_M_next; + _M_delete_node(__cur); + --_M_num_elements; + } + else + { + _Node* __next = __cur->_M_next; + while (__next) + { + if (__next == __p) + { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + --_M_num_elements; + break; + } + else + { + __cur = __next; + __next = __cur->_M_next; + } + } + } + } + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(iterator __first, iterator __last) + { + size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val) + : _M_buckets.size(); + + size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val) + : _M_buckets.size(); + + if (__first._M_cur == __last._M_cur) + return; + else if (__f_bucket == __l_bucket) + _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur); + else + { + _M_erase_bucket(__f_bucket, __first._M_cur, 0); + for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n) + _M_erase_bucket(__n, 0); + if (__l_bucket != _M_buckets.size()) + _M_erase_bucket(__l_bucket, __last._M_cur); + } + } + + template + inline void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(const_iterator __first, const_iterator __last) + { + erase(iterator(const_cast<_Node*>(__first._M_cur), + const_cast(__first._M_ht)), + iterator(const_cast<_Node*>(__last._M_cur), + const_cast(__last._M_ht))); + } + + template + inline void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(const const_iterator& __it) + { erase(iterator(const_cast<_Node*>(__it._M_cur), + const_cast(__it._M_ht))); } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + resize(size_type __num_elements_hint) + { + const size_type __old_n = _M_buckets.size(); + if (__num_elements_hint > __old_n) + { + const size_type __n = _M_next_size(__num_elements_hint); + if (__n > __old_n) + { + _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator()); + __try + { + for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) + { + _Node* __first = _M_buckets[__bucket]; + while (__first) + { + size_type __new_bucket = _M_bkt_num(__first->_M_val, + __n); + _M_buckets[__bucket] = __first->_M_next; + __first->_M_next = __tmp[__new_bucket]; + __tmp[__new_bucket] = __first; + __first = _M_buckets[__bucket]; + } + } + _M_buckets.swap(__tmp); + } + __catch(...) + { + for (size_type __bucket = 0; __bucket < __tmp.size(); + ++__bucket) + { + while (__tmp[__bucket]) + { + _Node* __next = __tmp[__bucket]->_M_next; + _M_delete_node(__tmp[__bucket]); + __tmp[__bucket] = __next; + } + } + __throw_exception_again; + } + } + } + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last) + { + _Node* __cur = _M_buckets[__n]; + if (__cur == __first) + _M_erase_bucket(__n, __last); + else + { + _Node* __next; + for (__next = __cur->_M_next; + __next != __first; + __cur = __next, __next = __cur->_M_next) + ; + while (__next != __last) + { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + __next = __cur->_M_next; + --_M_num_elements; + } + } + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + _M_erase_bucket(const size_type __n, _Node* __last) + { + _Node* __cur = _M_buckets[__n]; + while (__cur != __last) + { + _Node* __next = __cur->_M_next; + _M_delete_node(__cur); + __cur = __next; + _M_buckets[__n] = __cur; + --_M_num_elements; + } + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + clear() + { + if (_M_num_elements == 0) + return; + + for (size_type __i = 0; __i < _M_buckets.size(); ++__i) + { + _Node* __cur = _M_buckets[__i]; + while (__cur != 0) + { + _Node* __next = __cur->_M_next; + _M_delete_node(__cur); + __cur = __next; + } + _M_buckets[__i] = 0; + } + _M_num_elements = 0; + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + _M_copy_from(const hashtable& __ht) + { + _M_buckets.clear(); + _M_buckets.reserve(__ht._M_buckets.size()); + _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0); + __try + { + for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) { + const _Node* __cur = __ht._M_buckets[__i]; + if (__cur) + { + _Node* __local_copy = _M_new_node(__cur->_M_val); + _M_buckets[__i] = __local_copy; + + for (_Node* __next = __cur->_M_next; + __next; + __cur = __next, __next = __cur->_M_next) + { + __local_copy->_M_next = _M_new_node(__next->_M_val); + __local_copy = __local_copy->_M_next; + } + } + } + _M_num_elements = __ht._M_num_elements; + } + __catch(...) + { + clear(); + __throw_exception_again; + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bit b/resources/sources/avr-libstdcpp/include/bit new file mode 100644 index 000000000..f4344820d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bit @@ -0,0 +1,371 @@ +// -*- C++ -*- + +// Copyright (C) 2018-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bit + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_BIT +#define _GLIBCXX_BIT 1 + +#pragma GCC system_header + +#if __cplusplus >= 201402L + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup bit_manip Bit manipulation + * @ingroup numerics + * + * Utilities for examining and manipulating individual bits. + * + * @{ + */ + + /// @cond undoc + + template + constexpr _Tp + __rotl(_Tp __x, int __s) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x << __r) | (__x >> ((_Nd - __r) % _Nd)); + else + return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r) + } + + template + constexpr _Tp + __rotr(_Tp __x, int __s) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x >> __r) | (__x << ((_Nd - __r) % _Nd)); + else + return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r) + } + + template + constexpr int + __countl_zero(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + if (__x == 0) + return _Nd; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + { + constexpr int __diff = _Nd_u - _Nd; + return __builtin_clz(__x) - __diff; + } + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + { + constexpr int __diff = _Nd_ul - _Nd; + return __builtin_clzl(__x) - __diff; + } + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + { + constexpr int __diff = _Nd_ull - _Nd; + return __builtin_clzll(__x) - __diff; + } + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + unsigned long long __high = __x >> _Nd_ull; + if (__high != 0) + { + constexpr int __diff = (2 * _Nd_ull) - _Nd; + return __builtin_clzll(__high) - __diff; + } + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + return (_Nd - _Nd_ull) + __builtin_clzll(__low); + } + } + + template + constexpr int + __countl_one(_Tp __x) noexcept + { + if (__x == __gnu_cxx::__int_traits<_Tp>::__max) + return __gnu_cxx::__int_traits<_Tp>::__digits; + return std::__countl_zero<_Tp>((_Tp)~__x); + } + + template + constexpr int + __countr_zero(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + if (__x == 0) + return _Nd; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + return __builtin_ctz(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + return __builtin_ctzl(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + return __builtin_ctzll(__x); + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + if (__low != 0) + return __builtin_ctzll(__low); + unsigned long long __high = __x >> _Nd_ull; + return __builtin_ctzll(__high) + _Nd_ull; + } + } + + template + constexpr int + __countr_one(_Tp __x) noexcept + { + if (__x == __gnu_cxx::__int_traits<_Tp>::__max) + return __gnu_cxx::__int_traits<_Tp>::__digits; + return std::__countr_zero((_Tp)~__x); + } + + template + constexpr int + __popcount(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + if (__x == 0) + return 0; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + return __builtin_popcount(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + return __builtin_popcountl(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + return __builtin_popcountll(__x); + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + unsigned long long __high = __x >> _Nd_ull; + return __builtin_popcountll(__low) + __builtin_popcountll(__high); + } + } + + template + constexpr bool + __has_single_bit(_Tp __x) noexcept + { return std::__popcount(__x) == 1; } + + template + constexpr _Tp + __bit_ceil(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + if (__x == 0 || __x == 1) + return 1; + auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u)); + // If the shift exponent equals _Nd then the correct result is not + // representable as a value of _Tp, and so the result is undefined. + // Want that undefined behaviour to be detected in constant expressions, + // by UBSan, and by debug assertions. +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (!__builtin_is_constant_evaluated()) + { + __glibcxx_assert( __shift_exponent != __int_traits<_Tp>::__digits ); + } +#endif + using __promoted_type = decltype(__x << 1); + if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) + { + // If __x undergoes integral promotion then shifting by _Nd is + // not undefined. In order to make the shift undefined, so that + // it is diagnosed in constant expressions and by UBsan, we also + // need to "promote" the shift exponent to be too large for the + // promoted type. + const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2; + __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp; + } + return (_Tp)1u << __shift_exponent; + } + + template + constexpr _Tp + __bit_floor(_Tp __x) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + if (__x == 0) + return 0; + return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x >> 1))); + } + + template + constexpr _Tp + __bit_width(_Tp __x) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + return _Nd - std::__countl_zero(__x); + } + + /// @endcond + +#if __cplusplus > 201703L + +#define __cpp_lib_bitops 201907L + + /// @cond undoc + template + using _If_is_unsigned_integer + = enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>; + /// @endcond + + // [bit.rot], rotating + + /// Rotate `x` to the left by `s` bits. + template + [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> + rotl(_Tp __x, int __s) noexcept + { return std::__rotl(__x, __s); } + + /// Rotate `x` to the right by `s` bits. + template + [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> + rotr(_Tp __x, int __s) noexcept + { return std::__rotr(__x, __s); } + + // [bit.count], counting + + /// The number of contiguous zero bits, starting from the highest bit. + template + constexpr _If_is_unsigned_integer<_Tp, int> + countl_zero(_Tp __x) noexcept + { return std::__countl_zero(__x); } + + /// The number of contiguous one bits, starting from the highest bit. + template + constexpr _If_is_unsigned_integer<_Tp, int> + countl_one(_Tp __x) noexcept + { return std::__countl_one(__x); } + + /// The number of contiguous zero bits, starting from the lowest bit. + template + constexpr _If_is_unsigned_integer<_Tp, int> + countr_zero(_Tp __x) noexcept + { return std::__countr_zero(__x); } + + /// The number of contiguous one bits, starting from the lowest bit. + template + constexpr _If_is_unsigned_integer<_Tp, int> + countr_one(_Tp __x) noexcept + { return std::__countr_one(__x); } + + /// The number of bits set in `x`. + template + constexpr _If_is_unsigned_integer<_Tp, int> + popcount(_Tp __x) noexcept + { return std::__popcount(__x); } + + // [bit.pow.two], integral powers of 2 + +#define __cpp_lib_int_pow2 202002L + + /// True if `x` is a power of two, false otherwise. + template + constexpr _If_is_unsigned_integer<_Tp, bool> + has_single_bit(_Tp __x) noexcept + { return std::__has_single_bit(__x); } + + /// The smallest power-of-two not less than `x`. + template + constexpr _If_is_unsigned_integer<_Tp> + bit_ceil(_Tp __x) noexcept + { return std::__bit_ceil(__x); } + + /// The largest power-of-two not greater than `x`. + template + constexpr _If_is_unsigned_integer<_Tp> + bit_floor(_Tp __x) noexcept + { return std::__bit_floor(__x); } + + /// The smallest integer greater than the base-2 logarithm of `x`. + template + constexpr _If_is_unsigned_integer<_Tp> + bit_width(_Tp __x) noexcept + { return std::__bit_width(__x); } + +#define __cpp_lib_endian 201907L + + /// Byte order + enum class endian + { + little = __ORDER_LITTLE_ENDIAN__, + big = __ORDER_BIG_ENDIAN__, + native = __BYTE_ORDER__ + }; +#endif // C++2a + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 +#endif // _GLIBCXX_BIT diff --git a/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h b/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h new file mode 100644 index 000000000..de0bd44f6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h @@ -0,0 +1,963 @@ +// Forward declarations -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/algorithmfwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _GLIBCXX_ALGORITHMFWD_H +#define _GLIBCXX_ALGORITHMFWD_H 1 + +#pragma GCC system_header + +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /* + adjacent_find + all_of (C++11) + any_of (C++11) + binary_search + clamp (C++17) + copy + copy_backward + copy_if (C++11) + copy_n (C++11) + count + count_if + equal + equal_range + fill + fill_n + find + find_end + find_first_of + find_if + find_if_not (C++11) + for_each + generate + generate_n + includes + inplace_merge + is_heap (C++11) + is_heap_until (C++11) + is_partitioned (C++11) + is_sorted (C++11) + is_sorted_until (C++11) + iter_swap + lexicographical_compare + lower_bound + make_heap + max + max_element + merge + min + min_element + minmax (C++11) + minmax_element (C++11) + mismatch + next_permutation + none_of (C++11) + nth_element + partial_sort + partial_sort_copy + partition + partition_copy (C++11) + partition_point (C++11) + pop_heap + prev_permutation + push_heap + random_shuffle + remove + remove_copy + remove_copy_if + remove_if + replace + replace_copy + replace_copy_if + replace_if + reverse + reverse_copy + rotate + rotate_copy + search + search_n + set_difference + set_intersection + set_symmetric_difference + set_union + shuffle (C++11) + sort + sort_heap + stable_partition + stable_sort + swap + swap_ranges + transform + unique + unique_copy + upper_bound + */ + + /** + * @defgroup algorithms Algorithms + * + * Components for performing algorithmic operations. Includes + * non-modifying sequence, modifying (mutating) sequence, sorting, + * searching, merge, partition, heap, set, minima, maxima, and + * permutation operations. + */ + + /** + * @defgroup mutating_algorithms Mutating + * @ingroup algorithms + */ + + /** + * @defgroup non_mutating_algorithms Non-Mutating + * @ingroup algorithms + */ + + /** + * @defgroup sorting_algorithms Sorting + * @ingroup algorithms + */ + + /** + * @defgroup set_algorithms Set Operations + * @ingroup sorting_algorithms + * + * These algorithms are common set operations performed on sequences + * that are already sorted. The number of comparisons will be + * linear. + */ + + /** + * @defgroup binary_search_algorithms Binary Search + * @ingroup sorting_algorithms + * + * These algorithms are variations of a classic binary search, and + * all assume that the sequence being searched is already sorted. + * + * The number of comparisons will be logarithmic (and as few as + * possible). The number of steps through the sequence will be + * logarithmic for random-access iterators (e.g., pointers), and + * linear otherwise. + * + * The LWG has passed Defect Report 270, which notes: The + * proposed resolution reinterprets binary search. Instead of + * thinking about searching for a value in a sorted range, we view + * that as an important special case of a more general algorithm: + * searching for the partition point in a partitioned range. We + * also add a guarantee that the old wording did not: we ensure that + * the upper bound is no earlier than the lower bound, that the pair + * returned by equal_range is a valid range, and that the first part + * of that pair is the lower bound. + * + * The actual effect of the first sentence is that a comparison + * functor passed by the user doesn't necessarily need to induce a + * strict weak ordering relation. Rather, it partitions the range. + */ + + // adjacent_find + +#if __cplusplus > 201703L +# define __cpp_lib_constexpr_algorithms 201806L +#endif + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + all_of(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + any_of(_IIter, _IIter, _Predicate); +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_FIter, _FIter, const _Tp&, _Compare); + +#if __cplusplus > 201402L + template + _GLIBCXX14_CONSTEXPR + const _Tp& + clamp(const _Tp&, const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + clamp(const _Tp&, const _Tp&, const _Tp&, _Compare); +#endif + + template + _GLIBCXX20_CONSTEXPR + _OIter + copy(_IIter, _IIter, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _BIter2 + copy_backward(_BIter1, _BIter1, _BIter2); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + _OIter + copy_if(_IIter, _IIter, _OIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + copy_n(_IIter, _Size, _OIter); +#endif + + // count + // count_if + + template + _GLIBCXX20_CONSTEXPR + pair<_FIter, _FIter> + equal_range(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + pair<_FIter, _FIter> + equal_range(_FIter, _FIter, const _Tp&, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + fill(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + fill_n(_OIter, _Size, const _Tp&); + + // find + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_end(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_end(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + // find_first_of + // find_if + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + _IIter + find_if_not(_IIter, _IIter, _Predicate); +#endif + + // for_each + // generate + // generate_n + + template + _GLIBCXX20_CONSTEXPR + bool + includes(_IIter1, _IIter1, _IIter2, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); + + template + void + inplace_merge(_BIter, _BIter, _BIter); + + template + void + inplace_merge(_BIter, _BIter, _BIter, _Compare); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + is_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + bool + is_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + is_heap_until(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + is_heap_until(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + bool + is_partitioned(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + is_permutation(_FIter1, _FIter1, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + is_permutation(_FIter1, _FIter1, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + bool + is_sorted(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + bool + is_sorted(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _FIter + is_sorted_until(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + is_sorted_until(_FIter, _FIter, _Compare); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + iter_swap(_FIter1, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter + lower_bound(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + lower_bound(_FIter, _FIter, const _Tp&, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + make_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + make_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + max(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + max(const _Tp&, const _Tp&, _Compare); + + // max_element + // merge + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + min(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + min(const _Tp&, const _Tp&, _Compare); + + // min_element + +#if __cplusplus >= 201103L + template + _GLIBCXX14_CONSTEXPR + pair + minmax(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + pair + minmax(const _Tp&, const _Tp&, _Compare); + + template + _GLIBCXX14_CONSTEXPR + pair<_FIter, _FIter> + minmax_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + pair<_FIter, _FIter> + minmax_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _Tp + min(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + _Tp + min(initializer_list<_Tp>, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _Tp + max(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + _Tp + max(initializer_list<_Tp>, _Compare); + + template + _GLIBCXX14_CONSTEXPR + pair<_Tp, _Tp> + minmax(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + pair<_Tp, _Tp> + minmax(initializer_list<_Tp>, _Compare); +#endif + + // mismatch + + template + _GLIBCXX20_CONSTEXPR + bool + next_permutation(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + bool + next_permutation(_BIter, _BIter, _Compare); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + none_of(_IIter, _IIter, _Predicate); +#endif + + // nth_element + // partial_sort + + template + _GLIBCXX20_CONSTEXPR + _RAIter + partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter, _Compare); + + // partition + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + pair<_OIter1, _OIter2> + partition_copy(_IIter, _IIter, _OIter1, _OIter2, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _FIter + partition_point(_FIter, _FIter, _Predicate); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + pop_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + pop_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + bool + prev_permutation(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + bool + prev_permutation(_BIter, _BIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + push_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + push_heap(_RAIter, _RAIter, _Compare); + + // random_shuffle + + template + _GLIBCXX20_CONSTEXPR + _FIter + remove(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + remove_if(_FIter, _FIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + remove_copy(_IIter, _IIter, _OIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + remove_copy_if(_IIter, _IIter, _OIter, _Predicate); + + // replace + + template + _GLIBCXX20_CONSTEXPR + _OIter + replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&); + + // replace_if + + template + _GLIBCXX20_CONSTEXPR + void + reverse(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + reverse_copy(_BIter, _BIter, _OIter); + + inline namespace _V2 + { + template + _GLIBCXX20_CONSTEXPR + _FIter + rotate(_FIter, _FIter, _FIter); + } + + template + _GLIBCXX20_CONSTEXPR + _OIter + rotate_copy(_FIter, _FIter, _FIter, _OIter); + + // search + // search_n + // set_difference + // set_intersection + // set_symmetric_difference + // set_union + +#if (__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99_STDINT_TR1) + template + void + shuffle(_RAIter, _RAIter, _UGenerator&&); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + sort_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + sort_heap(_RAIter, _RAIter, _Compare); + + template + _BIter + stable_partition(_BIter, _BIter, _Predicate); + +#if __cplusplus < 201103L + // For C++11 swap() is declared in . + + template + _GLIBCXX20_CONSTEXPR + inline void + swap(_Tp& __a, _Tp& __b); + + template + _GLIBCXX20_CONSTEXPR + inline void + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]); +#endif + + template + _GLIBCXX20_CONSTEXPR + _FIter2 + swap_ranges(_FIter1, _FIter1, _FIter2); + + // transform + + template + _GLIBCXX20_CONSTEXPR + _FIter + unique(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + unique(_FIter, _FIter, _BinaryPredicate); + + // unique_copy + + template + _GLIBCXX20_CONSTEXPR + _FIter + upper_bound(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + upper_bound(_FIter, _FIter, const _Tp&, _Compare); + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + template + _GLIBCXX20_CONSTEXPR + _FIter + adjacent_find(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + adjacent_find(_FIter, _FIter, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_IIter>::difference_type + count(_IIter, _IIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_IIter>::difference_type + count_if(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + equal(_IIter1, _IIter1, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _IIter + find(_IIter, _IIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_first_of(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_first_of(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _IIter + find_if(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _Funct + for_each(_IIter, _IIter, _Funct); + + template + _GLIBCXX20_CONSTEXPR + void + generate(_FIter, _FIter, _Generator); + + template + _GLIBCXX20_CONSTEXPR + _OIter + generate_n(_OIter, _Size, _Generator); + + template + _GLIBCXX20_CONSTEXPR + bool + lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _FIter + max_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + _FIter + max_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _FIter + min_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + _FIter + min_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + pair<_IIter1, _IIter2> + mismatch(_IIter1, _IIter1, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + pair<_IIter1, _IIter2> + mismatch(_IIter1, _IIter1, _IIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + void + nth_element(_RAIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + nth_element(_RAIter, _RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + partial_sort(_RAIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + partial_sort(_RAIter, _RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _BIter + partition(_BIter, _BIter, _Predicate); + + template + void + random_shuffle(_RAIter, _RAIter); + + template + void + random_shuffle(_RAIter, _RAIter, +#if __cplusplus >= 201103L + _Generator&&); +#else + _Generator&); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + replace(_FIter, _FIter, const _Tp&, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + void + replace_if(_FIter, _FIter, _Predicate, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + search(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _FIter + search_n(_FIter, _FIter, _Size, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + search_n(_FIter, _FIter, _Size, const _Tp&, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, + _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + sort(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + sort(_RAIter, _RAIter, _Compare); + + template + void + stable_sort(_RAIter, _RAIter); + + template + void + stable_sort(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + transform(_IIter, _IIter, _OIter, _UnaryOperation); + + template + _GLIBCXX20_CONSTEXPR + _OIter + transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation); + + template + _GLIBCXX20_CONSTEXPR + _OIter + unique_copy(_IIter, _IIter, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate); + +_GLIBCXX_END_NAMESPACE_ALGO +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h b/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h new file mode 100644 index 000000000..86d8ed221 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h @@ -0,0 +1,743 @@ +// Allocator traits -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/alloc_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOC_TRAITS_H +#define _ALLOC_TRAITS_H 1 + +#include +#include +#if __cplusplus >= 201103L +# include +# include +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201103L +#define __cpp_lib_allocator_traits_is_always_equal 201411 + + struct __allocator_traits_base + { + template + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + + template + struct __rebind<_Tp, _Up, + __void_t::other>> + { using type = typename _Tp::template rebind<_Up>::other; }; + + protected: + template + using __pointer = typename _Tp::pointer; + template + using __c_pointer = typename _Tp::const_pointer; + template + using __v_pointer = typename _Tp::void_pointer; + template + using __cv_pointer = typename _Tp::const_void_pointer; + template + using __pocca = typename _Tp::propagate_on_container_copy_assignment; + template + using __pocma = typename _Tp::propagate_on_container_move_assignment; + template + using __pocs = typename _Tp::propagate_on_container_swap; + template + using __equal = typename _Tp::is_always_equal; + }; + + template + using __alloc_rebind + = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type; + + /** + * @brief Uniform interface to all allocator types. + * @ingroup allocators + */ + template + struct allocator_traits : __allocator_traits_base + { + /// The allocator type + typedef _Alloc allocator_type; + /// The allocated type + typedef typename _Alloc::value_type value_type; + + /** + * @brief The allocator's pointer type. + * + * @c Alloc::pointer if that type exists, otherwise @c value_type* + */ + using pointer = __detected_or_t; + + private: + // Select _Func<_Alloc> or pointer_traits::rebind<_Tp> + template class _Func, typename _Tp, typename = void> + struct _Ptr + { + using type = typename pointer_traits::template rebind<_Tp>; + }; + + template class _Func, typename _Tp> + struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> + { + using type = _Func<_Alloc>; + }; + + // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type + template + struct _Diff + { using type = typename pointer_traits<_PtrT>::difference_type; }; + + template + struct _Diff<_A2, _PtrT, __void_t> + { using type = typename _A2::difference_type; }; + + // Select _A2::size_type or make_unsigned<_DiffT>::type + template + struct _Size : make_unsigned<_DiffT> { }; + + template + struct _Size<_A2, _DiffT, __void_t> + { using type = typename _A2::size_type; }; + + public: + /** + * @brief The allocator's const pointer type. + * + * @c Alloc::const_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; + + /** + * @brief The allocator's void pointer type. + * + * @c Alloc::void_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using void_pointer = typename _Ptr<__v_pointer, void>::type; + + /** + * @brief The allocator's const void pointer type. + * + * @c Alloc::const_void_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; + + /** + * @brief The allocator's difference type + * + * @c Alloc::difference_type if that type exists, otherwise + * pointer_traits::difference_type + */ + using difference_type = typename _Diff<_Alloc, pointer>::type; + + /** + * @brief The allocator's size type + * + * @c Alloc::size_type if that type exists, otherwise + * make_unsigned::type + */ + using size_type = typename _Size<_Alloc, difference_type>::type; + + /** + * @brief How the allocator is propagated on copy assignment + * + * @c Alloc::propagate_on_container_copy_assignment if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_copy_assignment + = __detected_or_t; + + /** + * @brief How the allocator is propagated on move assignment + * + * @c Alloc::propagate_on_container_move_assignment if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_move_assignment + = __detected_or_t; + + /** + * @brief How the allocator is propagated on swap + * + * @c Alloc::propagate_on_container_swap if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_swap + = __detected_or_t; + + /** + * @brief Whether all instances of the allocator type compare equal. + * + * @c Alloc::is_always_equal if that type exists, + * otherwise @c is_empty::type + */ + using is_always_equal + = __detected_or_t::type, __equal, _Alloc>; + + template + using rebind_alloc = __alloc_rebind<_Alloc, _Tp>; + template + using rebind_traits = allocator_traits>; + + private: + template + static constexpr auto + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int) + -> decltype(__a.allocate(__n, __hint)) + { return __a.allocate(__n, __hint); } + + template + static constexpr pointer + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...) + { return __a.allocate(__n); } + + template + struct __construct_helper + { + template()->construct( + std::declval<_Tp*>(), std::declval<_Args>()...))> + static true_type __test(int); + + template + static false_type __test(...); + + using type = decltype(__test<_Alloc>(0)); + }; + + template + using __has_construct + = typename __construct_helper<_Tp, _Args...>::type; + + template + static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>> + _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) + noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...))) + { __a.construct(__p, std::forward<_Args>(__args)...); } + + template + static _GLIBCXX14_CONSTEXPR + _Require<__and_<__not_<__has_construct<_Tp, _Args...>>, + is_constructible<_Tp, _Args...>>> + _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value) + { +#if __cplusplus <= 201703L + ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); +#else + std::construct_at(__p, std::forward<_Args>(__args)...); +#endif + } + + template + static _GLIBCXX14_CONSTEXPR auto + _S_destroy(_Alloc2& __a, _Tp* __p, int) + noexcept(noexcept(__a.destroy(__p))) + -> decltype(__a.destroy(__p)) + { __a.destroy(__p); } + + template + static _GLIBCXX14_CONSTEXPR void + _S_destroy(_Alloc2&, _Tp* __p, ...) + noexcept(std::is_nothrow_destructible<_Tp>::value) + { std::_Destroy(__p); } + + template + static constexpr auto + _S_max_size(_Alloc2& __a, int) + -> decltype(__a.max_size()) + { return __a.max_size(); } + + template + static constexpr size_type + _S_max_size(_Alloc2&, ...) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2466. allocator_traits::max_size() default behavior is incorrect + return __gnu_cxx::__numeric_traits::__max + / sizeof(value_type); + } + + template + static constexpr auto + _S_select(_Alloc2& __a, int) + -> decltype(__a.select_on_container_copy_construction()) + { return __a.select_on_container_copy_construction(); } + + template + static constexpr _Alloc2 + _S_select(_Alloc2& __a, ...) + { return __a; } + + public: + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * + * Calls @c a.allocate(n) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(_Alloc& __a, size_type __n) + { return __a.allocate(__n); } + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * @param __hint Aid to locality. + * @return Memory of suitable size and alignment for @a n objects + * of type @c value_type + * + * Returns a.allocate(n, hint) if that expression is + * well-formed, otherwise returns @c a.allocate(n) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) + { return _S_allocate(__a, __n, __hint, 0); } + + /** + * @brief Deallocate memory. + * @param __a An allocator. + * @param __p Pointer to the memory to deallocate. + * @param __n The number of objects space was allocated for. + * + * Calls a.deallocate(p, n) + */ + static _GLIBCXX20_CONSTEXPR void + deallocate(_Alloc& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + /** + * @brief Construct an object of type @a _Tp + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for Tp + * @param __args Constructor arguments. + * + * Calls __a.construct(__p, std::forward(__args)...) + * if that expression is well-formed, otherwise uses placement-new + * to construct an object of type @a _Tp at location @a __p from the + * arguments @a __args... + */ + template + static _GLIBCXX20_CONSTEXPR auto + construct(_Alloc& __a, _Tp* __p, _Args&&... __args) + noexcept(noexcept(_S_construct(__a, __p, + std::forward<_Args>(__args)...))) + -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...)) + { _S_construct(__a, __p, std::forward<_Args>(__args)...); } + + /** + * @brief Destroy an object of type @a _Tp + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Calls @c __a.destroy(__p) if that expression is well-formed, + * otherwise calls @c __p->~_Tp() + */ + template + static _GLIBCXX20_CONSTEXPR void + destroy(_Alloc& __a, _Tp* __p) + noexcept(noexcept(_S_destroy(__a, __p, 0))) + { _S_destroy(__a, __p, 0); } + + /** + * @brief The maximum supported allocation size + * @param __a An allocator. + * @return @c __a.max_size() or @c numeric_limits::max() + * + * Returns @c __a.max_size() if that expression is well-formed, + * otherwise returns @c numeric_limits::max() + */ + static _GLIBCXX20_CONSTEXPR size_type + max_size(const _Alloc& __a) noexcept + { return _S_max_size(__a, 0); } + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return @c __rhs.select_on_container_copy_construction() or @a __rhs + * + * Returns @c __rhs.select_on_container_copy_construction() if that + * expression is well-formed, otherwise returns @a __rhs + */ + static _GLIBCXX20_CONSTEXPR _Alloc + select_on_container_copy_construction(const _Alloc& __rhs) + { return _S_select(__rhs, 0); } + }; + +#if __cplusplus > 201703L +# define __cpp_lib_constexpr_dynamic_alloc 201907L +#endif + + /// Partial specialization for std::allocator. + template + struct allocator_traits> + { + /// The allocator type + using allocator_type = allocator<_Tp>; + + /// The allocated type + using value_type = _Tp; + + /// The allocator's pointer type. + using pointer = _Tp*; + + /// The allocator's const pointer type. + using const_pointer = const _Tp*; + + /// The allocator's void pointer type. + using void_pointer = void*; + + /// The allocator's const void pointer type. + using const_void_pointer = const void*; + + /// The allocator's difference type + using difference_type = std::ptrdiff_t; + + /// The allocator's size type + using size_type = std::size_t; + + /// How the allocator is propagated on copy assignment + using propagate_on_container_copy_assignment = false_type; + + /// How the allocator is propagated on move assignment + using propagate_on_container_move_assignment = true_type; + + /// How the allocator is propagated on swap + using propagate_on_container_swap = false_type; + + /// Whether all instances of the allocator type compare equal. + using is_always_equal = true_type; + + template + using rebind_alloc = allocator<_Up>; + + template + using rebind_traits = allocator_traits>; + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * + * Calls @c a.allocate(n) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(allocator_type& __a, size_type __n) + { return __a.allocate(__n); } + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * @param __hint Aid to locality. + * @return Memory of suitable size and alignment for @a n objects + * of type @c value_type + * + * Returns a.allocate(n, hint) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) + { +#if __cplusplus <= 201703L + return __a.allocate(__n, __hint); +#else + return __a.allocate(__n); +#endif + } + + /** + * @brief Deallocate memory. + * @param __a An allocator. + * @param __p Pointer to the memory to deallocate. + * @param __n The number of objects space was allocated for. + * + * Calls a.deallocate(p, n) + */ + static _GLIBCXX20_CONSTEXPR void + deallocate(allocator_type& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + /** + * @brief Construct an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for + * an object of type `_Up`. + * @param __args Constructor arguments. + * + * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` + * in C++11, C++14 and C++17. Changed in C++20 to call + * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. + */ + template + static _GLIBCXX20_CONSTEXPR void + construct(allocator_type& __a __attribute__((__unused__)), _Up* __p, + _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { +#if __cplusplus <= 201703L + __a.construct(__p, std::forward<_Args>(__args)...); +#else + std::construct_at(__p, std::forward<_Args>(__args)...); +#endif + } + + /** + * @brief Destroy an object of type @a _Up + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Calls @c __a.destroy(__p). + */ + template + static _GLIBCXX20_CONSTEXPR void + destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p) + noexcept(is_nothrow_destructible<_Up>::value) + { +#if __cplusplus <= 201703L + __a.destroy(__p); +#else + std::destroy_at(__p); +#endif + } + + /** + * @brief The maximum supported allocation size + * @param __a An allocator. + * @return @c __a.max_size() + */ + static _GLIBCXX20_CONSTEXPR size_type + max_size(const allocator_type& __a __attribute__((__unused__))) noexcept + { +#if __cplusplus <= 201703L + return __a.max_size(); +#else + return size_t(-1) / sizeof(value_type); +#endif + } + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return @c __rhs + */ + static _GLIBCXX20_CONSTEXPR allocator_type + select_on_container_copy_construction(const allocator_type& __rhs) + { return __rhs; } + }; + +#if __cplusplus < 201703L + template + inline void + __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) + { __one = __two; } + + template + inline void + __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) + { } +#endif + + template + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_copy(_Alloc& __one, const _Alloc& __two) + { + typedef allocator_traits<_Alloc> __traits; + typedef typename __traits::propagate_on_container_copy_assignment __pocca; +#if __cplusplus >= 201703L + if constexpr (__pocca::value) + __one = __two; +#else + __do_alloc_on_copy(__one, __two, __pocca()); +#endif + } + + template + constexpr _Alloc + __alloc_on_copy(const _Alloc& __a) + { + typedef allocator_traits<_Alloc> __traits; + return __traits::select_on_container_copy_construction(__a); + } + +#if __cplusplus < 201703L + template + inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) + { __one = std::move(__two); } + + template + inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) + { } +#endif + + template + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_move(_Alloc& __one, _Alloc& __two) + { + typedef allocator_traits<_Alloc> __traits; + typedef typename __traits::propagate_on_container_move_assignment __pocma; +#if __cplusplus >= 201703L + if constexpr (__pocma::value) + __one = std::move(__two); +#else + __do_alloc_on_move(__one, __two, __pocma()); +#endif + } + +#if __cplusplus < 201703L + template + inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) + { + using std::swap; + swap(__one, __two); + } + + template + inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) + { } +#endif + + template + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_swap(_Alloc& __one, _Alloc& __two) + { + typedef allocator_traits<_Alloc> __traits; + typedef typename __traits::propagate_on_container_swap __pocs; +#if __cplusplus >= 201703L + if constexpr (__pocs::value) + { + using std::swap; + swap(__one, __two); + } +#else + __do_alloc_on_swap(__one, __two, __pocs()); +#endif + } + + template, + typename = void> + struct __is_alloc_insertable_impl + : false_type + { }; + + template + struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT, + __void_t::construct( + std::declval<_Alloc&>(), std::declval<_ValueT*>(), + std::declval<_Tp>()))>> + : true_type + { }; + + // true if _Alloc::value_type is CopyInsertable into containers using _Alloc + // (might be wrong if _Alloc::construct exists but is not constrained, + // i.e. actually trying to use it would still be invalid. Use with caution.) + template + struct __is_copy_insertable + : __is_alloc_insertable_impl<_Alloc, + typename _Alloc::value_type const&>::type + { }; + + // std::allocator<_Tp> just requires CopyConstructible + template + struct __is_copy_insertable> + : is_copy_constructible<_Tp> + { }; + + // true if _Alloc::value_type is MoveInsertable into containers using _Alloc + // (might be wrong if _Alloc::construct exists but is not constrained, + // i.e. actually trying to use it would still be invalid. Use with caution.) + template + struct __is_move_insertable + : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type + { }; + + // std::allocator<_Tp> just requires MoveConstructible + template + struct __is_move_insertable> + : is_move_constructible<_Tp> + { }; + + // Trait to detect Allocator-like types. + template + struct __is_allocator : false_type { }; + + template + struct __is_allocator<_Alloc, + __void_t().allocate(size_t{}))>> + : true_type { }; + + template + using _RequireAllocator + = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type; + + template + using _RequireNotAllocator + = typename enable_if::value, _Alloc>::type; +#endif // C++11 + + /** + * Destroy a range of objects using the supplied allocator. For + * non-default allocators we do not optimize away invocation of + * destroy() even if _Tp has a trivial destructor. + */ + + template + void + _Destroy(_ForwardIterator __first, _ForwardIterator __last, + _Allocator& __alloc) + { + for (; __first != __last; ++__first) +#if __cplusplus < 201103L + __alloc.destroy(std::__addressof(*__first)); +#else + allocator_traits<_Allocator>::destroy(__alloc, + std::__addressof(*__first)); +#endif + } + + template + inline void + _Destroy(_ForwardIterator __first, _ForwardIterator __last, + allocator<_Tp>&) + { + _Destroy(__first, __last); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // _ALLOC_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h b/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h new file mode 100644 index 000000000..5058ab084 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h @@ -0,0 +1,104 @@ +// Guarded Allocation -*- C++ -*- + +// Copyright (C) 2014-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/allocated_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOCATED_PTR_H +#define _ALLOCATED_PTR_H 1 + +#if __cplusplus < 201103L +# include +#else +# include +# include +# include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Non-standard RAII type for managing pointers obtained from allocators. + template + struct __allocated_ptr + { + using pointer = typename allocator_traits<_Alloc>::pointer; + using value_type = typename allocator_traits<_Alloc>::value_type; + + /// Take ownership of __ptr + __allocated_ptr(_Alloc& __a, pointer __ptr) noexcept + : _M_alloc(std::__addressof(__a)), _M_ptr(__ptr) + { } + + /// Convert __ptr to allocator's pointer type and take ownership of it + template>> + __allocated_ptr(_Alloc& __a, _Ptr __ptr) + : _M_alloc(std::__addressof(__a)), + _M_ptr(pointer_traits::pointer_to(*__ptr)) + { } + + /// Transfer ownership of the owned pointer + __allocated_ptr(__allocated_ptr&& __gd) noexcept + : _M_alloc(__gd._M_alloc), _M_ptr(__gd._M_ptr) + { __gd._M_ptr = nullptr; } + + /// Deallocate the owned pointer + ~__allocated_ptr() + { + if (_M_ptr != nullptr) + std::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1); + } + + /// Release ownership of the owned pointer + __allocated_ptr& + operator=(std::nullptr_t) noexcept + { + _M_ptr = nullptr; + return *this; + } + + /// Get the address that the owned pointer refers to. + value_type* get() { return std::__to_address(_M_ptr); } + + private: + _Alloc* _M_alloc; + pointer _M_ptr; + }; + + /// Allocate space for a single object using __a + template + __allocated_ptr<_Alloc> + __allocate_guarded(_Alloc& __a) + { + return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) }; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/allocator.h b/resources/sources/avr-libstdcpp/include/bits/allocator.h new file mode 100644 index 000000000..d224aa3ec --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/allocator.h @@ -0,0 +1,323 @@ +// Allocators -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/allocator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOCATOR_H +#define _ALLOCATOR_H 1 + +#include // Define the base class to std::allocator. +#include +#if __cplusplus >= 201103L +#include +#endif + +#define __cpp_lib_incomplete_container_elements 201505 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup allocators + * @{ + */ + + /// allocator specialization. + template<> + class allocator + { + public: + typedef void value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; +#if __cplusplus <= 201703L + typedef void* pointer; + typedef const void* const_pointer; + + template + struct rebind + { typedef allocator<_Tp1> other; }; +#else + allocator() = default; + + template + constexpr + allocator(const allocator<_Up>&) { } +#endif // ! C++20 + +#if __cplusplus >= 201103L && __cplusplus <= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. std::allocator propagate_on_container_move_assignment + typedef true_type propagate_on_container_move_assignment; + + typedef true_type is_always_equal; + + template + void + construct(_Up* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } + + template + void + destroy(_Up* __p) + noexcept(std::is_nothrow_destructible<_Up>::value) + { __p->~_Up(); } +#endif // C++11 to C++17 + }; + + /** + * @brief The @a standard allocator, as per [20.4]. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.allocator + * for further details. + * + * @tparam _Tp Type of allocated object. + */ + template + class allocator : public __allocator_base<_Tp> + { + public: + typedef _Tp value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; +#if __cplusplus <= 201703L + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + + template + struct rebind + { typedef allocator<_Tp1> other; }; +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. std::allocator propagate_on_container_move_assignment + typedef true_type propagate_on_container_move_assignment; + + typedef true_type is_always_equal; +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3035. std::allocator's constructors should be constexpr + _GLIBCXX20_CONSTEXPR + allocator() _GLIBCXX_NOTHROW { } + + _GLIBCXX20_CONSTEXPR + allocator(const allocator& __a) _GLIBCXX_NOTHROW + : __allocator_base<_Tp>(__a) { } + +#if __cplusplus >= 201103L + // Avoid implicit deprecation. + allocator& operator=(const allocator&) = default; +#endif + + template + _GLIBCXX20_CONSTEXPR + allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { } + +#if __cpp_constexpr_dynamic_alloc + constexpr +#endif + ~allocator() _GLIBCXX_NOTHROW { } + +#if __cplusplus > 201703L + [[nodiscard,__gnu__::__always_inline__]] + constexpr _Tp* + allocate(size_t __n) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); +#endif + return __allocator_base<_Tp>::allocate(__n, 0); + } + + [[__gnu__::__always_inline__]] + constexpr void + deallocate(_Tp* __p, size_t __n) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + ::operator delete(__p); + return; + } +#endif + __allocator_base<_Tp>::deallocate(__p, __n); + } +#endif // C++20 + + friend _GLIBCXX20_CONSTEXPR bool + operator==(const allocator&, const allocator&) _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + friend _GLIBCXX20_CONSTEXPR bool + operator!=(const allocator&, const allocator&) _GLIBCXX_NOTHROW + { return false; } +#endif + + // Inherit everything else. + }; + + template + inline _GLIBCXX20_CONSTEXPR bool + operator==(const allocator<_T1>&, const allocator<_T2>&) + _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline _GLIBCXX20_CONSTEXPR bool + operator!=(const allocator<_T1>&, const allocator<_T2>&) + _GLIBCXX_NOTHROW + { return false; } +#endif + + // Invalid allocator partial specializations. + // allocator_traits::rebind_alloc can be used to form a valid allocator type. + template + class allocator + { + public: + typedef _Tp value_type; + template allocator(const allocator<_Up>&) { } + }; + + template + class allocator + { + public: + typedef _Tp value_type; + template allocator(const allocator<_Up>&) { } + }; + + template + class allocator + { + public: + typedef _Tp value_type; + template allocator(const allocator<_Up>&) { } + }; + + /// @} group allocator + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. +#if _GLIBCXX_EXTERN_TEMPLATE + extern template class allocator; + extern template class allocator; +#endif + + // Undefine. +#undef __allocator_base + + // To implement Option 3 of DR 431. + template + struct __alloc_swap + { static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } }; + + template + struct __alloc_swap<_Alloc, false> + { + static void + _S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT + { + // Precondition: swappable allocators. + if (__one != __two) + swap(__one, __two); + } + }; + + // Optimize for stateless allocators. + template + struct __alloc_neq + { + static bool + _S_do_it(const _Alloc&, const _Alloc&) + { return false; } + }; + + template + struct __alloc_neq<_Alloc, false> + { + static bool + _S_do_it(const _Alloc& __one, const _Alloc& __two) + { return __one != __two; } + }; + +#if __cplusplus >= 201103L + template, + is_nothrow_move_constructible>::value> + struct __shrink_to_fit_aux + { static bool _S_do_it(_Tp&) noexcept { return false; } }; + + template + struct __shrink_to_fit_aux<_Tp, true> + { + static bool + _S_do_it(_Tp& __c) noexcept + { +#if __cpp_exceptions + try + { + _Tp(__make_move_if_noexcept_iterator(__c.begin()), + __make_move_if_noexcept_iterator(__c.end()), + __c.get_allocator()).swap(__c); + return true; + } + catch(...) + { return false; } +#else + return false; +#endif + } + }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/atomic_base.h b/resources/sources/avr-libstdcpp/include/bits/atomic_base.h new file mode 100644 index 000000000..b11de1edf --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/atomic_base.h @@ -0,0 +1,1724 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/atomic_base.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{atomic} + */ + +#ifndef _GLIBCXX_ATOMIC_BASE_H +#define _GLIBCXX_ATOMIC_BASE_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include + +#ifndef _GLIBCXX_ALWAYS_INLINE +#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup atomics Atomics + * + * Components for performing atomic operations. + * @{ + */ + + /// Enumeration for memory_order +#if __cplusplus > 201703L + enum class memory_order : int + { + relaxed, + consume, + acquire, + release, + acq_rel, + seq_cst + }; + + inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; + inline constexpr memory_order memory_order_consume = memory_order::consume; + inline constexpr memory_order memory_order_acquire = memory_order::acquire; + inline constexpr memory_order memory_order_release = memory_order::release; + inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; + inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; +#else + typedef enum memory_order + { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst + } memory_order; +#endif + + enum __memory_order_modifier + { + __memory_order_mask = 0x0ffff, + __memory_order_modifier_mask = 0xffff0000, + __memory_order_hle_acquire = 0x10000, + __memory_order_hle_release = 0x20000 + }; + + constexpr memory_order + operator|(memory_order __m, __memory_order_modifier __mod) + { + return memory_order(int(__m) | int(__mod)); + } + + constexpr memory_order + operator&(memory_order __m, __memory_order_modifier __mod) + { + return memory_order(int(__m) & int(__mod)); + } + + // Drop release ordering as per [atomics.types.operations.req]/21 + constexpr memory_order + __cmpexch_failure_order2(memory_order __m) noexcept + { + return __m == memory_order_acq_rel ? memory_order_acquire + : __m == memory_order_release ? memory_order_relaxed : __m; + } + + constexpr memory_order + __cmpexch_failure_order(memory_order __m) noexcept + { + return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask) + | __memory_order_modifier(__m & __memory_order_modifier_mask)); + } + + _GLIBCXX_ALWAYS_INLINE void + atomic_thread_fence(memory_order __m) noexcept + { __atomic_thread_fence(int(__m)); } + + _GLIBCXX_ALWAYS_INLINE void + atomic_signal_fence(memory_order __m) noexcept + { __atomic_signal_fence(int(__m)); } + + /// kill_dependency + template + inline _Tp + kill_dependency(_Tp __y) noexcept + { + _Tp __ret(__y); + return __ret; + } + + + // Base types for atomics. + template + struct __atomic_base; + +#if __cplusplus <= 201703L +# define _GLIBCXX20_INIT(I) +#else +# define __cpp_lib_atomic_value_initialization 201911L +# define _GLIBCXX20_INIT(I) = I +#endif + +#define ATOMIC_VAR_INIT(_VI) { _VI } + + template + struct atomic; + + template + struct atomic<_Tp*>; + + /* The target's "set" value for test-and-set may not be exactly 1. */ +#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1 + typedef bool __atomic_flag_data_type; +#else + typedef unsigned char __atomic_flag_data_type; +#endif + + /** + * @brief Base type for atomic_flag. + * + * Base type is POD with data, allowing atomic_flag to derive from + * it and meet the standard layout type requirement. In addition to + * compatibility with a C interface, this allows different + * implementations of atomic_flag to use the same atomic operation + * functions, via a standard conversion to the __atomic_flag_base + * argument. + */ + _GLIBCXX_BEGIN_EXTERN_C + + struct __atomic_flag_base + { + __atomic_flag_data_type _M_i _GLIBCXX20_INIT({}); + }; + + _GLIBCXX_END_EXTERN_C + +#define ATOMIC_FLAG_INIT { 0 } + + /// atomic_flag + struct atomic_flag : public __atomic_flag_base + { + atomic_flag() noexcept = default; + ~atomic_flag() noexcept = default; + atomic_flag(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) volatile = delete; + + // Conversion to ATOMIC_FLAG_INIT. + constexpr atomic_flag(bool __i) noexcept + : __atomic_flag_base{ _S_init(__i) } + { } + + _GLIBCXX_ALWAYS_INLINE bool + test_and_set(memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_test_and_set (&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_test_and_set (&_M_i, int(__m)); + } + +#if __cplusplus > 201703L +#define __cpp_lib_atomic_flag_test 201907L + + _GLIBCXX_ALWAYS_INLINE bool + test(memory_order __m = memory_order_seq_cst) const noexcept + { + __atomic_flag_data_type __v; + __atomic_load(&_M_i, &__v, int(__m)); + return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; + } + + _GLIBCXX_ALWAYS_INLINE bool + test(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + __atomic_flag_data_type __v; + __atomic_load(&_M_i, &__v, int(__m)); + return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; + } + +#endif // C++20 + + _GLIBCXX_ALWAYS_INLINE void + clear(memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_consume); + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + + __atomic_clear (&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + clear(memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_consume); + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + + __atomic_clear (&_M_i, int(__m)); + } + + private: + static constexpr __atomic_flag_data_type + _S_init(bool __i) + { return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; } + }; + + + /// Base class for atomic integrals. + // + // For each of the integral types, define atomic_[integral type] struct + // + // atomic_bool bool + // atomic_char char + // atomic_schar signed char + // atomic_uchar unsigned char + // atomic_short short + // atomic_ushort unsigned short + // atomic_int int + // atomic_uint unsigned int + // atomic_long long + // atomic_ulong unsigned long + // atomic_llong long long + // atomic_ullong unsigned long long + // atomic_char8_t char8_t + // atomic_char16_t char16_t + // atomic_char32_t char32_t + // atomic_wchar_t wchar_t + // + // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or + // 8 bytes, since that is what GCC built-in functions for atomic + // memory access expect. + template + struct __atomic_base + { + using value_type = _ITp; + using difference_type = value_type; + + private: + typedef _ITp __int_type; + + static constexpr int _S_alignment = + sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp); + + alignas(_S_alignment) __int_type _M_i _GLIBCXX20_INIT(0); + + public: + __atomic_base() noexcept = default; + ~__atomic_base() noexcept = default; + __atomic_base(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) volatile = delete; + + // Requires __int_type convertible to _M_i. + constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { } + + operator __int_type() const noexcept + { return load(); } + + operator __int_type() const volatile noexcept + { return load(); } + + __int_type + operator=(__int_type __i) noexcept + { + store(__i); + return __i; + } + + __int_type + operator=(__int_type __i) volatile noexcept + { + store(__i); + return __i; + } + + __int_type + operator++(int) noexcept + { return fetch_add(1); } + + __int_type + operator++(int) volatile noexcept + { return fetch_add(1); } + + __int_type + operator--(int) noexcept + { return fetch_sub(1); } + + __int_type + operator--(int) volatile noexcept + { return fetch_sub(1); } + + __int_type + operator++() noexcept + { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator++() volatile noexcept + { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator--() noexcept + { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator--() volatile noexcept + { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator+=(__int_type __i) noexcept + { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator+=(__int_type __i) volatile noexcept + { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator-=(__int_type __i) noexcept + { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator-=(__int_type __i) volatile noexcept + { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator&=(__int_type __i) noexcept + { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator&=(__int_type __i) volatile noexcept + { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator|=(__int_type __i) noexcept + { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator|=(__int_type __i) volatile noexcept + { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator^=(__int_type __i) noexcept + { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator^=(__int_type __i) volatile noexcept + { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + bool + is_lock_free() const noexcept + { + // Use a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + bool + is_lock_free() const volatile noexcept + { + // Use a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + exchange(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_exchange_n(&_M_i, __i, int(__m)); + } + + + _GLIBCXX_ALWAYS_INLINE __int_type + exchange(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_exchange_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m1, memory_order __m2) noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_weak(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_weak(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m1, memory_order __m2) noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_strong(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_strong(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_add(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_add(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_add(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_add(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_sub(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_sub(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_and(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_and(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_and(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_and(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_or(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_or(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_or(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_or(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_xor(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_xor(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } + }; + + + /// Partial specialization for pointer types. + template + struct __atomic_base<_PTp*> + { + private: + typedef _PTp* __pointer_type; + + __pointer_type _M_p _GLIBCXX20_INIT(nullptr); + + // Factored out to facilitate explicit specialization. + constexpr ptrdiff_t + _M_type_size(ptrdiff_t __d) const { return __d * sizeof(_PTp); } + + constexpr ptrdiff_t + _M_type_size(ptrdiff_t __d) const volatile { return __d * sizeof(_PTp); } + + public: + __atomic_base() noexcept = default; + ~__atomic_base() noexcept = default; + __atomic_base(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) volatile = delete; + + // Requires __pointer_type convertible to _M_p. + constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { } + + operator __pointer_type() const noexcept + { return load(); } + + operator __pointer_type() const volatile noexcept + { return load(); } + + __pointer_type + operator=(__pointer_type __p) noexcept + { + store(__p); + return __p; + } + + __pointer_type + operator=(__pointer_type __p) volatile noexcept + { + store(__p); + return __p; + } + + __pointer_type + operator++(int) noexcept + { return fetch_add(1); } + + __pointer_type + operator++(int) volatile noexcept + { return fetch_add(1); } + + __pointer_type + operator--(int) noexcept + { return fetch_sub(1); } + + __pointer_type + operator--(int) volatile noexcept + { return fetch_sub(1); } + + __pointer_type + operator++() noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator++() volatile noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator--() noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator--() volatile noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator+=(ptrdiff_t __d) noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator+=(ptrdiff_t __d) volatile noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator-=(ptrdiff_t __d) noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator-=(ptrdiff_t __d) volatile noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + bool + is_lock_free() const noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_p), + reinterpret_cast(-__alignof(_M_p))); + } + + bool + is_lock_free() const volatile noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_p), + reinterpret_cast(-__alignof(_M_p))); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b = __m & __memory_order_mask; + + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_exchange_n(&_M_p, __p, int(__m)); + } + + + _GLIBCXX_ALWAYS_INLINE __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_exchange_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } + }; + +#if __cplusplus > 201703L + // Implementation details of atomic_ref and atomic. + namespace __atomic_impl + { + // Remove volatile and create a non-deduced context for value arguments. + template + using _Val = remove_volatile_t<_Tp>; + + // As above, but for difference_type arguments. + template + using _Diff = conditional_t, ptrdiff_t, _Val<_Tp>>; + + template + _GLIBCXX_ALWAYS_INLINE bool + is_lock_free() noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(_Size, reinterpret_cast(-_Align)); + } + + template + _GLIBCXX_ALWAYS_INLINE void + store(_Tp* __ptr, _Val<_Tp> __t, memory_order __m) noexcept + { __atomic_store(__ptr, std::__addressof(__t), int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Val<_Tp> + load(const _Tp* __ptr, memory_order __m) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); + __atomic_load(__ptr, __dest, int(__m)); + return *__dest; + } + + template + _GLIBCXX_ALWAYS_INLINE _Val<_Tp> + exchange(_Tp* __ptr, _Val<_Tp> __desired, memory_order __m) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); + __atomic_exchange(__ptr, std::__addressof(__desired), __dest, int(__m)); + return *__dest; + } + + template + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(_Tp* __ptr, _Val<_Tp>& __expected, + _Val<_Tp> __desired, memory_order __success, + memory_order __failure) noexcept + { + return __atomic_compare_exchange(__ptr, std::__addressof(__expected), + std::__addressof(__desired), true, + int(__success), int(__failure)); + } + + template + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(_Tp* __ptr, _Val<_Tp>& __expected, + _Val<_Tp> __desired, memory_order __success, + memory_order __failure) noexcept + { + return __atomic_compare_exchange(__ptr, std::__addressof(__expected), + std::__addressof(__desired), false, + int(__success), int(__failure)); + } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_add(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_add(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_sub(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_sub(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_and(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_and(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_or(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_or(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_xor(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_xor(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __add_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept + { return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __sub_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept + { return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __and_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_and_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __or_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_or_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __xor_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_xor_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _Tp + __fetch_add_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval + __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, + memory_order_relaxed)) + __newval = __oldval + __i; + return __oldval; + } + + template + _Tp + __fetch_sub_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval - __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, + memory_order_relaxed)) + __newval = __oldval - __i; + return __oldval; + } + + template + _Tp + __add_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval + __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, + memory_order_seq_cst, + memory_order_relaxed)) + __newval = __oldval + __i; + return __newval; + } + + template + _Tp + __sub_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval - __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, + memory_order_seq_cst, + memory_order_relaxed)) + __newval = __oldval - __i; + return __newval; + } + } // namespace __atomic_impl + + // base class for atomic + template + struct __atomic_float + { + static_assert(is_floating_point_v<_Fp>); + + static constexpr size_t _S_alignment = __alignof__(_Fp); + + public: + using value_type = _Fp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Fp), 0); + + __atomic_float() = default; + + constexpr + __atomic_float(_Fp __t) : _M_fp(__t) + { } + + __atomic_float(const __atomic_float&) = delete; + __atomic_float& operator=(const __atomic_float&) = delete; + __atomic_float& operator=(const __atomic_float&) volatile = delete; + + _Fp + operator=(_Fp __t) volatile noexcept + { + this->store(__t); + return __t; + } + + _Fp + operator=(_Fp __t) noexcept + { + this->store(__t); + return __t; + } + + bool + is_lock_free() const volatile noexcept + { return __atomic_impl::is_lock_free(); } + + bool + is_lock_free() const noexcept + { return __atomic_impl::is_lock_free(); } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) volatile noexcept + { __atomic_impl::store(&_M_fp, __t, __m); } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) noexcept + { __atomic_impl::store(&_M_fp, __t, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return __atomic_impl::load(&_M_fp, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(&_M_fp, __m); } + + operator _Fp() const volatile noexcept { return this->load(); } + operator _Fp() const noexcept { return this->load(); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::exchange(&_M_fp, __desired, __m); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::exchange(&_M_fp, __desired, __m); } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) noexcept + { + return __atomic_impl::compare_exchange_weak(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) volatile noexcept + { + return __atomic_impl::compare_exchange_weak(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) noexcept + { + return __atomic_impl::compare_exchange_strong(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) volatile noexcept + { + return __atomic_impl::compare_exchange_strong(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + volatile noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + volatile noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } + + value_type + operator+=(value_type __i) noexcept + { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } + + value_type + operator+=(value_type __i) volatile noexcept + { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } + + value_type + operator-=(value_type __i) noexcept + { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } + + value_type + operator-=(value_type __i) volatile noexcept + { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } + + private: + alignas(_S_alignment) _Fp _M_fp _GLIBCXX20_INIT(0); + }; +#undef _GLIBCXX20_INIT + + template, bool = is_floating_point_v<_Tp>> + struct __atomic_ref; + + // base class for non-integral, non-floating-point, non-pointer types + template + struct __atomic_ref<_Tp, false, false> + { + static_assert(is_trivially_copyable_v<_Tp>); + + // 1/2/4/8/16-byte types must be aligned to at least their size. + static constexpr int _S_min_alignment + = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 + ? 0 : sizeof(_Tp); + + public: + using value_type = _Tp; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Tp), 0); + + static constexpr size_t required_alignment + = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); + + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp& __t) : _M_ptr(std::__addressof(__t)) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp + operator=(_Tp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { return __atomic_impl::is_lock_free(); } + + void + store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp + exchange(_Tp __desired, memory_order __m = memory_order_seq_cst) + const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + private: + _Tp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Tp, true, false> + { + static_assert(is_integral_v<_Tp>); + + public: + using value_type = _Tp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Tp), 0); + + static constexpr size_t required_alignment + = sizeof(_Tp) > alignof(_Tp) ? sizeof(_Tp) : alignof(_Tp); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp& __t) : _M_ptr(&__t) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp + operator=(_Tp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp + exchange(_Tp __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_add(_M_ptr, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_sub(_M_ptr, __i, __m); } + + value_type + fetch_and(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_and(_M_ptr, __i, __m); } + + value_type + fetch_or(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_or(_M_ptr, __i, __m); } + + value_type + fetch_xor(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_xor(_M_ptr, __i, __m); } + + _GLIBCXX_ALWAYS_INLINE value_type + operator++(int) const noexcept + { return fetch_add(1); } + + _GLIBCXX_ALWAYS_INLINE value_type + operator--(int) const noexcept + { return fetch_sub(1); } + + value_type + operator++() const noexcept + { return __atomic_impl::__add_fetch(_M_ptr, value_type(1)); } + + value_type + operator--() const noexcept + { return __atomic_impl::__sub_fetch(_M_ptr, value_type(1)); } + + value_type + operator+=(value_type __i) const noexcept + { return __atomic_impl::__add_fetch(_M_ptr, __i); } + + value_type + operator-=(value_type __i) const noexcept + { return __atomic_impl::__sub_fetch(_M_ptr, __i); } + + value_type + operator&=(value_type __i) const noexcept + { return __atomic_impl::__and_fetch(_M_ptr, __i); } + + value_type + operator|=(value_type __i) const noexcept + { return __atomic_impl::__or_fetch(_M_ptr, __i); } + + value_type + operator^=(value_type __i) const noexcept + { return __atomic_impl::__xor_fetch(_M_ptr, __i); } + + private: + _Tp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Fp, false, true> + { + static_assert(is_floating_point_v<_Fp>); + + public: + using value_type = _Fp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Fp), 0); + + static constexpr size_t required_alignment = __alignof__(_Fp); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Fp& __t) : _M_ptr(&__t) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Fp + operator=(_Fp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Fp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::__fetch_add_flt(_M_ptr, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::__fetch_sub_flt(_M_ptr, __i, __m); } + + value_type + operator+=(value_type __i) const noexcept + { return __atomic_impl::__add_fetch_flt(_M_ptr, __i); } + + value_type + operator-=(value_type __i) const noexcept + { return __atomic_impl::__sub_fetch_flt(_M_ptr, __i); } + + private: + _Fp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Tp*, false, false> + { + public: + using value_type = _Tp*; + using difference_type = ptrdiff_t; + + static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; + + static constexpr size_t required_alignment = __alignof__(_Tp*); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp*& __t) : _M_ptr(std::__addressof(__t)) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp* + operator=(_Tp* __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp*() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Tp* __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp* + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp* + exchange(_Tp* __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp*& __expected, _Tp* __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Tp*& __expected, _Tp* __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Tp*& __expected, _Tp* __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp*& __expected, _Tp* __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + _GLIBCXX_ALWAYS_INLINE value_type + fetch_add(difference_type __d, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_add(_M_ptr, _S_type_size(__d), __m); } + + _GLIBCXX_ALWAYS_INLINE value_type + fetch_sub(difference_type __d, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_sub(_M_ptr, _S_type_size(__d), __m); } + + value_type + operator++(int) const noexcept + { return fetch_add(1); } + + value_type + operator--(int) const noexcept + { return fetch_sub(1); } + + value_type + operator++() const noexcept + { + return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(1)); + } + + value_type + operator--() const noexcept + { + return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(1)); + } + + value_type + operator+=(difference_type __d) const noexcept + { + return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(__d)); + } + + value_type + operator-=(difference_type __d) const noexcept + { + return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(__d)); + } + + private: + static constexpr ptrdiff_t + _S_type_size(ptrdiff_t __d) noexcept + { + static_assert(is_object_v<_Tp>); + return __d * sizeof(_Tp); + } + + _Tp** _M_ptr; + }; + +#endif // C++2a + + // @} group atomics + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h b/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h new file mode 100644 index 000000000..f0b57aeee --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h @@ -0,0 +1,66 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/atomic_lockfree_defines.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{atomic} + */ + +#ifndef _GLIBCXX_ATOMIC_LOCK_FREE_H +#define _GLIBCXX_ATOMIC_LOCK_FREE_H 1 + +#pragma GCC system_header + +/** + * @addtogroup atomics + * @{ + */ + +/** + * Lock-free property. + * + * 0 indicates that the types are never lock-free. + * 1 indicates that the types are sometimes lock-free. + * 2 indicates that the types are always lock-free. + */ + +#if __cplusplus >= 201103L +#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE +#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE +#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE +#ifdef _GLIBCXX_USE_CHAR8_T +#define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE +#endif +#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE +#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE +#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE +#endif + +// @} group atomics + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h b/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h new file mode 100644 index 000000000..f12c1bdc2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h @@ -0,0 +1,794 @@ +// -*- C++ -*- + +// Copyright (C) 2004-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +// + +/** @file bits/boost_concept_check.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +// GCC Note: based on version 1.12.0 of the Boost library. + +#ifndef _BOOST_CONCEPT_CHECK_H +#define _BOOST_CONCEPT_CHECK_H 1 + +#pragma GCC system_header + +#include +#include // for traits and tags + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" + +#define _IsUnused __attribute__ ((__unused__)) + +// When the C-C code is in use, we would like this function to do as little +// as possible at runtime, use as few resources as possible, and hopefully +// be elided out of existence... hmmm. +template +_GLIBCXX14_CONSTEXPR inline void __function_requires() +{ + void (_Concept::*__x)() _IsUnused = &_Concept::__constraints; +} + +// No definition: if this is referenced, there's a problem with +// the instantiating type not being one of the required integer types. +// Unfortunately, this results in a link-time error, not a compile-time error. +void __error_type_must_be_an_integer_type(); +void __error_type_must_be_an_unsigned_integer_type(); +void __error_type_must_be_a_signed_integer_type(); + +// ??? Should the "concept_checking*" structs begin with more than _ ? +#define _GLIBCXX_CLASS_REQUIRES(_type_var, _ns, _concept) \ + typedef void (_ns::_concept <_type_var>::* _func##_type_var##_concept)(); \ + template <_func##_type_var##_concept _Tp1> \ + struct _concept_checking##_type_var##_concept { }; \ + typedef _concept_checking##_type_var##_concept< \ + &_ns::_concept <_type_var>::__constraints> \ + _concept_checking_typedef##_type_var##_concept + +#define _GLIBCXX_CLASS_REQUIRES2(_type_var1, _type_var2, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2>::* _func##_type_var1##_type_var2##_concept)(); \ + template <_func##_type_var1##_type_var2##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_concept< \ + &_ns::_concept <_type_var1,_type_var2>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_concept + +#define _GLIBCXX_CLASS_REQUIRES3(_type_var1, _type_var2, _type_var3, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3>::* _func##_type_var1##_type_var2##_type_var3##_concept)(); \ + template <_func##_type_var1##_type_var2##_type_var3##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_type_var3##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_type_var3##_concept< \ + &_ns::_concept <_type_var1,_type_var2,_type_var3>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_concept + +#define _GLIBCXX_CLASS_REQUIRES4(_type_var1, _type_var2, _type_var3, _type_var4, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::* _func##_type_var1##_type_var2##_type_var3##_type_var4##_concept)(); \ + template <_func##_type_var1##_type_var2##_type_var3##_type_var4##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept< \ + &_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_type_var4##_concept + + +template +struct _Aux_require_same { }; + +template +struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; + + template + struct _SameTypeConcept + { + void __constraints() { + typedef typename _Aux_require_same<_Tp1, _Tp2>::_Type _Required; + } + }; + + template + struct _IntegerConcept { + void __constraints() { + __error_type_must_be_an_integer_type(); + } + }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints(){} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept + { void __constraints() {} }; + + template + struct _SignedIntegerConcept { + void __constraints() { + __error_type_must_be_a_signed_integer_type(); + } + }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints(){}}; + + template + struct _UnsignedIntegerConcept { + void __constraints() { + __error_type_must_be_an_unsigned_integer_type(); + } + }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + + //=========================================================================== + // Basic Concepts + + template + struct _DefaultConstructibleConcept + { + void __constraints() { + _Tp __a _IsUnused; // require default constructor + } + }; + + template + struct _AssignableConcept + { + void __constraints() { + __a = __a; // require assignment operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __b) { + __a = __b; // const required for argument to assignment + } + _Tp __a; + // possibly should be "Tp* a;" and then dereference "a" in constraint + // functions? present way would require a default ctor, i think... + }; + + template + struct _CopyConstructibleConcept + { + void __constraints() { + _Tp __a(__b); // require copy constructor + _Tp* __ptr _IsUnused = &__a; // require address of operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __a) { + _Tp __c _IsUnused(__a); // require const copy constructor + const _Tp* __ptr _IsUnused = &__a; // require const address of operator + } + _Tp __b; + }; + + // The SGI STL version of Assignable requires copy constructor and operator= + template + struct _SGIAssignableConcept + { + void __constraints() { + _Tp __b _IsUnused(__a); + __a = __a; // require assignment operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __b) { + _Tp __c _IsUnused(__b); + __a = __b; // const required for argument to assignment + } + _Tp __a; + }; + + template + struct _ConvertibleConcept + { + void __constraints() { + _To __y _IsUnused = __x; + } + _From __x; + }; + + // The C++ standard requirements for many concepts talk about return + // types that must be "convertible to bool". The problem with this + // requirement is that it leaves the door open for evil proxies that + // define things like operator|| with strange return types. Two + // possible solutions are: + // 1) require the return type to be exactly bool + // 2) stay with convertible to bool, and also + // specify stuff about all the logical operators. + // For now we just test for convertible to bool. + template + void __aux_require_boolean_expr(const _Tp& __t) { + bool __x _IsUnused = __t; + } + +// FIXME + template + struct _EqualityComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a == __b); + } + _Tp __a, __b; + }; + + template + struct _LessThanComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a < __b); + } + _Tp __a, __b; + }; + + // This is equivalent to SGI STL's LessThanComparable. + template + struct _ComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a < __b); + __aux_require_boolean_expr(__a > __b); + __aux_require_boolean_expr(__a <= __b); + __aux_require_boolean_expr(__a >= __b); + } + _Tp __a, __b; + }; + +#define _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(_OP,_NAME) \ + template \ + struct _NAME { \ + void __constraints() { (void)__constraints_(); } \ + bool __constraints_() { \ + return __a _OP __b; \ + } \ + _First __a; \ + _Second __b; \ + } + +#define _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \ + template \ + struct _NAME { \ + void __constraints() { (void)__constraints_(); } \ + _Ret __constraints_() { \ + return __a _OP __b; \ + } \ + _First __a; \ + _Second __b; \ + } + + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, _EqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, _NotEqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, _LessThanOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, _LessEqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, _GreaterThanOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, _GreaterEqualOpConcept); + + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, _PlusOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, _TimesOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, _DivideOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, _SubtractOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, _ModOpConcept); + +#undef _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT +#undef _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT + + //=========================================================================== + // Function Object Concepts + + template + struct _GeneratorConcept + { + void __constraints() { + const _Return& __r _IsUnused = __f();// require operator() member function + } + _Func __f; + }; + + + template + struct _GeneratorConcept<_Func,void> + { + void __constraints() { + __f(); // require operator() member function + } + _Func __f; + }; + + template + struct _UnaryFunctionConcept + { + void __constraints() { + __r = __f(__arg); // require operator() + } + _Func __f; + _Arg __arg; + _Return __r; + }; + + template + struct _UnaryFunctionConcept<_Func, void, _Arg> { + void __constraints() { + __f(__arg); // require operator() + } + _Func __f; + _Arg __arg; + }; + + template + struct _BinaryFunctionConcept + { + void __constraints() { + __r = __f(__first, __second); // require operator() + } + _Func __f; + _First __first; + _Second __second; + _Return __r; + }; + + template + struct _BinaryFunctionConcept<_Func, void, _First, _Second> + { + void __constraints() { + __f(__first, __second); // require operator() + } + _Func __f; + _First __first; + _Second __second; + }; + + template + struct _UnaryPredicateConcept + { + void __constraints() { + __aux_require_boolean_expr(__f(__arg)); // require op() returning bool + } + _Func __f; + _Arg __arg; + }; + + template + struct _BinaryPredicateConcept + { + void __constraints() { + __aux_require_boolean_expr(__f(__a, __b)); // require op() returning bool + } + _Func __f; + _First __a; + _Second __b; + }; + + // use this when functor is used inside a container class like std::set + template + struct _Const_BinaryPredicateConcept { + void __constraints() { + __const_constraints(__f); + } + void __const_constraints(const _Func& __fun) { + __function_requires<_BinaryPredicateConcept<_Func, _First, _Second> >(); + // operator() must be a const member function + __aux_require_boolean_expr(__fun(__a, __b)); + } + _Func __f; + _First __a; + _Second __b; + }; + + //=========================================================================== + // Iterator Concepts + + template + struct _TrivialIteratorConcept + { + void __constraints() { +// __function_requires< _DefaultConstructibleConcept<_Tp> >(); + __function_requires< _AssignableConcept<_Tp> >(); + __function_requires< _EqualityComparableConcept<_Tp> >(); +// typedef typename std::iterator_traits<_Tp>::value_type _V; + (void)*__i; // require dereference operator + } + _Tp __i; + }; + + template + struct _Mutable_TrivialIteratorConcept + { + void __constraints() { + __function_requires< _TrivialIteratorConcept<_Tp> >(); + *__i = *__j; // require dereference and assignment + } + _Tp __i, __j; + }; + + template + struct _InputIteratorConcept + { + void __constraints() { + __function_requires< _TrivialIteratorConcept<_Tp> >(); + // require iterator_traits typedef's + typedef typename std::iterator_traits<_Tp>::difference_type _Diff; +// __function_requires< _SignedIntegerConcept<_Diff> >(); + typedef typename std::iterator_traits<_Tp>::reference _Ref; + typedef typename std::iterator_traits<_Tp>::pointer _Pt; + typedef typename std::iterator_traits<_Tp>::iterator_category _Cat; + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::input_iterator_tag> >(); + ++__i; // require preincrement operator + __i++; // require postincrement operator + } + _Tp __i; + }; + + template + struct _OutputIteratorConcept + { + void __constraints() { + __function_requires< _AssignableConcept<_Tp> >(); + ++__i; // require preincrement operator + __i++; // require postincrement operator + *__i++ = __t; // require postincrement and assignment + } + _Tp __i; + _ValueT __t; + }; + + template + struct _ForwardIteratorConcept + { + void __constraints() { + __function_requires< _InputIteratorConcept<_Tp> >(); + __function_requires< _DefaultConstructibleConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::forward_iterator_tag> >(); + typedef typename std::iterator_traits<_Tp>::reference _Ref; + _Ref __r _IsUnused = *__i; + } + _Tp __i; + }; + + template + struct _Mutable_ForwardIteratorConcept + { + void __constraints() { + __function_requires< _ForwardIteratorConcept<_Tp> >(); + *__i++ = *__i; // require postincrement and assignment + } + _Tp __i; + }; + + template + struct _BidirectionalIteratorConcept + { + void __constraints() { + __function_requires< _ForwardIteratorConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::bidirectional_iterator_tag> >(); + --__i; // require predecrement operator + __i--; // require postdecrement operator + } + _Tp __i; + }; + + template + struct _Mutable_BidirectionalIteratorConcept + { + void __constraints() { + __function_requires< _BidirectionalIteratorConcept<_Tp> >(); + __function_requires< _Mutable_ForwardIteratorConcept<_Tp> >(); + *__i-- = *__i; // require postdecrement and assignment + } + _Tp __i; + }; + + + template + struct _RandomAccessIteratorConcept + { + void __constraints() { + __function_requires< _BidirectionalIteratorConcept<_Tp> >(); + __function_requires< _ComparableConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::random_access_iterator_tag> >(); + // ??? We don't use _Ref, are we just checking for "referenceability"? + typedef typename std::iterator_traits<_Tp>::reference _Ref; + + __i += __n; // require assignment addition operator + __i = __i + __n; __i = __n + __i; // require addition with difference type + __i -= __n; // require assignment subtraction op + __i = __i - __n; // require subtraction with + // difference type + __n = __i - __j; // require difference operator + (void)__i[__n]; // require element access operator + } + _Tp __a, __b; + _Tp __i, __j; + typename std::iterator_traits<_Tp>::difference_type __n; + }; + + template + struct _Mutable_RandomAccessIteratorConcept + { + void __constraints() { + __function_requires< _RandomAccessIteratorConcept<_Tp> >(); + __function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >(); + __i[__n] = *__i; // require element access and assignment + } + _Tp __i; + typename std::iterator_traits<_Tp>::difference_type __n; + }; + + //=========================================================================== + // Container Concepts + + template + struct _ContainerConcept + { + typedef typename _Container::value_type _Value_type; + typedef typename _Container::difference_type _Difference_type; + typedef typename _Container::size_type _Size_type; + typedef typename _Container::const_reference _Const_reference; + typedef typename _Container::const_pointer _Const_pointer; + typedef typename _Container::const_iterator _Const_iterator; + + void __constraints() { + __function_requires< _InputIteratorConcept<_Const_iterator> >(); + __function_requires< _AssignableConcept<_Container> >(); + const _Container __c; + __i = __c.begin(); + __i = __c.end(); + __n = __c.size(); + __n = __c.max_size(); + __b = __c.empty(); + } + bool __b; + _Const_iterator __i; + _Size_type __n; + }; + + template + struct _Mutable_ContainerConcept + { + typedef typename _Container::value_type _Value_type; + typedef typename _Container::reference _Reference; + typedef typename _Container::iterator _Iterator; + typedef typename _Container::pointer _Pointer; + + void __constraints() { + __function_requires< _ContainerConcept<_Container> >(); + __function_requires< _AssignableConcept<_Value_type> >(); + __function_requires< _InputIteratorConcept<_Iterator> >(); + + __i = __c.begin(); + __i = __c.end(); + __c.swap(__c2); + } + _Iterator __i; + _Container __c, __c2; + }; + + template + struct _ForwardContainerConcept + { + void __constraints() { + __function_requires< _ContainerConcept<_ForwardContainer> >(); + typedef typename _ForwardContainer::const_iterator _Const_iterator; + __function_requires< _ForwardIteratorConcept<_Const_iterator> >(); + } + }; + + template + struct _Mutable_ForwardContainerConcept + { + void __constraints() { + __function_requires< _ForwardContainerConcept<_ForwardContainer> >(); + __function_requires< _Mutable_ContainerConcept<_ForwardContainer> >(); + typedef typename _ForwardContainer::iterator _Iterator; + __function_requires< _Mutable_ForwardIteratorConcept<_Iterator> >(); + } + }; + + template + struct _ReversibleContainerConcept + { + typedef typename _ReversibleContainer::const_iterator _Const_iterator; + typedef typename _ReversibleContainer::const_reverse_iterator + _Const_reverse_iterator; + + void __constraints() { + __function_requires< _ForwardContainerConcept<_ReversibleContainer> >(); + __function_requires< _BidirectionalIteratorConcept<_Const_iterator> >(); + __function_requires< + _BidirectionalIteratorConcept<_Const_reverse_iterator> >(); + + const _ReversibleContainer __c; + _Const_reverse_iterator __i = __c.rbegin(); + __i = __c.rend(); + } + }; + + template + struct _Mutable_ReversibleContainerConcept + { + typedef typename _ReversibleContainer::iterator _Iterator; + typedef typename _ReversibleContainer::reverse_iterator _Reverse_iterator; + + void __constraints() { + __function_requires<_ReversibleContainerConcept<_ReversibleContainer> >(); + __function_requires< + _Mutable_ForwardContainerConcept<_ReversibleContainer> >(); + __function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator> >(); + __function_requires< + _Mutable_BidirectionalIteratorConcept<_Reverse_iterator> >(); + + _Reverse_iterator __i = __c.rbegin(); + __i = __c.rend(); + } + _ReversibleContainer __c; + }; + + template + struct _RandomAccessContainerConcept + { + typedef typename _RandomAccessContainer::size_type _Size_type; + typedef typename _RandomAccessContainer::const_reference _Const_reference; + typedef typename _RandomAccessContainer::const_iterator _Const_iterator; + typedef typename _RandomAccessContainer::const_reverse_iterator + _Const_reverse_iterator; + + void __constraints() { + __function_requires< + _ReversibleContainerConcept<_RandomAccessContainer> >(); + __function_requires< _RandomAccessIteratorConcept<_Const_iterator> >(); + __function_requires< + _RandomAccessIteratorConcept<_Const_reverse_iterator> >(); + + const _RandomAccessContainer __c; + _Const_reference __r _IsUnused = __c[__n]; + } + _Size_type __n; + }; + + template + struct _Mutable_RandomAccessContainerConcept + { + typedef typename _RandomAccessContainer::size_type _Size_type; + typedef typename _RandomAccessContainer::reference _Reference; + typedef typename _RandomAccessContainer::iterator _Iterator; + typedef typename _RandomAccessContainer::reverse_iterator _Reverse_iterator; + + void __constraints() { + __function_requires< + _RandomAccessContainerConcept<_RandomAccessContainer> >(); + __function_requires< + _Mutable_ReversibleContainerConcept<_RandomAccessContainer> >(); + __function_requires< _Mutable_RandomAccessIteratorConcept<_Iterator> >(); + __function_requires< + _Mutable_RandomAccessIteratorConcept<_Reverse_iterator> >(); + + _Reference __r _IsUnused = __c[__i]; + } + _Size_type __i; + _RandomAccessContainer __c; + }; + + // A Sequence is inherently mutable + template + struct _SequenceConcept + { + typedef typename _Sequence::reference _Reference; + typedef typename _Sequence::const_reference _Const_reference; + + void __constraints() { + // Matt Austern's book puts DefaultConstructible here, the C++ + // standard places it in Container + // function_requires< DefaultConstructible >(); + __function_requires< _Mutable_ForwardContainerConcept<_Sequence> >(); + __function_requires< _DefaultConstructibleConcept<_Sequence> >(); + + _Sequence + __c _IsUnused(__n, __t), + __c2 _IsUnused(__first, __last); + + __c.insert(__p, __t); + __c.insert(__p, __n, __t); + __c.insert(__p, __first, __last); + + __c.erase(__p); + __c.erase(__p, __q); + + _Reference __r _IsUnused = __c.front(); + + __const_constraints(__c); + } + void __const_constraints(const _Sequence& __c) { + _Const_reference __r _IsUnused = __c.front(); + } + typename _Sequence::value_type __t; + typename _Sequence::size_type __n; + typename _Sequence::value_type *__first, *__last; + typename _Sequence::iterator __p, __q; + }; + + template + struct _FrontInsertionSequenceConcept + { + void __constraints() { + __function_requires< _SequenceConcept<_FrontInsertionSequence> >(); + + __c.push_front(__t); + __c.pop_front(); + } + _FrontInsertionSequence __c; + typename _FrontInsertionSequence::value_type __t; + }; + + template + struct _BackInsertionSequenceConcept + { + typedef typename _BackInsertionSequence::reference _Reference; + typedef typename _BackInsertionSequence::const_reference _Const_reference; + + void __constraints() { + __function_requires< _SequenceConcept<_BackInsertionSequence> >(); + + __c.push_back(__t); + __c.pop_back(); + _Reference __r _IsUnused = __c.back(); + } + void __const_constraints(const _BackInsertionSequence& __c) { + _Const_reference __r _IsUnused = __c.back(); + }; + _BackInsertionSequence __c; + typename _BackInsertionSequence::value_type __t; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#pragma GCC diagnostic pop +#undef _IsUnused + +#endif // _GLIBCXX_BOOST_CONCEPT_CHECK + + diff --git a/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h b/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h new file mode 100644 index 000000000..83dc80c34 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h @@ -0,0 +1,37 @@ +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++0x_warning.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _CXX0X_WARNING_H +#define _CXX0X_WARNING_H 1 + +#if __cplusplus < 201103L +#error This file requires compiler and library support \ +for the ISO C++ 2011 standard. This support must be enabled \ +with the -std=c++11 or -std=gnu++11 compiler options. +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/c++allocator.h b/resources/sources/avr-libstdcpp/include/bits/c++allocator.h new file mode 100644 index 000000000..6392d2207 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/c++allocator.h @@ -0,0 +1,59 @@ +// Base to std::allocator -*- C++ -*- + +// Copyright (C) 2004-2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++allocator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _GLIBCXX_CXX_ALLOCATOR_H +#define _GLIBCXX_CXX_ALLOCATOR_H 1 + +#include + +#if __cplusplus >= 201103L +namespace std +{ + /** + * @brief An alias to the base class for std::allocator. + * @ingroup allocators + * + * Used to set the std::allocator base class to + * __gnu_cxx::new_allocator. + * + * @tparam _Tp Type of allocated object. + */ + template + using __allocator_base = __gnu_cxx::new_allocator<_Tp>; +} +#else +// Define new_allocator as the base class to std::allocator. +# define __allocator_base __gnu_cxx::new_allocator +#endif + +#if defined(__SANITIZE_ADDRESS__) && !defined(_GLIBCXX_SANITIZE_STD_ALLOCATOR) +# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1 +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/c++config.h b/resources/sources/avr-libstdcpp/include/bits/c++config.h new file mode 100644 index 000000000..29b3eb2f0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/c++config.h @@ -0,0 +1,2074 @@ +// Predefined symbols and macros -*- C++ -*- + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++config.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{version} + */ + +#ifndef _GLIBCXX_CXX_CONFIG_H +#define _GLIBCXX_CXX_CONFIG_H 1 + +// The major release number for the GCC release the C++ library belongs to. +#define _GLIBCXX_RELEASE 10 + +// The datestamp of the C++ library in compressed ISO date format. +#define __GLIBCXX__ 20201103 + +// Macros for various attributes. +// _GLIBCXX_PURE +// _GLIBCXX_CONST +// _GLIBCXX_NORETURN +// _GLIBCXX_NOTHROW +// _GLIBCXX_VISIBILITY +#ifndef _GLIBCXX_PURE +# define _GLIBCXX_PURE __attribute__ ((__pure__)) +#endif + +#ifndef _GLIBCXX_CONST +# define _GLIBCXX_CONST __attribute__ ((__const__)) +#endif + +#ifndef _GLIBCXX_NORETURN +# define _GLIBCXX_NORETURN __attribute__ ((__noreturn__)) +#endif + +// See below for C++ +#ifndef _GLIBCXX_NOTHROW +# ifndef __cplusplus +# define _GLIBCXX_NOTHROW __attribute__((__nothrow__)) +# endif +#endif + +// Macros for visibility attributes. +// _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY +// _GLIBCXX_VISIBILITY +#define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY + +#ifdef _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY +# define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V))) +#else +// If this is not supplied by the OS-specific or CPU-specific +// headers included below, it will be defined to an empty default. +# define _GLIBCXX_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY(V) +#endif + +// Macros for deprecated attributes. +// _GLIBCXX_USE_DEPRECATED +// _GLIBCXX_DEPRECATED +// _GLIBCXX_DEPRECATED_SUGGEST +// _GLIBCXX17_DEPRECATED +// _GLIBCXX20_DEPRECATED( string-literal ) +#ifndef _GLIBCXX_USE_DEPRECATED +# define _GLIBCXX_USE_DEPRECATED 1 +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 201103L) +# define _GLIBCXX_DEPRECATED __attribute__ ((__deprecated__)) +# define _GLIBCXX_DEPRECATED_SUGGEST(ALT) \ + __attribute__ ((__deprecated__ ("use '" ALT "' instead"))) +#else +# define _GLIBCXX_DEPRECATED +# define _GLIBCXX_DEPRECATED_SUGGEST(ALT) +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 201703L) +# define _GLIBCXX17_DEPRECATED [[__deprecated__]] +#else +# define _GLIBCXX17_DEPRECATED +#endif + +#if defined(__DEPRECATED) && (__cplusplus > 201703L) +# define _GLIBCXX20_DEPRECATED(MSG) [[deprecated(MSG)]] +#else +# define _GLIBCXX20_DEPRECATED(MSG) +#endif + +// Macros for ABI tag attributes. +#ifndef _GLIBCXX_ABI_TAG_CXX11 +# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11"))) +#endif + +// Macro to warn about unused results. +#if __cplusplus >= 201703L +# define _GLIBCXX_NODISCARD [[__nodiscard__]] +#else +# define _GLIBCXX_NODISCARD +#endif + + + +#ifdef __cplusplus + +// Macro for constexpr, to support in mixed 03/0x mode. +#ifndef _GLIBCXX_CONSTEXPR +# if __cplusplus >= 201103L +# define _GLIBCXX_CONSTEXPR constexpr +# define _GLIBCXX_USE_CONSTEXPR constexpr +# else +# define _GLIBCXX_CONSTEXPR +# define _GLIBCXX_USE_CONSTEXPR const +# endif +#endif + +#ifndef _GLIBCXX14_CONSTEXPR +# if __cplusplus >= 201402L +# define _GLIBCXX14_CONSTEXPR constexpr +# else +# define _GLIBCXX14_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX17_CONSTEXPR +# if __cplusplus >= 201703L +# define _GLIBCXX17_CONSTEXPR constexpr +# else +# define _GLIBCXX17_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX20_CONSTEXPR +# if __cplusplus > 201703L +# define _GLIBCXX20_CONSTEXPR constexpr +# else +# define _GLIBCXX20_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX17_INLINE +# if __cplusplus >= 201703L +# define _GLIBCXX17_INLINE inline +# else +# define _GLIBCXX17_INLINE +# endif +#endif + +// Macro for noexcept, to support in mixed 03/0x mode. +#ifndef _GLIBCXX_NOEXCEPT +# if __cplusplus >= 201103L +# define _GLIBCXX_NOEXCEPT noexcept +# define _GLIBCXX_NOEXCEPT_IF(...) noexcept(__VA_ARGS__) +# define _GLIBCXX_USE_NOEXCEPT noexcept +# define _GLIBCXX_THROW(_EXC) +# else +# define _GLIBCXX_NOEXCEPT +# define _GLIBCXX_NOEXCEPT_IF(...) +# define _GLIBCXX_USE_NOEXCEPT throw() +# define _GLIBCXX_THROW(_EXC) throw(_EXC) +# endif +#endif + +#ifndef _GLIBCXX_NOTHROW +# define _GLIBCXX_NOTHROW _GLIBCXX_USE_NOEXCEPT +#endif + +#ifndef _GLIBCXX_THROW_OR_ABORT +# ifdef __cpp_exceptions +# define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC)) +# else +# define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort()) +# endif +#endif + +#ifdef __cpp_noexcept_function_type +#define _GLIBCXX_NOEXCEPT_PARM , bool _NE +#define _GLIBCXX_NOEXCEPT_QUAL noexcept (_NE) +#else +#define _GLIBCXX_NOEXCEPT_PARM +#define _GLIBCXX_NOEXCEPT_QUAL +#endif + +// Macro for extern template, ie controlling template linkage via use +// of extern keyword on template declaration. As documented in the g++ +// manual, it inhibits all implicit instantiations and is used +// throughout the library to avoid multiple weak definitions for +// required types that are already explicitly instantiated in the +// library binary. This substantially reduces the binary size of +// resulting executables. +// Special case: _GLIBCXX_EXTERN_TEMPLATE == -1 disallows extern +// templates only in basic_string, thus activating its debug-mode +// checks even at -O0. +# define _GLIBCXX_EXTERN_TEMPLATE 1 + +/* + Outline of libstdc++ namespaces. + + namespace std + { + namespace __debug { } + namespace __parallel { } + namespace __cxx1998 { } + + namespace __detail { + namespace __variant { } // C++17 + } + + namespace rel_ops { } + + namespace tr1 + { + namespace placeholders { } + namespace regex_constants { } + namespace __detail { } + } + + namespace tr2 { } + + namespace decimal { } + + namespace chrono { } // C++11 + namespace placeholders { } // C++11 + namespace regex_constants { } // C++11 + namespace this_thread { } // C++11 + inline namespace literals { // C++14 + inline namespace chrono_literals { } // C++14 + inline namespace complex_literals { } // C++14 + inline namespace string_literals { } // C++14 + inline namespace string_view_literals { } // C++17 + } + } + + namespace abi { } + + namespace __gnu_cxx + { + namespace __detail { } + } + + For full details see: + http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/namespaces.html +*/ +namespace std +{ + typedef __SIZE_TYPE__ size_t; + typedef __PTRDIFF_TYPE__ ptrdiff_t; + +#if __cplusplus >= 201103L + typedef decltype(nullptr) nullptr_t; +#endif +} + +# define _GLIBCXX_USE_DUAL_ABI 1 + +#ifndef _GLIBCXX_USE_DUAL_ABI +// Ignore any pre-defined value of _GLIBCXX_USE_CXX11_ABI +# undef _GLIBCXX_USE_CXX11_ABI +#endif + +#ifndef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_USE_CXX11_ABI 1 +#endif + +#ifdef _GLIBCXX_USE_CXX11_ABI +namespace std +{ + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +} +namespace __gnu_cxx +{ + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +} +# define _GLIBCXX_NAMESPACE_CXX11 __cxx11:: +# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 namespace __cxx11 { +# define _GLIBCXX_END_NAMESPACE_CXX11 } +# define _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_ABI_TAG_CXX11 +#else +# define _GLIBCXX_NAMESPACE_CXX11 +# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 +# define _GLIBCXX_END_NAMESPACE_CXX11 +# define _GLIBCXX_DEFAULT_ABI_TAG +#endif + +// Defined if inline namespaces are used for versioning. +//#define _GLIBCXX_INLINE_VERSION + +// Inline namespace for symbol versioning. +#ifdef _GLIBCXX_INLINE_VERSION +# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __8 { +# define _GLIBCXX_END_NAMESPACE_VERSION } + +namespace std +{ +inline _GLIBCXX_BEGIN_NAMESPACE_VERSION +#if __cplusplus >= 201402L + inline namespace literals { + inline namespace chrono_literals { } + inline namespace complex_literals { } + inline namespace string_literals { } +#if __cplusplus > 201402L + inline namespace string_view_literals { } +#endif // C++17 + } +#endif // C++14 +_GLIBCXX_END_NAMESPACE_VERSION +} + +namespace __gnu_cxx +{ +inline _GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_END_NAMESPACE_VERSION +} + +#else +# define _GLIBCXX_BEGIN_NAMESPACE_VERSION +# define _GLIBCXX_END_NAMESPACE_VERSION +#endif + +// Inline namespaces for special modes: debug, parallel. +#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Non-inline namespace for components replaced by alternates in active mode. + namespace __cxx1998 + { +# if _GLIBCXX_USE_CXX11_ABI + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +# endif + } + +_GLIBCXX_END_NAMESPACE_VERSION + + // Inline namespace for debug mode. +# ifdef _GLIBCXX_DEBUG + inline namespace __debug { } +# endif + + // Inline namespaces for parallel mode. +# ifdef _GLIBCXX_PARALLEL + inline namespace __parallel { } +# endif +} + +// Check for invalid usage and unsupported mixed-mode use. +# if defined(_GLIBCXX_DEBUG) && defined(_GLIBCXX_PARALLEL) +# error illegal use of multiple inlined namespaces +# endif + +// Check for invalid use due to lack for weak symbols. +# if __NO_INLINE__ && !__GXX_WEAK__ +# warning currently using inlined namespace mode which may fail \ + without inlining due to lack of weak symbols +# endif +#endif + +// Macros for namespace scope. Either namespace std:: or the name +// of some nested namespace within it corresponding to the active mode. +// _GLIBCXX_STD_A +// _GLIBCXX_STD_C +// +// Macros for opening/closing conditional namespaces. +// _GLIBCXX_BEGIN_NAMESPACE_ALGO +// _GLIBCXX_END_NAMESPACE_ALGO +// _GLIBCXX_BEGIN_NAMESPACE_CONTAINER +// _GLIBCXX_END_NAMESPACE_CONTAINER +#if defined(_GLIBCXX_DEBUG) +# define _GLIBCXX_STD_C __cxx1998 +# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER \ + namespace _GLIBCXX_STD_C { +# define _GLIBCXX_END_NAMESPACE_CONTAINER } +#else +# define _GLIBCXX_STD_C std +# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER +# define _GLIBCXX_END_NAMESPACE_CONTAINER +#endif + +#ifdef _GLIBCXX_PARALLEL +# define _GLIBCXX_STD_A __cxx1998 +# define _GLIBCXX_BEGIN_NAMESPACE_ALGO \ + namespace _GLIBCXX_STD_A { +# define _GLIBCXX_END_NAMESPACE_ALGO } +#else +# define _GLIBCXX_STD_A std +# define _GLIBCXX_BEGIN_NAMESPACE_ALGO +# define _GLIBCXX_END_NAMESPACE_ALGO +#endif + +// GLIBCXX_ABI Deprecated +// Define if compatibility should be provided for -mlong-double-64. +#undef _GLIBCXX_LONG_DOUBLE_COMPAT + +// Inline namespace for long double 128 mode. +#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ +namespace std +{ + inline namespace __gnu_cxx_ldbl128 { } +} +# define _GLIBCXX_NAMESPACE_LDBL __gnu_cxx_ldbl128:: +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL namespace __gnu_cxx_ldbl128 { +# define _GLIBCXX_END_NAMESPACE_LDBL } +#else +# define _GLIBCXX_NAMESPACE_LDBL +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL +# define _GLIBCXX_END_NAMESPACE_LDBL +#endif +#ifdef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_CXX11 +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_CXX11 +# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_CXX11 +#else +# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_LDBL +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_LDBL +# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_LDBL +#endif + +// Debug Mode implies checking assertions. +#if defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_ASSERTIONS) +# define _GLIBCXX_ASSERTIONS 1 +#endif + +// Disable std::string explicit instantiation declarations in order to assert. +#ifdef _GLIBCXX_ASSERTIONS +# undef _GLIBCXX_EXTERN_TEMPLATE +# define _GLIBCXX_EXTERN_TEMPLATE -1 +#endif + +// Assert. +#if defined(_GLIBCXX_ASSERTIONS) \ + || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PARALLEL_ASSERTIONS) +namespace std +{ + // Avoid the use of assert, because we're trying to keep the + // include out of the mix. + extern "C++" inline void + __replacement_assert(const char* __file, int __line, + const char* __function, const char* __condition) + { + __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, __line, + __function, __condition); + __builtin_abort(); + } +} +#define __glibcxx_assert_impl(_Condition) \ + do \ + { \ + if (! (_Condition)) \ + std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ + #_Condition); \ + } while (false) +#endif + +#if defined(_GLIBCXX_ASSERTIONS) +# define __glibcxx_assert(_Condition) __glibcxx_assert_impl(_Condition) +#else +# define __glibcxx_assert(_Condition) +#endif + +// Macros for race detectors. +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) and +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) should be used to explain +// atomic (lock-free) synchronization to race detectors: +// the race detector will infer a happens-before arc from the former to the +// latter when they share the same argument pointer. +// +// The most frequent use case for these macros (and the only case in the +// current implementation of the library) is atomic reference counting: +// void _M_remove_reference() +// { +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount); +// if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount, -1) <= 0) +// { +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount); +// _M_destroy(__a); +// } +// } +// The annotations in this example tell the race detector that all memory +// accesses occurred when the refcount was positive do not race with +// memory accesses which occurred after the refcount became zero. +#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE +# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) +#endif +#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER +# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) +#endif + +// Macros for C linkage: define extern "C" linkage only when using C++. +# define _GLIBCXX_BEGIN_EXTERN_C extern "C" { +# define _GLIBCXX_END_EXTERN_C } + +# define _GLIBCXX_USE_ALLOCATOR_NEW 1 + +#else // !__cplusplus +# define _GLIBCXX_BEGIN_EXTERN_C +# define _GLIBCXX_END_EXTERN_C +#endif + + +// First includes. + +// Pick up any OS-specific definitions. +//#include + +// Pick up any CPU-specific definitions. +//#include + +// If platform uses neither visibility nor psuedo-visibility, +// specify empty default for namespace annotation macros. +#ifndef _GLIBCXX_PSEUDO_VISIBILITY +# define _GLIBCXX_PSEUDO_VISIBILITY(V) +#endif + +// Certain function definitions that are meant to be overridable from +// user code are decorated with this macro. For some targets, this +// macro causes these definitions to be weak. +#ifndef _GLIBCXX_WEAK_DEFINITION +# define _GLIBCXX_WEAK_DEFINITION +#endif + +// By default, we assume that __GXX_WEAK__ also means that there is support +// for declaring functions as weak while not defining such functions. This +// allows for referring to functions provided by other libraries (e.g., +// libitm) without depending on them if the respective features are not used. +#ifndef _GLIBCXX_USE_WEAK_REF +# define _GLIBCXX_USE_WEAK_REF __GXX_WEAK__ +#endif + +// Conditionally enable annotations for the Transactional Memory TS on C++11. +// Most of the following conditions are due to limitations in the current +// implementation. +/*#if __cplusplus >= 201103L && _GLIBCXX_USE_CXX11_ABI \ + && _GLIBCXX_USE_DUAL_ABI && __cpp_transactional_memory >= 201505L \ + && !_GLIBCXX_FULLY_DYNAMIC_STRING && _GLIBCXX_USE_WEAK_REF \ + && _GLIBCXX_USE_ALLOCATOR_NEW +#define _GLIBCXX_TXN_SAFE transaction_safe +#define _GLIBCXX_TXN_SAFE_DYN transaction_safe_dynamic*/ +//#else +#define _GLIBCXX_TXN_SAFE +#define _GLIBCXX_TXN_SAFE_DYN +//#endif + +#if __cplusplus > 201402L +// In C++17 mathematical special functions are in namespace std. +# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 +#elif __cplusplus >= 201103L && __STDCPP_WANT_MATH_SPEC_FUNCS__ != 0 +// For C++11 and C++14 they are in namespace std when requested. +# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 +#endif + +// The remainder of the prewritten config is automatic; all the +// user hooks are listed above. + +// Create a boolean flag to be used to determine if --fast-math is set. +#ifdef __FAST_MATH__ +# define _GLIBCXX_FAST_MATH 1 +#else +# define _GLIBCXX_FAST_MATH 0 +#endif + +// This marks string literals in header files to be extracted for eventual +// translation. It is primarily used for messages in thrown exceptions; see +// src/functexcept.cc. We use __N because the more traditional _N is used +// for something else under certain OSes (see BADNAMES). + +// modm avr port: remove exception strings to save RAM +#define __N(msgid) ("") + +// For example, is known to #define min and max as macros... +#undef min +#undef max + +// N.B. these _GLIBCXX_USE_C99_XXX macros are defined unconditionally +// so they should be tested with #if not with #ifdef. +#if __cplusplus >= 201103L +# ifndef _GLIBCXX_USE_C99_MATH +# define _GLIBCXX_USE_C99_MATH _GLIBCXX11_USE_C99_MATH +# endif +# ifndef _GLIBCXX_USE_C99_COMPLEX +# define _GLIBCXX_USE_C99_COMPLEX _GLIBCXX11_USE_C99_COMPLEX +# endif +# ifndef _GLIBCXX_USE_C99_STDIO +# define _GLIBCXX_USE_C99_STDIO _GLIBCXX11_USE_C99_STDIO +# endif +# ifndef _GLIBCXX_USE_C99_STDLIB +# define _GLIBCXX_USE_C99_STDLIB _GLIBCXX11_USE_C99_STDLIB +# endif +# ifndef _GLIBCXX_USE_C99_WCHAR +# define _GLIBCXX_USE_C99_WCHAR _GLIBCXX11_USE_C99_WCHAR +# endif +#else +# ifndef _GLIBCXX_USE_C99_MATH +# define _GLIBCXX_USE_C99_MATH _GLIBCXX98_USE_C99_MATH +# endif +# ifndef _GLIBCXX_USE_C99_COMPLEX +# define _GLIBCXX_USE_C99_COMPLEX _GLIBCXX98_USE_C99_COMPLEX +# endif +# ifndef _GLIBCXX_USE_C99_STDIO +# define _GLIBCXX_USE_C99_STDIO _GLIBCXX98_USE_C99_STDIO +# endif +# ifndef _GLIBCXX_USE_C99_STDLIB +# define _GLIBCXX_USE_C99_STDLIB _GLIBCXX98_USE_C99_STDLIB +# endif +# ifndef _GLIBCXX_USE_C99_WCHAR +# define _GLIBCXX_USE_C99_WCHAR _GLIBCXX98_USE_C99_WCHAR +# endif +#endif + +// Unless explicitly specified, enable char8_t extensions only if the core +// language char8_t feature macro is defined. +#ifndef _GLIBCXX_USE_CHAR8_T +# ifdef __cpp_char8_t +# define _GLIBCXX_USE_CHAR8_T 1 +# endif +#endif +#ifdef _GLIBCXX_USE_CHAR8_T +# define __cpp_lib_char8_t 201907L +#endif + +/* Define if __float128 is supported on this host. */ +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +#undef _GLIBCXX_USE_FLOAT128 +#endif + +#if __GNUC__ >= 7 +// Assume these are available if the compiler claims to be a recent GCC: +# define _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP 1 +# define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 +# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 +# define _GLIBCXX_BUILTIN_IS_SAME_AS(T, U) __is_same_as(T, U) +# if __GNUC__ >= 9 +# define _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 1 +# endif +#elif defined(__is_identifier) && defined(__has_builtin) +// For non-GNU compilers: +# if ! __is_identifier(__has_unique_object_representations) +# define _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP 1 +# endif +# if ! __is_identifier(__is_aggregate) +# define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 +# endif +# if __has_builtin(__builtin_launder) +# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 +# endif +# if __has_builtin(__builtin_is_constant_evaluated) +# define _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 1 +# endif +# if ! __is_identifier(__is_same) +# define _GLIBCXX_BUILTIN_IS_SAME_AS(T, U) __is_same(T, U) +# endif +#endif // GCC + +// PSTL configuration + +#if __cplusplus >= 201703L +// This header is not installed for freestanding: +#if __has_include() +// Preserved here so we have some idea which version of upstream we've pulled in +// #define PSTL_VERSION 9000 + +// For now this defaults to being based on the presence of Thread Building Blocks +# ifndef _GLIBCXX_USE_TBB_PAR_BACKEND +# define _GLIBCXX_USE_TBB_PAR_BACKEND __has_include() +# endif +// This section will need some rework when a new (default) backend type is added +# if _GLIBCXX_USE_TBB_PAR_BACKEND +# define _PSTL_PAR_BACKEND_TBB +# else +# define _PSTL_PAR_BACKEND_SERIAL +# endif + +# define _PSTL_ASSERT(_Condition) __glibcxx_assert(_Condition) +# define _PSTL_ASSERT_MSG(_Condition, _Message) __glibcxx_assert(_Condition) + +#include +#endif // __has_include +#endif // C++17 + +// End of prewritten config; the settings discovered at configure time follow. +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `acosf' function. */ +#define _GLIBCXX_HAVE_ACOSF 1 + +/* Define to 1 if you have the `acosl' function. */ +/* #undef _GLIBCXX_HAVE_ACOSL */ + +/* Define to 1 if you have the `aligned_alloc' function. */ +/* #undef _GLIBCXX_HAVE_ALIGNED_ALLOC */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the `asinf' function. */ +#define _GLIBCXX_HAVE_ASINF 1 + +/* Define to 1 if you have the `asinl' function. */ +/* #undef _GLIBCXX_HAVE_ASINL */ + +/* Define to 1 if the target assembler supports .symver directive. */ +#define _GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE 1 + +/* Define to 1 if you have the `atan2f' function. */ +#define _GLIBCXX_HAVE_ATAN2F 1 + +/* Define to 1 if you have the `atan2l' function. */ +/* #undef _GLIBCXX_HAVE_ATAN2L */ + +/* Define to 1 if you have the `atanf' function. */ +#define _GLIBCXX_HAVE_ATANF 1 + +/* Define to 1 if you have the `atanl' function. */ +/* #undef _GLIBCXX_HAVE_ATANL */ + +/* Defined if shared_ptr reference counting should use atomic operations. */ +/* #undef _GLIBCXX_HAVE_ATOMIC_LOCK_POLICY */ + +/* Define to 1 if you have the `at_quick_exit' function. */ +/* #undef _GLIBCXX_HAVE_AT_QUICK_EXIT */ + +/* Define to 1 if the target assembler supports thread-local storage. */ +/* #undef _GLIBCXX_HAVE_CC_TLS */ + +/* Define to 1 if you have the `ceilf' function. */ +#define _GLIBCXX_HAVE_CEILF 1 + +/* Define to 1 if you have the `ceill' function. */ +/* #undef _GLIBCXX_HAVE_CEILL */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_COMPLEX_H 1 + +/* Define to 1 if you have the `cosf' function. */ +#define _GLIBCXX_HAVE_COSF 1 + +/* Define to 1 if you have the `coshf' function. */ +#define _GLIBCXX_HAVE_COSHF 1 + +/* Define to 1 if you have the `coshl' function. */ +/* #undef _GLIBCXX_HAVE_COSHL */ + +/* Define to 1 if you have the `cosl' function. */ +/* #undef _GLIBCXX_HAVE_COSL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_DIRENT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_DLFCN_H */ + +/* Define if EBADMSG exists. */ +//#define _GLIBCXX_HAVE_EBADMSG 1 + +/* Define if ECANCELED exists. */ +//#define _GLIBCXX_HAVE_ECANCELED 1 + +/* Define if ECHILD exists. */ +//#define _GLIBCXX_HAVE_ECHILD 1 + +/* Define if EIDRM exists. */ +//#define _GLIBCXX_HAVE_EIDRM 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_ENDIAN_H */ + +/* Define if ENODATA exists. */ +//#define _GLIBCXX_HAVE_ENODATA 1 + +/* Define if ENOLINK exists. */ +//#define _GLIBCXX_HAVE_ENOLINK 1 + +/* Define if ENOSPC exists. */ +//#define _GLIBCXX_HAVE_ENOSPC 1 + +/* Define if ENOSR exists. */ +//#define _GLIBCXX_HAVE_ENOSR 1 + +/* Define if ENOSTR exists. */ +//#define _GLIBCXX_HAVE_ENOSTR 1 + +/* Define if ENOTRECOVERABLE exists. */ +//#define _GLIBCXX_HAVE_ENOTRECOVERABLE 1 + +/* Define if ENOTSUP exists. */ +//#define _GLIBCXX_HAVE_ENOTSUP 1 + +/* Define if EOVERFLOW exists. */ +//#define _GLIBCXX_HAVE_EOVERFLOW 1 + +/* Define if EOWNERDEAD exists. */ +//#define _GLIBCXX_HAVE_EOWNERDEAD 1 + +/* Define if EPERM exists. */ +//#define _GLIBCXX_HAVE_EPERM 1 + +/* Define if EPROTO exists. */ +//#define _GLIBCXX_HAVE_EPROTO 1 + +/* Define if ETIME exists. */ +//#define _GLIBCXX_HAVE_ETIME 1 + +/* Define if ETIMEDOUT exists. */ +//#define _GLIBCXX_HAVE_ETIMEDOUT 1 + +/* Define if ETXTBSY exists. */ +//#define _GLIBCXX_HAVE_ETXTBSY 1 + +/* Define if EWOULDBLOCK exists. */ +//#define _GLIBCXX_HAVE_EWOULDBLOCK 1 + +/* Define to 1 if GCC 4.6 supported std::exception_ptr for the target */ +/* #undef _GLIBCXX_HAVE_EXCEPTION_PTR_SINCE_GCC46 */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_EXECINFO_H */ + +/* Define to 1 if you have the `expf' function. */ +#define _GLIBCXX_HAVE_EXPF 1 + +/* Define to 1 if you have the `expl' function. */ +/* #undef _GLIBCXX_HAVE_EXPL */ + +/* Define to 1 if you have the `fabsf' function. */ +#define _GLIBCXX_HAVE_FABSF 1 + +/* Define to 1 if you have the `fabsl' function. */ +/* #undef _GLIBCXX_HAVE_FABSL */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_FENV_H */ + +/* Define to 1 if you have the `finite' function. */ +/* #undef _GLIBCXX_HAVE_FINITE */ + +/* Define to 1 if you have the `finitef' function. */ +/* #undef _GLIBCXX_HAVE_FINITEF */ + +/* Define to 1 if you have the `finitel' function. */ +/* #undef _GLIBCXX_HAVE_FINITEL */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_FLOAT_H 1 + +/* Define to 1 if you have the `floorf' function. */ +#define _GLIBCXX_HAVE_FLOORF 1 + +/* Define to 1 if you have the `floorl' function. */ +/* #undef _GLIBCXX_HAVE_FLOORL */ + +/* Define to 1 if you have the `fmodf' function. */ +#define _GLIBCXX_HAVE_FMODF 1 + +/* Define to 1 if you have the `fmodl' function. */ +/* #undef _GLIBCXX_HAVE_FMODL */ + +/* Define to 1 if you have the `fpclass' function. */ +/* #undef _GLIBCXX_HAVE_FPCLASS */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_FP_H */ + +/* Define to 1 if you have the `frexpf' function. */ +#define _GLIBCXX_HAVE_FREXPF 1 + +/* Define to 1 if you have the `frexpl' function. */ +/* #undef _GLIBCXX_HAVE_FREXPL */ + +/* Define if _Unwind_GetIPInfo is available. */ +//#define _GLIBCXX_HAVE_GETIPINFO 1 + +/* Define if gets is available in before C++14. */ +#define _GLIBCXX_HAVE_GETS 1 + +/* Define to 1 if you have the `hypot' function. */ +#define _GLIBCXX_HAVE_HYPOT 1 + +/* Define to 1 if you have the `hypotf' function. */ +/* #undef _GLIBCXX_HAVE_HYPOTF */ + +/* Define to 1 if you have the `hypotl' function. */ +/* #undef _GLIBCXX_HAVE_HYPOTL */ + +/* Define if you have the iconv() function. */ +//#define _GLIBCXX_HAVE_ICONV 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_IEEEFP_H 1 + +/* Define if int64_t is available in . */ +#define _GLIBCXX_HAVE_INT64_T 1 + +/* Define if int64_t is a long. */ +/* #undef _GLIBCXX_HAVE_INT64_T_LONG */ + +/* Define if int64_t is a long long. */ +#define _GLIBCXX_HAVE_INT64_T_LONG_LONG 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `isinf' function. */ +/* #undef _GLIBCXX_HAVE_ISINF */ + +/* Define to 1 if you have the `isinff' function. */ +/* #undef _GLIBCXX_HAVE_ISINFF */ + +/* Define to 1 if you have the `isinfl' function. */ +/* #undef _GLIBCXX_HAVE_ISINFL */ + +/* Define to 1 if you have the `isnan' function. */ +/* #undef _GLIBCXX_HAVE_ISNAN */ + +/* Define to 1 if you have the `isnanf' function. */ +/* #undef _GLIBCXX_HAVE_ISNANF */ + +/* Define to 1 if you have the `isnanl' function. */ +/* #undef _GLIBCXX_HAVE_ISNANL */ + +/* Defined if iswblank exists. */ +//#define _GLIBCXX_HAVE_ISWBLANK 1 + +/* Define if LC_MESSAGES is available in . */ +#define _GLIBCXX_HAVE_LC_MESSAGES 1 + +/* Define to 1 if you have the `ldexpf' function. */ +#define _GLIBCXX_HAVE_LDEXPF 1 + +/* Define to 1 if you have the `ldexpl' function. */ +/* #undef _GLIBCXX_HAVE_LDEXPL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LIBINTL_H */ + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_AS 0 + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_DATA 0 + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_FSIZE 0 + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_RSS 0 + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_VMEM 0 + +/* Define if futex syscall is available. */ +/* #undef _GLIBCXX_HAVE_LINUX_FUTEX */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LINUX_RANDOM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LINUX_TYPES_H */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `log10f' function. */ +#define _GLIBCXX_HAVE_LOG10F 1 + +/* Define to 1 if you have the `log10l' function. */ +/* #undef _GLIBCXX_HAVE_LOG10L */ + +/* Define to 1 if you have the `logf' function. */ +#define _GLIBCXX_HAVE_LOGF 1 + +/* Define to 1 if you have the `logl' function. */ +/* #undef _GLIBCXX_HAVE_LOGL */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_MACHINE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_MACHINE_PARAM_H 1 + +/* Define if mbstate_t exists in wchar.h. */ +//#define _GLIBCXX_HAVE_MBSTATE_T 1 + +/* Define to 1 if you have the `memalign' function. */ +//#define _GLIBCXX_HAVE_MEMALIGN 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `modf' function. */ +/* #undef _GLIBCXX_HAVE_MODF */ + +/* Define to 1 if you have the `modff' function. */ +#define _GLIBCXX_HAVE_MODFF 1 + +/* Define to 1 if you have the `modfl' function. */ +/* #undef _GLIBCXX_HAVE_MODFL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NAN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETINET_IN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETINET_TCP_H */ + +/* Define if defines obsolete isinf function. */ +/* #undef _GLIBCXX_HAVE_OBSOLETE_ISINF */ + +/* Define if defines obsolete isnan function. */ +/* #undef _GLIBCXX_HAVE_OBSOLETE_ISNAN */ + +/* Define if poll is available in . */ +/* #undef _GLIBCXX_HAVE_POLL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_POLL_H */ + +/* Define to 1 if you have the `posix_memalign' function. */ +/* #undef _GLIBCXX_HAVE_POSIX_MEMALIGN */ + +/* Define to 1 if you have the `powf' function. */ +#define _GLIBCXX_HAVE_POWF 1 + +/* Define to 1 if you have the `powl' function. */ +/* #undef _GLIBCXX_HAVE_POWL */ + +/* Define to 1 if you have the `qfpclass' function. */ +/* #undef _GLIBCXX_HAVE_QFPCLASS */ + +/* Define to 1 if you have the `quick_exit' function. */ +/* #undef _GLIBCXX_HAVE_QUICK_EXIT */ + +/* Define to 1 if you have the `setenv' function. */ +/* #undef _GLIBCXX_HAVE_SETENV */ + +/* Define to 1 if you have the `sincos' function. */ +/* #undef _GLIBCXX_HAVE_SINCOS */ + +/* Define to 1 if you have the `sincosf' function. */ +/* #undef _GLIBCXX_HAVE_SINCOSF */ + +/* Define to 1 if you have the `sincosl' function. */ +/* #undef _GLIBCXX_HAVE_SINCOSL */ + +/* Define to 1 if you have the `sinf' function. */ +#define _GLIBCXX_HAVE_SINF 1 + +/* Define to 1 if you have the `sinhf' function. */ +#define _GLIBCXX_HAVE_SINHF 1 + +/* Define to 1 if you have the `sinhl' function. */ +/* #undef _GLIBCXX_HAVE_SINHL */ + +/* Define to 1 if you have the `sinl' function. */ +/* #undef _GLIBCXX_HAVE_SINL */ + +/* Defined if sleep exists. */ +//#define _GLIBCXX_HAVE_SLEEP 1 + +/* Define to 1 if you have the `sqrtf' function. */ +#define _GLIBCXX_HAVE_SQRTF 1 + +/* Define to 1 if you have the `sqrtl' function. */ +/* #undef _GLIBCXX_HAVE_SQRTL */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDALIGN_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDLIB_H 1 + +/* Define if strerror_l is available in . */ +/* #undef _GLIBCXX_HAVE_STRERROR_L */ + +/* Define if strerror_r is available in . */ +#define _GLIBCXX_HAVE_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtof' function. */ +#define _GLIBCXX_HAVE_STRTOF 1 + +/* Define to 1 if you have the `strtold' function. */ +/* #undef _GLIBCXX_HAVE_STRTOLD */ + +/* Define to 1 if `d_type' is a member of `struct dirent'. */ +/* #undef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE */ + +/* Define if strxfrm_l is available in . */ +/* #undef _GLIBCXX_HAVE_STRXFRM_L */ + +/* Define to 1 if the target runtime linker supports binding the same symbol + to different versions. */ +/* #undef _GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_IPC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_ISA_DEFS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_MACHINE_H */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have a suitable header file */ +/* #undef _GLIBCXX_HAVE_SYS_SDT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_STATVFS_H */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SYSINFO_H */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_UIO_H */ + +/* Define if S_IFREG is available in . */ +/* #undef _GLIBCXX_HAVE_S_IFREG */ + +/* Define if S_ISREG is available in . */ +//#define _GLIBCXX_HAVE_S_ISREG 1 + +/* Define to 1 if you have the `tanf' function. */ +#define _GLIBCXX_HAVE_TANF 1 + +/* Define to 1 if you have the `tanhf' function. */ +#define _GLIBCXX_HAVE_TANHF 1 + +/* Define to 1 if you have the `tanhl' function. */ +/* #undef _GLIBCXX_HAVE_TANHL */ + +/* Define to 1 if you have the `tanl' function. */ +/* #undef _GLIBCXX_HAVE_TANL */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_TGMATH_H 1 + +/* Define to 1 if you have the `timespec_get' function. */ +/* #undef _GLIBCXX_HAVE_TIMESPEC_GET */ + +/* Define to 1 if the target supports thread-local storage. */ +/* #undef _GLIBCXX_HAVE_TLS */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_UCHAR_H */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_UNISTD_H 1 + +/* Defined if usleep exists. */ +//#define _GLIBCXX_HAVE_USLEEP 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_UTIME_H 1 + +/* Defined if vfwscanf exists. */ +//#define _GLIBCXX_HAVE_VFWSCANF 1 + +/* Defined if vswscanf exists. */ +//#define _GLIBCXX_HAVE_VSWSCANF 1 + +/* Defined if vwscanf exists. */ +//#define _GLIBCXX_HAVE_VWSCANF 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_WCHAR_H 1 + +/* Defined if wcstof exists. */ +//#define _GLIBCXX_HAVE_WCSTOF 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_WCTYPE_H 1 + +/* Defined if Sleep exists. */ +/* #undef _GLIBCXX_HAVE_WIN32_SLEEP */ + +/* Define if writev is available in . */ +/* #undef _GLIBCXX_HAVE_WRITEV */ + +/* Define to 1 if you have the `_acosf' function. */ +/* #undef _GLIBCXX_HAVE__ACOSF */ + +/* Define to 1 if you have the `_acosl' function. */ +/* #undef _GLIBCXX_HAVE__ACOSL */ + +/* Define to 1 if you have the `_aligned_malloc' function. */ +/* #undef _GLIBCXX_HAVE__ALIGNED_MALLOC */ + +/* Define to 1 if you have the `_asinf' function. */ +/* #undef _GLIBCXX_HAVE__ASINF */ + +/* Define to 1 if you have the `_asinl' function. */ +/* #undef _GLIBCXX_HAVE__ASINL */ + +/* Define to 1 if you have the `_atan2f' function. */ +/* #undef _GLIBCXX_HAVE__ATAN2F */ + +/* Define to 1 if you have the `_atan2l' function. */ +/* #undef _GLIBCXX_HAVE__ATAN2L */ + +/* Define to 1 if you have the `_atanf' function. */ +/* #undef _GLIBCXX_HAVE__ATANF */ + +/* Define to 1 if you have the `_atanl' function. */ +/* #undef _GLIBCXX_HAVE__ATANL */ + +/* Define to 1 if you have the `_ceilf' function. */ +/* #undef _GLIBCXX_HAVE__CEILF */ + +/* Define to 1 if you have the `_ceill' function. */ +/* #undef _GLIBCXX_HAVE__CEILL */ + +/* Define to 1 if you have the `_cosf' function. */ +/* #undef _GLIBCXX_HAVE__COSF */ + +/* Define to 1 if you have the `_coshf' function. */ +/* #undef _GLIBCXX_HAVE__COSHF */ + +/* Define to 1 if you have the `_coshl' function. */ +/* #undef _GLIBCXX_HAVE__COSHL */ + +/* Define to 1 if you have the `_cosl' function. */ +/* #undef _GLIBCXX_HAVE__COSL */ + +/* Define to 1 if you have the `_expf' function. */ +/* #undef _GLIBCXX_HAVE__EXPF */ + +/* Define to 1 if you have the `_expl' function. */ +/* #undef _GLIBCXX_HAVE__EXPL */ + +/* Define to 1 if you have the `_fabsf' function. */ +/* #undef _GLIBCXX_HAVE__FABSF */ + +/* Define to 1 if you have the `_fabsl' function. */ +/* #undef _GLIBCXX_HAVE__FABSL */ + +/* Define to 1 if you have the `_finite' function. */ +/* #undef _GLIBCXX_HAVE__FINITE */ + +/* Define to 1 if you have the `_finitef' function. */ +/* #undef _GLIBCXX_HAVE__FINITEF */ + +/* Define to 1 if you have the `_finitel' function. */ +/* #undef _GLIBCXX_HAVE__FINITEL */ + +/* Define to 1 if you have the `_floorf' function. */ +/* #undef _GLIBCXX_HAVE__FLOORF */ + +/* Define to 1 if you have the `_floorl' function. */ +/* #undef _GLIBCXX_HAVE__FLOORL */ + +/* Define to 1 if you have the `_fmodf' function. */ +/* #undef _GLIBCXX_HAVE__FMODF */ + +/* Define to 1 if you have the `_fmodl' function. */ +/* #undef _GLIBCXX_HAVE__FMODL */ + +/* Define to 1 if you have the `_fpclass' function. */ +/* #undef _GLIBCXX_HAVE__FPCLASS */ + +/* Define to 1 if you have the `_frexpf' function. */ +/* #undef _GLIBCXX_HAVE__FREXPF */ + +/* Define to 1 if you have the `_frexpl' function. */ +/* #undef _GLIBCXX_HAVE__FREXPL */ + +/* Define to 1 if you have the `_hypot' function. */ +/* #undef _GLIBCXX_HAVE__HYPOT */ + +/* Define to 1 if you have the `_hypotf' function. */ +/* #undef _GLIBCXX_HAVE__HYPOTF */ + +/* Define to 1 if you have the `_hypotl' function. */ +/* #undef _GLIBCXX_HAVE__HYPOTL */ + +/* Define to 1 if you have the `_isinf' function. */ +/* #undef _GLIBCXX_HAVE__ISINF */ + +/* Define to 1 if you have the `_isinff' function. */ +/* #undef _GLIBCXX_HAVE__ISINFF */ + +/* Define to 1 if you have the `_isinfl' function. */ +/* #undef _GLIBCXX_HAVE__ISINFL */ + +/* Define to 1 if you have the `_isnan' function. */ +/* #undef _GLIBCXX_HAVE__ISNAN */ + +/* Define to 1 if you have the `_isnanf' function. */ +/* #undef _GLIBCXX_HAVE__ISNANF */ + +/* Define to 1 if you have the `_isnanl' function. */ +/* #undef _GLIBCXX_HAVE__ISNANL */ + +/* Define to 1 if you have the `_ldexpf' function. */ +/* #undef _GLIBCXX_HAVE__LDEXPF */ + +/* Define to 1 if you have the `_ldexpl' function. */ +/* #undef _GLIBCXX_HAVE__LDEXPL */ + +/* Define to 1 if you have the `_log10f' function. */ +/* #undef _GLIBCXX_HAVE__LOG10F */ + +/* Define to 1 if you have the `_log10l' function. */ +/* #undef _GLIBCXX_HAVE__LOG10L */ + +/* Define to 1 if you have the `_logf' function. */ +/* #undef _GLIBCXX_HAVE__LOGF */ + +/* Define to 1 if you have the `_logl' function. */ +/* #undef _GLIBCXX_HAVE__LOGL */ + +/* Define to 1 if you have the `_modf' function. */ +/* #undef _GLIBCXX_HAVE__MODF */ + +/* Define to 1 if you have the `_modff' function. */ +/* #undef _GLIBCXX_HAVE__MODFF */ + +/* Define to 1 if you have the `_modfl' function. */ +/* #undef _GLIBCXX_HAVE__MODFL */ + +/* Define to 1 if you have the `_powf' function. */ +/* #undef _GLIBCXX_HAVE__POWF */ + +/* Define to 1 if you have the `_powl' function. */ +/* #undef _GLIBCXX_HAVE__POWL */ + +/* Define to 1 if you have the `_qfpclass' function. */ +/* #undef _GLIBCXX_HAVE__QFPCLASS */ + +/* Define to 1 if you have the `_sincos' function. */ +/* #undef _GLIBCXX_HAVE__SINCOS */ + +/* Define to 1 if you have the `_sincosf' function. */ +/* #undef _GLIBCXX_HAVE__SINCOSF */ + +/* Define to 1 if you have the `_sincosl' function. */ +/* #undef _GLIBCXX_HAVE__SINCOSL */ + +/* Define to 1 if you have the `_sinf' function. */ +/* #undef _GLIBCXX_HAVE__SINF */ + +/* Define to 1 if you have the `_sinhf' function. */ +/* #undef _GLIBCXX_HAVE__SINHF */ + +/* Define to 1 if you have the `_sinhl' function. */ +/* #undef _GLIBCXX_HAVE__SINHL */ + +/* Define to 1 if you have the `_sinl' function. */ +/* #undef _GLIBCXX_HAVE__SINL */ + +/* Define to 1 if you have the `_sqrtf' function. */ +/* #undef _GLIBCXX_HAVE__SQRTF */ + +/* Define to 1 if you have the `_sqrtl' function. */ +/* #undef _GLIBCXX_HAVE__SQRTL */ + +/* Define to 1 if you have the `_tanf' function. */ +/* #undef _GLIBCXX_HAVE__TANF */ + +/* Define to 1 if you have the `_tanhf' function. */ +/* #undef _GLIBCXX_HAVE__TANHF */ + +/* Define to 1 if you have the `_tanhl' function. */ +/* #undef _GLIBCXX_HAVE__TANHL */ + +/* Define to 1 if you have the `_tanl' function. */ +/* #undef _GLIBCXX_HAVE__TANL */ + +/* Define to 1 if you have the `_wfopen' function. */ +/* #undef _GLIBCXX_HAVE__WFOPEN */ + +/* Define to 1 if you have the `__cxa_thread_atexit' function. */ +/* #undef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT */ + +/* Define to 1 if you have the `__cxa_thread_atexit_impl' function. */ +/* #undef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */ + +/* Define as const if the declaration of iconv() needs const. */ +/* #undef _GLIBCXX_ICONV_CONST */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +/* #undef _GLIBCXX_PACKAGE */ + +/* Define to the address where bug reports for this package should be sent. */ +#define _GLIBCXX_PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define _GLIBCXX_PACKAGE_NAME "package-unused" + +/* Define to the full name and version of this package. */ +#define _GLIBCXX_PACKAGE_STRING "package-unused version-unused" + +/* Define to the one symbol short name of this package. */ +#define _GLIBCXX_PACKAGE_TARNAME "libstdc++" + +/* Define to the home page for this package. */ +#define _GLIBCXX_PACKAGE_URL "" + +/* Define to the version of this package. */ +#define _GLIBCXX_PACKAGE__GLIBCXX_VERSION "version-unused" + +/* The size of `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of `void *', as computed by sizeof. */ +/* #undef SIZEOF_VOID_P */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +/* #undef _GLIBCXX_VERSION */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _GLIBCXX_FILE_OFFSET_BITS */ + +/* Define if C99 functions in should be used in for + C++11. Using compiler builtins for these functions requires corresponding + C99 library functions to be present. */ +/* #undef _GLIBCXX11_USE_C99_COMPLEX */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +#define _GLIBCXX11_USE_C99_MATH 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +#define _GLIBCXX11_USE_C99_STDIO 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +#define _GLIBCXX11_USE_C99_STDLIB 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +//#define _GLIBCXX11_USE_C99_WCHAR 1 + +/* Define if C99 functions in should be used in for + C++98. Using compiler builtins for these functions requires corresponding + C99 library functions to be present. */ +/* #undef _GLIBCXX98_USE_C99_COMPLEX */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +#define _GLIBCXX98_USE_C99_MATH 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +#define _GLIBCXX98_USE_C99_STDIO 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +#define _GLIBCXX98_USE_C99_STDLIB 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +//#define _GLIBCXX98_USE_C99_WCHAR 1 + +/* Define if the compiler supports C++11 atomics. */ +/* #undef _GLIBCXX_ATOMIC_BUILTINS */ + +/* Define to use concept checking code from the boost libraries. */ +/* #undef _GLIBCXX_CONCEPT_CHECKS */ + +/* Define to 1 if a fully dynamic basic_string is wanted, 0 to disable, + undefined for platform defaults */ +#define _GLIBCXX_FULLY_DYNAMIC_STRING 0 + +/* Define if gthreads library is available. */ +/* #undef _GLIBCXX_HAS_GTHREADS */ + +/* Define to 1 if a full hosted library is built, or 0 if freestanding. */ +#define _GLIBCXX_HOSTED 1 + +/* Define if compatibility should be provided for -mlong-double-64. */ + +/* Define to the letter to which size_t is mangled. */ +#define _GLIBCXX_MANGLE_SIZE_T j + +/* Define if C99 llrint and llround functions are missing from . */ +#define _GLIBCXX_NO_C99_ROUNDING_FUNCS + +/* Define if ptrdiff_t is int. */ +#define _GLIBCXX_PTRDIFF_T_IS_INT 1 + +/* Define if using setrlimit to set resource limits during "make check" */ +/* #undef _GLIBCXX_RES_LIMITS */ + +/* Define if size_t is unsigned int. */ +#define _GLIBCXX_SIZE_T_IS_UINT 1 + +/* Define to the value of the EOF integer constant. */ +#define _GLIBCXX_STDIO_EOF -1 + +/* Define to the value of the SEEK_CUR integer constant. */ +#define _GLIBCXX_STDIO_SEEK_CUR 1 + +/* Define to the value of the SEEK_END integer constant. */ +#define _GLIBCXX_STDIO_SEEK_END 2 + +/* Define to use symbol versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER */ + +/* Define to use darwin versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_DARWIN */ + +/* Define to use GNU versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_GNU */ + +/* Define to use GNU namespace versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_GNU_NAMESPACE */ + +/* Define to use Sun versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_SUN */ + +/* Define if C11 functions in should be imported into namespace std + in . */ +/* #undef _GLIBCXX_USE_C11_UCHAR_CXX11 */ + +/* Define if C99 functions or macros from , , , + , and can be used or exposed. */ +/* #undef _GLIBCXX_USE_C99 */ + +/* Define if C99 functions in should be used in . + Using compiler builtins for these functions requires corresponding C99 + library functions to be present. */ +/* #undef _GLIBCXX_USE_C99_COMPLEX_TR1 */ + +/* Define if C99 functions in should be imported in in + namespace std::tr1. */ +#define _GLIBCXX_USE_C99_CTYPE_TR1 1 + +/* Define if C99 functions in should be imported in in + namespace std::tr1. */ +/* #undef _GLIBCXX_USE_C99_FENV_TR1 */ + +/* Define if C99 functions in should be imported in + in namespace std::tr1. */ +#define _GLIBCXX_USE_C99_INTTYPES_TR1 1 + +/* Define if wchar_t C99 functions in should be imported in + in namespace std::tr1. */ +#define _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std::tr1. */ +#define _GLIBCXX_USE_C99_MATH_TR1 1 + +/* Define if C99 types in should be imported in in + namespace std::tr1. */ +#define _GLIBCXX_USE_C99_STDINT_TR1 1 + +/* Defined if clock_gettime syscall has monotonic and realtime clock support. + */ +/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */ + +/* Defined if clock_gettime has monotonic clock support. */ +/* #undef _GLIBCXX_USE_CLOCK_MONOTONIC */ + +/* Defined if clock_gettime has realtime clock support. */ +/* #undef _GLIBCXX_USE_CLOCK_REALTIME */ + +/* Define if ISO/IEC TR 24733 decimal floating point types are supported on + this host. */ +/* #undef _GLIBCXX_USE_DECIMAL_FLOAT */ + +/* Define if /dev/random and /dev/urandom are available for + std::random_device. */ +/* #undef _GLIBCXX_USE_DEV_RANDOM */ + +/* Define if fchmod is available in . */ +//#define _GLIBCXX_USE_FCHMOD 1 + +/* Define if fchmodat is available in . */ +//#define _GLIBCXX_USE_FCHMODAT 1 + + +/* Defined if gettimeofday is available. */ +//#define _GLIBCXX_USE_GETTIMEOFDAY 1 + +/* Define if get_nprocs is available in . */ +/* #undef _GLIBCXX_USE_GET_NPROCS */ + +/* Define if __int128 is supported on this host. */ +/* #undef _GLIBCXX_USE_INT128 */ + +/* Define if LFS support is available. */ +/* #undef _GLIBCXX_USE_LFS */ + +/* Define if code specialized for long long should be used. */ +#define _GLIBCXX_USE_LONG_LONG 1 + +/* Define if lstat is available in . */ +/* #undef _GLIBCXX_USE_LSTAT */ + +/* Defined if nanosleep is available. */ +/* #undef _GLIBCXX_USE_NANOSLEEP */ + +/* Define if NLS translations are to be used. */ +/* #undef _GLIBCXX_USE_NLS */ + +/* Define if pthreads_num_processors_np is available in . */ +/* #undef _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP */ + +/* Define if pthread_cond_clockwait is available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT */ + +/* Define if pthread_mutex_clocklock is available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK */ + +/* Define if pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock are + available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK */ + +/* Define if POSIX read/write locks are available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_RWLOCK_T */ + +/* Define if /dev/random and /dev/urandom are available for the random_device + of TR1 (Chapter 5.1). */ +/* #undef _GLIBCXX_USE_RANDOM_TR1 */ + +/* Define if usable realpath is available in . */ +/* #undef _GLIBCXX_USE_REALPATH */ + +/* Defined if sched_yield is available. */ +/* #undef _GLIBCXX_USE_SCHED_YIELD */ + +/* Define if _SC_NPROCESSORS_ONLN is available in . */ +//#define _GLIBCXX_USE_SC_NPROCESSORS_ONLN 1 + +/* Define if _SC_NPROC_ONLN is available in . */ +/* #undef _GLIBCXX_USE_SC_NPROC_ONLN */ + +/* Define if sendfile is available in . */ +/* #undef _GLIBCXX_USE_SENDFILE */ + +/* Define if struct stat has timespec members. */ +/* #undef _GLIBCXX_USE_ST_MTIM */ + +/* Define if sysctl(), CTL_HW and HW_NCPU are available in . */ +/* #undef _GLIBCXX_USE_SYSCTL_HW_NCPU */ + +/* Define if obsolescent tmpnam is available in . */ +#define _GLIBCXX_USE_TMPNAM 1 + +/* Define if utimensat and UTIME_OMIT are available in and + AT_FDCWD in . */ +/* #undef _GLIBCXX_USE_UTIMENSAT */ + +/* Define if code specialized for wchar_t should be used. */ +//#define _GLIBCXX_USE_WCHAR_T 1 + +/* Define to 1 if a verbose library is built, or 0 otherwise. */ +#define _GLIBCXX_VERBOSE 1 + +/* Defined if as can handle rdrand. */ +/* #undef _GLIBCXX_X86_RDRAND */ + +/* Defined if as can handle rdseed. */ +/* #undef _GLIBCXX_X86_RDSEED */ + +/* Define to 1 if mutex_timedlock is available. */ +//#define _GTHREAD_USE_MUTEX_TIMEDLOCK 1 + +/* Define for large files, on AIX-style hosts. */ +/* #undef _GLIBCXX_LARGE_FILES */ + +/* Define if all C++11 floating point overloads are available in . */ +#if __cplusplus >= 201103L +/* #undef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP */ +#endif + +/* Define if all C++11 integral type overloads are available in . */ +#if __cplusplus >= 201103L +/* #undef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT */ +#endif + +#if defined (_GLIBCXX_HAVE__ACOSF) && ! defined (_GLIBCXX_HAVE_ACOSF) +# define _GLIBCXX_HAVE_ACOSF 1 +# define acosf _acosf +#endif + +#if defined (_GLIBCXX_HAVE__ACOSL) && ! defined (_GLIBCXX_HAVE_ACOSL) +# define _GLIBCXX_HAVE_ACOSL 1 +# define acosl _acosl +#endif + +#if defined (_GLIBCXX_HAVE__ASINF) && ! defined (_GLIBCXX_HAVE_ASINF) +# define _GLIBCXX_HAVE_ASINF 1 +# define asinf _asinf +#endif + +#if defined (_GLIBCXX_HAVE__ASINL) && ! defined (_GLIBCXX_HAVE_ASINL) +# define _GLIBCXX_HAVE_ASINL 1 +# define asinl _asinl +#endif + +#if defined (_GLIBCXX_HAVE__ATAN2F) && ! defined (_GLIBCXX_HAVE_ATAN2F) +# define _GLIBCXX_HAVE_ATAN2F 1 +# define atan2f _atan2f +#endif + +#if defined (_GLIBCXX_HAVE__ATAN2L) && ! defined (_GLIBCXX_HAVE_ATAN2L) +# define _GLIBCXX_HAVE_ATAN2L 1 +# define atan2l _atan2l +#endif + +#if defined (_GLIBCXX_HAVE__ATANF) && ! defined (_GLIBCXX_HAVE_ATANF) +# define _GLIBCXX_HAVE_ATANF 1 +# define atanf _atanf +#endif + +#if defined (_GLIBCXX_HAVE__ATANL) && ! defined (_GLIBCXX_HAVE_ATANL) +# define _GLIBCXX_HAVE_ATANL 1 +# define atanl _atanl +#endif + +#if defined (_GLIBCXX_HAVE__CEILF) && ! defined (_GLIBCXX_HAVE_CEILF) +# define _GLIBCXX_HAVE_CEILF 1 +# define ceilf _ceilf +#endif + +#if defined (_GLIBCXX_HAVE__CEILL) && ! defined (_GLIBCXX_HAVE_CEILL) +# define _GLIBCXX_HAVE_CEILL 1 +# define ceill _ceill +#endif + +#if defined (_GLIBCXX_HAVE__COSF) && ! defined (_GLIBCXX_HAVE_COSF) +# define _GLIBCXX_HAVE_COSF 1 +# define cosf _cosf +#endif + +#if defined (_GLIBCXX_HAVE__COSHF) && ! defined (_GLIBCXX_HAVE_COSHF) +# define _GLIBCXX_HAVE_COSHF 1 +# define coshf _coshf +#endif + +#if defined (_GLIBCXX_HAVE__COSHL) && ! defined (_GLIBCXX_HAVE_COSHL) +# define _GLIBCXX_HAVE_COSHL 1 +# define coshl _coshl +#endif + +#if defined (_GLIBCXX_HAVE__COSL) && ! defined (_GLIBCXX_HAVE_COSL) +# define _GLIBCXX_HAVE_COSL 1 +# define cosl _cosl +#endif + +#if defined (_GLIBCXX_HAVE__EXPF) && ! defined (_GLIBCXX_HAVE_EXPF) +# define _GLIBCXX_HAVE_EXPF 1 +# define expf _expf +#endif + +#if defined (_GLIBCXX_HAVE__EXPL) && ! defined (_GLIBCXX_HAVE_EXPL) +# define _GLIBCXX_HAVE_EXPL 1 +# define expl _expl +#endif + +#if defined (_GLIBCXX_HAVE__FABSF) && ! defined (_GLIBCXX_HAVE_FABSF) +# define _GLIBCXX_HAVE_FABSF 1 +# define fabsf _fabsf +#endif + +#if defined (_GLIBCXX_HAVE__FABSL) && ! defined (_GLIBCXX_HAVE_FABSL) +# define _GLIBCXX_HAVE_FABSL 1 +# define fabsl _fabsl +#endif + +#if defined (_GLIBCXX_HAVE__FINITE) && ! defined (_GLIBCXX_HAVE_FINITE) +# define _GLIBCXX_HAVE_FINITE 1 +# define finite _finite +#endif + +#if defined (_GLIBCXX_HAVE__FINITEF) && ! defined (_GLIBCXX_HAVE_FINITEF) +# define _GLIBCXX_HAVE_FINITEF 1 +# define finitef _finitef +#endif + +#if defined (_GLIBCXX_HAVE__FINITEL) && ! defined (_GLIBCXX_HAVE_FINITEL) +# define _GLIBCXX_HAVE_FINITEL 1 +# define finitel _finitel +#endif + +#if defined (_GLIBCXX_HAVE__FLOORF) && ! defined (_GLIBCXX_HAVE_FLOORF) +# define _GLIBCXX_HAVE_FLOORF 1 +# define floorf _floorf +#endif + +#if defined (_GLIBCXX_HAVE__FLOORL) && ! defined (_GLIBCXX_HAVE_FLOORL) +# define _GLIBCXX_HAVE_FLOORL 1 +# define floorl _floorl +#endif + +#if defined (_GLIBCXX_HAVE__FMODF) && ! defined (_GLIBCXX_HAVE_FMODF) +# define _GLIBCXX_HAVE_FMODF 1 +# define fmodf _fmodf +#endif + +#if defined (_GLIBCXX_HAVE__FMODL) && ! defined (_GLIBCXX_HAVE_FMODL) +# define _GLIBCXX_HAVE_FMODL 1 +# define fmodl _fmodl +#endif + +#if defined (_GLIBCXX_HAVE__FPCLASS) && ! defined (_GLIBCXX_HAVE_FPCLASS) +# define _GLIBCXX_HAVE_FPCLASS 1 +# define fpclass _fpclass +#endif + +#if defined (_GLIBCXX_HAVE__FREXPF) && ! defined (_GLIBCXX_HAVE_FREXPF) +# define _GLIBCXX_HAVE_FREXPF 1 +# define frexpf _frexpf +#endif + +#if defined (_GLIBCXX_HAVE__FREXPL) && ! defined (_GLIBCXX_HAVE_FREXPL) +# define _GLIBCXX_HAVE_FREXPL 1 +# define frexpl _frexpl +#endif + +#if defined (_GLIBCXX_HAVE__HYPOT) && ! defined (_GLIBCXX_HAVE_HYPOT) +# define _GLIBCXX_HAVE_HYPOT 1 +# define hypot _hypot +#endif + +#if defined (_GLIBCXX_HAVE__HYPOTF) && ! defined (_GLIBCXX_HAVE_HYPOTF) +# define _GLIBCXX_HAVE_HYPOTF 1 +# define hypotf _hypotf +#endif + +#if defined (_GLIBCXX_HAVE__HYPOTL) && ! defined (_GLIBCXX_HAVE_HYPOTL) +# define _GLIBCXX_HAVE_HYPOTL 1 +# define hypotl _hypotl +#endif + +#if defined (_GLIBCXX_HAVE__ISINF) && ! defined (_GLIBCXX_HAVE_ISINF) +# define _GLIBCXX_HAVE_ISINF 1 +# define isinf _isinf +#endif + +#if defined (_GLIBCXX_HAVE__ISINFF) && ! defined (_GLIBCXX_HAVE_ISINFF) +# define _GLIBCXX_HAVE_ISINFF 1 +# define isinff _isinff +#endif + +#if defined (_GLIBCXX_HAVE__ISINFL) && ! defined (_GLIBCXX_HAVE_ISINFL) +# define _GLIBCXX_HAVE_ISINFL 1 +# define isinfl _isinfl +#endif + +#if defined (_GLIBCXX_HAVE__ISNAN) && ! defined (_GLIBCXX_HAVE_ISNAN) +# define _GLIBCXX_HAVE_ISNAN 1 +# define isnan _isnan +#endif + +#if defined (_GLIBCXX_HAVE__ISNANF) && ! defined (_GLIBCXX_HAVE_ISNANF) +# define _GLIBCXX_HAVE_ISNANF 1 +# define isnanf _isnanf +#endif + +#if defined (_GLIBCXX_HAVE__ISNANL) && ! defined (_GLIBCXX_HAVE_ISNANL) +# define _GLIBCXX_HAVE_ISNANL 1 +# define isnanl _isnanl +#endif + +#if defined (_GLIBCXX_HAVE__LDEXPF) && ! defined (_GLIBCXX_HAVE_LDEXPF) +# define _GLIBCXX_HAVE_LDEXPF 1 +# define ldexpf _ldexpf +#endif + +#if defined (_GLIBCXX_HAVE__LDEXPL) && ! defined (_GLIBCXX_HAVE_LDEXPL) +# define _GLIBCXX_HAVE_LDEXPL 1 +# define ldexpl _ldexpl +#endif + +#if defined (_GLIBCXX_HAVE__LOG10F) && ! defined (_GLIBCXX_HAVE_LOG10F) +# define _GLIBCXX_HAVE_LOG10F 1 +# define log10f _log10f +#endif + +#if defined (_GLIBCXX_HAVE__LOG10L) && ! defined (_GLIBCXX_HAVE_LOG10L) +# define _GLIBCXX_HAVE_LOG10L 1 +# define log10l _log10l +#endif + +#if defined (_GLIBCXX_HAVE__LOGF) && ! defined (_GLIBCXX_HAVE_LOGF) +# define _GLIBCXX_HAVE_LOGF 1 +# define logf _logf +#endif + +#if defined (_GLIBCXX_HAVE__LOGL) && ! defined (_GLIBCXX_HAVE_LOGL) +# define _GLIBCXX_HAVE_LOGL 1 +# define logl _logl +#endif + +#if defined (_GLIBCXX_HAVE__MODF) && ! defined (_GLIBCXX_HAVE_MODF) +# define _GLIBCXX_HAVE_MODF 1 +# define modf _modf +#endif + +#if defined (_GLIBCXX_HAVE__MODFF) && ! defined (_GLIBCXX_HAVE_MODFF) +# define _GLIBCXX_HAVE_MODFF 1 +# define modff _modff +#endif + +#if defined (_GLIBCXX_HAVE__MODFL) && ! defined (_GLIBCXX_HAVE_MODFL) +# define _GLIBCXX_HAVE_MODFL 1 +# define modfl _modfl +#endif + +#if defined (_GLIBCXX_HAVE__POWF) && ! defined (_GLIBCXX_HAVE_POWF) +# define _GLIBCXX_HAVE_POWF 1 +# define powf _powf +#endif + +#if defined (_GLIBCXX_HAVE__POWL) && ! defined (_GLIBCXX_HAVE_POWL) +# define _GLIBCXX_HAVE_POWL 1 +# define powl _powl +#endif + +#if defined (_GLIBCXX_HAVE__QFPCLASS) && ! defined (_GLIBCXX_HAVE_QFPCLASS) +# define _GLIBCXX_HAVE_QFPCLASS 1 +# define qfpclass _qfpclass +#endif + +#if defined (_GLIBCXX_HAVE__SINCOS) && ! defined (_GLIBCXX_HAVE_SINCOS) +# define _GLIBCXX_HAVE_SINCOS 1 +# define sincos _sincos +#endif + +#if defined (_GLIBCXX_HAVE__SINCOSF) && ! defined (_GLIBCXX_HAVE_SINCOSF) +# define _GLIBCXX_HAVE_SINCOSF 1 +# define sincosf _sincosf +#endif + +#if defined (_GLIBCXX_HAVE__SINCOSL) && ! defined (_GLIBCXX_HAVE_SINCOSL) +# define _GLIBCXX_HAVE_SINCOSL 1 +# define sincosl _sincosl +#endif + +#if defined (_GLIBCXX_HAVE__SINF) && ! defined (_GLIBCXX_HAVE_SINF) +# define _GLIBCXX_HAVE_SINF 1 +# define sinf _sinf +#endif + +#if defined (_GLIBCXX_HAVE__SINHF) && ! defined (_GLIBCXX_HAVE_SINHF) +# define _GLIBCXX_HAVE_SINHF 1 +# define sinhf _sinhf +#endif + +#if defined (_GLIBCXX_HAVE__SINHL) && ! defined (_GLIBCXX_HAVE_SINHL) +# define _GLIBCXX_HAVE_SINHL 1 +# define sinhl _sinhl +#endif + +#if defined (_GLIBCXX_HAVE__SINL) && ! defined (_GLIBCXX_HAVE_SINL) +# define _GLIBCXX_HAVE_SINL 1 +# define sinl _sinl +#endif + +#if defined (_GLIBCXX_HAVE__SQRTF) && ! defined (_GLIBCXX_HAVE_SQRTF) +# define _GLIBCXX_HAVE_SQRTF 1 +# define sqrtf _sqrtf +#endif + +#if defined (_GLIBCXX_HAVE__SQRTL) && ! defined (_GLIBCXX_HAVE_SQRTL) +# define _GLIBCXX_HAVE_SQRTL 1 +# define sqrtl _sqrtl +#endif + +#if defined (_GLIBCXX_HAVE__STRTOF) && ! defined (_GLIBCXX_HAVE_STRTOF) +# define _GLIBCXX_HAVE_STRTOF 1 +# define strtof _strtof +#endif + +#if defined (_GLIBCXX_HAVE__STRTOLD) && ! defined (_GLIBCXX_HAVE_STRTOLD) +# define _GLIBCXX_HAVE_STRTOLD 1 +# define strtold _strtold +#endif + +#if defined (_GLIBCXX_HAVE__TANF) && ! defined (_GLIBCXX_HAVE_TANF) +# define _GLIBCXX_HAVE_TANF 1 +# define tanf _tanf +#endif + +#if defined (_GLIBCXX_HAVE__TANHF) && ! defined (_GLIBCXX_HAVE_TANHF) +# define _GLIBCXX_HAVE_TANHF 1 +# define tanhf _tanhf +#endif + +#if defined (_GLIBCXX_HAVE__TANHL) && ! defined (_GLIBCXX_HAVE_TANHL) +# define _GLIBCXX_HAVE_TANHL 1 +# define tanhl _tanhl +#endif + +#if defined (_GLIBCXX_HAVE__TANL) && ! defined (_GLIBCXX_HAVE_TANL) +# define _GLIBCXX_HAVE_TANL 1 +# define tanl _tanl +#endif + +#endif // _GLIBCXX_CXX_CONFIG_H diff --git a/resources/sources/avr-libstdcpp/include/bits/char_traits.h b/resources/sources/avr-libstdcpp/include/bits/char_traits.h new file mode 100644 index 000000000..c6da184e4 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/char_traits.h @@ -0,0 +1,943 @@ +// Character Traits for use by standard string and iostream -*- C++ -*- + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/char_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{string} + */ + +// +// ISO C++ 14882: 21 Strings library +// + +#ifndef _CHAR_TRAITS_H +#define _CHAR_TRAITS_H 1 + +#pragma GCC system_header + +#include // std::copy, std::fill_n +#include // For streampos +#include // For WEOF, wmemmove, wmemset, etc. +#if __cplusplus > 201703L +# include +#endif + +#ifndef _GLIBCXX_ALWAYS_INLINE +# define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Mapping from character type to associated types. + * + * @note This is an implementation class for the generic version + * of char_traits. It defines int_type, off_type, pos_type, and + * state_type. By default these are unsigned long, streamoff, + * streampos, and mbstate_t. Users who need a different set of + * types, but who don't need to change the definitions of any function + * defined in char_traits, can specialize __gnu_cxx::_Char_types + * while leaving __gnu_cxx::char_traits alone. */ + template + struct _Char_types + { + typedef unsigned long int_type; + typedef std::streampos pos_type; + typedef std::streamoff off_type; + typedef std::mbstate_t state_type; + }; + + + /** + * @brief Base class used to implement std::char_traits. + * + * @note For any given actual character type, this definition is + * probably wrong. (Most of the member functions are likely to be + * right, but the int_type and state_type typedefs, and the eof() + * member function, are likely to be wrong.) The reason this class + * exists is so users can specialize it. Classes in namespace std + * may not be specialized for fundamental types, but classes in + * namespace __gnu_cxx may be. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types + * for advice on how to make use of this class for @a unusual character + * types. Also, check out include/ext/pod_char_traits.h. + */ + template + struct char_traits + { + typedef _CharT char_type; + typedef typename _Char_types<_CharT>::int_type int_type; + typedef typename _Char_types<_CharT>::pos_type pos_type; + typedef typename _Char_types<_CharT>::off_type off_type; + typedef typename _Char_types<_CharT>::state_type state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = std::strong_ordering; +#endif + + static _GLIBCXX14_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } + + static _GLIBCXX14_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX14_CONSTEXPR std::size_t + length(const char_type* __s); + + static _GLIBCXX14_CONSTEXPR const char_type* + find(const char_type* __s, std::size_t __n, const char_type& __a); + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, std::size_t __n, char_type __a); + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) + { return static_cast(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) + { return static_cast(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() + { return static_cast(_GLIBCXX_STDIO_EOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) + { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } + }; + + template + _GLIBCXX14_CONSTEXPR int + char_traits<_CharT>:: + compare(const char_type* __s1, const char_type* __s2, std::size_t __n) + { + for (std::size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + template + _GLIBCXX14_CONSTEXPR std::size_t + char_traits<_CharT>:: + length(const char_type* __p) + { + std::size_t __i = 0; + while (!eq(__p[__i], char_type())) + ++__i; + return __i; + } + + template + _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + find(const char_type* __s, std::size_t __n, const char_type& __a) + { + for (std::size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + move(char_type* __s1, const char_type* __s2, std::size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + if (__s1 > __s2 && __s1 < __s2 + __n) + std::copy_backward(__s2, __s2 + __n, __s1); + else + std::copy(__s2, __s2 + __n, __s1); + return __s1; + } +#endif + return static_cast<_CharT*>(__builtin_memmove(__s1, __s2, + __n * sizeof(char_type))); + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + copy(char_type* __s1, const char_type* __s2, std::size_t __n) + { + // NB: Inline std::copy so no recursive dependencies. + std::copy(__s2, __s2 + __n, __s1); + return __s1; + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + assign(char_type* __s, std::size_t __n, char_type __a) + { + // NB: Inline std::fill_n so no recursive dependencies. + std::fill_n(__s, __n, __a); + return __s; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201703L +#define __cpp_lib_constexpr_char_traits 201611 + + /** + * @brief Determine whether the characters of a NULL-terminated + * string are known at compile time. + * @param __s The string. + * + * Assumes that _CharT is a built-in character type. + */ + template + static _GLIBCXX_ALWAYS_INLINE constexpr bool + __constant_string_p(const _CharT* __s) + { +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + (void) __s; + // In constexpr contexts all strings should be constant. + return __builtin_is_constant_evaluated(); +#else + while (__builtin_constant_p(*__s) && *__s) + __s++; + return __builtin_constant_p(*__s); +#endif + } + + /** + * @brief Determine whether the characters of a character array are + * known at compile time. + * @param __a The character array. + * @param __n Number of characters. + * + * Assumes that _CharT is a built-in character type. + */ + template + static _GLIBCXX_ALWAYS_INLINE constexpr bool + __constant_char_array_p(const _CharT* __a, size_t __n) + { +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + (void) __a; + (void) __n; + // In constexpr contexts all character arrays should be constant. + return __builtin_is_constant_evaluated(); +#else + size_t __i = 0; + while (__i < __n && __builtin_constant_p(__a[__i])) + __i++; + return __i == __n; +#endif + } +#endif + + // 21.1 + /** + * @brief Basis for explicit traits specializations. + * + * @note For any given actual character type, this definition is + * probably wrong. Since this is just a thin wrapper around + * __gnu_cxx::char_traits, it is possible to achieve a more + * appropriate definition by specializing __gnu_cxx::char_traits. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types + * for advice on how to make use of this class for @a unusual character + * types. Also, check out include/ext/pod_char_traits.h. + */ + template + struct char_traits : public __gnu_cxx::char_traits<_CharT> + { }; + + + /// 21.1.3.1 char_traits specializations + template<> + struct char_traits + { + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { + // LWG 467. + return (static_cast(__c1) + < static_cast(__c2)); + } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits::compare(__s1, __s2, __n); +#endif + return __builtin_memcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus >= 201703L + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits::length(__s); +#endif + return __builtin_strlen(__s); + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return static_cast(__builtin_memchr(__s, __a, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return static_cast(__builtin_memmove(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return static_cast(__builtin_memcpy(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return static_cast(__builtin_memset(__s, __a, __n)); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return static_cast(__c); } + + // To keep both the byte 0xff and the eof symbol 0xffffffff + // from ending up as 0xffffffff. + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return static_cast(static_cast(__c)); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(_GLIBCXX_STDIO_EOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return (__c == eof()) ? 0 : __c; } + }; + + +#ifdef _GLIBCXX_USE_WCHAR_T + /// 21.1.3.2 char_traits specializations + template<> + struct char_traits + { + typedef wchar_t char_type; + typedef wint_t int_type; + typedef streamoff off_type; + typedef wstreampos pos_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits::compare(__s1, __s2, __n); +#endif + return wmemcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus >= 201703L + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits::length(__s); +#endif + return wcslen(__s); + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return wmemchr(__s, __a, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return wmemmove(__s1, __s2, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return wmemcpy(__s1, __s2, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return wmemset(__s, __a, __n); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return char_type(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return int_type(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(WEOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; +#endif //_GLIBCXX_USE_WCHAR_T + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct char_traits + { + typedef char8_t char_type; + typedef unsigned int int_type; + typedef u8streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits::compare(__s1, __s2, __n); +#endif + return __builtin_memcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus > 201402 + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits::length(__s); +#endif + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return static_cast(__builtin_memchr(__s, __a, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return static_cast(__builtin_memmove(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return static_cast(__builtin_memcpy(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return static_cast(__builtin_memset(__s, __a, __n)); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return char_type(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return int_type(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(-1); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; +#endif //_GLIBCXX_USE_CHAR8_T + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if __cplusplus >= 201103L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<> + struct char_traits + { + typedef char16_t char_type; +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + typedef uint_least16_t int_type; +#elif defined __UINT_LEAST16_TYPE__ + typedef __UINT_LEAST16_TYPE__ int_type; +#else + typedef make_unsigned::type int_type; +#endif + typedef streamoff off_type; + typedef u16streampos pos_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) noexcept + { __c1 = __c2; } + + static constexpr bool + eq(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr bool + lt(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + for (size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + for (size_t __i = 0; __i < __n; ++__i) + assign(__s[__i], __a); + return __s; + } + + static constexpr char_type + to_char_type(const int_type& __c) noexcept + { return char_type(__c); } + + static constexpr int_type + to_int_type(const char_type& __c) noexcept + { return __c == eof() ? int_type(0xfffd) : int_type(__c); } + + static constexpr bool + eq_int_type(const int_type& __c1, const int_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr int_type + eof() noexcept + { return static_cast(-1); } + + static constexpr int_type + not_eof(const int_type& __c) noexcept + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; + + template<> + struct char_traits + { + typedef char32_t char_type; +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + typedef uint_least32_t int_type; +#elif defined __UINT_LEAST32_TYPE__ + typedef __UINT_LEAST32_TYPE__ int_type; +#else + typedef make_unsigned::type int_type; +#endif + typedef streamoff off_type; + typedef u32streampos pos_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) noexcept + { __c1 = __c2; } + + static constexpr bool + eq(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr bool + lt(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + for (size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + for (size_t __i = 0; __i < __n; ++__i) + assign(__s[__i], __a); + return __s; + } + + static constexpr char_type + to_char_type(const int_type& __c) noexcept + { return char_type(__c); } + + static constexpr int_type + to_int_type(const char_type& __c) noexcept + { return int_type(__c); } + + static constexpr bool + eq_int_type(const int_type& __c1, const int_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr int_type + eof() noexcept + { return static_cast(-1); } + + static constexpr int_type + not_eof(const int_type& __c) noexcept + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; + +#if __cpp_lib_three_way_comparison + namespace __detail + { + template + constexpr auto + __char_traits_cmp_cat(int __cmp) noexcept + { + if constexpr (requires { typename _ChTraits::comparison_category; }) + { + using _Cat = typename _ChTraits::comparison_category; + static_assert( !is_void_v> ); + return static_cast<_Cat>(__cmp <=> 0); + } + else + return static_cast(__cmp <=> 0); + } + } // namespace __detail +#endif // C++20 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _CHAR_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/charconv.h b/resources/sources/avr-libstdcpp/include/bits/charconv.h new file mode 100644 index 000000000..a3149bddb --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/charconv.h @@ -0,0 +1,106 @@ +// Numeric conversions (to_string, to_chars) -*- C++ -*- + +// Copyright (C) 2017-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/charconv.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{charconv} + */ + +#ifndef _GLIBCXX_CHARCONV_H +#define _GLIBCXX_CHARCONV_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace __detail +{ + // Generic implementation for arbitrary bases. + template + _GLIBCXX14_CONSTEXPR unsigned + __to_chars_len(_Tp __value, int __base = 10) noexcept + { + static_assert(is_integral<_Tp>::value, "implementation bug"); + static_assert(is_unsigned<_Tp>::value, "implementation bug"); + + unsigned __n = 1; + const unsigned __b2 = __base * __base; + const unsigned __b3 = __b2 * __base; + const unsigned long __b4 = __b3 * __base; + for (;;) + { + if (__value < (unsigned)__base) return __n; + if (__value < __b2) return __n + 1; + if (__value < __b3) return __n + 2; + if (__value < __b4) return __n + 3; + __value /= __b4; + __n += 4; + } + } + + // Write an unsigned integer value to the range [first,first+len). + // The caller is required to provide a buffer of exactly the right size + // (which can be determined by the __to_chars_len function). + template + void + __to_chars_10_impl(char* __first, unsigned __len, _Tp __val) noexcept + { + static_assert(is_integral<_Tp>::value, "implementation bug"); + static_assert(is_unsigned<_Tp>::value, "implementation bug"); + + static constexpr char __digits[201] = + "0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"; + unsigned __pos = __len - 1; + while (__val >= 100) + { + auto const __num = (__val % 100) * 2; + __val /= 100; + __first[__pos] = __digits[__num + 1]; + __first[__pos - 1] = __digits[__num]; + __pos -= 2; + } + if (__val >= 10) + { + auto const __num = __val * 2; + __first[1] = __digits[__num + 1]; + __first[0] = __digits[__num]; + } + else + __first[0] = '0' + __val; + } + +} // namespace __detail +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++11 +#endif // _GLIBCXX_CHARCONV_H diff --git a/resources/sources/avr-libstdcpp/include/bits/concept_check.h b/resources/sources/avr-libstdcpp/include/bits/concept_check.h new file mode 100644 index 000000000..8923a71fc --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/concept_check.h @@ -0,0 +1,81 @@ +// Concept-checking control -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/concept_check.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _CONCEPT_CHECK_H +#define _CONCEPT_CHECK_H 1 + +#pragma GCC system_header + +#include + +// All places in libstdc++-v3 where these are used, or /might/ be used, or +// don't need to be used, or perhaps /should/ be used, are commented with +// "concept requirements" (and maybe some more text). So grep like crazy +// if you're looking for additional places to use these. + +// Concept-checking code is off by default unless users turn it on via +// configure options or editing c++config.h. +// It is not supported for freestanding implementations. + +#if !defined(_GLIBCXX_CONCEPT_CHECKS) || !_GLIBCXX_HOSTED + +#define __glibcxx_function_requires(...) +#define __glibcxx_class_requires(_a,_b) +#define __glibcxx_class_requires2(_a,_b,_c) +#define __glibcxx_class_requires3(_a,_b,_c,_d) +#define __glibcxx_class_requires4(_a,_b,_c,_d,_e) + +#else // the checks are on + +#include + +// Note that the obvious and elegant approach of +// +//#define glibcxx_function_requires(C) debug::function_requires< debug::C >() +// +// won't work due to concept templates with more than one parameter, e.g., +// BinaryPredicateConcept. The preprocessor tries to split things up on +// the commas in the template argument list. We can't use an inner pair of +// parenthesis to hide the commas, because "debug::(Temp)" isn't +// a valid instantiation pattern. Thus, we steal a feature from C99. + +#define __glibcxx_function_requires(...) \ + __gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >(); +#define __glibcxx_class_requires(_a,_C) \ + _GLIBCXX_CLASS_REQUIRES(_a, __gnu_cxx, _C); +#define __glibcxx_class_requires2(_a,_b,_C) \ + _GLIBCXX_CLASS_REQUIRES2(_a, _b, __gnu_cxx, _C); +#define __glibcxx_class_requires3(_a,_b,_c,_C) \ + _GLIBCXX_CLASS_REQUIRES3(_a, _b, _c, __gnu_cxx, _C); +#define __glibcxx_class_requires4(_a,_b,_c,_d,_C) \ + _GLIBCXX_CLASS_REQUIRES4(_a, _b, _c, _d, __gnu_cxx, _C); + +#endif // enable/disable + +#endif // _GLIBCXX_CONCEPT_CHECK diff --git a/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h b/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h new file mode 100644 index 000000000..ca83f590e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h @@ -0,0 +1,551 @@ +// The -*- C++ -*- type traits classes for internal use in libstdc++ + +// Copyright (C) 2000-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cpp_type_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ext/type_traits} + */ + +// Written by Gabriel Dos Reis + +#ifndef _CPP_TYPE_TRAITS_H +#define _CPP_TYPE_TRAITS_H 1 + +#pragma GCC system_header + +#include + +// +// This file provides some compile-time information about various types. +// These representations were designed, on purpose, to be constant-expressions +// and not types as found in . In particular, they +// can be used in control structures and the optimizer hopefully will do +// the obvious thing. +// +// Why integral expressions, and not functions nor types? +// Firstly, these compile-time entities are used as template-arguments +// so function return values won't work: We need compile-time entities. +// We're left with types and constant integral expressions. +// Secondly, from the point of view of ease of use, type-based compile-time +// information is -not- *that* convenient. One has to write lots of +// overloaded functions and to hope that the compiler will select the right +// one. As a net effect, the overall structure isn't very clear at first +// glance. +// Thirdly, partial ordering and overload resolution (of function templates) +// is highly costly in terms of compiler-resource. It is a Good Thing to +// keep these resource consumption as least as possible. +// +// See valarray_array.h for a case use. +// +// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06. +// +// Update 2005: types are also provided and has been +// removed. +// + +extern "C++" { + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct __true_type { }; + struct __false_type { }; + + template + struct __truth_type + { typedef __false_type __type; }; + + template<> + struct __truth_type + { typedef __true_type __type; }; + + // N.B. The conversions to bool are needed due to the issue + // explained in c++/19404. + template + struct __traitor + { + enum { __value = bool(_Sp::__value) || bool(_Tp::__value) }; + typedef typename __truth_type<__value>::__type __type; + }; + + // Compare for equality of types. + template + struct __are_same + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template + struct __are_same<_Tp, _Tp> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // Holds if the template-argument is a void type. + template + struct __is_void + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_void + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // + // Integer types + // + template + struct __is_integer + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // Thirteen specializations (yes there are eleven standard integer + // types; long long and unsigned long long are + // supported as extensions). Up to four target-specific __int + // types are supported as well. + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +# ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +# endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#if __cplusplus >= 201103L + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#define __INT_N(TYPE) \ + template<> \ + struct __is_integer \ + { \ + enum { __value = 1 }; \ + typedef __true_type __type; \ + }; \ + template<> \ + struct __is_integer \ + { \ + enum { __value = 1 }; \ + typedef __true_type __type; \ + }; + +#ifdef __GLIBCXX_TYPE_INT_N_0 +__INT_N(__GLIBCXX_TYPE_INT_N_0) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 +__INT_N(__GLIBCXX_TYPE_INT_N_1) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 +__INT_N(__GLIBCXX_TYPE_INT_N_2) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 +__INT_N(__GLIBCXX_TYPE_INT_N_3) +#endif + +#undef __INT_N + + // + // Floating point types + // + template + struct __is_floating + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // three specializations (float, double and 'long double') + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // + // Pointer types + // + template + struct __is_pointer + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template + struct __is_pointer<_Tp*> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // + // An arithmetic type is an integer type or a floating point type + // + template + struct __is_arithmetic + : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> > + { }; + + // + // A scalar type is an arithmetic type or a pointer type + // + template + struct __is_scalar + : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> > + { }; + + // + // For use in std::copy and std::find overloads for streambuf iterators. + // + template + struct __is_char + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_char + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct __is_char + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template + struct __is_byte + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#if __cplusplus >= 201703L + enum class byte : unsigned char; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif // C++17 + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template struct iterator_traits; + + // A type that is safe for use with memcpy, memmove, memcmp etc. + template + struct __is_nonvolatile_trivially_copyable + { + enum { __value = __is_trivially_copyable(_Tp) }; + }; + + // Cannot use memcpy/memmove/memcmp on volatile types even if they are + // trivially copyable, so ensure __memcpyable + // and similar will be false. + template + struct __is_nonvolatile_trivially_copyable + { + enum { __value = 0 }; + }; + + // Whether two iterator types can be used with memcpy/memmove. + template + struct __memcpyable + { + enum { __value = 0 }; + }; + + template + struct __memcpyable<_Tp*, _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcpyable<_Tp*, const _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + // Whether two iterator types can be used with memcmp. + // This trait only says it's well-formed to use memcmp, not that it + // gives the right answer for a given algorithm. So for example, std::equal + // needs to add additional checks that the types are integers or pointers, + // because other trivially copyable types can overload operator==. + template + struct __memcmpable + { + enum { __value = 0 }; + }; + + // OK to use memcmp with pointers to trivially copyable types. + template + struct __memcmpable<_Tp*, _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcmpable + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcmpable<_Tp*, const _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + // Whether memcmp can be used to determine ordering for a type + // e.g. in std::lexicographical_compare or three-way comparisons. + // True for unsigned narrow character types (and std::byte). + template::__value> + struct __is_memcmp_ordered + { + static const bool __value = _Tp(-1) > _Tp(1); // is unsigned + }; + + template + struct __is_memcmp_ordered<_Tp, false> + { + static const bool __value = false; + }; + + // Whether two types can be compared using memcmp. + template + struct __is_memcmp_ordered_with + { + static const bool __value = __is_memcmp_ordered<_Tp>::__value + && __is_memcmp_ordered<_Up>::__value; + }; + + template + struct __is_memcmp_ordered_with<_Tp, _Up, false> + { + static const bool __value = false; + }; + +#if __cplusplus >= 201703L + // std::byte can only be compared to itself, not to other types. + template<> + struct __is_memcmp_ordered_with + { static constexpr bool __value = true; }; + + template + struct __is_memcmp_ordered_with<_Tp, std::byte, _SameSize> + { static constexpr bool __value = false; }; + + template + struct __is_memcmp_ordered_with + { static constexpr bool __value = false; }; +#endif + + // + // Move iterator type + // + template + struct __is_move_iterator + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // Fallback implementation of the function in bits/stl_iterator.h used to + // remove the move_iterator wrapper. + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __miter_base(_Iterator __it) + { return __it; } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#endif //_CPP_TYPE_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h b/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h new file mode 100644 index 000000000..9e61a382b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h @@ -0,0 +1,60 @@ +// cxxabi.h subset for cancellation -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cxxabi_forced.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{cxxabi.h} + */ + +#ifndef _CXXABI_FORCED_H +#define _CXXABI_FORCED_H 1 + +#pragma GCC system_header + +#pragma GCC visibility push(default) + +#ifdef __cplusplus +namespace __cxxabiv1 +{ + /** + * @brief Thrown as part of forced unwinding. + * @ingroup exceptions + * + * A magic placeholder class that can be caught by reference to + * recognize forced unwinding. + */ + class __forced_unwind + { + virtual ~__forced_unwind() throw(); + + // Prevent catch by value. + virtual void __pure_dummy() = 0; + }; +} +#endif // __cplusplus + +#pragma GCC visibility pop + +#endif // __CXXABI_FORCED_H diff --git a/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h b/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h new file mode 100644 index 000000000..9ea0599ed --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h @@ -0,0 +1,80 @@ +// ABI Support -*- C++ -*- + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cxxabi_init_exception.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef _CXXABI_INIT_EXCEPTION_H +#define _CXXABI_INIT_EXCEPTION_H 1 + +#pragma GCC system_header + +#pragma GCC visibility push(default) + +#include +#include + +#ifndef _GLIBCXX_CDTOR_CALLABI +#define _GLIBCXX_CDTOR_CALLABI +#define _GLIBCXX_HAVE_CDTOR_CALLABI 0 +#else +#define _GLIBCXX_HAVE_CDTOR_CALLABI 1 +#endif + +#ifdef __cplusplus + +namespace std +{ + class type_info; +} + +namespace __cxxabiv1 +{ + struct __cxa_refcounted_exception; + + extern "C" + { + // Allocate memory for the primary exception plus the thrown object. + void* + __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW; + + void + __cxa_free_exception(void*) _GLIBCXX_NOTHROW; + + // Initialize exception (this is a GNU extension) + __cxa_refcounted_exception* + __cxa_init_primary_exception(void *object, std::type_info *tinfo, + void (_GLIBCXX_CDTOR_CALLABI *dest) (void *)) _GLIBCXX_NOTHROW; + + } +} // namespace __cxxabiv1 + +#endif + +#pragma GCC visibility pop + +#endif // _CXXABI_INIT_EXCEPTION_H diff --git a/resources/sources/avr-libstdcpp/include/bits/deque.tcc b/resources/sources/avr-libstdcpp/include/bits/deque.tcc new file mode 100644 index 000000000..b4943e8ea --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/deque.tcc @@ -0,0 +1,1216 @@ +// Deque implementation (out of line) -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/deque.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{deque} + */ + +#ifndef _DEQUE_TCC +#define _DEQUE_TCC 1 + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + +#if __cplusplus >= 201103L + template + void + deque<_Tp, _Alloc>:: + _M_default_initialize() + { + _Map_pointer __cur; + __try + { + for (__cur = this->_M_impl._M_start._M_node; + __cur < this->_M_impl._M_finish._M_node; + ++__cur) + std::__uninitialized_default_a(*__cur, *__cur + _S_buffer_size(), + _M_get_Tp_allocator()); + std::__uninitialized_default_a(this->_M_impl._M_finish._M_first, + this->_M_impl._M_finish._M_cur, + _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), + _M_get_Tp_allocator()); + __throw_exception_again; + } + } +#endif + + template + deque<_Tp, _Alloc>& + deque<_Tp, _Alloc>:: + operator=(const deque& __x) + { + if (&__x != this) + { +#if __cplusplus >= 201103L + if (_Alloc_traits::_S_propagate_on_copy_assign()) + { + if (!_Alloc_traits::_S_always_equal() + && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) + { + // Replacement allocator cannot free existing storage, + // so deallocate everything and take copy of __x's data. + _M_replace_map(__x, __x.get_allocator()); + std::__alloc_on_copy(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + return *this; + } + std::__alloc_on_copy(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + } +#endif + const size_type __len = size(); + if (__len >= __x.size()) + _M_erase_at_end(std::copy(__x.begin(), __x.end(), + this->_M_impl._M_start)); + else + { + const_iterator __mid = __x.begin() + difference_type(__len); + std::copy(__x.begin(), __mid, this->_M_impl._M_start); + _M_range_insert_aux(this->_M_impl._M_finish, __mid, __x.end(), + std::random_access_iterator_tag()); + } + } + return *this; + } + +#if __cplusplus >= 201103L + template + template +#if __cplusplus > 201402L + typename deque<_Tp, _Alloc>::reference +#else + void +#endif + deque<_Tp, _Alloc>:: + emplace_front(_Args&&... __args) + { + if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) + { + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_start._M_cur - 1, + std::forward<_Args>(__args)...); + --this->_M_impl._M_start._M_cur; + } + else + _M_push_front_aux(std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif + } + + template + template +#if __cplusplus > 201402L + typename deque<_Tp, _Alloc>::reference +#else + void +#endif + deque<_Tp, _Alloc>:: + emplace_back(_Args&&... __args) + { + if (this->_M_impl._M_finish._M_cur + != this->_M_impl._M_finish._M_last - 1) + { + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_finish._M_cur, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish._M_cur; + } + else + _M_push_back_aux(std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif + } +#endif + +#if __cplusplus >= 201103L + template + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + emplace(const_iterator __position, _Args&&... __args) + { + if (__position._M_cur == this->_M_impl._M_start._M_cur) + { + emplace_front(std::forward<_Args>(__args)...); + return this->_M_impl._M_start; + } + else if (__position._M_cur == this->_M_impl._M_finish._M_cur) + { + emplace_back(std::forward<_Args>(__args)...); + iterator __tmp = this->_M_impl._M_finish; + --__tmp; + return __tmp; + } + else + return _M_insert_aux(__position._M_const_cast(), + std::forward<_Args>(__args)...); + } +#endif + + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { + if (__position._M_cur == this->_M_impl._M_start._M_cur) + { + push_front(__x); + return this->_M_impl._M_start; + } + else if (__position._M_cur == this->_M_impl._M_finish._M_cur) + { + push_back(__x); + iterator __tmp = this->_M_impl._M_finish; + --__tmp; + return __tmp; + } + else + return _M_insert_aux(__position._M_const_cast(), __x); + } + + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + _M_erase(iterator __position) + { + iterator __next = __position; + ++__next; + const difference_type __index = __position - begin(); + if (static_cast(__index) < (size() >> 1)) + { + if (__position != begin()) + _GLIBCXX_MOVE_BACKWARD3(begin(), __position, __next); + pop_front(); + } + else + { + if (__next != end()) + _GLIBCXX_MOVE3(__next, end(), __position); + pop_back(); + } + return begin() + __index; + } + + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + _M_erase(iterator __first, iterator __last) + { + if (__first == __last) + return __first; + else if (__first == begin() && __last == end()) + { + clear(); + return end(); + } + else + { + const difference_type __n = __last - __first; + const difference_type __elems_before = __first - begin(); + if (static_cast(__elems_before) <= (size() - __n) / 2) + { + if (__first != begin()) + _GLIBCXX_MOVE_BACKWARD3(begin(), __first, __last); + _M_erase_at_begin(begin() + __n); + } + else + { + if (__last != end()) + _GLIBCXX_MOVE3(__last, end(), __first); + _M_erase_at_end(end() - __n); + } + return begin() + __elems_before; + } + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + iterator __cur = begin(); + for (; __first != __last && __cur != end(); ++__cur, (void)++__first) + *__cur = *__first; + if (__first == __last) + _M_erase_at_end(__cur); + else + _M_range_insert_aux(end(), __first, __last, + std::__iterator_category(__first)); + } + + template + void + deque<_Tp, _Alloc>:: + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) + { + if (__pos._M_cur == this->_M_impl._M_start._M_cur) + { + iterator __new_start = _M_reserve_elements_at_front(__n); + __try + { + std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start, + __x, _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + } + __catch(...) + { + _M_destroy_nodes(__new_start._M_node, + this->_M_impl._M_start._M_node); + __throw_exception_again; + } + } + else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + __try + { + std::__uninitialized_fill_a(this->_M_impl._M_finish, + __new_finish, __x, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + else + _M_insert_aux(__pos, __n, __x); + } + +#if __cplusplus >= 201103L + template + void + deque<_Tp, _Alloc>:: + _M_default_append(size_type __n) + { + if (__n) + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + __try + { + std::__uninitialized_default_a(this->_M_impl._M_finish, + __new_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + } + + template + bool + deque<_Tp, _Alloc>:: + _M_shrink_to_fit() + { + const difference_type __front_capacity + = (this->_M_impl._M_start._M_cur - this->_M_impl._M_start._M_first); + if (__front_capacity == 0) + return false; + + const difference_type __back_capacity + = (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur); + if (__front_capacity + __back_capacity < _S_buffer_size()) + return false; + + return std::__shrink_to_fit_aux::_S_do_it(*this); + } +#endif + + template + void + deque<_Tp, _Alloc>:: + _M_fill_initialize(const value_type& __value) + { + _Map_pointer __cur; + __try + { + for (__cur = this->_M_impl._M_start._M_node; + __cur < this->_M_impl._M_finish._M_node; + ++__cur) + std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(), + __value, _M_get_Tp_allocator()); + std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first, + this->_M_impl._M_finish._M_cur, + __value, _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), + _M_get_Tp_allocator()); + __throw_exception_again; + } + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_range_initialize(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + this->_M_initialize_map(0); + __try + { + for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else + push_back(*__first); +#endif + } + __catch(...) + { + clear(); + __throw_exception_again; + } + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __n = std::distance(__first, __last); + this->_M_initialize_map(_S_check_init_len(__n, _M_get_Tp_allocator())); + + _Map_pointer __cur_node; + __try + { + for (__cur_node = this->_M_impl._M_start._M_node; + __cur_node < this->_M_impl._M_finish._M_node; + ++__cur_node) + { + _ForwardIterator __mid = __first; + std::advance(__mid, _S_buffer_size()); + std::__uninitialized_copy_a(__first, __mid, *__cur_node, + _M_get_Tp_allocator()); + __first = __mid; + } + std::__uninitialized_copy_a(__first, __last, + this->_M_impl._M_finish._M_first, + _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(this->_M_impl._M_start, + iterator(*__cur_node, __cur_node), + _M_get_Tp_allocator()); + __throw_exception_again; + } + } + + // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1. + template +#if __cplusplus >= 201103L + template + void + deque<_Tp, _Alloc>:: + _M_push_back_aux(_Args&&... __args) +#else + void + deque<_Tp, _Alloc>:: + _M_push_back_aux(const value_type& __t) +#endif + { + if (size() == max_size()) + __throw_length_error( + __N("cannot create std::deque larger than max_size()")); + + _M_reserve_map_at_back(); + *(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node(); + __try + { +#if __cplusplus >= 201103L + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_finish._M_cur, + std::forward<_Args>(__args)...); +#else + this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t); +#endif + this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node + + 1); + this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first; + } + __catch(...) + { + _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1)); + __throw_exception_again; + } + } + + // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first. + template +#if __cplusplus >= 201103L + template + void + deque<_Tp, _Alloc>:: + _M_push_front_aux(_Args&&... __args) +#else + void + deque<_Tp, _Alloc>:: + _M_push_front_aux(const value_type& __t) +#endif + { + if (size() == max_size()) + __throw_length_error( + __N("cannot create std::deque larger than max_size()")); + + _M_reserve_map_at_front(); + *(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node(); + __try + { + this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + - 1); + this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1; +#if __cplusplus >= 201103L + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_start._M_cur, + std::forward<_Args>(__args)...); +#else + this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t); +#endif + } + __catch(...) + { + ++this->_M_impl._M_start; + _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1)); + __throw_exception_again; + } + } + + // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first. + template + void deque<_Tp, _Alloc>:: + _M_pop_back_aux() + { + _M_deallocate_node(this->_M_impl._M_finish._M_first); + this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1); + this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1; + _Alloc_traits::destroy(_M_get_Tp_allocator(), + this->_M_impl._M_finish._M_cur); + } + + // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1. + // Note that if the deque has at least one element (a precondition for this + // member function), and if + // _M_impl._M_start._M_cur == _M_impl._M_start._M_last, + // then the deque must have at least two nodes. + template + void deque<_Tp, _Alloc>:: + _M_pop_front_aux() + { + _Alloc_traits::destroy(_M_get_Tp_allocator(), + this->_M_impl._M_start._M_cur); + _M_deallocate_node(this->_M_impl._M_start._M_first); + this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1); + this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first; + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_range_insert_aux(iterator __pos, + _InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { std::copy(__first, __last, std::inserter(*this, __pos)); } + + template + template + void + deque<_Tp, _Alloc>:: + _M_range_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __n = std::distance(__first, __last); + if (__pos._M_cur == this->_M_impl._M_start._M_cur) + { + iterator __new_start = _M_reserve_elements_at_front(__n); + __try + { + std::__uninitialized_copy_a(__first, __last, __new_start, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + } + __catch(...) + { + _M_destroy_nodes(__new_start._M_node, + this->_M_impl._M_start._M_node); + __throw_exception_again; + } + } + else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + __try + { + std::__uninitialized_copy_a(__first, __last, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + else + _M_insert_aux(__pos, __first, __last, __n); + } + + template +#if __cplusplus >= 201103L + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + _M_insert_aux(iterator __pos, _Args&&... __args) + { + value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy +#else + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + _M_insert_aux(iterator __pos, const value_type& __x) + { + value_type __x_copy = __x; // XXX copy +#endif + difference_type __index = __pos - this->_M_impl._M_start; + if (static_cast(__index) < size() / 2) + { + push_front(_GLIBCXX_MOVE(front())); + iterator __front1 = this->_M_impl._M_start; + ++__front1; + iterator __front2 = __front1; + ++__front2; + __pos = this->_M_impl._M_start + __index; + iterator __pos1 = __pos; + ++__pos1; + _GLIBCXX_MOVE3(__front2, __pos1, __front1); + } + else + { + push_back(_GLIBCXX_MOVE(back())); + iterator __back1 = this->_M_impl._M_finish; + --__back1; + iterator __back2 = __back1; + --__back2; + __pos = this->_M_impl._M_start + __index; + _GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1); + } + *__pos = _GLIBCXX_MOVE(__x_copy); + return __pos; + } + + template + void + deque<_Tp, _Alloc>:: + _M_insert_aux(iterator __pos, size_type __n, const value_type& __x) + { + const difference_type __elems_before = __pos - this->_M_impl._M_start; + const size_type __length = this->size(); + value_type __x_copy = __x; + if (__elems_before < difference_type(__length / 2)) + { + iterator __new_start = _M_reserve_elements_at_front(__n); + iterator __old_start = this->_M_impl._M_start; + __pos = this->_M_impl._M_start + __elems_before; + __try + { + if (__elems_before >= difference_type(__n)) + { + iterator __start_n = (this->_M_impl._M_start + + difference_type(__n)); + std::__uninitialized_move_a(this->_M_impl._M_start, + __start_n, __new_start, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + _GLIBCXX_MOVE3(__start_n, __pos, __old_start); + std::fill(__pos - difference_type(__n), __pos, __x_copy); + } + else + { + std::__uninitialized_move_fill(this->_M_impl._M_start, + __pos, __new_start, + this->_M_impl._M_start, + __x_copy, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + std::fill(__old_start, __pos, __x_copy); + } + } + __catch(...) + { + _M_destroy_nodes(__new_start._M_node, + this->_M_impl._M_start._M_node); + __throw_exception_again; + } + } + else + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + iterator __old_finish = this->_M_impl._M_finish; + const difference_type __elems_after = + difference_type(__length) - __elems_before; + __pos = this->_M_impl._M_finish - __elems_after; + __try + { + if (__elems_after > difference_type(__n)) + { + iterator __finish_n = (this->_M_impl._M_finish + - difference_type(__n)); + std::__uninitialized_move_a(__finish_n, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); + std::fill(__pos, __pos + difference_type(__n), __x_copy); + } + else + { + std::__uninitialized_fill_move(this->_M_impl._M_finish, + __pos + difference_type(__n), + __x_copy, __pos, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + std::fill(__pos, __old_finish, __x_copy); + } + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + size_type __n) + { + const difference_type __elemsbefore = __pos - this->_M_impl._M_start; + const size_type __length = size(); + if (static_cast(__elemsbefore) < __length / 2) + { + iterator __new_start = _M_reserve_elements_at_front(__n); + iterator __old_start = this->_M_impl._M_start; + __pos = this->_M_impl._M_start + __elemsbefore; + __try + { + if (__elemsbefore >= difference_type(__n)) + { + iterator __start_n = (this->_M_impl._M_start + + difference_type(__n)); + std::__uninitialized_move_a(this->_M_impl._M_start, + __start_n, __new_start, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + _GLIBCXX_MOVE3(__start_n, __pos, __old_start); + std::copy(__first, __last, __pos - difference_type(__n)); + } + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, difference_type(__n) - __elemsbefore); + std::__uninitialized_move_copy(this->_M_impl._M_start, + __pos, __first, __mid, + __new_start, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + std::copy(__mid, __last, __old_start); + } + } + __catch(...) + { + _M_destroy_nodes(__new_start._M_node, + this->_M_impl._M_start._M_node); + __throw_exception_again; + } + } + else + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + iterator __old_finish = this->_M_impl._M_finish; + const difference_type __elemsafter = + difference_type(__length) - __elemsbefore; + __pos = this->_M_impl._M_finish - __elemsafter; + __try + { + if (__elemsafter > difference_type(__n)) + { + iterator __finish_n = (this->_M_impl._M_finish + - difference_type(__n)); + std::__uninitialized_move_a(__finish_n, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); + std::copy(__first, __last, __pos); + } + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, __elemsafter); + std::__uninitialized_copy_move(__mid, __last, __pos, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + std::copy(__first, __mid, __pos); + } + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + } + + template + void + deque<_Tp, _Alloc>:: + _M_destroy_data_aux(iterator __first, iterator __last) + { + for (_Map_pointer __node = __first._M_node + 1; + __node < __last._M_node; ++__node) + std::_Destroy(*__node, *__node + _S_buffer_size(), + _M_get_Tp_allocator()); + + if (__first._M_node != __last._M_node) + { + std::_Destroy(__first._M_cur, __first._M_last, + _M_get_Tp_allocator()); + std::_Destroy(__last._M_first, __last._M_cur, + _M_get_Tp_allocator()); + } + else + std::_Destroy(__first._M_cur, __last._M_cur, + _M_get_Tp_allocator()); + } + + template + void + deque<_Tp, _Alloc>:: + _M_new_elements_at_front(size_type __new_elems) + { + if (this->max_size() - this->size() < __new_elems) + __throw_length_error(__N("deque::_M_new_elements_at_front")); + + const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1) + / _S_buffer_size()); + _M_reserve_map_at_front(__new_nodes); + size_type __i; + __try + { + for (__i = 1; __i <= __new_nodes; ++__i) + *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node(); + } + __catch(...) + { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j)); + __throw_exception_again; + } + } + + template + void + deque<_Tp, _Alloc>:: + _M_new_elements_at_back(size_type __new_elems) + { + if (this->max_size() - this->size() < __new_elems) + __throw_length_error(__N("deque::_M_new_elements_at_back")); + + const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1) + / _S_buffer_size()); + _M_reserve_map_at_back(__new_nodes); + size_type __i; + __try + { + for (__i = 1; __i <= __new_nodes; ++__i) + *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node(); + } + __catch(...) + { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j)); + __throw_exception_again; + } + } + + template + void + deque<_Tp, _Alloc>:: + _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front) + { + const size_type __old_num_nodes + = this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1; + const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add; + + _Map_pointer __new_nstart; + if (this->_M_impl._M_map_size > 2 * __new_num_nodes) + { + __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size + - __new_num_nodes) / 2 + + (__add_at_front ? __nodes_to_add : 0); + if (__new_nstart < this->_M_impl._M_start._M_node) + std::copy(this->_M_impl._M_start._M_node, + this->_M_impl._M_finish._M_node + 1, + __new_nstart); + else + std::copy_backward(this->_M_impl._M_start._M_node, + this->_M_impl._M_finish._M_node + 1, + __new_nstart + __old_num_nodes); + } + else + { + size_type __new_map_size = this->_M_impl._M_map_size + + std::max(this->_M_impl._M_map_size, + __nodes_to_add) + 2; + + _Map_pointer __new_map = this->_M_allocate_map(__new_map_size); + __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2 + + (__add_at_front ? __nodes_to_add : 0); + std::copy(this->_M_impl._M_start._M_node, + this->_M_impl._M_finish._M_node + 1, + __new_nstart); + _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); + + this->_M_impl._M_map = __new_map; + this->_M_impl._M_map_size = __new_map_size; + } + + this->_M_impl._M_start._M_set_node(__new_nstart); + this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1); + } + +_GLIBCXX_END_NAMESPACE_CONTAINER + + // Overload for deque::iterators, exploiting the "segmented-iterator + // optimization". + template + void + __fill_a1(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __first, + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __last, + const _VTp& __value) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; + if (__first._M_node != __last._M_node) + { + std::__fill_a1(__first._M_cur, __first._M_last, __value); + + for (typename _Iter::_Map_pointer __node = __first._M_node + 1; + __node < __last._M_node; ++__node) + std::__fill_a1(*__node, *__node + _Iter::_S_buffer_size(), __value); + + std::__fill_a1(__last._M_first, __last._M_cur, __value); + } + else + std::__fill_a1(__first._M_cur, __last._M_cur, __value); + } + + template + _OI + __copy_move_dit(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, + _OI __result) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; + if (__first._M_node != __last._M_node) + { + __result + = std::__copy_move_a1<_IsMove>(__first._M_cur, __first._M_last, + __result); + + for (typename _Iter::_Map_pointer __node = __first._M_node + 1; + __node != __last._M_node; ++__node) + __result + = std::__copy_move_a1<_IsMove>(*__node, + *__node + _Iter::_S_buffer_size(), + __result); + + return std::__copy_move_a1<_IsMove>(__last._M_first, __last._M_cur, + __result); + } + + return std::__copy_move_a1<_IsMove>(__first._M_cur, __last._M_cur, + __result); + } + + template + _OI + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, + _OI __result) + { return __copy_move_dit<_IsMove>(__first, __last, __result); } + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result) + { return __copy_move_dit<_IsMove>(__first, __last, __result); } + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_a1(_II __first, _II __last, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; + typedef typename _Iter::difference_type difference_type; + + difference_type __len = __last - __first; + while (__len > 0) + { + const difference_type __clen + = std::min(__len, __result._M_last - __result._M_cur); + std::__copy_move_a1<_IsMove>(__first, __first + __clen, + __result._M_cur); + + __first += __clen; + __result += __clen; + __len -= __clen; + } + + return __result; + } + + template + _OI + __copy_move_backward_dit( + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, + _OI __result) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; + if (__first._M_node != __last._M_node) + { + __result = std::__copy_move_backward_a1<_IsMove>( + __last._M_first, __last._M_cur, __result); + + for (typename _Iter::_Map_pointer __node = __last._M_node - 1; + __node != __first._M_node; --__node) + __result = std::__copy_move_backward_a1<_IsMove>( + *__node, *__node + _Iter::_S_buffer_size(), __result); + + return std::__copy_move_backward_a1<_IsMove>( + __first._M_cur, __first._M_last, __result); + } + + return std::__copy_move_backward_a1<_IsMove>( + __first._M_cur, __last._M_cur, __result); + } + + template + _OI + __copy_move_backward_a1( + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, + _OI __result) + { return __copy_move_backward_dit<_IsMove>(__first, __last, __result); } + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_backward_a1( + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result) + { return __copy_move_backward_dit<_IsMove>(__first, __last, __result); } + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_backward_a1(_II __first, _II __last, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; + typedef typename _Iter::difference_type difference_type; + + difference_type __len = __last - __first; + while (__len > 0) + { + difference_type __rlen = __result._M_cur - __result._M_first; + _Tp* __rend = __result._M_cur; + if (!__rlen) + { + __rlen = _Iter::_S_buffer_size(); + __rend = *(__result._M_node - 1) + __rlen; + } + + const difference_type __clen = std::min(__len, __rlen); + std::__copy_move_backward_a1<_IsMove>(__last - __clen, __last, __rend); + + __last -= __clen; + __result -= __clen; + __len -= __clen; + } + + return __result; + } + + template + bool + __equal_dit( + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __first1, + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __last1, + _II __first2) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; + if (__first1._M_node != __last1._M_node) + { + if (!std::__equal_aux1(__first1._M_cur, __first1._M_last, __first2)) + return false; + + __first2 += __first1._M_last - __first1._M_cur; + for (typename _Iter::_Map_pointer __node = __first1._M_node + 1; + __node != __last1._M_node; + __first2 += _Iter::_S_buffer_size(), ++__node) + if (!std::__equal_aux1(*__node, *__node + _Iter::_S_buffer_size(), + __first2)) + return false; + + return std::__equal_aux1(__last1._M_first, __last1._M_cur, __first2); + } + + return std::__equal_aux1(__first1._M_cur, __last1._M_cur, __first2); + } + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first1, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last1, + _II __first2) + { return std::__equal_dit(__first1, __last1, __first2); } + + template + bool + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __first1, + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __last1, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2> __first2) + { return std::__equal_dit(__first1, __last1, __first2); } + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_II __first1, _II __last1, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first2) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; + typedef typename _Iter::difference_type difference_type; + + difference_type __len = __last1 - __first1; + while (__len > 0) + { + const difference_type __clen + = std::min(__len, __first2._M_last - __first2._M_cur); + if (!std::__equal_aux1(__first1, __first1 + __clen, __first2._M_cur)) + return false; + + __first1 += __clen; + __len -= __clen; + __first2 += __clen; + } + + return true; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h b/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h new file mode 100644 index 000000000..3c12cfcf8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h @@ -0,0 +1,312 @@ +// -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/enable_special_members.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef _ENABLE_SPECIAL_MEMBERS_H +#define _ENABLE_SPECIAL_MEMBERS_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct _Enable_default_constructor_tag + { + explicit constexpr _Enable_default_constructor_tag() = default; + }; + +/** + * @brief A mixin helper to conditionally enable or disable the default + * constructor. + * @sa _Enable_special_members + */ +template + struct _Enable_default_constructor + { + constexpr _Enable_default_constructor() noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor const&) + noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor&&) + noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor const&) noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor&&) noexcept = default; + + // Can be used in other ctors. + constexpr explicit + _Enable_default_constructor(_Enable_default_constructor_tag) { } + }; + + +/** + * @brief A mixin helper to conditionally enable or disable the default + * destructor. + * @sa _Enable_special_members + */ +template + struct _Enable_destructor { }; + +/** + * @brief A mixin helper to conditionally enable or disable the copy/move + * special members. + * @sa _Enable_special_members + */ +template + struct _Enable_copy_move { }; + +/** + * @brief A mixin helper to conditionally enable or disable the special + * members. + * + * The @c _Tag type parameter is to make mixin bases unique and thus avoid + * ambiguities. + */ +template + struct _Enable_special_members + : private _Enable_default_constructor<_Default, _Tag>, + private _Enable_destructor<_Destructor, _Tag>, + private _Enable_copy_move<_Copy, _CopyAssignment, + _Move, _MoveAssignment, + _Tag> + { }; + +// Boilerplate follows. + +template + struct _Enable_default_constructor + { + constexpr _Enable_default_constructor() noexcept = delete; + constexpr _Enable_default_constructor(_Enable_default_constructor const&) + noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor&&) + noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor const&) noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor&&) noexcept = default; + + // Can be used in other ctors. + constexpr explicit + _Enable_default_constructor(_Enable_default_constructor_tag) { } + }; + +template + struct _Enable_destructor + { ~_Enable_destructor() noexcept = delete; }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _ENABLE_SPECIAL_MEMBERS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/erase_if.h b/resources/sources/avr-libstdcpp/include/bits/erase_if.h new file mode 100644 index 000000000..dc5e6ae58 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/erase_if.h @@ -0,0 +1,72 @@ +// -*- C++ -*- + +// Copyright (C) 2015-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/erase_if.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef _GLIBCXX_ERASE_IF_H +#define _GLIBCXX_ERASE_IF_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201402L + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus > 201703L +# define __cpp_lib_erase_if 202002L +#endif + + namespace __detail + { + template + typename _Container::size_type + __erase_nodes_if(_Container& __cont, _Predicate __pred) + { + typename _Container::size_type __num = 0; + for (auto __iter = __cont.begin(), __last = __cont.end(); + __iter != __last;) + { + if (__pred(*__iter)) + { + __iter = __cont.erase(__iter); + ++__num; + } + else + ++__iter; + } + return __num; + } + } // namespace __detail + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + +#endif // _GLIBCXX_ERASE_IF_H diff --git a/resources/sources/avr-libstdcpp/include/bits/error_constants.h b/resources/sources/avr-libstdcpp/include/bits/error_constants.h new file mode 100644 index 000000000..203891454 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/error_constants.h @@ -0,0 +1,180 @@ +// Specific definitions for generic platforms -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/error_constants.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{system_error} + */ + +#ifndef _GLIBCXX_ERROR_CONSTANTS +#define _GLIBCXX_ERROR_CONSTANTS 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + enum class errc + { + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, + +#ifdef EBADMSG + bad_message = EBADMSG, +#endif + + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + +#ifdef EIDRM + identifier_removed = EIDRM, +#endif + + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, + +#ifdef ENOLINK + no_link = ENOLINK, +#endif + + no_lock_available = ENOLCK, + +#ifdef ENODATA + no_message_available = ENODATA, +#endif + + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, + +#ifdef ENOSR + no_stream_resources = ENOSR, +#endif + + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, + +#ifdef ENOSTR + not_a_stream = ENOSTR, +#endif + + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + +#ifdef ENOTSUP + not_supported = ENOTSUP, +#endif + +#ifdef ECANCELED + operation_canceled = ECANCELED, +#endif + + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, + +#ifdef EOWNERDEAD + owner_dead = EOWNERDEAD, +#endif + + permission_denied = EACCES, + +#ifdef EPROTO + protocol_error = EPROTO, +#endif + + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, + +#ifdef ENOTRECOVERABLE + state_not_recoverable = ENOTRECOVERABLE, +#endif + +#ifdef ETIME + stream_timeout = ETIME, +#endif + +#ifdef ETXTBSY + text_file_busy = ETXTBSY, +#endif + + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + +#ifdef EOVERFLOW + value_too_large = EOVERFLOW, +#elif defined __AVR__ + value_too_large = 999, +#endif + + wrong_protocol_type = EPROTOTYPE + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/exception_defines.h b/resources/sources/avr-libstdcpp/include/bits/exception_defines.h new file mode 100644 index 000000000..bc73d4194 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/exception_defines.h @@ -0,0 +1,47 @@ +// -fno-exceptions Support -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/exception_defines.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + */ + +#ifndef _EXCEPTION_DEFINES_H +#define _EXCEPTION_DEFINES_H 1 + +#pragma GCC system_header + +#if ! __cpp_exceptions +// Iff -fno-exceptions, transform error handling code to work without it. +# define __try if (true) +# define __catch(X) if (false) +# define __throw_exception_again +#else +// Else proceed normally. +# define __try try +# define __catch(X) catch(X) +# define __throw_exception_again throw +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/forward_list.h b/resources/sources/avr-libstdcpp/include/bits/forward_list.h new file mode 100644 index 000000000..49b2a9737 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/forward_list.h @@ -0,0 +1,1514 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/forward_list.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{forward_list} + */ + +#ifndef _FORWARD_LIST_H +#define _FORWARD_LIST_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * @brief A helper basic node class for %forward_list. + * This is just a linked list with nothing inside it. + * There are purely list shuffling utility methods here. + */ + struct _Fwd_list_node_base + { + _Fwd_list_node_base() = default; + _Fwd_list_node_base(_Fwd_list_node_base&& __x) noexcept + : _M_next(__x._M_next) + { __x._M_next = nullptr; } + + _Fwd_list_node_base(const _Fwd_list_node_base&) = delete; + _Fwd_list_node_base& operator=(const _Fwd_list_node_base&) = delete; + + _Fwd_list_node_base& + operator=(_Fwd_list_node_base&& __x) noexcept + { + _M_next = __x._M_next; + __x._M_next = nullptr; + return *this; + } + + _Fwd_list_node_base* _M_next = nullptr; + + _Fwd_list_node_base* + _M_transfer_after(_Fwd_list_node_base* __begin, + _Fwd_list_node_base* __end) noexcept + { + _Fwd_list_node_base* __keep = __begin->_M_next; + if (__end) + { + __begin->_M_next = __end->_M_next; + __end->_M_next = _M_next; + } + else + __begin->_M_next = nullptr; + _M_next = __keep; + return __end; + } + + void + _M_reverse_after() noexcept + { + _Fwd_list_node_base* __tail = _M_next; + if (!__tail) + return; + while (_Fwd_list_node_base* __temp = __tail->_M_next) + { + _Fwd_list_node_base* __keep = _M_next; + _M_next = __temp; + __tail->_M_next = __temp->_M_next; + _M_next->_M_next = __keep; + } + } + }; + + /** + * @brief A helper node class for %forward_list. + * This is just a linked list with uninitialized storage for a + * data value in each node. + * There is a sorting utility method. + */ + template + struct _Fwd_list_node + : public _Fwd_list_node_base + { + _Fwd_list_node() = default; + + __gnu_cxx::__aligned_buffer<_Tp> _M_storage; + + _Tp* + _M_valptr() noexcept + { return _M_storage._M_ptr(); } + + const _Tp* + _M_valptr() const noexcept + { return _M_storage._M_ptr(); } + }; + + /** + * @brief A forward_list::iterator. + * + * All the functions are op overloads. + */ + template + struct _Fwd_list_iterator + { + typedef _Fwd_list_iterator<_Tp> _Self; + typedef _Fwd_list_node<_Tp> _Node; + + typedef _Tp value_type; + typedef _Tp* pointer; + typedef _Tp& reference; + typedef ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Fwd_list_iterator() noexcept + : _M_node() { } + + explicit + _Fwd_list_iterator(_Fwd_list_node_base* __n) noexcept + : _M_node(__n) { } + + reference + operator*() const noexcept + { return *static_cast<_Node*>(this->_M_node)->_M_valptr(); } + + pointer + operator->() const noexcept + { return static_cast<_Node*>(this->_M_node)->_M_valptr(); } + + _Self& + operator++() noexcept + { + _M_node = _M_node->_M_next; + return *this; + } + + _Self + operator++(int) noexcept + { + _Self __tmp(*this); + _M_node = _M_node->_M_next; + return __tmp; + } + + /** + * @brief Forward list iterator equality comparison. + */ + friend bool + operator==(const _Self& __x, const _Self& __y) noexcept + { return __x._M_node == __y._M_node; } + +#if __cpp_impl_three_way_comparison < 201907L + /** + * @brief Forward list iterator inequality comparison. + */ + friend bool + operator!=(const _Self& __x, const _Self& __y) noexcept + { return __x._M_node != __y._M_node; } +#endif + + _Self + _M_next() const noexcept + { + if (_M_node) + return _Fwd_list_iterator(_M_node->_M_next); + else + return _Fwd_list_iterator(nullptr); + } + + _Fwd_list_node_base* _M_node; + }; + + /** + * @brief A forward_list::const_iterator. + * + * All the functions are op overloads. + */ + template + struct _Fwd_list_const_iterator + { + typedef _Fwd_list_const_iterator<_Tp> _Self; + typedef const _Fwd_list_node<_Tp> _Node; + typedef _Fwd_list_iterator<_Tp> iterator; + + typedef _Tp value_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + typedef ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Fwd_list_const_iterator() noexcept + : _M_node() { } + + explicit + _Fwd_list_const_iterator(const _Fwd_list_node_base* __n) noexcept + : _M_node(__n) { } + + _Fwd_list_const_iterator(const iterator& __iter) noexcept + : _M_node(__iter._M_node) { } + + reference + operator*() const noexcept + { return *static_cast<_Node*>(this->_M_node)->_M_valptr(); } + + pointer + operator->() const noexcept + { return static_cast<_Node*>(this->_M_node)->_M_valptr(); } + + _Self& + operator++() noexcept + { + _M_node = _M_node->_M_next; + return *this; + } + + _Self + operator++(int) noexcept + { + _Self __tmp(*this); + _M_node = _M_node->_M_next; + return __tmp; + } + + /** + * @brief Forward list const_iterator equality comparison. + */ + friend bool + operator==(const _Self& __x, const _Self& __y) noexcept + { return __x._M_node == __y._M_node; } + +#if __cpp_impl_three_way_comparison < 201907L + /** + * @brief Forward list const_iterator inequality comparison. + */ + friend bool + operator!=(const _Self& __x, const _Self& __y) noexcept + { return __x._M_node != __y._M_node; } +#endif + + _Self + _M_next() const noexcept + { + if (this->_M_node) + return _Fwd_list_const_iterator(_M_node->_M_next); + else + return _Fwd_list_const_iterator(nullptr); + } + + const _Fwd_list_node_base* _M_node; + }; + + /** + * @brief Base class for %forward_list. + */ + template + struct _Fwd_list_base + { + protected: + typedef __alloc_rebind<_Alloc, _Fwd_list_node<_Tp>> _Node_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; + + struct _Fwd_list_impl + : public _Node_alloc_type + { + _Fwd_list_node_base _M_head; + + _Fwd_list_impl() + noexcept(is_nothrow_default_constructible<_Node_alloc_type>::value) + : _Node_alloc_type(), _M_head() + { } + + _Fwd_list_impl(_Fwd_list_impl&&) = default; + + _Fwd_list_impl(_Fwd_list_impl&& __fl, _Node_alloc_type&& __a) + : _Node_alloc_type(std::move(__a)), _M_head(std::move(__fl._M_head)) + { } + + _Fwd_list_impl(_Node_alloc_type&& __a) + : _Node_alloc_type(std::move(__a)), _M_head() + { } + }; + + _Fwd_list_impl _M_impl; + + public: + typedef _Fwd_list_iterator<_Tp> iterator; + typedef _Fwd_list_const_iterator<_Tp> const_iterator; + typedef _Fwd_list_node<_Tp> _Node; + + _Node_alloc_type& + _M_get_Node_allocator() noexcept + { return this->_M_impl; } + + const _Node_alloc_type& + _M_get_Node_allocator() const noexcept + { return this->_M_impl; } + + _Fwd_list_base() = default; + + _Fwd_list_base(_Node_alloc_type&& __a) + : _M_impl(std::move(__a)) { } + + // When allocators are always equal. + _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a, + std::true_type) + : _M_impl(std::move(__lst._M_impl), std::move(__a)) + { } + + // When allocators are not always equal. + _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a); + + _Fwd_list_base(_Fwd_list_base&&) = default; + + ~_Fwd_list_base() + { _M_erase_after(&_M_impl._M_head, nullptr); } + + protected: + _Node* + _M_get_node() + { + auto __ptr = _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1); + return std::__to_address(__ptr); + } + + template + _Node* + _M_create_node(_Args&&... __args) + { + _Node* __node = this->_M_get_node(); + __try + { + ::new ((void*)__node) _Node; + _Node_alloc_traits::construct(_M_get_Node_allocator(), + __node->_M_valptr(), + std::forward<_Args>(__args)...); + } + __catch(...) + { + this->_M_put_node(__node); + __throw_exception_again; + } + return __node; + } + + template + _Fwd_list_node_base* + _M_insert_after(const_iterator __pos, _Args&&... __args); + + void + _M_put_node(_Node* __p) + { + typedef typename _Node_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__p); + _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ptr, 1); + } + + _Fwd_list_node_base* + _M_erase_after(_Fwd_list_node_base* __pos); + + _Fwd_list_node_base* + _M_erase_after(_Fwd_list_node_base* __pos, + _Fwd_list_node_base* __last); + }; + + /** + * @brief A standard container with linear time access to elements, + * and fixed time insertion/deletion at any point in the sequence. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. + * + * Meets the requirements of a container, a + * sequence, including the + * optional sequence requirements with the + * %exception of @c at and @c operator[]. + * + * This is a @e singly @e linked %list. Traversal up the + * %list requires linear time, but adding and removing elements (or + * @e nodes) is done in constant time, regardless of where the + * change takes place. Unlike std::vector and std::deque, + * random-access iterators are not provided, so subscripting ( @c + * [] ) access is not allowed. For algorithms which only need + * sequential access, this lack makes no difference. + * + * Also unlike the other standard containers, std::forward_list provides + * specialized algorithms %unique to linked lists, such as + * splicing, sorting, and in-place reversal. + */ + template> + class forward_list : private _Fwd_list_base<_Tp, _Alloc> + { + static_assert(is_same::type, _Tp>::value, + "std::forward_list must have a non-const, non-volatile value_type"); +#if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::forward_list must have the same value_type as its allocator"); +#endif + + private: + typedef _Fwd_list_base<_Tp, _Alloc> _Base; + typedef _Fwd_list_node_base _Node_base; + typedef typename _Base::_Node _Node; + typedef typename _Base::_Node_alloc_type _Node_alloc_type; + typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; + typedef allocator_traits<__alloc_rebind<_Alloc, _Tp>> _Alloc_traits; + + public: + // types: + typedef _Tp value_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef typename _Base::iterator iterator; + typedef typename _Base::const_iterator const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + // 23.3.4.2 construct/copy/destroy: + + /** + * @brief Creates a %forward_list with no elements. + */ + forward_list() = default; + + /** + * @brief Creates a %forward_list with no elements. + * @param __al An allocator object. + */ + explicit + forward_list(const _Alloc& __al) noexcept + : _Base(_Node_alloc_type(__al)) + { } + + /** + * @brief Copy constructor with allocator argument. + * @param __list Input list to copy. + * @param __al An allocator object. + */ + forward_list(const forward_list& __list, const _Alloc& __al) + : _Base(_Node_alloc_type(__al)) + { _M_range_initialize(__list.begin(), __list.end()); } + + private: + forward_list(forward_list&& __list, _Node_alloc_type&& __al, + false_type) + : _Base(std::move(__list), std::move(__al)) + { + // If __list is not empty it means its allocator is not equal to __a, + // so we need to move from each element individually. + insert_after(cbefore_begin(), + std::__make_move_if_noexcept_iterator(__list.begin()), + std::__make_move_if_noexcept_iterator(__list.end())); + } + + forward_list(forward_list&& __list, _Node_alloc_type&& __al, + true_type) + noexcept + : _Base(std::move(__list), _Node_alloc_type(__al), true_type{}) + { } + + public: + /** + * @brief Move constructor with allocator argument. + * @param __list Input list to move. + * @param __al An allocator object. + */ + forward_list(forward_list&& __list, const _Alloc& __al) + noexcept(_Node_alloc_traits::_S_always_equal()) + : forward_list(std::move(__list), _Node_alloc_type(__al), + typename _Node_alloc_traits::is_always_equal{}) + { } + + /** + * @brief Creates a %forward_list with default constructed elements. + * @param __n The number of elements to initially create. + * @param __al An allocator object. + * + * This constructor creates the %forward_list with @a __n default + * constructed elements. + */ + explicit + forward_list(size_type __n, const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) + { _M_default_initialize(__n); } + + /** + * @brief Creates a %forward_list with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __al An allocator object. + * + * This constructor fills the %forward_list with @a __n copies of + * @a __value. + */ + forward_list(size_type __n, const _Tp& __value, + const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) + { _M_fill_initialize(__n, __value); } + + /** + * @brief Builds a %forward_list from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __al An allocator object. + * + * Create a %forward_list consisting of copies of the elements from + * [@a __first,@a __last). This is linear in N (where N is + * distance(@a __first,@a __last)). + */ + template> + forward_list(_InputIterator __first, _InputIterator __last, + const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) + { _M_range_initialize(__first, __last); } + + /** + * @brief The %forward_list copy constructor. + * @param __list A %forward_list of identical element and allocator + * types. + */ + forward_list(const forward_list& __list) + : _Base(_Node_alloc_traits::_S_select_on_copy( + __list._M_get_Node_allocator())) + { _M_range_initialize(__list.begin(), __list.end()); } + + /** + * @brief The %forward_list move constructor. + * @param __list A %forward_list of identical element and allocator + * types. + * + * The newly-created %forward_list contains the exact contents of the + * moved instance. The contents of the moved instance are a valid, but + * unspecified %forward_list. + */ + forward_list(forward_list&&) = default; + + /** + * @brief Builds a %forward_list from an initializer_list + * @param __il An initializer_list of value_type. + * @param __al An allocator object. + * + * Create a %forward_list consisting of copies of the elements + * in the initializer_list @a __il. This is linear in __il.size(). + */ + forward_list(std::initializer_list<_Tp> __il, + const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) + { _M_range_initialize(__il.begin(), __il.end()); } + + /** + * @brief The forward_list dtor. + */ + ~forward_list() noexcept + { } + + /** + * @brief The %forward_list assignment operator. + * @param __list A %forward_list of identical element and allocator + * types. + * + * All the elements of @a __list are copied. + * + * Whether the allocator is copied depends on the allocator traits. + */ + forward_list& + operator=(const forward_list& __list); + + /** + * @brief The %forward_list move assignment operator. + * @param __list A %forward_list of identical element and allocator + * types. + * + * The contents of @a __list are moved into this %forward_list + * (without copying, if the allocators permit it). + * + * Afterwards @a __list is a valid, but unspecified %forward_list + * + * Whether the allocator is moved depends on the allocator traits. + */ + forward_list& + operator=(forward_list&& __list) + noexcept(_Node_alloc_traits::_S_nothrow_move()) + { + constexpr bool __move_storage = + _Node_alloc_traits::_S_propagate_on_move_assign() + || _Node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__list), __bool_constant<__move_storage>()); + return *this; + } + + /** + * @brief The %forward_list initializer list assignment operator. + * @param __il An initializer_list of value_type. + * + * Replace the contents of the %forward_list with copies of the + * elements in the initializer_list @a __il. This is linear in + * __il.size(). + */ + forward_list& + operator=(std::initializer_list<_Tp> __il) + { + assign(__il); + return *this; + } + + /** + * @brief Assigns a range to a %forward_list. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function fills a %forward_list with copies of the elements + * in the range [@a __first,@a __last). + * + * Note that the assignment completely changes the %forward_list and + * that the number of elements of the resulting %forward_list is the + * same as the number of elements assigned. + */ + template> + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef is_assignable<_Tp, decltype(*__first)> __assignable; + _M_assign(__first, __last, __assignable()); + } + + /** + * @brief Assigns a given value to a %forward_list. + * @param __n Number of elements to be assigned. + * @param __val Value to be assigned. + * + * This function fills a %forward_list with @a __n copies of the + * given value. Note that the assignment completely changes the + * %forward_list, and that the resulting %forward_list has __n + * elements. + */ + void + assign(size_type __n, const _Tp& __val) + { _M_assign_n(__n, __val, is_copy_assignable<_Tp>()); } + + /** + * @brief Assigns an initializer_list to a %forward_list. + * @param __il An initializer_list of value_type. + * + * Replace the contents of the %forward_list with copies of the + * elements in the initializer_list @a __il. This is linear in + * il.size(). + */ + void + assign(std::initializer_list<_Tp> __il) + { assign(__il.begin(), __il.end()); } + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const noexcept + { return allocator_type(this->_M_get_Node_allocator()); } + + // 23.3.4.3 iterators: + + /** + * Returns a read/write iterator that points before the first element + * in the %forward_list. Iteration is done in ordinary element order. + */ + iterator + before_begin() noexcept + { return iterator(&this->_M_impl._M_head); } + + /** + * Returns a read-only (constant) iterator that points before the + * first element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + before_begin() const noexcept + { return const_iterator(&this->_M_impl._M_head); } + + /** + * Returns a read/write iterator that points to the first element + * in the %forward_list. Iteration is done in ordinary element order. + */ + iterator + begin() noexcept + { return iterator(this->_M_impl._M_head._M_next); } + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + begin() const noexcept + { return const_iterator(this->_M_impl._M_head._M_next); } + + /** + * Returns a read/write iterator that points one past the last + * element in the %forward_list. Iteration is done in ordinary + * element order. + */ + iterator + end() noexcept + { return iterator(nullptr); } + + /** + * Returns a read-only iterator that points one past the last + * element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + end() const noexcept + { return const_iterator(nullptr); } + + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + cbegin() const noexcept + { return const_iterator(this->_M_impl._M_head._M_next); } + + /** + * Returns a read-only (constant) iterator that points before the + * first element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + cbefore_begin() const noexcept + { return const_iterator(&this->_M_impl._M_head); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %forward_list. Iteration is done in + * ordinary element order. + */ + const_iterator + cend() const noexcept + { return const_iterator(nullptr); } + + /** + * Returns true if the %forward_list is empty. (Thus begin() would + * equal end().) + */ + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return this->_M_impl._M_head._M_next == nullptr; } + + /** + * Returns the largest possible number of elements of %forward_list. + */ + size_type + max_size() const noexcept + { return _Node_alloc_traits::max_size(this->_M_get_Node_allocator()); } + + // 23.3.4.4 element access: + + /** + * Returns a read/write reference to the data at the first + * element of the %forward_list. + */ + reference + front() + { + _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); + return *__front->_M_valptr(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %forward_list. + */ + const_reference + front() const + { + _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); + return *__front->_M_valptr(); + } + + // 23.3.4.5 modifiers: + + /** + * @brief Constructs object in %forward_list at the front of the + * list. + * @param __args Arguments. + * + * This function will insert an object of type Tp constructed + * with Tp(std::forward(args)...) at the front of the list + * Due to the nature of a %forward_list this operation can + * be done in constant time, and does not invalidate iterators + * and references. + */ + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_front(_Args&&... __args) + { + this->_M_insert_after(cbefore_begin(), + std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif + } + + /** + * @brief Add data to the front of the %forward_list. + * @param __val Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the front of the %forward_list and assigns the given + * data to it. Due to the nature of a %forward_list this operation + * can be done in constant time, and does not invalidate iterators + * and references. + */ + void + push_front(const _Tp& __val) + { this->_M_insert_after(cbefore_begin(), __val); } + + /** + * + */ + void + push_front(_Tp&& __val) + { this->_M_insert_after(cbefore_begin(), std::move(__val)); } + + /** + * @brief Removes first element. + * + * This is a typical stack operation. It shrinks the %forward_list + * by one. Due to the nature of a %forward_list this operation can + * be done in constant time, and only invalidates iterators/references + * to the element being removed. + * + * Note that no data is returned, and if the first element's data + * is needed, it should be retrieved before pop_front() is + * called. + */ + void + pop_front() + { this->_M_erase_after(&this->_M_impl._M_head); } + + /** + * @brief Constructs object in %forward_list after the specified + * iterator. + * @param __pos A const_iterator into the %forward_list. + * @param __args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) after the specified + * location. Due to the nature of a %forward_list this operation can + * be done in constant time, and does not invalidate iterators + * and references. + */ + template + iterator + emplace_after(const_iterator __pos, _Args&&... __args) + { return iterator(this->_M_insert_after(__pos, + std::forward<_Args>(__args)...)); } + + /** + * @brief Inserts given value into %forward_list after specified + * iterator. + * @param __pos An iterator into the %forward_list. + * @param __val Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value after + * the specified location. Due to the nature of a %forward_list this + * operation can be done in constant time, and does not + * invalidate iterators and references. + */ + iterator + insert_after(const_iterator __pos, const _Tp& __val) + { return iterator(this->_M_insert_after(__pos, __val)); } + + /** + * + */ + iterator + insert_after(const_iterator __pos, _Tp&& __val) + { return iterator(this->_M_insert_after(__pos, std::move(__val))); } + + /** + * @brief Inserts a number of copies of given data into the + * %forward_list. + * @param __pos An iterator into the %forward_list. + * @param __n Number of elements to be inserted. + * @param __val Data to be inserted. + * @return An iterator pointing to the last inserted copy of + * @a val or @a pos if @a n == 0. + * + * This function will insert a specified number of copies of the + * given data after the location specified by @a pos. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + iterator + insert_after(const_iterator __pos, size_type __n, const _Tp& __val); + + /** + * @brief Inserts a range into the %forward_list. + * @param __pos An iterator into the %forward_list. + * @param __first An input iterator. + * @param __last An input iterator. + * @return An iterator pointing to the last inserted element or + * @a __pos if @a __first == @a __last. + * + * This function will insert copies of the data in the range + * [@a __first,@a __last) into the %forward_list after the + * location specified by @a __pos. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + template> + iterator + insert_after(const_iterator __pos, + _InputIterator __first, _InputIterator __last); + + /** + * @brief Inserts the contents of an initializer_list into + * %forward_list after the specified iterator. + * @param __pos An iterator into the %forward_list. + * @param __il An initializer_list of value_type. + * @return An iterator pointing to the last inserted element + * or @a __pos if @a __il is empty. + * + * This function will insert copies of the data in the + * initializer_list @a __il into the %forward_list before the location + * specified by @a __pos. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + iterator + insert_after(const_iterator __pos, std::initializer_list<_Tp> __il) + { return insert_after(__pos, __il.begin(), __il.end()); } + + /** + * @brief Removes the element pointed to by the iterator following + * @c pos. + * @param __pos Iterator pointing before element to be erased. + * @return An iterator pointing to the element following the one + * that was erased, or end() if no such element exists. + * + * This function will erase the element at the given position and + * thus shorten the %forward_list by one. + * + * Due to the nature of a %forward_list this operation can be done + * in constant time, and only invalidates iterators/references to + * the element being removed. The user is also cautioned that + * this function only erases the element, and that if the element + * is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator + erase_after(const_iterator __pos) + { return iterator(this->_M_erase_after(const_cast<_Node_base*> + (__pos._M_node))); } + + /** + * @brief Remove a range of elements. + * @param __pos Iterator pointing before the first element to be + * erased. + * @param __last Iterator pointing to one past the last element to be + * erased. + * @return @ __last. + * + * This function will erase the elements in the range + * @a (__pos,__last) and shorten the %forward_list accordingly. + * + * This operation is linear time in the size of the range and only + * invalidates iterators/references to the element being removed. + * The user is also cautioned that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + iterator + erase_after(const_iterator __pos, const_iterator __last) + { return iterator(this->_M_erase_after(const_cast<_Node_base*> + (__pos._M_node), + const_cast<_Node_base*> + (__last._M_node))); } + + /** + * @brief Swaps data with another %forward_list. + * @param __list A %forward_list of the same element and allocator + * types. + * + * This exchanges the elements between two lists in constant + * time. Note that the global std::swap() function is + * specialized such that std::swap(l1,l2) will feed to this + * function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(forward_list& __list) noexcept + { + std::swap(this->_M_impl._M_head._M_next, + __list._M_impl._M_head._M_next); + _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(), + __list._M_get_Node_allocator()); + } + + /** + * @brief Resizes the %forward_list to the specified number of + * elements. + * @param __sz Number of elements the %forward_list should contain. + * + * This function will %resize the %forward_list to the specified + * number of elements. If the number is smaller than the + * %forward_list's current number of elements the %forward_list + * is truncated, otherwise the %forward_list is extended and the + * new elements are default constructed. + */ + void + resize(size_type __sz); + + /** + * @brief Resizes the %forward_list to the specified number of + * elements. + * @param __sz Number of elements the %forward_list should contain. + * @param __val Data with which new elements should be populated. + * + * This function will %resize the %forward_list to the specified + * number of elements. If the number is smaller than the + * %forward_list's current number of elements the %forward_list + * is truncated, otherwise the %forward_list is extended and new + * elements are populated with given data. + */ + void + resize(size_type __sz, const value_type& __val); + + /** + * @brief Erases all the elements. + * + * Note that this function only erases + * the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + void + clear() noexcept + { this->_M_erase_after(&this->_M_impl._M_head, nullptr); } + + // 23.3.4.6 forward_list operations: + + /** + * @brief Insert contents of another %forward_list. + * @param __pos Iterator referencing the element to insert after. + * @param __list Source list. + * + * The elements of @a list are inserted in constant time after + * the element referenced by @a pos. @a list becomes an empty + * list. + * + * Requires this != @a x. + */ + void + splice_after(const_iterator __pos, forward_list&& __list) noexcept + { + if (!__list.empty()) + _M_splice_after(__pos, __list.before_begin(), __list.end()); + } + + void + splice_after(const_iterator __pos, forward_list& __list) noexcept + { splice_after(__pos, std::move(__list)); } + + /** + * @brief Insert element from another %forward_list. + * @param __pos Iterator referencing the element to insert after. + * @param __list Source list. + * @param __i Iterator referencing the element before the element + * to move. + * + * Removes the element in list @a list referenced by @a i and + * inserts it into the current list after @a pos. + */ + void + splice_after(const_iterator __pos, forward_list&& __list, + const_iterator __i) noexcept; + + void + splice_after(const_iterator __pos, forward_list& __list, + const_iterator __i) noexcept + { splice_after(__pos, std::move(__list), __i); } + + /** + * @brief Insert range from another %forward_list. + * @param __pos Iterator referencing the element to insert after. + * @param __list Source list. + * @param __before Iterator referencing before the start of range + * in list. + * @param __last Iterator referencing the end of range in list. + * + * Removes elements in the range (__before,__last) and inserts them + * after @a __pos in constant time. + * + * Undefined if @a __pos is in (__before,__last). + * @{ + */ + void + splice_after(const_iterator __pos, forward_list&&, + const_iterator __before, const_iterator __last) noexcept + { _M_splice_after(__pos, __before, __last); } + + void + splice_after(const_iterator __pos, forward_list&, + const_iterator __before, const_iterator __last) noexcept + { _M_splice_after(__pos, __before, __last); } + // @} + + private: +#if __cplusplus > 201703L +# define __cpp_lib_list_remove_return_type 201806L + using __remove_return_type = size_type; +# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG \ + __attribute__((__abi_tag__("__cxx20"))) +#else + using __remove_return_type = void; +# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG +#endif + public: + + /** + * @brief Remove all elements equal to value. + * @param __val The value to remove. + * + * Removes every element in the list equal to @a __val. + * Remaining elements stay in list order. Note that this + * function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type + remove(const _Tp& __val); + + /** + * @brief Remove all elements satisfying a predicate. + * @param __pred Unary predicate function or object. + * + * Removes every element in the list for which the predicate + * returns true. Remaining elements stay in list order. Note + * that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + template + __remove_return_type + remove_if(_Pred __pred); + + /** + * @brief Remove consecutive duplicate elements. + * + * For each consecutive set of elements with the same value, + * remove all but the first one. Remaining elements stay in + * list order. Note that this function only erases the + * elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + */ + _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type + unique() + { return unique(std::equal_to<_Tp>()); } + +#undef _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG + + /** + * @brief Remove consecutive elements satisfying a predicate. + * @param __binary_pred Binary predicate function or object. + * + * For each consecutive set of elements [first,last) that + * satisfy predicate(first,i) where i is an iterator in + * [first,last), remove all but the first one. Remaining + * elements stay in list order. Note that this function only + * erases the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + template + __remove_return_type + unique(_BinPred __binary_pred); + + /** + * @brief Merge sorted lists. + * @param __list Sorted list to merge. + * + * Assumes that both @a list and this list are sorted according to + * operator<(). Merges elements of @a __list into this list in + * sorted order, leaving @a __list empty when complete. Elements in + * this list precede elements in @a __list that are equal. + */ + void + merge(forward_list&& __list) + { merge(std::move(__list), std::less<_Tp>()); } + + void + merge(forward_list& __list) + { merge(std::move(__list)); } + + /** + * @brief Merge sorted lists according to comparison function. + * @param __list Sorted list to merge. + * @param __comp Comparison function defining sort order. + * + * Assumes that both @a __list and this list are sorted according to + * comp. Merges elements of @a __list into this list + * in sorted order, leaving @a __list empty when complete. Elements + * in this list precede elements in @a __list that are equivalent + * according to comp(). + */ + template + void + merge(forward_list&& __list, _Comp __comp); + + template + void + merge(forward_list& __list, _Comp __comp) + { merge(std::move(__list), __comp); } + + /** + * @brief Sort the elements of the list. + * + * Sorts the elements of this list in NlogN time. Equivalent + * elements remain in list order. + */ + void + sort() + { sort(std::less<_Tp>()); } + + /** + * @brief Sort the forward_list using a comparison function. + * + * Sorts the elements of this list in NlogN time. Equivalent + * elements remain in list order. + */ + template + void + sort(_Comp __comp); + + /** + * @brief Reverse the elements in list. + * + * Reverse the order of elements in the list in linear time. + */ + void + reverse() noexcept + { this->_M_impl._M_head._M_reverse_after(); } + + private: + // Called by the range constructor to implement [23.3.4.2]/9 + template + void + _M_range_initialize(_InputIterator __first, _InputIterator __last); + + // Called by forward_list(n,v,a), and the range constructor when it + // turns out to be the same thing. + void + _M_fill_initialize(size_type __n, const value_type& __value); + + // Called by splice_after and insert_after. + iterator + _M_splice_after(const_iterator __pos, const_iterator __before, + const_iterator __last); + + // Called by forward_list(n). + void + _M_default_initialize(size_type __n); + + // Called by resize(sz). + void + _M_default_insert_after(const_iterator __pos, size_type __n); + + // Called by operator=(forward_list&&) + void + _M_move_assign(forward_list&& __list, true_type) noexcept + { + clear(); + this->_M_impl._M_head._M_next = __list._M_impl._M_head._M_next; + __list._M_impl._M_head._M_next = nullptr; + std::__alloc_on_move(this->_M_get_Node_allocator(), + __list._M_get_Node_allocator()); + } + + // Called by operator=(forward_list&&) + void + _M_move_assign(forward_list&& __list, false_type) + { + if (__list._M_get_Node_allocator() == this->_M_get_Node_allocator()) + _M_move_assign(std::move(__list), true_type()); + else + // The rvalue's allocator cannot be moved, or is not equal, + // so we need to individually move each element. + this->assign(std::make_move_iterator(__list.begin()), + std::make_move_iterator(__list.end())); + } + + // Called by assign(_InputIterator, _InputIterator) if _Tp is + // CopyAssignable. + template + void + _M_assign(_InputIterator __first, _InputIterator __last, true_type) + { + auto __prev = before_begin(); + auto __curr = begin(); + auto __end = end(); + while (__curr != __end && __first != __last) + { + *__curr = *__first; + ++__prev; + ++__curr; + ++__first; + } + if (__first != __last) + insert_after(__prev, __first, __last); + else if (__curr != __end) + erase_after(__prev, __end); + } + + // Called by assign(_InputIterator, _InputIterator) if _Tp is not + // CopyAssignable. + template + void + _M_assign(_InputIterator __first, _InputIterator __last, false_type) + { + clear(); + insert_after(cbefore_begin(), __first, __last); + } + + // Called by assign(size_type, const _Tp&) if Tp is CopyAssignable + void + _M_assign_n(size_type __n, const _Tp& __val, true_type) + { + auto __prev = before_begin(); + auto __curr = begin(); + auto __end = end(); + while (__curr != __end && __n > 0) + { + *__curr = __val; + ++__prev; + ++__curr; + --__n; + } + if (__n > 0) + insert_after(__prev, __n, __val); + else if (__curr != __end) + erase_after(__prev, __end); + } + + // Called by assign(size_type, const _Tp&) if Tp is non-CopyAssignable + void + _M_assign_n(size_type __n, const _Tp& __val, false_type) + { + clear(); + insert_after(cbefore_begin(), __n, __val); + } + }; + +#if __cpp_deduction_guides >= 201606 + template::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + forward_list(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> forward_list<_ValT, _Allocator>; +#endif + + /** + * @brief Forward list equality comparison. + * @param __lx A %forward_list + * @param __ly A %forward_list of the same type as @a __lx. + * @return True iff the elements of the forward lists are equal. + * + * This is an equivalence relation. It is linear in the number of + * elements of the forward lists. Deques are considered equivalent + * if corresponding elements compare equal. + */ + template + bool + operator==(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly); + +#if __cpp_lib_three_way_comparison + /** + * @brief Forward list ordering relation. + * @param __x A `forward_list`. + * @param __y A `forward_list` of the same type as `__x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Tp> + operator<=>(const forward_list<_Tp, _Alloc>& __x, + const forward_list<_Tp, _Alloc>& __y) + { + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + /** + * @brief Forward list ordering relation. + * @param __lx A %forward_list. + * @param __ly A %forward_list of the same type as @a __lx. + * @return True iff @a __lx is lexicographically less than @a __ly. + * + * This is a total ordering relation. It is linear in the number of + * elements of the forward lists. The elements must be comparable + * with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return std::lexicographical_compare(__lx.cbegin(), __lx.cend(), + __ly.cbegin(), __ly.cend()); } + + /// Based on operator== + template + inline bool + operator!=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__lx == __ly); } + + /// Based on operator< + template + inline bool + operator>(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return (__ly < __lx); } + + /// Based on operator< + template + inline bool + operator>=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__lx < __ly); } + + /// Based on operator< + template + inline bool + operator<=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__ly < __lx); } +#endif // three-way comparison + + /// See std::forward_list::swap(). + template + inline void + swap(forward_list<_Tp, _Alloc>& __lx, + forward_list<_Tp, _Alloc>& __ly) + noexcept(noexcept(__lx.swap(__ly))) + { __lx.swap(__ly); } + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _FORWARD_LIST_H diff --git a/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc b/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc new file mode 100644 index 000000000..c42bdc0fd --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc @@ -0,0 +1,517 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/forward_list.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{forward_list} + */ + +#ifndef _FORWARD_LIST_TCC +#define _FORWARD_LIST_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + _Fwd_list_base<_Tp, _Alloc>:: + _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a) + : _M_impl(std::move(__a)) + { + if (__lst._M_get_Node_allocator() == _M_get_Node_allocator()) + this->_M_impl._M_head = std::move(__lst._M_impl._M_head); + } + + template + template + _Fwd_list_node_base* + _Fwd_list_base<_Tp, _Alloc>:: + _M_insert_after(const_iterator __pos, _Args&&... __args) + { + _Fwd_list_node_base* __to + = const_cast<_Fwd_list_node_base*>(__pos._M_node); + _Node* __thing = _M_create_node(std::forward<_Args>(__args)...); + __thing->_M_next = __to->_M_next; + __to->_M_next = __thing; + return __to->_M_next; + } + + template + _Fwd_list_node_base* + _Fwd_list_base<_Tp, _Alloc>:: + _M_erase_after(_Fwd_list_node_base* __pos) + { + _Node* __curr = static_cast<_Node*>(__pos->_M_next); + __pos->_M_next = __curr->_M_next; + _Node_alloc_traits::destroy(_M_get_Node_allocator(), + __curr->_M_valptr()); + __curr->~_Node(); + _M_put_node(__curr); + return __pos->_M_next; + } + + template + _Fwd_list_node_base* + _Fwd_list_base<_Tp, _Alloc>:: + _M_erase_after(_Fwd_list_node_base* __pos, + _Fwd_list_node_base* __last) + { + _Node* __curr = static_cast<_Node*>(__pos->_M_next); + while (__curr != __last) + { + _Node* __temp = __curr; + __curr = static_cast<_Node*>(__curr->_M_next); + _Node_alloc_traits::destroy(_M_get_Node_allocator(), + __temp->_M_valptr()); + __temp->~_Node(); + _M_put_node(__temp); + } + __pos->_M_next = __last; + return __last; + } + + // Called by the range constructor to implement [23.3.4.2]/9 + template + template + void + forward_list<_Tp, _Alloc>:: + _M_range_initialize(_InputIterator __first, _InputIterator __last) + { + _Node_base* __to = &this->_M_impl._M_head; + for (; __first != __last; ++__first) + { + __to->_M_next = this->_M_create_node(*__first); + __to = __to->_M_next; + } + } + + // Called by forward_list(n,v,a). + template + void + forward_list<_Tp, _Alloc>:: + _M_fill_initialize(size_type __n, const value_type& __value) + { + _Node_base* __to = &this->_M_impl._M_head; + for (; __n; --__n) + { + __to->_M_next = this->_M_create_node(__value); + __to = __to->_M_next; + } + } + + template + void + forward_list<_Tp, _Alloc>:: + _M_default_initialize(size_type __n) + { + _Node_base* __to = &this->_M_impl._M_head; + for (; __n; --__n) + { + __to->_M_next = this->_M_create_node(); + __to = __to->_M_next; + } + } + + template + forward_list<_Tp, _Alloc>& + forward_list<_Tp, _Alloc>:: + operator=(const forward_list& __list) + { + if (std::__addressof(__list) != this) + { + if (_Node_alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_get_Node_allocator(); + auto& __that_alloc = __list._M_get_Node_allocator(); + if (!_Node_alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // replacement allocator cannot free existing storage + clear(); + } + std::__alloc_on_copy(__this_alloc, __that_alloc); + } + assign(__list.cbegin(), __list.cend()); + } + return *this; + } + + template + void + forward_list<_Tp, _Alloc>:: + _M_default_insert_after(const_iterator __pos, size_type __n) + { + const_iterator __saved_pos = __pos; + __try + { + for (; __n; --__n) + __pos = emplace_after(__pos); + } + __catch(...) + { + erase_after(__saved_pos, ++__pos); + __throw_exception_again; + } + } + + template + void + forward_list<_Tp, _Alloc>:: + resize(size_type __sz) + { + iterator __k = before_begin(); + + size_type __len = 0; + while (__k._M_next() != end() && __len < __sz) + { + ++__k; + ++__len; + } + if (__len == __sz) + erase_after(__k, end()); + else + _M_default_insert_after(__k, __sz - __len); + } + + template + void + forward_list<_Tp, _Alloc>:: + resize(size_type __sz, const value_type& __val) + { + iterator __k = before_begin(); + + size_type __len = 0; + while (__k._M_next() != end() && __len < __sz) + { + ++__k; + ++__len; + } + if (__len == __sz) + erase_after(__k, end()); + else + insert_after(__k, __sz - __len, __val); + } + + template + typename forward_list<_Tp, _Alloc>::iterator + forward_list<_Tp, _Alloc>:: + _M_splice_after(const_iterator __pos, + const_iterator __before, const_iterator __last) + { + _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node); + _Node_base* __b = const_cast<_Node_base*>(__before._M_node); + _Node_base* __end = __b; + + while (__end && __end->_M_next != __last._M_node) + __end = __end->_M_next; + + if (__b != __end) + return iterator(__tmp->_M_transfer_after(__b, __end)); + else + return iterator(__tmp); + } + + template + void + forward_list<_Tp, _Alloc>:: + splice_after(const_iterator __pos, forward_list&&, + const_iterator __i) noexcept + { + const_iterator __j = __i; + ++__j; + + if (__pos == __i || __pos == __j) + return; + + _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node); + __tmp->_M_transfer_after(const_cast<_Node_base*>(__i._M_node), + const_cast<_Node_base*>(__j._M_node)); + } + + template + typename forward_list<_Tp, _Alloc>::iterator + forward_list<_Tp, _Alloc>:: + insert_after(const_iterator __pos, size_type __n, const _Tp& __val) + { + if (__n) + { + forward_list __tmp(__n, __val, get_allocator()); + return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end()); + } + else + return iterator(const_cast<_Node_base*>(__pos._M_node)); + } + + template + template + typename forward_list<_Tp, _Alloc>::iterator + forward_list<_Tp, _Alloc>:: + insert_after(const_iterator __pos, + _InputIterator __first, _InputIterator __last) + { + forward_list __tmp(__first, __last, get_allocator()); + if (!__tmp.empty()) + return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end()); + else + return iterator(const_cast<_Node_base*>(__pos._M_node)); + } + +#if __cplusplus > 201703L +# define _GLIBCXX20_ONLY(__expr) __expr +#else +# define _GLIBCXX20_ONLY(__expr) +#endif + + template + auto + forward_list<_Tp, _Alloc>:: + remove(const _Tp& __val) -> __remove_return_type + { + size_type __removed __attribute__((__unused__)) = 0; + _Node_base* __curr = &this->_M_impl._M_head; + _Node_base* __extra = nullptr; + + while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) + { + if (*__tmp->_M_valptr() == __val) + { + if (__tmp->_M_valptr() != std::__addressof(__val)) + { + this->_M_erase_after(__curr); + _GLIBCXX20_ONLY( __removed++ ); + continue; + } + else + __extra = __curr; + } + __curr = __curr->_M_next; + } + + if (__extra) + { + this->_M_erase_after(__extra); + _GLIBCXX20_ONLY( __removed++ ); + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + template + auto + forward_list<_Tp, _Alloc>:: + remove_if(_Pred __pred) -> __remove_return_type + { + size_type __removed __attribute__((__unused__)) = 0; + _Node_base* __curr = &this->_M_impl._M_head; + while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) + { + if (__pred(*__tmp->_M_valptr())) + { + this->_M_erase_after(__curr); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __curr = __curr->_M_next; + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + template + auto + forward_list<_Tp, _Alloc>:: + unique(_BinPred __binary_pred) -> __remove_return_type + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return _GLIBCXX20_ONLY(0); + size_type __removed __attribute__((__unused__)) = 0; + iterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(*__first, *__next)) + { + erase_after(__first); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __first = __next; + __next = __first; + } + return _GLIBCXX20_ONLY( __removed ); + } + +#undef _GLIBCXX20_ONLY + + template + template + void + forward_list<_Tp, _Alloc>:: + merge(forward_list&& __list, _Comp __comp) + { + _Node_base* __node = &this->_M_impl._M_head; + while (__node->_M_next && __list._M_impl._M_head._M_next) + { + if (__comp(*static_cast<_Node*> + (__list._M_impl._M_head._M_next)->_M_valptr(), + *static_cast<_Node*> + (__node->_M_next)->_M_valptr())) + __node->_M_transfer_after(&__list._M_impl._M_head, + __list._M_impl._M_head._M_next); + __node = __node->_M_next; + } + + if (__list._M_impl._M_head._M_next) + *__node = std::move(__list._M_impl._M_head); + } + + template + bool + operator==(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { + // We don't have size() so we need to walk through both lists + // making sure both iterators are valid. + auto __ix = __lx.cbegin(); + auto __iy = __ly.cbegin(); + while (__ix != __lx.cend() && __iy != __ly.cend()) + { + if (!(*__ix == *__iy)) + return false; + ++__ix; + ++__iy; + } + if (__ix == __lx.cend() && __iy == __ly.cend()) + return true; + else + return false; + } + + template + template + void + forward_list<_Tp, _Alloc>:: + sort(_Comp __comp) + { + // If `next' is nullptr, return immediately. + _Node* __list = static_cast<_Node*>(this->_M_impl._M_head._M_next); + if (!__list) + return; + + unsigned long __insize = 1; + + while (1) + { + _Node* __p = __list; + __list = nullptr; + _Node* __tail = nullptr; + + // Count number of merges we do in this pass. + unsigned long __nmerges = 0; + + while (__p) + { + ++__nmerges; + // There exists a merge to be done. + // Step `insize' places along from p. + _Node* __q = __p; + unsigned long __psize = 0; + for (unsigned long __i = 0; __i < __insize; ++__i) + { + ++__psize; + __q = static_cast<_Node*>(__q->_M_next); + if (!__q) + break; + } + + // If q hasn't fallen off end, we have two lists to merge. + unsigned long __qsize = __insize; + + // Now we have two lists; merge them. + while (__psize > 0 || (__qsize > 0 && __q)) + { + // Decide whether next node of merge comes from p or q. + _Node* __e; + if (__psize == 0) + { + // p is empty; e must come from q. + __e = __q; + __q = static_cast<_Node*>(__q->_M_next); + --__qsize; + } + else if (__qsize == 0 || !__q) + { + // q is empty; e must come from p. + __e = __p; + __p = static_cast<_Node*>(__p->_M_next); + --__psize; + } + else if (!__comp(*__q->_M_valptr(), *__p->_M_valptr())) + { + // First node of q is not lower; e must come from p. + __e = __p; + __p = static_cast<_Node*>(__p->_M_next); + --__psize; + } + else + { + // First node of q is lower; e must come from q. + __e = __q; + __q = static_cast<_Node*>(__q->_M_next); + --__qsize; + } + + // Add the next node to the merged list. + if (__tail) + __tail->_M_next = __e; + else + __list = __e; + __tail = __e; + } + + // Now p has stepped `insize' places along, and q has too. + __p = __q; + } + __tail->_M_next = nullptr; + + // If we have done only one merge, we're finished. + // Allow for nmerges == 0, the empty list case. + if (__nmerges <= 1) + { + this->_M_impl._M_head._M_next = __list; + return; + } + + // Otherwise repeat, merging lists twice the size. + __insize *= 2; + } + } + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _FORWARD_LIST_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bits/functexcept.h b/resources/sources/avr-libstdcpp/include/bits/functexcept.h new file mode 100644 index 000000000..b7494f367 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/functexcept.h @@ -0,0 +1,114 @@ +// Function-Based Exception Support -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/functexcept.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + * + * This header provides support for -fno-exceptions. + */ + +// +// ISO C++ 14882: 19.1 Exception classes +// + +#ifndef _FUNCTEXCEPT_H +#define _FUNCTEXCEPT_H 1 + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Helper for exception objects in + void + __throw_bad_exception(void) __attribute__((__noreturn__)); + + // Helper for exception objects in + void + __throw_bad_alloc(void) __attribute__((__noreturn__)); + + // Helper for exception objects in + void + __throw_bad_cast(void) __attribute__((__noreturn__)); + + void + __throw_bad_typeid(void) __attribute__((__noreturn__)); + + // Helpers for exception objects in + void + __throw_logic_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_domain_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_invalid_argument(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_length_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_out_of_range(const char* __s = "") __attribute__((__noreturn__)); + + inline void __attribute__((__noreturn__)) __attribute__((always_inline)) + __throw_out_of_range_fmt(const char*, ...) + { __throw_out_of_range(); } + + void + __throw_runtime_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_range_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_overflow_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_underflow_error(const char* __s = "") __attribute__((__noreturn__)); + + // Helpers for exception objects in + void + __throw_system_error(int) __attribute__((__noreturn__)); + + // Helpers for exception objects in + void + __throw_bad_function_call() __attribute__((__noreturn__)); + + void + __throw_bad_optional_access() __attribute__((__noreturn__)); + + void + __throw_bad_variant_access(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_bad_any_cast() __attribute__((__noreturn__)); + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/functional_hash.h b/resources/sources/avr-libstdcpp/include/bits/functional_hash.h new file mode 100644 index 000000000..e50b047ff --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/functional_hash.h @@ -0,0 +1,280 @@ +// functional_hash.h header -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/functional_hash.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _FUNCTIONAL_HASH_H +#define _FUNCTIONAL_HASH_H 1 + +#pragma GCC system_header + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @defgroup hashes Hashes + * @ingroup functors + * + * Hashing functors taking a variable type and returning a @c std::size_t. + * + * @{ + */ + + template + struct __hash_base + { + typedef _Result result_type _GLIBCXX17_DEPRECATED; + typedef _Arg argument_type _GLIBCXX17_DEPRECATED; + }; + + /// Primary class template hash. + template + struct hash; + + template + struct __poison_hash + { + static constexpr bool __enable_hash_call = false; + private: + // Private rather than deleted to be non-trivially-copyable. + __poison_hash(__poison_hash&&); + ~__poison_hash(); + }; + + template + struct __poison_hash<_Tp, __void_t()(declval<_Tp>()))>> + { + static constexpr bool __enable_hash_call = true; + }; + + // Helper struct for SFINAE-poisoning non-enum types. + template::value> + struct __hash_enum + { + private: + // Private rather than deleted to be non-trivially-copyable. + __hash_enum(__hash_enum&&); + ~__hash_enum(); + }; + + // Helper struct for hash with enum types. + template + struct __hash_enum<_Tp, true> : public __hash_base + { + size_t + operator()(_Tp __val) const noexcept + { + using __type = typename underlying_type<_Tp>::type; + return hash<__type>{}(static_cast<__type>(__val)); + } + }; + + /// Primary class template hash, usable for enum types only. + // Use with non-enum types still SFINAES. + template + struct hash : __hash_enum<_Tp> + { }; + + /// Partial specializations for pointer types. + template + struct hash<_Tp*> : public __hash_base + { + size_t + operator()(_Tp* __p) const noexcept + { return reinterpret_cast(__p); } + }; + + // Explicit specializations for integer types. +#define _Cxx_hashtable_define_trivial_hash(_Tp) \ + template<> \ + struct hash<_Tp> : public __hash_base \ + { \ + size_t \ + operator()(_Tp __val) const noexcept \ + { return static_cast(__val); } \ + }; + + /// Explicit specialization for bool. + _Cxx_hashtable_define_trivial_hash(bool) + + /// Explicit specialization for char. + _Cxx_hashtable_define_trivial_hash(char) + + /// Explicit specialization for signed char. + _Cxx_hashtable_define_trivial_hash(signed char) + + /// Explicit specialization for unsigned char. + _Cxx_hashtable_define_trivial_hash(unsigned char) + + /// Explicit specialization for wchar_t. + _Cxx_hashtable_define_trivial_hash(wchar_t) + +#ifdef _GLIBCXX_USE_CHAR8_T + /// Explicit specialization for char8_t. + _Cxx_hashtable_define_trivial_hash(char8_t) +#endif + + /// Explicit specialization for char16_t. + _Cxx_hashtable_define_trivial_hash(char16_t) + + /// Explicit specialization for char32_t. + _Cxx_hashtable_define_trivial_hash(char32_t) + + /// Explicit specialization for short. + _Cxx_hashtable_define_trivial_hash(short) + + /// Explicit specialization for int. + _Cxx_hashtable_define_trivial_hash(int) + + /// Explicit specialization for long. + _Cxx_hashtable_define_trivial_hash(long) + + /// Explicit specialization for long long. + _Cxx_hashtable_define_trivial_hash(long long) + + /// Explicit specialization for unsigned short. + _Cxx_hashtable_define_trivial_hash(unsigned short) + + /// Explicit specialization for unsigned int. + _Cxx_hashtable_define_trivial_hash(unsigned int) + + /// Explicit specialization for unsigned long. + _Cxx_hashtable_define_trivial_hash(unsigned long) + + /// Explicit specialization for unsigned long long. + _Cxx_hashtable_define_trivial_hash(unsigned long long) + +#ifdef __GLIBCXX_TYPE_INT_N_0 + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0) + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1) + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2) + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3) + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3 unsigned) +#endif + +#undef _Cxx_hashtable_define_trivial_hash + + struct _Hash_impl + { + static size_t + hash(const void* __ptr, size_t __clength, + size_t __seed = static_cast(0xc70f6907UL)) + { return _Hash_bytes(__ptr, __clength, __seed); } + + template + static size_t + hash(const _Tp& __val) + { return hash(&__val, sizeof(__val)); } + + template + static size_t + __hash_combine(const _Tp& __val, size_t __hash) + { return hash(&__val, sizeof(__val), __hash); } + }; + + // A hash function similar to FNV-1a (see PR59406 for how it differs). + struct _Fnv_hash_impl + { + static size_t + hash(const void* __ptr, size_t __clength, + size_t __seed = static_cast(2166136261UL)) + { return _Fnv_hash_bytes(__ptr, __clength, __seed); } + + template + static size_t + hash(const _Tp& __val) + { return hash(&__val, sizeof(__val)); } + + template + static size_t + __hash_combine(const _Tp& __val, size_t __hash) + { return hash(&__val, sizeof(__val), __hash); } + }; + + /// Specialization for float. + template<> + struct hash : public __hash_base + { + size_t + operator()(float __val) const noexcept + { + // 0 and -0 both hash to zero. + return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0; + } + }; + + /// Specialization for double. + template<> + struct hash : public __hash_base + { + size_t + operator()(double __val) const noexcept + { + // 0 and -0 both hash to zero. + return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0; + } + }; + +#if __cplusplus >= 201703L + template<> + struct hash : public __hash_base + { + size_t + operator()(nullptr_t) const noexcept + { return 0; } + }; +#endif + + // @} group hashes + + // Hint about performance of hash functor. If not fast the hash-based + // containers will cache the hash code. + // Default behavior is to consider that hashers are fast unless specified + // otherwise. + template + struct __is_fast_hash : public std::true_type + { }; + + template<> + struct __is_fast_hash> : public std::false_type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // _FUNCTIONAL_HASH_H diff --git a/resources/sources/avr-libstdcpp/include/bits/gslice.h b/resources/sources/avr-libstdcpp/include/bits/gslice.h new file mode 100644 index 000000000..b252c3c1f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/gslice.h @@ -0,0 +1,185 @@ +// The template and inlines for the -*- C++ -*- gslice class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/gslice.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _GSLICE_H +#define _GSLICE_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Class defining multi-dimensional subset of an array. + * + * The slice class represents a multi-dimensional subset of an array, + * specified by three parameter sets: start offset, size array, and stride + * array. The start offset is the index of the first element of the array + * that is part of the subset. The size and stride array describe each + * dimension of the slice. Size is the number of elements in that + * dimension, and stride is the distance in the array between successive + * elements in that dimension. Each dimension's size and stride is taken + * to begin at an array element described by the previous dimension. The + * size array and stride array must be the same size. + * + * For example, if you have offset==3, stride[0]==11, size[1]==3, + * stride[1]==3, then slice[0,0]==array[3], slice[0,1]==array[6], + * slice[0,2]==array[9], slice[1,0]==array[14], slice[1,1]==array[17], + * slice[1,2]==array[20]. + */ + class gslice + { + public: + /// Construct an empty slice. + gslice(); + + /** + * @brief Construct a slice. + * + * Constructs a slice with as many dimensions as the length of the @a l + * and @a s arrays. + * + * @param __o Offset in array of first element. + * @param __l Array of dimension lengths. + * @param __s Array of dimension strides between array elements. + */ + gslice(size_t __o, const valarray& __l, + const valarray& __s); + + // XXX: the IS says the copy-ctor and copy-assignment operators are + // synthesized by the compiler but they are just unsuitable + // for a ref-counted semantic + /// Copy constructor. + gslice(const gslice&); + + /// Destructor. + ~gslice(); + + // XXX: See the note above. + /// Assignment operator. + gslice& operator=(const gslice&); + + /// Return array offset of first slice element. + size_t start() const; + + /// Return array of sizes of slice dimensions. + valarray size() const; + + /// Return array of array strides for each dimension. + valarray stride() const; + + private: + struct _Indexer + { + size_t _M_count; + size_t _M_start; + valarray _M_size; + valarray _M_stride; + valarray _M_index; // Linear array of referenced indices + + _Indexer() + : _M_count(1), _M_start(0), _M_size(), _M_stride(), _M_index() {} + + _Indexer(size_t, const valarray&, + const valarray&); + + void + _M_increment_use() + { ++_M_count; } + + size_t + _M_decrement_use() + { return --_M_count; } + }; + + _Indexer* _M_index; + + template friend class valarray; + }; + + inline size_t + gslice::start() const + { return _M_index ? _M_index->_M_start : 0; } + + inline valarray + gslice::size() const + { return _M_index ? _M_index->_M_size : valarray(); } + + inline valarray + gslice::stride() const + { return _M_index ? _M_index->_M_stride : valarray(); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 543. valarray slice default constructor + inline + gslice::gslice() + : _M_index(new gslice::_Indexer()) {} + + inline + gslice::gslice(size_t __o, const valarray& __l, + const valarray& __s) + : _M_index(new gslice::_Indexer(__o, __l, __s)) {} + + inline + gslice::gslice(const gslice& __g) + : _M_index(__g._M_index) + { if (_M_index) _M_index->_M_increment_use(); } + + inline + gslice::~gslice() + { + if (_M_index && _M_index->_M_decrement_use() == 0) + delete _M_index; + } + + inline gslice& + gslice::operator=(const gslice& __g) + { + if (__g._M_index) + __g._M_index->_M_increment_use(); + if (_M_index && _M_index->_M_decrement_use() == 0) + delete _M_index; + _M_index = __g._M_index; + return *this; + } + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _GSLICE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/gslice_array.h b/resources/sources/avr-libstdcpp/include/bits/gslice_array.h new file mode 100644 index 000000000..89fdda537 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/gslice_array.h @@ -0,0 +1,223 @@ +// The template and inlines for the -*- C++ -*- gslice_array class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/gslice_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _GSLICE_ARRAY_H +#define _GSLICE_ARRAY_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Reference to multi-dimensional subset of an array. + * + * A gslice_array is a reference to the actual elements of an array + * specified by a gslice. The way to get a gslice_array is to call + * operator[](gslice) on a valarray. The returned gslice_array then + * permits carrying operations out on the referenced subset of elements in + * the original valarray. For example, operator+=(valarray) will add + * values to the subset of elements in the underlying valarray this + * gslice_array refers to. + * + * @param Tp Element type. + */ + template + class gslice_array + { + public: + typedef _Tp value_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 253. valarray helper functions are almost entirely useless + + /// Copy constructor. Both slices refer to the same underlying array. + gslice_array(const gslice_array&); + + /// Assignment operator. Assigns slice elements to corresponding + /// elements of @a a. + gslice_array& operator=(const gslice_array&); + + /// Assign slice elements to corresponding elements of @a v. + void operator=(const valarray<_Tp>&) const; + /// Multiply slice elements by corresponding elements of @a v. + void operator*=(const valarray<_Tp>&) const; + /// Divide slice elements by corresponding elements of @a v. + void operator/=(const valarray<_Tp>&) const; + /// Modulo slice elements by corresponding elements of @a v. + void operator%=(const valarray<_Tp>&) const; + /// Add corresponding elements of @a v to slice elements. + void operator+=(const valarray<_Tp>&) const; + /// Subtract corresponding elements of @a v from slice elements. + void operator-=(const valarray<_Tp>&) const; + /// Logical xor slice elements with corresponding elements of @a v. + void operator^=(const valarray<_Tp>&) const; + /// Logical and slice elements with corresponding elements of @a v. + void operator&=(const valarray<_Tp>&) const; + /// Logical or slice elements with corresponding elements of @a v. + void operator|=(const valarray<_Tp>&) const; + /// Left shift slice elements by corresponding elements of @a v. + void operator<<=(const valarray<_Tp>&) const; + /// Right shift slice elements by corresponding elements of @a v. + void operator>>=(const valarray<_Tp>&) const; + /// Assign all slice elements to @a t. + void operator=(const _Tp&) const; + + template + void operator=(const _Expr<_Dom, _Tp>&) const; + template + void operator*=(const _Expr<_Dom, _Tp>&) const; + template + void operator/=(const _Expr<_Dom, _Tp>&) const; + template + void operator%=(const _Expr<_Dom, _Tp>&) const; + template + void operator+=(const _Expr<_Dom, _Tp>&) const; + template + void operator-=(const _Expr<_Dom, _Tp>&) const; + template + void operator^=(const _Expr<_Dom, _Tp>&) const; + template + void operator&=(const _Expr<_Dom, _Tp>&) const; + template + void operator|=(const _Expr<_Dom, _Tp>&) const; + template + void operator<<=(const _Expr<_Dom, _Tp>&) const; + template + void operator>>=(const _Expr<_Dom, _Tp>&) const; + + private: + _Array<_Tp> _M_array; + const valarray& _M_index; + + friend class valarray<_Tp>; + + gslice_array(_Array<_Tp>, const valarray&); + +#if __cplusplus < 201103L + // not implemented + gslice_array(); +#else + public: + gslice_array() = delete; +#endif + }; + + template + inline + gslice_array<_Tp>::gslice_array(_Array<_Tp> __a, + const valarray& __i) + : _M_array(__a), _M_index(__i) {} + + template + inline + gslice_array<_Tp>::gslice_array(const gslice_array<_Tp>& __a) + : _M_array(__a._M_array), _M_index(__a._M_index) {} + + template + inline gslice_array<_Tp>& + gslice_array<_Tp>::operator=(const gslice_array<_Tp>& __a) + { + std::__valarray_copy(_Array<_Tp>(__a._M_array), + _Array(__a._M_index), _M_index.size(), + _M_array, _Array(_M_index)); + return *this; + } + + template + inline void + gslice_array<_Tp>::operator=(const _Tp& __t) const + { + std::__valarray_fill(_M_array, _Array(_M_index), + _M_index.size(), __t); + } + + template + inline void + gslice_array<_Tp>::operator=(const valarray<_Tp>& __v) const + { + std::__valarray_copy(_Array<_Tp>(__v), __v.size(), + _M_array, _Array(_M_index)); + } + + template + template + inline void + gslice_array<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) const + { + std::__valarray_copy (__e, _M_index.size(), _M_array, + _Array(_M_index)); + } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ + template \ + inline void \ + gslice_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ + { \ + _Array_augmented_##_Name(_M_array, _Array(_M_index), \ + _Array<_Tp>(__v), __v.size()); \ + } \ + \ + template \ + template \ + inline void \ + gslice_array<_Tp>::operator _Op##= (const _Expr<_Dom, _Tp>& __e) const\ + { \ + _Array_augmented_##_Name(_M_array, _Array(_M_index), __e,\ + _M_index.size()); \ + } + +_DEFINE_VALARRAY_OPERATOR(*, __multiplies) +_DEFINE_VALARRAY_OPERATOR(/, __divides) +_DEFINE_VALARRAY_OPERATOR(%, __modulus) +_DEFINE_VALARRAY_OPERATOR(+, __plus) +_DEFINE_VALARRAY_OPERATOR(-, __minus) +_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) +_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) +_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) +_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _GSLICE_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h b/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h new file mode 100644 index 000000000..8d9c9eb24 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h @@ -0,0 +1,59 @@ +// Declarations for hash functions. -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/hash_bytes.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _HASH_BYTES_H +#define _HASH_BYTES_H 1 + +#pragma GCC system_header + +#include + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Hash function implementation for the nontrivial specialization. + // All of them are based on a primitive that hashes a pointer to a + // byte array. The actual hash algorithm is not guaranteed to stay + // the same from release to release -- it may be updated or tuned to + // improve hash quality or speed. + size_t + _Hash_bytes(const void* __ptr, size_t __len, size_t __seed); + + // A similar hash primitive, using the FNV hash algorithm. This + // algorithm is guaranteed to stay the same from release to release. + // (although it might not produce the same values on different + // machines.) + size_t + _Fnv_hash_bytes(const void* __ptr, size_t __len, size_t __seed); + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/hashtable.h b/resources/sources/avr-libstdcpp/include/bits/hashtable.h new file mode 100644 index 000000000..b00319a66 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/hashtable.h @@ -0,0 +1,2228 @@ +// hashtable.h header -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/hashtable.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{unordered_map, unordered_set} + */ + +#ifndef _HASHTABLE_H +#define _HASHTABLE_H 1 + +#pragma GCC system_header + +#include +#if __cplusplus > 201402L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + using __cache_default + = __not_<__and_, + // Mandatory to have erase not throwing. + __is_nothrow_invocable>>; + + /** + * Primary class template _Hashtable. + * + * @ingroup hashtable-detail + * + * @tparam _Value CopyConstructible type. + * + * @tparam _Key CopyConstructible type. + * + * @tparam _Alloc An allocator type + * ([lib.allocator.requirements]) whose _Alloc::value_type is + * _Value. As a conforming extension, we allow for + * _Alloc::value_type != _Value. + * + * @tparam _ExtractKey Function object that takes an object of type + * _Value and returns a value of type _Key. + * + * @tparam _Equal Function object that takes two objects of type k + * and returns a bool-like value that is true if the two objects + * are considered equal. + * + * @tparam _H1 The hash function. A unary function object with + * argument type _Key and result type size_t. Return values should + * be distributed over the entire range [0, numeric_limits:::max()]. + * + * @tparam _H2 The range-hashing function (in the terminology of + * Tavori and Dreizin). A binary function object whose argument + * types and result type are all size_t. Given arguments r and N, + * the return value is in the range [0, N). + * + * @tparam _Hash The ranged hash function (Tavori and Dreizin). A + * binary function whose argument types are _Key and size_t and + * whose result type is size_t. Given arguments k and N, the + * return value is in the range [0, N). Default: hash(k, N) = + * h2(h1(k), N). If _Hash is anything other than the default, _H1 + * and _H2 are ignored. + * + * @tparam _RehashPolicy Policy class with three members, all of + * which govern the bucket count. _M_next_bkt(n) returns a bucket + * count no smaller than n. _M_bkt_for_elements(n) returns a + * bucket count appropriate for an element count of n. + * _M_need_rehash(n_bkt, n_elt, n_ins) determines whether, if the + * current bucket count is n_bkt and the current element count is + * n_elt, we need to increase the bucket count. If so, returns + * make_pair(true, n), where n is the new bucket count. If not, + * returns make_pair(false, ) + * + * @tparam _Traits Compile-time class with three boolean + * std::integral_constant members: __cache_hash_code, __constant_iterators, + * __unique_keys. + * + * Each _Hashtable data structure has: + * + * - _Bucket[] _M_buckets + * - _Hash_node_base _M_before_begin + * - size_type _M_bucket_count + * - size_type _M_element_count + * + * with _Bucket being _Hash_node* and _Hash_node containing: + * + * - _Hash_node* _M_next + * - Tp _M_value + * - size_t _M_hash_code if cache_hash_code is true + * + * In terms of Standard containers the hashtable is like the aggregation of: + * + * - std::forward_list<_Node> containing the elements + * - std::vector::iterator> representing the buckets + * + * The non-empty buckets contain the node before the first node in the + * bucket. This design makes it possible to implement something like a + * std::forward_list::insert_after on container insertion and + * std::forward_list::erase_after on container erase + * calls. _M_before_begin is equivalent to + * std::forward_list::before_begin. Empty buckets contain + * nullptr. Note that one of the non-empty buckets contains + * &_M_before_begin which is not a dereferenceable node so the + * node pointer in a bucket shall never be dereferenced, only its + * next node can be. + * + * Walking through a bucket's nodes requires a check on the hash code to + * see if each node is still in the bucket. Such a design assumes a + * quite efficient hash functor and is one of the reasons it is + * highly advisable to set __cache_hash_code to true. + * + * The container iterators are simply built from nodes. This way + * incrementing the iterator is perfectly efficient independent of + * how many empty buckets there are in the container. + * + * On insert we compute the element's hash code and use it to find the + * bucket index. If the element must be inserted in an empty bucket + * we add it at the beginning of the singly linked list and make the + * bucket point to _M_before_begin. The bucket that used to point to + * _M_before_begin, if any, is updated to point to its new before + * begin node. + * + * On erase, the simple iterator design requires using the hash + * functor to get the index of the bucket to update. For this + * reason, when __cache_hash_code is set to false the hash functor must + * not throw and this is enforced by a static assertion. + * + * Functionality is implemented by decomposition into base classes, + * where the derived _Hashtable class is used in _Map_base, + * _Insert, _Rehash_base, and _Equality base classes to access the + * "this" pointer. _Hashtable_base is used in the base classes as a + * non-recursive, fully-completed-type so that detailed nested type + * information, such as iterator type and node type, can be + * used. This is similar to the "Curiously Recurring Template + * Pattern" (CRTP) technique, but uses a reconstructed, not + * explicitly passed, template pattern. + * + * Base class templates are: + * - __detail::_Hashtable_base + * - __detail::_Map_base + * - __detail::_Insert + * - __detail::_Rehash_base + * - __detail::_Equality + */ + template + class _Hashtable + : public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, + _H1, _H2, _Hash, _Traits>, + public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>, + public __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>, + public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>, + public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>, + private __detail::_Hashtable_alloc< + __alloc_rebind<_Alloc, + __detail::_Hash_node<_Value, + _Traits::__hash_cached::value>>> + { + static_assert(is_same::type, _Value>::value, + "unordered container must have a non-const, non-volatile value_type"); +#if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same{}, + "unordered container must have the same value_type as its allocator"); +#endif + + using __traits_type = _Traits; + using __hash_cached = typename __traits_type::__hash_cached; + using __node_type = __detail::_Hash_node<_Value, __hash_cached::value>; + using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>; + + using __hashtable_alloc = __detail::_Hashtable_alloc<__node_alloc_type>; + + using __value_alloc_traits = + typename __hashtable_alloc::__value_alloc_traits; + using __node_alloc_traits = + typename __hashtable_alloc::__node_alloc_traits; + using __node_base = typename __hashtable_alloc::__node_base; + using __bucket_type = typename __hashtable_alloc::__bucket_type; + + public: + typedef _Key key_type; + typedef _Value value_type; + typedef _Alloc allocator_type; + typedef _Equal key_equal; + + // mapped_type, if present, comes from _Map_base. + // hasher, if present, comes from _Hash_code_base/_Hashtable_base. + typedef typename __value_alloc_traits::pointer pointer; + typedef typename __value_alloc_traits::const_pointer const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + private: + using __rehash_type = _RehashPolicy; + using __rehash_state = typename __rehash_type::_State; + + using __constant_iterators = typename __traits_type::__constant_iterators; + using __unique_keys = typename __traits_type::__unique_keys; + + using __key_extract = typename std::conditional< + __constant_iterators::value, + __detail::_Identity, + __detail::_Select1st>::type; + + using __hashtable_base = __detail:: + _Hashtable_base<_Key, _Value, _ExtractKey, + _Equal, _H1, _H2, _Hash, _Traits>; + + using __hash_code_base = typename __hashtable_base::__hash_code_base; + using __hash_code = typename __hashtable_base::__hash_code; + using __ireturn_type = typename __hashtable_base::__ireturn_type; + + using __map_base = __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __rehash_base = __detail::_Rehash_base<_Key, _Value, _Alloc, + _ExtractKey, _Equal, + _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __eq_base = __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __reuse_or_alloc_node_gen_t = + __detail::_ReuseOrAllocNode<__node_alloc_type>; + using __alloc_node_gen_t = + __detail::_AllocNode<__node_alloc_type>; + + // Simple RAII type for managing a node containing an element + struct _Scoped_node + { + // Take ownership of a node with a constructed element. + _Scoped_node(__node_type* __n, __hashtable_alloc* __h) + : _M_h(__h), _M_node(__n) { } + + // Allocate a node and construct an element within it. + template + _Scoped_node(__hashtable_alloc* __h, _Args&&... __args) + : _M_h(__h), + _M_node(__h->_M_allocate_node(std::forward<_Args>(__args)...)) + { } + + // Destroy element and deallocate node. + ~_Scoped_node() { if (_M_node) _M_h->_M_deallocate_node(_M_node); }; + + _Scoped_node(const _Scoped_node&) = delete; + _Scoped_node& operator=(const _Scoped_node&) = delete; + + __hashtable_alloc* _M_h; + __node_type* _M_node; + }; + + template + static constexpr + typename conditional::value, + const value_type&, value_type&&>::type + __fwd_value_for(value_type& __val) noexcept + { return std::move(__val); } + + // Metaprogramming for picking apart hash caching. + template + using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>; + + template + using __if_hash_not_cached = __or_<__hash_cached, _Cond>; + + // Compile-time diagnostics. + + // _Hash_code_base has everything protected, so use this derived type to + // access it. + struct __hash_code_base_access : __hash_code_base + { using __hash_code_base::_M_bucket_index; }; + + // Getting a bucket index from a node shall not throw because it is used + // in methods (erase, swap...) that shall not throw. + static_assert(noexcept(declval() + ._M_bucket_index((const __node_type*)nullptr, + (std::size_t)0)), + "Cache the hash code or qualify your functors involved" + " in hash code and bucket index computation with noexcept"); + + // When hash codes are cached local iterator inherits from H2 functor + // which must then be default constructible. + static_assert(__if_hash_cached>::value, + "Functor used to map hash code to bucket index" + " must be default constructible"); + + template + friend struct __detail::_Map_base; + + template + friend struct __detail::_Insert_base; + + template + friend struct __detail::_Insert; + + template + friend struct __detail::_Equality; + + public: + using size_type = typename __hashtable_base::size_type; + using difference_type = typename __hashtable_base::difference_type; + + using iterator = typename __hashtable_base::iterator; + using const_iterator = typename __hashtable_base::const_iterator; + + using local_iterator = typename __hashtable_base::local_iterator; + using const_local_iterator = typename __hashtable_base:: + const_local_iterator; + +#if __cplusplus > 201402L + using node_type = _Node_handle<_Key, _Value, __node_alloc_type>; + using insert_return_type = _Node_insert_return; +#endif + + private: + __bucket_type* _M_buckets = &_M_single_bucket; + size_type _M_bucket_count = 1; + __node_base _M_before_begin; + size_type _M_element_count = 0; + _RehashPolicy _M_rehash_policy; + + // A single bucket used when only need for 1 bucket. Especially + // interesting in move semantic to leave hashtable with only 1 bucket + // which is not allocated so that we can have those operations noexcept + // qualified. + // Note that we can't leave hashtable with 0 bucket without adding + // numerous checks in the code to avoid 0 modulus. + __bucket_type _M_single_bucket = nullptr; + + bool + _M_uses_single_bucket(__bucket_type* __bkts) const + { return __builtin_expect(__bkts == &_M_single_bucket, false); } + + bool + _M_uses_single_bucket() const + { return _M_uses_single_bucket(_M_buckets); } + + __hashtable_alloc& + _M_base_alloc() { return *this; } + + __bucket_type* + _M_allocate_buckets(size_type __bkt_count) + { + if (__builtin_expect(__bkt_count == 1, false)) + { + _M_single_bucket = nullptr; + return &_M_single_bucket; + } + + return __hashtable_alloc::_M_allocate_buckets(__bkt_count); + } + + void + _M_deallocate_buckets(__bucket_type* __bkts, size_type __bkt_count) + { + if (_M_uses_single_bucket(__bkts)) + return; + + __hashtable_alloc::_M_deallocate_buckets(__bkts, __bkt_count); + } + + void + _M_deallocate_buckets() + { _M_deallocate_buckets(_M_buckets, _M_bucket_count); } + + // Gets bucket begin, deals with the fact that non-empty buckets contain + // their before begin node. + __node_type* + _M_bucket_begin(size_type __bkt) const; + + __node_type* + _M_begin() const + { return static_cast<__node_type*>(_M_before_begin._M_nxt); } + + // Assign *this using another _Hashtable instance. Whether elements + // are copied or moved depends on the _Ht reference. + template + void + _M_assign_elements(_Ht&&); + + template + void + _M_assign(_Ht&&, const _NodeGenerator&); + + void + _M_move_assign(_Hashtable&&, true_type); + + void + _M_move_assign(_Hashtable&&, false_type); + + void + _M_reset() noexcept; + + _Hashtable(const _H1& __h1, const _H2& __h2, const _Hash& __h, + const _Equal& __eq, const _ExtractKey& __exk, + const allocator_type& __a) + : __hashtable_base(__exk, __h1, __h2, __h, __eq), + __hashtable_alloc(__node_alloc_type(__a)) + { } + + public: + // Constructor, destructor, assignment, swap + _Hashtable() = default; + _Hashtable(size_type __bkt_count_hint, + const _H1&, const _H2&, const _Hash&, + const _Equal&, const _ExtractKey&, + const allocator_type&); + + template + _Hashtable(_InputIterator __first, _InputIterator __last, + size_type __bkt_count_hint, + const _H1&, const _H2&, const _Hash&, + const _Equal&, const _ExtractKey&, + const allocator_type&); + + _Hashtable(const _Hashtable&); + + _Hashtable(_Hashtable&&) noexcept; + + _Hashtable(const _Hashtable&, const allocator_type&); + + _Hashtable(_Hashtable&&, const allocator_type&); + + // Use delegating constructors. + explicit + _Hashtable(const allocator_type& __a) + : __hashtable_alloc(__node_alloc_type(__a)) + { } + + explicit + _Hashtable(size_type __bkt_count_hint, + const _H1& __hf = _H1(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Hashtable(__bkt_count_hint, __hf, _H2(), _Hash(), __eql, + __key_extract(), __a) + { } + + template + _Hashtable(_InputIterator __f, _InputIterator __l, + size_type __bkt_count_hint = 0, + const _H1& __hf = _H1(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Hashtable(__f, __l, __bkt_count_hint, __hf, _H2(), _Hash(), __eql, + __key_extract(), __a) + { } + + _Hashtable(initializer_list __l, + size_type __bkt_count_hint = 0, + const _H1& __hf = _H1(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Hashtable(__l.begin(), __l.end(), __bkt_count_hint, + __hf, _H2(), _Hash(), __eql, + __key_extract(), __a) + { } + + _Hashtable& + operator=(const _Hashtable& __ht); + + _Hashtable& + operator=(_Hashtable&& __ht) + noexcept(__node_alloc_traits::_S_nothrow_move() + && is_nothrow_move_assignable<_H1>::value + && is_nothrow_move_assignable<_Equal>::value) + { + constexpr bool __move_storage = + __node_alloc_traits::_S_propagate_on_move_assign() + || __node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__ht), __bool_constant<__move_storage>()); + return *this; + } + + _Hashtable& + operator=(initializer_list __l) + { + __reuse_or_alloc_node_gen_t __roan(_M_begin(), *this); + _M_before_begin._M_nxt = nullptr; + clear(); + this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys()); + return *this; + } + + ~_Hashtable() noexcept; + + void + swap(_Hashtable&) + noexcept(__and_<__is_nothrow_swappable<_H1>, + __is_nothrow_swappable<_Equal>>::value); + + // Basic container operations + iterator + begin() noexcept + { return iterator(_M_begin()); } + + const_iterator + begin() const noexcept + { return const_iterator(_M_begin()); } + + iterator + end() noexcept + { return iterator(nullptr); } + + const_iterator + end() const noexcept + { return const_iterator(nullptr); } + + const_iterator + cbegin() const noexcept + { return const_iterator(_M_begin()); } + + const_iterator + cend() const noexcept + { return const_iterator(nullptr); } + + size_type + size() const noexcept + { return _M_element_count; } + + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return size() == 0; } + + allocator_type + get_allocator() const noexcept + { return allocator_type(this->_M_node_allocator()); } + + size_type + max_size() const noexcept + { return __node_alloc_traits::max_size(this->_M_node_allocator()); } + + // Observers + key_equal + key_eq() const + { return this->_M_eq(); } + + // hash_function, if present, comes from _Hash_code_base. + + // Bucket operations + size_type + bucket_count() const noexcept + { return _M_bucket_count; } + + size_type + max_bucket_count() const noexcept + { return max_size(); } + + size_type + bucket_size(size_type __bkt) const + { return std::distance(begin(__bkt), end(__bkt)); } + + size_type + bucket(const key_type& __k) const + { return _M_bucket_index(__k, this->_M_hash_code(__k)); } + + local_iterator + begin(size_type __bkt) + { + return local_iterator(*this, _M_bucket_begin(__bkt), + __bkt, _M_bucket_count); + } + + local_iterator + end(size_type __bkt) + { return local_iterator(*this, nullptr, __bkt, _M_bucket_count); } + + const_local_iterator + begin(size_type __bkt) const + { + return const_local_iterator(*this, _M_bucket_begin(__bkt), + __bkt, _M_bucket_count); + } + + const_local_iterator + end(size_type __bkt) const + { return const_local_iterator(*this, nullptr, __bkt, _M_bucket_count); } + + // DR 691. + const_local_iterator + cbegin(size_type __bkt) const + { + return const_local_iterator(*this, _M_bucket_begin(__bkt), + __bkt, _M_bucket_count); + } + + const_local_iterator + cend(size_type __bkt) const + { return const_local_iterator(*this, nullptr, __bkt, _M_bucket_count); } + + float + load_factor() const noexcept + { + return static_cast(size()) / static_cast(bucket_count()); + } + + // max_load_factor, if present, comes from _Rehash_base. + + // Generalization of max_load_factor. Extension, not found in + // TR1. Only useful if _RehashPolicy is something other than + // the default. + const _RehashPolicy& + __rehash_policy() const + { return _M_rehash_policy; } + + void + __rehash_policy(const _RehashPolicy& __pol) + { _M_rehash_policy = __pol; } + + // Lookup. + iterator + find(const key_type& __k); + + const_iterator + find(const key_type& __k) const; + + size_type + count(const key_type& __k) const; + + std::pair + equal_range(const key_type& __k); + + std::pair + equal_range(const key_type& __k) const; + + protected: + // Bucket index computation helpers. + size_type + _M_bucket_index(__node_type* __n) const noexcept + { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); } + + size_type + _M_bucket_index(const key_type& __k, __hash_code __c) const + { return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); } + + // Find and insert helper functions and types + // Find the node before the one matching the criteria. + __node_base* + _M_find_before_node(size_type, const key_type&, __hash_code) const; + + __node_type* + _M_find_node(size_type __bkt, const key_type& __key, + __hash_code __c) const + { + __node_base* __before_n = _M_find_before_node(__bkt, __key, __c); + if (__before_n) + return static_cast<__node_type*>(__before_n->_M_nxt); + return nullptr; + } + + // Insert a node at the beginning of a bucket. + void + _M_insert_bucket_begin(size_type, __node_type*); + + // Remove the bucket first node + void + _M_remove_bucket_begin(size_type __bkt, __node_type* __next_n, + size_type __next_bkt); + + // Get the node before __n in the bucket __bkt + __node_base* + _M_get_previous_node(size_type __bkt, __node_base* __n); + + // Insert node __n with key __k and hash code __code, in bucket __bkt + // if no rehash (assumes no element with same key already present). + // Takes ownership of __n if insertion succeeds, throws otherwise. + iterator + _M_insert_unique_node(const key_type& __k, size_type __bkt, + __hash_code __code, __node_type* __n, + size_type __n_elt = 1); + + // Insert node __n with key __k and hash code __code. + // Takes ownership of __n if insertion succeeds, throws otherwise. + iterator + _M_insert_multi_node(__node_type* __hint, const key_type& __k, + __hash_code __code, __node_type* __n); + + template + std::pair + _M_emplace(true_type, _Args&&... __args); + + template + iterator + _M_emplace(false_type __uk, _Args&&... __args) + { return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); } + + // Emplace with hint, useless when keys are unique. + template + iterator + _M_emplace(const_iterator, true_type __uk, _Args&&... __args) + { return _M_emplace(__uk, std::forward<_Args>(__args)...).first; } + + template + iterator + _M_emplace(const_iterator, false_type, _Args&&... __args); + + template + std::pair + _M_insert(_Arg&&, const _NodeGenerator&, true_type, size_type = 1); + + template + iterator + _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen, + false_type __uk) + { + return _M_insert(cend(), std::forward<_Arg>(__arg), __node_gen, + __uk); + } + + // Insert with hint, not used when keys are unique. + template + iterator + _M_insert(const_iterator, _Arg&& __arg, + const _NodeGenerator& __node_gen, true_type __uk) + { + return + _M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).first; + } + + // Insert with hint when keys are not unique. + template + iterator + _M_insert(const_iterator, _Arg&&, + const _NodeGenerator&, false_type); + + size_type + _M_erase(true_type, const key_type&); + + size_type + _M_erase(false_type, const key_type&); + + iterator + _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n); + + public: + // Emplace + template + __ireturn_type + emplace(_Args&&... __args) + { return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); } + + template + iterator + emplace_hint(const_iterator __hint, _Args&&... __args) + { + return _M_emplace(__hint, __unique_keys(), + std::forward<_Args>(__args)...); + } + + // Insert member functions via inheritance. + + // Erase + iterator + erase(const_iterator); + + // LWG 2059. + iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + size_type + erase(const key_type& __k) + { return _M_erase(__unique_keys(), __k); } + + iterator + erase(const_iterator, const_iterator); + + void + clear() noexcept; + + // Set number of buckets keeping it appropriate for container's number + // of elements. + void rehash(size_type __bkt_count); + + // DR 1189. + // reserve, if present, comes from _Rehash_base. + +#if __cplusplus > 201402L + /// Re-insert an extracted node into a container with unique keys. + insert_return_type + _M_reinsert_node(node_type&& __nh) + { + insert_return_type __ret; + if (__nh.empty()) + __ret.position = end(); + else + { + __glibcxx_assert(get_allocator() == __nh.get_allocator()); + + const key_type& __k = __nh._M_key(); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + if (__node_type* __n = _M_find_node(__bkt, __k, __code)) + { + __ret.node = std::move(__nh); + __ret.position = iterator(__n); + __ret.inserted = false; + } + else + { + __ret.position + = _M_insert_unique_node(__k, __bkt, __code, __nh._M_ptr); + __nh._M_ptr = nullptr; + __ret.inserted = true; + } + } + return __ret; + } + + /// Re-insert an extracted node into a container with equivalent keys. + iterator + _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh) + { + if (__nh.empty()) + return end(); + + __glibcxx_assert(get_allocator() == __nh.get_allocator()); + + const key_type& __k = __nh._M_key(); + auto __code = this->_M_hash_code(__k); + auto __ret + = _M_insert_multi_node(__hint._M_cur, __k, __code, __nh._M_ptr); + __nh._M_ptr = nullptr; + return __ret; + } + + private: + node_type + _M_extract_node(size_t __bkt, __node_base* __prev_n) + { + __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); + if (__prev_n == _M_buckets[__bkt]) + _M_remove_bucket_begin(__bkt, __n->_M_next(), + __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0); + else if (__n->_M_nxt) + { + size_type __next_bkt = _M_bucket_index(__n->_M_next()); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __prev_n; + } + + __prev_n->_M_nxt = __n->_M_nxt; + __n->_M_nxt = nullptr; + --_M_element_count; + return { __n, this->_M_node_allocator() }; + } + + public: + // Extract a node. + node_type + extract(const_iterator __pos) + { + size_t __bkt = _M_bucket_index(__pos._M_cur); + return _M_extract_node(__bkt, + _M_get_previous_node(__bkt, __pos._M_cur)); + } + + /// Extract a node. + node_type + extract(const _Key& __k) + { + node_type __nh; + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + if (__node_base* __prev_node = _M_find_before_node(__bkt, __k, __code)) + __nh = _M_extract_node(__bkt, __prev_node); + return __nh; + } + + /// Merge from a compatible container into one with unique keys. + template + void + _M_merge_unique(_Compatible_Hashtable& __src) noexcept + { + static_assert(is_same_v, "Node types are compatible"); + __glibcxx_assert(get_allocator() == __src.get_allocator()); + + auto __n_elt = __src.size(); + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + const key_type& __k = this->_M_extract()(*__pos); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + if (_M_find_node(__bkt, __k, __code) == nullptr) + { + auto __nh = __src.extract(__pos); + _M_insert_unique_node(__k, __bkt, __code, __nh._M_ptr, + __n_elt); + __nh._M_ptr = nullptr; + __n_elt = 1; + } + else if (__n_elt != 1) + --__n_elt; + } + } + + /// Merge from a compatible container into one with equivalent keys. + template + void + _M_merge_multi(_Compatible_Hashtable& __src) noexcept + { + static_assert(is_same_v, "Node types are compatible"); + __glibcxx_assert(get_allocator() == __src.get_allocator()); + + this->reserve(size() + __src.size()); + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + _M_reinsert_node_multi(cend(), __src.extract(__i++)); + } +#endif // C++17 + + private: + // Helper rehash method used when keys are unique. + void _M_rehash_aux(size_type __bkt_count, true_type); + + // Helper rehash method used when keys can be non-unique. + void _M_rehash_aux(size_type __bkt_count, false_type); + + // Unconditionally change size of bucket array to n, restore + // hash policy state to __state on exception. + void _M_rehash(size_type __bkt_count, const __rehash_state& __state); + }; + + + // Definitions of class template _Hashtable's out-of-line member functions. + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_bucket_begin(size_type __bkt) const + -> __node_type* + { + __node_base* __n = _M_buckets[__bkt]; + return __n ? static_cast<__node_type*>(__n->_M_nxt) : nullptr; + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(size_type __bkt_count_hint, + const _H1& __h1, const _H2& __h2, const _Hash& __h, + const _Equal& __eq, const _ExtractKey& __exk, + const allocator_type& __a) + : _Hashtable(__h1, __h2, __h, __eq, __exk, __a) + { + auto __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count_hint); + if (__bkt_count > _M_bucket_count) + { + _M_buckets = _M_allocate_buckets(__bkt_count); + _M_bucket_count = __bkt_count; + } + } + + template + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(_InputIterator __f, _InputIterator __l, + size_type __bkt_count_hint, + const _H1& __h1, const _H2& __h2, const _Hash& __h, + const _Equal& __eq, const _ExtractKey& __exk, + const allocator_type& __a) + : _Hashtable(__h1, __h2, __h, __eq, __exk, __a) + { + auto __nb_elems = __detail::__distance_fw(__f, __l); + auto __bkt_count = + _M_rehash_policy._M_next_bkt( + std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems), + __bkt_count_hint)); + + if (__bkt_count > _M_bucket_count) + { + _M_buckets = _M_allocate_buckets(__bkt_count); + _M_bucket_count = __bkt_count; + } + + for (; __f != __l; ++__f) + this->insert(*__f); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + operator=(const _Hashtable& __ht) + -> _Hashtable& + { + if (&__ht == this) + return *this; + + if (__node_alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_node_allocator(); + auto& __that_alloc = __ht._M_node_allocator(); + if (!__node_alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // Replacement allocator cannot free existing storage. + this->_M_deallocate_nodes(_M_begin()); + _M_before_begin._M_nxt = nullptr; + _M_deallocate_buckets(); + _M_buckets = nullptr; + std::__alloc_on_copy(__this_alloc, __that_alloc); + __hashtable_base::operator=(__ht); + _M_bucket_count = __ht._M_bucket_count; + _M_element_count = __ht._M_element_count; + _M_rehash_policy = __ht._M_rehash_policy; + __alloc_node_gen_t __alloc_node_gen(*this); + __try + { + _M_assign(__ht, __alloc_node_gen); + } + __catch(...) + { + // _M_assign took care of deallocating all memory. Now we + // must make sure this instance remains in a usable state. + _M_reset(); + __throw_exception_again; + } + return *this; + } + std::__alloc_on_copy(__this_alloc, __that_alloc); + } + + // Reuse allocated buckets and nodes. + _M_assign_elements(__ht); + return *this; + } + + template + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_assign_elements(_Ht&& __ht) + { + __bucket_type* __former_buckets = nullptr; + std::size_t __former_bucket_count = _M_bucket_count; + const __rehash_state& __former_state = _M_rehash_policy._M_state(); + + if (_M_bucket_count != __ht._M_bucket_count) + { + __former_buckets = _M_buckets; + _M_buckets = _M_allocate_buckets(__ht._M_bucket_count); + _M_bucket_count = __ht._M_bucket_count; + } + else + __builtin_memset(_M_buckets, 0, + _M_bucket_count * sizeof(__bucket_type)); + + __try + { + __hashtable_base::operator=(std::forward<_Ht>(__ht)); + _M_element_count = __ht._M_element_count; + _M_rehash_policy = __ht._M_rehash_policy; + __reuse_or_alloc_node_gen_t __roan(_M_begin(), *this); + _M_before_begin._M_nxt = nullptr; + _M_assign(std::forward<_Ht>(__ht), __roan); + if (__former_buckets) + _M_deallocate_buckets(__former_buckets, __former_bucket_count); + } + __catch(...) + { + if (__former_buckets) + { + // Restore previous buckets. + _M_deallocate_buckets(); + _M_rehash_policy._M_reset(__former_state); + _M_buckets = __former_buckets; + _M_bucket_count = __former_bucket_count; + } + __builtin_memset(_M_buckets, 0, + _M_bucket_count * sizeof(__bucket_type)); + __throw_exception_again; + } + } + + template + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_assign(_Ht&& __ht, const _NodeGenerator& __node_gen) + { + __bucket_type* __buckets = nullptr; + if (!_M_buckets) + _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count); + + __try + { + if (!__ht._M_before_begin._M_nxt) + return; + + // First deal with the special first node pointed to by + // _M_before_begin. + __node_type* __ht_n = __ht._M_begin(); + __node_type* __this_n + = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v())); + this->_M_copy_code(__this_n, __ht_n); + _M_before_begin._M_nxt = __this_n; + _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin; + + // Then deal with other nodes. + __node_base* __prev_n = __this_n; + for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next()) + { + __this_n = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v())); + __prev_n->_M_nxt = __this_n; + this->_M_copy_code(__this_n, __ht_n); + size_type __bkt = _M_bucket_index(__this_n); + if (!_M_buckets[__bkt]) + _M_buckets[__bkt] = __prev_n; + __prev_n = __this_n; + } + } + __catch(...) + { + clear(); + if (__buckets) + _M_deallocate_buckets(); + __throw_exception_again; + } + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_reset() noexcept + { + _M_rehash_policy._M_reset(); + _M_bucket_count = 1; + _M_single_bucket = nullptr; + _M_buckets = &_M_single_bucket; + _M_before_begin._M_nxt = nullptr; + _M_element_count = 0; + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_move_assign(_Hashtable&& __ht, true_type) + { + this->_M_deallocate_nodes(_M_begin()); + _M_deallocate_buckets(); + __hashtable_base::operator=(std::move(__ht)); + _M_rehash_policy = __ht._M_rehash_policy; + if (!__ht._M_uses_single_bucket()) + _M_buckets = __ht._M_buckets; + else + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } + _M_bucket_count = __ht._M_bucket_count; + _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt; + _M_element_count = __ht._M_element_count; + std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator()); + + // Fix buckets containing the _M_before_begin pointers that can't be + // moved. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + __ht._M_reset(); + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_move_assign(_Hashtable&& __ht, false_type) + { + if (__ht._M_node_allocator() == this->_M_node_allocator()) + _M_move_assign(std::move(__ht), true_type()); + else + { + // Can't move memory, move elements then. + _M_assign_elements(std::move(__ht)); + __ht.clear(); + } + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(const _Hashtable& __ht) + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + __hashtable_alloc( + __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())), + _M_buckets(nullptr), + _M_bucket_count(__ht._M_bucket_count), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + __alloc_node_gen_t __alloc_node_gen(*this); + _M_assign(__ht, __alloc_node_gen); + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(_Hashtable&& __ht) noexcept + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + __hashtable_alloc(std::move(__ht._M_base_alloc())), + _M_buckets(__ht._M_buckets), + _M_bucket_count(__ht._M_bucket_count), + _M_before_begin(__ht._M_before_begin._M_nxt), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + // Update, if necessary, buckets if __ht is using its single bucket. + if (__ht._M_uses_single_bucket()) + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } + + // Update, if necessary, bucket pointing to before begin that hasn't + // moved. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + + __ht._M_reset(); + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(const _Hashtable& __ht, const allocator_type& __a) + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + __hashtable_alloc(__node_alloc_type(__a)), + _M_buckets(), + _M_bucket_count(__ht._M_bucket_count), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + __alloc_node_gen_t __alloc_node_gen(*this); + _M_assign(__ht, __alloc_node_gen); + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(_Hashtable&& __ht, const allocator_type& __a) + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + __hashtable_alloc(__node_alloc_type(__a)), + _M_buckets(nullptr), + _M_bucket_count(__ht._M_bucket_count), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + if (__ht._M_node_allocator() == this->_M_node_allocator()) + { + if (__ht._M_uses_single_bucket()) + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } + else + _M_buckets = __ht._M_buckets; + + _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt; + // Update, if necessary, bucket pointing to before begin that hasn't + // moved. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + __ht._M_reset(); + } + else + { + __alloc_node_gen_t __alloc_gen(*this); + + using _Fwd_Ht = typename + conditional<__move_if_noexcept_cond::value, + const _Hashtable&, _Hashtable&&>::type; + _M_assign(std::forward<_Fwd_Ht>(__ht), __alloc_gen); + __ht.clear(); + } + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + ~_Hashtable() noexcept + { + clear(); + _M_deallocate_buckets(); + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + swap(_Hashtable& __x) + noexcept(__and_<__is_nothrow_swappable<_H1>, + __is_nothrow_swappable<_Equal>>::value) + { + // The only base class with member variables is hash_code_base. + // We define _Hash_code_base::_M_swap because different + // specializations have different members. + this->_M_swap(__x); + + std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator()); + std::swap(_M_rehash_policy, __x._M_rehash_policy); + + // Deal properly with potentially moved instances. + if (this->_M_uses_single_bucket()) + { + if (!__x._M_uses_single_bucket()) + { + _M_buckets = __x._M_buckets; + __x._M_buckets = &__x._M_single_bucket; + } + } + else if (__x._M_uses_single_bucket()) + { + __x._M_buckets = _M_buckets; + _M_buckets = &_M_single_bucket; + } + else + std::swap(_M_buckets, __x._M_buckets); + + std::swap(_M_bucket_count, __x._M_bucket_count); + std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt); + std::swap(_M_element_count, __x._M_element_count); + std::swap(_M_single_bucket, __x._M_single_bucket); + + // Fix buckets containing the _M_before_begin pointers that can't be + // swapped. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + + if (__x._M_begin()) + __x._M_buckets[__x._M_bucket_index(__x._M_begin())] + = &__x._M_before_begin; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + find(const key_type& __k) + -> iterator + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_find_node(__bkt, __k, __code); + return __p ? iterator(__p) : end(); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + find(const key_type& __k) const + -> const_iterator + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_find_node(__bkt, __k, __code); + return __p ? const_iterator(__p) : end(); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + count(const key_type& __k) const + -> size_type + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_bucket_begin(__bkt); + if (!__p) + return 0; + + std::size_t __result = 0; + for (;; __p = __p->_M_next()) + { + if (this->_M_equals(__k, __code, __p)) + ++__result; + else if (__result) + // All equivalent values are next to each other, if we + // found a non-equivalent value after an equivalent one it + // means that we won't find any new equivalent value. + break; + if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __bkt) + break; + } + return __result; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + equal_range(const key_type& __k) + -> pair + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_find_node(__bkt, __k, __code); + + if (__p) + { + __node_type* __p1 = __p->_M_next(); + while (__p1 && _M_bucket_index(__p1) == __bkt + && this->_M_equals(__k, __code, __p1)) + __p1 = __p1->_M_next(); + + return std::make_pair(iterator(__p), iterator(__p1)); + } + else + return std::make_pair(end(), end()); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + equal_range(const key_type& __k) const + -> pair + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_find_node(__bkt, __k, __code); + + if (__p) + { + __node_type* __p1 = __p->_M_next(); + while (__p1 && _M_bucket_index(__p1) == __bkt + && this->_M_equals(__k, __code, __p1)) + __p1 = __p1->_M_next(); + + return std::make_pair(const_iterator(__p), const_iterator(__p1)); + } + else + return std::make_pair(end(), end()); + } + + // Find the node whose key compares equal to k in the bucket bkt. + // Return nullptr if no node is found. + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_find_before_node(size_type __bkt, const key_type& __k, + __hash_code __code) const + -> __node_base* + { + __node_base* __prev_p = _M_buckets[__bkt]; + if (!__prev_p) + return nullptr; + + for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);; + __p = __p->_M_next()) + { + if (this->_M_equals(__k, __code, __p)) + return __prev_p; + + if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __bkt) + break; + __prev_p = __p; + } + return nullptr; + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert_bucket_begin(size_type __bkt, __node_type* __node) + { + if (_M_buckets[__bkt]) + { + // Bucket is not empty, we just need to insert the new node + // after the bucket before begin. + __node->_M_nxt = _M_buckets[__bkt]->_M_nxt; + _M_buckets[__bkt]->_M_nxt = __node; + } + else + { + // The bucket is empty, the new node is inserted at the + // beginning of the singly-linked list and the bucket will + // contain _M_before_begin pointer. + __node->_M_nxt = _M_before_begin._M_nxt; + _M_before_begin._M_nxt = __node; + if (__node->_M_nxt) + // We must update former begin bucket that is pointing to + // _M_before_begin. + _M_buckets[_M_bucket_index(__node->_M_next())] = __node; + _M_buckets[__bkt] = &_M_before_begin; + } + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_remove_bucket_begin(size_type __bkt, __node_type* __next, + size_type __next_bkt) + { + if (!__next || __next_bkt != __bkt) + { + // Bucket is now empty + // First update next bucket if any + if (__next) + _M_buckets[__next_bkt] = _M_buckets[__bkt]; + + // Second update before begin node if necessary + if (&_M_before_begin == _M_buckets[__bkt]) + _M_before_begin._M_nxt = __next; + _M_buckets[__bkt] = nullptr; + } + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_get_previous_node(size_type __bkt, __node_base* __n) + -> __node_base* + { + __node_base* __prev_n = _M_buckets[__bkt]; + while (__prev_n->_M_nxt != __n) + __prev_n = __prev_n->_M_nxt; + return __prev_n; + } + + template + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_emplace(true_type, _Args&&... __args) + -> pair + { + // First build the node to get access to the hash code + _Scoped_node __node { this, std::forward<_Args>(__args)... }; + const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + if (__node_type* __p = _M_find_node(__bkt, __k, __code)) + // There is already an equivalent node, no insertion + return std::make_pair(iterator(__p), false); + + // Insert the node + auto __pos = _M_insert_unique_node(__k, __bkt, __code, __node._M_node); + __node._M_node = nullptr; + return { __pos, true }; + } + + template + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_emplace(const_iterator __hint, false_type, _Args&&... __args) + -> iterator + { + // First build the node to get its hash code. + _Scoped_node __node { this, std::forward<_Args>(__args)... }; + const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); + + __hash_code __code = this->_M_hash_code(__k); + auto __pos + = _M_insert_multi_node(__hint._M_cur, __k, __code, __node._M_node); + __node._M_node = nullptr; + return __pos; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert_unique_node(const key_type& __k, size_type __bkt, + __hash_code __code, __node_type* __node, + size_type __n_elt) + -> iterator + { + const __rehash_state& __saved_state = _M_rehash_policy._M_state(); + std::pair __do_rehash + = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, + __n_elt); + + if (__do_rehash.first) + { + _M_rehash(__do_rehash.second, __saved_state); + __bkt = _M_bucket_index(__k, __code); + } + + this->_M_store_code(__node, __code); + + // Always insert at the beginning of the bucket. + _M_insert_bucket_begin(__bkt, __node); + ++_M_element_count; + return iterator(__node); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert_multi_node(__node_type* __hint, const key_type& __k, + __hash_code __code, __node_type* __node) + -> iterator + { + const __rehash_state& __saved_state = _M_rehash_policy._M_state(); + std::pair __do_rehash + = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1); + + if (__do_rehash.first) + _M_rehash(__do_rehash.second, __saved_state); + + this->_M_store_code(__node, __code); + size_type __bkt = _M_bucket_index(__k, __code); + + // Find the node before an equivalent one or use hint if it exists and + // if it is equivalent. + __node_base* __prev + = __builtin_expect(__hint != nullptr, false) + && this->_M_equals(__k, __code, __hint) + ? __hint + : _M_find_before_node(__bkt, __k, __code); + if (__prev) + { + // Insert after the node before the equivalent one. + __node->_M_nxt = __prev->_M_nxt; + __prev->_M_nxt = __node; + if (__builtin_expect(__prev == __hint, false)) + // hint might be the last bucket node, in this case we need to + // update next bucket. + if (__node->_M_nxt + && !this->_M_equals(__k, __code, __node->_M_next())) + { + size_type __next_bkt = _M_bucket_index(__node->_M_next()); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __node; + } + } + else + // The inserted node has no equivalent in the hashtable. We must + // insert the new node at the beginning of the bucket to preserve + // equivalent elements' relative positions. + _M_insert_bucket_begin(__bkt, __node); + ++_M_element_count; + return iterator(__node); + } + + // Insert v if no element with its key is already present. + template + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert(_Arg&& __v, const _NodeGenerator& __node_gen, true_type, + size_type __n_elt) + -> pair + { + const key_type& __k = this->_M_extract()(__v); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + + if (__node_type* __node = _M_find_node(__bkt, __k, __code)) + return { iterator(__node), false }; + + _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)), this }; + auto __pos + = _M_insert_unique_node(__k, __bkt, __code, __node._M_node, __n_elt); + __node._M_node = nullptr; + return { __pos, true }; + } + + // Insert v unconditionally. + template + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert(const_iterator __hint, _Arg&& __v, + const _NodeGenerator& __node_gen, false_type) + -> iterator + { + // First compute the hash code so that we don't do anything if it + // throws. + __hash_code __code = this->_M_hash_code(this->_M_extract()(__v)); + + // Second allocate new node so that we don't rehash if it throws. + _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)), this }; + const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); + auto __pos + = _M_insert_multi_node(__hint._M_cur, __k, __code, __node._M_node); + __node._M_node = nullptr; + return __pos; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + erase(const_iterator __it) + -> iterator + { + __node_type* __n = __it._M_cur; + std::size_t __bkt = _M_bucket_index(__n); + + // Look for previous node to unlink it from the erased one, this + // is why we need buckets to contain the before begin to make + // this search fast. + __node_base* __prev_n = _M_get_previous_node(__bkt, __n); + return _M_erase(__bkt, __prev_n, __n); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n) + -> iterator + { + if (__prev_n == _M_buckets[__bkt]) + _M_remove_bucket_begin(__bkt, __n->_M_next(), + __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0); + else if (__n->_M_nxt) + { + size_type __next_bkt = _M_bucket_index(__n->_M_next()); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __prev_n; + } + + __prev_n->_M_nxt = __n->_M_nxt; + iterator __result(__n->_M_next()); + this->_M_deallocate_node(__n); + --_M_element_count; + + return __result; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_erase(true_type, const key_type& __k) + -> size_type + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + + // Look for the node before the first matching node. + __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code); + if (!__prev_n) + return 0; + + // We found a matching node, erase it. + __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); + _M_erase(__bkt, __prev_n, __n); + return 1; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_erase(false_type, const key_type& __k) + -> size_type + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + + // Look for the node before the first matching node. + __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code); + if (!__prev_n) + return 0; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 526. Is it undefined if a function in the standard changes + // in parameters? + // We use one loop to find all matching nodes and another to deallocate + // them so that the key stays valid during the first loop. It might be + // invalidated indirectly when destroying nodes. + __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); + __node_type* __n_last = __n; + std::size_t __n_last_bkt = __bkt; + do + { + __n_last = __n_last->_M_next(); + if (!__n_last) + break; + __n_last_bkt = _M_bucket_index(__n_last); + } + while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last)); + + // Deallocate nodes. + size_type __result = 0; + do + { + __node_type* __p = __n->_M_next(); + this->_M_deallocate_node(__n); + __n = __p; + ++__result; + --_M_element_count; + } + while (__n != __n_last); + + if (__prev_n == _M_buckets[__bkt]) + _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt); + else if (__n_last && __n_last_bkt != __bkt) + _M_buckets[__n_last_bkt] = __prev_n; + __prev_n->_M_nxt = __n_last; + return __result; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + erase(const_iterator __first, const_iterator __last) + -> iterator + { + __node_type* __n = __first._M_cur; + __node_type* __last_n = __last._M_cur; + if (__n == __last_n) + return iterator(__n); + + std::size_t __bkt = _M_bucket_index(__n); + + __node_base* __prev_n = _M_get_previous_node(__bkt, __n); + bool __is_bucket_begin = __n == _M_bucket_begin(__bkt); + std::size_t __n_bkt = __bkt; + for (;;) + { + do + { + __node_type* __tmp = __n; + __n = __n->_M_next(); + this->_M_deallocate_node(__tmp); + --_M_element_count; + if (!__n) + break; + __n_bkt = _M_bucket_index(__n); + } + while (__n != __last_n && __n_bkt == __bkt); + if (__is_bucket_begin) + _M_remove_bucket_begin(__bkt, __n, __n_bkt); + if (__n == __last_n) + break; + __is_bucket_begin = true; + __bkt = __n_bkt; + } + + if (__n && (__n_bkt != __bkt || __is_bucket_begin)) + _M_buckets[__n_bkt] = __prev_n; + __prev_n->_M_nxt = __n; + return iterator(__n); + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + clear() noexcept + { + this->_M_deallocate_nodes(_M_begin()); + __builtin_memset(_M_buckets, 0, _M_bucket_count * sizeof(__bucket_type)); + _M_element_count = 0; + _M_before_begin._M_nxt = nullptr; + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + rehash(size_type __bkt_count) + { + const __rehash_state& __saved_state = _M_rehash_policy._M_state(); + __bkt_count + = std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1), + __bkt_count); + __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count); + + if (__bkt_count != _M_bucket_count) + _M_rehash(__bkt_count, __saved_state); + else + // No rehash, restore previous state to keep it consistent with + // container state. + _M_rehash_policy._M_reset(__saved_state); + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_rehash(size_type __bkt_count, const __rehash_state& __state) + { + __try + { + _M_rehash_aux(__bkt_count, __unique_keys()); + } + __catch(...) + { + // A failure here means that buckets allocation failed. We only + // have to restore hash policy previous state. + _M_rehash_policy._M_reset(__state); + __throw_exception_again; + } + } + + // Rehash when there is no equivalent elements. + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_rehash_aux(size_type __bkt_count, true_type) + { + __bucket_type* __new_buckets = _M_allocate_buckets(__bkt_count); + __node_type* __p = _M_begin(); + _M_before_begin._M_nxt = nullptr; + std::size_t __bbegin_bkt = 0; + while (__p) + { + __node_type* __next = __p->_M_next(); + std::size_t __bkt + = __hash_code_base::_M_bucket_index(__p, __bkt_count); + if (!__new_buckets[__bkt]) + { + __p->_M_nxt = _M_before_begin._M_nxt; + _M_before_begin._M_nxt = __p; + __new_buckets[__bkt] = &_M_before_begin; + if (__p->_M_nxt) + __new_buckets[__bbegin_bkt] = __p; + __bbegin_bkt = __bkt; + } + else + { + __p->_M_nxt = __new_buckets[__bkt]->_M_nxt; + __new_buckets[__bkt]->_M_nxt = __p; + } + __p = __next; + } + + _M_deallocate_buckets(); + _M_bucket_count = __bkt_count; + _M_buckets = __new_buckets; + } + + // Rehash when there can be equivalent elements, preserve their relative + // order. + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_rehash_aux(size_type __bkt_count, false_type) + { + __bucket_type* __new_buckets = _M_allocate_buckets(__bkt_count); + + __node_type* __p = _M_begin(); + _M_before_begin._M_nxt = nullptr; + std::size_t __bbegin_bkt = 0; + std::size_t __prev_bkt = 0; + __node_type* __prev_p = nullptr; + bool __check_bucket = false; + + while (__p) + { + __node_type* __next = __p->_M_next(); + std::size_t __bkt + = __hash_code_base::_M_bucket_index(__p, __bkt_count); + + if (__prev_p && __prev_bkt == __bkt) + { + // Previous insert was already in this bucket, we insert after + // the previously inserted one to preserve equivalent elements + // relative order. + __p->_M_nxt = __prev_p->_M_nxt; + __prev_p->_M_nxt = __p; + + // Inserting after a node in a bucket require to check that we + // haven't change the bucket last node, in this case next + // bucket containing its before begin node must be updated. We + // schedule a check as soon as we move out of the sequence of + // equivalent nodes to limit the number of checks. + __check_bucket = true; + } + else + { + if (__check_bucket) + { + // Check if we shall update the next bucket because of + // insertions into __prev_bkt bucket. + if (__prev_p->_M_nxt) + { + std::size_t __next_bkt + = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), + __bkt_count); + if (__next_bkt != __prev_bkt) + __new_buckets[__next_bkt] = __prev_p; + } + __check_bucket = false; + } + + if (!__new_buckets[__bkt]) + { + __p->_M_nxt = _M_before_begin._M_nxt; + _M_before_begin._M_nxt = __p; + __new_buckets[__bkt] = &_M_before_begin; + if (__p->_M_nxt) + __new_buckets[__bbegin_bkt] = __p; + __bbegin_bkt = __bkt; + } + else + { + __p->_M_nxt = __new_buckets[__bkt]->_M_nxt; + __new_buckets[__bkt]->_M_nxt = __p; + } + } + __prev_p = __p; + __prev_bkt = __bkt; + __p = __next; + } + + if (__check_bucket && __prev_p->_M_nxt) + { + std::size_t __next_bkt + = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), + __bkt_count); + if (__next_bkt != __prev_bkt) + __new_buckets[__next_bkt] = __prev_p; + } + + _M_deallocate_buckets(); + _M_bucket_count = __bkt_count; + _M_buckets = __new_buckets; + } + +#if __cplusplus > 201402L + template class _Hash_merge_helper { }; +#endif // C++17 + +#if __cpp_deduction_guides >= 201606 + // Used to constrain deduction guides + template + using _RequireNotAllocatorOrIntegral + = __enable_if_t, __is_allocator<_Hash>>::value>; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _HASHTABLE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h b/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h new file mode 100644 index 000000000..ef1201349 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h @@ -0,0 +1,2107 @@ +// Internal policy header for unordered_set and unordered_map -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/hashtable_policy.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + * @headername{unordered_map,unordered_set} + */ + +#ifndef _HASHTABLE_POLICY_H +#define _HASHTABLE_POLICY_H 1 + +#include // for std::tuple, std::forward_as_tuple +#include // for std::numeric_limits +#include // for std::min, std::is_permutation. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + class _Hashtable; + +namespace __detail +{ + /** + * @defgroup hashtable-detail Base and Implementation Classes + * @ingroup unordered_associative_containers + * @{ + */ + template + struct _Hashtable_base; + + // Helper function: return distance(first, last) for forward + // iterators, or 0/1 for input iterators. + template + inline typename std::iterator_traits<_Iterator>::difference_type + __distance_fw(_Iterator __first, _Iterator __last, + std::input_iterator_tag) + { return __first != __last ? 1 : 0; } + + template + inline typename std::iterator_traits<_Iterator>::difference_type + __distance_fw(_Iterator __first, _Iterator __last, + std::forward_iterator_tag) + { return std::distance(__first, __last); } + + template + inline typename std::iterator_traits<_Iterator>::difference_type + __distance_fw(_Iterator __first, _Iterator __last) + { return __distance_fw(__first, __last, + std::__iterator_category(__first)); } + + struct _Identity + { + template + _Tp&& + operator()(_Tp&& __x) const + { return std::forward<_Tp>(__x); } + }; + + struct _Select1st + { + template + auto + operator()(_Tp&& __x) const + -> decltype(std::get<0>(std::forward<_Tp>(__x))) + { return std::get<0>(std::forward<_Tp>(__x)); } + }; + + template + struct _Hashtable_alloc; + + // Functor recycling a pool of nodes and using allocation once the pool is + // empty. + template + struct _ReuseOrAllocNode + { + private: + using __node_alloc_type = _NodeAlloc; + using __hashtable_alloc = _Hashtable_alloc<__node_alloc_type>; + using __node_alloc_traits = + typename __hashtable_alloc::__node_alloc_traits; + using __node_type = typename __hashtable_alloc::__node_type; + + public: + _ReuseOrAllocNode(__node_type* __nodes, __hashtable_alloc& __h) + : _M_nodes(__nodes), _M_h(__h) { } + _ReuseOrAllocNode(const _ReuseOrAllocNode&) = delete; + + ~_ReuseOrAllocNode() + { _M_h._M_deallocate_nodes(_M_nodes); } + + template + __node_type* + operator()(_Arg&& __arg) const + { + if (_M_nodes) + { + __node_type* __node = _M_nodes; + _M_nodes = _M_nodes->_M_next(); + __node->_M_nxt = nullptr; + auto& __a = _M_h._M_node_allocator(); + __node_alloc_traits::destroy(__a, __node->_M_valptr()); + __try + { + __node_alloc_traits::construct(__a, __node->_M_valptr(), + std::forward<_Arg>(__arg)); + } + __catch(...) + { + _M_h._M_deallocate_node_ptr(__node); + __throw_exception_again; + } + return __node; + } + return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); + } + + private: + mutable __node_type* _M_nodes; + __hashtable_alloc& _M_h; + }; + + // Functor similar to the previous one but without any pool of nodes to + // recycle. + template + struct _AllocNode + { + private: + using __hashtable_alloc = _Hashtable_alloc<_NodeAlloc>; + using __node_type = typename __hashtable_alloc::__node_type; + + public: + _AllocNode(__hashtable_alloc& __h) + : _M_h(__h) { } + + template + __node_type* + operator()(_Arg&& __arg) const + { return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); } + + private: + __hashtable_alloc& _M_h; + }; + + // Auxiliary types used for all instantiations of _Hashtable nodes + // and iterators. + + /** + * struct _Hashtable_traits + * + * Important traits for hash tables. + * + * @tparam _Cache_hash_code Boolean value. True if the value of + * the hash function is stored along with the value. This is a + * time-space tradeoff. Storing it may improve lookup speed by + * reducing the number of times we need to call the _Hash or _Equal + * functors. + * + * @tparam _Constant_iterators Boolean value. True if iterator and + * const_iterator are both constant iterator types. This is true + * for unordered_set and unordered_multiset, false for + * unordered_map and unordered_multimap. + * + * @tparam _Unique_keys Boolean value. True if the return value + * of _Hashtable::count(k) is always at most one, false if it may + * be an arbitrary number. This is true for unordered_set and + * unordered_map, false for unordered_multiset and + * unordered_multimap. + */ + template + struct _Hashtable_traits + { + using __hash_cached = __bool_constant<_Cache_hash_code>; + using __constant_iterators = __bool_constant<_Constant_iterators>; + using __unique_keys = __bool_constant<_Unique_keys>; + }; + + /** + * struct _Hash_node_base + * + * Nodes, used to wrap elements stored in the hash table. A policy + * template parameter of class template _Hashtable controls whether + * nodes also store a hash code. In some cases (e.g. strings) this + * may be a performance win. + */ + struct _Hash_node_base + { + _Hash_node_base* _M_nxt; + + _Hash_node_base() noexcept : _M_nxt() { } + + _Hash_node_base(_Hash_node_base* __next) noexcept : _M_nxt(__next) { } + }; + + /** + * struct _Hash_node_value_base + * + * Node type with the value to store. + */ + template + struct _Hash_node_value_base : _Hash_node_base + { + typedef _Value value_type; + + __gnu_cxx::__aligned_buffer<_Value> _M_storage; + + _Value* + _M_valptr() noexcept + { return _M_storage._M_ptr(); } + + const _Value* + _M_valptr() const noexcept + { return _M_storage._M_ptr(); } + + _Value& + _M_v() noexcept + { return *_M_valptr(); } + + const _Value& + _M_v() const noexcept + { return *_M_valptr(); } + }; + + /** + * Primary template struct _Hash_node. + */ + template + struct _Hash_node; + + /** + * Specialization for nodes with caches, struct _Hash_node. + * + * Base class is __detail::_Hash_node_value_base. + */ + template + struct _Hash_node<_Value, true> : _Hash_node_value_base<_Value> + { + std::size_t _M_hash_code; + + _Hash_node* + _M_next() const noexcept + { return static_cast<_Hash_node*>(this->_M_nxt); } + }; + + /** + * Specialization for nodes without caches, struct _Hash_node. + * + * Base class is __detail::_Hash_node_value_base. + */ + template + struct _Hash_node<_Value, false> : _Hash_node_value_base<_Value> + { + _Hash_node* + _M_next() const noexcept + { return static_cast<_Hash_node*>(this->_M_nxt); } + }; + + /// Base class for node iterators. + template + struct _Node_iterator_base + { + using __node_type = _Hash_node<_Value, _Cache_hash_code>; + + __node_type* _M_cur; + + _Node_iterator_base(__node_type* __p) noexcept + : _M_cur(__p) { } + + void + _M_incr() noexcept + { _M_cur = _M_cur->_M_next(); } + }; + + template + inline bool + operator==(const _Node_iterator_base<_Value, _Cache_hash_code>& __x, + const _Node_iterator_base<_Value, _Cache_hash_code >& __y) + noexcept + { return __x._M_cur == __y._M_cur; } + + template + inline bool + operator!=(const _Node_iterator_base<_Value, _Cache_hash_code>& __x, + const _Node_iterator_base<_Value, _Cache_hash_code>& __y) + noexcept + { return __x._M_cur != __y._M_cur; } + + /// Node iterators, used to iterate through all the hashtable. + template + struct _Node_iterator + : public _Node_iterator_base<_Value, __cache> + { + private: + using __base_type = _Node_iterator_base<_Value, __cache>; + using __node_type = typename __base_type::__node_type; + + public: + typedef _Value value_type; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + using pointer = typename std::conditional<__constant_iterators, + const _Value*, _Value*>::type; + + using reference = typename std::conditional<__constant_iterators, + const _Value&, _Value&>::type; + + _Node_iterator() noexcept + : __base_type(0) { } + + explicit + _Node_iterator(__node_type* __p) noexcept + : __base_type(__p) { } + + reference + operator*() const noexcept + { return this->_M_cur->_M_v(); } + + pointer + operator->() const noexcept + { return this->_M_cur->_M_valptr(); } + + _Node_iterator& + operator++() noexcept + { + this->_M_incr(); + return *this; + } + + _Node_iterator + operator++(int) noexcept + { + _Node_iterator __tmp(*this); + this->_M_incr(); + return __tmp; + } + }; + + /// Node const_iterators, used to iterate through all the hashtable. + template + struct _Node_const_iterator + : public _Node_iterator_base<_Value, __cache> + { + private: + using __base_type = _Node_iterator_base<_Value, __cache>; + using __node_type = typename __base_type::__node_type; + + public: + typedef _Value value_type; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + typedef const _Value* pointer; + typedef const _Value& reference; + + _Node_const_iterator() noexcept + : __base_type(0) { } + + explicit + _Node_const_iterator(__node_type* __p) noexcept + : __base_type(__p) { } + + _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators, + __cache>& __x) noexcept + : __base_type(__x._M_cur) { } + + reference + operator*() const noexcept + { return this->_M_cur->_M_v(); } + + pointer + operator->() const noexcept + { return this->_M_cur->_M_valptr(); } + + _Node_const_iterator& + operator++() noexcept + { + this->_M_incr(); + return *this; + } + + _Node_const_iterator + operator++(int) noexcept + { + _Node_const_iterator __tmp(*this); + this->_M_incr(); + return __tmp; + } + }; + + // Many of class template _Hashtable's template parameters are policy + // classes. These are defaults for the policies. + + /// Default range hashing function: use division to fold a large number + /// into the range [0, N). + struct _Mod_range_hashing + { + typedef std::size_t first_argument_type; + typedef std::size_t second_argument_type; + typedef std::size_t result_type; + + result_type + operator()(first_argument_type __num, + second_argument_type __den) const noexcept + { return __num % __den; } + }; + + /// Default ranged hash function H. In principle it should be a + /// function object composed from objects of type H1 and H2 such that + /// h(k, N) = h2(h1(k), N), but that would mean making extra copies of + /// h1 and h2. So instead we'll just use a tag to tell class template + /// hashtable to do that composition. + struct _Default_ranged_hash { }; + + /// Default value for rehash policy. Bucket size is (usually) the + /// smallest prime that keeps the load factor small enough. + struct _Prime_rehash_policy + { + using __has_load_factor = true_type; + + _Prime_rehash_policy(float __z = 1.0) noexcept + : _M_max_load_factor(__z), _M_next_resize(0) { } + + float + max_load_factor() const noexcept + { return _M_max_load_factor; } + + // Return a bucket size no smaller than n. + std::size_t + _M_next_bkt(std::size_t __n) const; + + // Return a bucket count appropriate for n elements + std::size_t + _M_bkt_for_elements(std::size_t __n) const + { return __builtin_ceill(__n / (long double)_M_max_load_factor); } + + // __n_bkt is current bucket count, __n_elt is current element count, + // and __n_ins is number of elements to be inserted. Do we need to + // increase bucket count? If so, return make_pair(true, n), where n + // is the new bucket count. If not, return make_pair(false, 0). + std::pair + _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, + std::size_t __n_ins) const; + + typedef std::size_t _State; + + _State + _M_state() const + { return _M_next_resize; } + + void + _M_reset() noexcept + { _M_next_resize = 0; } + + void + _M_reset(_State __state) + { _M_next_resize = __state; } + + static const std::size_t _S_growth_factor = 2; + + float _M_max_load_factor; + mutable std::size_t _M_next_resize; + }; + + /// Range hashing function assuming that second arg is a power of 2. + struct _Mask_range_hashing + { + typedef std::size_t first_argument_type; + typedef std::size_t second_argument_type; + typedef std::size_t result_type; + + result_type + operator()(first_argument_type __num, + second_argument_type __den) const noexcept + { return __num & (__den - 1); } + }; + + /// Compute closest power of 2 not less than __n + inline std::size_t + __clp2(std::size_t __n) noexcept + { + // Equivalent to return __n ? std::bit_ceil(__n) : 0; + if (__n < 2) + return __n; + const unsigned __lz = sizeof(size_t) > sizeof(long) + ? __builtin_clzll(__n - 1ull) + : __builtin_clzl(__n - 1ul); + // Doing two shifts avoids undefined behaviour when __lz == 0. + return (size_t(1) << (numeric_limits::digits - __lz - 1)) << 1; + } + + /// Rehash policy providing power of 2 bucket numbers. Avoids modulo + /// operations. + struct _Power2_rehash_policy + { + using __has_load_factor = true_type; + + _Power2_rehash_policy(float __z = 1.0) noexcept + : _M_max_load_factor(__z), _M_next_resize(0) { } + + float + max_load_factor() const noexcept + { return _M_max_load_factor; } + + // Return a bucket size no smaller than n (as long as n is not above the + // highest power of 2). + std::size_t + _M_next_bkt(std::size_t __n) noexcept + { + if (__n == 0) + // Special case on container 1st initialization with 0 bucket count + // hint. We keep _M_next_resize to 0 to make sure that next time we + // want to add an element allocation will take place. + return 1; + + const auto __max_width = std::min(sizeof(size_t), 8); + const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1); + std::size_t __res = __clp2(__n); + + if (__res == 0) + __res = __max_bkt; + else if (__res == 1) + // If __res is 1 we force it to 2 to make sure there will be an + // allocation so that nothing need to be stored in the initial + // single bucket + __res = 2; + + if (__res == __max_bkt) + // Set next resize to the max value so that we never try to rehash again + // as we already reach the biggest possible bucket number. + // Note that it might result in max_load_factor not being respected. + _M_next_resize = numeric_limits::max(); + else + _M_next_resize + = __builtin_floorl(__res * (long double)_M_max_load_factor); + + return __res; + } + + // Return a bucket count appropriate for n elements + std::size_t + _M_bkt_for_elements(std::size_t __n) const noexcept + { return __builtin_ceill(__n / (long double)_M_max_load_factor); } + + // __n_bkt is current bucket count, __n_elt is current element count, + // and __n_ins is number of elements to be inserted. Do we need to + // increase bucket count? If so, return make_pair(true, n), where n + // is the new bucket count. If not, return make_pair(false, 0). + std::pair + _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, + std::size_t __n_ins) noexcept + { + if (__n_elt + __n_ins > _M_next_resize) + { + // If _M_next_resize is 0 it means that we have nothing allocated so + // far and that we start inserting elements. In this case we start + // with an initial bucket size of 11. + long double __min_bkts + = std::max(__n_elt + __n_ins, _M_next_resize ? 0 : 11) + / (long double)_M_max_load_factor; + if (__min_bkts >= __n_bkt) + return { true, + _M_next_bkt(std::max(__builtin_floorl(__min_bkts) + 1, + __n_bkt * _S_growth_factor)) }; + + _M_next_resize + = __builtin_floorl(__n_bkt * (long double)_M_max_load_factor); + return { false, 0 }; + } + else + return { false, 0 }; + } + + typedef std::size_t _State; + + _State + _M_state() const noexcept + { return _M_next_resize; } + + void + _M_reset() noexcept + { _M_next_resize = 0; } + + void + _M_reset(_State __state) noexcept + { _M_next_resize = __state; } + + static const std::size_t _S_growth_factor = 2; + + float _M_max_load_factor; + std::size_t _M_next_resize; + }; + + // Base classes for std::_Hashtable. We define these base classes + // because in some cases we want to do different things depending on + // the value of a policy class. In some cases the policy class + // affects which member functions and nested typedefs are defined; + // we handle that by specializing base class templates. Several of + // the base class templates need to access other members of class + // template _Hashtable, so we use a variant of the "Curiously + // Recurring Template Pattern" (CRTP) technique. + + /** + * Primary class template _Map_base. + * + * If the hashtable has a value type of the form pair and a + * key extraction policy (_ExtractKey) that returns the first part + * of the pair, the hashtable gets a mapped_type typedef. If it + * satisfies those criteria and also has unique keys, then it also + * gets an operator[]. + */ + template + struct _Map_base { }; + + /// Partial specialization, __unique_keys set to false. + template + struct _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, false> + { + using mapped_type = typename std::tuple_element<1, _Pair>::type; + }; + + /// Partial specialization, __unique_keys set to true. + template + struct _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true> + { + private: + using __hashtable_base = __detail::_Hashtable_base<_Key, _Pair, + _Select1st, + _Equal, _H1, _H2, _Hash, + _Traits>; + + using __hashtable = _Hashtable<_Key, _Pair, _Alloc, + _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>; + + using __hash_code = typename __hashtable_base::__hash_code; + using __node_type = typename __hashtable_base::__node_type; + + public: + using key_type = typename __hashtable_base::key_type; + using iterator = typename __hashtable_base::iterator; + using mapped_type = typename std::tuple_element<1, _Pair>::type; + + mapped_type& + operator[](const key_type& __k); + + mapped_type& + operator[](key_type&& __k); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 761. unordered_map needs an at() member function. + mapped_type& + at(const key_type& __k); + + const mapped_type& + at(const key_type& __k) const; + }; + + template + auto + _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + operator[](const key_type& __k) + -> mapped_type& + { + __hashtable* __h = static_cast<__hashtable*>(this); + __hash_code __code = __h->_M_hash_code(__k); + std::size_t __bkt = __h->_M_bucket_index(__k, __code); + if (__node_type* __node = __h->_M_find_node(__bkt, __k, __code)) + return __node->_M_v().second; + + typename __hashtable::_Scoped_node __node { + __h, + std::piecewise_construct, + std::tuple(__k), + std::tuple<>() + }; + auto __pos + = __h->_M_insert_unique_node(__k, __bkt, __code, __node._M_node); + __node._M_node = nullptr; + return __pos->second; + } + + template + auto + _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + operator[](key_type&& __k) + -> mapped_type& + { + __hashtable* __h = static_cast<__hashtable*>(this); + __hash_code __code = __h->_M_hash_code(__k); + std::size_t __bkt = __h->_M_bucket_index(__k, __code); + if (__node_type* __node = __h->_M_find_node(__bkt, __k, __code)) + return __node->_M_v().second; + + typename __hashtable::_Scoped_node __node { + __h, + std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::tuple<>() + }; + auto __pos + = __h->_M_insert_unique_node(__k, __bkt, __code, __node._M_node); + __node._M_node = nullptr; + return __pos->second; + } + + template + auto + _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + at(const key_type& __k) + -> mapped_type& + { + __hashtable* __h = static_cast<__hashtable*>(this); + __hash_code __code = __h->_M_hash_code(__k); + std::size_t __bkt = __h->_M_bucket_index(__k, __code); + __node_type* __p = __h->_M_find_node(__bkt, __k, __code); + + if (!__p) + __throw_out_of_range(__N("_Map_base::at")); + return __p->_M_v().second; + } + + template + auto + _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + at(const key_type& __k) const + -> const mapped_type& + { + const __hashtable* __h = static_cast(this); + __hash_code __code = __h->_M_hash_code(__k); + std::size_t __bkt = __h->_M_bucket_index(__k, __code); + __node_type* __p = __h->_M_find_node(__bkt, __k, __code); + + if (!__p) + __throw_out_of_range(__N("_Map_base::at")); + return __p->_M_v().second; + } + + /** + * Primary class template _Insert_base. + * + * Defines @c insert member functions appropriate to all _Hashtables. + */ + template + struct _Insert_base + { + protected: + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _Traits>; + + using value_type = typename __hashtable_base::value_type; + using iterator = typename __hashtable_base::iterator; + using const_iterator = typename __hashtable_base::const_iterator; + using size_type = typename __hashtable_base::size_type; + + using __unique_keys = typename __hashtable_base::__unique_keys; + using __ireturn_type = typename __hashtable_base::__ireturn_type; + using __node_type = _Hash_node<_Value, _Traits::__hash_cached::value>; + using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>; + using __node_gen_type = _AllocNode<__node_alloc_type>; + + __hashtable& + _M_conjure_hashtable() + { return *(static_cast<__hashtable*>(this)); } + + template + void + _M_insert_range(_InputIterator __first, _InputIterator __last, + const _NodeGetter&, true_type); + + template + void + _M_insert_range(_InputIterator __first, _InputIterator __last, + const _NodeGetter&, false_type); + + public: + __ireturn_type + insert(const value_type& __v) + { + __hashtable& __h = _M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return __h._M_insert(__v, __node_gen, __unique_keys()); + } + + iterator + insert(const_iterator __hint, const value_type& __v) + { + __hashtable& __h = _M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return __h._M_insert(__hint, __v, __node_gen, __unique_keys()); + } + + void + insert(initializer_list __l) + { this->insert(__l.begin(), __l.end()); } + + template + void + insert(_InputIterator __first, _InputIterator __last) + { + __hashtable& __h = _M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return _M_insert_range(__first, __last, __node_gen, __unique_keys()); + } + }; + + template + template + void + _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>:: + _M_insert_range(_InputIterator __first, _InputIterator __last, + const _NodeGetter& __node_gen, true_type) + { + size_type __n_elt = __detail::__distance_fw(__first, __last); + if (__n_elt == 0) + return; + + __hashtable& __h = _M_conjure_hashtable(); + for (; __first != __last; ++__first) + { + if (__h._M_insert(*__first, __node_gen, __unique_keys(), + __n_elt).second) + __n_elt = 1; + else if (__n_elt != 1) + --__n_elt; + } + } + + template + template + void + _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>:: + _M_insert_range(_InputIterator __first, _InputIterator __last, + const _NodeGetter& __node_gen, false_type) + { + using __rehash_type = typename __hashtable::__rehash_type; + using __rehash_state = typename __hashtable::__rehash_state; + using pair_type = std::pair; + + size_type __n_elt = __detail::__distance_fw(__first, __last); + if (__n_elt == 0) + return; + + __hashtable& __h = _M_conjure_hashtable(); + __rehash_type& __rehash = __h._M_rehash_policy; + const __rehash_state& __saved_state = __rehash._M_state(); + pair_type __do_rehash = __rehash._M_need_rehash(__h._M_bucket_count, + __h._M_element_count, + __n_elt); + + if (__do_rehash.first) + __h._M_rehash(__do_rehash.second, __saved_state); + + for (; __first != __last; ++__first) + __h._M_insert(*__first, __node_gen, __unique_keys()); + } + + /** + * Primary class template _Insert. + * + * Defines @c insert member functions that depend on _Hashtable policies, + * via partial specializations. + */ + template + struct _Insert; + + /// Specialization. + template + struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits, true> + : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits> + { + using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _Traits>; + + using value_type = typename __base_type::value_type; + using iterator = typename __base_type::iterator; + using const_iterator = typename __base_type::const_iterator; + + using __unique_keys = typename __base_type::__unique_keys; + using __ireturn_type = typename __hashtable_base::__ireturn_type; + using __hashtable = typename __base_type::__hashtable; + using __node_gen_type = typename __base_type::__node_gen_type; + + using __base_type::insert; + + __ireturn_type + insert(value_type&& __v) + { + __hashtable& __h = this->_M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return __h._M_insert(std::move(__v), __node_gen, __unique_keys()); + } + + iterator + insert(const_iterator __hint, value_type&& __v) + { + __hashtable& __h = this->_M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return __h._M_insert(__hint, std::move(__v), __node_gen, + __unique_keys()); + } + }; + + /// Specialization. + template + struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits, false> + : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits> + { + using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + using value_type = typename __base_type::value_type; + using iterator = typename __base_type::iterator; + using const_iterator = typename __base_type::const_iterator; + + using __unique_keys = typename __base_type::__unique_keys; + using __hashtable = typename __base_type::__hashtable; + using __ireturn_type = typename __base_type::__ireturn_type; + + using __base_type::insert; + + template + using __is_cons = std::is_constructible; + + template + using _IFcons = std::enable_if<__is_cons<_Pair>::value>; + + template + using _IFconsp = typename _IFcons<_Pair>::type; + + template> + __ireturn_type + insert(_Pair&& __v) + { + __hashtable& __h = this->_M_conjure_hashtable(); + return __h._M_emplace(__unique_keys(), std::forward<_Pair>(__v)); + } + + template> + iterator + insert(const_iterator __hint, _Pair&& __v) + { + __hashtable& __h = this->_M_conjure_hashtable(); + return __h._M_emplace(__hint, __unique_keys(), + std::forward<_Pair>(__v)); + } + }; + + template + using __has_load_factor = typename _Policy::__has_load_factor; + + /** + * Primary class template _Rehash_base. + * + * Give hashtable the max_load_factor functions and reserve iff the + * rehash policy supports it. + */ + template> + struct _Rehash_base; + + /// Specialization when rehash policy doesn't provide load factor management. + template + struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, + false_type> + { + }; + + /// Specialization when rehash policy provide load factor management. + template + struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, + true_type> + { + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + float + max_load_factor() const noexcept + { + const __hashtable* __this = static_cast(this); + return __this->__rehash_policy().max_load_factor(); + } + + void + max_load_factor(float __z) + { + __hashtable* __this = static_cast<__hashtable*>(this); + __this->__rehash_policy(_RehashPolicy(__z)); + } + + void + reserve(std::size_t __n) + { + __hashtable* __this = static_cast<__hashtable*>(this); + __this->rehash(__this->__rehash_policy()._M_bkt_for_elements(__n)); + } + }; + + /** + * Primary class template _Hashtable_ebo_helper. + * + * Helper class using EBO when it is not forbidden (the type is not + * final) and when it is worth it (the type is empty.) + */ + template + struct _Hashtable_ebo_helper; + + /// Specialization using EBO. + template + struct _Hashtable_ebo_helper<_Nm, _Tp, true> + : private _Tp + { + _Hashtable_ebo_helper() = default; + + template + _Hashtable_ebo_helper(_OtherTp&& __tp) + : _Tp(std::forward<_OtherTp>(__tp)) + { } + + const _Tp& _M_cget() const { return static_cast(*this); } + _Tp& _M_get() { return static_cast<_Tp&>(*this); } + }; + + /// Specialization not using EBO. + template + struct _Hashtable_ebo_helper<_Nm, _Tp, false> + { + _Hashtable_ebo_helper() = default; + + template + _Hashtable_ebo_helper(_OtherTp&& __tp) + : _M_tp(std::forward<_OtherTp>(__tp)) + { } + + const _Tp& _M_cget() const { return _M_tp; } + _Tp& _M_get() { return _M_tp; } + + private: + _Tp _M_tp; + }; + + /** + * Primary class template _Local_iterator_base. + * + * Base class for local iterators, used to iterate within a bucket + * but not between buckets. + */ + template + struct _Local_iterator_base; + + /** + * Primary class template _Hash_code_base. + * + * Encapsulates two policy issues that aren't quite orthogonal. + * (1) the difference between using a ranged hash function and using + * the combination of a hash function and a range-hashing function. + * In the former case we don't have such things as hash codes, so + * we have a dummy type as placeholder. + * (2) Whether or not we cache hash codes. Caching hash codes is + * meaningless if we have a ranged hash function. + * + * We also put the key extraction objects here, for convenience. + * Each specialization derives from one or more of the template + * parameters to benefit from Ebo. This is important as this type + * is inherited in some cases by the _Local_iterator_base type used + * to implement local_iterator and const_local_iterator. As with + * any iterator type we prefer to make it as small as possible. + * + * Primary template is unused except as a hook for specializations. + */ + template + struct _Hash_code_base; + + /// Specialization: ranged hash function, no caching hash codes. H1 + /// and H2 are provided but ignored. We define a dummy hash code type. + template + struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, false> + : private _Hashtable_ebo_helper<0, _ExtractKey>, + private _Hashtable_ebo_helper<1, _Hash> + { + private: + using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; + using __ebo_hash = _Hashtable_ebo_helper<1, _Hash>; + + protected: + typedef void* __hash_code; + typedef _Hash_node<_Value, false> __node_type; + + // We need the default constructor for the local iterators and _Hashtable + // default constructor. + _Hash_code_base() = default; + + _Hash_code_base(const _ExtractKey& __ex, const _H1&, const _H2&, + const _Hash& __h) + : __ebo_extract_key(__ex), __ebo_hash(__h) { } + + __hash_code + _M_hash_code(const _Key& __key) const + { return 0; } + + std::size_t + _M_bucket_index(const _Key& __k, __hash_code, + std::size_t __bkt_count) const + { return _M_ranged_hash()(__k, __bkt_count); } + + std::size_t + _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const + noexcept( noexcept(declval()(declval(), + (std::size_t)0)) ) + { return _M_ranged_hash()(_M_extract()(__p->_M_v()), __bkt_count); } + + void + _M_store_code(__node_type*, __hash_code) const + { } + + void + _M_copy_code(__node_type*, const __node_type*) const + { } + + void + _M_swap(_Hash_code_base& __x) + { + std::swap(__ebo_extract_key::_M_get(), + __x.__ebo_extract_key::_M_get()); + std::swap(__ebo_hash::_M_get(), __x.__ebo_hash::_M_get()); + } + + const _ExtractKey& + _M_extract() const { return __ebo_extract_key::_M_cget(); } + + const _Hash& + _M_ranged_hash() const { return __ebo_hash::_M_cget(); } + }; + + // No specialization for ranged hash function while caching hash codes. + // That combination is meaningless, and trying to do it is an error. + + /// Specialization: ranged hash function, cache hash codes. This + /// combination is meaningless, so we provide only a declaration + /// and no definition. + template + struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, true>; + + /// Specialization: hash function and range-hashing function, no + /// caching of hash codes. + /// Provides typedef and accessor required by C++ 11. + template + struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, + _Default_ranged_hash, false> + : private _Hashtable_ebo_helper<0, _ExtractKey>, + private _Hashtable_ebo_helper<1, _H1>, + private _Hashtable_ebo_helper<2, _H2> + { + private: + using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; + using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>; + using __ebo_h2 = _Hashtable_ebo_helper<2, _H2>; + + // Gives the local iterator implementation access to _M_bucket_index(). + friend struct _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, + _Default_ranged_hash, false>; + + public: + typedef _H1 hasher; + + hasher + hash_function() const + { return _M_h1(); } + + protected: + typedef std::size_t __hash_code; + typedef _Hash_node<_Value, false> __node_type; + + // We need the default constructor for the local iterators and _Hashtable + // default constructor. + _Hash_code_base() = default; + + _Hash_code_base(const _ExtractKey& __ex, + const _H1& __h1, const _H2& __h2, + const _Default_ranged_hash&) + : __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { } + + __hash_code + _M_hash_code(const _Key& __k) const + { + static_assert(__is_invocable{}, + "hash function must be invocable with an argument of key type"); + return _M_h1()(__k); + } + + std::size_t + _M_bucket_index(const _Key&, __hash_code __c, + std::size_t __bkt_count) const + { return _M_h2()(__c, __bkt_count); } + + std::size_t + _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const + noexcept( noexcept(declval()(declval())) + && noexcept(declval()((__hash_code)0, + (std::size_t)0)) ) + { return _M_h2()(_M_h1()(_M_extract()(__p->_M_v())), __bkt_count); } + + void + _M_store_code(__node_type*, __hash_code) const + { } + + void + _M_copy_code(__node_type*, const __node_type*) const + { } + + void + _M_swap(_Hash_code_base& __x) + { + std::swap(__ebo_extract_key::_M_get(), + __x.__ebo_extract_key::_M_get()); + std::swap(__ebo_h1::_M_get(), __x.__ebo_h1::_M_get()); + std::swap(__ebo_h2::_M_get(), __x.__ebo_h2::_M_get()); + } + + const _ExtractKey& + _M_extract() const { return __ebo_extract_key::_M_cget(); } + + const _H1& + _M_h1() const { return __ebo_h1::_M_cget(); } + + const _H2& + _M_h2() const { return __ebo_h2::_M_cget(); } + }; + + /// Specialization: hash function and range-hashing function, + /// caching hash codes. H is provided but ignored. Provides + /// typedef and accessor required by C++ 11. + template + struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, + _Default_ranged_hash, true> + : private _Hashtable_ebo_helper<0, _ExtractKey>, + private _Hashtable_ebo_helper<1, _H1>, + private _Hashtable_ebo_helper<2, _H2> + { + private: + // Gives the local iterator implementation access to _M_h2(). + friend struct _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, + _Default_ranged_hash, true>; + + using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; + using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>; + using __ebo_h2 = _Hashtable_ebo_helper<2, _H2>; + + public: + typedef _H1 hasher; + + hasher + hash_function() const + { return _M_h1(); } + + protected: + typedef std::size_t __hash_code; + typedef _Hash_node<_Value, true> __node_type; + + // We need the default constructor for _Hashtable default constructor. + _Hash_code_base() = default; + _Hash_code_base(const _ExtractKey& __ex, + const _H1& __h1, const _H2& __h2, + const _Default_ranged_hash&) + : __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { } + + __hash_code + _M_hash_code(const _Key& __k) const + { + static_assert(__is_invocable{}, + "hash function must be invocable with an argument of key type"); + return _M_h1()(__k); + } + + std::size_t + _M_bucket_index(const _Key&, __hash_code __c, + std::size_t __bkt_count) const + { return _M_h2()(__c, __bkt_count); } + + std::size_t + _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const + noexcept( noexcept(declval()((__hash_code)0, + (std::size_t)0)) ) + { return _M_h2()(__p->_M_hash_code, __bkt_count); } + + void + _M_store_code(__node_type* __n, __hash_code __c) const + { __n->_M_hash_code = __c; } + + void + _M_copy_code(__node_type* __to, const __node_type* __from) const + { __to->_M_hash_code = __from->_M_hash_code; } + + void + _M_swap(_Hash_code_base& __x) + { + std::swap(__ebo_extract_key::_M_get(), + __x.__ebo_extract_key::_M_get()); + std::swap(__ebo_h1::_M_get(), __x.__ebo_h1::_M_get()); + std::swap(__ebo_h2::_M_get(), __x.__ebo_h2::_M_get()); + } + + const _ExtractKey& + _M_extract() const { return __ebo_extract_key::_M_cget(); } + + const _H1& + _M_h1() const { return __ebo_h1::_M_cget(); } + + const _H2& + _M_h2() const { return __ebo_h2::_M_cget(); } + }; + + /// Partial specialization used when nodes contain a cached hash code. + template + struct _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, true> + : private _Hashtable_ebo_helper<0, _H2> + { + protected: + using __base_type = _Hashtable_ebo_helper<0, _H2>; + using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, true>; + + _Local_iterator_base() = default; + _Local_iterator_base(const __hash_code_base& __base, + _Hash_node<_Value, true>* __p, + std::size_t __bkt, std::size_t __bkt_count) + : __base_type(__base._M_h2()), + _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { } + + void + _M_incr() + { + _M_cur = _M_cur->_M_next(); + if (_M_cur) + { + std::size_t __bkt + = __base_type::_M_get()(_M_cur->_M_hash_code, + _M_bucket_count); + if (__bkt != _M_bucket) + _M_cur = nullptr; + } + } + + _Hash_node<_Value, true>* _M_cur; + std::size_t _M_bucket; + std::size_t _M_bucket_count; + + public: + const void* + _M_curr() const { return _M_cur; } // for equality ops + + std::size_t + _M_get_bucket() const { return _M_bucket; } // for debug mode + }; + + // Uninitialized storage for a _Hash_code_base. + // This type is DefaultConstructible and Assignable even if the + // _Hash_code_base type isn't, so that _Local_iterator_base<..., false> + // can be DefaultConstructible and Assignable. + template::value> + struct _Hash_code_storage + { + __gnu_cxx::__aligned_buffer<_Tp> _M_storage; + + _Tp* + _M_h() { return _M_storage._M_ptr(); } + + const _Tp* + _M_h() const { return _M_storage._M_ptr(); } + }; + + // Empty partial specialization for empty _Hash_code_base types. + template + struct _Hash_code_storage<_Tp, true> + { + static_assert( std::is_empty<_Tp>::value, "Type must be empty" ); + + // As _Tp is an empty type there will be no bytes written/read through + // the cast pointer, so no strict-aliasing violation. + _Tp* + _M_h() { return reinterpret_cast<_Tp*>(this); } + + const _Tp* + _M_h() const { return reinterpret_cast(this); } + }; + + template + using __hash_code_for_local_iter + = _Hash_code_storage<_Hash_code_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, false>>; + + // Partial specialization used when hash codes are not cached + template + struct _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, false> + : __hash_code_for_local_iter<_Key, _Value, _ExtractKey, _H1, _H2, _Hash> + { + protected: + using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, false>; + + _Local_iterator_base() : _M_bucket_count(-1) { } + + _Local_iterator_base(const __hash_code_base& __base, + _Hash_node<_Value, false>* __p, + std::size_t __bkt, std::size_t __bkt_count) + : _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) + { _M_init(__base); } + + ~_Local_iterator_base() + { + if (_M_bucket_count != -1) + _M_destroy(); + } + + _Local_iterator_base(const _Local_iterator_base& __iter) + : _M_cur(__iter._M_cur), _M_bucket(__iter._M_bucket), + _M_bucket_count(__iter._M_bucket_count) + { + if (_M_bucket_count != -1) + _M_init(*__iter._M_h()); + } + + _Local_iterator_base& + operator=(const _Local_iterator_base& __iter) + { + if (_M_bucket_count != -1) + _M_destroy(); + _M_cur = __iter._M_cur; + _M_bucket = __iter._M_bucket; + _M_bucket_count = __iter._M_bucket_count; + if (_M_bucket_count != -1) + _M_init(*__iter._M_h()); + return *this; + } + + void + _M_incr() + { + _M_cur = _M_cur->_M_next(); + if (_M_cur) + { + std::size_t __bkt = this->_M_h()->_M_bucket_index(_M_cur, + _M_bucket_count); + if (__bkt != _M_bucket) + _M_cur = nullptr; + } + } + + _Hash_node<_Value, false>* _M_cur; + std::size_t _M_bucket; + std::size_t _M_bucket_count; + + void + _M_init(const __hash_code_base& __base) + { ::new(this->_M_h()) __hash_code_base(__base); } + + void + _M_destroy() { this->_M_h()->~__hash_code_base(); } + + public: + const void* + _M_curr() const { return _M_cur; } // for equality ops and debug mode + + std::size_t + _M_get_bucket() const { return _M_bucket; } // for debug mode + }; + + template + inline bool + operator==(const _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>& __x, + const _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>& __y) + { return __x._M_curr() == __y._M_curr(); } + + template + inline bool + operator!=(const _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>& __x, + const _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>& __y) + { return __x._M_curr() != __y._M_curr(); } + + /// local iterators + template + struct _Local_iterator + : public _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache> + { + private: + using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>; + using __hash_code_base = typename __base_type::__hash_code_base; + public: + typedef _Value value_type; + typedef typename std::conditional<__constant_iterators, + const _Value*, _Value*>::type + pointer; + typedef typename std::conditional<__constant_iterators, + const _Value&, _Value&>::type + reference; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Local_iterator() = default; + + _Local_iterator(const __hash_code_base& __base, + _Hash_node<_Value, __cache>* __n, + std::size_t __bkt, std::size_t __bkt_count) + : __base_type(__base, __n, __bkt, __bkt_count) + { } + + reference + operator*() const + { return this->_M_cur->_M_v(); } + + pointer + operator->() const + { return this->_M_cur->_M_valptr(); } + + _Local_iterator& + operator++() + { + this->_M_incr(); + return *this; + } + + _Local_iterator + operator++(int) + { + _Local_iterator __tmp(*this); + this->_M_incr(); + return __tmp; + } + }; + + /// local const_iterators + template + struct _Local_const_iterator + : public _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache> + { + private: + using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>; + using __hash_code_base = typename __base_type::__hash_code_base; + + public: + typedef _Value value_type; + typedef const _Value* pointer; + typedef const _Value& reference; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Local_const_iterator() = default; + + _Local_const_iterator(const __hash_code_base& __base, + _Hash_node<_Value, __cache>* __n, + std::size_t __bkt, std::size_t __bkt_count) + : __base_type(__base, __n, __bkt, __bkt_count) + { } + + _Local_const_iterator(const _Local_iterator<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, + __constant_iterators, + __cache>& __x) + : __base_type(__x) + { } + + reference + operator*() const + { return this->_M_cur->_M_v(); } + + pointer + operator->() const + { return this->_M_cur->_M_valptr(); } + + _Local_const_iterator& + operator++() + { + this->_M_incr(); + return *this; + } + + _Local_const_iterator + operator++(int) + { + _Local_const_iterator __tmp(*this); + this->_M_incr(); + return __tmp; + } + }; + + /** + * Primary class template _Hashtable_base. + * + * Helper class adding management of _Equal functor to + * _Hash_code_base type. + * + * Base class templates are: + * - __detail::_Hash_code_base + * - __detail::_Hashtable_ebo_helper + */ + template + struct _Hashtable_base + : public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, + _Traits::__hash_cached::value>, + private _Hashtable_ebo_helper<0, _Equal> + { + public: + typedef _Key key_type; + typedef _Value value_type; + typedef _Equal key_equal; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + using __traits_type = _Traits; + using __hash_cached = typename __traits_type::__hash_cached; + using __constant_iterators = typename __traits_type::__constant_iterators; + using __unique_keys = typename __traits_type::__unique_keys; + + using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, + __hash_cached::value>; + + using __hash_code = typename __hash_code_base::__hash_code; + using __node_type = typename __hash_code_base::__node_type; + + using iterator = __detail::_Node_iterator; + + using const_iterator = __detail::_Node_const_iterator; + + using local_iterator = __detail::_Local_iterator; + + using const_local_iterator = __detail::_Local_const_iterator; + + using __ireturn_type = typename std::conditional<__unique_keys::value, + std::pair, + iterator>::type; + private: + using _EqualEBO = _Hashtable_ebo_helper<0, _Equal>; + + template + struct _Equal_hash_code + { + static bool + _S_equals(__hash_code, const _NodeT&) + { return true; } + }; + + template + struct _Equal_hash_code<_Hash_node<_Ptr2, true>> + { + static bool + _S_equals(__hash_code __c, const _Hash_node<_Ptr2, true>& __n) + { return __c == __n._M_hash_code; } + }; + + protected: + _Hashtable_base() = default; + _Hashtable_base(const _ExtractKey& __ex, const _H1& __h1, const _H2& __h2, + const _Hash& __hash, const _Equal& __eq) + : __hash_code_base(__ex, __h1, __h2, __hash), _EqualEBO(__eq) + { } + + bool + _M_equals(const _Key& __k, __hash_code __c, __node_type* __n) const + { + static_assert(__is_invocable{}, + "key equality predicate must be invocable with two arguments of " + "key type"); + return _Equal_hash_code<__node_type>::_S_equals(__c, *__n) + && _M_eq()(__k, this->_M_extract()(__n->_M_v())); + } + + void + _M_swap(_Hashtable_base& __x) + { + __hash_code_base::_M_swap(__x); + std::swap(_EqualEBO::_M_get(), __x._EqualEBO::_M_get()); + } + + const _Equal& + _M_eq() const { return _EqualEBO::_M_cget(); } + }; + + /** + * Primary class template _Equality. + * + * This is for implementing equality comparison for unordered + * containers, per N3068, by John Lakos and Pablo Halpern. + * Algorithmically, we follow closely the reference implementations + * therein. + */ + template + struct _Equality; + + /// unordered_map and unordered_set specializations. + template + struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true> + { + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>; + + bool + _M_equal(const __hashtable&) const; + }; + + template + bool + _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + _M_equal(const __hashtable& __other) const + { + using __node_base = typename __hashtable::__node_base; + using __node_type = typename __hashtable::__node_type; + const __hashtable* __this = static_cast(this); + if (__this->size() != __other.size()) + return false; + + for (auto __itx = __this->begin(); __itx != __this->end(); ++__itx) + { + std::size_t __ybkt = __other._M_bucket_index(__itx._M_cur); + __node_base* __prev_n = __other._M_buckets[__ybkt]; + if (!__prev_n) + return false; + + for (__node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);; + __n = __n->_M_next()) + { + if (__n->_M_v() == *__itx) + break; + + if (!__n->_M_nxt + || __other._M_bucket_index(__n->_M_next()) != __ybkt) + return false; + } + } + + return true; + } + + /// unordered_multiset and unordered_multimap specializations. + template + struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, false> + { + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>; + + bool + _M_equal(const __hashtable&) const; + }; + + template + bool + _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, false>:: + _M_equal(const __hashtable& __other) const + { + using __node_base = typename __hashtable::__node_base; + using __node_type = typename __hashtable::__node_type; + const __hashtable* __this = static_cast(this); + if (__this->size() != __other.size()) + return false; + + for (auto __itx = __this->begin(); __itx != __this->end();) + { + std::size_t __x_count = 1; + auto __itx_end = __itx; + for (++__itx_end; __itx_end != __this->end() + && __this->key_eq()(_ExtractKey()(*__itx), + _ExtractKey()(*__itx_end)); + ++__itx_end) + ++__x_count; + + std::size_t __ybkt = __other._M_bucket_index(__itx._M_cur); + __node_base* __y_prev_n = __other._M_buckets[__ybkt]; + if (!__y_prev_n) + return false; + + __node_type* __y_n = static_cast<__node_type*>(__y_prev_n->_M_nxt); + for (;; __y_n = __y_n->_M_next()) + { + if (__this->key_eq()(_ExtractKey()(__y_n->_M_v()), + _ExtractKey()(*__itx))) + break; + + if (!__y_n->_M_nxt + || __other._M_bucket_index(__y_n->_M_next()) != __ybkt) + return false; + } + + typename __hashtable::const_iterator __ity(__y_n); + for (auto __ity_end = __ity; __ity_end != __other.end(); ++__ity_end) + if (--__x_count == 0) + break; + + if (__x_count != 0) + return false; + + if (!std::is_permutation(__itx, __itx_end, __ity)) + return false; + + __itx = __itx_end; + } + return true; + } + + /** + * This type deals with all allocation and keeps an allocator instance + * through inheritance to benefit from EBO when possible. + */ + template + struct _Hashtable_alloc : private _Hashtable_ebo_helper<0, _NodeAlloc> + { + private: + using __ebo_node_alloc = _Hashtable_ebo_helper<0, _NodeAlloc>; + public: + using __node_type = typename _NodeAlloc::value_type; + using __node_alloc_type = _NodeAlloc; + // Use __gnu_cxx to benefit from _S_always_equal and al. + using __node_alloc_traits = __gnu_cxx::__alloc_traits<__node_alloc_type>; + + using __value_alloc_traits = typename __node_alloc_traits::template + rebind_traits; + + using __node_base = __detail::_Hash_node_base; + using __bucket_type = __node_base*; + using __bucket_alloc_type = + __alloc_rebind<__node_alloc_type, __bucket_type>; + using __bucket_alloc_traits = std::allocator_traits<__bucket_alloc_type>; + + _Hashtable_alloc() = default; + _Hashtable_alloc(const _Hashtable_alloc&) = default; + _Hashtable_alloc(_Hashtable_alloc&&) = default; + + template + _Hashtable_alloc(_Alloc&& __a) + : __ebo_node_alloc(std::forward<_Alloc>(__a)) + { } + + __node_alloc_type& + _M_node_allocator() + { return __ebo_node_alloc::_M_get(); } + + const __node_alloc_type& + _M_node_allocator() const + { return __ebo_node_alloc::_M_cget(); } + + // Allocate a node and construct an element within it. + template + __node_type* + _M_allocate_node(_Args&&... __args); + + // Destroy the element within a node and deallocate the node. + void + _M_deallocate_node(__node_type* __n); + + // Deallocate a node. + void + _M_deallocate_node_ptr(__node_type* __n); + + // Deallocate the linked list of nodes pointed to by __n. + // The elements within the nodes are destroyed. + void + _M_deallocate_nodes(__node_type* __n); + + __bucket_type* + _M_allocate_buckets(std::size_t __bkt_count); + + void + _M_deallocate_buckets(__bucket_type*, std::size_t __bkt_count); + }; + + // Definitions of class template _Hashtable_alloc's out-of-line member + // functions. + template + template + auto + _Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&&... __args) + -> __node_type* + { + auto __nptr = __node_alloc_traits::allocate(_M_node_allocator(), 1); + __node_type* __n = std::__to_address(__nptr); + __try + { + ::new ((void*)__n) __node_type; + __node_alloc_traits::construct(_M_node_allocator(), + __n->_M_valptr(), + std::forward<_Args>(__args)...); + return __n; + } + __catch(...) + { + __node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1); + __throw_exception_again; + } + } + + template + void + _Hashtable_alloc<_NodeAlloc>::_M_deallocate_node(__node_type* __n) + { + __node_alloc_traits::destroy(_M_node_allocator(), __n->_M_valptr()); + _M_deallocate_node_ptr(__n); + } + + template + void + _Hashtable_alloc<_NodeAlloc>::_M_deallocate_node_ptr(__node_type* __n) + { + typedef typename __node_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__n); + __n->~__node_type(); + __node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1); + } + + template + void + _Hashtable_alloc<_NodeAlloc>::_M_deallocate_nodes(__node_type* __n) + { + while (__n) + { + __node_type* __tmp = __n; + __n = __n->_M_next(); + _M_deallocate_node(__tmp); + } + } + + template + typename _Hashtable_alloc<_NodeAlloc>::__bucket_type* + _Hashtable_alloc<_NodeAlloc>::_M_allocate_buckets(std::size_t __bkt_count) + { + __bucket_alloc_type __alloc(_M_node_allocator()); + + auto __ptr = __bucket_alloc_traits::allocate(__alloc, __bkt_count); + __bucket_type* __p = std::__to_address(__ptr); + __builtin_memset(__p, 0, __bkt_count * sizeof(__bucket_type)); + return __p; + } + + template + void + _Hashtable_alloc<_NodeAlloc>::_M_deallocate_buckets(__bucket_type* __bkts, + std::size_t __bkt_count) + { + typedef typename __bucket_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__bkts); + __bucket_alloc_type __alloc(_M_node_allocator()); + __bucket_alloc_traits::deallocate(__alloc, __ptr, __bkt_count); + } + + //@} hashtable-detail +} // namespace __detail +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _HASHTABLE_POLICY_H diff --git a/resources/sources/avr-libstdcpp/include/bits/indirect_array.h b/resources/sources/avr-libstdcpp/include/bits/indirect_array.h new file mode 100644 index 000000000..11fac3290 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/indirect_array.h @@ -0,0 +1,212 @@ +// The template and inlines for the -*- C++ -*- indirect_array class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/indirect_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _INDIRECT_ARRAY_H +#define _INDIRECT_ARRAY_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Reference to arbitrary subset of an array. + * + * An indirect_array is a reference to the actual elements of an array + * specified by an ordered array of indices. The way to get an + * indirect_array is to call operator[](valarray) on a valarray. + * The returned indirect_array then permits carrying operations out on the + * referenced subset of elements in the original valarray. + * + * For example, if an indirect_array is obtained using the array (4,2,0) as + * an argument, and then assigned to an array containing (1,2,3), then the + * underlying array will have array[0]==3, array[2]==2, and array[4]==1. + * + * @param Tp Element type. + */ + template + class indirect_array + { + public: + typedef _Tp value_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 253. valarray helper functions are almost entirely useless + + /// Copy constructor. Both slices refer to the same underlying array. + indirect_array(const indirect_array&); + + /// Assignment operator. Assigns elements to corresponding elements + /// of @a a. + indirect_array& operator=(const indirect_array&); + + /// Assign slice elements to corresponding elements of @a v. + void operator=(const valarray<_Tp>&) const; + /// Multiply slice elements by corresponding elements of @a v. + void operator*=(const valarray<_Tp>&) const; + /// Divide slice elements by corresponding elements of @a v. + void operator/=(const valarray<_Tp>&) const; + /// Modulo slice elements by corresponding elements of @a v. + void operator%=(const valarray<_Tp>&) const; + /// Add corresponding elements of @a v to slice elements. + void operator+=(const valarray<_Tp>&) const; + /// Subtract corresponding elements of @a v from slice elements. + void operator-=(const valarray<_Tp>&) const; + /// Logical xor slice elements with corresponding elements of @a v. + void operator^=(const valarray<_Tp>&) const; + /// Logical and slice elements with corresponding elements of @a v. + void operator&=(const valarray<_Tp>&) const; + /// Logical or slice elements with corresponding elements of @a v. + void operator|=(const valarray<_Tp>&) const; + /// Left shift slice elements by corresponding elements of @a v. + void operator<<=(const valarray<_Tp>&) const; + /// Right shift slice elements by corresponding elements of @a v. + void operator>>=(const valarray<_Tp>&) const; + /// Assign all slice elements to @a t. + void operator= (const _Tp&) const; + // ~indirect_array(); + + template + void operator=(const _Expr<_Dom, _Tp>&) const; + template + void operator*=(const _Expr<_Dom, _Tp>&) const; + template + void operator/=(const _Expr<_Dom, _Tp>&) const; + template + void operator%=(const _Expr<_Dom, _Tp>&) const; + template + void operator+=(const _Expr<_Dom, _Tp>&) const; + template + void operator-=(const _Expr<_Dom, _Tp>&) const; + template + void operator^=(const _Expr<_Dom, _Tp>&) const; + template + void operator&=(const _Expr<_Dom, _Tp>&) const; + template + void operator|=(const _Expr<_Dom, _Tp>&) const; + template + void operator<<=(const _Expr<_Dom, _Tp>&) const; + template + void operator>>=(const _Expr<_Dom, _Tp>&) const; + + private: + /// Copy constructor. Both slices refer to the same underlying array. + indirect_array(_Array<_Tp>, size_t, _Array); + + friend class valarray<_Tp>; + friend class gslice_array<_Tp>; + + const size_t _M_sz; + const _Array _M_index; + const _Array<_Tp> _M_array; + + // not implemented + indirect_array(); + }; + + template + inline + indirect_array<_Tp>::indirect_array(const indirect_array<_Tp>& __a) + : _M_sz(__a._M_sz), _M_index(__a._M_index), _M_array(__a._M_array) {} + + template + inline + indirect_array<_Tp>::indirect_array(_Array<_Tp> __a, size_t __s, + _Array __i) + : _M_sz(__s), _M_index(__i), _M_array(__a) {} + + template + inline indirect_array<_Tp>& + indirect_array<_Tp>::operator=(const indirect_array<_Tp>& __a) + { + std::__valarray_copy(__a._M_array, _M_sz, __a._M_index, _M_array, + _M_index); + return *this; + } + + template + inline void + indirect_array<_Tp>::operator=(const _Tp& __t) const + { std::__valarray_fill(_M_array, _M_index, _M_sz, __t); } + + template + inline void + indirect_array<_Tp>::operator=(const valarray<_Tp>& __v) const + { std::__valarray_copy(_Array<_Tp>(__v), _M_sz, _M_array, _M_index); } + + template + template + inline void + indirect_array<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) const + { std::__valarray_copy(__e, _M_sz, _M_array, _M_index); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ + template \ + inline void \ + indirect_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const\ + { \ + _Array_augmented_##_Name(_M_array, _M_index, _Array<_Tp>(__v), _M_sz); \ + } \ + \ + template \ + template \ + inline void \ + indirect_array<_Tp>::operator _Op##=(const _Expr<_Dom,_Tp>& __e) const\ + { \ + _Array_augmented_##_Name(_M_array, _M_index, __e, _M_sz); \ + } + +_DEFINE_VALARRAY_OPERATOR(*, __multiplies) +_DEFINE_VALARRAY_OPERATOR(/, __divides) +_DEFINE_VALARRAY_OPERATOR(%, __modulus) +_DEFINE_VALARRAY_OPERATOR(+, __plus) +_DEFINE_VALARRAY_OPERATOR(-, __minus) +_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) +_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) +_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) +_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _INDIRECT_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/invoke.h b/resources/sources/avr-libstdcpp/include/bits/invoke.h new file mode 100644 index 000000000..18f5b9442 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/invoke.h @@ -0,0 +1,163 @@ +// Implementation of INVOKE -*- C++ -*- + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/invoke.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_INVOKE_H +#define _GLIBCXX_INVOKE_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + // Used by __invoke_impl instead of std::forward<_Tp> so that a + // reference_wrapper is converted to an lvalue-reference. + template::type> + constexpr _Up&& + __invfwd(typename remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Up&&>(__t); } + + template + constexpr _Res + __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args) + { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); } + + template + constexpr _Res + __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); } + + template + constexpr _Res + __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { + return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...); + } + + template + constexpr _Res + __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t) + { return __invfwd<_Tp>(__t).*__f; } + + template + constexpr _Res + __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t) + { return (*std::forward<_Tp>(__t)).*__f; } + + /// Invoke a callable object. + template + constexpr typename __invoke_result<_Callable, _Args...>::type + __invoke(_Callable&& __fn, _Args&&... __args) + noexcept(__is_nothrow_invocable<_Callable, _Args...>::value) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } + +#if __cplusplus >= 201703L + // INVOKE: Invoke a callable object and convert the result to R. + template + constexpr enable_if_t, _Res> + __invoke_r(_Callable&& __fn, _Args&&... __args) + noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + if constexpr (is_void_v<_Res>) + std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + else + return std::__invoke_impl<__type>(__tag{}, + std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#else // C++11 + template + using __can_invoke_as_void = __enable_if_t< + __and_, __is_invocable<_Callable, _Args...>>::value, + _Res + >; + + template + using __can_invoke_as_nonvoid = __enable_if_t< + __and_<__not_>, + is_convertible::type, + _Res> + >::value, + _Res + >; + + // INVOKE: Invoke a callable object and convert the result to R. + template + constexpr __can_invoke_as_nonvoid<_Res, _Callable, _Args...> + __invoke_r(_Callable&& __fn, _Args&&... __args) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } + + // INVOKE when R is cv void + template + _GLIBCXX14_CONSTEXPR __can_invoke_as_void<_Res, _Callable, _Args...> + __invoke_r(_Callable&& __fn, _Args&&... __args) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_INVOKE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h b/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h new file mode 100644 index 000000000..2721240e3 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h @@ -0,0 +1,911 @@ +// Concepts and traits for use with iterators -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/iterator_concepts.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _ITERATOR_CONCEPTS_H +#define _ITERATOR_CONCEPTS_H 1 + +#pragma GCC system_header + +#include +#include // to_address +#include // identity, ranges::less + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct input_iterator_tag; + struct output_iterator_tag; + struct forward_iterator_tag; + struct bidirectional_iterator_tag; + struct random_access_iterator_tag; + struct contiguous_iterator_tag; + + template + struct iterator_traits; + + template requires is_object_v<_Tp> + struct iterator_traits<_Tp*>; + + template + struct __iterator_traits; + + namespace __detail + { + template + using __with_ref = _Tp&; + + template + concept __can_reference = requires { typename __with_ref<_Tp>; }; + + template + concept __dereferenceable = requires(_Tp& __t) + { + { *__t } -> __can_reference; + }; + } // namespace __detail + + template<__detail::__dereferenceable _Tp> + using iter_reference_t = decltype(*std::declval<_Tp&>()); + + namespace ranges + { + namespace __cust_imove + { + void iter_move(); + + template + concept __adl_imove + = (std::__detail::__class_or_enum>) + && requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); }; + + struct _IMove + { + private: + template + struct __result + { using type = iter_reference_t<_Tp>; }; + + template + requires __adl_imove<_Tp> + struct __result<_Tp> + { using type = decltype(iter_move(std::declval<_Tp>())); }; + + template + requires (!__adl_imove<_Tp>) + && is_lvalue_reference_v> + struct __result<_Tp> + { using type = remove_reference_t>&&; }; + + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_imove<_Tp>) + return noexcept(iter_move(std::declval<_Tp>())); + else + return noexcept(*std::declval<_Tp>()); + } + + public: + // The result type of iter_move(std::declval<_Tp>()) + template + using __type = typename __result<_Tp>::type; + + template + constexpr __type<_Tp> + operator()(_Tp&& __e) const + noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__adl_imove<_Tp>) + return iter_move(static_cast<_Tp&&>(__e)); + else if constexpr (is_lvalue_reference_v>) + return static_cast<__type<_Tp>>(*__e); + else + return *__e; + } + }; + } // namespace __cust_imove + + inline namespace __cust + { + inline constexpr __cust_imove::_IMove iter_move{}; + } // inline namespace __cust + } // namespace ranges + + template<__detail::__dereferenceable _Tp> + requires requires(_Tp& __t) + { { ranges::iter_move(__t) } -> __detail::__can_reference; } + using iter_rvalue_reference_t + = decltype(ranges::iter_move(std::declval<_Tp&>())); + + template struct incrementable_traits { }; + + template requires is_object_v<_Tp> + struct incrementable_traits<_Tp*> + { using difference_type = ptrdiff_t; }; + + template + struct incrementable_traits + : incrementable_traits<_Iter> { }; + + template requires requires { typename _Tp::difference_type; } + struct incrementable_traits<_Tp> + { using difference_type = typename _Tp::difference_type; }; + + template + requires (!requires { typename _Tp::difference_type; } + && requires(const _Tp& __a, const _Tp& __b) + { + requires (!is_void_v>); // PR c++/78173 + { __a - __b } -> integral; + }) + struct incrementable_traits<_Tp> + { + using difference_type + = make_signed_t() - std::declval<_Tp>())>; + }; + + namespace __detail + { + // An iterator such that iterator_traits<_Iter> names a specialization + // generated from the primary template. + template + concept __primary_traits_iter + = __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>); + + template + struct __iter_traits_impl + { using type = iterator_traits<_Iter>; }; + + template + requires __primary_traits_iter<_Iter> + struct __iter_traits_impl<_Iter, _Tp> + { using type = _Tp; }; + + // ITER_TRAITS + template + using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type; + + template + using __iter_diff_t = typename + __iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type; + } // namespace __detail + + template + using iter_difference_t = __detail::__iter_diff_t>; + + namespace __detail + { + template struct __cond_value_type { }; + + template requires is_object_v<_Tp> + struct __cond_value_type<_Tp> + { using value_type = remove_cv_t<_Tp>; }; + } // namespace __detail + + template struct indirectly_readable_traits { }; + + template + struct indirectly_readable_traits<_Tp*> + : __detail::__cond_value_type<_Tp> + { }; + + template requires is_array_v<_Iter> + struct indirectly_readable_traits<_Iter> + { using value_type = remove_cv_t>; }; + + template + struct indirectly_readable_traits + : indirectly_readable_traits<_Iter> + { }; + + template requires requires { typename _Tp::value_type; } + struct indirectly_readable_traits<_Tp> + : __detail::__cond_value_type + { }; + + template requires requires { typename _Tp::element_type; } + struct indirectly_readable_traits<_Tp> + : __detail::__cond_value_type + { }; + + namespace __detail + { + template + using __iter_value_t = typename + __iter_traits<_Tp, indirectly_readable_traits<_Tp>>::value_type; + } // namespace __detail + + template + using iter_value_t = __detail::__iter_value_t>; + + namespace __detail + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3420. cpp17-iterator should check [type] looks like an iterator first + template + concept __cpp17_iterator = requires(_Iter __it) + { + { *__it } -> __can_reference; + { ++__it } -> same_as<_Iter&>; + { *__it++ } -> __can_reference; + } && copyable<_Iter>; + + template + concept __cpp17_input_iterator = __cpp17_iterator<_Iter> + && equality_comparable<_Iter> + && requires(_Iter __it) + { + typename incrementable_traits<_Iter>::difference_type; + typename indirectly_readable_traits<_Iter>::value_type; + typename common_reference_t&&, + typename indirectly_readable_traits<_Iter>::value_type&>; + typename common_reference_t::value_type&>; + requires signed_integral< + typename incrementable_traits<_Iter>::difference_type>; + }; + + template + concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter> + && constructible_from<_Iter> + && is_lvalue_reference_v> + && same_as>, + typename indirectly_readable_traits<_Iter>::value_type> + && requires(_Iter __it) + { + { __it++ } -> convertible_to; + { *__it++ } -> same_as>; + }; + + template + concept __cpp17_bidi_iterator = __cpp17_fwd_iterator<_Iter> + && requires(_Iter __it) + { + { --__it } -> same_as<_Iter&>; + { __it-- } -> convertible_to; + { *__it-- } -> same_as>; + }; + + template + concept __cpp17_randacc_iterator = __cpp17_bidi_iterator<_Iter> + && totally_ordered<_Iter> + && requires(_Iter __it, + typename incrementable_traits<_Iter>::difference_type __n) + { + { __it += __n } -> same_as<_Iter&>; + { __it -= __n } -> same_as<_Iter&>; + { __it + __n } -> same_as<_Iter>; + { __n + __it } -> same_as<_Iter>; + { __it - __n } -> same_as<_Iter>; + { __it - __it } -> same_as; + { __it[__n] } -> convertible_to>; + }; + + template + concept __iter_with_nested_types = requires { + typename _Iter::iterator_category; + typename _Iter::value_type; + typename _Iter::difference_type; + typename _Iter::reference; + }; + + template + concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>; + + // FIXME: These have to be at namespace-scope because of PR 92103. + template + struct __ptr + { using type = void; }; + + template requires requires { typename _Iter::pointer; } + struct __ptr<_Iter, true> + { using type = typename _Iter::pointer; }; + + template requires requires { typename _Iter::pointer; } + struct __ptr<_Iter, false> + { using type = typename _Iter::pointer; }; + + template + requires (!requires { typename _Iter::pointer; } + && requires(_Iter& __it) { __it.operator->(); }) + struct __ptr<_Iter, true> + { using type = decltype(std::declval<_Iter&>().operator->()); }; + + template + struct __ref + { using type = iter_reference_t<_Iter>; }; + + template requires requires { typename _Iter::reference; } + struct __ref<_Iter> + { using type = typename _Iter::reference; }; + + template + struct __cat + { using type = input_iterator_tag; }; + + template + requires requires { typename _Iter::iterator_category; } + struct __cat<_Iter> + { using type = typename _Iter::iterator_category; }; + + template + requires (!requires { typename _Iter::iterator_category; } + && __detail::__cpp17_randacc_iterator<_Iter>) + struct __cat<_Iter> + { using type = random_access_iterator_tag; }; + + template + requires (!requires { typename _Iter::iterator_category; } + && __detail::__cpp17_bidi_iterator<_Iter>) + struct __cat<_Iter> + { using type = bidirectional_iterator_tag; }; + + template + requires (!requires { typename _Iter::iterator_category; } + && __detail::__cpp17_fwd_iterator<_Iter>) + struct __cat<_Iter> + { using type = forward_iterator_tag; }; + + template + struct __diff + { using type = void; }; + + template + requires requires { + typename incrementable_traits<_Iter>::difference_type; + } + struct __diff<_Iter> + { + using type = typename incrementable_traits<_Iter>::difference_type; + }; + + } // namespace __detail + + template + requires __detail::__iter_with_nested_types<_Iterator> + struct __iterator_traits<_Iterator, void> + { + using iterator_category = typename _Iterator::iterator_category; + using value_type = typename _Iterator::value_type; + using difference_type = typename _Iterator::difference_type; + using pointer = typename __detail::__ptr<_Iterator>::type; + using reference = typename _Iterator::reference; + }; + + template + requires __detail::__iter_without_nested_types<_Iterator> + && __detail::__cpp17_input_iterator<_Iterator> + struct __iterator_traits<_Iterator, void> + { + using iterator_category = typename __detail::__cat<_Iterator>::type; + using value_type + = typename indirectly_readable_traits<_Iterator>::value_type; + using difference_type + = typename incrementable_traits<_Iterator>::difference_type; + using pointer = typename __detail::__ptr<_Iterator, true>::type; + using reference = typename __detail::__ref<_Iterator>::type; + }; + + template + requires __detail::__iter_without_nested_types<_Iterator> + && __detail::__cpp17_iterator<_Iterator> + struct __iterator_traits<_Iterator, void> + { + using iterator_category = output_iterator_tag; + using value_type = void; + using difference_type = typename __detail::__diff<_Iterator>::type; + using pointer = void; + using reference = void; + }; + + namespace __detail + { + template + struct __iter_concept_impl; + + // ITER_CONCEPT(I) is ITER_TRAITS(I)::iterator_concept if that is valid. + template + requires requires { typename __iter_traits<_Iter>::iterator_concept; } + struct __iter_concept_impl<_Iter> + { using type = typename __iter_traits<_Iter>::iterator_concept; }; + + // Otherwise, ITER_TRAITS(I)::iterator_category if that is valid. + template + requires (!requires { typename __iter_traits<_Iter>::iterator_concept; } + && requires { typename __iter_traits<_Iter>::iterator_category; }) + struct __iter_concept_impl<_Iter> + { using type = typename __iter_traits<_Iter>::iterator_category; }; + + // Otherwise, random_access_tag if iterator_traits is not specialized. + template + requires (!requires { typename __iter_traits<_Iter>::iterator_concept; } + && !requires { typename __iter_traits<_Iter>::iterator_category; } + && __primary_traits_iter<_Iter>) + struct __iter_concept_impl<_Iter> + { using type = random_access_iterator_tag; }; + + // Otherwise, there is no ITER_CONCEPT(I) type. + template + struct __iter_concept_impl + { }; + + // ITER_CONCEPT + template + using __iter_concept = typename __iter_concept_impl<_Iter>::type; + + template + concept __indirectly_readable_impl = requires(const _In __in) + { + typename iter_value_t<_In>; + typename iter_reference_t<_In>; + typename iter_rvalue_reference_t<_In>; + { *__in } -> same_as>; + { ranges::iter_move(__in) } -> same_as>; + } + && common_reference_with&&, iter_value_t<_In>&> + && common_reference_with&&, + iter_rvalue_reference_t<_In>&&> + && common_reference_with&&, + const iter_value_t<_In>&>; + + } // namespace __detail + + /// Requirements for types that are readable by applying operator*. + template + concept indirectly_readable + = __detail::__indirectly_readable_impl>; + + template + using iter_common_reference_t + = common_reference_t, iter_value_t<_Tp>&>; + + /// Requirements for writing a value into an iterator's referenced object. + template + concept indirectly_writable = requires(_Out&& __o, _Tp&& __t) + { + *__o = std::forward<_Tp>(__t); + *std::forward<_Out>(__o) = std::forward<_Tp>(__t); + const_cast&&>(*__o) + = std::forward<_Tp>(__t); + const_cast&&>(*std::forward<_Out>(__o)) + = std::forward<_Tp>(__t); + }; + + namespace ranges::__detail + { +#if __SIZEOF_INT128__ + using __max_diff_type = __int128; + using __max_size_type = unsigned __int128; +#else + using __max_diff_type = long long; + using __max_size_type = unsigned long long; +#endif + + template + concept __is_integer_like = integral<_Tp> + || same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>; + + template + concept __is_signed_integer_like = signed_integral<_Tp> + || same_as<_Tp, __max_diff_type>; + + } // namespace ranges::__detail + + namespace __detail { using ranges::__detail::__is_signed_integer_like; } + + /// Requirements on types that can be incremented with ++. + template + concept weakly_incrementable = default_initializable<_Iter> + && movable<_Iter> + && requires(_Iter __i) + { + typename iter_difference_t<_Iter>; + requires __detail::__is_signed_integer_like>; + { ++__i } -> same_as<_Iter&>; + __i++; + }; + + template + concept incrementable = regular<_Iter> && weakly_incrementable<_Iter> + && requires(_Iter __i) { { __i++ } -> same_as<_Iter>; }; + + template + concept input_or_output_iterator + = requires(_Iter __i) { { *__i } -> __detail::__can_reference; } + && weakly_incrementable<_Iter>; + + template + concept sentinel_for = semiregular<_Sent> + && input_or_output_iterator<_Iter> + && __detail::__weakly_eq_cmp_with<_Sent, _Iter>; + + template + inline constexpr bool disable_sized_sentinel_for = false; + + template + concept sized_sentinel_for = sentinel_for<_Sent, _Iter> + && !disable_sized_sentinel_for, remove_cv_t<_Iter>> + && requires(const _Iter& __i, const _Sent& __s) + { + { __s - __i } -> same_as>; + { __i - __s } -> same_as>; + }; + + template + concept input_iterator = input_or_output_iterator<_Iter> + && indirectly_readable<_Iter> + && requires { typename __detail::__iter_concept<_Iter>; } + && derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>; + + template + concept output_iterator = input_or_output_iterator<_Iter> + && indirectly_writable<_Iter, _Tp> + && requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); }; + + template + concept forward_iterator = input_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, forward_iterator_tag> + && incrementable<_Iter> && sentinel_for<_Iter, _Iter>; + + template + concept bidirectional_iterator = forward_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, + bidirectional_iterator_tag> + && requires(_Iter __i) + { + { --__i } -> same_as<_Iter&>; + { __i-- } -> same_as<_Iter>; + }; + + template + concept random_access_iterator = bidirectional_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, + random_access_iterator_tag> + && totally_ordered<_Iter> && sized_sentinel_for<_Iter, _Iter> + && requires(_Iter __i, const _Iter __j, + const iter_difference_t<_Iter> __n) + { + { __i += __n } -> same_as<_Iter&>; + { __j + __n } -> same_as<_Iter>; + { __n + __j } -> same_as<_Iter>; + { __i -= __n } -> same_as<_Iter&>; + { __j - __n } -> same_as<_Iter>; + { __j[__n] } -> same_as>; + }; + + template + concept contiguous_iterator = random_access_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, contiguous_iterator_tag> + && is_lvalue_reference_v> + && same_as, remove_cvref_t>> + && requires(const _Iter& __i) + { + { std::to_address(__i) } + -> same_as>>; + }; + + // [indirectcallable], indirect callable requirements + + // [indirectcallable.indirectinvocable], indirect callables + + template + concept indirectly_unary_invocable = indirectly_readable<_Iter> + && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&> + && invocable<_Fn&, iter_reference_t<_Iter>> + && invocable<_Fn&, iter_common_reference_t<_Iter>> + && common_reference_with&>, + invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; + + template + concept indirectly_regular_unary_invocable = indirectly_readable<_Iter> + && copy_constructible<_Fn> + && regular_invocable<_Fn&, iter_value_t<_Iter>&> + && regular_invocable<_Fn&, iter_reference_t<_Iter>> + && regular_invocable<_Fn&, iter_common_reference_t<_Iter>> + && common_reference_with&>, + invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; + + template + concept indirect_unary_predicate = indirectly_readable<_Iter> + && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&> + && predicate<_Fn&, iter_reference_t<_Iter>> + && predicate<_Fn&, iter_common_reference_t<_Iter>>; + + template + concept indirect_binary_predicate + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && predicate<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>> + && predicate<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + concept indirect_equivalence_relation + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && equivalence_relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && equivalence_relation<_Fn&, iter_reference_t<_I1>, + iter_reference_t<_I2>> + && equivalence_relation<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + concept indirect_strict_weak_order + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>> + && strict_weak_order<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + requires (indirectly_readable<_Is> && ...) + && invocable<_Fn, iter_reference_t<_Is>...> + using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>; + + /// [projected], projected + template _Proj> + struct projected + { + using value_type = remove_cvref_t>; + + indirect_result_t<_Proj&, _Iter> operator*() const; // not defined + }; + + template + struct incrementable_traits> + { using difference_type = iter_difference_t<_Iter>; }; + + // [alg.req], common algorithm requirements + + /// [alg.req.ind.move], concept `indirectly_movable` + + template + concept indirectly_movable = indirectly_readable<_In> + && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; + + template + concept indirectly_movable_storable = indirectly_movable<_In, _Out> + && indirectly_writable<_Out, iter_value_t<_In>> + && movable> + && constructible_from, iter_rvalue_reference_t<_In>> + && assignable_from&, iter_rvalue_reference_t<_In>>; + + /// [alg.req.ind.copy], concept `indirectly_copyable` + template + concept indirectly_copyable = indirectly_readable<_In> + && indirectly_writable<_Out, iter_reference_t<_In>>; + + template + concept indirectly_copyable_storable = indirectly_copyable<_In, _Out> + && indirectly_writable<_Out, iter_value_t<_In>&> + && indirectly_writable<_Out, const iter_value_t<_In>&> + && indirectly_writable<_Out, iter_value_t<_In>&&> + && indirectly_writable<_Out, const iter_value_t<_In>&&> + && copyable> + && constructible_from, iter_reference_t<_In>> + && assignable_from&, iter_reference_t<_In>>; + +namespace ranges +{ + namespace __cust_iswap + { + template + void iter_swap(_It1, _It2) = delete; + + template + concept __adl_iswap + = (std::__detail::__class_or_enum> + || std::__detail::__class_or_enum>) + && requires(_Tp&& __t, _Up&& __u) { + iter_swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + }; + + template + constexpr iter_value_t<_Xp> + __iter_exchange_move(_Xp&& __x, _Yp&& __y) + noexcept(noexcept(iter_value_t<_Xp>(iter_move(__x))) + && noexcept(*__x = iter_move(__y))) + { + iter_value_t<_Xp> __old_value(iter_move(__x)); + *__x = iter_move(__y); + return __old_value; + } + + struct _IterSwap + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_iswap<_Tp, _Up>) + return noexcept(iter_swap(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (indirectly_readable<_Tp> + && indirectly_readable<_Up> + && swappable_with, iter_reference_t<_Up>>) + return noexcept(ranges::swap(*std::declval<_Tp>(), + *std::declval<_Up>())); + else + return noexcept(*std::declval<_Tp>() + = __iter_exchange_move(std::declval<_Up>(), + std::declval<_Tp>())); + } + + public: + template + requires __adl_iswap<_Tp, _Up> + || (indirectly_readable> + && indirectly_readable> + && swappable_with, iter_reference_t<_Up>>) + || (indirectly_movable_storable<_Tp, _Up> + && indirectly_movable_storable<_Up, _Tp>) + constexpr void + operator()(_Tp&& __e1, _Up&& __e2) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__adl_iswap<_Tp, _Up>) + iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2)); + else if constexpr (indirectly_readable<_Tp> + && indirectly_readable<_Up> + && swappable_with, iter_reference_t<_Up>>) + ranges::swap(*__e1, *__e2); + else + *__e1 = __iter_exchange_move(__e2, __e1); + } + }; + } // namespace __cust_iswap + + inline namespace __cust + { + inline constexpr __cust_iswap::_IterSwap iter_swap{}; + } // inline namespace __cust + +} // namespace ranges + + /// [alg.req.ind.swap], concept `indirectly_swappable` + template + concept indirectly_swappable + = indirectly_readable<_I1> && indirectly_readable<_I2> + && requires(const _I1 __i1, const _I2 __i2) + { + ranges::iter_swap(__i1, __i1); + ranges::iter_swap(__i2, __i2); + ranges::iter_swap(__i1, __i2); + ranges::iter_swap(__i2, __i1); + }; + + /// [alg.req.ind.cmp], concept `indirectly_comparable` + template + concept indirectly_comparable + = indirect_binary_predicate<_Rel, projected<_I1, _P1>, + projected<_I2, _P2>>; + + /// [alg.req.permutable], concept `permutable` + template + concept permutable = forward_iterator<_Iter> + && indirectly_movable_storable<_Iter, _Iter> + && indirectly_swappable<_Iter, _Iter>; + + /// [alg.req.mergeable], concept `mergeable` + template + concept mergeable = input_iterator<_I1> && input_iterator<_I2> + && weakly_incrementable<_Out> && indirectly_copyable<_I1, _Out> + && indirectly_copyable<_I2, _Out> + && indirect_strict_weak_order<_Rel, projected<_I1, _P1>, + projected<_I2, _P2>>; + + /// [alg.req.sortable], concept `sortable` + template + concept sortable = permutable<_Iter> + && indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>; + + struct unreachable_sentinel_t + { + template + friend constexpr bool + operator==(unreachable_sentinel_t, const _It&) noexcept + { return false; } + }; + + inline constexpr unreachable_sentinel_t unreachable_sentinel{}; + + struct default_sentinel_t { }; + inline constexpr default_sentinel_t default_sentinel{}; + + namespace __detail + { + template + constexpr decay_t<_Tp> + __decay_copy(_Tp&& __t) + noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) + { return std::forward<_Tp>(__t); } + + template + concept __member_begin = requires(_Tp& __t) + { + { __detail::__decay_copy(__t.begin()) } -> input_or_output_iterator; + }; + + void begin(auto&) = delete; + void begin(const auto&) = delete; + + template + concept __adl_begin = __class_or_enum> + && requires(_Tp& __t) + { + { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator; + }; + + // Simplified version of std::ranges::begin that only supports lvalues, + // for use by __range_iter_t below. + template + requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&> + auto + __ranges_begin(_Tp& __t) + { + if constexpr (is_array_v<_Tp>) + { + static_assert(sizeof(remove_all_extents_t<_Tp>) != 0, + "not array of incomplete type"); + return __t + 0; + } + else if constexpr (__member_begin<_Tp&>) + return __t.begin(); + else + return begin(__t); + } + + // Implementation of std::ranges::iterator_t, without using ranges::begin. + template + using __range_iter_t + = decltype(__detail::__ranges_begin(std::declval<_Tp&>())); + + } // namespace __detail + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 library concepts +#endif // _ITERATOR_CONCEPTS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/list.tcc b/resources/sources/avr-libstdcpp/include/bits/list.tcc new file mode 100644 index 000000000..ce9e983c5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/list.tcc @@ -0,0 +1,633 @@ +// List implementation (out of line) -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/list.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{list} + */ + +#ifndef _LIST_TCC +#define _LIST_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + void + _List_base<_Tp, _Alloc>:: + _M_clear() _GLIBCXX_NOEXCEPT + { + typedef _List_node<_Tp> _Node; + __detail::_List_node_base* __cur = _M_impl._M_node._M_next; + while (__cur != &_M_impl._M_node) + { + _Node* __tmp = static_cast<_Node*>(__cur); + __cur = __tmp->_M_next; + _Tp* __val = __tmp->_M_valptr(); +#if __cplusplus >= 201103L + _Node_alloc_traits::destroy(_M_get_Node_allocator(), __val); +#else + _Tp_alloc_type(_M_get_Node_allocator()).destroy(__val); +#endif + _M_put_node(__tmp); + } + } + +#if __cplusplus >= 201103L + template + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: + emplace(const_iterator __position, _Args&&... __args) + { + _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...); + __tmp->_M_hook(__position._M_const_cast()._M_node); + this->_M_inc_size(1); + return iterator(__tmp); + } +#endif + + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { + _Node* __tmp = _M_create_node(__x); + __tmp->_M_hook(__position._M_const_cast()._M_node); + this->_M_inc_size(1); + return iterator(__tmp); + } + +#if __cplusplus >= 201103L + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: + insert(const_iterator __position, size_type __n, const value_type& __x) + { + if (__n) + { + list __tmp(__n, __x, get_allocator()); + iterator __it = __tmp.begin(); + splice(__position, __tmp); + return __it; + } + return __position._M_const_cast(); + } + + template + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: + insert(const_iterator __position, _InputIterator __first, + _InputIterator __last) + { + list __tmp(__first, __last, get_allocator()); + if (!__tmp.empty()) + { + iterator __it = __tmp.begin(); + splice(__position, __tmp); + return __it; + } + return __position._M_const_cast(); + } +#endif + + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + erase(const_iterator __position) noexcept +#else + erase(iterator __position) +#endif + { + iterator __ret = iterator(__position._M_node->_M_next); + _M_erase(__position._M_const_cast()); + return __ret; + } + + // Return a const_iterator indicating the position to start inserting or + // erasing elements (depending whether the list is growing or shrinking), + // and set __new_size to the number of new elements that must be appended. + // Equivalent to the following, but performed optimally: + // if (__new_size < size()) { + // __new_size = 0; + // return std::next(begin(), __new_size); + // } else { + // __newsize -= size(); + // return end(); + // } + template + typename list<_Tp, _Alloc>::const_iterator + list<_Tp, _Alloc>:: + _M_resize_pos(size_type& __new_size) const + { + const_iterator __i; +#if _GLIBCXX_USE_CXX11_ABI + const size_type __len = size(); + if (__new_size < __len) + { + if (__new_size <= __len / 2) + { + __i = begin(); + std::advance(__i, __new_size); + } + else + { + __i = end(); + ptrdiff_t __num_erase = __len - __new_size; + std::advance(__i, -__num_erase); + } + __new_size = 0; + return __i; + } + else + __i = end(); +#else + size_type __len = 0; + for (__i = begin(); __i != end() && __len < __new_size; ++__i, ++__len) + ; +#endif + __new_size -= __len; + return __i; + } + +#if __cplusplus >= 201103L + template + void + list<_Tp, _Alloc>:: + _M_default_append(size_type __n) + { + size_type __i = 0; + __try + { + for (; __i < __n; ++__i) + emplace_back(); + } + __catch(...) + { + for (; __i; --__i) + pop_back(); + __throw_exception_again; + } + } + + template + void + list<_Tp, _Alloc>:: + resize(size_type __new_size) + { + const_iterator __i = _M_resize_pos(__new_size); + if (__new_size) + _M_default_append(__new_size); + else + erase(__i, end()); + } + + template + void + list<_Tp, _Alloc>:: + resize(size_type __new_size, const value_type& __x) + { + const_iterator __i = _M_resize_pos(__new_size); + if (__new_size) + insert(end(), __new_size, __x); + else + erase(__i, end()); + } +#else + template + void + list<_Tp, _Alloc>:: + resize(size_type __new_size, value_type __x) + { + const_iterator __i = _M_resize_pos(__new_size); + if (__new_size) + insert(end(), __new_size, __x); + else + erase(__i._M_const_cast(), end()); + } +#endif + + template + list<_Tp, _Alloc>& + list<_Tp, _Alloc>:: + operator=(const list& __x) + { + if (this != std::__addressof(__x)) + { +#if __cplusplus >= 201103L + if (_Node_alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_get_Node_allocator(); + auto& __that_alloc = __x._M_get_Node_allocator(); + if (!_Node_alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // replacement allocator cannot free existing storage + clear(); + } + std::__alloc_on_copy(__this_alloc, __that_alloc); + } +#endif + _M_assign_dispatch(__x.begin(), __x.end(), __false_type()); + } + return *this; + } + + template + void + list<_Tp, _Alloc>:: + _M_fill_assign(size_type __n, const value_type& __val) + { + iterator __i = begin(); + for (; __i != end() && __n > 0; ++__i, --__n) + *__i = __val; + if (__n > 0) + insert(end(), __n, __val); + else + erase(__i, end()); + } + + template + template + void + list<_Tp, _Alloc>:: + _M_assign_dispatch(_InputIterator __first2, _InputIterator __last2, + __false_type) + { + iterator __first1 = begin(); + iterator __last1 = end(); + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + *__first1 = *__first2; + if (__first2 == __last2) + erase(__first1, __last1); + else + insert(__last1, __first2, __last2); + } + +#if __cplusplus > 201703L +# define _GLIBCXX20_ONLY(__expr) __expr +#else +# define _GLIBCXX20_ONLY(__expr) +#endif + + template + typename list<_Tp, _Alloc>::__remove_return_type + list<_Tp, _Alloc>:: + remove(const value_type& __value) + { + size_type __removed __attribute__((__unused__)) = 0; + iterator __first = begin(); + iterator __last = end(); + iterator __extra = __last; + while (__first != __last) + { + iterator __next = __first; + ++__next; + if (*__first == __value) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 526. Is it undefined if a function in the standard changes + // in parameters? + if (std::__addressof(*__first) != std::__addressof(__value)) + { + _M_erase(__first); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __extra = __first; + } + __first = __next; + } + if (__extra != __last) + { + _M_erase(__extra); + _GLIBCXX20_ONLY( __removed++ ); + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + typename list<_Tp, _Alloc>::__remove_return_type + list<_Tp, _Alloc>:: + unique() + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return _GLIBCXX20_ONLY( 0 ); + size_type __removed __attribute__((__unused__)) = 0; + iterator __next = __first; + while (++__next != __last) + { + if (*__first == *__next) + { + _M_erase(__next); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __first = __next; + __next = __first; + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + void + list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + merge(list&& __x) +#else + merge(list& __x) +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 300. list::merge() specification incomplete + if (this != std::__addressof(__x)) + { + _M_check_equal_allocators(__x); + + iterator __first1 = begin(); + iterator __last1 = end(); + iterator __first2 = __x.begin(); + iterator __last2 = __x.end(); + const size_t __orig_size = __x.size(); + __try { + while (__first1 != __last1 && __first2 != __last2) + if (*__first2 < *__first1) + { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); + + this->_M_inc_size(__x._M_get_size()); + __x._M_set_size(0); + } + __catch(...) + { + const size_t __dist = std::distance(__first2, __last2); + this->_M_inc_size(__orig_size - __dist); + __x._M_set_size(__dist); + __throw_exception_again; + } + } + } + + template + template + void + list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + merge(list&& __x, _StrictWeakOrdering __comp) +#else + merge(list& __x, _StrictWeakOrdering __comp) +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 300. list::merge() specification incomplete + if (this != std::__addressof(__x)) + { + _M_check_equal_allocators(__x); + + iterator __first1 = begin(); + iterator __last1 = end(); + iterator __first2 = __x.begin(); + iterator __last2 = __x.end(); + const size_t __orig_size = __x.size(); + __try + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first2, *__first1)) + { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); + + this->_M_inc_size(__x._M_get_size()); + __x._M_set_size(0); + } + __catch(...) + { + const size_t __dist = std::distance(__first2, __last2); + this->_M_inc_size(__orig_size - __dist); + __x._M_set_size(__dist); + __throw_exception_again; + } + } + } + + template + void + list<_Tp, _Alloc>:: + sort() + { + // Do nothing if the list has length 0 or 1. + if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node + && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) + { + list __carry; + list __tmp[64]; + list * __fill = __tmp; + list * __counter; + __try + { + do + { + __carry.splice(__carry.begin(), *this, begin()); + + for(__counter = __tmp; + __counter != __fill && !__counter->empty(); + ++__counter) + { + __counter->merge(__carry); + __carry.swap(*__counter); + } + __carry.swap(*__counter); + if (__counter == __fill) + ++__fill; + } + while ( !empty() ); + + for (__counter = __tmp + 1; __counter != __fill; ++__counter) + __counter->merge(*(__counter - 1)); + swap( *(__fill - 1) ); + } + __catch(...) + { + this->splice(this->end(), __carry); + for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i) + this->splice(this->end(), __tmp[__i]); + __throw_exception_again; + } + } + } + + template + template + typename list<_Tp, _Alloc>::__remove_return_type + list<_Tp, _Alloc>:: + remove_if(_Predicate __pred) + { + size_type __removed __attribute__((__unused__)) = 0; + iterator __first = begin(); + iterator __last = end(); + while (__first != __last) + { + iterator __next = __first; + ++__next; + if (__pred(*__first)) + { + _M_erase(__first); + _GLIBCXX20_ONLY( __removed++ ); + } + __first = __next; + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + template + typename list<_Tp, _Alloc>::__remove_return_type + list<_Tp, _Alloc>:: + unique(_BinaryPredicate __binary_pred) + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return _GLIBCXX20_ONLY(0); + size_type __removed __attribute__((__unused__)) = 0; + iterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(*__first, *__next)) + { + _M_erase(__next); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __first = __next; + __next = __first; + } + return _GLIBCXX20_ONLY( __removed ); + } + +#undef _GLIBCXX20_ONLY + + template + template + void + list<_Tp, _Alloc>:: + sort(_StrictWeakOrdering __comp) + { + // Do nothing if the list has length 0 or 1. + if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node + && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) + { + list __carry; + list __tmp[64]; + list * __fill = __tmp; + list * __counter; + __try + { + do + { + __carry.splice(__carry.begin(), *this, begin()); + + for(__counter = __tmp; + __counter != __fill && !__counter->empty(); + ++__counter) + { + __counter->merge(__carry, __comp); + __carry.swap(*__counter); + } + __carry.swap(*__counter); + if (__counter == __fill) + ++__fill; + } + while ( !empty() ); + + for (__counter = __tmp + 1; __counter != __fill; ++__counter) + __counter->merge(*(__counter - 1), __comp); + swap(*(__fill - 1)); + } + __catch(...) + { + this->splice(this->end(), __carry); + for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i) + this->splice(this->end(), __tmp[__i]); + __throw_exception_again; + } + } + } + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _LIST_TCC */ + diff --git a/resources/sources/avr-libstdcpp/include/bits/mask_array.h b/resources/sources/avr-libstdcpp/include/bits/mask_array.h new file mode 100644 index 000000000..579cd59e5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/mask_array.h @@ -0,0 +1,213 @@ +// The template and inlines for the -*- C++ -*- mask_array class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/mask_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _MASK_ARRAY_H +#define _MASK_ARRAY_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Reference to selected subset of an array. + * + * A mask_array is a reference to the actual elements of an array specified + * by a bitmask in the form of an array of bool. The way to get a + * mask_array is to call operator[](valarray) on a valarray. The + * returned mask_array then permits carrying operations out on the + * referenced subset of elements in the original valarray. + * + * For example, if a mask_array is obtained using the array (false, true, + * false, true) as an argument, the mask array has two elements referring + * to array[1] and array[3] in the underlying array. + * + * @param Tp Element type. + */ + template + class mask_array + { + public: + typedef _Tp value_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 253. valarray helper functions are almost entirely useless + + /// Copy constructor. Both slices refer to the same underlying array. + mask_array (const mask_array&); + + /// Assignment operator. Assigns elements to corresponding elements + /// of @a a. + mask_array& operator=(const mask_array&); + + void operator=(const valarray<_Tp>&) const; + /// Multiply slice elements by corresponding elements of @a v. + void operator*=(const valarray<_Tp>&) const; + /// Divide slice elements by corresponding elements of @a v. + void operator/=(const valarray<_Tp>&) const; + /// Modulo slice elements by corresponding elements of @a v. + void operator%=(const valarray<_Tp>&) const; + /// Add corresponding elements of @a v to slice elements. + void operator+=(const valarray<_Tp>&) const; + /// Subtract corresponding elements of @a v from slice elements. + void operator-=(const valarray<_Tp>&) const; + /// Logical xor slice elements with corresponding elements of @a v. + void operator^=(const valarray<_Tp>&) const; + /// Logical and slice elements with corresponding elements of @a v. + void operator&=(const valarray<_Tp>&) const; + /// Logical or slice elements with corresponding elements of @a v. + void operator|=(const valarray<_Tp>&) const; + /// Left shift slice elements by corresponding elements of @a v. + void operator<<=(const valarray<_Tp>&) const; + /// Right shift slice elements by corresponding elements of @a v. + void operator>>=(const valarray<_Tp>&) const; + /// Assign all slice elements to @a t. + void operator=(const _Tp&) const; + + // ~mask_array (); + + template + void operator=(const _Expr<_Dom,_Tp>&) const; + template + void operator*=(const _Expr<_Dom,_Tp>&) const; + template + void operator/=(const _Expr<_Dom,_Tp>&) const; + template + void operator%=(const _Expr<_Dom,_Tp>&) const; + template + void operator+=(const _Expr<_Dom,_Tp>&) const; + template + void operator-=(const _Expr<_Dom,_Tp>&) const; + template + void operator^=(const _Expr<_Dom,_Tp>&) const; + template + void operator&=(const _Expr<_Dom,_Tp>&) const; + template + void operator|=(const _Expr<_Dom,_Tp>&) const; + template + void operator<<=(const _Expr<_Dom,_Tp>&) const; + template + void operator>>=(const _Expr<_Dom,_Tp>&) const; + + private: + mask_array(_Array<_Tp>, size_t, _Array); + friend class valarray<_Tp>; + + const size_t _M_sz; + const _Array _M_mask; + const _Array<_Tp> _M_array; + +#if __cplusplus < 201103L + // not implemented + mask_array(); +#else + public: + mask_array() = delete; +#endif + }; + + template + inline mask_array<_Tp>::mask_array(const mask_array<_Tp>& __a) + : _M_sz(__a._M_sz), _M_mask(__a._M_mask), _M_array(__a._M_array) {} + + template + inline + mask_array<_Tp>::mask_array(_Array<_Tp> __a, size_t __s, _Array __m) + : _M_sz(__s), _M_mask(__m), _M_array(__a) {} + + template + inline mask_array<_Tp>& + mask_array<_Tp>::operator=(const mask_array<_Tp>& __a) + { + std::__valarray_copy(__a._M_array, __a._M_mask, + _M_sz, _M_array, _M_mask); + return *this; + } + + template + inline void + mask_array<_Tp>::operator=(const _Tp& __t) const + { std::__valarray_fill(_M_array, _M_sz, _M_mask, __t); } + + template + inline void + mask_array<_Tp>::operator=(const valarray<_Tp>& __v) const + { std::__valarray_copy(_Array<_Tp>(__v), __v.size(), _M_array, _M_mask); } + + template + template + inline void + mask_array<_Tp>::operator=(const _Expr<_Ex, _Tp>& __e) const + { std::__valarray_copy(__e, __e.size(), _M_array, _M_mask); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ + template \ + inline void \ + mask_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ + { \ + _Array_augmented_##_Name(_M_array, _M_mask, \ + _Array<_Tp>(__v), __v.size()); \ + } \ + \ + template \ + template \ + inline void \ + mask_array<_Tp>::operator _Op##=(const _Expr<_Dom, _Tp>& __e) const\ + { \ + _Array_augmented_##_Name(_M_array, _M_mask, __e, __e.size()); \ + } + +_DEFINE_VALARRAY_OPERATOR(*, __multiplies) +_DEFINE_VALARRAY_OPERATOR(/, __divides) +_DEFINE_VALARRAY_OPERATOR(%, __modulus) +_DEFINE_VALARRAY_OPERATOR(+, __plus) +_DEFINE_VALARRAY_OPERATOR(-, __minus) +_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) +_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) +_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) +_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _MASK_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h b/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h new file mode 100644 index 000000000..af1a1c69c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h @@ -0,0 +1,82 @@ +// Forward declarations -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/memoryfwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _MEMORYFWD_H +#define _MEMORYFWD_H 1 + +#pragma GCC system_header + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup allocators Allocators + * @ingroup memory + * + * Classes encapsulating memory operations. + * + * @{ + */ + + template + class allocator; + +#if __cplusplus <= 201703L + template<> + class allocator; +#endif + +#if __cplusplus >= 201103L + /// Declare uses_allocator so it can be specialized in \ etc. + template + struct uses_allocator; +#endif + + /// @} group memory + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/move.h b/resources/sources/avr-libstdcpp/include/bits/move.h new file mode 100644 index 000000000..5a4dbdc82 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/move.h @@ -0,0 +1,224 @@ +// Move, forward and identity for C++11 + swap -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/move.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + */ + +#ifndef _MOVE_H +#define _MOVE_H 1 + +#include +#if __cplusplus < 201103L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Used, in C++03 mode too, by allocators, etc. + /** + * @brief Same as C++11 std::addressof + * @ingroup utilities + */ + template + inline _GLIBCXX_CONSTEXPR _Tp* + __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT + { return __builtin_addressof(__r); } + +#if __cplusplus >= 201103L + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#include // Brings in std::declval too. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Forward an lvalue. + * @return The parameter cast to the specified type. + * + * This function is used to implement "perfect forwarding". + */ + template + constexpr _Tp&& + forward(typename std::remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Tp&&>(__t); } + + /** + * @brief Forward an rvalue. + * @return The parameter cast to the specified type. + * + * This function is used to implement "perfect forwarding". + */ + template + constexpr _Tp&& + forward(typename std::remove_reference<_Tp>::type&& __t) noexcept + { + static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" + " substituting _Tp is an lvalue reference type"); + return static_cast<_Tp&&>(__t); + } + + /** + * @brief Convert a value to an rvalue. + * @param __t A thing of arbitrary type. + * @return The parameter cast to an rvalue-reference to allow moving it. + */ + template + constexpr typename std::remove_reference<_Tp>::type&& + move(_Tp&& __t) noexcept + { return static_cast::type&&>(__t); } + + + template + struct __move_if_noexcept_cond + : public __and_<__not_>, + is_copy_constructible<_Tp>>::type { }; + + /** + * @brief Conditionally convert a value to an rvalue. + * @param __x A thing of arbitrary type. + * @return The parameter, possibly cast to an rvalue-reference. + * + * Same as std::move unless the type's move constructor could throw and the + * type is copyable, in which case an lvalue-reference is returned instead. + */ + template + constexpr typename + conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type + move_if_noexcept(_Tp& __x) noexcept + { return std::move(__x); } + + // declval, from type_traits. + +#if __cplusplus > 201402L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2296. std::addressof should be constexpr +# define __cpp_lib_addressof_constexpr 201603 +#endif + /** + * @brief Returns the actual address of the object or function + * referenced by r, even in the presence of an overloaded + * operator&. + * @param __r Reference to an object or function. + * @return The actual address. + */ + template + inline _GLIBCXX17_CONSTEXPR _Tp* + addressof(_Tp& __r) noexcept + { return std::__addressof(__r); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2598. addressof works on temporaries + template + const _Tp* addressof(const _Tp&&) = delete; + + // C++11 version of std::exchange for internal use. + template + _GLIBCXX20_CONSTEXPR + inline _Tp + __exchange(_Tp& __obj, _Up&& __new_val) + { + _Tp __old_val = std::move(__obj); + __obj = std::forward<_Up>(__new_val); + return __old_val; + } + + /// @} group utilities + +#define _GLIBCXX_MOVE(__val) std::move(__val) +#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val) +#else +#define _GLIBCXX_MOVE(__val) (__val) +#define _GLIBCXX_FORWARD(_Tp, __val) (__val) +#endif + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Swaps two values. + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return Nothing. + */ + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus >= 201103L + typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>, + is_move_constructible<_Tp>, + is_move_assignable<_Tp>>::value>::type +#else + void +#endif + swap(_Tp& __a, _Tp& __b) + _GLIBCXX_NOEXCEPT_IF(__and_, + is_nothrow_move_assignable<_Tp>>::value) + { +#if __cplusplus < 201103L + // concept requirements + __glibcxx_function_requires(_SGIAssignableConcept<_Tp>) +#endif + _Tp __tmp = _GLIBCXX_MOVE(__a); + __a = _GLIBCXX_MOVE(__b); + __b = _GLIBCXX_MOVE(__tmp); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 809. std::swap should be overloaded for array types. + /// Swap the contents of two arrays. + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus >= 201103L + typename enable_if<__is_swappable<_Tp>::value>::type +#else + void +#endif + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Tp>::value) + { + for (size_t __n = 0; __n < _Nm; ++__n) + swap(__a[__n], __b[__n]); + } + + /// @} group utilities +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _MOVE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/node_handle.h b/resources/sources/avr-libstdcpp/include/bits/node_handle.h new file mode 100644 index 000000000..cbf95f045 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/node_handle.h @@ -0,0 +1,299 @@ +// Node handles for containers -*- C++ -*- + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/node_handle.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + * @headername{map,set,unordered_map,unordered_set} + */ + +#ifndef _NODE_HANDLE +#define _NODE_HANDLE 1 + +#pragma GCC system_header + +#if __cplusplus > 201402L +# define __cpp_lib_node_extract 201606 + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Base class for node handle types of maps and sets. + template + class _Node_handle_common + { + using _AllocTraits = allocator_traits<_NodeAlloc>; + + public: + using allocator_type = __alloc_rebind<_NodeAlloc, _Val>; + + allocator_type + get_allocator() const noexcept + { + __glibcxx_assert(!this->empty()); + return allocator_type(*_M_alloc); + } + + explicit operator bool() const noexcept { return _M_ptr != nullptr; } + + [[nodiscard]] bool empty() const noexcept { return _M_ptr == nullptr; } + + protected: + constexpr _Node_handle_common() noexcept : _M_ptr(), _M_alloc() {} + + ~_Node_handle_common() { _M_destroy(); } + + _Node_handle_common(_Node_handle_common&& __nh) noexcept + : _M_ptr(__nh._M_ptr), _M_alloc(std::move(__nh._M_alloc)) + { + __nh._M_ptr = nullptr; + __nh._M_alloc = nullopt; + } + + _Node_handle_common& + operator=(_Node_handle_common&& __nh) noexcept + { + _M_destroy(); + _M_ptr = __nh._M_ptr; + if constexpr (is_move_assignable_v<_NodeAlloc>) + { + if (_AllocTraits::propagate_on_container_move_assignment::value + || !this->_M_alloc) + this->_M_alloc = std::move(__nh._M_alloc); + else + { + __glibcxx_assert(this->_M_alloc == __nh._M_alloc); + } + } + else + { + __glibcxx_assert(_M_alloc); + } + __nh._M_ptr = nullptr; + __nh._M_alloc = nullopt; + return *this; + } + + _Node_handle_common(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _M_ptr(__ptr), _M_alloc(__alloc) { } + + void + _M_swap(_Node_handle_common& __nh) noexcept + { + using std::swap; + swap(_M_ptr, __nh._M_ptr); + if (_AllocTraits::propagate_on_container_swap::value + || !_M_alloc || !__nh._M_alloc) + _M_alloc.swap(__nh._M_alloc); + else + { + __glibcxx_assert(_M_alloc == __nh._M_alloc); + } + } + + private: + void + _M_destroy() noexcept + { + if (_M_ptr != nullptr) + { + allocator_type __alloc(*_M_alloc); + allocator_traits::destroy(__alloc, + _M_ptr->_M_valptr()); + _AllocTraits::deallocate(*_M_alloc, _M_ptr, 1); + } + } + + protected: + typename _AllocTraits::pointer _M_ptr; + private: + optional<_NodeAlloc> _M_alloc; + + template + friend class _Rb_tree; + }; + + /// Node handle type for maps. + template + class _Node_handle : public _Node_handle_common<_Value, _NodeAlloc> + { + public: + constexpr _Node_handle() noexcept = default; + ~_Node_handle() = default; + _Node_handle(_Node_handle&&) noexcept = default; + + _Node_handle& + operator=(_Node_handle&&) noexcept = default; + + using key_type = _Key; + using mapped_type = typename _Value::second_type; + + key_type& + key() const noexcept + { + __glibcxx_assert(!this->empty()); + return *_M_pkey; + } + + mapped_type& + mapped() const noexcept + { + __glibcxx_assert(!this->empty()); + return *_M_pmapped; + } + + void + swap(_Node_handle& __nh) noexcept + { + this->_M_swap(__nh); + using std::swap; + swap(_M_pkey, __nh._M_pkey); + swap(_M_pmapped, __nh._M_pmapped); + } + + friend void + swap(_Node_handle& __x, _Node_handle& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + private: + using _AllocTraits = allocator_traits<_NodeAlloc>; + + _Node_handle(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) + { + if (__ptr) + { + auto& __key = const_cast<_Key&>(__ptr->_M_valptr()->first); + _M_pkey = _S_pointer_to(__key); + _M_pmapped = _S_pointer_to(__ptr->_M_valptr()->second); + } + else + { + _M_pkey = nullptr; + _M_pmapped = nullptr; + } + } + + template + using __pointer + = __ptr_rebind>; + + __pointer<_Key> _M_pkey = nullptr; + __pointer _M_pmapped = nullptr; + + template + __pointer<_Tp> + _S_pointer_to(_Tp& __obj) + { return pointer_traits<__pointer<_Tp>>::pointer_to(__obj); } + + const key_type& + _M_key() const noexcept { return key(); } + + template + friend class _Rb_tree; + + template + friend class _Hashtable; + }; + + /// Node handle type for sets. + template + class _Node_handle<_Value, _Value, _NodeAlloc> + : public _Node_handle_common<_Value, _NodeAlloc> + { + public: + constexpr _Node_handle() noexcept = default; + ~_Node_handle() = default; + _Node_handle(_Node_handle&&) noexcept = default; + + _Node_handle& + operator=(_Node_handle&&) noexcept = default; + + using value_type = _Value; + + value_type& + value() const noexcept + { + __glibcxx_assert(!this->empty()); + return *this->_M_ptr->_M_valptr(); + } + + void + swap(_Node_handle& __nh) noexcept + { this->_M_swap(__nh); } + + friend void + swap(_Node_handle& __x, _Node_handle& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + private: + using _AllocTraits = allocator_traits<_NodeAlloc>; + + _Node_handle(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) { } + + const value_type& + _M_key() const noexcept { return value(); } + + template + friend class _Rb_tree; + + template + friend class _Hashtable; + }; + + /// Return type of insert(node_handle&&) on unique maps/sets. + template + struct _Node_insert_return + { + _Iterator position = _Iterator(); + bool inserted = false; + _NodeHandle node; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h b/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h new file mode 100644 index 000000000..5e80907af --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h @@ -0,0 +1,294 @@ +// Components for compile-time parsing of numbers -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/parse_numbers.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{chrono} + */ + +#ifndef _GLIBCXX_PARSE_NUMBERS_H +#define _GLIBCXX_PARSE_NUMBERS_H 1 + +#pragma GCC system_header + +// From n3642.pdf except I added binary literals and digit separator '\''. + +#if __cplusplus >= 201402L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __parse_int +{ + template + struct _Digit; + + template + struct _Digit<_Base, '0'> : integral_constant + { + using __valid = true_type; + }; + + template + struct _Digit<_Base, '1'> : integral_constant + { + using __valid = true_type; + }; + + template + struct _Digit_impl : integral_constant + { + static_assert(_Base > _Val, "invalid digit"); + using __valid = true_type; + }; + + template + struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2> + { }; + + template + struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3> + { }; + + template + struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4> + { }; + + template + struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5> + { }; + + template + struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6> + { }; + + template + struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7> + { }; + + template + struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8> + { }; + + template + struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9> + { }; + + template + struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa> + { }; + + template + struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa> + { }; + + template + struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb> + { }; + + template + struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb> + { }; + + template + struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc> + { }; + + template + struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc> + { }; + + template + struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd> + { }; + + template + struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd> + { }; + + template + struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe> + { }; + + template + struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe> + { }; + + template + struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf> + { }; + + template + struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf> + { }; + + // Digit separator + template + struct _Digit<_Base, '\''> : integral_constant + { + using __valid = false_type; + }; + +//------------------------------------------------------------------------------ + + template + using __ull_constant = integral_constant; + + template + struct _Power_help + { + using __next = typename _Power_help<_Base, _Digs...>::type; + using __valid_digit = typename _Digit<_Base, _Dig>::__valid; + using type + = __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>; + }; + + template + struct _Power_help<_Base, _Dig> + { + using __valid_digit = typename _Digit<_Base, _Dig>::__valid; + using type = __ull_constant<__valid_digit::value>; + }; + + template + struct _Power : _Power_help<_Base, _Digs...>::type + { }; + + template + struct _Power<_Base> : __ull_constant<0> + { }; + +//------------------------------------------------------------------------------ + + template + struct _Number_help + { + using __digit = _Digit<_Base, _Dig>; + using __valid_digit = typename __digit::__valid; + using __next = _Number_help<_Base, + __valid_digit::value ? _Pow / _Base : _Pow, + _Digs...>; + using type = __ull_constant<_Pow * __digit::value + __next::type::value>; + static_assert((type::value / _Pow) == __digit::value, + "integer literal does not fit in unsigned long long"); + }; + + // Skip past digit separators: + template + struct _Number_help<_Base, _Pow, '\'', _Dig, _Digs...> + : _Number_help<_Base, _Pow, _Dig, _Digs...> + { }; + + // Terminating case for recursion: + template + struct _Number_help<_Base, 1ULL, _Dig> + { + using type = __ull_constant<_Digit<_Base, _Dig>::value>; + }; + + template + struct _Number + : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type + { }; + + template + struct _Number<_Base> + : __ull_constant<0> + { }; + +//------------------------------------------------------------------------------ + + template + struct _Parse_int; + + template + struct _Parse_int<'0', 'b', _Digs...> + : _Number<2U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'B', _Digs...> + : _Number<2U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'x', _Digs...> + : _Number<16U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'X', _Digs...> + : _Number<16U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', _Digs...> + : _Number<8U, _Digs...>::type + { }; + + template + struct _Parse_int + : _Number<10U, _Digs...>::type + { }; + +} // namespace __parse_int + + +namespace __select_int +{ + template + struct _Select_int_base; + + template + struct _Select_int_base<_Val, _IntType, _Ints...> + : conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max), + integral_constant<_IntType, _Val>, + _Select_int_base<_Val, _Ints...>> + { }; + + template + struct _Select_int_base<_Val> + { }; + + template + using _Select_int = typename _Select_int_base< + __parse_int::_Parse_int<_Digs...>::value, + unsigned char, + unsigned short, + unsigned int, + unsigned long, + unsigned long long + >::type; + +} // namespace __select_int + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + +#endif // _GLIBCXX_PARSE_NUMBERS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/postypes.h b/resources/sources/avr-libstdcpp/include/bits/postypes.h new file mode 100644 index 000000000..718ff4462 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/postypes.h @@ -0,0 +1,253 @@ +// Position types -*- C++ -*- + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/postypes.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +// +// ISO C++ 14882: 27.4.1 - Types +// ISO C++ 14882: 27.4.3 - Template class fpos +// + +#ifndef _GLIBCXX_POSTYPES_H +#define _GLIBCXX_POSTYPES_H 1 + +#pragma GCC system_header + +#include // For mbstate_t + +// XXX If is really needed, make sure to define the macros +// before including it, in order not to break (and +// in C++11). Reconsider all this as soon as possible... +#if (defined(_GLIBCXX_HAVE_INT64_T) && !defined(_GLIBCXX_HAVE_INT64_T_LONG) \ + && !defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)) + +#ifndef __STDC_LIMIT_MACROS +# define _UNDEF__STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define _UNDEF__STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif +#include // For int64_t +#ifdef _UNDEF__STDC_LIMIT_MACROS +# undef __STDC_LIMIT_MACROS +# undef _UNDEF__STDC_LIMIT_MACROS +#endif +#ifdef _UNDEF__STDC_CONSTANT_MACROS +# undef __STDC_CONSTANT_MACROS +# undef _UNDEF__STDC_CONSTANT_MACROS +#endif + +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // The types streamoff, streampos and wstreampos and the class + // template fpos<> are described in clauses 21.1.2, 21.1.3, 27.1.2, + // 27.2, 27.4.1, 27.4.3 and D.6. Despite all this verbiage, the + // behaviour of these types is mostly implementation defined or + // unspecified. The behaviour in this implementation is as noted + // below. + + /** + * @brief Type used by fpos, char_traits, and char_traits. + * + * In clauses 21.1.3.1 and 27.4.1 streamoff is described as an + * implementation defined type. + * Note: In versions of GCC up to and including GCC 3.3, streamoff + * was typedef long. + */ +#ifdef _GLIBCXX_HAVE_INT64_T_LONG + typedef long streamoff; +#elif defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG) + typedef long long streamoff; +#elif defined(_GLIBCXX_HAVE_INT64_T) + typedef int64_t streamoff; +#else + typedef long long streamoff; +#endif + + /// Integral type for I/O operation counts and buffer sizes. + typedef ptrdiff_t streamsize; // Signed integral type + + /** + * @brief Class representing stream positions. + * + * The standard places no requirements upon the template parameter StateT. + * In this implementation StateT must be DefaultConstructible, + * CopyConstructible and Assignable. The standard only requires that fpos + * should contain a member of type StateT. In this implementation it also + * contains an offset stored as a signed integer. + * + * @param StateT Type passed to and returned from state(). + */ + template + class fpos + { + private: + streamoff _M_off; + _StateT _M_state; + + public: + // The standard doesn't require that fpos objects can be default + // constructed. This implementation provides a default + // constructor that initializes the offset to 0 and default + // constructs the state. + fpos() + : _M_off(0), _M_state() { } + + // The standard requires that fpos objects can be constructed + // from streamoff objects using the constructor syntax, and + // fails to give any meaningful semantics. In this + // implementation implicit conversion is also allowed, and this + // constructor stores the streamoff as the offset and default + // constructs the state. + /// Construct position from offset. + fpos(streamoff __off) + : _M_off(__off), _M_state() { } + +#if __cplusplus >= 201103L + fpos(const fpos&) = default; + fpos& operator=(const fpos&) = default; + ~fpos() = default; +#endif + + /// Convert to streamoff. + operator streamoff() const { return _M_off; } + + /// Remember the value of @a st. + void + state(_StateT __st) + { _M_state = __st; } + + /// Return the last set value of @a st. + _StateT + state() const + { return _M_state; } + + // The standard requires that this operator must be defined, but + // gives no semantics. In this implementation it just adds its + // argument to the stored offset and returns *this. + /// Add offset to this position. + fpos& + operator+=(streamoff __off) + { + _M_off += __off; + return *this; + } + + // The standard requires that this operator must be defined, but + // gives no semantics. In this implementation it just subtracts + // its argument from the stored offset and returns *this. + /// Subtract offset from this position. + fpos& + operator-=(streamoff __off) + { + _M_off -= __off; + return *this; + } + + // The standard requires that this operator must be defined, but + // defines its semantics only in terms of operator-. In this + // implementation it constructs a copy of *this, adds the + // argument to that copy using operator+= and then returns the + // copy. + /// Add position and offset. + fpos + operator+(streamoff __off) const + { + fpos __pos(*this); + __pos += __off; + return __pos; + } + + // The standard requires that this operator must be defined, but + // defines its semantics only in terms of operator+. In this + // implementation it constructs a copy of *this, subtracts the + // argument from that copy using operator-= and then returns the + // copy. + /// Subtract offset from position. + fpos + operator-(streamoff __off) const + { + fpos __pos(*this); + __pos -= __off; + return __pos; + } + + // The standard requires that this operator must be defined, but + // defines its semantics only in terms of operator+. In this + // implementation it returns the difference between the offset + // stored in *this and in the argument. + /// Subtract position to return offset. + streamoff + operator-(const fpos& __other) const + { return _M_off - __other._M_off; } + }; + + // The standard only requires that operator== must be an + // equivalence relation. In this implementation two fpos + // objects belong to the same equivalence class if the contained + // offsets compare equal. + /// Test if equivalent to another position. + template + inline bool + operator==(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs) + { return streamoff(__lhs) == streamoff(__rhs); } + + template + inline bool + operator!=(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs) + { return streamoff(__lhs) != streamoff(__rhs); } + + // Clauses 21.1.3.1 and 21.1.3.2 describe streampos and wstreampos + // as implementation defined types, but clause 27.2 requires that + // they must both be typedefs for fpos + /// File position for char streams. + typedef fpos streampos; + /// File position for wchar_t streams. + typedef fpos wstreampos; + +#ifdef _GLIBCXX_USE_CHAR8_T + /// File position for char8_t streams. + typedef fpos u8streampos; +#endif + +#if __cplusplus >= 201103L + /// File position for char16_t streams. + typedef fpos u16streampos; + /// File position for char32_t streams. + typedef fpos u32streampos; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h b/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h new file mode 100644 index 000000000..7ac9a467d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h @@ -0,0 +1,405 @@ +// Default predicates for internal use -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file predefined_ops.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _GLIBCXX_PREDEFINED_OPS_H +#define _GLIBCXX_PREDEFINED_OPS_H 1 + +namespace __gnu_cxx +{ +namespace __ops +{ + struct _Iter_less_iter + { + template + _GLIBCXX14_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) const + { return *__it1 < *__it2; } + }; + + _GLIBCXX14_CONSTEXPR + inline _Iter_less_iter + __iter_less_iter() + { return _Iter_less_iter(); } + + struct _Iter_less_val + { +#if __cplusplus >= 201103L + constexpr _Iter_less_val() = default; +#else + _Iter_less_val() { } +#endif + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_less_val(_Iter_less_iter) { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) const + { return *__it < __val; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_less_val + __iter_less_val() + { return _Iter_less_val(); } + + _GLIBCXX20_CONSTEXPR + inline _Iter_less_val + __iter_comp_val(_Iter_less_iter) + { return _Iter_less_val(); } + + struct _Val_less_iter + { +#if __cplusplus >= 201103L + constexpr _Val_less_iter() = default; +#else + _Val_less_iter() { } +#endif + + _GLIBCXX20_CONSTEXPR + explicit + _Val_less_iter(_Iter_less_iter) { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Value& __val, _Iterator __it) const + { return __val < *__it; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Val_less_iter + __val_less_iter() + { return _Val_less_iter(); } + + _GLIBCXX20_CONSTEXPR + inline _Val_less_iter + __val_comp_iter(_Iter_less_iter) + { return _Val_less_iter(); } + + struct _Iter_equal_to_iter + { + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) const + { return *__it1 == *__it2; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_iter + __iter_equal_to_iter() + { return _Iter_equal_to_iter(); } + + struct _Iter_equal_to_val + { + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) const + { return *__it == __val; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_val + __iter_equal_to_val() + { return _Iter_equal_to_val(); } + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_val + __iter_comp_val(_Iter_equal_to_iter) + { return _Iter_equal_to_val(); } + + template + struct _Iter_comp_iter + { + _Compare _M_comp; + + explicit _GLIBCXX14_CONSTEXPR + _Iter_comp_iter(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + template + _GLIBCXX14_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) + { return bool(_M_comp(*__it1, *__it2)); } + }; + + template + _GLIBCXX14_CONSTEXPR + inline _Iter_comp_iter<_Compare> + __iter_comp_iter(_Compare __comp) + { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Iter_comp_val + { + _Compare _M_comp; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp) + : _M_comp(__comp._M_comp) + { } + +#if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp) + : _M_comp(std::move(__comp._M_comp)) + { } +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) + { return bool(_M_comp(*__it, __val)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_val<_Compare> + __iter_comp_val(_Compare __comp) + { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_val<_Compare> + __iter_comp_val(_Iter_comp_iter<_Compare> __comp) + { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Val_comp_iter + { + _Compare _M_comp; + + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp) + : _M_comp(__comp._M_comp) + { } + +#if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp) + : _M_comp(std::move(__comp._M_comp)) + { } +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Value& __val, _Iterator __it) + { return bool(_M_comp(__val, *__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Val_comp_iter<_Compare> + __val_comp_iter(_Compare __comp) + { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + _GLIBCXX20_CONSTEXPR + inline _Val_comp_iter<_Compare> + __val_comp_iter(_Iter_comp_iter<_Compare> __comp) + { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Iter_equals_val + { + _Value& _M_value; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_equals_val(_Value& __value) + : _M_value(__value) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return *__it == _M_value; } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_equals_val<_Value> + __iter_equals_val(_Value& __val) + { return _Iter_equals_val<_Value>(__val); } + + template + struct _Iter_equals_iter + { + _Iterator1 _M_it1; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_equals_iter(_Iterator1 __it1) + : _M_it1(__it1) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator2 __it2) + { return *__it2 == *_M_it1; } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_equals_iter<_Iterator> + __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it) + { return _Iter_equals_iter<_Iterator>(__it); } + + template + struct _Iter_pred + { + _Predicate _M_pred; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_pred(_Predicate __pred) + : _M_pred(_GLIBCXX_MOVE(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return bool(_M_pred(*__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_pred<_Predicate> + __pred_iter(_Predicate __pred) + { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); } + + template + struct _Iter_comp_to_val + { + _Compare _M_comp; + _Value& _M_value; + + _GLIBCXX20_CONSTEXPR + _Iter_comp_to_val(_Compare __comp, _Value& __value) + : _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return bool(_M_comp(*__it, _M_value)); } + }; + + template + _Iter_comp_to_val<_Compare, _Value> + _GLIBCXX20_CONSTEXPR + __iter_comp_val(_Compare __comp, _Value &__val) + { + return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val); + } + + template + struct _Iter_comp_to_iter + { + _Compare _M_comp; + _Iterator1 _M_it1; + + _GLIBCXX20_CONSTEXPR + _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1) + : _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator2 __it2) + { return bool(_M_comp(*__it2, *_M_it1)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_to_iter<_Compare, _Iterator> + __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it) + { + return _Iter_comp_to_iter<_Compare, _Iterator>( + _GLIBCXX_MOVE(__comp._M_comp), __it); + } + + template + struct _Iter_negate + { + _Predicate _M_pred; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_negate(_Predicate __pred) + : _M_pred(_GLIBCXX_MOVE(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return !bool(_M_pred(*__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_negate<_Predicate> + __negate(_Iter_pred<_Predicate> __pred) + { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); } + +} // namespace __ops +} // namespace __gnu_cxx + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h b/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h new file mode 100644 index 000000000..38f694df5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h @@ -0,0 +1,211 @@ +// Pointer Traits -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ptr_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _PTR_TRAITS_H +#define _PTR_TRAITS_H 1 + +#if __cplusplus >= 201103L + +#include + +#if __cplusplus > 201703L +#define __cpp_lib_constexpr_memory 201811L +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + class __undefined; + + // Given Template return T, otherwise invalid. + template + struct __get_first_arg + { using type = __undefined; }; + + template class _Template, typename _Tp, + typename... _Types> + struct __get_first_arg<_Template<_Tp, _Types...>> + { using type = _Tp; }; + + template + using __get_first_arg_t = typename __get_first_arg<_Tp>::type; + + // Given Template and U return Template, otherwise invalid. + template + struct __replace_first_arg + { }; + + template class _Template, typename _Up, + typename _Tp, typename... _Types> + struct __replace_first_arg<_Template<_Tp, _Types...>, _Up> + { using type = _Template<_Up, _Types...>; }; + + template + using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type; + + template + using __make_not_void + = typename conditional::value, __undefined, _Tp>::type; + + /** + * @brief Uniform interface to all pointer-like types + * @ingroup pointer_abstractions + */ + template + struct pointer_traits + { + private: + template + using __element_type = typename _Tp::element_type; + + template + using __difference_type = typename _Tp::difference_type; + + template + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + + template + struct __rebind<_Tp, _Up, __void_t>> + { using type = typename _Tp::template rebind<_Up>; }; + + public: + /// The pointer type. + using pointer = _Ptr; + + /// The type pointed to. + using element_type + = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>; + + /// The type used to represent the difference between two pointers. + using difference_type + = __detected_or_t; + + /// A pointer to a different type. + template + using rebind = typename __rebind<_Ptr, _Up>::type; + + static _Ptr + pointer_to(__make_not_void& __e) + { return _Ptr::pointer_to(__e); } + + static_assert(!is_same::value, + "pointer type defines element_type or is like SomePointer"); + }; + + /** + * @brief Partial specialization for built-in pointers. + * @ingroup pointer_abstractions + */ + template + struct pointer_traits<_Tp*> + { + /// The pointer type + typedef _Tp* pointer; + /// The type pointed to + typedef _Tp element_type; + /// Type used to represent the difference between two pointers + typedef ptrdiff_t difference_type; + + template + using rebind = _Up*; + + /** + * @brief Obtain a pointer to an object + * @param __r A reference to an object of type @c element_type + * @return @c addressof(__r) + */ + static _GLIBCXX20_CONSTEXPR pointer + pointer_to(__make_not_void& __r) noexcept + { return std::addressof(__r); } + }; + + /// Convenience alias for rebinding pointers. + template + using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; + + template + constexpr _Tp* + __to_address(_Tp* __ptr) noexcept + { + static_assert(!std::is_function<_Tp>::value, "not a function pointer"); + return __ptr; + } + +#if __cplusplus <= 201703L + template + constexpr typename std::pointer_traits<_Ptr>::element_type* + __to_address(const _Ptr& __ptr) + { return std::__to_address(__ptr.operator->()); } +#else + template + constexpr auto + __to_address(const _Ptr& __ptr) noexcept + -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) + { return std::pointer_traits<_Ptr>::to_address(__ptr); } + + template + constexpr auto + __to_address(const _Ptr& __ptr, _None...) noexcept + { + return std::__to_address(__ptr.operator->()); + } + +#define __cpp_lib_to_address 201711L + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __ptr A pointer to an object + * @return @c __ptr + * @ingroup pointer_abstractions + */ + template + constexpr _Tp* + to_address(_Tp* __ptr) noexcept + { return std::__to_address(__ptr); } + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __ptr A pointer to an object + * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is + well-formed, otherwise @c to_address(__ptr.operator->()) + * @ingroup pointer_abstractions + */ + template + constexpr auto + to_address(const _Ptr& __ptr) noexcept + { return std::__to_address(__ptr); } +#endif // C++2a + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/random.h b/resources/sources/avr-libstdcpp/include/bits/random.h new file mode 100644 index 000000000..0b0877394 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/random.h @@ -0,0 +1,5183 @@ +// random number generation -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** + * @file bits/random.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{random} + */ + +#ifndef _RANDOM_H +#define _RANDOM_H 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // [26.4] Random number generation + + /** + * @defgroup random Random Number Generation + * @ingroup numerics + * + * A facility for generating random numbers on selected distributions. + * @{ + */ + + // std::uniform_random_bit_generator is defined in + + /** + * @brief A function template for converting the output of a (integral) + * uniform random number generator to a floatng point result in the range + * [0-1). + */ + template + _RealType + generate_canonical(_UniformRandomNumberGenerator& __g); + + /* + * Implementation-space details. + */ + namespace __detail + { + template + (std::numeric_limits<_UIntType>::digits)> + struct _Shift + { static const _UIntType __value = 0; }; + + template + struct _Shift<_UIntType, __w, true> + { static const _UIntType __value = _UIntType(1) << __w; }; + + template + struct _Select_uint_least_t + { + static_assert(__which < 0, /* needs to be dependent */ + "sorry, would be too much trouble for a slow result"); + }; + + template + struct _Select_uint_least_t<__s, 4> + { typedef unsigned int type; }; + + template + struct _Select_uint_least_t<__s, 3> + { typedef unsigned long type; }; + + template + struct _Select_uint_least_t<__s, 2> + { typedef unsigned long long type; }; + +#ifdef _GLIBCXX_USE_INT128 + template + struct _Select_uint_least_t<__s, 1> + { typedef unsigned __int128 type; }; +#endif + + // Assume a != 0, a < m, c < m, x < m. + template= __m - 1), + bool __schrage_ok = __m % __a < __m / __a> + struct _Mod + { + typedef typename _Select_uint_least_t::type _Tp2; + static _Tp + __calc(_Tp __x) + { return static_cast<_Tp>((_Tp2(__a) * __x + __c) % __m); } + }; + + // Schrage. + template + struct _Mod<_Tp, __m, __a, __c, false, true> + { + static _Tp + __calc(_Tp __x); + }; + + // Special cases: + // - for m == 2^n or m == 0, unsigned integer overflow is safe. + // - a * (m - 1) + c fits in _Tp, there is no overflow. + template + struct _Mod<_Tp, __m, __a, __c, true, __s> + { + static _Tp + __calc(_Tp __x) + { + _Tp __res = __a * __x + __c; + if (__m) + __res %= __m; + return __res; + } + }; + + template + inline _Tp + __mod(_Tp __x) + { return _Mod<_Tp, __m, __a, __c>::__calc(__x); } + + /* + * An adaptor class for converting the output of any Generator into + * the input for a specific Distribution. + */ + template + struct _Adaptor + { + static_assert(std::is_floating_point<_DInputType>::value, + "template argument must be a floating point type"); + + public: + _Adaptor(_Engine& __g) + : _M_g(__g) { } + + _DInputType + min() const + { return _DInputType(0); } + + _DInputType + max() const + { return _DInputType(1); } + + /* + * Converts a value generated by the adapted random number generator + * into a value in the input domain for the dependent random number + * distribution. + */ + _DInputType + operator()() + { + return std::generate_canonical<_DInputType, + std::numeric_limits<_DInputType>::digits, + _Engine>(_M_g); + } + + private: + _Engine& _M_g; + }; + + template + using __seed_seq_generate_t = decltype( + std::declval<_Sseq&>().generate(std::declval(), + std::declval())); + + // Detect whether _Sseq is a valid seed sequence for + // a random number engine _Engine with result type _Res. + template> + using __is_seed_seq = __and_< + __not_, _Engine>>, + is_unsigned, + __not_> + >; + + } // namespace __detail + + /** + * @addtogroup random_generators Random Number Generators + * @ingroup random + * + * These classes define objects which provide random or pseudorandom + * numbers, either from a discrete or a continuous interval. The + * random number generator supplied as a part of this library are + * all uniform random number generators which provide a sequence of + * random number uniformly distributed over their range. + * + * A number generator is a function object with an operator() that + * takes zero arguments and returns a number. + * + * A compliant random number generator must satisfy the following + * requirements. + * + *
Random Number Generator Requirements
To be documented.
+ * + * @{ + */ + + /** + * @brief A model of a linear congruential random number generator. + * + * A random number generator that produces pseudorandom numbers via + * linear function: + * @f[ + * x_{i+1}\leftarrow(ax_{i} + c) \bmod m + * @f] + * + * The template parameter @p _UIntType must be an unsigned integral type + * large enough to store values up to (__m-1). If the template parameter + * @p __m is 0, the modulus @p __m used is + * std::numeric_limits<_UIntType>::max() plus 1. Otherwise, the template + * parameters @p __a and @p __c must be less than @p __m. + * + * The size of the state is @f$1@f$. + */ + template + class linear_congruential_engine + { + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); + static_assert(__m == 0u || (__a < __m && __c < __m), + "template argument substituting __m out of bounds"); + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, linear_congruential_engine, _UIntType>::value>::type; + + public: + /** The type of the generated random value. */ + typedef _UIntType result_type; + + /** The multiplier. */ + static constexpr result_type multiplier = __a; + /** An increment. */ + static constexpr result_type increment = __c; + /** The modulus. */ + static constexpr result_type modulus = __m; + static constexpr result_type default_seed = 1u; + + /** + * @brief Constructs a %linear_congruential_engine random number + * generator engine with seed 1. + */ + linear_congruential_engine() : linear_congruential_engine(default_seed) + { } + + /** + * @brief Constructs a %linear_congruential_engine random number + * generator engine with seed @p __s. The default seed value + * is 1. + * + * @param __s The initial seed value. + */ + explicit + linear_congruential_engine(result_type __s) + { seed(__s); } + + /** + * @brief Constructs a %linear_congruential_engine random number + * generator engine seeded from the seed sequence @p __q. + * + * @param __q the seed sequence. + */ + template> + explicit + linear_congruential_engine(_Sseq& __q) + { seed(__q); } + + /** + * @brief Reseeds the %linear_congruential_engine random number generator + * engine sequence to the seed @p __s. + * + * @param __s The new seed. + */ + void + seed(result_type __s = default_seed); + + /** + * @brief Reseeds the %linear_congruential_engine random number generator + * engine + * sequence using values from the seed sequence @p __q. + * + * @param __q the seed sequence. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q); + + /** + * @brief Gets the smallest possible value in the output range. + * + * The minimum depends on the @p __c parameter: if it is zero, the + * minimum generated must be > 0, otherwise 0 is allowed. + */ + static constexpr result_type + min() + { return __c == 0u ? 1u : 0u; } + + /** + * @brief Gets the largest possible value in the output range. + */ + static constexpr result_type + max() + { return __m - 1u; } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * @brief Gets the next random number in the sequence. + */ + result_type + operator()() + { + _M_x = __detail::__mod<_UIntType, __m, __a, __c>(_M_x); + return _M_x; + } + + /** + * @brief Compares two linear congruential random number generator + * objects of the same type for equality. + * + * @param __lhs A linear congruential random number generator object. + * @param __rhs Another linear congruential random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const linear_congruential_engine& __lhs, + const linear_congruential_engine& __rhs) + { return __lhs._M_x == __rhs._M_x; } + + private: + _UIntType _M_x; + }; + + /** + * @brief Compares two linear congruential random number generator + * objects of the same type for inequality. + * + * @param __lhs A linear congruential random number generator object. + * @param __rhs Another linear congruential random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::linear_congruential_engine<_UIntType, __a, + __c, __m>& __lhs, + const std::linear_congruential_engine<_UIntType, __a, + __c, __m>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * A generalized feedback shift register discrete random number generator. + * + * This algorithm avoids multiplication and division and is designed to be + * friendly to a pipelined architecture. If the parameters are chosen + * correctly, this generator will produce numbers with a very long period and + * fairly good apparent entropy, although still not cryptographically strong. + * + * The best way to use this generator is with the predefined mt19937 class. + * + * This algorithm was originally invented by Makoto Matsumoto and + * Takuji Nishimura. + * + * @tparam __w Word size, the number of bits in each element of + * the state vector. + * @tparam __n The degree of recursion. + * @tparam __m The period parameter. + * @tparam __r The separation point bit index. + * @tparam __a The last row of the twist matrix. + * @tparam __u The first right-shift tempering matrix parameter. + * @tparam __d The first right-shift tempering matrix mask. + * @tparam __s The first left-shift tempering matrix parameter. + * @tparam __b The first left-shift tempering matrix mask. + * @tparam __t The second left-shift tempering matrix parameter. + * @tparam __c The second left-shift tempering matrix mask. + * @tparam __l The second right-shift tempering matrix parameter. + * @tparam __f Initialization multiplier. + */ + template + class mersenne_twister_engine + { + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); + static_assert(1u <= __m && __m <= __n, + "template argument substituting __m out of bounds"); + static_assert(__r <= __w, "template argument substituting " + "__r out of bound"); + static_assert(__u <= __w, "template argument substituting " + "__u out of bound"); + static_assert(__s <= __w, "template argument substituting " + "__s out of bound"); + static_assert(__t <= __w, "template argument substituting " + "__t out of bound"); + static_assert(__l <= __w, "template argument substituting " + "__l out of bound"); + static_assert(__w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bound"); + static_assert(__a <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __a out of bound"); + static_assert(__b <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __b out of bound"); + static_assert(__c <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __c out of bound"); + static_assert(__d <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __d out of bound"); + static_assert(__f <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __f out of bound"); + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, mersenne_twister_engine, _UIntType>::value>::type; + + public: + /** The type of the generated random value. */ + typedef _UIntType result_type; + + // parameter values + static constexpr size_t word_size = __w; + static constexpr size_t state_size = __n; + static constexpr size_t shift_size = __m; + static constexpr size_t mask_bits = __r; + static constexpr result_type xor_mask = __a; + static constexpr size_t tempering_u = __u; + static constexpr result_type tempering_d = __d; + static constexpr size_t tempering_s = __s; + static constexpr result_type tempering_b = __b; + static constexpr size_t tempering_t = __t; + static constexpr result_type tempering_c = __c; + static constexpr size_t tempering_l = __l; + static constexpr result_type initialization_multiplier = __f; + static constexpr result_type default_seed = 5489u; + + // constructors and member functions + + mersenne_twister_engine() : mersenne_twister_engine(default_seed) { } + + explicit + mersenne_twister_engine(result_type __sd) + { seed(__sd); } + + /** + * @brief Constructs a %mersenne_twister_engine random number generator + * engine seeded from the seed sequence @p __q. + * + * @param __q the seed sequence. + */ + template> + explicit + mersenne_twister_engine(_Sseq& __q) + { seed(__q); } + + void + seed(result_type __sd = default_seed); + + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q); + + /** + * @brief Gets the smallest possible value in the output range. + */ + static constexpr result_type + min() + { return 0; } + + /** + * @brief Gets the largest possible value in the output range. + */ + static constexpr result_type + max() + { return __detail::_Shift<_UIntType, __w>::__value - 1; } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z); + + result_type + operator()(); + + /** + * @brief Compares two % mersenne_twister_engine random number generator + * objects of the same type for equality. + * + * @param __lhs A % mersenne_twister_engine random number generator + * object. + * @param __rhs Another % mersenne_twister_engine random number + * generator object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const mersenne_twister_engine& __lhs, + const mersenne_twister_engine& __rhs) + { return (std::equal(__lhs._M_x, __lhs._M_x + state_size, __rhs._M_x) + && __lhs._M_p == __rhs._M_p); } + + private: + void _M_gen_rand(); + + _UIntType _M_x[state_size]; + size_t _M_p; + }; + + /** + * @brief Compares two % mersenne_twister_engine random number generator + * objects of the same type for inequality. + * + * @param __lhs A % mersenne_twister_engine random number generator + * object. + * @param __rhs Another % mersenne_twister_engine random number + * generator object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::mersenne_twister_engine<_UIntType, __w, __n, __m, + __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __lhs, + const std::mersenne_twister_engine<_UIntType, __w, __n, __m, + __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * @brief The Marsaglia-Zaman generator. + * + * This is a model of a Generalized Fibonacci discrete random number + * generator, sometimes referred to as the SWC generator. + * + * A discrete random number generator that produces pseudorandom + * numbers using: + * @f[ + * x_{i}\leftarrow(x_{i - s} - x_{i - r} - carry_{i-1}) \bmod m + * @f] + * + * The size of the state is @f$r@f$ + * and the maximum period of the generator is @f$(m^r - m^s - 1)@f$. + */ + template + class subtract_with_carry_engine + { + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); + static_assert(0u < __s && __s < __r, + "0 < s < r"); + static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bounds"); + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, subtract_with_carry_engine, _UIntType>::value>::type; + + public: + /** The type of the generated random value. */ + typedef _UIntType result_type; + + // parameter values + static constexpr size_t word_size = __w; + static constexpr size_t short_lag = __s; + static constexpr size_t long_lag = __r; + static constexpr result_type default_seed = 19780503u; + + subtract_with_carry_engine() : subtract_with_carry_engine(default_seed) + { } + + /** + * @brief Constructs an explicitly seeded %subtract_with_carry_engine + * random number generator. + */ + explicit + subtract_with_carry_engine(result_type __sd) + { seed(__sd); } + + /** + * @brief Constructs a %subtract_with_carry_engine random number engine + * seeded from the seed sequence @p __q. + * + * @param __q the seed sequence. + */ + template> + explicit + subtract_with_carry_engine(_Sseq& __q) + { seed(__q); } + + /** + * @brief Seeds the initial state @f$x_0@f$ of the random number + * generator. + * + * N1688[4.19] modifies this as follows. If @p __value == 0, + * sets value to 19780503. In any case, with a linear + * congruential generator lcg(i) having parameters @f$ m_{lcg} = + * 2147483563, a_{lcg} = 40014, c_{lcg} = 0, and lcg(0) = value + * @f$, sets @f$ x_{-r} \dots x_{-1} @f$ to @f$ lcg(1) \bmod m + * \dots lcg(r) \bmod m @f$ respectively. If @f$ x_{-1} = 0 @f$ + * set carry to 1, otherwise sets carry to 0. + */ + void + seed(result_type __sd = default_seed); + + /** + * @brief Seeds the initial state @f$x_0@f$ of the + * % subtract_with_carry_engine random number generator. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q); + + /** + * @brief Gets the inclusive minimum value of the range of random + * integers returned by this generator. + */ + static constexpr result_type + min() + { return 0; } + + /** + * @brief Gets the inclusive maximum value of the range of random + * integers returned by this generator. + */ + static constexpr result_type + max() + { return __detail::_Shift<_UIntType, __w>::__value - 1; } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * @brief Gets the next random number in the sequence. + */ + result_type + operator()(); + + /** + * @brief Compares two % subtract_with_carry_engine random number + * generator objects of the same type for equality. + * + * @param __lhs A % subtract_with_carry_engine random number generator + * object. + * @param __rhs Another % subtract_with_carry_engine random number + * generator object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const subtract_with_carry_engine& __lhs, + const subtract_with_carry_engine& __rhs) + { return (std::equal(__lhs._M_x, __lhs._M_x + long_lag, __rhs._M_x) + && __lhs._M_carry == __rhs._M_carry + && __lhs._M_p == __rhs._M_p); } + + private: + /// The state of the generator. This is a ring buffer. + _UIntType _M_x[long_lag]; + _UIntType _M_carry; ///< The carry + size_t _M_p; ///< Current index of x(i - r). + }; + + /** + * @brief Compares two % subtract_with_carry_engine random number + * generator objects of the same type for inequality. + * + * @param __lhs A % subtract_with_carry_engine random number generator + * object. + * @param __rhs Another % subtract_with_carry_engine random number + * generator object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::subtract_with_carry_engine<_UIntType, __w, + __s, __r>& __lhs, + const std::subtract_with_carry_engine<_UIntType, __w, + __s, __r>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * Produces random numbers from some base engine by discarding blocks of + * data. + * + * 0 <= @p __r <= @p __p + */ + template + class discard_block_engine + { + static_assert(1 <= __r && __r <= __p, + "template argument substituting __r out of bounds"); + + public: + /** The type of the generated random value. */ + typedef typename _RandomNumberEngine::result_type result_type; + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, discard_block_engine, result_type>::value>::type; + + // parameter values + static constexpr size_t block_size = __p; + static constexpr size_t used_block = __r; + + /** + * @brief Constructs a default %discard_block_engine engine. + * + * The underlying engine is default constructed as well. + */ + discard_block_engine() + : _M_b(), _M_n(0) { } + + /** + * @brief Copy constructs a %discard_block_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + discard_block_engine(const _RandomNumberEngine& __rng) + : _M_b(__rng), _M_n(0) { } + + /** + * @brief Move constructs a %discard_block_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + discard_block_engine(_RandomNumberEngine&& __rng) + : _M_b(std::move(__rng)), _M_n(0) { } + + /** + * @brief Seed constructs a %discard_block_engine engine. + * + * Constructs the underlying generator engine seeded with @p __s. + * @param __s A seed value for the base class engine. + */ + explicit + discard_block_engine(result_type __s) + : _M_b(__s), _M_n(0) { } + + /** + * @brief Generator construct a %discard_block_engine engine. + * + * @param __q A seed sequence. + */ + template> + explicit + discard_block_engine(_Sseq& __q) + : _M_b(__q), _M_n(0) + { } + + /** + * @brief Reseeds the %discard_block_engine object with the default + * seed for the underlying base class generator engine. + */ + void + seed() + { + _M_b.seed(); + _M_n = 0; + } + + /** + * @brief Reseeds the %discard_block_engine object with the default + * seed for the underlying base class generator engine. + */ + void + seed(result_type __s) + { + _M_b.seed(__s); + _M_n = 0; + } + + /** + * @brief Reseeds the %discard_block_engine object with the given seed + * sequence. + * @param __q A seed generator function. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q) + { + _M_b.seed(__q); + _M_n = 0; + } + + /** + * @brief Gets a const reference to the underlying generator engine + * object. + */ + const _RandomNumberEngine& + base() const noexcept + { return _M_b; } + + /** + * @brief Gets the minimum value in the generated random number range. + */ + static constexpr result_type + min() + { return _RandomNumberEngine::min(); } + + /** + * @brief Gets the maximum value in the generated random number range. + */ + static constexpr result_type + max() + { return _RandomNumberEngine::max(); } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * @brief Gets the next value in the generated random number sequence. + */ + result_type + operator()(); + + /** + * @brief Compares two %discard_block_engine random number generator + * objects of the same type for equality. + * + * @param __lhs A %discard_block_engine random number generator object. + * @param __rhs Another %discard_block_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const discard_block_engine& __lhs, + const discard_block_engine& __rhs) + { return __lhs._M_b == __rhs._M_b && __lhs._M_n == __rhs._M_n; } + + private: + _RandomNumberEngine _M_b; + size_t _M_n; + }; + + /** + * @brief Compares two %discard_block_engine random number generator + * objects of the same type for inequality. + * + * @param __lhs A %discard_block_engine random number generator object. + * @param __rhs Another %discard_block_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::discard_block_engine<_RandomNumberEngine, __p, + __r>& __lhs, + const std::discard_block_engine<_RandomNumberEngine, __p, + __r>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * Produces random numbers by combining random numbers from some base + * engine to produce random numbers with a specifies number of bits @p __w. + */ + template + class independent_bits_engine + { + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); + static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bounds"); + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, independent_bits_engine, _UIntType>::value>::type; + + public: + /** The type of the generated random value. */ + typedef _UIntType result_type; + + /** + * @brief Constructs a default %independent_bits_engine engine. + * + * The underlying engine is default constructed as well. + */ + independent_bits_engine() + : _M_b() { } + + /** + * @brief Copy constructs a %independent_bits_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + independent_bits_engine(const _RandomNumberEngine& __rng) + : _M_b(__rng) { } + + /** + * @brief Move constructs a %independent_bits_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + independent_bits_engine(_RandomNumberEngine&& __rng) + : _M_b(std::move(__rng)) { } + + /** + * @brief Seed constructs a %independent_bits_engine engine. + * + * Constructs the underlying generator engine seeded with @p __s. + * @param __s A seed value for the base class engine. + */ + explicit + independent_bits_engine(result_type __s) + : _M_b(__s) { } + + /** + * @brief Generator construct a %independent_bits_engine engine. + * + * @param __q A seed sequence. + */ + template> + explicit + independent_bits_engine(_Sseq& __q) + : _M_b(__q) + { } + + /** + * @brief Reseeds the %independent_bits_engine object with the default + * seed for the underlying base class generator engine. + */ + void + seed() + { _M_b.seed(); } + + /** + * @brief Reseeds the %independent_bits_engine object with the default + * seed for the underlying base class generator engine. + */ + void + seed(result_type __s) + { _M_b.seed(__s); } + + /** + * @brief Reseeds the %independent_bits_engine object with the given + * seed sequence. + * @param __q A seed generator function. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q) + { _M_b.seed(__q); } + + /** + * @brief Gets a const reference to the underlying generator engine + * object. + */ + const _RandomNumberEngine& + base() const noexcept + { return _M_b; } + + /** + * @brief Gets the minimum value in the generated random number range. + */ + static constexpr result_type + min() + { return 0U; } + + /** + * @brief Gets the maximum value in the generated random number range. + */ + static constexpr result_type + max() + { return __detail::_Shift<_UIntType, __w>::__value - 1; } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * @brief Gets the next value in the generated random number sequence. + */ + result_type + operator()(); + + /** + * @brief Compares two %independent_bits_engine random number generator + * objects of the same type for equality. + * + * @param __lhs A %independent_bits_engine random number generator + * object. + * @param __rhs Another %independent_bits_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const independent_bits_engine& __lhs, + const independent_bits_engine& __rhs) + { return __lhs._M_b == __rhs._M_b; } + + private: + _RandomNumberEngine _M_b; + }; + + /** + * @brief Compares two %independent_bits_engine random number generator + * objects of the same type for inequality. + * + * @param __lhs A %independent_bits_engine random number generator + * object. + * @param __rhs Another %independent_bits_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::independent_bits_engine<_RandomNumberEngine, __w, + _UIntType>& __lhs, + const std::independent_bits_engine<_RandomNumberEngine, __w, + _UIntType>& __rhs) + { return !(__lhs == __rhs); } + + + + /** + * @brief Produces random numbers by combining random numbers from some + * base engine to produce random numbers with a specifies number of bits + * @p __k. + */ + template + class shuffle_order_engine + { + static_assert(1u <= __k, "template argument substituting " + "__k out of bound"); + + public: + /** The type of the generated random value. */ + typedef typename _RandomNumberEngine::result_type result_type; + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, shuffle_order_engine, result_type>::value>::type; + + static constexpr size_t table_size = __k; + + /** + * @brief Constructs a default %shuffle_order_engine engine. + * + * The underlying engine is default constructed as well. + */ + shuffle_order_engine() + : _M_b() + { _M_initialize(); } + + /** + * @brief Copy constructs a %shuffle_order_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + shuffle_order_engine(const _RandomNumberEngine& __rng) + : _M_b(__rng) + { _M_initialize(); } + + /** + * @brief Move constructs a %shuffle_order_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + shuffle_order_engine(_RandomNumberEngine&& __rng) + : _M_b(std::move(__rng)) + { _M_initialize(); } + + /** + * @brief Seed constructs a %shuffle_order_engine engine. + * + * Constructs the underlying generator engine seeded with @p __s. + * @param __s A seed value for the base class engine. + */ + explicit + shuffle_order_engine(result_type __s) + : _M_b(__s) + { _M_initialize(); } + + /** + * @brief Generator construct a %shuffle_order_engine engine. + * + * @param __q A seed sequence. + */ + template> + explicit + shuffle_order_engine(_Sseq& __q) + : _M_b(__q) + { _M_initialize(); } + + /** + * @brief Reseeds the %shuffle_order_engine object with the default seed + for the underlying base class generator engine. + */ + void + seed() + { + _M_b.seed(); + _M_initialize(); + } + + /** + * @brief Reseeds the %shuffle_order_engine object with the default seed + * for the underlying base class generator engine. + */ + void + seed(result_type __s) + { + _M_b.seed(__s); + _M_initialize(); + } + + /** + * @brief Reseeds the %shuffle_order_engine object with the given seed + * sequence. + * @param __q A seed generator function. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q) + { + _M_b.seed(__q); + _M_initialize(); + } + + /** + * Gets a const reference to the underlying generator engine object. + */ + const _RandomNumberEngine& + base() const noexcept + { return _M_b; } + + /** + * Gets the minimum value in the generated random number range. + */ + static constexpr result_type + min() + { return _RandomNumberEngine::min(); } + + /** + * Gets the maximum value in the generated random number range. + */ + static constexpr result_type + max() + { return _RandomNumberEngine::max(); } + + /** + * Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * Gets the next value in the generated random number sequence. + */ + result_type + operator()(); + + /** + * Compares two %shuffle_order_engine random number generator objects + * of the same type for equality. + * + * @param __lhs A %shuffle_order_engine random number generator object. + * @param __rhs Another %shuffle_order_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const shuffle_order_engine& __lhs, + const shuffle_order_engine& __rhs) + { return (__lhs._M_b == __rhs._M_b + && std::equal(__lhs._M_v, __lhs._M_v + __k, __rhs._M_v) + && __lhs._M_y == __rhs._M_y); } + + + private: + void _M_initialize() + { + for (size_t __i = 0; __i < __k; ++__i) + _M_v[__i] = _M_b(); + _M_y = _M_b(); + } + + _RandomNumberEngine _M_b; + result_type _M_v[__k]; + result_type _M_y; + }; + + /** + * Compares two %shuffle_order_engine random number generator objects + * of the same type for inequality. + * + * @param __lhs A %shuffle_order_engine random number generator object. + * @param __rhs Another %shuffle_order_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::shuffle_order_engine<_RandomNumberEngine, + __k>& __lhs, + const std::shuffle_order_engine<_RandomNumberEngine, + __k>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * The classic Minimum Standard rand0 of Lewis, Goodman, and Miller. + */ + typedef linear_congruential_engine + minstd_rand0; + + /** + * An alternative LCR (Lehmer Generator function). + */ + typedef linear_congruential_engine + minstd_rand; + + /** + * The classic Mersenne Twister. + * + * Reference: + * M. Matsumoto and T. Nishimura, Mersenne Twister: A 623-Dimensionally + * Equidistributed Uniform Pseudo-Random Number Generator, ACM Transactions + * on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. + */ + typedef mersenne_twister_engine< + uint_fast32_t, + 32, 624, 397, 31, + 0x9908b0dfUL, 11, + 0xffffffffUL, 7, + 0x9d2c5680UL, 15, + 0xefc60000UL, 18, 1812433253UL> mt19937; + + /** + * An alternative Mersenne Twister. + */ + typedef mersenne_twister_engine< + uint_fast64_t, + 64, 312, 156, 31, + 0xb5026f5aa96619e9ULL, 29, + 0x5555555555555555ULL, 17, + 0x71d67fffeda60000ULL, 37, + 0xfff7eee000000000ULL, 43, + 6364136223846793005ULL> mt19937_64; + + typedef subtract_with_carry_engine + ranlux24_base; + + typedef subtract_with_carry_engine + ranlux48_base; + + typedef discard_block_engine ranlux24; + + typedef discard_block_engine ranlux48; + + typedef shuffle_order_engine knuth_b; + + typedef minstd_rand0 default_random_engine; + + /* @} */ // group random_generators + + /** + * @addtogroup random_distributions Random Number Distributions + * @ingroup random + * @{ + */ + + /** + * @addtogroup random_distributions_uniform Uniform Distributions + * @ingroup random_distributions + * @{ + */ + + // std::uniform_int_distribution is defined in + + /** + * @brief Return true if two uniform integer distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::uniform_int_distribution<_IntType>& __d1, + const std::uniform_int_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief Uniform continuous distribution for random numbers. + * + * A continuous random distribution on the range [min, max) with equal + * probability throughout the range. The URNG should be real-valued and + * deliver number in the range [0, 1). + */ + template + class uniform_real_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef uniform_real_distribution<_RealType> distribution_type; + + param_type() : param_type(0) { } + + explicit + param_type(_RealType __a, _RealType __b = _RealType(1)) + : _M_a(__a), _M_b(__b) + { + __glibcxx_assert(_M_a <= _M_b); + } + + result_type + a() const + { return _M_a; } + + result_type + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_a; + _RealType _M_b; + }; + + public: + /** + * @brief Constructs a uniform_real_distribution object. + * + * The lower bound is set to 0.0 and the upper bound to 1.0 + */ + uniform_real_distribution() : uniform_real_distribution(0.0) { } + + /** + * @brief Constructs a uniform_real_distribution object. + * + * @param __a [IN] The lower bound of the distribution. + * @param __b [IN] The upper bound of the distribution. + */ + explicit + uniform_real_distribution(_RealType __a, _RealType __b = _RealType(1)) + : _M_param(__a, __b) + { } + + explicit + uniform_real_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for the uniform real distribution. + */ + void + reset() { } + + result_type + a() const + { return _M_param.a(); } + + result_type + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the inclusive lower bound of the distribution range. + */ + result_type + min() const + { return this->a(); } + + /** + * @brief Returns the inclusive upper bound of the distribution range. + */ + result_type + max() const + { return this->b(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + return (__aurng() * (__p.b() - __p.a())) + __p.a(); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two uniform real distributions have + * the same parameters. + */ + friend bool + operator==(const uniform_real_distribution& __d1, + const uniform_real_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two uniform real distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::uniform_real_distribution<_IntType>& __d1, + const std::uniform_real_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + /* @} */ // group random_distributions_uniform + + /** + * @addtogroup random_distributions_normal Normal Distributions + * @ingroup random_distributions + * @{ + */ + + /** + * @brief A normal continuous distribution for random numbers. + * + * The formula for the normal probability density function is + * @f[ + * p(x|\mu,\sigma) = \frac{1}{\sigma \sqrt{2 \pi}} + * e^{- \frac{{x - \mu}^ {2}}{2 \sigma ^ {2}} } + * @f] + */ + template + class normal_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef normal_distribution<_RealType> distribution_type; + + param_type() : param_type(0.0) { } + + explicit + param_type(_RealType __mean, _RealType __stddev = _RealType(1)) + : _M_mean(__mean), _M_stddev(__stddev) + { + __glibcxx_assert(_M_stddev > _RealType(0)); + } + + _RealType + mean() const + { return _M_mean; } + + _RealType + stddev() const + { return _M_stddev; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return (__p1._M_mean == __p2._M_mean + && __p1._M_stddev == __p2._M_stddev); } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_mean; + _RealType _M_stddev; + }; + + public: + normal_distribution() : normal_distribution(0.0) { } + + /** + * Constructs a normal distribution with parameters @f$mean@f$ and + * standard deviation. + */ + explicit + normal_distribution(result_type __mean, + result_type __stddev = result_type(1)) + : _M_param(__mean, __stddev), _M_saved_available(false) + { } + + explicit + normal_distribution(const param_type& __p) + : _M_param(__p), _M_saved_available(false) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_saved_available = false; } + + /** + * @brief Returns the mean of the distribution. + */ + _RealType + mean() const + { return _M_param.mean(); } + + /** + * @brief Returns the standard deviation of the distribution. + */ + _RealType + stddev() const + { return _M_param.stddev(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::lowest(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two normal distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + template + friend bool + operator==(const std::normal_distribution<_RealType1>& __d1, + const std::normal_distribution<_RealType1>& __d2); + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + result_type _M_saved; + bool _M_saved_available; + }; + + /** + * @brief Return true if two normal distributions are different. + */ + template + inline bool + operator!=(const std::normal_distribution<_RealType>& __d1, + const std::normal_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A lognormal_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f[ + * p(x|m,s) = \frac{1}{sx\sqrt{2\pi}} + * \exp{-\frac{(\ln{x} - m)^2}{2s^2}} + * @f] + */ + template + class lognormal_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef lognormal_distribution<_RealType> distribution_type; + + param_type() : param_type(0.0) { } + + explicit + param_type(_RealType __m, _RealType __s = _RealType(1)) + : _M_m(__m), _M_s(__s) + { } + + _RealType + m() const + { return _M_m; } + + _RealType + s() const + { return _M_s; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_m == __p2._M_m && __p1._M_s == __p2._M_s; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_m; + _RealType _M_s; + }; + + lognormal_distribution() : lognormal_distribution(0.0) { } + + explicit + lognormal_distribution(_RealType __m, _RealType __s = _RealType(1)) + : _M_param(__m, __s), _M_nd() + { } + + explicit + lognormal_distribution(const param_type& __p) + : _M_param(__p), _M_nd() + { } + + /** + * Resets the distribution state. + */ + void + reset() + { _M_nd.reset(); } + + /** + * + */ + _RealType + m() const + { return _M_param.m(); } + + _RealType + s() const + { return _M_param.s(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { return std::exp(__p.s() * _M_nd(__urng) + __p.m()); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two lognormal distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + friend bool + operator==(const lognormal_distribution& __d1, + const lognormal_distribution& __d2) + { return (__d1._M_param == __d2._M_param + && __d1._M_nd == __d2._M_nd); } + + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::normal_distribution _M_nd; + }; + + /** + * @brief Return true if two lognormal distributions are different. + */ + template + inline bool + operator!=(const std::lognormal_distribution<_RealType>& __d1, + const std::lognormal_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A gamma continuous distribution for random numbers. + * + * The formula for the gamma probability density function is: + * @f[ + * p(x|\alpha,\beta) = \frac{1}{\beta\Gamma(\alpha)} + * (x/\beta)^{\alpha - 1} e^{-x/\beta} + * @f] + */ + template + class gamma_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef gamma_distribution<_RealType> distribution_type; + friend class gamma_distribution<_RealType>; + + param_type() : param_type(1.0) { } + + explicit + param_type(_RealType __alpha_val, _RealType __beta_val = _RealType(1)) + : _M_alpha(__alpha_val), _M_beta(__beta_val) + { + __glibcxx_assert(_M_alpha > _RealType(0)); + _M_initialize(); + } + + _RealType + alpha() const + { return _M_alpha; } + + _RealType + beta() const + { return _M_beta; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return (__p1._M_alpha == __p2._M_alpha + && __p1._M_beta == __p2._M_beta); } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + _RealType _M_alpha; + _RealType _M_beta; + + _RealType _M_malpha, _M_a2; + }; + + public: + /** + * @brief Constructs a gamma distribution with parameters 1 and 1. + */ + gamma_distribution() : gamma_distribution(1.0) { } + + /** + * @brief Constructs a gamma distribution with parameters + * @f$\alpha@f$ and @f$\beta@f$. + */ + explicit + gamma_distribution(_RealType __alpha_val, + _RealType __beta_val = _RealType(1)) + : _M_param(__alpha_val, __beta_val), _M_nd() + { } + + explicit + gamma_distribution(const param_type& __p) + : _M_param(__p), _M_nd() + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_nd.reset(); } + + /** + * @brief Returns the @f$\alpha@f$ of the distribution. + */ + _RealType + alpha() const + { return _M_param.alpha(); } + + /** + * @brief Returns the @f$\beta@f$ of the distribution. + */ + _RealType + beta() const + { return _M_param.beta(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two gamma distributions have the same + * parameters and the sequences that would be generated + * are equal. + */ + friend bool + operator==(const gamma_distribution& __d1, + const gamma_distribution& __d2) + { return (__d1._M_param == __d2._M_param + && __d1._M_nd == __d2._M_nd); } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::normal_distribution _M_nd; + }; + + /** + * @brief Return true if two gamma distributions are different. + */ + template + inline bool + operator!=(const std::gamma_distribution<_RealType>& __d1, + const std::gamma_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A chi_squared_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f$p(x|n) = \frac{x^{(n/2) - 1}e^{-x/2}}{\Gamma(n/2) 2^{n/2}}@f$ + */ + template + class chi_squared_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef chi_squared_distribution<_RealType> distribution_type; + + param_type() : param_type(1) { } + + explicit + param_type(_RealType __n) + : _M_n(__n) + { } + + _RealType + n() const + { return _M_n; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_n == __p2._M_n; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_n; + }; + + chi_squared_distribution() : chi_squared_distribution(1) { } + + explicit + chi_squared_distribution(_RealType __n) + : _M_param(__n), _M_gd(__n / 2) + { } + + explicit + chi_squared_distribution(const param_type& __p) + : _M_param(__p), _M_gd(__p.n() / 2) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_gd.reset(); } + + /** + * + */ + _RealType + n() const + { return _M_param.n(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { + _M_param = __param; + typedef typename std::gamma_distribution::param_type + param_type; + _M_gd.param(param_type{__param.n() / 2}); + } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return 2 * _M_gd(__urng); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + return 2 * _M_gd(__urng, param_type(__p.n() / 2)); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { typename std::gamma_distribution::param_type + __p2(__p.n() / 2); + this->__generate_impl(__f, __t, __urng, __p2); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { typename std::gamma_distribution::param_type + __p2(__p.n() / 2); + this->__generate_impl(__f, __t, __urng, __p2); } + + /** + * @brief Return true if two Chi-squared distributions have + * the same parameters and the sequences that would be + * generated are equal. + */ + friend bool + operator==(const chi_squared_distribution& __d1, + const chi_squared_distribution& __d2) + { return __d1._M_param == __d2._M_param && __d1._M_gd == __d2._M_gd; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng); + + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const typename + std::gamma_distribution::param_type& __p); + + param_type _M_param; + + std::gamma_distribution _M_gd; + }; + + /** + * @brief Return true if two Chi-squared distributions are different. + */ + template + inline bool + operator!=(const std::chi_squared_distribution<_RealType>& __d1, + const std::chi_squared_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A cauchy_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f$p(x|a,b) = (\pi b (1 + (\frac{x-a}{b})^2))^{-1}@f$ + */ + template + class cauchy_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef cauchy_distribution<_RealType> distribution_type; + + param_type() : param_type(0) { } + + explicit + param_type(_RealType __a, _RealType __b = _RealType(1)) + : _M_a(__a), _M_b(__b) + { } + + _RealType + a() const + { return _M_a; } + + _RealType + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_a; + _RealType _M_b; + }; + + cauchy_distribution() : cauchy_distribution(0.0) { } + + explicit + cauchy_distribution(_RealType __a, _RealType __b = 1.0) + : _M_param(__a, __b) + { } + + explicit + cauchy_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * + */ + _RealType + a() const + { return _M_param.a(); } + + _RealType + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::lowest(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Cauchy distributions have + * the same parameters. + */ + friend bool + operator==(const cauchy_distribution& __d1, + const cauchy_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two Cauchy distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::cauchy_distribution<_RealType>& __d1, + const std::cauchy_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + + /** + * @brief A fisher_f_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f[ + * p(x|m,n) = \frac{\Gamma((m+n)/2)}{\Gamma(m/2)\Gamma(n/2)} + * (\frac{m}{n})^{m/2} x^{(m/2)-1} + * (1 + \frac{mx}{n})^{-(m+n)/2} + * @f] + */ + template + class fisher_f_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef fisher_f_distribution<_RealType> distribution_type; + + param_type() : param_type(1) { } + + explicit + param_type(_RealType __m, _RealType __n = _RealType(1)) + : _M_m(__m), _M_n(__n) + { } + + _RealType + m() const + { return _M_m; } + + _RealType + n() const + { return _M_n; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_m == __p2._M_m && __p1._M_n == __p2._M_n; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_m; + _RealType _M_n; + }; + + fisher_f_distribution() : fisher_f_distribution(1.0) { } + + explicit + fisher_f_distribution(_RealType __m, + _RealType __n = _RealType(1)) + : _M_param(__m, __n), _M_gd_x(__m / 2), _M_gd_y(__n / 2) + { } + + explicit + fisher_f_distribution(const param_type& __p) + : _M_param(__p), _M_gd_x(__p.m() / 2), _M_gd_y(__p.n() / 2) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { + _M_gd_x.reset(); + _M_gd_y.reset(); + } + + /** + * + */ + _RealType + m() const + { return _M_param.m(); } + + _RealType + n() const + { return _M_param.n(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return (_M_gd_x(__urng) * n()) / (_M_gd_y(__urng) * m()); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + return ((_M_gd_x(__urng, param_type(__p.m() / 2)) * n()) + / (_M_gd_y(__urng, param_type(__p.n() / 2)) * m())); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Fisher f distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + friend bool + operator==(const fisher_f_distribution& __d1, + const fisher_f_distribution& __d2) + { return (__d1._M_param == __d2._M_param + && __d1._M_gd_x == __d2._M_gd_x + && __d1._M_gd_y == __d2._M_gd_y); } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng); + + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::gamma_distribution _M_gd_x, _M_gd_y; + }; + + /** + * @brief Return true if two Fisher f distributions are different. + */ + template + inline bool + operator!=(const std::fisher_f_distribution<_RealType>& __d1, + const std::fisher_f_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + /** + * @brief A student_t_distribution random number distribution. + * + * The formula for the normal probability mass function is: + * @f[ + * p(x|n) = \frac{1}{\sqrt(n\pi)} \frac{\Gamma((n+1)/2)}{\Gamma(n/2)} + * (1 + \frac{x^2}{n}) ^{-(n+1)/2} + * @f] + */ + template + class student_t_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef student_t_distribution<_RealType> distribution_type; + + param_type() : param_type(1) { } + + explicit + param_type(_RealType __n) + : _M_n(__n) + { } + + _RealType + n() const + { return _M_n; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_n == __p2._M_n; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_n; + }; + + student_t_distribution() : student_t_distribution(1.0) { } + + explicit + student_t_distribution(_RealType __n) + : _M_param(__n), _M_nd(), _M_gd(__n / 2, 2) + { } + + explicit + student_t_distribution(const param_type& __p) + : _M_param(__p), _M_nd(), _M_gd(__p.n() / 2, 2) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { + _M_nd.reset(); + _M_gd.reset(); + } + + /** + * + */ + _RealType + n() const + { return _M_param.n(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::lowest(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return _M_nd(__urng) * std::sqrt(n() / _M_gd(__urng)); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + + const result_type __g = _M_gd(__urng, param_type(__p.n() / 2, 2)); + return _M_nd(__urng) * std::sqrt(__p.n() / __g); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Student t distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + friend bool + operator==(const student_t_distribution& __d1, + const student_t_distribution& __d2) + { return (__d1._M_param == __d2._M_param + && __d1._M_nd == __d2._M_nd && __d1._M_gd == __d2._M_gd); } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng); + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::normal_distribution _M_nd; + std::gamma_distribution _M_gd; + }; + + /** + * @brief Return true if two Student t distributions are different. + */ + template + inline bool + operator!=(const std::student_t_distribution<_RealType>& __d1, + const std::student_t_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /* @} */ // group random_distributions_normal + + /** + * @addtogroup random_distributions_bernoulli Bernoulli Distributions + * @ingroup random_distributions + * @{ + */ + + /** + * @brief A Bernoulli random number distribution. + * + * Generates a sequence of true and false values with likelihood @f$p@f$ + * that true will come up and @f$(1 - p)@f$ that false will appear. + */ + class bernoulli_distribution + { + public: + /** The type of the range of the distribution. */ + typedef bool result_type; + + /** Parameter type. */ + struct param_type + { + typedef bernoulli_distribution distribution_type; + + param_type() : param_type(0.5) { } + + explicit + param_type(double __p) + : _M_p(__p) + { + __glibcxx_assert((_M_p >= 0.0) && (_M_p <= 1.0)); + } + + double + p() const + { return _M_p; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_p == __p2._M_p; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + double _M_p; + }; + + public: + /** + * @brief Constructs a Bernoulli distribution with likelihood 0.5. + */ + bernoulli_distribution() : bernoulli_distribution(0.5) { } + + /** + * @brief Constructs a Bernoulli distribution with likelihood @p p. + * + * @param __p [IN] The likelihood of a true result being returned. + * Must be in the interval @f$[0, 1]@f$. + */ + explicit + bernoulli_distribution(double __p) + : _M_param(__p) + { } + + explicit + bernoulli_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for a Bernoulli distribution. + */ + void + reset() { } + + /** + * @brief Returns the @p p parameter of the distribution. + */ + double + p() const + { return _M_param.p(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::min(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + if ((__aurng() - __aurng.min()) + < __p.p() * (__aurng.max() - __aurng.min())) + return true; + return false; + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Bernoulli distributions have + * the same parameters. + */ + friend bool + operator==(const bernoulli_distribution& __d1, + const bernoulli_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two Bernoulli distributions have + * different parameters. + */ + inline bool + operator!=(const std::bernoulli_distribution& __d1, + const std::bernoulli_distribution& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A discrete binomial random number distribution. + * + * The formula for the binomial probability density function is + * @f$p(i|t,p) = \binom{t}{i} p^i (1 - p)^{t - i}@f$ where @f$t@f$ + * and @f$p@f$ are the parameters of the distribution. + */ + template + class binomial_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef binomial_distribution<_IntType> distribution_type; + friend class binomial_distribution<_IntType>; + + param_type() : param_type(1) { } + + explicit + param_type(_IntType __t, double __p = 0.5) + : _M_t(__t), _M_p(__p) + { + __glibcxx_assert((_M_t >= _IntType(0)) + && (_M_p >= 0.0) + && (_M_p <= 1.0)); + _M_initialize(); + } + + _IntType + t() const + { return _M_t; } + + double + p() const + { return _M_p; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_t == __p2._M_t && __p1._M_p == __p2._M_p; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + _IntType _M_t; + double _M_p; + + double _M_q; +#if _GLIBCXX_USE_C99_MATH_TR1 + double _M_d1, _M_d2, _M_s1, _M_s2, _M_c, + _M_a1, _M_a123, _M_s, _M_lf, _M_lp1p; +#endif + bool _M_easy; + }; + + // constructors and member functions + + binomial_distribution() : binomial_distribution(1) { } + + explicit + binomial_distribution(_IntType __t, double __p = 0.5) + : _M_param(__t, __p), _M_nd() + { } + + explicit + binomial_distribution(const param_type& __p) + : _M_param(__p), _M_nd() + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_nd.reset(); } + + /** + * @brief Returns the distribution @p t parameter. + */ + _IntType + t() const + { return _M_param.t(); } + + /** + * @brief Returns the distribution @p p parameter. + */ + double + p() const + { return _M_param.p(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return 0; } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return _M_param.t(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two binomial distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + friend bool + operator==(const binomial_distribution& __d1, + const binomial_distribution& __d2) +#ifdef _GLIBCXX_USE_C99_MATH_TR1 + { return __d1._M_param == __d2._M_param && __d1._M_nd == __d2._M_nd; } +#else + { return __d1._M_param == __d2._M_param; } +#endif + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + result_type + _M_waiting(_UniformRandomNumberGenerator& __urng, + _IntType __t, double __q); + + param_type _M_param; + + // NB: Unused when _GLIBCXX_USE_C99_MATH_TR1 is undefined. + std::normal_distribution _M_nd; + }; + + /** + * @brief Return true if two binomial distributions are different. + */ + template + inline bool + operator!=(const std::binomial_distribution<_IntType>& __d1, + const std::binomial_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A discrete geometric random number distribution. + * + * The formula for the geometric probability density function is + * @f$p(i|p) = p(1 - p)^{i}@f$ where @f$p@f$ is the parameter of the + * distribution. + */ + template + class geometric_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef geometric_distribution<_IntType> distribution_type; + friend class geometric_distribution<_IntType>; + + param_type() : param_type(0.5) { } + + explicit + param_type(double __p) + : _M_p(__p) + { + __glibcxx_assert((_M_p > 0.0) && (_M_p < 1.0)); + _M_initialize(); + } + + double + p() const + { return _M_p; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_p == __p2._M_p; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize() + { _M_log_1_p = std::log(1.0 - _M_p); } + + double _M_p; + + double _M_log_1_p; + }; + + // constructors and member functions + + geometric_distribution() : geometric_distribution(0.5) { } + + explicit + geometric_distribution(double __p) + : _M_param(__p) + { } + + explicit + geometric_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for the geometric distribution. + */ + void + reset() { } + + /** + * @brief Returns the distribution parameter @p p. + */ + double + p() const + { return _M_param.p(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return 0; } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two geometric distributions have + * the same parameters. + */ + friend bool + operator==(const geometric_distribution& __d1, + const geometric_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two geometric distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::geometric_distribution<_IntType>& __d1, + const std::geometric_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A negative_binomial_distribution random number distribution. + * + * The formula for the negative binomial probability mass function is + * @f$p(i) = \binom{n}{i} p^i (1 - p)^{t - i}@f$ where @f$t@f$ + * and @f$p@f$ are the parameters of the distribution. + */ + template + class negative_binomial_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef negative_binomial_distribution<_IntType> distribution_type; + + param_type() : param_type(1) { } + + explicit + param_type(_IntType __k, double __p = 0.5) + : _M_k(__k), _M_p(__p) + { + __glibcxx_assert((_M_k > 0) && (_M_p > 0.0) && (_M_p <= 1.0)); + } + + _IntType + k() const + { return _M_k; } + + double + p() const + { return _M_p; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_k == __p2._M_k && __p1._M_p == __p2._M_p; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _IntType _M_k; + double _M_p; + }; + + negative_binomial_distribution() : negative_binomial_distribution(1) { } + + explicit + negative_binomial_distribution(_IntType __k, double __p = 0.5) + : _M_param(__k, __p), _M_gd(__k, (1.0 - __p) / __p) + { } + + explicit + negative_binomial_distribution(const param_type& __p) + : _M_param(__p), _M_gd(__p.k(), (1.0 - __p.p()) / __p.p()) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_gd.reset(); } + + /** + * @brief Return the @f$k@f$ parameter of the distribution. + */ + _IntType + k() const + { return _M_param.k(); } + + /** + * @brief Return the @f$p@f$ parameter of the distribution. + */ + double + p() const + { return _M_param.p(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng); + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two negative binomial distributions have + * the same parameters and the sequences that would be + * generated are equal. + */ + friend bool + operator==(const negative_binomial_distribution& __d1, + const negative_binomial_distribution& __d2) + { return __d1._M_param == __d2._M_param && __d1._M_gd == __d2._M_gd; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng); + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::gamma_distribution _M_gd; + }; + + /** + * @brief Return true if two negative binomial distributions are different. + */ + template + inline bool + operator!=(const std::negative_binomial_distribution<_IntType>& __d1, + const std::negative_binomial_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /* @} */ // group random_distributions_bernoulli + + /** + * @addtogroup random_distributions_poisson Poisson Distributions + * @ingroup random_distributions + * @{ + */ + + /** + * @brief A discrete Poisson random number distribution. + * + * The formula for the Poisson probability density function is + * @f$p(i|\mu) = \frac{\mu^i}{i!} e^{-\mu}@f$ where @f$\mu@f$ is the + * parameter of the distribution. + */ + template + class poisson_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef poisson_distribution<_IntType> distribution_type; + friend class poisson_distribution<_IntType>; + + param_type() : param_type(1.0) { } + + explicit + param_type(double __mean) + : _M_mean(__mean) + { + __glibcxx_assert(_M_mean > 0.0); + _M_initialize(); + } + + double + mean() const + { return _M_mean; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_mean == __p2._M_mean; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + // Hosts either log(mean) or the threshold of the simple method. + void + _M_initialize(); + + double _M_mean; + + double _M_lm_thr; +#if _GLIBCXX_USE_C99_MATH_TR1 + double _M_lfm, _M_sm, _M_d, _M_scx, _M_1cx, _M_c2b, _M_cb; +#endif + }; + + // constructors and member functions + + poisson_distribution() : poisson_distribution(1.0) { } + + explicit + poisson_distribution(double __mean) + : _M_param(__mean), _M_nd() + { } + + explicit + poisson_distribution(const param_type& __p) + : _M_param(__p), _M_nd() + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_nd.reset(); } + + /** + * @brief Returns the distribution parameter @p mean. + */ + double + mean() const + { return _M_param.mean(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return 0; } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Poisson distributions have the same + * parameters and the sequences that would be generated + * are equal. + */ + friend bool + operator==(const poisson_distribution& __d1, + const poisson_distribution& __d2) +#ifdef _GLIBCXX_USE_C99_MATH_TR1 + { return __d1._M_param == __d2._M_param && __d1._M_nd == __d2._M_nd; } +#else + { return __d1._M_param == __d2._M_param; } +#endif + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + // NB: Unused when _GLIBCXX_USE_C99_MATH_TR1 is undefined. + std::normal_distribution _M_nd; + }; + + /** + * @brief Return true if two Poisson distributions are different. + */ + template + inline bool + operator!=(const std::poisson_distribution<_IntType>& __d1, + const std::poisson_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief An exponential continuous distribution for random numbers. + * + * The formula for the exponential probability density function is + * @f$p(x|\lambda) = \lambda e^{-\lambda x}@f$. + * + * + * + * + * + * + * + * + *
Distribution Statistics
Mean@f$\frac{1}{\lambda}@f$
Median@f$\frac{\ln 2}{\lambda}@f$
Mode@f$zero@f$
Range@f$[0, \infty]@f$
Standard Deviation@f$\frac{1}{\lambda}@f$
+ */ + template + class exponential_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef exponential_distribution<_RealType> distribution_type; + + param_type() : param_type(1.0) { } + + explicit + param_type(_RealType __lambda) + : _M_lambda(__lambda) + { + __glibcxx_assert(_M_lambda > _RealType(0)); + } + + _RealType + lambda() const + { return _M_lambda; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_lambda == __p2._M_lambda; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_lambda; + }; + + public: + /** + * @brief Constructs an exponential distribution with inverse scale + * parameter 1.0 + */ + exponential_distribution() : exponential_distribution(1.0) { } + + /** + * @brief Constructs an exponential distribution with inverse scale + * parameter @f$\lambda@f$. + */ + explicit + exponential_distribution(_RealType __lambda) + : _M_param(__lambda) + { } + + explicit + exponential_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Has no effect on exponential distributions. + */ + void + reset() { } + + /** + * @brief Returns the inverse scale parameter of the distribution. + */ + _RealType + lambda() const + { return _M_param.lambda(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + return -std::log(result_type(1) - __aurng()) / __p.lambda(); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two exponential distributions have the same + * parameters. + */ + friend bool + operator==(const exponential_distribution& __d1, + const exponential_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two exponential distributions have different + * parameters. + */ + template + inline bool + operator!=(const std::exponential_distribution<_RealType>& __d1, + const std::exponential_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A weibull_distribution random number distribution. + * + * The formula for the normal probability density function is: + * @f[ + * p(x|\alpha,\beta) = \frac{\alpha}{\beta} (\frac{x}{\beta})^{\alpha-1} + * \exp{(-(\frac{x}{\beta})^\alpha)} + * @f] + */ + template + class weibull_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef weibull_distribution<_RealType> distribution_type; + + param_type() : param_type(1.0) { } + + explicit + param_type(_RealType __a, _RealType __b = _RealType(1.0)) + : _M_a(__a), _M_b(__b) + { } + + _RealType + a() const + { return _M_a; } + + _RealType + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_a; + _RealType _M_b; + }; + + weibull_distribution() : weibull_distribution(1.0) { } + + explicit + weibull_distribution(_RealType __a, _RealType __b = _RealType(1)) + : _M_param(__a, __b) + { } + + explicit + weibull_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Return the @f$a@f$ parameter of the distribution. + */ + _RealType + a() const + { return _M_param.a(); } + + /** + * @brief Return the @f$b@f$ parameter of the distribution. + */ + _RealType + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Weibull distributions have the same + * parameters. + */ + friend bool + operator==(const weibull_distribution& __d1, + const weibull_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two Weibull distributions have different + * parameters. + */ + template + inline bool + operator!=(const std::weibull_distribution<_RealType>& __d1, + const std::weibull_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A extreme_value_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f[ + * p(x|a,b) = \frac{1}{b} + * \exp( \frac{a-x}{b} - \exp(\frac{a-x}{b})) + * @f] + */ + template + class extreme_value_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef extreme_value_distribution<_RealType> distribution_type; + + param_type() : param_type(0.0) { } + + explicit + param_type(_RealType __a, _RealType __b = _RealType(1.0)) + : _M_a(__a), _M_b(__b) + { } + + _RealType + a() const + { return _M_a; } + + _RealType + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_a; + _RealType _M_b; + }; + + extreme_value_distribution() : extreme_value_distribution(0.0) { } + + explicit + extreme_value_distribution(_RealType __a, _RealType __b = _RealType(1)) + : _M_param(__a, __b) + { } + + explicit + extreme_value_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Return the @f$a@f$ parameter of the distribution. + */ + _RealType + a() const + { return _M_param.a(); } + + /** + * @brief Return the @f$b@f$ parameter of the distribution. + */ + _RealType + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::lowest(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two extreme value distributions have the same + * parameters. + */ + friend bool + operator==(const extreme_value_distribution& __d1, + const extreme_value_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two extreme value distributions have different + * parameters. + */ + template + inline bool + operator!=(const std::extreme_value_distribution<_RealType>& __d1, + const std::extreme_value_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A discrete_distribution random number distribution. + * + * The formula for the discrete probability mass function is + * + */ + template + class discrete_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef discrete_distribution<_IntType> distribution_type; + friend class discrete_distribution<_IntType>; + + param_type() + : _M_prob(), _M_cp() + { } + + template + param_type(_InputIterator __wbegin, + _InputIterator __wend) + : _M_prob(__wbegin, __wend), _M_cp() + { _M_initialize(); } + + param_type(initializer_list __wil) + : _M_prob(__wil.begin(), __wil.end()), _M_cp() + { _M_initialize(); } + + template + param_type(size_t __nw, double __xmin, double __xmax, + _Func __fw); + + // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ + param_type(const param_type&) = default; + param_type& operator=(const param_type&) = default; + + std::vector + probabilities() const + { return _M_prob.empty() ? std::vector(1, 1.0) : _M_prob; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_prob == __p2._M_prob; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + std::vector _M_prob; + std::vector _M_cp; + }; + + discrete_distribution() + : _M_param() + { } + + template + discrete_distribution(_InputIterator __wbegin, + _InputIterator __wend) + : _M_param(__wbegin, __wend) + { } + + discrete_distribution(initializer_list __wl) + : _M_param(__wl) + { } + + template + discrete_distribution(size_t __nw, double __xmin, double __xmax, + _Func __fw) + : _M_param(__nw, __xmin, __xmax, __fw) + { } + + explicit + discrete_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Returns the probabilities of the distribution. + */ + std::vector + probabilities() const + { + return _M_param._M_prob.empty() + ? std::vector(1, 1.0) : _M_param._M_prob; + } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { + return _M_param._M_prob.empty() + ? result_type(0) : result_type(_M_param._M_prob.size() - 1); + } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two discrete distributions have the same + * parameters. + */ + friend bool + operator==(const discrete_distribution& __d1, + const discrete_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two discrete distributions have different + * parameters. + */ + template + inline bool + operator!=(const std::discrete_distribution<_IntType>& __d1, + const std::discrete_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A piecewise_constant_distribution random number distribution. + * + * The formula for the piecewise constant probability mass function is + * + */ + template + class piecewise_constant_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef piecewise_constant_distribution<_RealType> distribution_type; + friend class piecewise_constant_distribution<_RealType>; + + param_type() + : _M_int(), _M_den(), _M_cp() + { } + + template + param_type(_InputIteratorB __bfirst, + _InputIteratorB __bend, + _InputIteratorW __wbegin); + + template + param_type(initializer_list<_RealType> __bi, _Func __fw); + + template + param_type(size_t __nw, _RealType __xmin, _RealType __xmax, + _Func __fw); + + // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ + param_type(const param_type&) = default; + param_type& operator=(const param_type&) = default; + + std::vector<_RealType> + intervals() const + { + if (_M_int.empty()) + { + std::vector<_RealType> __tmp(2); + __tmp[1] = _RealType(1); + return __tmp; + } + else + return _M_int; + } + + std::vector + densities() const + { return _M_den.empty() ? std::vector(1, 1.0) : _M_den; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_int == __p2._M_int && __p1._M_den == __p2._M_den; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + std::vector<_RealType> _M_int; + std::vector _M_den; + std::vector _M_cp; + }; + + piecewise_constant_distribution() + : _M_param() + { } + + template + piecewise_constant_distribution(_InputIteratorB __bfirst, + _InputIteratorB __bend, + _InputIteratorW __wbegin) + : _M_param(__bfirst, __bend, __wbegin) + { } + + template + piecewise_constant_distribution(initializer_list<_RealType> __bl, + _Func __fw) + : _M_param(__bl, __fw) + { } + + template + piecewise_constant_distribution(size_t __nw, + _RealType __xmin, _RealType __xmax, + _Func __fw) + : _M_param(__nw, __xmin, __xmax, __fw) + { } + + explicit + piecewise_constant_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Returns a vector of the intervals. + */ + std::vector<_RealType> + intervals() const + { + if (_M_param._M_int.empty()) + { + std::vector<_RealType> __tmp(2); + __tmp[1] = _RealType(1); + return __tmp; + } + else + return _M_param._M_int; + } + + /** + * @brief Returns a vector of the probability densities. + */ + std::vector + densities() const + { + return _M_param._M_den.empty() + ? std::vector(1, 1.0) : _M_param._M_den; + } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { + return _M_param._M_int.empty() + ? result_type(0) : _M_param._M_int.front(); + } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { + return _M_param._M_int.empty() + ? result_type(1) : _M_param._M_int.back(); + } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two piecewise constant distributions have the + * same parameters. + */ + friend bool + operator==(const piecewise_constant_distribution& __d1, + const piecewise_constant_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two piecewise constant distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::piecewise_constant_distribution<_RealType>& __d1, + const std::piecewise_constant_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A piecewise_linear_distribution random number distribution. + * + * The formula for the piecewise linear probability mass function is + * + */ + template + class piecewise_linear_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef piecewise_linear_distribution<_RealType> distribution_type; + friend class piecewise_linear_distribution<_RealType>; + + param_type() + : _M_int(), _M_den(), _M_cp(), _M_m() + { } + + template + param_type(_InputIteratorB __bfirst, + _InputIteratorB __bend, + _InputIteratorW __wbegin); + + template + param_type(initializer_list<_RealType> __bl, _Func __fw); + + template + param_type(size_t __nw, _RealType __xmin, _RealType __xmax, + _Func __fw); + + // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ + param_type(const param_type&) = default; + param_type& operator=(const param_type&) = default; + + std::vector<_RealType> + intervals() const + { + if (_M_int.empty()) + { + std::vector<_RealType> __tmp(2); + __tmp[1] = _RealType(1); + return __tmp; + } + else + return _M_int; + } + + std::vector + densities() const + { return _M_den.empty() ? std::vector(2, 1.0) : _M_den; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_int == __p2._M_int && __p1._M_den == __p2._M_den; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + std::vector<_RealType> _M_int; + std::vector _M_den; + std::vector _M_cp; + std::vector _M_m; + }; + + piecewise_linear_distribution() + : _M_param() + { } + + template + piecewise_linear_distribution(_InputIteratorB __bfirst, + _InputIteratorB __bend, + _InputIteratorW __wbegin) + : _M_param(__bfirst, __bend, __wbegin) + { } + + template + piecewise_linear_distribution(initializer_list<_RealType> __bl, + _Func __fw) + : _M_param(__bl, __fw) + { } + + template + piecewise_linear_distribution(size_t __nw, + _RealType __xmin, _RealType __xmax, + _Func __fw) + : _M_param(__nw, __xmin, __xmax, __fw) + { } + + explicit + piecewise_linear_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Return the intervals of the distribution. + */ + std::vector<_RealType> + intervals() const + { + if (_M_param._M_int.empty()) + { + std::vector<_RealType> __tmp(2); + __tmp[1] = _RealType(1); + return __tmp; + } + else + return _M_param._M_int; + } + + /** + * @brief Return a vector of the probability densities of the + * distribution. + */ + std::vector + densities() const + { + return _M_param._M_den.empty() + ? std::vector(2, 1.0) : _M_param._M_den; + } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { + return _M_param._M_int.empty() + ? result_type(0) : _M_param._M_int.front(); + } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { + return _M_param._M_int.empty() + ? result_type(1) : _M_param._M_int.back(); + } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two piecewise linear distributions have the + * same parameters. + */ + friend bool + operator==(const piecewise_linear_distribution& __d1, + const piecewise_linear_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two piecewise linear distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::piecewise_linear_distribution<_RealType>& __d1, + const std::piecewise_linear_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /* @} */ // group random_distributions_poisson + + /* @} */ // group random_distributions + + /** + * @addtogroup random_utilities Random Number Utilities + * @ingroup random + * @{ + */ + + /** + * @brief The seed_seq class generates sequences of seeds for random + * number generators. + */ + class seed_seq + { + public: + /** The type of the seed vales. */ + typedef uint_least32_t result_type; + + /** Default constructor. */ + seed_seq() noexcept + : _M_v() + { } + + template + seed_seq(std::initializer_list<_IntType> __il); + + template + seed_seq(_InputIterator __begin, _InputIterator __end); + + // generating functions + template + void + generate(_RandomAccessIterator __begin, _RandomAccessIterator __end); + + // property functions + size_t size() const noexcept + { return _M_v.size(); } + + template + void + param(_OutputIterator __dest) const + { std::copy(_M_v.begin(), _M_v.end(), __dest); } + + // no copy functions + seed_seq(const seed_seq&) = delete; + seed_seq& operator=(const seed_seq&) = delete; + + private: + std::vector _M_v; + }; + + /* @} */ // group random_utilities + + /* @} */ // group random + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/random.tcc b/resources/sources/avr-libstdcpp/include/bits/random.tcc new file mode 100644 index 000000000..a9b90d6ca --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/random.tcc @@ -0,0 +1,2193 @@ +// random number generation (out of line) -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/random.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{random} + */ + +#ifndef _RANDOM_TCC +#define _RANDOM_TCC 1 + +#include // std::accumulate and std::partial_sum + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /* + * (Further) implementation-space details. + */ + namespace __detail + { + // General case for x = (ax + c) mod m -- use Schrage's algorithm + // to avoid integer overflow. + // + // Preconditions: a > 0, m > 0. + // + // Note: only works correctly for __m % __a < __m / __a. + template + _Tp + _Mod<_Tp, __m, __a, __c, false, true>:: + __calc(_Tp __x) + { + if (__a == 1) + __x %= __m; + else + { + static const _Tp __q = __m / __a; + static const _Tp __r = __m % __a; + + _Tp __t1 = __a * (__x % __q); + _Tp __t2 = __r * (__x / __q); + if (__t1 >= __t2) + __x = __t1 - __t2; + else + __x = __m - __t2 + __t1; + } + + if (__c != 0) + { + const _Tp __d = __m - __x; + if (__d > __c) + __x += __c; + else + __x = __c - __d; + } + return __x; + } + + template + _OutputIterator + __normalize(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, const _Tp& __factor) + { + for (; __first != __last; ++__first, ++__result) + *__result = *__first / __factor; + return __result; + } + + } // namespace __detail + + template + constexpr _UIntType + linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier; + + template + constexpr _UIntType + linear_congruential_engine<_UIntType, __a, __c, __m>::increment; + + template + constexpr _UIntType + linear_congruential_engine<_UIntType, __a, __c, __m>::modulus; + + template + constexpr _UIntType + linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed; + + /** + * Seeds the LCR with integral value @p __s, adjusted so that the + * ring identity is never a member of the convergence set. + */ + template + void + linear_congruential_engine<_UIntType, __a, __c, __m>:: + seed(result_type __s) + { + if ((__detail::__mod<_UIntType, __m>(__c) == 0) + && (__detail::__mod<_UIntType, __m>(__s) == 0)) + _M_x = 1; + else + _M_x = __detail::__mod<_UIntType, __m>(__s); + } + + /** + * Seeds the LCR engine with a value generated by @p __q. + */ + template + template + auto + linear_congruential_engine<_UIntType, __a, __c, __m>:: + seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> + { + const _UIntType __k0 = __m == 0 ? std::numeric_limits<_UIntType>::digits + : std::__lg(__m); + const _UIntType __k = (__k0 + 31) / 32; + uint_least32_t __arr[__k + 3]; + __q.generate(__arr + 0, __arr + __k + 3); + _UIntType __factor = 1u; + _UIntType __sum = 0u; + for (size_t __j = 0; __j < __k; ++__j) + { + __sum += __arr[__j + 3] * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + seed(__sum); + } + + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::word_size; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::state_size; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::shift_size; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::mask_bits; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::xor_mask; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_u; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_d; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_s; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_b; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_t; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_c; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_l; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + initialization_multiplier; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::default_seed; + + template + void + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + seed(result_type __sd) + { + _M_x[0] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__sd); + + for (size_t __i = 1; __i < state_size; ++__i) + { + _UIntType __x = _M_x[__i - 1]; + __x ^= __x >> (__w - 2); + __x *= __f; + __x += __detail::__mod<_UIntType, __n>(__i); + _M_x[__i] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__x); + } + _M_p = state_size; + } + + template + template + auto + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> + { + const _UIntType __upper_mask = (~_UIntType()) << __r; + const size_t __k = (__w + 31) / 32; + uint_least32_t __arr[__n * __k]; + __q.generate(__arr + 0, __arr + __n * __k); + + bool __zero = true; + for (size_t __i = 0; __i < state_size; ++__i) + { + _UIntType __factor = 1u; + _UIntType __sum = 0u; + for (size_t __j = 0; __j < __k; ++__j) + { + __sum += __arr[__k * __i + __j] * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + _M_x[__i] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__sum); + + if (__zero) + { + if (__i == 0) + { + if ((_M_x[0] & __upper_mask) != 0u) + __zero = false; + } + else if (_M_x[__i] != 0u) + __zero = false; + } + } + if (__zero) + _M_x[0] = __detail::_Shift<_UIntType, __w - 1>::__value; + _M_p = state_size; + } + + template + void + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + _M_gen_rand(void) + { + const _UIntType __upper_mask = (~_UIntType()) << __r; + const _UIntType __lower_mask = ~__upper_mask; + + for (size_t __k = 0; __k < (__n - __m); ++__k) + { + _UIntType __y = ((_M_x[__k] & __upper_mask) + | (_M_x[__k + 1] & __lower_mask)); + _M_x[__k] = (_M_x[__k + __m] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + } + + for (size_t __k = (__n - __m); __k < (__n - 1); ++__k) + { + _UIntType __y = ((_M_x[__k] & __upper_mask) + | (_M_x[__k + 1] & __lower_mask)); + _M_x[__k] = (_M_x[__k + (__m - __n)] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + } + + _UIntType __y = ((_M_x[__n - 1] & __upper_mask) + | (_M_x[0] & __lower_mask)); + _M_x[__n - 1] = (_M_x[__m - 1] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + _M_p = 0; + } + + template + void + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + discard(unsigned long long __z) + { + while (__z > state_size - _M_p) + { + __z -= state_size - _M_p; + _M_gen_rand(); + } + _M_p += __z; + } + + template + typename + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::result_type + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + operator()() + { + // Reload the vector - cost is O(n) amortized over n calls. + if (_M_p >= state_size) + _M_gen_rand(); + + // Calculate o(x(i)). + result_type __z = _M_x[_M_p++]; + __z ^= (__z >> __u) & __d; + __z ^= (__z << __s) & __b; + __z ^= (__z << __t) & __c; + __z ^= (__z >> __l); + + return __z; + } + + + template + constexpr size_t + subtract_with_carry_engine<_UIntType, __w, __s, __r>::word_size; + + template + constexpr size_t + subtract_with_carry_engine<_UIntType, __w, __s, __r>::short_lag; + + template + constexpr size_t + subtract_with_carry_engine<_UIntType, __w, __s, __r>::long_lag; + + template + constexpr _UIntType + subtract_with_carry_engine<_UIntType, __w, __s, __r>::default_seed; + + template + void + subtract_with_carry_engine<_UIntType, __w, __s, __r>:: + seed(result_type __value) + { + std::linear_congruential_engine + __lcg(__value == 0u ? default_seed : __value); + + const size_t __n = (__w + 31) / 32; + + for (size_t __i = 0; __i < long_lag; ++__i) + { + _UIntType __sum = 0u; + _UIntType __factor = 1u; + for (size_t __j = 0; __j < __n; ++__j) + { + __sum += __detail::__mod::__value> + (__lcg()) * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + _M_x[__i] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__sum); + } + _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0; + _M_p = 0; + } + + template + template + auto + subtract_with_carry_engine<_UIntType, __w, __s, __r>:: + seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> + { + const size_t __k = (__w + 31) / 32; + uint_least32_t __arr[__r * __k]; + __q.generate(__arr + 0, __arr + __r * __k); + + for (size_t __i = 0; __i < long_lag; ++__i) + { + _UIntType __sum = 0u; + _UIntType __factor = 1u; + for (size_t __j = 0; __j < __k; ++__j) + { + __sum += __arr[__k * __i + __j] * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + _M_x[__i] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__sum); + } + _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0; + _M_p = 0; + } + + template + typename subtract_with_carry_engine<_UIntType, __w, __s, __r>:: + result_type + subtract_with_carry_engine<_UIntType, __w, __s, __r>:: + operator()() + { + // Derive short lag index from current index. + long __ps = _M_p - short_lag; + if (__ps < 0) + __ps += long_lag; + + // Calculate new x(i) without overflow or division. + // NB: Thanks to the requirements for _UIntType, _M_x[_M_p] + _M_carry + // cannot overflow. + _UIntType __xi; + if (_M_x[__ps] >= _M_x[_M_p] + _M_carry) + { + __xi = _M_x[__ps] - _M_x[_M_p] - _M_carry; + _M_carry = 0; + } + else + { + __xi = (__detail::_Shift<_UIntType, __w>::__value + - _M_x[_M_p] - _M_carry + _M_x[__ps]); + _M_carry = 1; + } + _M_x[_M_p] = __xi; + + // Adjust current index to loop around in ring buffer. + if (++_M_p >= long_lag) + _M_p = 0; + + return __xi; + } + + + template + constexpr size_t + discard_block_engine<_RandomNumberEngine, __p, __r>::block_size; + + template + constexpr size_t + discard_block_engine<_RandomNumberEngine, __p, __r>::used_block; + + template + typename discard_block_engine<_RandomNumberEngine, + __p, __r>::result_type + discard_block_engine<_RandomNumberEngine, __p, __r>:: + operator()() + { + if (_M_n >= used_block) + { + _M_b.discard(block_size - _M_n); + _M_n = 0; + } + ++_M_n; + return _M_b(); + } + + + template + typename independent_bits_engine<_RandomNumberEngine, __w, _UIntType>:: + result_type + independent_bits_engine<_RandomNumberEngine, __w, _UIntType>:: + operator()() + { + typedef typename _RandomNumberEngine::result_type _Eresult_type; + const _Eresult_type __r + = (_M_b.max() - _M_b.min() < std::numeric_limits<_Eresult_type>::max() + ? _M_b.max() - _M_b.min() + 1 : 0); + const unsigned __edig = std::numeric_limits<_Eresult_type>::digits; + const unsigned __m = __r ? std::__lg(__r) : __edig; + + typedef typename std::common_type<_Eresult_type, result_type>::type + __ctype; + const unsigned __cdig = std::numeric_limits<__ctype>::digits; + + unsigned __n, __n0; + __ctype __s0, __s1, __y0, __y1; + + for (size_t __i = 0; __i < 2; ++__i) + { + __n = (__w + __m - 1) / __m + __i; + __n0 = __n - __w % __n; + const unsigned __w0 = __w / __n; // __w0 <= __m + + __s0 = 0; + __s1 = 0; + if (__w0 < __cdig) + { + __s0 = __ctype(1) << __w0; + __s1 = __s0 << 1; + } + + __y0 = 0; + __y1 = 0; + if (__r) + { + __y0 = __s0 * (__r / __s0); + if (__s1) + __y1 = __s1 * (__r / __s1); + + if (__r - __y0 <= __y0 / __n) + break; + } + else + break; + } + + result_type __sum = 0; + for (size_t __k = 0; __k < __n0; ++__k) + { + __ctype __u; + do + __u = _M_b() - _M_b.min(); + while (__y0 && __u >= __y0); + __sum = __s0 * __sum + (__s0 ? __u % __s0 : __u); + } + for (size_t __k = __n0; __k < __n; ++__k) + { + __ctype __u; + do + __u = _M_b() - _M_b.min(); + while (__y1 && __u >= __y1); + __sum = __s1 * __sum + (__s1 ? __u % __s1 : __u); + } + return __sum; + } + + + template + constexpr size_t + shuffle_order_engine<_RandomNumberEngine, __k>::table_size; + + template + typename shuffle_order_engine<_RandomNumberEngine, __k>::result_type + shuffle_order_engine<_RandomNumberEngine, __k>:: + operator()() + { + size_t __j = __k * ((_M_y - _M_b.min()) + / (_M_b.max() - _M_b.min() + 1.0L)); + _M_y = _M_v[__j]; + _M_v[__j] = _M_b(); + + return _M_y; + } + + + template + template + void + uniform_real_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + auto __range = __p.b() - __p.a(); + while (__f != __t) + *__f++ = __aurng() * __range + __p.a(); + } + + + template + void + std::bernoulli_distribution:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + auto __limit = __p.p() * (__aurng.max() - __aurng.min()); + + while (__f != __t) + *__f++ = (__aurng() - __aurng.min()) < __limit; + } + + + template + template + typename geometric_distribution<_IntType>::result_type + geometric_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + // About the epsilon thing see this thread: + // http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00971.html + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + // The largest _RealType convertible to _IntType. + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + double __cand; + do + __cand = std::floor(std::log(1.0 - __aurng()) / __param._M_log_1_p); + while (__cand >= __thr); + + return result_type(__cand + __naf); + } + + template + template + void + geometric_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // About the epsilon thing see this thread: + // http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00971.html + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + // The largest _RealType convertible to _IntType. + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + while (__f != __t) + { + double __cand; + do + __cand = std::floor(std::log(1.0 - __aurng()) + / __param._M_log_1_p); + while (__cand >= __thr); + + *__f++ = __cand + __naf; + } + } + + + // This is Leger's algorithm, also in Devroye, Ch. X, Example 1.5. + template + template + typename negative_binomial_distribution<_IntType>::result_type + negative_binomial_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng) + { + const double __y = _M_gd(__urng); + + // XXX Is the constructor too slow? + std::poisson_distribution __poisson(__y); + return __poisson(__urng); + } + + template + template + typename negative_binomial_distribution<_IntType>::result_type + negative_binomial_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + + const double __y = + _M_gd(__urng, param_type(__p.k(), (1.0 - __p.p()) / __p.p())); + + std::poisson_distribution __poisson(__y); + return __poisson(__urng); + } + + template + template + void + negative_binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + { + const double __y = _M_gd(__urng); + + // XXX Is the constructor too slow? + std::poisson_distribution __poisson(__y); + *__f++ = __poisson(__urng); + } + } + + template + template + void + negative_binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typename std::gamma_distribution::param_type + __p2(__p.k(), (1.0 - __p.p()) / __p.p()); + + while (__f != __t) + { + const double __y = _M_gd(__urng, __p2); + + std::poisson_distribution __poisson(__y); + *__f++ = __poisson(__urng); + } + } + + + template + void + poisson_distribution<_IntType>::param_type:: + _M_initialize() + { +#if _GLIBCXX_USE_C99_MATH_TR1 + if (_M_mean >= 12) + { + const double __m = std::floor(_M_mean); + _M_lm_thr = std::log(_M_mean); + _M_lfm = std::lgamma(__m + 1); + _M_sm = std::sqrt(__m); + + const double __pi_4 = 0.7853981633974483096156608458198757L; + const double __dx = std::sqrt(2 * __m * std::log(32 * __m + / __pi_4)); + _M_d = std::round(std::max(6.0, std::min(__m, __dx))); + const double __cx = 2 * __m + _M_d; + _M_scx = std::sqrt(__cx / 2); + _M_1cx = 1 / __cx; + + _M_c2b = std::sqrt(__pi_4 * __cx) * std::exp(_M_1cx); + _M_cb = 2 * __cx * std::exp(-_M_d * _M_1cx * (1 + _M_d / 2)) + / _M_d; + } + else +#endif + _M_lm_thr = std::exp(-_M_mean); + } + + /** + * A rejection algorithm when mean >= 12 and a simple method based + * upon the multiplication of uniform random variates otherwise. + * NB: The former is available only if _GLIBCXX_USE_C99_MATH_TR1 + * is defined. + * + * Reference: + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. X, Sects. 3.3 & 3.4 (+ Errata!). + */ + template + template + typename poisson_distribution<_IntType>::result_type + poisson_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); +#if _GLIBCXX_USE_C99_MATH_TR1 + if (__param.mean() >= 12) + { + double __x; + + // See comments above... + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + + const double __m = std::floor(__param.mean()); + // sqrt(pi / 2) + const double __spi_2 = 1.2533141373155002512078826424055226L; + const double __c1 = __param._M_sm * __spi_2; + const double __c2 = __param._M_c2b + __c1; + const double __c3 = __c2 + 1; + const double __c4 = __c3 + 1; + // 1 / 78 + const double __178 = 0.0128205128205128205128205128205128L; + // e^(1 / 78) + const double __e178 = 1.0129030479320018583185514777512983L; + const double __c5 = __c4 + __e178; + const double __c = __param._M_cb + __c5; + const double __2cx = 2 * (2 * __m + __param._M_d); + + bool __reject = true; + do + { + const double __u = __c * __aurng(); + const double __e = -std::log(1.0 - __aurng()); + + double __w = 0.0; + + if (__u <= __c1) + { + const double __n = _M_nd(__urng); + const double __y = -std::abs(__n) * __param._M_sm - 1; + __x = std::floor(__y); + __w = -__n * __n / 2; + if (__x < -__m) + continue; + } + else if (__u <= __c2) + { + const double __n = _M_nd(__urng); + const double __y = 1 + std::abs(__n) * __param._M_scx; + __x = std::ceil(__y); + __w = __y * (2 - __y) * __param._M_1cx; + if (__x > __param._M_d) + continue; + } + else if (__u <= __c3) + // NB: This case not in the book, nor in the Errata, + // but should be ok... + __x = -1; + else if (__u <= __c4) + __x = 0; + else if (__u <= __c5) + { + __x = 1; + // Only in the Errata, see libstdc++/83237. + __w = __178; + } + else + { + const double __v = -std::log(1.0 - __aurng()); + const double __y = __param._M_d + + __v * __2cx / __param._M_d; + __x = std::ceil(__y); + __w = -__param._M_d * __param._M_1cx * (1 + __y / 2); + } + + __reject = (__w - __e - __x * __param._M_lm_thr + > __param._M_lfm - std::lgamma(__x + __m + 1)); + + __reject |= __x + __m >= __thr; + + } while (__reject); + + return result_type(__x + __m + __naf); + } + else +#endif + { + _IntType __x = 0; + double __prod = 1.0; + + do + { + __prod *= __aurng(); + __x += 1; + } + while (__prod > __param._M_lm_thr); + + return __x - 1; + } + } + + template + template + void + poisson_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + + + template + void + binomial_distribution<_IntType>::param_type:: + _M_initialize() + { + const double __p12 = _M_p <= 0.5 ? _M_p : 1.0 - _M_p; + + _M_easy = true; + +#if _GLIBCXX_USE_C99_MATH_TR1 + if (_M_t * __p12 >= 8) + { + _M_easy = false; + const double __np = std::floor(_M_t * __p12); + const double __pa = __np / _M_t; + const double __1p = 1 - __pa; + + const double __pi_4 = 0.7853981633974483096156608458198757L; + const double __d1x = + std::sqrt(__np * __1p * std::log(32 * __np + / (81 * __pi_4 * __1p))); + _M_d1 = std::round(std::max(1.0, __d1x)); + const double __d2x = + std::sqrt(__np * __1p * std::log(32 * _M_t * __1p + / (__pi_4 * __pa))); + _M_d2 = std::round(std::max(1.0, __d2x)); + + // sqrt(pi / 2) + const double __spi_2 = 1.2533141373155002512078826424055226L; + _M_s1 = std::sqrt(__np * __1p) * (1 + _M_d1 / (4 * __np)); + _M_s2 = std::sqrt(__np * __1p) * (1 + _M_d2 / (4 * _M_t * __1p)); + _M_c = 2 * _M_d1 / __np; + _M_a1 = std::exp(_M_c) * _M_s1 * __spi_2; + const double __a12 = _M_a1 + _M_s2 * __spi_2; + const double __s1s = _M_s1 * _M_s1; + _M_a123 = __a12 + (std::exp(_M_d1 / (_M_t * __1p)) + * 2 * __s1s / _M_d1 + * std::exp(-_M_d1 * _M_d1 / (2 * __s1s))); + const double __s2s = _M_s2 * _M_s2; + _M_s = (_M_a123 + 2 * __s2s / _M_d2 + * std::exp(-_M_d2 * _M_d2 / (2 * __s2s))); + _M_lf = (std::lgamma(__np + 1) + + std::lgamma(_M_t - __np + 1)); + _M_lp1p = std::log(__pa / __1p); + + _M_q = -std::log(1 - (__p12 - __pa) / __1p); + } + else +#endif + _M_q = -std::log(1 - __p12); + } + + template + template + typename binomial_distribution<_IntType>::result_type + binomial_distribution<_IntType>:: + _M_waiting(_UniformRandomNumberGenerator& __urng, + _IntType __t, double __q) + { + _IntType __x = 0; + double __sum = 0.0; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + do + { + if (__t == __x) + return __x; + const double __e = -std::log(1.0 - __aurng()); + __sum += __e / (__t - __x); + __x += 1; + } + while (__sum <= __q); + + return __x - 1; + } + + /** + * A rejection algorithm when t * p >= 8 and a simple waiting time + * method - the second in the referenced book - otherwise. + * NB: The former is available only if _GLIBCXX_USE_C99_MATH_TR1 + * is defined. + * + * Reference: + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. X, Sect. 4 (+ Errata!). + */ + template + template + typename binomial_distribution<_IntType>::result_type + binomial_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + result_type __ret; + const _IntType __t = __param.t(); + const double __p = __param.p(); + const double __p12 = __p <= 0.5 ? __p : 1.0 - __p; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + +#if _GLIBCXX_USE_C99_MATH_TR1 + if (!__param._M_easy) + { + double __x; + + // See comments above... + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + + const double __np = std::floor(__t * __p12); + + // sqrt(pi / 2) + const double __spi_2 = 1.2533141373155002512078826424055226L; + const double __a1 = __param._M_a1; + const double __a12 = __a1 + __param._M_s2 * __spi_2; + const double __a123 = __param._M_a123; + const double __s1s = __param._M_s1 * __param._M_s1; + const double __s2s = __param._M_s2 * __param._M_s2; + + bool __reject; + do + { + const double __u = __param._M_s * __aurng(); + + double __v; + + if (__u <= __a1) + { + const double __n = _M_nd(__urng); + const double __y = __param._M_s1 * std::abs(__n); + __reject = __y >= __param._M_d1; + if (!__reject) + { + const double __e = -std::log(1.0 - __aurng()); + __x = std::floor(__y); + __v = -__e - __n * __n / 2 + __param._M_c; + } + } + else if (__u <= __a12) + { + const double __n = _M_nd(__urng); + const double __y = __param._M_s2 * std::abs(__n); + __reject = __y >= __param._M_d2; + if (!__reject) + { + const double __e = -std::log(1.0 - __aurng()); + __x = std::floor(-__y); + __v = -__e - __n * __n / 2; + } + } + else if (__u <= __a123) + { + const double __e1 = -std::log(1.0 - __aurng()); + const double __e2 = -std::log(1.0 - __aurng()); + + const double __y = __param._M_d1 + + 2 * __s1s * __e1 / __param._M_d1; + __x = std::floor(__y); + __v = (-__e2 + __param._M_d1 * (1 / (__t - __np) + -__y / (2 * __s1s))); + __reject = false; + } + else + { + const double __e1 = -std::log(1.0 - __aurng()); + const double __e2 = -std::log(1.0 - __aurng()); + + const double __y = __param._M_d2 + + 2 * __s2s * __e1 / __param._M_d2; + __x = std::floor(-__y); + __v = -__e2 - __param._M_d2 * __y / (2 * __s2s); + __reject = false; + } + + __reject = __reject || __x < -__np || __x > __t - __np; + if (!__reject) + { + const double __lfx = + std::lgamma(__np + __x + 1) + + std::lgamma(__t - (__np + __x) + 1); + __reject = __v > __param._M_lf - __lfx + + __x * __param._M_lp1p; + } + + __reject |= __x + __np >= __thr; + } + while (__reject); + + __x += __np + __naf; + + const _IntType __z = _M_waiting(__urng, __t - _IntType(__x), + __param._M_q); + __ret = _IntType(__x) + __z; + } + else +#endif + __ret = _M_waiting(__urng, __t, __param._M_q); + + if (__p12 != __p) + __ret = __t - __ret; + return __ret; + } + + template + template + void + binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + + + template + template + void + std::exponential_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + while (__f != __t) + *__f++ = -std::log(result_type(1) - __aurng()) / __p.lambda(); + } + + + /** + * Polar method due to Marsaglia. + * + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. V, Sect. 4.4. + */ + template + template + typename normal_distribution<_RealType>::result_type + normal_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + result_type __ret; + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + if (_M_saved_available) + { + _M_saved_available = false; + __ret = _M_saved; + } + else + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + _M_saved = __x * __mult; + _M_saved_available = true; + __ret = __y * __mult; + } + + __ret = __ret * __param.stddev() + __param.mean(); + return __ret; + } + + template + template + void + normal_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + + if (__f == __t) + return; + + if (_M_saved_available) + { + _M_saved_available = false; + *__f++ = _M_saved * __param.stddev() + __param.mean(); + + if (__f == __t) + return; + } + + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + while (__f + 1 < __t) + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + *__f++ = __y * __mult * __param.stddev() + __param.mean(); + *__f++ = __x * __mult * __param.stddev() + __param.mean(); + } + + if (__f != __t) + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + _M_saved = __x * __mult; + _M_saved_available = true; + *__f = __y * __mult * __param.stddev() + __param.mean(); + } + } + + template + bool + operator==(const std::normal_distribution<_RealType>& __d1, + const std::normal_distribution<_RealType>& __d2) + { + if (__d1._M_param == __d2._M_param + && __d1._M_saved_available == __d2._M_saved_available) + { + if (__d1._M_saved_available + && __d1._M_saved == __d2._M_saved) + return true; + else if(!__d1._M_saved_available) + return true; + else + return false; + } + else + return false; + } + + + template + template + void + lognormal_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = std::exp(__p.s() * _M_nd(__urng) + __p.m()); + } + + template + template + void + std::chi_squared_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = 2 * _M_gd(__urng); + } + + template + template + void + std::chi_squared_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const typename + std::gamma_distribution::param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = 2 * _M_gd(__urng, __p); + } + + + template + template + typename cauchy_distribution<_RealType>::result_type + cauchy_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + _RealType __u; + do + __u = __aurng(); + while (__u == 0.5); + + const _RealType __pi = 3.1415926535897932384626433832795029L; + return __p.a() + __p.b() * std::tan(__pi * __u); + } + + template + template + void + cauchy_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + const _RealType __pi = 3.1415926535897932384626433832795029L; + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + while (__f != __t) + { + _RealType __u; + do + __u = __aurng(); + while (__u == 0.5); + + *__f++ = __p.a() + __p.b() * std::tan(__pi * __u); + } + } + + + template + template + void + std::fisher_f_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = ((_M_gd_x(__urng) * n()) / (_M_gd_y(__urng) * m())); + } + + template + template + void + std::fisher_f_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typedef typename std::gamma_distribution::param_type + param_type; + param_type __p1(__p.m() / 2); + param_type __p2(__p.n() / 2); + while (__f != __t) + *__f++ = ((_M_gd_x(__urng, __p1) * n()) + / (_M_gd_y(__urng, __p2) * m())); + } + + + template + template + void + std::student_t_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = _M_nd(__urng) * std::sqrt(n() / _M_gd(__urng)); + } + + template + template + void + std::student_t_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typename std::gamma_distribution::param_type + __p2(__p.n() / 2, 2); + while (__f != __t) + *__f++ = _M_nd(__urng) * std::sqrt(__p.n() / _M_gd(__urng, __p2)); + } + + + template + void + gamma_distribution<_RealType>::param_type:: + _M_initialize() + { + _M_malpha = _M_alpha < 1.0 ? _M_alpha + _RealType(1.0) : _M_alpha; + + const _RealType __a1 = _M_malpha - _RealType(1.0) / _RealType(3.0); + _M_a2 = _RealType(1.0) / std::sqrt(_RealType(9.0) * __a1); + } + + /** + * Marsaglia, G. and Tsang, W. W. + * "A Simple Method for Generating Gamma Variables" + * ACM Transactions on Mathematical Software, 26, 3, 363-372, 2000. + */ + template + template + typename gamma_distribution<_RealType>::result_type + gamma_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + result_type __u, __v, __n; + const result_type __a1 = (__param._M_malpha + - _RealType(1.0) / _RealType(3.0)); + + do + { + do + { + __n = _M_nd(__urng); + __v = result_type(1.0) + __param._M_a2 * __n; + } + while (__v <= 0.0); + + __v = __v * __v * __v; + __u = __aurng(); + } + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n + && (std::log(__u) > (0.5 * __n * __n + __a1 + * (1.0 - __v + std::log(__v))))); + + if (__param.alpha() == __param._M_malpha) + return __a1 * __v * __param.beta(); + else + { + do + __u = __aurng(); + while (__u == 0.0); + + return (std::pow(__u, result_type(1.0) / __param.alpha()) + * __a1 * __v * __param.beta()); + } + } + + template + template + void + gamma_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + result_type __u, __v, __n; + const result_type __a1 = (__param._M_malpha + - _RealType(1.0) / _RealType(3.0)); + + if (__param.alpha() == __param._M_malpha) + while (__f != __t) + { + do + { + do + { + __n = _M_nd(__urng); + __v = result_type(1.0) + __param._M_a2 * __n; + } + while (__v <= 0.0); + + __v = __v * __v * __v; + __u = __aurng(); + } + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n + && (std::log(__u) > (0.5 * __n * __n + __a1 + * (1.0 - __v + std::log(__v))))); + + *__f++ = __a1 * __v * __param.beta(); + } + else + while (__f != __t) + { + do + { + do + { + __n = _M_nd(__urng); + __v = result_type(1.0) + __param._M_a2 * __n; + } + while (__v <= 0.0); + + __v = __v * __v * __v; + __u = __aurng(); + } + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n + && (std::log(__u) > (0.5 * __n * __n + __a1 + * (1.0 - __v + std::log(__v))))); + + do + __u = __aurng(); + while (__u == 0.0); + + *__f++ = (std::pow(__u, result_type(1.0) / __param.alpha()) + * __a1 * __v * __param.beta()); + } + } + + + template + template + typename weibull_distribution<_RealType>::result_type + weibull_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + return __p.b() * std::pow(-std::log(result_type(1) - __aurng()), + result_type(1) / __p.a()); + } + + template + template + void + weibull_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + auto __inv_a = result_type(1) / __p.a(); + + while (__f != __t) + *__f++ = __p.b() * std::pow(-std::log(result_type(1) - __aurng()), + __inv_a); + } + + + template + template + typename extreme_value_distribution<_RealType>::result_type + extreme_value_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + return __p.a() - __p.b() * std::log(-std::log(result_type(1) + - __aurng())); + } + + template + template + void + extreme_value_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + while (__f != __t) + *__f++ = __p.a() - __p.b() * std::log(-std::log(result_type(1) + - __aurng())); + } + + + template + void + discrete_distribution<_IntType>::param_type:: + _M_initialize() + { + if (_M_prob.size() < 2) + { + _M_prob.clear(); + return; + } + + const double __sum = std::accumulate(_M_prob.begin(), + _M_prob.end(), 0.0); + // Now normalize the probabilites. + __detail::__normalize(_M_prob.begin(), _M_prob.end(), _M_prob.begin(), + __sum); + // Accumulate partial sums. + _M_cp.reserve(_M_prob.size()); + std::partial_sum(_M_prob.begin(), _M_prob.end(), + std::back_inserter(_M_cp)); + // Make sure the last cumulative probability is one. + _M_cp[_M_cp.size() - 1] = 1.0; + } + + template + template + discrete_distribution<_IntType>::param_type:: + param_type(size_t __nw, double __xmin, double __xmax, _Func __fw) + : _M_prob(), _M_cp() + { + const size_t __n = __nw == 0 ? 1 : __nw; + const double __delta = (__xmax - __xmin) / __n; + + _M_prob.reserve(__n); + for (size_t __k = 0; __k < __nw; ++__k) + _M_prob.push_back(__fw(__xmin + __k * __delta + 0.5 * __delta)); + + _M_initialize(); + } + + template + template + typename discrete_distribution<_IntType>::result_type + discrete_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + if (__param._M_cp.empty()) + return result_type(0); + + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + const double __p = __aurng(); + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + + return __pos - __param._M_cp.begin(); + } + + template + template + void + discrete_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + + if (__param._M_cp.empty()) + { + while (__f != __t) + *__f++ = result_type(0); + return; + } + + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + while (__f != __t) + { + const double __p = __aurng(); + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + + *__f++ = __pos - __param._M_cp.begin(); + } + } + + + template + void + piecewise_constant_distribution<_RealType>::param_type:: + _M_initialize() + { + if (_M_int.size() < 2 + || (_M_int.size() == 2 + && _M_int[0] == _RealType(0) + && _M_int[1] == _RealType(1))) + { + _M_int.clear(); + _M_den.clear(); + return; + } + + const double __sum = std::accumulate(_M_den.begin(), + _M_den.end(), 0.0); + + __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(), + __sum); + + _M_cp.reserve(_M_den.size()); + std::partial_sum(_M_den.begin(), _M_den.end(), + std::back_inserter(_M_cp)); + + // Make sure the last cumulative probability is one. + _M_cp[_M_cp.size() - 1] = 1.0; + + for (size_t __k = 0; __k < _M_den.size(); ++__k) + _M_den[__k] /= _M_int[__k + 1] - _M_int[__k]; + } + + template + template + piecewise_constant_distribution<_RealType>::param_type:: + param_type(_InputIteratorB __bbegin, + _InputIteratorB __bend, + _InputIteratorW __wbegin) + : _M_int(), _M_den(), _M_cp() + { + if (__bbegin != __bend) + { + for (;;) + { + _M_int.push_back(*__bbegin); + ++__bbegin; + if (__bbegin == __bend) + break; + + _M_den.push_back(*__wbegin); + ++__wbegin; + } + } + + _M_initialize(); + } + + template + template + piecewise_constant_distribution<_RealType>::param_type:: + param_type(initializer_list<_RealType> __bl, _Func __fw) + : _M_int(), _M_den(), _M_cp() + { + _M_int.reserve(__bl.size()); + for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter) + _M_int.push_back(*__biter); + + _M_den.reserve(_M_int.size() - 1); + for (size_t __k = 0; __k < _M_int.size() - 1; ++__k) + _M_den.push_back(__fw(0.5 * (_M_int[__k + 1] + _M_int[__k]))); + + _M_initialize(); + } + + template + template + piecewise_constant_distribution<_RealType>::param_type:: + param_type(size_t __nw, _RealType __xmin, _RealType __xmax, _Func __fw) + : _M_int(), _M_den(), _M_cp() + { + const size_t __n = __nw == 0 ? 1 : __nw; + const _RealType __delta = (__xmax - __xmin) / __n; + + _M_int.reserve(__n + 1); + for (size_t __k = 0; __k <= __nw; ++__k) + _M_int.push_back(__xmin + __k * __delta); + + _M_den.reserve(__n); + for (size_t __k = 0; __k < __nw; ++__k) + _M_den.push_back(__fw(_M_int[__k] + 0.5 * __delta)); + + _M_initialize(); + } + + template + template + typename piecewise_constant_distribution<_RealType>::result_type + piecewise_constant_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + const double __p = __aurng(); + if (__param._M_cp.empty()) + return __p; + + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + const size_t __i = __pos - __param._M_cp.begin(); + + const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; + + return __param._M_int[__i] + (__p - __pref) / __param._M_den[__i]; + } + + template + template + void + piecewise_constant_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + if (__param._M_cp.empty()) + { + while (__f != __t) + *__f++ = __aurng(); + return; + } + + while (__f != __t) + { + const double __p = __aurng(); + + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + const size_t __i = __pos - __param._M_cp.begin(); + + const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; + + *__f++ = (__param._M_int[__i] + + (__p - __pref) / __param._M_den[__i]); + } + } + + + template + void + piecewise_linear_distribution<_RealType>::param_type:: + _M_initialize() + { + if (_M_int.size() < 2 + || (_M_int.size() == 2 + && _M_int[0] == _RealType(0) + && _M_int[1] == _RealType(1) + && _M_den[0] == _M_den[1])) + { + _M_int.clear(); + _M_den.clear(); + return; + } + + double __sum = 0.0; + _M_cp.reserve(_M_int.size() - 1); + _M_m.reserve(_M_int.size() - 1); + for (size_t __k = 0; __k < _M_int.size() - 1; ++__k) + { + const _RealType __delta = _M_int[__k + 1] - _M_int[__k]; + __sum += 0.5 * (_M_den[__k + 1] + _M_den[__k]) * __delta; + _M_cp.push_back(__sum); + _M_m.push_back((_M_den[__k + 1] - _M_den[__k]) / __delta); + } + + // Now normalize the densities... + __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(), + __sum); + // ... and partial sums... + __detail::__normalize(_M_cp.begin(), _M_cp.end(), _M_cp.begin(), __sum); + // ... and slopes. + __detail::__normalize(_M_m.begin(), _M_m.end(), _M_m.begin(), __sum); + + // Make sure the last cumulative probablility is one. + _M_cp[_M_cp.size() - 1] = 1.0; + } + + template + template + piecewise_linear_distribution<_RealType>::param_type:: + param_type(_InputIteratorB __bbegin, + _InputIteratorB __bend, + _InputIteratorW __wbegin) + : _M_int(), _M_den(), _M_cp(), _M_m() + { + for (; __bbegin != __bend; ++__bbegin, ++__wbegin) + { + _M_int.push_back(*__bbegin); + _M_den.push_back(*__wbegin); + } + + _M_initialize(); + } + + template + template + piecewise_linear_distribution<_RealType>::param_type:: + param_type(initializer_list<_RealType> __bl, _Func __fw) + : _M_int(), _M_den(), _M_cp(), _M_m() + { + _M_int.reserve(__bl.size()); + _M_den.reserve(__bl.size()); + for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter) + { + _M_int.push_back(*__biter); + _M_den.push_back(__fw(*__biter)); + } + + _M_initialize(); + } + + template + template + piecewise_linear_distribution<_RealType>::param_type:: + param_type(size_t __nw, _RealType __xmin, _RealType __xmax, _Func __fw) + : _M_int(), _M_den(), _M_cp(), _M_m() + { + const size_t __n = __nw == 0 ? 1 : __nw; + const _RealType __delta = (__xmax - __xmin) / __n; + + _M_int.reserve(__n + 1); + _M_den.reserve(__n + 1); + for (size_t __k = 0; __k <= __nw; ++__k) + { + _M_int.push_back(__xmin + __k * __delta); + _M_den.push_back(__fw(_M_int[__k] + __delta)); + } + + _M_initialize(); + } + + template + template + typename piecewise_linear_distribution<_RealType>::result_type + piecewise_linear_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + const double __p = __aurng(); + if (__param._M_cp.empty()) + return __p; + + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + const size_t __i = __pos - __param._M_cp.begin(); + + const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; + + const double __a = 0.5 * __param._M_m[__i]; + const double __b = __param._M_den[__i]; + const double __cm = __p - __pref; + + _RealType __x = __param._M_int[__i]; + if (__a == 0) + __x += __cm / __b; + else + { + const double __d = __b * __b + 4.0 * __a * __cm; + __x += 0.5 * (std::sqrt(__d) - __b) / __a; + } + + return __x; + } + + template + template + void + piecewise_linear_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + + + template + seed_seq::seed_seq(std::initializer_list<_IntType> __il) + { + for (auto __iter = __il.begin(); __iter != __il.end(); ++__iter) + _M_v.push_back(__detail::__mod::__value>(*__iter)); + } + + template + seed_seq::seed_seq(_InputIterator __begin, _InputIterator __end) + { + for (_InputIterator __iter = __begin; __iter != __end; ++__iter) + _M_v.push_back(__detail::__mod::__value>(*__iter)); + } + + template + void + seed_seq::generate(_RandomAccessIterator __begin, + _RandomAccessIterator __end) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _Type; + + if (__begin == __end) + return; + + std::fill(__begin, __end, _Type(0x8b8b8b8bu)); + + const size_t __n = __end - __begin; + const size_t __s = _M_v.size(); + const size_t __t = (__n >= 623) ? 11 + : (__n >= 68) ? 7 + : (__n >= 39) ? 5 + : (__n >= 7) ? 3 + : (__n - 1) / 2; + const size_t __p = (__n - __t) / 2; + const size_t __q = __p + __t; + const size_t __m = std::max(size_t(__s + 1), __n); + + for (size_t __k = 0; __k < __m; ++__k) + { + _Type __arg = (__begin[__k % __n] + ^ __begin[(__k + __p) % __n] + ^ __begin[(__k - 1) % __n]); + _Type __r1 = __arg ^ (__arg >> 27); + __r1 = __detail::__mod<_Type, + __detail::_Shift<_Type, 32>::__value>(1664525u * __r1); + _Type __r2 = __r1; + if (__k == 0) + __r2 += __s; + else if (__k <= __s) + __r2 += __k % __n + _M_v[__k - 1]; + else + __r2 += __k % __n; + __r2 = __detail::__mod<_Type, + __detail::_Shift<_Type, 32>::__value>(__r2); + __begin[(__k + __p) % __n] += __r1; + __begin[(__k + __q) % __n] += __r2; + __begin[__k % __n] = __r2; + } + + for (size_t __k = __m; __k < __m + __n; ++__k) + { + _Type __arg = (__begin[__k % __n] + + __begin[(__k + __p) % __n] + + __begin[(__k - 1) % __n]); + _Type __r3 = __arg ^ (__arg >> 27); + __r3 = __detail::__mod<_Type, + __detail::_Shift<_Type, 32>::__value>(1566083941u * __r3); + _Type __r4 = __r3 - __k % __n; + __r4 = __detail::__mod<_Type, + __detail::_Shift<_Type, 32>::__value>(__r4); + __begin[(__k + __p) % __n] ^= __r3; + __begin[(__k + __q) % __n] ^= __r4; + __begin[__k % __n] = __r4; + } + } + + template + _RealType + generate_canonical(_UniformRandomNumberGenerator& __urng) + { + static_assert(std::is_floating_point<_RealType>::value, + "template argument must be a floating point type"); + + const size_t __b + = std::min(static_cast(std::numeric_limits<_RealType>::digits), + __bits); + const long double __r = static_cast(__urng.max()) + - static_cast(__urng.min()) + 1.0L; + const size_t __log2r = std::log(__r) / std::log(2.0L); + const size_t __m = std::max(1UL, + (__b + __log2r - 1UL) / __log2r); + _RealType __ret; + _RealType __sum = _RealType(0); + _RealType __tmp = _RealType(1); + for (size_t __k = __m; __k != 0; --__k) + { + __sum += _RealType(__urng() - __urng.min()) * __tmp; + __tmp *= __r; + } + __ret = __sum / __tmp; + if (__builtin_expect(__ret >= _RealType(1), 0)) + { +#if _GLIBCXX_USE_C99_MATH_TR1 + __ret = std::nextafter(_RealType(1), _RealType(0)); +#else + __ret = _RealType(1) + - std::numeric_limits<_RealType>::epsilon() / _RealType(2); +#endif + } + return __ret; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/range_access.h b/resources/sources/avr-libstdcpp/include/bits/range_access.h new file mode 100644 index 000000000..3919183c5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/range_access.h @@ -0,0 +1,1148 @@ +// -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/range_access.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _GLIBCXX_RANGE_ACCESS_H +#define _GLIBCXX_RANGE_ACCESS_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Return an iterator pointing to the first element of + * the container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + begin(_Container& __cont) -> decltype(__cont.begin()) + { return __cont.begin(); } + + /** + * @brief Return an iterator pointing to the first element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + begin(const _Container& __cont) -> decltype(__cont.begin()) + { return __cont.begin(); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + end(_Container& __cont) -> decltype(__cont.end()) + { return __cont.end(); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + end(const _Container& __cont) -> decltype(__cont.end()) + { return __cont.end(); } + + /** + * @brief Return an iterator pointing to the first element of the array. + * @param __arr Array. + */ + template + inline _GLIBCXX14_CONSTEXPR _Tp* + begin(_Tp (&__arr)[_Nm]) + { return __arr; } + + /** + * @brief Return an iterator pointing to one past the last element + * of the array. + * @param __arr Array. + */ + template + inline _GLIBCXX14_CONSTEXPR _Tp* + end(_Tp (&__arr)[_Nm]) + { return __arr + _Nm; } + +#if __cplusplus >= 201402L + + template class valarray; + // These overloads must be declared for cbegin and cend to use them. + template _Tp* begin(valarray<_Tp>&); + template const _Tp* begin(const valarray<_Tp>&); + template _Tp* end(valarray<_Tp>&); + template const _Tp* end(const valarray<_Tp>&); + + /** + * @brief Return an iterator pointing to the first element of + * the const container. + * @param __cont Container. + */ + template + inline constexpr auto + cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont))) + -> decltype(std::begin(__cont)) + { return std::begin(__cont); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the const container. + * @param __cont Container. + */ + template + inline constexpr auto + cend(const _Container& __cont) noexcept(noexcept(std::end(__cont))) + -> decltype(std::end(__cont)) + { return std::end(__cont); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + rbegin(_Container& __cont) -> decltype(__cont.rbegin()) + { return __cont.rbegin(); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + rbegin(const _Container& __cont) -> decltype(__cont.rbegin()) + { return __cont.rbegin(); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + rend(_Container& __cont) -> decltype(__cont.rend()) + { return __cont.rend(); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + rend(const _Container& __cont) -> decltype(__cont.rend()) + { return __cont.rend(); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the array. + * @param __arr Array. + */ + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> + rbegin(_Tp (&__arr)[_Nm]) + { return reverse_iterator<_Tp*>(__arr + _Nm); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the array. + * @param __arr Array. + */ + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> + rend(_Tp (&__arr)[_Nm]) + { return reverse_iterator<_Tp*>(__arr); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the initializer_list. + * @param __il initializer_list. + */ + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator + rbegin(initializer_list<_Tp> __il) + { return reverse_iterator(__il.end()); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the initializer_list. + * @param __il initializer_list. + */ + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator + rend(initializer_list<_Tp> __il) + { return reverse_iterator(__il.begin()); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont)) + { return std::rbegin(__cont); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + crend(const _Container& __cont) -> decltype(std::rend(__cont)) + { return std::rend(__cont); } + +#endif // C++14 + +#if __cplusplus >= 201703L +#define __cpp_lib_nonmember_container_access 201411 + + /** + * @brief Return the size of a container. + * @param __cont Container. + */ + template + constexpr auto + size(const _Container& __cont) noexcept(noexcept(__cont.size())) + -> decltype(__cont.size()) + { return __cont.size(); } + + /** + * @brief Return the size of an array. + */ + template + constexpr size_t + size(const _Tp (&)[_Nm]) noexcept + { return _Nm; } + + /** + * @brief Return whether a container is empty. + * @param __cont Container. + */ + template + [[nodiscard]] constexpr auto + empty(const _Container& __cont) noexcept(noexcept(__cont.empty())) + -> decltype(__cont.empty()) + { return __cont.empty(); } + + /** + * @brief Return whether an array is empty (always false). + */ + template + [[nodiscard]] constexpr bool + empty(const _Tp (&)[_Nm]) noexcept + { return false; } + + /** + * @brief Return whether an initializer_list is empty. + * @param __il Initializer list. + */ + template + [[nodiscard]] constexpr bool + empty(initializer_list<_Tp> __il) noexcept + { return __il.size() == 0;} + + /** + * @brief Return the data pointer of a container. + * @param __cont Container. + */ + template + constexpr auto + data(_Container& __cont) noexcept(noexcept(__cont.data())) + -> decltype(__cont.data()) + { return __cont.data(); } + + /** + * @brief Return the data pointer of a const container. + * @param __cont Container. + */ + template + constexpr auto + data(const _Container& __cont) noexcept(noexcept(__cont.data())) + -> decltype(__cont.data()) + { return __cont.data(); } + + /** + * @brief Return the data pointer of an array. + * @param __array Array. + */ + template + constexpr _Tp* + data(_Tp (&__array)[_Nm]) noexcept + { return __array; } + + /** + * @brief Return the data pointer of an initializer list. + * @param __il Initializer list. + */ + template + constexpr const _Tp* + data(initializer_list<_Tp> __il) noexcept + { return __il.begin(); } + +#endif // C++17 + +#if __cplusplus > 201703L +#define __cpp_lib_ssize 201902L + template + constexpr auto + ssize(const _Container& __cont) + noexcept(noexcept(__cont.size())) + -> common_type_t> + { + using type = make_signed_t; + return static_cast>(__cont.size()); + } + + template + constexpr ptrdiff_t + ssize(const _Tp (&)[_Num]) noexcept + { return _Num; } + +#ifdef __cpp_lib_concepts +namespace ranges +{ + template + inline constexpr bool disable_sized_range = false; + + template + inline constexpr bool enable_borrowed_range = false; + + template + extern const bool enable_view; + + namespace __detail + { + template + constexpr make_unsigned_t<_Tp> + __to_unsigned_like(_Tp __t) noexcept + { return __t; } + + template> + using __make_unsigned_like_t + = conditional_t<_MaxDiff, __max_size_type, make_unsigned_t<_Tp>>; + + // Part of the constraints of ranges::borrowed_range + template + concept __maybe_borrowed_range + = is_lvalue_reference_v<_Tp> + || enable_borrowed_range>; + + } // namespace __detail + + namespace __cust_access + { + using std::ranges::__detail::__maybe_borrowed_range; + using std::__detail::__class_or_enum; + using std::__detail::__decay_copy; + using std::__detail::__member_begin; + using std::__detail::__adl_begin; + + struct _Begin + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_array_v>) + return true; + else if constexpr (__member_begin<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().begin())); + else + return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); + } + + public: + template<__maybe_borrowed_range _Tp> + requires is_array_v> || __member_begin<_Tp> + || __adl_begin<_Tp> + constexpr auto + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (is_array_v>) + { + static_assert(is_lvalue_reference_v<_Tp>); + using _Up = remove_all_extents_t>; + static_assert(sizeof(_Up) != 0, "not array of incomplete type"); + return __t + 0; + } + else if constexpr (__member_begin<_Tp>) + return __t.begin(); + else + return begin(__t); + } + }; + + template + concept __member_end = requires(_Tp& __t) + { + { __decay_copy(__t.end()) } + -> sentinel_for(__t)))>; + }; + + void end(auto&) = delete; + void end(const auto&) = delete; + + template + concept __adl_end = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(end(__t)) } + -> sentinel_for(__t)))>; + }; + + struct _End + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_bounded_array_v>) + return true; + else if constexpr (__member_end<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().end())); + else + return noexcept(__decay_copy(end(std::declval<_Tp&>()))); + } + + public: + template<__maybe_borrowed_range _Tp> + requires is_bounded_array_v> || __member_end<_Tp> + || __adl_end<_Tp> + constexpr auto + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (is_bounded_array_v>) + { + static_assert(is_lvalue_reference_v<_Tp>); + return __t + extent_v>; + } + else if constexpr (__member_end<_Tp>) + return __t.end(); + else + return end(__t); + } + }; + + template + constexpr decltype(auto) + __as_const(_Tp&& __t) noexcept + { + if constexpr (is_lvalue_reference_v<_Tp>) + return static_cast&>(__t); + else + return static_cast(__t); + } + + struct _CBegin + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Begin{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _Begin{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _Begin{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + struct _CEnd + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_End{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _End{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _End{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + template + concept __member_rbegin = requires(_Tp& __t) + { + { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; + }; + + void rbegin(auto&) = delete; + void rbegin(const auto&) = delete; + + template + concept __adl_rbegin = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(rbegin(__t)) } -> input_or_output_iterator; + }; + + template + concept __reversable = requires(_Tp& __t) + { + { _Begin{}(__t) } -> bidirectional_iterator; + { _End{}(__t) } -> same_as; + }; + + struct _RBegin + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_rbegin<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().rbegin())); + else if constexpr (__adl_rbegin<_Tp>) + return noexcept(__decay_copy(rbegin(std::declval<_Tp&>()))); + else + { + if constexpr (noexcept(_End{}(std::declval<_Tp&>()))) + { + using _It = decltype(_End{}(std::declval<_Tp&>())); + // std::reverse_iterator copy-initializes its member. + return is_nothrow_copy_constructible_v<_It>; + } + else + return false; + } + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp> + constexpr auto + operator()(_Tp&& __t) const + noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_rbegin<_Tp>) + return __t.rbegin(); + else if constexpr (__adl_rbegin<_Tp>) + return rbegin(__t); + else + return std::make_reverse_iterator(_End{}(__t)); + } + }; + + template + concept __member_rend = requires(_Tp& __t) + { + { __decay_copy(__t.rend()) } + -> sentinel_for; + }; + + void rend(auto&) = delete; + void rend(const auto&) = delete; + + template + concept __adl_rend = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(rend(__t)) } + -> sentinel_for(__t)))>; + }; + + struct _REnd + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_rend<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().rend())); + else if constexpr (__adl_rend<_Tp>) + return noexcept(__decay_copy(rend(std::declval<_Tp&>()))); + else + { + if constexpr (noexcept(_Begin{}(std::declval<_Tp&>()))) + { + using _It = decltype(_Begin{}(std::declval<_Tp&>())); + // std::reverse_iterator copy-initializes its member. + return is_nothrow_copy_constructible_v<_It>; + } + else + return false; + } + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp> + constexpr auto + operator()(_Tp&& __t) const + noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_rend<_Tp>) + return __t.rend(); + else if constexpr (__adl_rend<_Tp>) + return rend(__t); + else + return std::make_reverse_iterator(_Begin{}(__t)); + } + }; + + struct _CRBegin + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_RBegin{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _RBegin{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _RBegin{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + struct _CREnd + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_REnd{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _REnd{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _REnd{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + template + concept __member_size = !disable_sized_range> + && requires(_Tp&& __t) + { + { __decay_copy(std::forward<_Tp>(__t).size()) } + -> __detail::__is_integer_like; + }; + + void size(auto&) = delete; + void size(const auto&) = delete; + + template + concept __adl_size = __class_or_enum> + && !disable_sized_range> + && requires(_Tp&& __t) + { + { __decay_copy(size(std::forward<_Tp>(__t))) } + -> __detail::__is_integer_like; + }; + + template + concept __sentinel_size = requires(_Tp&& __t) + { + { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator; + + { _End{}(std::forward<_Tp>(__t)) } + -> sized_sentinel_for(__t)))>; + }; + + struct _Size + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_bounded_array_v>) + return true; + else if constexpr (__member_size<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp>().size())); + else if constexpr (__adl_size<_Tp>) + return noexcept(__decay_copy(size(std::declval<_Tp>()))); + else if constexpr (__sentinel_size<_Tp>) + return noexcept(_End{}(std::declval<_Tp>()) + - _Begin{}(std::declval<_Tp>())); + } + + public: + template + requires is_bounded_array_v> + || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp> + constexpr auto + operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (is_bounded_array_v>) + { + return extent_v>; + } + else if constexpr (__member_size<_Tp>) + return std::forward<_Tp>(__e).size(); + else if constexpr (__adl_size<_Tp>) + return size(std::forward<_Tp>(__e)); + else if constexpr (__sentinel_size<_Tp>) + return __detail::__to_unsigned_like( + _End{}(std::forward<_Tp>(__e)) + - _Begin{}(std::forward<_Tp>(__e))); + } + }; + + struct _SSize + { + template + requires requires (_Tp&& __e) + { + _Begin{}(std::forward<_Tp>(__e)); + _Size{}(std::forward<_Tp>(__e)); + } + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Size{}(std::forward<_Tp>(__e)))) + { + using __iter_type = decltype(_Begin{}(std::forward<_Tp>(__e))); + using __diff_type = iter_difference_t<__iter_type>; + using __gnu_cxx::__int_traits; + auto __size = _Size{}(std::forward<_Tp>(__e)); + if constexpr (integral<__diff_type>) + { + if constexpr (__int_traits<__diff_type>::__digits + < __int_traits::__digits) + return static_cast(__size); + } + return static_cast<__diff_type>(__size); + } + }; + + template + concept __member_empty = requires(_Tp&& __t) + { bool(std::forward<_Tp>(__t).empty()); }; + + template + concept __size0_empty = requires(_Tp&& __t) + { _Size{}(std::forward<_Tp>(__t)) == 0; }; + + template + concept __eq_iter_empty = requires(_Tp&& __t) + { + { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator; + bool(_Begin{}(std::forward<_Tp>(__t)) + == _End{}(std::forward<_Tp>(__t))); + }; + + struct _Empty + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_empty<_Tp>) + return noexcept(std::declval<_Tp>().empty()); + else if constexpr (__size0_empty<_Tp>) + return noexcept(_Size{}(std::declval<_Tp>()) == 0); + else + return noexcept(bool(_Begin{}(std::declval<_Tp>()) + == _End{}(std::declval<_Tp>()))); + } + + public: + template + requires __member_empty<_Tp> || __size0_empty<_Tp> + || __eq_iter_empty<_Tp> + constexpr bool + operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_empty<_Tp>) + return bool(std::forward<_Tp>(__e).empty()); + else if constexpr (__size0_empty<_Tp>) + return _Size{}(std::forward<_Tp>(__e)) == 0; + else + return bool(_Begin{}(std::forward<_Tp>(__e)) + == _End{}(std::forward<_Tp>(__e))); + } + }; + + template + concept __pointer_to_object = is_pointer_v<_Tp> + && is_object_v>; + + template + concept __member_data = is_lvalue_reference_v<_Tp> + && requires(_Tp __t) { { __t.data() } -> __pointer_to_object; }; + + template + concept __begin_data = requires(_Tp&& __t) + { { _Begin{}(std::forward<_Tp>(__t)) } -> contiguous_iterator; }; + + struct _Data + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_data<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp>().data())); + else + return noexcept(_Begin{}(std::declval<_Tp>())); + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_data<_Tp> || __begin_data<_Tp> + constexpr auto + operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_data<_Tp>) + return __e.data(); + else + return std::to_address(_Begin{}(std::forward<_Tp>(__e))); + } + }; + + struct _CData + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Data{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _Data{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _Data{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + } // namespace __cust_access + + inline namespace __cust + { + inline constexpr __cust_access::_Begin begin{}; + inline constexpr __cust_access::_End end{}; + inline constexpr __cust_access::_CBegin cbegin{}; + inline constexpr __cust_access::_CEnd cend{}; + inline constexpr __cust_access::_RBegin rbegin{}; + inline constexpr __cust_access::_REnd rend{}; + inline constexpr __cust_access::_CRBegin crbegin{}; + inline constexpr __cust_access::_CREnd crend{}; + inline constexpr __cust_access::_Size size{}; + inline constexpr __cust_access::_SSize ssize{}; + inline constexpr __cust_access::_Empty empty{}; + inline constexpr __cust_access::_Data data{}; + inline constexpr __cust_access::_CData cdata{}; + } + + /// [range.range] The range concept. + template + concept range = requires(_Tp& __t) + { + ranges::begin(__t); + ranges::end(__t); + }; + + /// [range.range] The borrowed_range concept. + template + concept borrowed_range + = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>; + + template + using iterator_t = std::__detail::__range_iter_t<_Tp>; + + template + using sentinel_t = decltype(ranges::end(std::declval<_Range&>())); + + template + using range_difference_t = iter_difference_t>; + + template + using range_value_t = iter_value_t>; + + template + using range_reference_t = iter_reference_t>; + + template + using range_rvalue_reference_t + = iter_rvalue_reference_t>; + + /// [range.sized] The sized_range concept. + template + concept sized_range = range<_Tp> + && requires(_Tp& __t) { ranges::size(__t); }; + + template + using range_size_t = decltype(ranges::size(std::declval<_Range&>())); + + // [range.refinements] + + /// A range for which ranges::begin returns an output iterator. + template + concept output_range + = range<_Range> && output_iterator, _Tp>; + + /// A range for which ranges::begin returns an input iterator. + template + concept input_range = range<_Tp> && input_iterator>; + + /// A range for which ranges::begin returns a forward iterator. + template + concept forward_range + = input_range<_Tp> && forward_iterator>; + + /// A range for which ranges::begin returns a bidirectional iterator. + template + concept bidirectional_range + = forward_range<_Tp> && bidirectional_iterator>; + + /// A range for which ranges::begin returns a random access iterator. + template + concept random_access_range + = bidirectional_range<_Tp> && random_access_iterator>; + + /// A range for which ranges::begin returns a contiguous iterator. + template + concept contiguous_range + = random_access_range<_Tp> && contiguous_iterator> + && requires(_Tp& __t) + { + { ranges::data(__t) } -> same_as>>; + }; + + /// A range for which ranges::begin and ranges::end return the same type. + template + concept common_range + = range<_Tp> && same_as, sentinel_t<_Tp>>; + + // [range.iter.ops] range iterator operations + + template + constexpr void + advance(_It& __it, iter_difference_t<_It> __n) + { + if constexpr (random_access_iterator<_It>) + __it += __n; + else if constexpr (bidirectional_iterator<_It>) + { + if (__n > 0) + { + do + { + ++__it; + } + while (--__n); + } + else if (__n < 0) + { + do + { + --__it; + } + while (++__n); + } + } + else + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated() && __n < 0) + throw "attempt to decrement a non-bidirectional iterator"; +#endif + __glibcxx_assert(__n >= 0); + while (__n-- > 0) + ++__it; + } + } + + template _Sent> + constexpr void + advance(_It& __it, _Sent __bound) + { + if constexpr (assignable_from<_It&, _Sent>) + __it = std::move(__bound); + else if constexpr (sized_sentinel_for<_Sent, _It>) + ranges::advance(__it, __bound - __it); + else + { + while (__it != __bound) + ++__it; + } + } + + template _Sent> + constexpr iter_difference_t<_It> + advance(_It& __it, iter_difference_t<_It> __n, _Sent __bound) + { + if constexpr (sized_sentinel_for<_Sent, _It>) + { + const auto __diff = __bound - __it; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated() + && !(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0))) + throw "inconsistent directions for distance and bound"; +#endif + // n and bound must not lead in opposite directions: + __glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0)); + const auto __absdiff = __diff < 0 ? -__diff : __diff; + const auto __absn = __n < 0 ? -__n : __n;; + if (__absn >= __absdiff) + { + ranges::advance(__it, __bound); + return __n - __diff; + } + else + { + ranges::advance(__it, __n); + return 0; + } + } + else if (__it == __bound || __n == 0) + return iter_difference_t<_It>(0); + else if (__n > 0) + { + iter_difference_t<_It> __m = 0; + do + { + ++__it; + ++__m; + } + while (__m != __n && __it != __bound); + return __n - __m; + } + else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>) + { + iter_difference_t<_It> __m = 0; + do + { + --__it; + --__m; + } + while (__m != __n && __it != __bound); + return __n - __m; + } + else + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated() && __n < 0) + throw "attempt to decrement a non-bidirectional iterator"; +#endif + __glibcxx_assert(__n >= 0); + return __n; + } + } + + template _Sent> + constexpr iter_difference_t<_It> + distance(_It __first, _Sent __last) + { + if constexpr (sized_sentinel_for<_Sent, _It>) + return __last - __first; + else + { + iter_difference_t<_It> __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } + } + + template + constexpr range_difference_t<_Range> + distance(_Range&& __r) + { + if constexpr (sized_range<_Range>) + return static_cast>(ranges::size(__r)); + else + return ranges::distance(ranges::begin(__r), ranges::end(__r)); + } + + template + constexpr _It + next(_It __x) + { + ++__x; + return __x; + } + + template + constexpr _It + next(_It __x, iter_difference_t<_It> __n) + { + ranges::advance(__x, __n); + return __x; + } + + template _Sent> + constexpr _It + next(_It __x, _Sent __bound) + { + ranges::advance(__x, __bound); + return __x; + } + + template _Sent> + constexpr _It + next(_It __x, iter_difference_t<_It> __n, _Sent __bound) + { + ranges::advance(__x, __n, __bound); + return __x; + } + + template + constexpr _It + prev(_It __x) + { + --__x; + return __x; + } + + template + constexpr _It + prev(_It __x, iter_difference_t<_It> __n) + { + ranges::advance(__x, -__n); + return __x; + } + + template + constexpr _It + prev(_It __x, iter_difference_t<_It> __n, _It __bound) + { + ranges::advance(__x, -__n, __bound); + return __x; + } + +} // namespace ranges +#endif // library concepts +#endif // C++20 +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _GLIBCXX_RANGE_ACCESS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/range_cmp.h b/resources/sources/avr-libstdcpp/include/bits/range_cmp.h new file mode 100644 index 000000000..0587c599c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/range_cmp.h @@ -0,0 +1,195 @@ +// Concept-constrained comparison implementations -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/range_cmp.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _RANGE_CMP_H +#define _RANGE_CMP_H 1 + +#if __cplusplus > 201703L +# include +# include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct __is_transparent; // not defined + + // Define std::identity here so that and + // don't need to include to get it. + + /// [func.identity] The identity function. + struct identity + { + template + constexpr _Tp&& + operator()(_Tp&& __t) const noexcept + { return std::forward<_Tp>(__t); } + + using is_transparent = __is_transparent; + }; + +#ifdef __cpp_lib_concepts +// Define this here, included by all the headers that need to define it. +#define __cpp_lib_ranges 201911L + +namespace ranges +{ + namespace __detail + { + // BUILTIN-PTR-CMP(T, ==, U) + template + concept __eq_builtin_ptr_cmp + = requires (_Tp&& __t, _Up&& __u) { { __t == __u } -> same_as; } + && convertible_to<_Tp, const volatile void*> + && convertible_to<_Up, const volatile void*> + && (! requires(_Tp&& __t, _Up&& __u) + { operator==(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + && + ! requires(_Tp&& __t, _Up&& __u) + { std::forward<_Tp>(__t).operator==(std::forward<_Up>(__u)); }); + + // BUILTIN-PTR-CMP(T, <, U) + template + concept __less_builtin_ptr_cmp + = requires (_Tp&& __t, _Up&& __u) { { __t < __u } -> same_as; } + && convertible_to<_Tp, const volatile void*> + && convertible_to<_Up, const volatile void*> + && (! requires(_Tp&& __t, _Up&& __u) + { operator<(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + && ! requires(_Tp&& __t, _Up&& __u) + { std::forward<_Tp>(__t).operator<(std::forward<_Up>(__u)); }); + } // namespace __detail + + // [range.cmp] Concept-constrained comparisons + + /// ranges::equal_to function object type. + struct equal_to + { + template + requires equality_comparable_with<_Tp, _Up> + || __detail::__eq_builtin_ptr_cmp<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) + { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } + + using is_transparent = __is_transparent; + }; + + /// ranges::not_equal_to function object type. + struct not_equal_to + { + template + requires equality_comparable_with<_Tp, _Up> + || __detail::__eq_builtin_ptr_cmp<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() == std::declval<_Tp>())) + { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::less function object type. + struct less + { + template + requires totally_ordered_with<_Tp, _Up> + || __detail::__less_builtin_ptr_cmp<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) + { + if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __t < __u; +#endif + auto __x = reinterpret_cast<__UINTPTR_TYPE__>( + static_cast(std::forward<_Tp>(__t))); + auto __y = reinterpret_cast<__UINTPTR_TYPE__>( + static_cast(std::forward<_Up>(__u))); + return __x < __y; + } + else + return std::forward<_Tp>(__t) < std::forward<_Up>(__u); + } + + using is_transparent = __is_transparent; + }; + + /// ranges::greater function object type. + struct greater + { + template + requires totally_ordered_with<_Tp, _Up> + || __detail::__less_builtin_ptr_cmp<_Up, _Tp> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) + { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::greater_equal function object type. + struct greater_equal + { + template + requires totally_ordered_with<_Tp, _Up> + || __detail::__less_builtin_ptr_cmp<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) + { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::less_equal function object type. + struct less_equal + { + template + requires totally_ordered_with<_Tp, _Up> + || __detail::__less_builtin_ptr_cmp<_Up, _Tp> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) + { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } + + using is_transparent = __is_transparent; + }; + +} // namespace ranges +#endif // library concepts +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 +#endif // _RANGE_CMP_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h b/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h new file mode 100644 index 000000000..4d4f74016 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h @@ -0,0 +1,3792 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_algo.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _RANGES_ALGO_H +#define _RANGES_ALGO_H 1 + +#if __cplusplus > 201703L + +#include +#include // concept uniform_random_bit_generator + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr auto + __make_comp_proj(_Comp& __comp, _Proj& __proj) + { + return [&] (auto&& __lhs, auto&& __rhs) -> bool { + using _TL = decltype(__lhs); + using _TR = decltype(__rhs); + return std::__invoke(__comp, + std::__invoke(__proj, std::forward<_TL>(__lhs)), + std::__invoke(__proj, std::forward<_TR>(__rhs))); + }; + } + + template + constexpr auto + __make_pred_proj(_Pred& __pred, _Proj& __proj) + { + return [&] (_Tp&& __arg) -> bool { + return std::__invoke(__pred, + std::__invoke(__proj, std::forward<_Tp>(__arg))); + }; + } + } // namespace __detail + + struct __all_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __all_of_fn all_of{}; + + struct __any_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return true; + return false; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __any_of_fn any_of{}; + + struct __none_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __none_of_fn none_of{}; + + template + struct in_fun_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Fp fun; + + template + requires convertible_to + && convertible_to + constexpr + operator in_fun_result<_Iter2, _F2p>() const & + { return {in, fun}; } + + template + requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p> + constexpr + operator in_fun_result<_Iter2, _F2p>() && + { return {std::move(in), std::move(fun)}; } + }; + + template + using for_each_result = in_fun_result<_Iter, _Fp>; + + struct __for_each_fn + { + template _Sent, + typename _Proj = identity, + indirectly_unary_invocable> _Fun> + constexpr for_each_result<_Iter, _Fun> + operator()(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + std::__invoke(__f, std::__invoke(__proj, *__first)); + return { std::move(__first), std::move(__f) }; + } + + template, _Proj>> + _Fun> + constexpr for_each_result, _Fun> + operator()(_Range&& __r, _Fun __f, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__f), std::move(__proj)); + } + }; + + inline constexpr __for_each_fn for_each{}; + + template + using for_each_n_result = in_fun_result<_Iter, _Fp>; + + struct __for_each_n_fn + { + template> _Fun> + constexpr for_each_n_result<_Iter, _Fun> + operator()(_Iter __first, iter_difference_t<_Iter> __n, + _Fun __f, _Proj __proj = {}) const + { + if constexpr (random_access_iterator<_Iter>) + { + if (__n <= 0) + return {std::move(__first), std::move(__f)}; + auto __last = __first + __n; + return ranges::for_each(std::move(__first), std::move(__last), + std::move(__f), std::move(__proj)); + } + else + { + while (__n-- > 0) + { + std::__invoke(__f, std::__invoke(__proj, *__first)); + ++__first; + } + return {std::move(__first), std::move(__f)}; + } + } + }; + + inline constexpr __for_each_n_fn for_each_n{}; + + struct __find_fn + { + template _Sent, typename _Tp, + typename _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + while (__first != __last + && !(std::__invoke(__proj, *__first) == __value)) + ++__first; + return __first; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __find_fn find{}; + + struct __find_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + while (__first != __last + && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __find_if_fn find_if{}; + + struct __find_if_not_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + while (__first != __last + && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __find_if_not_fn find_if_not{}; + + struct __find_first_of_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr _Iter1 + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + for (; __first1 != __last1; ++__first1) + for (auto __iter = __first2; __iter != __last2; ++__iter) + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__iter))) + return __first1; + return __first1; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_iterator_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __find_first_of_fn find_first_of{}; + + struct __count_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __value) + ++__n; + return __n; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr range_difference_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __count_fn count{}; + + struct __count_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__n; + return __n; + } + + template, _Proj>> + _Pred> + constexpr range_difference_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __count_if_fn count_if{}; + + template + struct in_in_result + { + [[no_unique_address]] _Iter1 in1; + [[no_unique_address]] _Iter2 in2; + + template + requires convertible_to + && convertible_to + constexpr + operator in_in_result<_IIter1, _IIter2>() const & + { return {in1, in2}; } + + template + requires convertible_to<_Iter1, _IIter1> + && convertible_to<_Iter2, _IIter2> + constexpr + operator in_in_result<_IIter1, _IIter2>() && + { return {std::move(in1), std::move(in2)}; } + }; + + template + using mismatch_result = in_in_result<_Iter1, _Iter2>; + + struct __mismatch_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr mismatch_result<_Iter1, _Iter2> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2 + && (bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + ++__first1; + ++__first2; + } + return { std::move(__first1), std::move(__first2) }; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr mismatch_result, iterator_t<_Range2>> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __mismatch_fn mismatch{}; + + struct __search_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if (__first1 == __last1 || __first2 == __last2) + return {__first1, __first1}; + + for (;;) + { + for (;;) + { + if (__first1 == __last1) + return {__first1, __first1}; + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + ++__first1; + } + auto __cur1 = __first1; + auto __cur2 = __first2; + for (;;) + { + if (++__cur2 == __last2) + return {__first1, ++__cur1}; + if (++__cur1 == __last1) + return {__cur1, __cur1}; + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__cur1), + std::__invoke(__proj2, *__cur2))) + { + ++__first1; + break; + } + } + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_subrange_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __search_fn search{}; + + struct __search_n_fn + { + template _Sent, typename _Tp, + typename _Pred = ranges::equal_to, typename _Proj = identity> + requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const + { + if (__count <= 0) + return {__first, __first}; + + auto __value_comp = [&] (_Rp&& __arg) { + return std::__invoke(__pred, std::forward<_Rp>(__arg), __value); + }; + if (__count == 1) + { + __first = ranges::find_if(std::move(__first), __last, + std::move(__value_comp), + std::move(__proj)); + if (__first == __last) + return {__first, __first}; + else + { + auto __end = __first; + return {__first, ++__end}; + } + } + + if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + auto __tail_size = __last - __first; + auto __remainder = __count; + + while (__remainder <= __tail_size) + { + __first += __remainder; + __tail_size -= __remainder; + auto __backtrack = __first; + while (__value_comp(std::__invoke(__proj, *--__backtrack))) + { + if (--__remainder == 0) + return {__first - __count, __first}; + } + } + auto __i = __first + __tail_size; + return {__i, __i}; + } + else + { + __first = ranges::find_if(__first, __last, __value_comp, __proj); + while (__first != __last) + { + auto __n = __count; + auto __i = __first; + ++__i; + while (__i != __last && __n != 1 + && __value_comp(std::__invoke(__proj, *__i))) + { + ++__i; + --__n; + } + if (__n == 1) + return {__first, __i}; + if (__i == __last) + return {__i, __i}; + __first = ranges::find_if(++__i, __last, __value_comp, __proj); + } + return {__first, __first}; + } + } + + template + requires indirectly_comparable, const _Tp*, + _Pred, _Proj> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, range_difference_t<_Range> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__count), __value, + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __search_n_fn search_n{}; + + struct __find_end_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if constexpr (bidirectional_iterator<_Iter1> + && bidirectional_iterator<_Iter2>) + { + auto __i1 = ranges::next(__first1, __last1); + auto __i2 = ranges::next(__first2, __last2); + auto __rresult + = ranges::search(reverse_iterator<_Iter1>{__i1}, + reverse_iterator<_Iter1>{__first1}, + reverse_iterator<_Iter2>{__i2}, + reverse_iterator<_Iter2>{__first2}, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + auto __result_first = ranges::end(__rresult).base(); + auto __result_last = ranges::begin(__rresult).base(); + if (__result_last == __first1) + return {__i1, __i1}; + else + return {__result_first, __result_last}; + } + else + { + auto __i = ranges::next(__first1, __last1); + if (__first2 == __last2) + return {__i, __i}; + + auto __result_begin = __i; + auto __result_end = __i; + for (;;) + { + auto __new_range = ranges::search(__first1, __last1, + __first2, __last2, + __pred, __proj1, __proj2); + auto __new_result_begin = ranges::begin(__new_range); + auto __new_result_end = ranges::end(__new_range); + if (__new_result_begin == __last1) + return {__result_begin, __result_end}; + else + { + __result_begin = __new_result_begin; + __result_end = __new_result_end; + __first1 = __result_begin; + ++__first1; + } + } + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_subrange_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __find_end_fn find_end{}; + + struct __adjacent_find_fn + { + template _Sent, + typename _Proj = identity, + indirect_binary_predicate, + projected<_Iter, _Proj>> _Pred + = ranges::equal_to> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + auto __next = __first; + for (; ++__next != __last; __first = __next) + { + if (std::__invoke(__pred, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + return __first; + } + return __next; + } + + template, _Proj>, + projected, _Proj>> _Pred = ranges::equal_to> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __adjacent_find_fn adjacent_find{}; + + struct __is_permutation_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_equivalence_relation, + projected<_Iter2, _Proj2>> _Pred + = ranges::equal_to> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + + if constexpr (__sized_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (auto __scan = __first1; __scan != __last1; ++__scan) + { + auto __proj_scan = std::__invoke(__proj1, *__scan); + auto __comp_scan = [&] (_Tp&& __arg) { + return std::__invoke(__pred, __proj_scan, + std::forward<_Tp>(__arg)); + }; + if (__scan != ranges::find_if(__first1, __scan, + __comp_scan, __proj1)) + continue; // We've seen this one before. + + auto __matches = ranges::count_if(__first2, __last2, + __comp_scan, __proj2); + if (__matches == 0 + || ranges::count_if(__scan, __last1, + __comp_scan, __proj1) != __matches) + return false; + } + return true; + } + + template, _Proj1>, + projected, _Proj2>> _Pred = ranges::equal_to> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __is_permutation_fn is_permutation{}; + + template + using copy_if_result = in_out_result<_Iter, _Out>; + + struct __copy_if_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __copy_if_fn copy_if{}; + + template + using swap_ranges_result = in_in_result<_Iter1, _Iter2>; + + struct __swap_ranges_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2> + requires indirectly_swappable<_Iter1, _Iter2> + constexpr swap_ranges_result<_Iter1, _Iter2> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2) const + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + ranges::iter_swap(__first1, __first2); + return {std::move(__first1), std::move(__first2)}; + } + + template + requires indirectly_swappable, iterator_t<_Range2>> + constexpr swap_ranges_result, + borrowed_iterator_t<_Range2>> + operator()(_Range1&& __r1, _Range2&& __r2) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2)); + } + }; + + inline constexpr __swap_ranges_fn swap_ranges{}; + + template + using unary_transform_result = in_out_result<_Iter, _Out>; + + template + struct in_in_out_result + { + [[no_unique_address]] _Iter1 in1; + [[no_unique_address]] _Iter2 in2; + [[no_unique_address]] _Out out; + + template + requires convertible_to + && convertible_to + && convertible_to + constexpr + operator in_in_out_result<_IIter1, _IIter2, _OOut>() const & + { return {in1, in2, out}; } + + template + requires convertible_to<_Iter1, _IIter1> + && convertible_to<_Iter2, _IIter2> + && convertible_to<_Out, _OOut> + constexpr + operator in_in_out_result<_IIter1, _IIter2, _OOut>() && + { return {std::move(in1), std::move(in2), std::move(out)}; } + }; + + template + using binary_transform_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __transform_fn + { + template _Sent, + weakly_incrementable _Out, + copy_constructible _Fp, typename _Proj = identity> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected<_Iter, _Proj>>> + constexpr unary_transform_result<_Iter, _Out> + operator()(_Iter __first1, _Sent __last1, _Out __result, + _Fp __op, _Proj __proj = {}) const + { + for (; __first1 != __last1; ++__first1, (void)++__result) + *__result = std::__invoke(__op, std::__invoke(__proj, *__first1)); + return {std::move(__first1), std::move(__result)}; + } + + template + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj>>> + constexpr unary_transform_result, _Out> + operator()(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__op), std::move(__proj)); + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, copy_constructible _Fp, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>>> + constexpr binary_transform_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Fp __binary_op, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2, ++__result) + *__result = std::__invoke(__binary_op, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2)); + return {std::move(__first1), std::move(__first2), std::move(__result)}; + } + + template + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj1>, + projected, _Proj2>>> + constexpr binary_transform_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, _Fp __binary_op, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__binary_op), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __transform_fn transform{}; + + struct __replace_fn + { + template _Sent, + typename _Tp1, typename _Tp2, typename _Proj = identity> + requires indirectly_writable<_Iter, const _Tp2&> + && indirect_binary_predicate, + const _Tp1*> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __old_value) + *__first = __new_value; + return __first; + } + + template + requires indirectly_writable, const _Tp2&> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __old_value, __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_fn replace{}; + + struct __replace_if_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_writable<_Iter, const _Tp&> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__first = __new_value; + return std::move(__first); + } + + template, _Proj>> + _Pred> + requires indirectly_writable, const _Tp&> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_if_fn replace_if{}; + + template + using replace_copy_result = in_out_result<_Iter, _Out>; + + struct __replace_copy_fn + { + template _Sent, + typename _Tp1, typename _Tp2, output_iterator _Out, + typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, const _Tp1*> + constexpr replace_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__proj, *__first) == __old_value) + *__result = __new_value; + else + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + + template _Out, typename _Proj = identity> + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr replace_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), __old_value, + __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_copy_fn replace_copy{}; + + template + using replace_copy_if_result = in_out_result<_Iter, _Out>; + + struct __replace_copy_if_fn + { + template _Sent, + typename _Tp, output_iterator _Out, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr replace_copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__result = __new_value; + else + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + + template _Out, + typename _Proj = identity, + indirect_unary_predicate, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr replace_copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), std::move(__pred), + __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_copy_if_fn replace_copy_if{}; + + struct __generate_n_fn + { + template + requires invocable<_Fp&> + && indirectly_writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + operator()(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) const + { + for (; __n > 0; --__n, (void)++__first) + *__first = std::__invoke(__gen); + return __first; + } + }; + + inline constexpr __generate_n_fn generate_n{}; + + struct __generate_fn + { + template _Sent, + copy_constructible _Fp> + requires invocable<_Fp&> + && indirectly_writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + operator()(_Out __first, _Sent __last, _Fp __gen) const + { + for (; __first != __last; ++__first) + *__first = std::__invoke(__gen); + return __first; + } + + template + requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Fp __gen) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__gen)); + } + }; + + inline constexpr __generate_fn generate{}; + + struct __remove_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + __first = ranges::find_if(__first, __last, __pred, __proj); + if (__first == __last) + return {__first, __first}; + + auto __result = __first; + ++__first; + for (; __first != __last; ++__first) + if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = std::move(*__first); + ++__result; + } + + return {__result, __first}; + } + + template, _Proj>> + _Pred> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __remove_if_fn remove_if{}; + + struct __remove_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + auto __pred = [&] (auto&& __arg) { + return std::forward(__arg) == __value; + }; + return ranges::remove_if(__first, __last, + std::move(__pred), std::move(__proj)); + } + + template + requires permutable> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __remove_fn remove{}; + + template + using remove_copy_if_result = in_out_result<_Iter, _Out>; + + struct __remove_copy_if_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr remove_copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr remove_copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __remove_copy_if_fn remove_copy_if{}; + + template + using remove_copy_result = in_out_result<_Iter, _Out>; + + struct __remove_copy_fn + { + template _Sent, + weakly_incrementable _Out, typename _Tp, typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, + const _Tp*> + constexpr remove_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + const _Tp& __value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(std::__invoke(__proj, *__first) == __value)) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr remove_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), __value, std::move(__proj)); + } + }; + + inline constexpr __remove_copy_fn remove_copy{}; + + struct __unique_fn + { + template _Sent, + typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + __first = ranges::adjacent_find(__first, __last, __comp, __proj); + if (__first == __last) + return {__first, __first}; + + auto __dest = __first; + ++__first; + while (++__first != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__dest), + std::__invoke(__proj, *__first))) + *++__dest = std::move(*__first); + return {++__dest, __first}; + } + + template, _Proj>> _Comp = ranges::equal_to> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __unique_fn unique{}; + + template + using unique_copy_result = in_out_result<_Iter, _Out>; + + struct __unique_copy_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable<_Iter, _Out> + && (forward_iterator<_Iter> + || (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + || indirectly_copyable_storable<_Iter, _Out>) + constexpr unique_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), std::move(__result)}; + + // TODO: perform a closer comparison with reference implementations + if constexpr (forward_iterator<_Iter>) + { + auto __next = __first; + *__result = *__next; + while (++__next != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + { + __first = __next; + *++__result = *__first; + } + return {__next, std::move(++__result)}; + } + else if constexpr (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + { + *__result = *__first; + while (++__first != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__result), + std::__invoke(__proj, *__first))) + *++__result = *__first; + return {std::move(__first), std::move(++__result)}; + } + else // indirectly_copyable_storable<_Iter, _Out> + { + auto __value = *__first; + *__result = __value; + while (++__first != __last) + { + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, __value))) + { + __value = *__first; + *++__result = __value; + } + } + return {std::move(__first), std::move(++__result)}; + } + } + + template, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable, _Out> + && (forward_iterator> + || (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + || indirectly_copyable_storable, _Out>) + constexpr unique_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __unique_copy_fn unique_copy{}; + + struct __reverse_fn + { + template _Sent> + requires permutable<_Iter> + constexpr _Iter + operator()(_Iter __first, _Sent __last) const + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + + if constexpr (random_access_iterator<_Iter>) + { + if (__first != __last) + { + --__tail; + while (__first < __tail) + { + ranges::iter_swap(__first, __tail); + ++__first; + --__tail; + } + } + return __i; + } + else + { + for (;;) + if (__first == __tail || __first == --__tail) + break; + else + { + ranges::iter_swap(__first, __tail); + ++__first; + } + return __i; + } + } + + template + requires permutable> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __reverse_fn reverse{}; + + template + using reverse_copy_result = in_out_result<_Iter, _Out>; + + struct __reverse_copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr reverse_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + while (__first != __tail) + { + --__tail; + *__result = *__tail; + ++__result; + } + return {__i, __result}; + } + + template + requires indirectly_copyable, _Out> + constexpr reverse_copy_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __reverse_copy_fn reverse_copy{}; + + struct __rotate_fn + { + template _Sent> + constexpr subrange<_Iter> + operator()(_Iter __first, _Iter __middle, _Sent __last) const + { + auto __lasti = ranges::next(__first, __last); + if (__first == __middle) + return {__lasti, __lasti}; + if (__last == __middle) + return {std::move(__first), std::move(__lasti)}; + + if constexpr (random_access_iterator<_Iter>) + { + auto __n = __lasti - __first; + auto __k = __middle - __first; + + if (__k == __n - __k) + { + ranges::swap_ranges(__first, __middle, __middle, __middle + __k); + return {std::move(__middle), std::move(__lasti)}; + } + + auto __p = __first; + auto __ret = __first + (__lasti - __middle); + + for (;;) + { + if (__k < __n - __k) + { + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*__p); + ranges::move(__p + 1, __p + __n, __p); + *(__p + __n - 1) = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + ranges::iter_swap(__p, __q); + ++__p; + ++__q; + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + ranges::swap(__n, __k); + __k = __n - __k; + } + else + { + __k = __n - __k; + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*(__p + __n - 1)); + ranges::move_backward(__p, __p + __n - 1, __p + __n); + *__p = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __n; + __p = __q - __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + ranges::iter_swap(__p, __q); + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + std::swap(__n, __k); + } + } + } + else if constexpr (bidirectional_iterator<_Iter>) + { + auto __tail = __lasti; + + ranges::reverse(__first, __middle); + ranges::reverse(__middle, __tail); + + while (__first != __middle && __middle != __tail) + { + ranges::iter_swap(__first, --__tail); + ++__first; + } + + if (__first == __middle) + { + ranges::reverse(__middle, __tail); + return {std::move(__tail), std::move(__lasti)}; + } + else + { + ranges::reverse(__first, __middle); + return {std::move(__first), std::move(__lasti)}; + } + } + else + { + auto __first2 = __middle; + do + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + } while (__first2 != __last); + + auto __ret = __first; + + __first2 = __middle; + + while (__first2 != __last) + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + return {std::move(__ret), std::move(__lasti)}; + } + } + + template + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r)); + } + }; + + inline constexpr __rotate_fn rotate{}; + + template + using rotate_copy_result = in_out_result<_Iter, _Out>; + + struct __rotate_copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr rotate_copy_result<_Iter, _Out> + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Out __result) const + { + auto __copy1 = ranges::copy(__middle, + std::move(__last), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first), + std::move(__middle), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.out) }; + } + + template + requires indirectly_copyable, _Out> + constexpr rotate_copy_result, _Out> + operator()(_Range&& __r, iterator_t<_Range> __middle, _Out __result) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), std::move(__result)); + } + }; + + inline constexpr __rotate_copy_fn rotate_copy{}; + + struct __sample_fn + { + template _Sent, + weakly_incrementable _Out, typename _Gen> + requires (forward_iterator<_Iter> || random_access_iterator<_Out>) + && indirectly_copyable<_Iter, _Out> + && uniform_random_bit_generator> + _Out + operator()(_Iter __first, _Sent __last, _Out __out, + iter_difference_t<_Iter> __n, _Gen&& __g) const + { + if constexpr (forward_iterator<_Iter>) + { + // FIXME: Forwarding to std::sample here requires computing __lasti + // which may take linear time. + auto __lasti = ranges::next(__first, __last); + return std::sample(std::move(__first), std::move(__lasti), + std::move(__out), __n, std::forward<_Gen>(__g)); + } + else + { + using __distrib_type + = uniform_int_distribution>; + using __param_type = typename __distrib_type::param_type; + __distrib_type __d{}; + iter_difference_t<_Iter> __sample_sz = 0; + while (__first != __last && __sample_sz != __n) + { + __out[__sample_sz++] = *__first; + ++__first; + } + for (auto __pop_sz = __sample_sz; __first != __last; + ++__first, (void) ++__pop_sz) + { + const auto __k = __d(__g, __param_type{0, __pop_sz}); + if (__k < __n) + __out[__k] = *__first; + } + return __out + __sample_sz; + } + } + + template + requires (forward_range<_Range> || random_access_iterator<_Out>) + && indirectly_copyable, _Out> + && uniform_random_bit_generator> + _Out + operator()(_Range&& __r, _Out __out, + range_difference_t<_Range> __n, _Gen&& __g) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__out), __n, + std::forward<_Gen>(__g)); + } + }; + + inline constexpr __sample_fn sample{}; + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + struct __shuffle_fn + { + template _Sent, + typename _Gen> + requires permutable<_Iter> + && uniform_random_bit_generator> + _Iter + operator()(_Iter __first, _Sent __last, _Gen&& __g) const + { + auto __lasti = ranges::next(__first, __last); + std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g)); + return __lasti; + } + + template + requires permutable> + && uniform_random_bit_generator> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Gen&& __g) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::forward<_Gen>(__g)); + } + }; + + inline constexpr __shuffle_fn shuffle{}; +#endif + + struct __push_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::push_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __push_heap_fn push_heap{}; + + struct __pop_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::pop_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __pop_heap_fn pop_heap{}; + + struct __make_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::make_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __make_heap_fn make_heap{}; + + struct __sort_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::sort_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __sort_heap_fn sort_heap{}; + + struct __is_heap_until_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = ranges::distance(__first, __last); + iter_difference_t<_Iter> __parent = 0, __child = 1; + for (; __child < __n; ++__child) + if (std::__invoke(__comp, + std::__invoke(__proj, *(__first + __parent)), + std::__invoke(__proj, *(__first + __child)))) + return __first + __child; + else if ((__child & 1) == 0) + ++__parent; + + return __first + __n; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_heap_until_fn is_heap_until{}; + + struct __is_heap_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (__last + == ranges::is_heap_until(__first, __last, + std::move(__comp), + std::move(__proj))); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_heap_fn is_heap{}; + + struct __sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __sort_fn sort{}; + + struct __stable_sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::stable_sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __stable_sort_fn stable_sort{}; + + struct __partial_sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __middle) + return ranges::next(__first, __last); + + ranges::make_heap(__first, __middle, __comp, __proj); + auto __i = __middle; + for (; __i != __last; ++__i) + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + { + ranges::pop_heap(__first, __middle, __comp, __proj); + ranges::iter_swap(__middle-1, __i); + ranges::push_heap(__first, __middle, __comp, __proj); + } + ranges::sort_heap(__first, __middle, __comp, __proj); + + return __i; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __partial_sort_fn partial_sort{}; + + template + using partial_sort_copy_result = in_out_result<_Iter, _Out>; + + struct __partial_sort_copy_fn + { + template _Sent1, + random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_copyable<_Iter1, _Iter2> + && sortable<_Iter2, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>> + constexpr partial_sort_copy_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, + _Iter2 __result_first, _Sent2 __result_last, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if (__result_first == __result_last) + { + // TODO: Eliminating the variable __lasti triggers an ICE. + auto __lasti = ranges::next(std::move(__first), + std::move(__last)); + return {std::move(__lasti), std::move(__result_first)}; + } + + auto __result_real_last = __result_first; + while (__first != __last && __result_real_last != __result_last) + { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + + ranges::make_heap(__result_first, __result_real_last, __comp, __proj2); + for (; __first != __last; ++__first) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first), + std::__invoke(__proj2, *__result_first))) + { + ranges::pop_heap(__result_first, __result_real_last, + __comp, __proj2); + *(__result_real_last-1) = *__first; + ranges::push_heap(__result_first, __result_real_last, + __comp, __proj2); + } + ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2); + + return {std::move(__first), std::move(__result_real_last)}; + } + + template + requires indirectly_copyable, iterator_t<_Range2>> + && sortable, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected, _Proj1>, + projected, _Proj2>> + constexpr partial_sort_copy_result, + borrowed_iterator_t<_Range2>> + operator()(_Range1&& __r, _Range2&& __out, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + ranges::begin(__out), ranges::end(__out), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __partial_sort_copy_fn partial_sort_copy{}; + + struct __is_sorted_until_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return __next; + return __next; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_sorted_until_fn is_sorted_until{}; + + struct __is_sorted_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return true; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_sorted_fn is_sorted{}; + + struct __nth_element_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Iter __nth, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::nth_element(std::move(__first), std::move(__nth), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __nth, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__nth), + ranges::end(__r), std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __nth_element_fn nth_element{}; + + struct __lower_bound_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __lower_bound_fn lower_bound{}; + + struct __upper_bound_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle))) + __len = __half; + else + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __upper_bound_fn upper_bound{}; + + struct __equal_range_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, + std::__invoke(__proj, *__middle), + __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (std::__invoke(__comp, + __value, + std::__invoke(__proj, *__middle))) + __len = __half; + else + { + auto __left + = ranges::lower_bound(__first, __middle, + __value, __comp, __proj); + ranges::advance(__first, __len); + auto __right + = ranges::upper_bound(++__middle, __first, + __value, __comp, __proj); + return {__left, __right}; + } + } + return {__first, __first}; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __equal_range_fn equal_range{}; + + struct __binary_search_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj); + if (__i == __last) + return false; + return !(bool)std::__invoke(__comp, __value, + std::__invoke(__proj, *__i)); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __binary_search_fn binary_search{}; + + struct __is_partitioned_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + __first = ranges::find_if_not(std::move(__first), __last, + __pred, __proj); + if (__first == __last) + return true; + ++__first; + return ranges::none_of(std::move(__first), std::move(__last), + std::move(__pred), std::move(__proj)); + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __is_partitioned_fn is_partitioned{}; + + struct __partition_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + if constexpr (bidirectional_iterator<_Iter>) + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + for (;;) + { + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (std::__invoke(__pred, + std::__invoke(__proj, *__first))) + ++__first; + else + break; + --__tail; + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (!(bool)std::__invoke(__pred, + std::__invoke(__proj, *__tail))) + --__tail; + else + break; + ranges::iter_swap(__first, __tail); + ++__first; + } + } + else + { + if (__first == __last) + return {std::move(__first), std::move(__first)}; + + while (std::__invoke(__pred, std::__invoke(__proj, *__first))) + if (++__first == __last) + return {std::move(__first), std::move(__first)}; + + auto __next = __first; + while (++__next != __last) + if (std::__invoke(__pred, std::__invoke(__proj, *__next))) + { + ranges::iter_swap(__first, __next); + ++__first; + } + + return {std::move(__first), std::move(__next)}; + } + } + + template, _Proj>> + _Pred> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_fn partition{}; + + struct __stable_partition_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires permutable<_Iter> + subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + auto __middle + = std::stable_partition(std::move(__first), __lasti, + __detail::__make_pred_proj(__pred, __proj)); + return {std::move(__middle), std::move(__lasti)}; + } + + template, _Proj>> + _Pred> + requires permutable> + borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __stable_partition_fn stable_partition{}; + + template + struct in_out_out_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Out1 out1; + [[no_unique_address]] _Out2 out2; + + template + requires convertible_to + && convertible_to + && convertible_to + constexpr + operator in_out_out_result<_IIter, _OOut1, _OOut2>() const & + { return {in, out1, out2}; } + + template + requires convertible_to<_Iter, _IIter> + && convertible_to<_Out1, _OOut1> + && convertible_to<_Out2, _OOut2> + constexpr + operator in_out_out_result<_IIter, _OOut1, _OOut2>() && + { return {std::move(in), std::move(out1), std::move(out2)}; } + }; + + template + using partition_copy_result = in_out_out_result<_Iter, _Out1, _Out2>; + + struct __partition_copy_fn + { + template _Sent, + weakly_incrementable _Out1, weakly_incrementable _O2, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out1> + && indirectly_copyable<_Iter, _O2> + constexpr partition_copy_result<_Iter, _Out1, _O2> + operator()(_Iter __first, _Sent __last, + _Out1 __out_true, _O2 __out_false, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + + return {std::move(__first), + std::move(__out_true), std::move(__out_false)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out1> + && indirectly_copyable, _O2> + constexpr partition_copy_result, _Out1, _O2> + operator()(_Range&& __r, _Out1 out_true, _O2 out_false, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(out_true), std::move(out_false), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_copy_fn partition_copy{}; + + struct __partition_point_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__pred, std::__invoke(__proj, *__middle))) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_point_fn partition_point{}; + + template + using merge_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __merge_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr merge_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out) }; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr merge_result, + borrowed_iterator_t<_Range2>, + _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __merge_fn merge{}; + + struct __inplace_merge_fn + { + template _Sent, + typename _Comp = ranges::less, + typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::inplace_merge(std::move(__first), std::move(__middle), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __inplace_merge_fn inplace_merge{}; + + struct __includes_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + else if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else + { + ++__first1; + ++__first2; + } + + return __first2 == __last2; + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __includes_fn includes{}; + + template + using set_union_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_union_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_union_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_union_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_union_fn set_union{}; + + template + using set_intersection_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_intersection_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_intersection_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; + else + { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + // TODO: Eliminating these variables triggers an ICE. + auto __last1i = ranges::next(std::move(__first1), std::move(__last1)); + auto __last2i = ranges::next(std::move(__first2), std::move(__last2)); + return {std::move(__last1i), std::move(__last2i), std::move(__result)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_intersection_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_intersection_fn set_intersection{}; + + template + using set_difference_result = in_out_result<_Iter, _Out>; + + struct __set_difference_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_difference_result<_Iter1, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; + else + { + ++__first1; + ++__first2; + } + return ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_difference_result, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_difference_fn set_difference{}; + + template + using set_symmetric_difference_result + = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_symmetric_difference_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + ++__result; + } + else + { + ++__first1; + ++__first2; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result, + borrowed_iterator_t<_Range2>, + _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_symmetric_difference_fn set_symmetric_difference{}; + + struct __min_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_fn min{}; + + struct __max_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __a), + std::__invoke(__proj, __b))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __result), + std::__invoke(__proj, __tmp))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __max_fn max{}; + + struct __clamp_fn + { + template> _Comp + = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, + _Comp __comp = {}, _Proj __proj = {}) const + { + __glibcxx_assert(!(std::__invoke(__comp, + std::__invoke(__proj, __hi), + std::__invoke(__proj, __lo)))); + auto&& __proj_val = std::__invoke(__proj, __val); + if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo))) + return __lo; + else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val)) + return __hi; + else + return __val; + } + }; + + inline constexpr __clamp_fn clamp{}; + + template + struct min_max_result + { + [[no_unique_address]] _Tp min; + [[no_unique_address]] _Tp max; + + template + requires convertible_to + constexpr + operator min_max_result<_Tp2>() const & + { return {min, max}; } + + template + requires convertible_to<_Tp, _Tp2> + constexpr + operator min_max_result<_Tp2>() && + { return {std::move(min), std::move(max)}; } + }; + + template + using minmax_result = min_max_result<_Tp>; + + struct __minmax_fn + { + template> + _Comp = ranges::less> + constexpr minmax_result + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return {__b, __a}; + else + return {__a, __b}; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr minmax_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + minmax_result> __result = {*__first, *__first}; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result.min))) + __result.min = std::move(__tmp); + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result.max))) + __result.max = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr minmax_result<_Tp> + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __minmax_fn minmax{}; + + struct __min_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + __first = __i; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_element_fn min_element{}; + + struct __max_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__i))) + __first = __i; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __max_element_fn max_element{}; + + template + using minmax_element_result = min_max_result<_Iter>; + + struct __minmax_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr minmax_element_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {__first, __first}; + + minmax_element_result<_Iter> __result = {__first, __first}; + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__result.min))) + __result.min = __i; + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__result.max))) + __result.max = __i; + } + return __result; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr minmax_element_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __minmax_element_fn minmax_element{}; + + struct __lexicographical_compare_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if constexpr (__detail::__is_normal_iterator<_Iter1> + && same_as<_Iter1, _Sent1>) + return (*this)(__first1.base(), __last1.base(), + std::move(__first2), std::move(__last2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + else if constexpr (__detail::__is_normal_iterator<_Iter2> + && same_as<_Iter2, _Sent2>) + return (*this)(std::move(__first1), std::move(__last1), + __first2.base(), __last2.base(), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + else + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + // This condition is consistent with the one in + // __lexicographical_compare_aux in . + constexpr bool __use_memcmp + = (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value + && __ptr_to_nonvolatile<_Iter1> + && __ptr_to_nonvolatile<_Iter2> + && (is_same_v<_Comp, ranges::less> + || is_same_v<_Comp, ranges::greater>) + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + const auto __d1 = __last1 - __first1; + const auto __d2 = __last2 - __first2; + + if (const auto __len = std::min(__d1, __d2)) + { + const auto __c + = std::__memcmp(__first1, __first2, __len); + if constexpr (is_same_v<_Comp, ranges::less>) + { + if (__c < 0) + return true; + if (__c > 0) + return false; + } + else if constexpr (is_same_v<_Comp, ranges::greater>) + { + if (__c > 0) + return true; + if (__c < 0) + return false; + } + } + return __d1 < __d2; + } + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void) ++__first2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return true; + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + private: + template> + static constexpr bool __ptr_to_nonvolatile + = is_pointer_v<_Iter> && !is_volatile_v>; + }; + + inline constexpr __lexicographical_compare_fn lexicographical_compare; + + template + struct in_found_result + { + [[no_unique_address]] _Iter in; + bool found; + + template + requires convertible_to + constexpr + operator in_found_result<_Iter2>() const & + { return {in, found}; } + + template + requires convertible_to<_Iter, _Iter2> + constexpr + operator in_found_result<_Iter2>() && + { return {std::move(in), found}; } + }; + + template + using next_permutation_result = in_found_result<_Iter>; + + struct __next_permutation_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr next_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), false}; + + auto __i = __first; + ++__i; + if (__i == __last) + return {std::move(__i), false}; + + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; + + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__ii))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *--__j))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {std::move(__lasti), true}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {std::move(__lasti), false}; + } + } + } + + template + requires sortable, _Comp, _Proj> + constexpr next_permutation_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __next_permutation_fn next_permutation{}; + + template + using prev_permutation_result = in_found_result<_Iter>; + + struct __prev_permutation_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr prev_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), false}; + + auto __i = __first; + ++__i; + if (__i == __last) + return {std::move(__i), false}; + + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; + + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__ii), + std::__invoke(__proj, *__i))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *--__j), + std::__invoke(__proj, *__i))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {std::move(__lasti), true}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {std::move(__lasti), false}; + } + } + } + + template + requires sortable, _Comp, _Proj> + constexpr prev_permutation_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __prev_permutation_fn prev_permutation{}; + +} // namespace ranges + +#define __cpp_lib_shift 201806L + template + constexpr _ForwardIterator + shift_left(_ForwardIterator __first, _ForwardIterator __last, + typename iterator_traits<_ForwardIterator>::difference_type __n) + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return __last; + + auto __mid = ranges::next(__first, __n, __last); + if (__mid == __last) + return __first; + return std::move(std::move(__mid), std::move(__last), std::move(__first)); + } + + template + constexpr _ForwardIterator + shift_right(_ForwardIterator __first, _ForwardIterator __last, + typename iterator_traits<_ForwardIterator>::difference_type __n) + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return __first; + + using _Cat + = typename iterator_traits<_ForwardIterator>::iterator_category; + if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + { + auto __mid = ranges::next(__last, -__n, __first); + if (__mid == __first) + return __last; + + return std::move_backward(std::move(__first), std::move(__mid), + std::move(__last)); + } + else + { + auto __result = ranges::next(__first, __n, __last); + if (__result == __last) + return __last; + + auto __dest_head = __first, __dest_tail = __result; + while (__dest_head != __result) + { + if (__dest_tail == __last) + { + // If we get here, then we must have + // 2*n >= distance(__first, __last) + // i.e. we are shifting out at least half of the range. In + // this case we can safely perform the shift with a single + // move. + std::move(std::move(__first), std::move(__dest_head), + std::move(__result)); + return __result; + } + ++__dest_head; + ++__dest_tail; + } + + for (;;) + { + // At the start of each iteration of this outer loop, the range + // [__first, __result) contains those elements that after shifting + // the whole range right by __n, should end up in + // [__dest_head, __dest_tail) in order. + + // The below inner loop swaps the elements of [__first, __result) + // and [__dest_head, __dest_tail), while simultaneously shifting + // the latter range by __n. + auto __cursor = __first; + while (__cursor != __result) + { + if (__dest_tail == __last) + { + // At this point the ranges [__first, result) and + // [__dest_head, dest_tail) are disjoint, so we can safely + // move the remaining elements. + __dest_head = std::move(__cursor, __result, + std::move(__dest_head)); + std::move(std::move(__first), std::move(__cursor), + std::move(__dest_head)); + return __result; + } + std::iter_swap(__cursor, __dest_head); + ++__dest_head; + ++__dest_tail; + ++__cursor; + } + } + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_ALGO_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h b/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h new file mode 100644 index 000000000..618bc7d10 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h @@ -0,0 +1,597 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_algobase.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _RANGES_ALGOBASE_H +#define _RANGES_ALGOBASE_H 1 + +#if __cplusplus > 201703L + +#include +#include +// #include +#include +#include +#include // __is_byte + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr inline bool __is_normal_iterator = false; + + template + constexpr inline bool + __is_normal_iterator<__gnu_cxx::__normal_iterator<_Iterator, + _Container>> = true; + + template + constexpr inline bool __is_reverse_iterator = false; + + template + constexpr inline bool + __is_reverse_iterator> = true; + + template + constexpr inline bool __is_move_iterator = false; + + template + constexpr inline bool + __is_move_iterator> = true; + } // namespace __detail + + struct __equal_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + // TODO: implement more specializations to at least have parity with + // std::equal. + if constexpr (__detail::__is_normal_iterator<_Iter1> + && same_as<_Iter1, _Sent1>) + return (*this)(__first1.base(), __last1.base(), + std::move(__first2), std::move(__last2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + else if constexpr (__detail::__is_normal_iterator<_Iter2> + && same_as<_Iter2, _Sent2>) + return (*this)(std::move(__first1), std::move(__last1), + __first2.base(), __last2.base(), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + else if constexpr (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + constexpr bool __use_memcmp + = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) + && __memcmpable<_Iter1, _Iter2>::__value + && is_same_v<_Pred, ranges::equal_to> + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + if (const size_t __len = (__last1 - __first1)) + return !std::__memcmp(__first1, __first2, __len); + return true; + } + else + { + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return true; + } + } + else + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __equal_fn equal{}; + + template + struct in_out_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Out out; + + template + requires convertible_to + && convertible_to + constexpr + operator in_out_result<_Iter2, _Out2>() const & + { return {in, out}; } + + template + requires convertible_to<_Iter, _Iter2> + && convertible_to<_Out, _Out2> + constexpr + operator in_out_result<_Iter2, _Out2>() && + { return {std::move(in), std::move(out)}; } + }; + + template + using copy_result = in_out_result<_Iter, _Out>; + + template + using move_result = in_out_result<_Iter, _Out>; + + template + using move_backward_result = in_out_result<_Iter1, _Iter2>; + + template + using copy_backward_result = in_out_result<_Iter1, _Iter2>; + + template _Sent, + bidirectional_iterator _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_backward_result<_Iter, _Out>, + copy_backward_result<_Iter, _Out>> + __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result); + + template _Sent, + weakly_incrementable _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_result<_Iter, _Out>, + copy_result<_Iter, _Out>> + __copy_or_move(_Iter __first, _Sent __last, _Out __result) + { + // TODO: implement more specializations to be at least on par with + // std::copy/std::move. + using __detail::__is_move_iterator; + using __detail::__is_reverse_iterator; + using __detail::__is_normal_iterator; + if constexpr (__is_move_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in, __out] + = ranges::__copy_or_move(std::move(__first).base(), + std::move(__last).base(), + std::move(__result)); + return {move_iterator{std::move(__in)}, std::move(__out)}; + } + else if constexpr (__is_reverse_iterator<_Iter> && same_as<_Iter, _Sent> + && __is_reverse_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(std::move(__last).base(), + std::move(__first).base(), + std::move(__result).base()); + return {reverse_iterator{std::move(__in)}, + reverse_iterator{std::move(__out)}}; + } + else if constexpr (__is_normal_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(__first.base(), __last.base(), + __result); + return {decltype(__first){__in}, std::move(__out)}; + } + else if constexpr (__is_normal_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(__first, __last, __result.base()); + return {std::move(__in), decltype(__result){__out}}; + } + else if constexpr (sized_sentinel_for<_Sent, _Iter>) + { +#ifdef __cpp_lib_is_constant_evaluated + if (!std::is_constant_evaluated()) +#endif + { + if constexpr (__memcpyable<_Iter, _Out>::__value) + { + using _ValueTypeI = iter_value_t<_Iter>; + static_assert(_IsMove + ? is_move_assignable_v<_ValueTypeI> + : is_copy_assignable_v<_ValueTypeI>); + auto __num = __last - __first; + if (__num) + __builtin_memmove(__result, __first, + sizeof(_ValueTypeI) * __num); + return {__first + __num, __result + __num}; + } + } + + for (auto __n = __last - __first; __n > 0; --__n) + { + if constexpr (_IsMove) + *__result = std::move(*__first); + else + *__result = *__first; + ++__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + else + { + while (__first != __last) + { + if constexpr (_IsMove) + *__result = std::move(*__first); + else + *__result = *__first; + ++__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + } + + struct __copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Out> + constexpr copy_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __copy_fn copy{}; + + struct __move_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_movable<_Iter, _Out> + constexpr move_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Out> + constexpr move_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __move_fn move{}; + + template _Sent, + bidirectional_iterator _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_backward_result<_Iter, _Out>, + copy_backward_result<_Iter, _Out>> + __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result) + { + // TODO: implement more specializations to be at least on par with + // std::copy_backward/std::move_backward. + using __detail::__is_reverse_iterator; + using __detail::__is_normal_iterator; + if constexpr (__is_reverse_iterator<_Iter> && same_as<_Iter, _Sent> + && __is_reverse_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(std::move(__last).base(), + std::move(__first).base(), + std::move(__result).base()); + return {reverse_iterator{std::move(__in)}, + reverse_iterator{std::move(__out)}}; + } + else if constexpr (__is_normal_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(__first.base(), + __last.base(), + std::move(__result)); + return {decltype(__first){__in}, std::move(__out)}; + } + else if constexpr (__is_normal_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(std::move(__first), + std::move(__last), + __result.base()); + return {std::move(__in), decltype(__result){__out}}; + } + else if constexpr (sized_sentinel_for<_Sent, _Iter>) + { +#ifdef __cpp_lib_is_constant_evaluated + if (!std::is_constant_evaluated()) +#endif + { + if constexpr (__memcpyable<_Out, _Iter>::__value) + { + using _ValueTypeI = iter_value_t<_Iter>; + static_assert(_IsMove + ? is_move_assignable_v<_ValueTypeI> + : is_copy_assignable_v<_ValueTypeI>); + auto __num = __last - __first; + if (__num) + __builtin_memmove(__result - __num, __first, + sizeof(_ValueTypeI) * __num); + return {__first + __num, __result - __num}; + } + } + + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + + for (auto __n = __last - __first; __n > 0; --__n) + { + --__tail; + --__result; + if constexpr (_IsMove) + *__result = std::move(*__tail); + else + *__result = *__tail; + } + return {std::move(__lasti), std::move(__result)}; + } + else + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + + while (__first != __tail) + { + --__tail; + --__result; + if constexpr (_IsMove) + *__result = std::move(*__tail); + else + *__result = *__tail; + } + return {std::move(__lasti), std::move(__result)}; + } + } + + struct __copy_backward_fn + { + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_copyable<_Iter1, _Iter2> + constexpr copy_backward_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Iter> + constexpr copy_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __copy_backward_fn copy_backward{}; + + struct __move_backward_fn + { + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_movable<_Iter1, _Iter2> + constexpr move_backward_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Iter> + constexpr move_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __move_backward_fn move_backward{}; + + template + using copy_n_result = in_out_result<_Iter, _Out>; + + struct __copy_n_fn + { + template + requires indirectly_copyable<_Iter, _Out> + constexpr copy_n_result<_Iter, _Out> + operator()(_Iter __first, iter_difference_t<_Iter> __n, + _Out __result) const + { + if constexpr (random_access_iterator<_Iter>) + return ranges::copy(__first, __first + __n, std::move(__result)); + else + { + for (; __n > 0; --__n, (void)++__result, (void)++__first) + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + } + }; + + inline constexpr __copy_n_fn copy_n{}; + + struct __fill_n_fn + { + template _Out> + constexpr _Out + operator()(_Out __first, iter_difference_t<_Out> __n, + const _Tp& __value) const + { + // TODO: implement more specializations to be at least on par with + // std::fill_n + if (__n <= 0) + return __first; + + // TODO: Generalize this optimization to contiguous iterators. + if constexpr (is_pointer_v<_Out> + // Note that __is_byte already implies !is_volatile. + && __is_byte>::__value + && integral<_Tp>) + { + __builtin_memset(__first, static_cast(__value), __n); + return __first + __n; + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __n > 0; --__n, (void)++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __n > 0; --__n, (void)++__first) + *__first = __value; + return __first; + } + } + }; + + inline constexpr __fill_n_fn fill_n{}; + + struct __fill_fn + { + template _Out, sentinel_for<_Out> _Sent> + constexpr _Out + operator()(_Out __first, _Sent __last, const _Tp& __value) const + { + // TODO: implement more specializations to be at least on par with + // std::fill + if constexpr (sized_sentinel_for<_Sent, _Out>) + { + const auto __len = __last - __first; + return ranges::fill_n(__first, __len, __value); + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __first != __last; ++__first) + *__first = __value; + return __first; + } + } + + template _Range> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __value) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __value); + } + }; + + inline constexpr __fill_fn fill{}; +} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_ALGOBASE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h b/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h new file mode 100644 index 000000000..25e664de7 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h @@ -0,0 +1,574 @@ +// Raw memory manipulators -*- C++ -*- + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_uninitialized.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _RANGES_UNINITIALIZED_H +#define _RANGES_UNINITIALIZED_H 1 + +#if __cplusplus > 201703L +#if __cpp_lib_concepts + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr void* + __voidify(_Tp& __obj) noexcept + { + return const_cast + (static_cast(std::__addressof(__obj))); + } + + template + concept __nothrow_input_iterator + = (input_iterator<_Iter> + && is_lvalue_reference_v> + && same_as>, + iter_value_t<_Iter>>); + + template + concept __nothrow_sentinel = sentinel_for<_Sent, _Iter>; + + template + concept __nothrow_input_range + = (range<_Range> + && __nothrow_input_iterator> + && __nothrow_sentinel, iterator_t<_Range>>); + + template + concept __nothrow_forward_iterator + = (__nothrow_input_iterator<_Iter> + && forward_iterator<_Iter> + && __nothrow_sentinel<_Iter, _Iter>); + + template + concept __nothrow_forward_range + = (__nothrow_input_range<_Range> + && __nothrow_forward_iterator>); + } // namespace __detail + + struct __destroy_fn + { + template<__detail::__nothrow_input_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires destructible> + constexpr _Iter + operator()(_Iter __first, _Sent __last) const noexcept; + + template<__detail::__nothrow_input_range _Range> + requires destructible> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r) const noexcept; + }; + + inline constexpr __destroy_fn destroy{}; + + namespace __detail + { + template + requires destructible> + struct _DestroyGuard + { + private: + _Iter _M_first; + const _Iter* _M_cur; + + public: + explicit + _DestroyGuard(const _Iter* __iter) + : _M_first(*__iter), _M_cur(__iter) + { } + + void + release() noexcept + { _M_cur = nullptr; } + + ~_DestroyGuard() + { + if (_M_cur != nullptr) + ranges::destroy(std::move(_M_first), *_M_cur); + } + }; + + template + requires destructible> + && is_trivially_destructible_v> + struct _DestroyGuard<_Iter> + { + explicit + _DestroyGuard(const _Iter*) + { } + + void + release() noexcept + { } + }; + } // namespace __detail + + struct __uninitialized_default_construct_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires default_initializable> + _Iter + operator()(_Iter __first, _Sent __last) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivially_default_constructible_v<_ValueType>) + return ranges::next(__first, __last); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType; + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range> + requires default_initializable> + borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __uninitialized_default_construct_fn + uninitialized_default_construct{}; + + struct __uninitialized_default_construct_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter> + requires default_initializable> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivially_default_constructible_v<_ValueType>) + return ranges::next(__first, __n); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void) --__n) + ::new (__detail::__voidify(*__first)) _ValueType; + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_default_construct_n_fn + uninitialized_default_construct_n; + + struct __uninitialized_value_construct_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires default_initializable> + _Iter + operator()(_Iter __first, _Sent __last) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_copy_assignable_v<_ValueType>) + return ranges::fill(__first, __last, _ValueType()); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType(); + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range> + requires default_initializable> + borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __uninitialized_value_construct_fn + uninitialized_value_construct{}; + + struct __uninitialized_value_construct_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter> + requires default_initializable> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_copy_assignable_v<_ValueType>) + return ranges::fill_n(__first, __n, _ValueType()); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void) --__n) + ::new (__detail::__voidify(*__first)) _ValueType(); + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_value_construct_n_fn + uninitialized_value_construct_n; + + template + using uninitialized_copy_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_copy_fn + { + template _ISent, + __detail::__nothrow_forward_iterator _Out, + __detail::__nothrow_sentinel<_Out> _OSent> + requires constructible_from, iter_reference_t<_Iter>> + uninitialized_copy_result<_Iter, _Out> + operator()(_Iter __ifirst, _ISent __ilast, + _Out __ofirst, _OSent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_ISent, _Iter> + && sized_sentinel_for<_OSent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_reference_t<_Iter>>) + { + auto __d1 = __ilast - __ifirst; + auto __d2 = __olast - __ofirst; + return ranges::copy_n(std::move(__ifirst), std::min(__d1, __d2), + __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __ifirst != __ilast && __ofirst != __olast; + ++__ofirst, (void)++__ifirst) + ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + + template + requires constructible_from, + range_reference_t<_IRange>> + uninitialized_copy_result, + borrowed_iterator_t<_ORange>> + operator()(_IRange&& __inr, _ORange&& __outr) const + { + return (*this)(ranges::begin(__inr), ranges::end(__inr), + ranges::begin(__outr), ranges::end(__outr)); + } + }; + + inline constexpr __uninitialized_copy_fn uninitialized_copy{}; + + template + using uninitialized_copy_n_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_copy_n_fn + { + template _Sent> + requires constructible_from, iter_reference_t<_Iter>> + uninitialized_copy_n_result<_Iter, _Out> + operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, + _Out __ofirst, _Sent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_Sent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_reference_t<_Iter>>) + { + auto __d = __olast - __ofirst; + return ranges::copy_n(std::move(__ifirst), std::min(__n, __d), + __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __n > 0 && __ofirst != __olast; + ++__ofirst, (void)++__ifirst, (void)--__n) + ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + }; + + inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{}; + + template + using uninitialized_move_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_move_fn + { + template _ISent, + __detail::__nothrow_forward_iterator _Out, + __detail::__nothrow_sentinel<_Out> _OSent> + requires constructible_from, + iter_rvalue_reference_t<_Iter>> + uninitialized_move_result<_Iter, _Out> + operator()(_Iter __ifirst, _ISent __ilast, + _Out __ofirst, _OSent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_ISent, _Iter> + && sized_sentinel_for<_OSent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_rvalue_reference_t<_Iter>>) + { + auto __d1 = __ilast - __ifirst; + auto __d2 = __olast - __ofirst; + auto [__in, __out] + = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), + std::min(__d1, __d2), __ofirst); + return {std::move(__in).base(), __out}; + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __ifirst != __ilast && __ofirst != __olast; + ++__ofirst, (void)++__ifirst) + ::new (__detail::__voidify(*__ofirst)) + _OutType(ranges::iter_move(__ifirst)); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + + template + requires constructible_from, + range_rvalue_reference_t<_IRange>> + uninitialized_move_result, + borrowed_iterator_t<_ORange>> + operator()(_IRange&& __inr, _ORange&& __outr) const + { + return (*this)(ranges::begin(__inr), ranges::end(__inr), + ranges::begin(__outr), ranges::end(__outr)); + } + }; + + inline constexpr __uninitialized_move_fn uninitialized_move{}; + + template + using uninitialized_move_n_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_move_n_fn + { + template _Sent> + requires constructible_from, + iter_rvalue_reference_t<_Iter>> + uninitialized_move_n_result<_Iter, _Out> + operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, + _Out __ofirst, _Sent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_Sent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_rvalue_reference_t<_Iter>>) + { + auto __d = __olast - __ofirst; + auto [__in, __out] + = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), + std::min(__n, __d), __ofirst); + return {std::move(__in).base(), __out}; + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __n > 0 && __ofirst != __olast; + ++__ofirst, (void)++__ifirst, (void)--__n) + ::new (__detail::__voidify(*__ofirst)) + _OutType(ranges::iter_move(__ifirst)); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + }; + + inline constexpr __uninitialized_move_n_fn uninitialized_move_n{}; + + struct __uninitialized_fill_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp> + requires constructible_from, const _Tp&> + _Iter + operator()(_Iter __first, _Sent __last, const _Tp& __x) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_nothrow_assignable_v<_ValueType&, const _Tp&>) + return ranges::fill(__first, __last, __x); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType(__x); + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range, typename _Tp> + requires constructible_from, const _Tp&> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __x) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __x); + } + }; + + inline constexpr __uninitialized_fill_fn uninitialized_fill{}; + + struct __uninitialized_fill_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter, typename _Tp> + requires constructible_from, const _Tp&> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n, + const _Tp& __x) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_nothrow_assignable_v<_ValueType&, const _Tp&>) + return ranges::fill_n(__first, __n, __x); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void)--__n) + ::new (__detail::__voidify(*__first)) _ValueType(__x); + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{}; + + struct __construct_at_fn + { + template + requires requires { + ::new (std::declval()) _Tp(std::declval<_Args>()...); + } + constexpr _Tp* + operator()(_Tp* __location, _Args&&... __args) const + noexcept(noexcept(std::construct_at(__location, + std::forward<_Args>(__args)...))) + { + return std::construct_at(__location, + std::forward<_Args>(__args)...); + } + }; + + inline constexpr __construct_at_fn construct_at{}; + + struct __destroy_at_fn + { + template + constexpr void + operator()(_Tp* __location) const noexcept + { + if constexpr (is_array_v<_Tp>) + ranges::destroy(ranges::begin(*__location), ranges::end(*__location)); + else + __location->~_Tp(); + } + }; + + inline constexpr __destroy_at_fn destroy_at{}; + + template<__detail::__nothrow_input_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires destructible> + constexpr _Iter + __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept + { + if constexpr (is_trivially_destructible_v>) + return ranges::next(std::move(__first), __last); + else + { + for (; __first != __last; ++__first) + ranges::destroy_at(std::__addressof(*__first)); + return __first; + } + } + + template<__detail::__nothrow_input_range _Range> + requires destructible> + constexpr borrowed_iterator_t<_Range> + __destroy_fn::operator()(_Range&& __r) const noexcept + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + + struct __destroy_n_fn + { + template<__detail::__nothrow_input_iterator _Iter> + requires destructible> + constexpr _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept + { + if constexpr (is_trivially_destructible_v>) + return ranges::next(std::move(__first), __n); + else + { + for (; __n > 0; ++__first, (void)--__n) + ranges::destroy_at(std::__addressof(*__first)); + return __first; + } + } + }; + + inline constexpr __destroy_n_fn destroy_n{}; +} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_UNINITIALIZED_H diff --git a/resources/sources/avr-libstdcpp/include/bits/refwrap.h b/resources/sources/avr-libstdcpp/include/bits/refwrap.h new file mode 100644 index 000000000..717aa0162 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/refwrap.h @@ -0,0 +1,401 @@ +// Implementation of std::reference_wrapper -*- C++ -*- + +// Copyright (C) 2004-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/refwrap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_REFWRAP_H +#define _GLIBCXX_REFWRAP_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include // for unary_function and binary_function + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// @cond undocumented + + /** + * Derives from @c unary_function or @c binary_function, or perhaps + * nothing, depending on the number of arguments provided. The + * primary template is the basis case, which derives nothing. + */ + template + struct _Maybe_unary_or_binary_function { }; + + /// Derives from @c unary_function, as appropriate. + template + struct _Maybe_unary_or_binary_function<_Res, _T1> + : std::unary_function<_T1, _Res> { }; + + /// Derives from @c binary_function, as appropriate. + template + struct _Maybe_unary_or_binary_function<_Res, _T1, _T2> + : std::binary_function<_T1, _T2, _Res> { }; + + template + struct _Mem_fn_traits; + + template + struct _Mem_fn_traits_base + { + using __result_type = _Res; + using __maybe_type + = _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>; + using __arity = integral_constant; + }; + +#define _GLIBCXX_MEM_FN_TRAITS2(_CV, _REF, _LVAL, _RVAL) \ + template \ + struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF> \ + : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ + { \ + using __vararg = false_type; \ + }; \ + template \ + struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \ + : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ + { \ + using __vararg = true_type; \ + }; + +#define _GLIBCXX_MEM_FN_TRAITS(_REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2( , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(const , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(volatile , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(const volatile, _REF, _LVAL, _RVAL) + +_GLIBCXX_MEM_FN_TRAITS( , true_type, true_type) +_GLIBCXX_MEM_FN_TRAITS(&, true_type, false_type) +_GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) + +#if __cplusplus > 201402L +_GLIBCXX_MEM_FN_TRAITS(noexcept, true_type, true_type) +_GLIBCXX_MEM_FN_TRAITS(& noexcept, true_type, false_type) +_GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) +#endif + +#undef _GLIBCXX_MEM_FN_TRAITS +#undef _GLIBCXX_MEM_FN_TRAITS2 + + /// If we have found a result_type, extract it. + template> + struct _Maybe_get_result_type + { }; + + template + struct _Maybe_get_result_type<_Functor, + __void_t> + { typedef typename _Functor::result_type result_type; }; + + /** + * Base class for any function object that has a weak result type, as + * defined in 20.8.2 [func.require] of C++11. + */ + template + struct _Weak_result_type_impl + : _Maybe_get_result_type<_Functor> + { }; + + /// Retrieve the result type for a function type. + template + struct _Weak_result_type_impl<_Res(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a varargs function type. + template + struct _Weak_result_type_impl<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a function pointer. + template + struct _Weak_result_type_impl<_Res(*)(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a varargs function pointer. + template + struct + _Weak_result_type_impl<_Res(*)(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + // Let _Weak_result_type_impl perform the real work. + template::value> + struct _Weak_result_type_memfun + : _Weak_result_type_impl<_Functor> + { }; + + // A pointer to member function has a weak result type. + template + struct _Weak_result_type_memfun<_MemFunPtr, true> + { + using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; + }; + + // A pointer to data member doesn't have a weak result type. + template + struct _Weak_result_type_memfun<_Func _Class::*, false> + { }; + + /** + * Strip top-level cv-qualifiers from the function object and let + * _Weak_result_type_memfun perform the real work. + */ + template + struct _Weak_result_type + : _Weak_result_type_memfun::type> + { }; + +#if __cplusplus <= 201703L + // Detect nested argument_type. + template> + struct _Refwrap_base_arg1 + { }; + + // Nested argument_type. + template + struct _Refwrap_base_arg1<_Tp, + __void_t> + { + typedef typename _Tp::argument_type argument_type; + }; + + // Detect nested first_argument_type and second_argument_type. + template> + struct _Refwrap_base_arg2 + { }; + + // Nested first_argument_type and second_argument_type. + template + struct _Refwrap_base_arg2<_Tp, + __void_t> + { + typedef typename _Tp::first_argument_type first_argument_type; + typedef typename _Tp::second_argument_type second_argument_type; + }; + + /** + * Derives from unary_function or binary_function when it + * can. Specializations handle all of the easy cases. The primary + * template determines what to do with a class type, which may + * derive from both unary_function and binary_function. + */ + template + struct _Reference_wrapper_base + : _Weak_result_type<_Tp>, _Refwrap_base_arg1<_Tp>, _Refwrap_base_arg2<_Tp> + { }; + + // - a function type (unary) + template + struct _Reference_wrapper_base<_Res(_T1) _GLIBCXX_NOEXCEPT_QUAL> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) const> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) volatile> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) const volatile> + : unary_function<_T1, _Res> + { }; + + // - a function type (binary) + template + struct _Reference_wrapper_base<_Res(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) const> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) volatile> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) const volatile> + : binary_function<_T1, _T2, _Res> + { }; + + // - a function pointer type (unary) + template + struct _Reference_wrapper_base<_Res(*)(_T1) _GLIBCXX_NOEXCEPT_QUAL> + : unary_function<_T1, _Res> + { }; + + // - a function pointer type (binary) + template + struct _Reference_wrapper_base<_Res(*)(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> + : binary_function<_T1, _T2, _Res> + { }; + + template::value> + struct _Reference_wrapper_base_memfun + : _Reference_wrapper_base<_Tp> + { }; + + template + struct _Reference_wrapper_base_memfun<_MemFunPtr, true> + : _Mem_fn_traits<_MemFunPtr>::__maybe_type + { + using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; + }; +#endif // ! C++20 + + /// @endcond + + /** + * @brief Primary class template for reference_wrapper. + * @ingroup functors + */ + template + class reference_wrapper +#if __cplusplus <= 201703L + // In C++20 std::reference_wrapper allows T to be incomplete, + // so checking for nested types could result in ODR violations. + : public _Reference_wrapper_base_memfun::type> +#endif + { + _Tp* _M_data; + + _GLIBCXX20_CONSTEXPR + static _Tp* _S_fun(_Tp& __r) noexcept { return std::__addressof(__r); } + + static void _S_fun(_Tp&&) = delete; + + template> + using __not_same + = typename enable_if::value>::type; + + public: + typedef _Tp type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2993. reference_wrapper conversion from T&& + // 3041. Unnecessary decay in reference_wrapper + template, typename + = decltype(reference_wrapper::_S_fun(std::declval<_Up>()))> + _GLIBCXX20_CONSTEXPR + reference_wrapper(_Up&& __uref) + noexcept(noexcept(reference_wrapper::_S_fun(std::declval<_Up>()))) + : _M_data(reference_wrapper::_S_fun(std::forward<_Up>(__uref))) + { } + + reference_wrapper(const reference_wrapper&) = default; + + reference_wrapper& + operator=(const reference_wrapper&) = default; + + _GLIBCXX20_CONSTEXPR + operator _Tp&() const noexcept + { return this->get(); } + + _GLIBCXX20_CONSTEXPR + _Tp& + get() const noexcept + { return *_M_data; } + + template + _GLIBCXX20_CONSTEXPR + typename result_of<_Tp&(_Args&&...)>::type + operator()(_Args&&... __args) const + { +#if __cplusplus > 201703L + if constexpr (is_object_v) + static_assert(sizeof(type), "type must be complete"); +#endif + return std::__invoke(get(), std::forward<_Args>(__args)...); + } + }; + +#if __cpp_deduction_guides + template + reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; +#endif + + /// @relates reference_wrapper @{ + + /// Denotes a reference should be taken to a variable. + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper<_Tp> + ref(_Tp& __t) noexcept + { return reference_wrapper<_Tp>(__t); } + + /// Denotes a const reference should be taken to a variable. + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper + cref(const _Tp& __t) noexcept + { return reference_wrapper(__t); } + + template + void ref(const _Tp&&) = delete; + + template + void cref(const _Tp&&) = delete; + + /// std::ref overload to prevent wrapping a reference_wrapper + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper<_Tp> + ref(reference_wrapper<_Tp> __t) noexcept + { return __t; } + + /// std::cref overload to prevent wrapping a reference_wrapper + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper + cref(reference_wrapper<_Tp> __t) noexcept + { return { __t.get() }; } + + // @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_REFWRAP_H diff --git a/resources/sources/avr-libstdcpp/include/bits/slice_array.h b/resources/sources/avr-libstdcpp/include/bits/slice_array.h new file mode 100644 index 000000000..de33342e2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/slice_array.h @@ -0,0 +1,284 @@ +// The template and inlines for the -*- C++ -*- slice_array class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/slice_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _SLICE_ARRAY_H +#define _SLICE_ARRAY_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Class defining one-dimensional subset of an array. + * + * The slice class represents a one-dimensional subset of an array, + * specified by three parameters: start offset, size, and stride. The + * start offset is the index of the first element of the array that is part + * of the subset. The size is the total number of elements in the subset. + * Stride is the distance between each successive array element to include + * in the subset. + * + * For example, with an array of size 10, and a slice with offset 1, size 3 + * and stride 2, the subset consists of array elements 1, 3, and 5. + */ + class slice + { + public: + /// Construct an empty slice. + slice(); + + /** + * @brief Construct a slice. + * + * @param __o Offset in array of first element. + * @param __d Number of elements in slice. + * @param __s Stride between array elements. + */ + slice(size_t __o, size_t __d, size_t __s); + + /// Return array offset of first slice element. + size_t start() const; + /// Return size of slice. + size_t size() const; + /// Return array stride of slice. + size_t stride() const; + +#if __cpp_impl_three_way_comparison >= 201907L + /// Equality comparison + friend bool operator==(const slice&, const slice&) = default; +#endif + + private: + size_t _M_off; // offset + size_t _M_sz; // size + size_t _M_st; // stride unit + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 543. valarray slice default constructor + inline + slice::slice() + : _M_off(0), _M_sz(0), _M_st(0) {} + + inline + slice::slice(size_t __o, size_t __d, size_t __s) + : _M_off(__o), _M_sz(__d), _M_st(__s) {} + + inline size_t + slice::start() const + { return _M_off; } + + inline size_t + slice::size() const + { return _M_sz; } + + inline size_t + slice::stride() const + { return _M_st; } + + /** + * @brief Reference to one-dimensional subset of an array. + * + * A slice_array is a reference to the actual elements of an array + * specified by a slice. The way to get a slice_array is to call + * operator[](slice) on a valarray. The returned slice_array then permits + * carrying operations out on the referenced subset of elements in the + * original valarray. For example, operator+=(valarray) will add values + * to the subset of elements in the underlying valarray this slice_array + * refers to. + * + * @param Tp Element type. + */ + template + class slice_array + { + public: + typedef _Tp value_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 253. valarray helper functions are almost entirely useless + + /// Copy constructor. Both slices refer to the same underlying array. + slice_array(const slice_array&); + + /// Assignment operator. Assigns slice elements to corresponding + /// elements of @a a. + slice_array& operator=(const slice_array&); + + /// Assign slice elements to corresponding elements of @a v. + void operator=(const valarray<_Tp>&) const; + /// Multiply slice elements by corresponding elements of @a v. + void operator*=(const valarray<_Tp>&) const; + /// Divide slice elements by corresponding elements of @a v. + void operator/=(const valarray<_Tp>&) const; + /// Modulo slice elements by corresponding elements of @a v. + void operator%=(const valarray<_Tp>&) const; + /// Add corresponding elements of @a v to slice elements. + void operator+=(const valarray<_Tp>&) const; + /// Subtract corresponding elements of @a v from slice elements. + void operator-=(const valarray<_Tp>&) const; + /// Logical xor slice elements with corresponding elements of @a v. + void operator^=(const valarray<_Tp>&) const; + /// Logical and slice elements with corresponding elements of @a v. + void operator&=(const valarray<_Tp>&) const; + /// Logical or slice elements with corresponding elements of @a v. + void operator|=(const valarray<_Tp>&) const; + /// Left shift slice elements by corresponding elements of @a v. + void operator<<=(const valarray<_Tp>&) const; + /// Right shift slice elements by corresponding elements of @a v. + void operator>>=(const valarray<_Tp>&) const; + /// Assign all slice elements to @a t. + void operator=(const _Tp &) const; + // ~slice_array (); + + template + void operator=(const _Expr<_Dom, _Tp>&) const; + template + void operator*=(const _Expr<_Dom, _Tp>&) const; + template + void operator/=(const _Expr<_Dom, _Tp>&) const; + template + void operator%=(const _Expr<_Dom, _Tp>&) const; + template + void operator+=(const _Expr<_Dom, _Tp>&) const; + template + void operator-=(const _Expr<_Dom, _Tp>&) const; + template + void operator^=(const _Expr<_Dom, _Tp>&) const; + template + void operator&=(const _Expr<_Dom, _Tp>&) const; + template + void operator|=(const _Expr<_Dom, _Tp>&) const; + template + void operator<<=(const _Expr<_Dom, _Tp>&) const; + template + void operator>>=(const _Expr<_Dom, _Tp>&) const; + + private: + friend class valarray<_Tp>; + slice_array(_Array<_Tp>, const slice&); + + const size_t _M_sz; + const size_t _M_stride; + const _Array<_Tp> _M_array; + +#if __cplusplus < 201103L + // not implemented + slice_array(); +#else + public: + slice_array() = delete; +#endif + }; + + template + inline + slice_array<_Tp>::slice_array(_Array<_Tp> __a, const slice& __s) + : _M_sz(__s.size()), _M_stride(__s.stride()), + _M_array(__a.begin() + __s.start()) {} + + template + inline + slice_array<_Tp>::slice_array(const slice_array<_Tp>& __a) + : _M_sz(__a._M_sz), _M_stride(__a._M_stride), _M_array(__a._M_array) {} + + // template + // inline slice_array<_Tp>::~slice_array () {} + + template + inline slice_array<_Tp>& + slice_array<_Tp>::operator=(const slice_array<_Tp>& __a) + { + std::__valarray_copy(__a._M_array, __a._M_sz, __a._M_stride, + _M_array, _M_stride); + return *this; + } + + template + inline void + slice_array<_Tp>::operator=(const _Tp& __t) const + { std::__valarray_fill(_M_array, _M_sz, _M_stride, __t); } + + template + inline void + slice_array<_Tp>::operator=(const valarray<_Tp>& __v) const + { std::__valarray_copy(_Array<_Tp>(__v), _M_array, _M_sz, _M_stride); } + + template + template + inline void + slice_array<_Tp>::operator=(const _Expr<_Dom,_Tp>& __e) const + { std::__valarray_copy(__e, _M_sz, _M_array, _M_stride); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(_Op,_Name) \ + template \ + inline void \ + slice_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ + { \ + _Array_augmented_##_Name(_M_array, _M_sz, _M_stride, _Array<_Tp>(__v));\ + } \ + \ + template \ + template \ + inline void \ + slice_array<_Tp>::operator _Op##=(const _Expr<_Dom,_Tp>& __e) const\ + { \ + _Array_augmented_##_Name(_M_array, _M_stride, __e, _M_sz); \ + } + + +_DEFINE_VALARRAY_OPERATOR(*, __multiplies) +_DEFINE_VALARRAY_OPERATOR(/, __divides) +_DEFINE_VALARRAY_OPERATOR(%, __modulus) +_DEFINE_VALARRAY_OPERATOR(+, __plus) +_DEFINE_VALARRAY_OPERATOR(-, __minus) +_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) +_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) +_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) +_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _SLICE_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/std_abs.h b/resources/sources/avr-libstdcpp/include/bits/std_abs.h new file mode 100644 index 000000000..b0451a3ab --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/std_abs.h @@ -0,0 +1,111 @@ +// -*- C++ -*- C library enhancements header. + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/std_abs.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{cmath, cstdlib} + */ + +#ifndef _GLIBCXX_BITS_STD_ABS_H +#define _GLIBCXX_BITS_STD_ABS_H + +#pragma GCC system_header + +#include + +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include_next +#ifdef __CORRECT_ISO_CPP_MATH_H_PROTO +# include_next +#endif +#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS + +#undef abs + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::abs; + +#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO + inline long + abs(long __i) { return __builtin_labs(__i); } +#endif + +#ifdef _GLIBCXX_USE_LONG_LONG + inline long long + abs(long long __x) { return __builtin_llabs (__x); } +#endif + +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// 2192. Validity and return type of std::abs(0u) is unclear +// 2294. should declare abs(double) +// 2735. std::abs(short), std::abs(signed char) and others should return int + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR double + abs(double __x) + { return __builtin_fabs(__x); } + + inline _GLIBCXX_CONSTEXPR float + abs(float __x) + { return __builtin_fabsf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + abs(long double __x) + { return __builtin_fabsl(__x); } +#endif + +#if defined(__GLIBCXX_TYPE_INT_N_0) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0 + abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1 + abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2 + abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 + abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; } +#endif + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + inline _GLIBCXX_CONSTEXPR + __float128 + abs(__float128 __x) + { return __x < 0 ? -__x : __x; } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C"++" + +#endif // _GLIBCXX_BITS_STD_ABS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/std_function.h b/resources/sources/avr-libstdcpp/include/bits/std_function.h new file mode 100644 index 000000000..4a3848030 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/std_function.h @@ -0,0 +1,728 @@ +// Implementation of std::function -*- C++ -*- + +// Copyright (C) 2004-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/std_function.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_STD_FUNCTION_H +#define _GLIBCXX_STD_FUNCTION_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#if __cpp_rtti +# include +#endif +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * Trait identifying "location-invariant" types, meaning that the + * address of the object (or any of its members) will not escape. + * Trivially copyable types are location-invariant and users can + * specialize this trait for other types. + */ + template + struct __is_location_invariant + : is_trivially_copyable<_Tp>::type + { }; + + class _Undefined_class; + + union _Nocopy_types + { + void* _M_object; + const void* _M_const_object; + void (*_M_function_pointer)(); + void (_Undefined_class::*_M_member_pointer)(); + }; + + union [[gnu::may_alias]] _Any_data + { + void* _M_access() { return &_M_pod_data[0]; } + const void* _M_access() const { return &_M_pod_data[0]; } + + template + _Tp& + _M_access() + { return *static_cast<_Tp*>(_M_access()); } + + template + const _Tp& + _M_access() const + { return *static_cast(_M_access()); } + + _Nocopy_types _M_unused; + char _M_pod_data[sizeof(_Nocopy_types)]; + }; + + enum _Manager_operation + { + __get_type_info, + __get_functor_ptr, + __clone_functor, + __destroy_functor + }; + + template + class function; + + /// Base class of all polymorphic function object wrappers. + class _Function_base + { + public: + static const size_t _M_max_size = sizeof(_Nocopy_types); + static const size_t _M_max_align = __alignof__(_Nocopy_types); + + template + class _Base_manager + { + protected: + static const bool __stored_locally = + (__is_location_invariant<_Functor>::value + && sizeof(_Functor) <= _M_max_size + && __alignof__(_Functor) <= _M_max_align + && (_M_max_align % __alignof__(_Functor) == 0)); + + typedef integral_constant _Local_storage; + + // Retrieve a pointer to the function object + static _Functor* + _M_get_pointer(const _Any_data& __source) + { + if _GLIBCXX17_CONSTEXPR (__stored_locally) + { + const _Functor& __f = __source._M_access<_Functor>(); + return const_cast<_Functor*>(std::__addressof(__f)); + } + else // have stored a pointer + return __source._M_access<_Functor*>(); + } + + // Clone a location-invariant function object that fits within + // an _Any_data structure. + static void + _M_clone(_Any_data& __dest, const _Any_data& __source, true_type) + { + ::new (__dest._M_access()) _Functor(__source._M_access<_Functor>()); + } + + // Clone a function object that is not location-invariant or + // that cannot fit into an _Any_data structure. + static void + _M_clone(_Any_data& __dest, const _Any_data& __source, false_type) + { + __dest._M_access<_Functor*>() = + new _Functor(*__source._M_access()); + } + + // Destroying a location-invariant object may still require + // destruction. + static void + _M_destroy(_Any_data& __victim, true_type) + { + __victim._M_access<_Functor>().~_Functor(); + } + + // Destroying an object located on the heap. + static void + _M_destroy(_Any_data& __victim, false_type) + { + delete __victim._M_access<_Functor*>(); + } + + public: + static bool + _M_manager(_Any_data& __dest, const _Any_data& __source, + _Manager_operation __op) + { + switch (__op) + { +#if __cpp_rtti + case __get_type_info: + __dest._M_access() = &typeid(_Functor); + break; +#endif + case __get_functor_ptr: + __dest._M_access<_Functor*>() = _M_get_pointer(__source); + break; + + case __clone_functor: + _M_clone(__dest, __source, _Local_storage()); + break; + + case __destroy_functor: + _M_destroy(__dest, _Local_storage()); + break; + } + return false; + } + + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f) + { _M_init_functor(__functor, std::move(__f), _Local_storage()); } + + template + static bool + _M_not_empty_function(const function<_Signature>& __f) + { return static_cast(__f); } + + template + static bool + _M_not_empty_function(_Tp* __fp) + { return __fp != nullptr; } + + template + static bool + _M_not_empty_function(_Tp _Class::* __mp) + { return __mp != nullptr; } + + template + static bool + _M_not_empty_function(const _Tp&) + { return true; } + + private: + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type) + { ::new (__functor._M_access()) _Functor(std::move(__f)); } + + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type) + { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); } + }; + + _Function_base() : _M_manager(nullptr) { } + + ~_Function_base() + { + if (_M_manager) + _M_manager(_M_functor, _M_functor, __destroy_functor); + } + + bool _M_empty() const { return !_M_manager; } + + typedef bool (*_Manager_type)(_Any_data&, const _Any_data&, + _Manager_operation); + + _Any_data _M_functor; + _Manager_type _M_manager; + }; + + template + class _Function_handler; + + template + class _Function_handler<_Res(_ArgTypes...), _Functor> + : public _Function_base::_Base_manager<_Functor> + { + typedef _Function_base::_Base_manager<_Functor> _Base; + + public: + static bool + _M_manager(_Any_data& __dest, const _Any_data& __source, + _Manager_operation __op) + { + switch (__op) + { +#if __cpp_rtti + case __get_type_info: + __dest._M_access() = &typeid(_Functor); + break; +#endif + case __get_functor_ptr: + __dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source); + break; + + default: + _Base::_M_manager(__dest, __source, __op); + } + return false; + } + + static _Res + _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) + { + return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor), + std::forward<_ArgTypes>(__args)...); + } + }; + + /** + * @brief Primary class template for std::function. + * @ingroup functors + * + * Polymorphic function wrapper. + */ + template + class function<_Res(_ArgTypes...)> + : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, + private _Function_base + { + template> + struct _Callable + : __is_invocable_impl<_Res2, _Res>::type + { }; + + // Used so the return type convertibility checks aren't done when + // performing overload resolution for copy construction/assignment. + template + struct _Callable : false_type { }; + + template + using _Requires = typename enable_if<_Cond::value, _Tp>::type; + + public: + typedef _Res result_type; + + // [3.7.2.1] construct/copy/destroy + + /** + * @brief Default construct creates an empty function call wrapper. + * @post @c !(bool)*this + */ + function() noexcept + : _Function_base() { } + + /** + * @brief Creates an empty function call wrapper. + * @post @c !(bool)*this + */ + function(nullptr_t) noexcept + : _Function_base() { } + + /** + * @brief %Function copy constructor. + * @param __x A %function object with identical call signature. + * @post @c bool(*this) == bool(__x) + * + * The newly-created %function contains a copy of the target of @a + * __x (if it has one). + */ + function(const function& __x); + + /** + * @brief %Function move constructor. + * @param __x A %function object rvalue with identical call signature. + * + * The newly-created %function contains the target of @a __x + * (if it has one). + */ + function(function&& __x) noexcept : _Function_base() + { + __x.swap(*this); + } + + /** + * @brief Builds a %function that targets a copy of the incoming + * function object. + * @param __f A %function object that is callable with parameters of + * type @c T1, @c T2, ..., @c TN and returns a value convertible + * to @c Res. + * + * The newly-created %function object will target a copy of + * @a __f. If @a __f is @c reference_wrapper, then this function + * object will contain a reference to the function object @c + * __f.get(). If @a __f is a NULL function pointer or NULL + * pointer-to-member, the newly-created object will be empty. + * + * If @a __f is a non-NULL function pointer or an object of type @c + * reference_wrapper, this function will not throw. + */ + template>, void>, + typename = _Requires<_Callable<_Functor>, void>> + function(_Functor); + + /** + * @brief %Function assignment operator. + * @param __x A %function with identical call signature. + * @post @c (bool)*this == (bool)x + * @returns @c *this + * + * The target of @a __x is copied to @c *this. If @a __x has no + * target, then @c *this will be empty. + * + * If @a __x targets a function pointer or a reference to a function + * object, then this operation will not throw an %exception. + */ + function& + operator=(const function& __x) + { + function(__x).swap(*this); + return *this; + } + + /** + * @brief %Function move-assignment operator. + * @param __x A %function rvalue with identical call signature. + * @returns @c *this + * + * The target of @a __x is moved to @c *this. If @a __x has no + * target, then @c *this will be empty. + * + * If @a __x targets a function pointer or a reference to a function + * object, then this operation will not throw an %exception. + */ + function& + operator=(function&& __x) noexcept + { + function(std::move(__x)).swap(*this); + return *this; + } + + /** + * @brief %Function assignment to zero. + * @post @c !(bool)*this + * @returns @c *this + * + * The target of @c *this is deallocated, leaving it empty. + */ + function& + operator=(nullptr_t) noexcept + { + if (_M_manager) + { + _M_manager(_M_functor, _M_functor, __destroy_functor); + _M_manager = nullptr; + _M_invoker = nullptr; + } + return *this; + } + + /** + * @brief %Function assignment to a new target. + * @param __f A %function object that is callable with parameters of + * type @c T1, @c T2, ..., @c TN and returns a value convertible + * to @c Res. + * @return @c *this + * + * This %function object wrapper will target a copy of @a + * __f. If @a __f is @c reference_wrapper, then this function + * object will contain a reference to the function object @c + * __f.get(). If @a __f is a NULL function pointer or NULL + * pointer-to-member, @c this object will be empty. + * + * If @a __f is a non-NULL function pointer or an object of type @c + * reference_wrapper, this function will not throw. + */ + template + _Requires<_Callable::type>, function&> + operator=(_Functor&& __f) + { + function(std::forward<_Functor>(__f)).swap(*this); + return *this; + } + + /// @overload + template + function& + operator=(reference_wrapper<_Functor> __f) noexcept + { + function(__f).swap(*this); + return *this; + } + + // [3.7.2.2] function modifiers + + /** + * @brief Swap the targets of two %function objects. + * @param __x A %function with identical call signature. + * + * Swap the targets of @c this function object and @a __f. This + * function will not throw an %exception. + */ + void swap(function& __x) noexcept + { + std::swap(_M_functor, __x._M_functor); + std::swap(_M_manager, __x._M_manager); + std::swap(_M_invoker, __x._M_invoker); + } + + // [3.7.2.3] function capacity + + /** + * @brief Determine if the %function wrapper has a target. + * + * @return @c true when this %function object contains a target, + * or @c false when it is empty. + * + * This function will not throw an %exception. + */ + explicit operator bool() const noexcept + { return !_M_empty(); } + + // [3.7.2.4] function invocation + + /** + * @brief Invokes the function targeted by @c *this. + * @returns the result of the target. + * @throws bad_function_call when @c !(bool)*this + * + * The function call operator invokes the target function object + * stored by @c this. + */ + _Res operator()(_ArgTypes... __args) const; + +#if __cpp_rtti + // [3.7.2.5] function target access + /** + * @brief Determine the type of the target of this function object + * wrapper. + * + * @returns the type identifier of the target function object, or + * @c typeid(void) if @c !(bool)*this. + * + * This function will not throw an %exception. + */ + const type_info& target_type() const noexcept; + + /** + * @brief Access the stored target function object. + * + * @return Returns a pointer to the stored target function object, + * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL + * pointer. + * + * This function does not throw exceptions. + * + * @{ + */ + template _Functor* target() noexcept; + + template const _Functor* target() const noexcept; + // @} +#endif + + private: + using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...); + _Invoker_type _M_invoker; + }; + +#if __cpp_deduction_guides >= 201606 + template + struct __function_guide_helper + { }; + + template + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) & noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) const noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) const & noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template + function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>; + + template::type> + function(_Functor) -> function<_Signature>; +#endif + + // Out-of-line member definitions. + template + function<_Res(_ArgTypes...)>:: + function(const function& __x) + : _Function_base() + { + if (static_cast(__x)) + { + __x._M_manager(_M_functor, __x._M_functor, __clone_functor); + _M_invoker = __x._M_invoker; + _M_manager = __x._M_manager; + } + } + + template + template + function<_Res(_ArgTypes...)>:: + function(_Functor __f) + : _Function_base() + { + typedef _Function_handler<_Res(_ArgTypes...), _Functor> _My_handler; + + if (_My_handler::_M_not_empty_function(__f)) + { + _My_handler::_M_init_functor(_M_functor, std::move(__f)); + _M_invoker = &_My_handler::_M_invoke; + _M_manager = &_My_handler::_M_manager; + } + } + + template + _Res + function<_Res(_ArgTypes...)>:: + operator()(_ArgTypes... __args) const + { + if (_M_empty()) + __throw_bad_function_call(); + return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...); + } + +#if __cpp_rtti + template + const type_info& + function<_Res(_ArgTypes...)>:: + target_type() const noexcept + { + if (_M_manager) + { + _Any_data __typeinfo_result; + _M_manager(__typeinfo_result, _M_functor, __get_type_info); + return *__typeinfo_result._M_access(); + } + else + return typeid(void); + } + + template + template + _Functor* + function<_Res(_ArgTypes...)>:: + target() noexcept + { + const function* __const_this = this; + const _Functor* __func = __const_this->template target<_Functor>(); + return const_cast<_Functor*>(__func); + } + + template + template + const _Functor* + function<_Res(_ArgTypes...)>:: + target() const noexcept + { + if (typeid(_Functor) == target_type() && _M_manager) + { + _Any_data __ptr; + _M_manager(__ptr, _M_functor, __get_functor_ptr); + return __ptr._M_access(); + } + else + return nullptr; + } +#endif + + // [20.7.15.2.6] null pointer comparisons + + /** + * @brief Compares a polymorphic function object wrapper against 0 + * (the NULL pointer). + * @returns @c true if the wrapper has no target, @c false otherwise + * + * This function will not throw an %exception. + */ + template + inline bool + operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept + { return !static_cast(__f); } + +#if __cpp_impl_three_way_comparison < 201907L + /// @overload + template + inline bool + operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept + { return !static_cast(__f); } + + /** + * @brief Compares a polymorphic function object wrapper against 0 + * (the NULL pointer). + * @returns @c false if the wrapper has no target, @c true otherwise + * + * This function will not throw an %exception. + */ + template + inline bool + operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept + { return static_cast(__f); } + + /// @overload + template + inline bool + operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept + { return static_cast(__f); } +#endif + + // [20.7.15.2.7] specialized algorithms + + /** + * @brief Swap the targets of two polymorphic function object wrappers. + * + * This function will not throw an %exception. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps + template + inline void + swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept + { __x.swap(__y); } + +#if __cplusplus >= 201703L + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing a + // function into a variant. + template + struct _Never_valueless_alt> + : std::true_type + { }; + } // namespace __detail::__variant +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 +#endif // _GLIBCXX_STD_FUNCTION_H diff --git a/resources/sources/avr-libstdcpp/include/bits/std_mutex.h b/resources/sources/avr-libstdcpp/include/bits/std_mutex.h new file mode 100644 index 000000000..aef12b679 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/std_mutex.h @@ -0,0 +1,176 @@ +// std::mutex implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/std_mutex.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{mutex} + */ + +#ifndef _GLIBCXX_MUTEX_H +#define _GLIBCXX_MUTEX_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup mutexes Mutexes + * @ingroup concurrency + * + * Classes for mutex support. + * @{ + */ + +#ifdef _GLIBCXX_HAS_GTHREADS + // Common base class for std::mutex and std::timed_mutex + class __mutex_base + { + protected: + typedef __gthread_mutex_t __native_type; + +#ifdef __GTHREAD_MUTEX_INIT + __native_type _M_mutex = __GTHREAD_MUTEX_INIT; + + constexpr __mutex_base() noexcept = default; +#else + __native_type _M_mutex; + + __mutex_base() noexcept + { + // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) + __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); + } + + ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } +#endif + + __mutex_base(const __mutex_base&) = delete; + __mutex_base& operator=(const __mutex_base&) = delete; + }; + + /// The standard mutex type. + class mutex : private __mutex_base + { + public: + typedef __native_type* native_handle_type; + +#ifdef __GTHREAD_MUTEX_INIT + constexpr +#endif + mutex() noexcept = default; + ~mutex() = default; + + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + + void + lock() + { + int __e = __gthread_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() noexcept + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_mutex_trylock(&_M_mutex); + } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EPERM + __gthread_mutex_unlock(&_M_mutex); + } + + native_handle_type + native_handle() noexcept + { return &_M_mutex; } + }; + +#endif // _GLIBCXX_HAS_GTHREADS + + /// Do not acquire ownership of the mutex. + struct defer_lock_t { explicit defer_lock_t() = default; }; + + /// Try to acquire ownership of the mutex without blocking. + struct try_to_lock_t { explicit try_to_lock_t() = default; }; + + /// Assume the calling thread has already obtained mutex ownership + /// and manage it. + struct adopt_lock_t { explicit adopt_lock_t() = default; }; + + /// Tag used to prevent a scoped lock from acquiring ownership of a mutex. + _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { }; + + /// Tag used to prevent a scoped lock from blocking if a mutex is locked. + _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { }; + + /// Tag used to make a scoped lock take ownership of a locked mutex. + _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { }; + + /** @brief A simple scoped lock type. + * + * A lock_guard controls mutex ownership within a scope, releasing + * ownership in the destructor. + */ + template + class lock_guard + { + public: + typedef _Mutex mutex_type; + + explicit lock_guard(mutex_type& __m) : _M_device(__m) + { _M_device.lock(); } + + lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m) + { } // calling thread owns mutex + + ~lock_guard() + { _M_device.unlock(); } + + lock_guard(const lock_guard&) = delete; + lock_guard& operator=(const lock_guard&) = delete; + + private: + mutex_type& _M_device; + }; + + // @} group mutexes +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // C++11 +#endif // _GLIBCXX_MUTEX_H diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_algo.h b/resources/sources/avr-libstdcpp/include/bits/stl_algo.h new file mode 100644 index 000000000..2eb637e85 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_algo.h @@ -0,0 +1,5884 @@ +// Algorithm implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_algo.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _STL_ALGO_H +#define _STL_ALGO_H 1 + +#include // for rand +#include +#include +#include // for _Temporary_buffer +#include + +#if __cplusplus >= 201103L +#include +#endif + +// See concept_check.h for the __glibcxx_*_requires macros. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Swaps the median value of *__a, *__b and *__c under __comp to *__result + template + _GLIBCXX20_CONSTEXPR + void + __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b, + _Iterator __c, _Compare __comp) + { + if (__comp(__a, __b)) + { + if (__comp(__b, __c)) + std::iter_swap(__result, __b); + else if (__comp(__a, __c)) + std::iter_swap(__result, __c); + else + std::iter_swap(__result, __a); + } + else if (__comp(__a, __c)) + std::iter_swap(__result, __a); + else if (__comp(__b, __c)) + std::iter_swap(__result, __c); + else + std::iter_swap(__result, __b); + } + + /// Provided for stable_partition to use. + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + __find_if_not(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__negate(__pred), + std::__iterator_category(__first)); + } + + /// Like find_if_not(), but uses and updates a count of the + /// remaining range length instead of comparing against an end + /// iterator. + template + _GLIBCXX20_CONSTEXPR + _InputIterator + __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred) + { + for (; __len; --__len, (void) ++__first) + if (!__pred(__first)) + break; + return __first; + } + + // set_difference + // set_intersection + // set_symmetric_difference + // set_union + // for_each + // find + // find_if + // find_first_of + // adjacent_find + // count + // count_if + // search + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator1 + __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __predicate) + { + // Test for empty ranges + if (__first1 == __last1 || __first2 == __last2) + return __first1; + + // Test for a pattern of length 1. + _ForwardIterator2 __p1(__first2); + if (++__p1 == __last2) + return std::__find_if(__first1, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); + + // General case. + _ForwardIterator1 __current = __first1; + + for (;;) + { + __first1 = + std::__find_if(__first1, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); + + if (__first1 == __last1) + return __last1; + + _ForwardIterator2 __p = __p1; + __current = __first1; + if (++__current == __last1) + return __last1; + + while (__predicate(__current, __p)) + { + if (++__p == __last2) + return __first1; + if (++__current == __last1) + return __last1; + } + ++__first1; + } + return __first1; + } + + // search_n + + /** + * This is an helper function for search_n overloaded for forward iterators. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __search_n_aux(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, _UnaryPredicate __unary_pred, + std::forward_iterator_tag) + { + __first = std::__find_if(__first, __last, __unary_pred); + while (__first != __last) + { + typename iterator_traits<_ForwardIterator>::difference_type + __n = __count; + _ForwardIterator __i = __first; + ++__i; + while (__i != __last && __n != 1 && __unary_pred(__i)) + { + ++__i; + --__n; + } + if (__n == 1) + return __first; + if (__i == __last) + return __last; + __first = std::__find_if(++__i, __last, __unary_pred); + } + return __last; + } + + /** + * This is an helper function for search_n overloaded for random access + * iterators. + */ + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIter + __search_n_aux(_RandomAccessIter __first, _RandomAccessIter __last, + _Integer __count, _UnaryPredicate __unary_pred, + std::random_access_iterator_tag) + { + typedef typename std::iterator_traits<_RandomAccessIter>::difference_type + _DistanceType; + + _DistanceType __tailSize = __last - __first; + _DistanceType __remainder = __count; + + while (__remainder <= __tailSize) // the main loop... + { + __first += __remainder; + __tailSize -= __remainder; + // __first here is always pointing to one past the last element of + // next possible match. + _RandomAccessIter __backTrack = __first; + while (__unary_pred(--__backTrack)) + { + if (--__remainder == 0) + return (__first - __count); // Success + } + __remainder = __count + 1 - (__first - __backTrack); + } + return __last; // Failure + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, + _UnaryPredicate __unary_pred) + { + if (__count <= 0) + return __first; + + if (__count == 1) + return std::__find_if(__first, __last, __unary_pred); + + return std::__search_n_aux(__first, __last, __count, __unary_pred, + std::__iterator_category(__first)); + } + + // find_end for forward iterators. + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator1 + __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + forward_iterator_tag, forward_iterator_tag, + _BinaryPredicate __comp) + { + if (__first2 == __last2) + return __last1; + + _ForwardIterator1 __result = __last1; + while (1) + { + _ForwardIterator1 __new_result + = std::__search(__first1, __last1, __first2, __last2, __comp); + if (__new_result == __last1) + return __result; + else + { + __result = __new_result; + __first1 = __new_result; + ++__first1; + } + } + } + + // find_end for bidirectional iterators (much faster). + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator1 + __find_end(_BidirectionalIterator1 __first1, + _BidirectionalIterator1 __last1, + _BidirectionalIterator2 __first2, + _BidirectionalIterator2 __last2, + bidirectional_iterator_tag, bidirectional_iterator_tag, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator1>) + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator2>) + + typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1; + typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2; + + _RevIterator1 __rlast1(__first1); + _RevIterator2 __rlast2(__first2); + _RevIterator1 __rresult = std::__search(_RevIterator1(__last1), __rlast1, + _RevIterator2(__last2), __rlast2, + __comp); + + if (__rresult == __rlast1) + return __last1; + else + { + _BidirectionalIterator1 __result = __rresult.base(); + std::advance(__result, -std::distance(__first2, __last2)); + return __result; + } + } + + /** + * @brief Find last matching subsequence in a sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of sequence to match. + * @param __last2 End of sequence to match. + * @return The last iterator @c i in the range + * @p [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == + * @p *(__first2+N) for each @c N in the range @p + * [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) and returns an iterator to the __first + * element of the sub-sequence, or @p __last1 if the sub-sequence + * is not found. The sub-sequence will be the last such + * subsequence contained in [__first1,__last1). + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. This means that the returned + * iterator @c i will be in the range @p + * [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__find_end(__first1, __last1, __first2, __last2, + std::__iterator_category(__first1), + std::__iterator_category(__first2), + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Find last matching subsequence in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of sequence to match. + * @param __last2 End of sequence to match. + * @param __comp The predicate to use. + * @return The last iterator @c i in the range @p + * [__first1,__last1-(__last2-__first2)) such that @c + * predicate(*(i+N), @p (__first2+N)) is true for each @c N in the + * range @p [0,__last2-__first2), or @p __last1 if no such iterator + * exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) using comp as a predicate and returns an + * iterator to the first element of the sub-sequence, or @p __last1 + * if the sub-sequence is not found. The sub-sequence will be the + * last such subsequence contained in [__first,__last1). + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. This means that the returned + * iterator @c i will be in the range @p + * [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__find_end(__first1, __last1, __first2, __last2, + std::__iterator_category(__first1), + std::__iterator_category(__first2), + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cplusplus >= 201103L + /** + * @brief Checks that a predicate is true for all the elements + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if @p __pred is true for each element in the range + * @p [__first,__last), and false otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return __last == std::find_if_not(__first, __last, __pred); } + + /** + * @brief Checks that a predicate is false for all the elements + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if @p __pred is false for each element in the range + * @p [__first,__last), and false otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return __last == _GLIBCXX_STD_A::find_if(__first, __last, __pred); } + + /** + * @brief Checks that a predicate is true for at least one element + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if an element exists in the range @p + * [__first,__last) such that @p __pred is true, and false + * otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return !std::none_of(__first, __last, __pred); } + + /** + * @brief Find the first element in a sequence for which a + * predicate is false. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @p __pred(*i) is false, or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + find_if_not(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + return std::__find_if_not(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Checks whether the sequence is partitioned. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the range @p [__first,__last) is partioned by @p __pred, + * i.e. if all elements that satisfy @p __pred appear before those that + * do not. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_partitioned(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + __first = std::find_if_not(__first, __last, __pred); + if (__first == __last) + return true; + ++__first; + return std::none_of(__first, __last, __pred); + } + + /** + * @brief Find the partition point of a partitioned range. + * @ingroup mutating_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __pred A predicate. + * @return An iterator @p mid such that @p all_of(__first, mid, __pred) + * and @p none_of(mid, __last, __pred) are both true. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + partition_point(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + + // A specific debug-mode test will be necessary... + __glibcxx_requires_valid_range(__first, __last); + + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__pred(*__middle)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } +#endif + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __remove_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + for (; __first != __last; ++__first) + if (!__pred(__first)) + { + *__result = *__first; + ++__result; + } + return __result; + } + + /** + * @brief Copy a sequence, removing elements of a given value. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __value The value to be removed. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) not equal + * to @p __value to the range beginning at @p __result. + * remove_copy() is stable, so the relative order of elements that + * are copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + remove_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Copy a sequence, removing elements for which a predicate is true. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns false to the range beginning at @p __result. + * + * remove_copy_if() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + remove_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + +#if __cplusplus >= 201103L + /** + * @brief Copy the elements of a sequence for which a predicate is true. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns true to the range beginning at @p __result. + * + * copy_if() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + { + *__result = *__first; + ++__result; + } + return __result; + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result) + { + if (__n > 0) + { + while (true) + { + *__result = *__first; + ++__result; + if (--__n > 0) + ++__first; + else + break; + } + } + return __result; + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __copy_n(_InputIterator __first, _Size __n, + _OutputIterator __result, input_iterator_tag) + { + return std::__niter_wrap(__result, + __copy_n_a(__first, __n, + std::__niter_base(__result))); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __copy_n(_RandomAccessIterator __first, _Size __n, + _OutputIterator __result, random_access_iterator_tag) + { return std::copy(__first, __first + __n, __result); } + + /** + * @brief Copies the range [first,first+n) into [result,result+n). + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __n The number of elements to copy. + * @param __result An output iterator. + * @return result+n. + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_can_increment(__first, __n); + __glibcxx_requires_can_increment(__result, __n); + + return std::__copy_n(__first, __n, __result, + std::__iterator_category(__first)); + } + + /** + * @brief Copy the elements of a sequence to separate output sequences + * depending on the truth value of a predicate. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __out_true An output iterator. + * @param __out_false An output iterator. + * @param __pred A predicate. + * @return A pair designating the ends of the resulting sequences. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns true to the range beginning at @p out_true + * and each element for which @p __pred returns false to @p __out_false. + */ + template + _GLIBCXX20_CONSTEXPR + pair<_OutputIterator1, _OutputIterator2> + partition_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator1 __out_true, _OutputIterator2 __out_false, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator1, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator2, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + + return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); + } +#endif // C++11 + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __remove_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + __first = std::__find_if(__first, __last, __pred); + if (__first == __last) + return __first; + _ForwardIterator __result = __first; + ++__first; + for (; __first != __last; ++__first) + if (!__pred(__first)) + { + *__result = _GLIBCXX_MOVE(*__first); + ++__result; + } + return __result; + } + + /** + * @brief Remove elements from a sequence. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __value The value to be removed. + * @return An iterator designating the end of the resulting sequence. + * + * All elements equal to @p __value are removed from the range + * @p [__first,__last). + * + * remove() is stable, so the relative order of elements that are + * not removed is unchanged. + * + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + remove(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Remove elements from a sequence using a predicate. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * All elements for which @p __pred returns true are removed from the range + * @p [__first,__last). + * + * remove_if() is stable, so the relative order of elements that are + * not removed is unchanged. + * + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + remove_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __adjacent_find(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + if (__first == __last) + return __last; + _ForwardIterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(__first, __next)) + return __first; + __first = __next; + } + return __last; + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __unique(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // Skip the beginning, if already unique. + __first = std::__adjacent_find(__first, __last, __binary_pred); + if (__first == __last) + return __last; + + // Do the real copy work. + _ForwardIterator __dest = __first; + ++__first; + while (++__first != __last) + if (!__binary_pred(__dest, __first)) + *++__dest = _GLIBCXX_MOVE(*__first); + return ++__dest; + } + + /** + * @brief Remove consecutive duplicate values from a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Removes all but the first element from each group of consecutive + * values that compare equal. + * unique() is stable, so the relative order of elements that are + * not removed is unchanged. + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + unique(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__unique(__first, __last, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Remove consecutive values from a sequence using a predicate. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __binary_pred A binary predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Removes all but the first element from each group of consecutive + * values for which @p __binary_pred returns true. + * unique() is stable, so the relative order of elements that are + * not removed is unchanged. + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + unique(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__unique(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for forward iterators and output iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __unique_copy(_ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __result, _BinaryPredicate __binary_pred, + forward_iterator_tag, output_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + + _ForwardIterator __next = __first; + *__result = *__first; + while (++__next != __last) + if (!__binary_pred(__first, __next)) + { + __first = __next; + *++__result = *__first; + } + return ++__result; + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for input iterators and output iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryPredicate __binary_pred, + input_iterator_tag, output_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_InputIterator>::value_type>) + + typename iterator_traits<_InputIterator>::value_type __value = *__first; + __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred)) + __rebound_pred + = __gnu_cxx::__ops::__iter_comp_val(__binary_pred); + *__result = __value; + while (++__first != __last) + if (!__rebound_pred(__first, __value)) + { + __value = *__first; + *++__result = __value; + } + return ++__result; + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for input iterators and forward iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __unique_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _BinaryPredicate __binary_pred, + input_iterator_tag, forward_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_InputIterator>::value_type>) + *__result = *__first; + while (++__first != __last) + if (!__binary_pred(__result, __first)) + *++__result = *__first; + return ++__result; + } + + /** + * This is an uglified reverse(_BidirectionalIterator, + * _BidirectionalIterator) + * overloaded for bidirectional iterators. + */ + template + _GLIBCXX20_CONSTEXPR + void + __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, + bidirectional_iterator_tag) + { + while (true) + if (__first == __last || __first == --__last) + return; + else + { + std::iter_swap(__first, __last); + ++__first; + } + } + + /** + * This is an uglified reverse(_BidirectionalIterator, + * _BidirectionalIterator) + * overloaded for random access iterators. + */ + template + _GLIBCXX20_CONSTEXPR + void + __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + if (__first == __last) + return; + --__last; + while (__first < __last) + { + std::iter_swap(__first, __last); + ++__first; + --__last; + } + } + + /** + * @brief Reverse a sequence. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @return reverse() returns no value. + * + * Reverses the order of the elements in the range @p [__first,__last), + * so that the first element becomes the last etc. + * For every @c i such that @p 0<=i<=(__last-__first)/2), @p reverse() + * swaps @p *(__first+i) and @p *(__last-(i+1)) + */ + template + _GLIBCXX20_CONSTEXPR + inline void + reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_requires_valid_range(__first, __last); + std::__reverse(__first, __last, std::__iterator_category(__first)); + } + + /** + * @brief Copy a sequence, reversing its elements. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies the elements in the range @p [__first,__last) to the + * range @p [__result,__result+(__last-__first)) such that the + * order of the elements is reversed. For every @c i such that @p + * 0<=i<=(__last-__first), @p reverse_copy() performs the + * assignment @p *(__result+(__last-__first)-1-i) = *(__first+i). + * The ranges @p [__first,__last) and @p + * [__result,__result+(__last-__first)) must not overlap. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + while (__first != __last) + { + --__last; + *__result = *__last; + ++__result; + } + return __result; + } + + /** + * This is a helper function for the rotate algorithm specialized on RAIs. + * It returns the greatest common divisor of two integer values. + */ + template + _GLIBCXX20_CONSTEXPR + _EuclideanRingElement + __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n) + { + while (__n != 0) + { + _EuclideanRingElement __t = __m % __n; + __m = __n; + __n = __t; + } + return __m; + } + + inline namespace _V2 + { + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __rotate(_ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + forward_iterator_tag) + { + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + _ForwardIterator __first2 = __middle; + do + { + std::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + } + while (__first2 != __last); + + _ForwardIterator __ret = __first; + + __first2 = __middle; + + while (__first2 != __last) + { + std::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + return __ret; + } + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator + __rotate(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + bidirectional_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + std::__reverse(__first, __middle, bidirectional_iterator_tag()); + std::__reverse(__middle, __last, bidirectional_iterator_tag()); + + while (__first != __middle && __middle != __last) + { + std::iter_swap(__first, --__last); + ++__first; + } + + if (__first == __middle) + { + std::__reverse(__middle, __last, bidirectional_iterator_tag()); + return __last; + } + else + { + std::__reverse(__first, __middle, bidirectional_iterator_tag()); + return __first; + } + } + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __rotate(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _Distance; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + + _Distance __n = __last - __first; + _Distance __k = __middle - __first; + + if (__k == __n - __k) + { + std::swap_ranges(__first, __middle, __middle); + return __middle; + } + + _RandomAccessIterator __p = __first; + _RandomAccessIterator __ret = __first + (__last - __middle); + + for (;;) + { + if (__k < __n - __k) + { + if (__is_pod(_ValueType) && __k == 1) + { + _ValueType __t = _GLIBCXX_MOVE(*__p); + _GLIBCXX_MOVE3(__p + 1, __p + __n, __p); + *(__p + __n - 1) = _GLIBCXX_MOVE(__t); + return __ret; + } + _RandomAccessIterator __q = __p + __k; + for (_Distance __i = 0; __i < __n - __k; ++ __i) + { + std::iter_swap(__p, __q); + ++__p; + ++__q; + } + __n %= __k; + if (__n == 0) + return __ret; + std::swap(__n, __k); + __k = __n - __k; + } + else + { + __k = __n - __k; + if (__is_pod(_ValueType) && __k == 1) + { + _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1)); + _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n); + *__p = _GLIBCXX_MOVE(__t); + return __ret; + } + _RandomAccessIterator __q = __p + __n; + __p = __q - __k; + for (_Distance __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + std::iter_swap(__p, __q); + } + __n %= __k; + if (__n == 0) + return __ret; + std::swap(__n, __k); + } + } + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 488. rotate throws away useful information + /** + * @brief Rotate the elements of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __middle A forward iterator. + * @param __last A forward iterator. + * @return first + (last - middle). + * + * Rotates the elements of the range @p [__first,__last) by + * @p (__middle - __first) positions so that the element at @p __middle + * is moved to @p __first, the element at @p __middle+1 is moved to + * @p __first+1 and so on for each element in the range + * @p [__first,__last). + * + * This effectively swaps the ranges @p [__first,__middle) and + * @p [__middle,__last). + * + * Performs + * @p *(__first+(n+(__last-__middle))%(__last-__first))=*(__first+n) + * for each @p n in the range @p [0,__last-__first). + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + rotate(_ForwardIterator __first, _ForwardIterator __middle, + _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + + return std::__rotate(__first, __middle, __last, + std::__iterator_category(__first)); + } + + } // namespace _V2 + + /** + * @brief Copy a sequence, rotating its elements. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __middle A forward iterator. + * @param __last A forward iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies the elements of the range @p [__first,__last) to the + * range beginning at @result, rotating the copied elements by + * @p (__middle-__first) positions so that the element at @p __middle + * is moved to @p __result, the element at @p __middle+1 is moved + * to @p __result+1 and so on for each element in the range @p + * [__first,__last). + * + * Performs + * @p *(__result+(n+(__last-__middle))%(__last-__first))=*(__first+n) + * for each @p n in the range @p [0,__last-__first). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, + _ForwardIterator __last, _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + + return std::copy(__first, __middle, + std::copy(__middle, __last, __result)); + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, forward_iterator_tag) + { + if (__first == __last) + return __first; + + while (__pred(*__first)) + if (++__first == __last) + return __first; + + _ForwardIterator __next = __first; + + while (++__next != __last) + if (__pred(*__next)) + { + std::iter_swap(__first, __next); + ++__first; + } + + return __first; + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator + __partition(_BidirectionalIterator __first, _BidirectionalIterator __last, + _Predicate __pred, bidirectional_iterator_tag) + { + while (true) + { + while (true) + if (__first == __last) + return __first; + else if (__pred(*__first)) + ++__first; + else + break; + --__last; + while (true) + if (__first == __last) + return __first; + else if (!bool(__pred(*__last))) + --__last; + else + break; + std::iter_swap(__first, __last); + ++__first; + } + } + + // partition + + /// This is a helper function... + /// Requires __first != __last and !__pred(__first) + /// and __len == distance(__first, __last). + /// + /// !__pred(__first) allows us to guarantee that we don't + /// move-assign an element onto itself. + template + _ForwardIterator + __stable_partition_adaptive(_ForwardIterator __first, + _ForwardIterator __last, + _Predicate __pred, _Distance __len, + _Pointer __buffer, + _Distance __buffer_size) + { + if (__len == 1) + return __first; + + if (__len <= __buffer_size) + { + _ForwardIterator __result1 = __first; + _Pointer __result2 = __buffer; + + // The precondition guarantees that !__pred(__first), so + // move that element to the buffer before starting the loop. + // This ensures that we only call __pred once per element. + *__result2 = _GLIBCXX_MOVE(*__first); + ++__result2; + ++__first; + for (; __first != __last; ++__first) + if (__pred(__first)) + { + *__result1 = _GLIBCXX_MOVE(*__first); + ++__result1; + } + else + { + *__result2 = _GLIBCXX_MOVE(*__first); + ++__result2; + } + + _GLIBCXX_MOVE3(__buffer, __result2, __result1); + return __result1; + } + + _ForwardIterator __middle = __first; + std::advance(__middle, __len / 2); + _ForwardIterator __left_split = + std::__stable_partition_adaptive(__first, __middle, __pred, + __len / 2, __buffer, + __buffer_size); + + // Advance past true-predicate values to satisfy this + // function's preconditions. + _Distance __right_len = __len - __len / 2; + _ForwardIterator __right_split = + std::__find_if_not_n(__middle, __right_len, __pred); + + if (__right_len) + __right_split = + std::__stable_partition_adaptive(__right_split, __last, __pred, + __right_len, + __buffer, __buffer_size); + + return std::rotate(__left_split, __middle, __right_split); + } + + template + _ForwardIterator + __stable_partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + __first = std::__find_if_not(__first, __last, __pred); + + if (__first == __last) + return __first; + + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _Temporary_buffer<_ForwardIterator, _ValueType> + __buf(__first, std::distance(__first, __last)); + return + std::__stable_partition_adaptive(__first, __last, __pred, + _DistanceType(__buf.requested_size()), + __buf.begin(), + _DistanceType(__buf.size())); + } + + /** + * @brief Move elements for which a predicate is true to the beginning + * of a sequence, preserving relative ordering. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate functor. + * @return An iterator @p middle such that @p __pred(i) is true for each + * iterator @p i in the range @p [first,middle) and false for each @p i + * in the range @p [middle,last). + * + * Performs the same function as @p partition() with the additional + * guarantee that the relative ordering of elements in each group is + * preserved, so any two elements @p x and @p y in the range + * @p [__first,__last) such that @p __pred(x)==__pred(y) will have the same + * relative ordering after calling @p stable_partition(). + */ + template + inline _ForwardIterator + stable_partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__stable_partition(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /// This is a helper function for the sort routines. + template + _GLIBCXX20_CONSTEXPR + void + __heap_select(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, _Compare __comp) + { + std::__make_heap(__first, __middle, __comp); + for (_RandomAccessIterator __i = __middle; __i < __last; ++__i) + if (__comp(__i, __first)) + std::__pop_heap(__first, __middle, __i, __comp); + } + + // partial_sort + + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last, + _Compare __comp) + { + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef iterator_traits<_RandomAccessIterator> _RItTraits; + typedef typename _RItTraits::difference_type _DistanceType; + + if (__result_first == __result_last) + return __result_last; + _RandomAccessIterator __result_real_last = __result_first; + while (__first != __last && __result_real_last != __result_last) + { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + + std::__make_heap(__result_first, __result_real_last, __comp); + while (__first != __last) + { + if (__comp(__first, __result_first)) + std::__adjust_heap(__result_first, _DistanceType(0), + _DistanceType(__result_real_last + - __result_first), + _InputValueType(*__first), __comp); + ++__first; + } + std::__sort_heap(__result_first, __result_real_last, __comp); + return __result_real_last; + } + + /** + * @brief Copy the smallest elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __result_first A random-access iterator. + * @param __result_last Another random-access iterator. + * @return An iterator indicating the end of the resulting sequence. + * + * Copies and sorts the smallest N values from the range @p [__first,__last) + * to the range beginning at @p __result_first, where the number of + * elements to be copied, @p N, is the smaller of @p (__last-__first) and + * @p (__result_last-__result_first). + * After the sort if @e i and @e j are iterators in the range + * @p [__result_first,__result_first+N) such that i precedes j then + * *j<*i is false. + * The value returned is @p __result_first+N. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _OutputValueType; +#endif + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_LessThanOpConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_LessThanComparableConcept<_OutputValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_valid_range(__result_first, __result_last); + + return std::__partial_sort_copy(__first, __last, + __result_first, __result_last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Copy the smallest elements of a sequence using a predicate for + * comparison. + * @ingroup sorting_algorithms + * @param __first An input iterator. + * @param __last Another input iterator. + * @param __result_first A random-access iterator. + * @param __result_last Another random-access iterator. + * @param __comp A comparison functor. + * @return An iterator indicating the end of the resulting sequence. + * + * Copies and sorts the smallest N values from the range @p [__first,__last) + * to the range beginning at @p result_first, where the number of + * elements to be copied, @p N, is the smaller of @p (__last-__first) and + * @p (__result_last-__result_first). + * After the sort if @e i and @e j are iterators in the range + * @p [__result_first,__result_first+N) such that i precedes j then + * @p __comp(*j,*i) is false. + * The value returned is @p __result_first+N. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last, + _Compare __comp) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _OutputValueType; +#endif + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _InputValueType, _OutputValueType>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _OutputValueType, _OutputValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_valid_range(__result_first, __result_last); + + return std::__partial_sort_copy(__first, __last, + __result_first, __result_last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __unguarded_linear_insert(_RandomAccessIterator __last, + _Compare __comp) + { + typename iterator_traits<_RandomAccessIterator>::value_type + __val = _GLIBCXX_MOVE(*__last); + _RandomAccessIterator __next = __last; + --__next; + while (__comp(__val, __next)) + { + *__last = _GLIBCXX_MOVE(*__next); + __last = __next; + --__next; + } + *__last = _GLIBCXX_MOVE(__val); + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__first == __last) return; + + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + if (__comp(__i, __first)) + { + typename iterator_traits<_RandomAccessIterator>::value_type + __val = _GLIBCXX_MOVE(*__i); + _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1); + *__first = _GLIBCXX_MOVE(__val); + } + else + std::__unguarded_linear_insert(__i, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + inline void + __unguarded_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + for (_RandomAccessIterator __i = __first; __i != __last; ++__i) + std::__unguarded_linear_insert(__i, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + /** + * @doctodo + * This controls some aspect of the sort routines. + */ + enum { _S_threshold = 16 }; + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __final_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__last - __first > int(_S_threshold)) + { + std::__insertion_sort(__first, __first + int(_S_threshold), __comp); + std::__unguarded_insertion_sort(__first + int(_S_threshold), __last, + __comp); + } + else + std::__insertion_sort(__first, __last, __comp); + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __unguarded_partition(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _RandomAccessIterator __pivot, _Compare __comp) + { + while (true) + { + while (__comp(__first, __pivot)) + ++__first; + --__last; + while (__comp(__pivot, __last)) + --__last; + if (!(__first < __last)) + return __first; + std::iter_swap(__first, __last); + ++__first; + } + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + __unguarded_partition_pivot(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + _RandomAccessIterator __mid = __first + (__last - __first) / 2; + std::__move_median_to_first(__first, __first + 1, __mid, __last - 1, + __comp); + return std::__unguarded_partition(__first + 1, __last, __first, __comp); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) + { + std::__heap_select(__first, __middle, __last, __comp); + std::__sort_heap(__first, __middle, __comp); + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __introsort_loop(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Size __depth_limit, _Compare __comp) + { + while (__last - __first > int(_S_threshold)) + { + if (__depth_limit == 0) + { + std::__partial_sort(__first, __last, __last, __comp); + return; + } + --__depth_limit; + _RandomAccessIterator __cut = + std::__unguarded_partition_pivot(__first, __last, __comp); + std::__introsort_loop(__cut, __last, __depth_limit, __comp); + __last = __cut; + } + } + + // sort + + template + _GLIBCXX20_CONSTEXPR + inline void + __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + if (__first != __last) + { + std::__introsort_loop(__first, __last, + std::__lg(__last - __first) * 2, + __comp); + std::__final_insertion_sort(__first, __last, __comp); + } + } + + template + _GLIBCXX20_CONSTEXPR + void + __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last, _Size __depth_limit, + _Compare __comp) + { + while (__last - __first > 3) + { + if (__depth_limit == 0) + { + std::__heap_select(__first, __nth + 1, __last, __comp); + // Place the nth largest element in its final position. + std::iter_swap(__first, __nth); + return; + } + --__depth_limit; + _RandomAccessIterator __cut = + std::__unguarded_partition_pivot(__first, __last, __comp); + if (__cut <= __nth) + __first = __cut; + else + __last = __cut; + } + std::__insertion_sort(__first, __last, __comp); + } + + // nth_element + + // lower_bound moved to stl_algobase.h + + /** + * @brief Finds the first position in which @p __val could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An iterator pointing to the first element not less + * than @p __val, or end() if every element is less + * than @p __val. + * @ingroup binary_search_algorithms + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + + return std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp(__val, __middle)) + __len = __half; + else + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + return __first; + } + + /** + * @brief Finds the last position in which @p __val could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An iterator pointing to the first element greater than @p __val, + * or end() if no elements are greater than @p __val. + * @ingroup binary_search_algorithms + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + return std::__upper_bound(__first, __last, __val, + __gnu_cxx::__ops::__val_less_iter()); + } + + /** + * @brief Finds the last position in which @p __val could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An iterator pointing to the first element greater than @p __val, + * or end() if no elements are greater than @p __val. + * @ingroup binary_search_algorithms + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + return std::__upper_bound(__first, __last, __val, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + pair<_ForwardIterator, _ForwardIterator> + __equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, + _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp_it_val(__middle, __val)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (__comp_val_it(__val, __middle)) + __len = __half; + else + { + _ForwardIterator __left + = std::__lower_bound(__first, __middle, __val, __comp_it_val); + std::advance(__first, __len); + _ForwardIterator __right + = std::__upper_bound(++__middle, __first, __val, __comp_val_it); + return pair<_ForwardIterator, _ForwardIterator>(__left, __right); + } + } + return pair<_ForwardIterator, _ForwardIterator>(__first, __first); + } + + /** + * @brief Finds the largest subrange in which @p __val could be inserted + * at any place in it without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An pair of iterators defining the subrange. + * @ingroup binary_search_algorithms + * + * This is equivalent to + * @code + * std::make_pair(lower_bound(__first, __last, __val), + * upper_bound(__first, __last, __val)) + * @endcode + * but does not actually call those functions. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + return std::__equal_range(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val(), + __gnu_cxx::__ops::__val_less_iter()); + } + + /** + * @brief Finds the largest subrange in which @p __val could be inserted + * at any place in it without changing the ordering. + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An pair of iterators defining the subrange. + * @ingroup binary_search_algorithms + * + * This is equivalent to + * @code + * std::make_pair(lower_bound(__first, __last, __val, __comp), + * upper_bound(__first, __last, __val, __comp)) + * @endcode + * but does not actually call those functions. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + return std::__equal_range(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp), + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + /** + * @brief Determines whether an element exists in a range. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return True if @p __val (or its equivalent) is in [@p + * __first,@p __last ]. + * + * Note that this does not actually return an iterator to @p __val. For + * that, use std::find or a container's specialized find member functions. + */ + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + _ForwardIterator __i + = std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val()); + return __i != __last && !(__val < *__i); + } + + /** + * @brief Determines whether an element exists in a range. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return True if @p __val (or its equivalent) is in @p [__first,__last]. + * + * Note that this does not actually return an iterator to @p __val. For + * that, use std::find or a container's specialized find member functions. + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + _ForwardIterator __i + = std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + return __i != __last && !bool(__comp(__val, *__i)); + } + + // merge + + /// This is a helper function for the __merge_adaptive routines. + template + void + __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + if (__first1 != __last1) + _GLIBCXX_MOVE3(__first1, __last1, __result); + } + + /// This is a helper function for the __merge_adaptive routines. + template + void + __move_merge_adaptive_backward(_BidirectionalIterator1 __first1, + _BidirectionalIterator1 __last1, + _BidirectionalIterator2 __first2, + _BidirectionalIterator2 __last2, + _BidirectionalIterator3 __result, + _Compare __comp) + { + if (__first1 == __last1) + { + _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); + return; + } + else if (__first2 == __last2) + return; + + --__last1; + --__last2; + while (true) + { + if (__comp(__last2, __last1)) + { + *--__result = _GLIBCXX_MOVE(*__last1); + if (__first1 == __last1) + { + _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); + return; + } + --__last1; + } + else + { + *--__result = _GLIBCXX_MOVE(*__last2); + if (__first2 == __last2) + return; + --__last2; + } + } + } + + /// This is a helper function for the merge routines. + template + _BidirectionalIterator1 + __rotate_adaptive(_BidirectionalIterator1 __first, + _BidirectionalIterator1 __middle, + _BidirectionalIterator1 __last, + _Distance __len1, _Distance __len2, + _BidirectionalIterator2 __buffer, + _Distance __buffer_size) + { + _BidirectionalIterator2 __buffer_end; + if (__len1 > __len2 && __len2 <= __buffer_size) + { + if (__len2) + { + __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last); + return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first); + } + else + return __first; + } + else if (__len1 <= __buffer_size) + { + if (__len1) + { + __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + _GLIBCXX_MOVE3(__middle, __last, __first); + return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last); + } + else + return __last; + } + else + return std::rotate(__first, __middle, __last); + } + + /// This is a helper function for the merge routines. + template + void + __merge_adaptive(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Distance __len1, _Distance __len2, + _Pointer __buffer, _Distance __buffer_size, + _Compare __comp) + { + if (__len1 <= __len2 && __len1 <= __buffer_size) + { + _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last, + __first, __comp); + } + else if (__len2 <= __buffer_size) + { + _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + std::__move_merge_adaptive_backward(__first, __middle, __buffer, + __buffer_end, __last, __comp); + } + else + { + _BidirectionalIterator __first_cut = __first; + _BidirectionalIterator __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) + { + __len11 = __len1 / 2; + std::advance(__first_cut, __len11); + __second_cut + = std::__lower_bound(__middle, __last, *__first_cut, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + __len22 = std::distance(__middle, __second_cut); + } + else + { + __len22 = __len2 / 2; + std::advance(__second_cut, __len22); + __first_cut + = std::__upper_bound(__first, __middle, *__second_cut, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + __len11 = std::distance(__first, __first_cut); + } + + _BidirectionalIterator __new_middle + = std::__rotate_adaptive(__first_cut, __middle, __second_cut, + __len1 - __len11, __len22, __buffer, + __buffer_size); + std::__merge_adaptive(__first, __first_cut, __new_middle, __len11, + __len22, __buffer, __buffer_size, __comp); + std::__merge_adaptive(__new_middle, __second_cut, __last, + __len1 - __len11, + __len2 - __len22, __buffer, + __buffer_size, __comp); + } + } + + /// This is a helper function for the merge routines. + template + void + __merge_without_buffer(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Distance __len1, _Distance __len2, + _Compare __comp) + { + if (__len1 == 0 || __len2 == 0) + return; + + if (__len1 + __len2 == 2) + { + if (__comp(__middle, __first)) + std::iter_swap(__first, __middle); + return; + } + + _BidirectionalIterator __first_cut = __first; + _BidirectionalIterator __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) + { + __len11 = __len1 / 2; + std::advance(__first_cut, __len11); + __second_cut + = std::__lower_bound(__middle, __last, *__first_cut, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + __len22 = std::distance(__middle, __second_cut); + } + else + { + __len22 = __len2 / 2; + std::advance(__second_cut, __len22); + __first_cut + = std::__upper_bound(__first, __middle, *__second_cut, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + __len11 = std::distance(__first, __first_cut); + } + + _BidirectionalIterator __new_middle + = std::rotate(__first_cut, __middle, __second_cut); + std::__merge_without_buffer(__first, __first_cut, __new_middle, + __len11, __len22, __comp); + std::__merge_without_buffer(__new_middle, __second_cut, __last, + __len1 - __len11, __len2 - __len22, __comp); + } + + template + void + __inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_BidirectionalIterator>::value_type + _ValueType; + typedef typename iterator_traits<_BidirectionalIterator>::difference_type + _DistanceType; + + if (__first == __middle || __middle == __last) + return; + + const _DistanceType __len1 = std::distance(__first, __middle); + const _DistanceType __len2 = std::distance(__middle, __last); + + typedef _Temporary_buffer<_BidirectionalIterator, _ValueType> _TmpBuf; + _TmpBuf __buf(__first, __len1 + __len2); + + if (__buf.begin() == 0) + std::__merge_without_buffer + (__first, __middle, __last, __len1, __len2, __comp); + else + std::__merge_adaptive + (__first, __middle, __last, __len1, __len2, __buf.begin(), + _DistanceType(__buf.size()), __comp); + } + + /** + * @brief Merges two sorted ranges in place. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Merges two sorted and consecutive ranges, [__first,__middle) and + * [__middle,__last), and puts the result in [__first,__last). The + * output will be sorted. The sort is @e stable, that is, for + * equivalent elements in the two ranges, elements from the first + * range will always come before elements from the second. + * + * If enough additional memory is available, this takes (__last-__first)-1 + * comparisons. Otherwise an NlogN algorithm is used, where N is + * distance(__first,__last). + */ + template + inline void + inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_sorted(__first, __middle); + __glibcxx_requires_sorted(__middle, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__inplace_merge(__first, __middle, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Merges two sorted ranges in place. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @param __comp A functor to use for comparisons. + * @return Nothing. + * + * Merges two sorted and consecutive ranges, [__first,__middle) and + * [middle,last), and puts the result in [__first,__last). The output will + * be sorted. The sort is @e stable, that is, for equivalent + * elements in the two ranges, elements from the first range will always + * come before elements from the second. + * + * If enough additional memory is available, this takes (__last-__first)-1 + * comparisons. Otherwise an NlogN algorithm is used, where N is + * distance(__first,__last). + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + inline void + inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_sorted_pred(__first, __middle, __comp); + __glibcxx_requires_sorted_pred(__middle, __last, __comp); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__inplace_merge(__first, __middle, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + + /// This is a helper function for the __merge_sort_loop routines. + template + _OutputIterator + __move_merge(_InputIterator __first1, _InputIterator __last1, + _InputIterator __first2, _InputIterator __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + return _GLIBCXX_MOVE3(__first2, __last2, + _GLIBCXX_MOVE3(__first1, __last1, + __result)); + } + + template + void + __merge_sort_loop(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, _Distance __step_size, + _Compare __comp) + { + const _Distance __two_step = 2 * __step_size; + + while (__last - __first >= __two_step) + { + __result = std::__move_merge(__first, __first + __step_size, + __first + __step_size, + __first + __two_step, + __result, __comp); + __first += __two_step; + } + __step_size = std::min(_Distance(__last - __first), __step_size); + + std::__move_merge(__first, __first + __step_size, + __first + __step_size, __last, __result, __comp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __chunk_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Distance __chunk_size, _Compare __comp) + { + while (__last - __first >= __chunk_size) + { + std::__insertion_sort(__first, __first + __chunk_size, __comp); + __first += __chunk_size; + } + std::__insertion_sort(__first, __last, __comp); + } + + enum { _S_chunk_size = 7 }; + + template + void + __merge_sort_with_buffer(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Pointer __buffer, _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _Distance; + + const _Distance __len = __last - __first; + const _Pointer __buffer_last = __buffer + __len; + + _Distance __step_size = _S_chunk_size; + std::__chunk_insertion_sort(__first, __last, __step_size, __comp); + + while (__step_size < __len) + { + std::__merge_sort_loop(__first, __last, __buffer, + __step_size, __comp); + __step_size *= 2; + std::__merge_sort_loop(__buffer, __buffer_last, __first, + __step_size, __comp); + __step_size *= 2; + } + } + + template + void + __stable_sort_adaptive(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Pointer __buffer, _Distance __buffer_size, + _Compare __comp) + { + const _Distance __len = (__last - __first + 1) / 2; + const _RandomAccessIterator __middle = __first + __len; + if (__len > __buffer_size) + { + std::__stable_sort_adaptive(__first, __middle, __buffer, + __buffer_size, __comp); + std::__stable_sort_adaptive(__middle, __last, __buffer, + __buffer_size, __comp); + } + else + { + std::__merge_sort_with_buffer(__first, __middle, __buffer, __comp); + std::__merge_sort_with_buffer(__middle, __last, __buffer, __comp); + } + std::__merge_adaptive(__first, __middle, __last, + _Distance(__middle - __first), + _Distance(__last - __middle), + __buffer, __buffer_size, + __comp); + } + + /// This is a helper function for the stable sorting routines. + template + void + __inplace_stable_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__last - __first < 15) + { + std::__insertion_sort(__first, __last, __comp); + return; + } + _RandomAccessIterator __middle = __first + (__last - __first) / 2; + std::__inplace_stable_sort(__first, __middle, __comp); + std::__inplace_stable_sort(__middle, __last, __comp); + std::__merge_without_buffer(__first, __middle, __last, + __middle - __first, + __last - __middle, + __comp); + } + + // stable_sort + + // Set algorithms: includes, set_union, set_intersection, set_difference, + // set_symmetric_difference. All of these algorithms have the precondition + // that their input ranges are sorted and the postcondition that their output + // ranges are sorted. + + template + _GLIBCXX20_CONSTEXPR + bool + __includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first2, __first1)) + return false; + else if (__comp(__first1, __first2)) + ++__first1; + else + { + ++__first1; + ++__first2; + } + + return __first2 == __last2; + } + + /** + * @brief Determines whether all elements of a sequence exists in a range. + * @param __first1 Start of search range. + * @param __last1 End of search range. + * @param __first2 Start of sequence + * @param __last2 End of sequence. + * @return True if each element in [__first2,__last2) is contained in order + * within [__first1,__last1). False otherwise. + * @ingroup set_algorithms + * + * This operation expects both [__first1,__last1) and + * [__first2,__last2) to be sorted. Searches for the presence of + * each element in [__first2,__last2) within [__first1,__last1). + * The iterators over each range only move forward, so this is a + * linear algorithm. If an element in [__first2,__last2) is not + * found before the search iterator reaches @p __last2, false is + * returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return std::__includes(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Determines whether all elements of a sequence exists in a range + * using comparison. + * @ingroup set_algorithms + * @param __first1 Start of search range. + * @param __last1 End of search range. + * @param __first2 Start of sequence + * @param __last2 End of sequence. + * @param __comp Comparison function to use. + * @return True if each element in [__first2,__last2) is contained + * in order within [__first1,__last1) according to comp. False + * otherwise. @ingroup set_algorithms + * + * This operation expects both [__first1,__last1) and + * [__first2,__last2) to be sorted. Searches for the presence of + * each element in [__first2,__last2) within [__first1,__last1), + * using comp to decide. The iterators over each range only move + * forward, so this is a linear algorithm. If an element in + * [__first2,__last2) is not found before the search iterator + * reaches @p __last2, false is returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return std::__includes(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + // nth_element + // merge + // set_difference + // set_intersection + // set_union + // stable_sort + // set_symmetric_difference + // min_element + // max_element + + template + _GLIBCXX20_CONSTEXPR + bool + __next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + if (__first == __last) + return false; + _BidirectionalIterator __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) + { + _BidirectionalIterator __ii = __i; + --__i; + if (__comp(__i, __ii)) + { + _BidirectionalIterator __j = __last; + while (!__comp(__i, --__j)) + {} + std::iter_swap(__i, __j); + std::__reverse(__ii, __last, + std::__iterator_category(__first)); + return true; + } + if (__i == __first) + { + std::__reverse(__first, __last, + std::__iterator_category(__first)); + return false; + } + } + } + + /** + * @brief Permute range into the next @e dictionary ordering. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return False if wrapped to first permutation, true otherwise. + * + * Treats all permutations of the range as a set of @e dictionary sorted + * sequences. Permutes the current sequence into the next one of this set. + * Returns true if there are more sequences to generate. If the sequence + * is the largest of the set, the smallest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__next_permutation + (__first, __last, __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Permute range into the next @e dictionary ordering using + * comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp A comparison functor. + * @return False if wrapped to first permutation, true otherwise. + * + * Treats all permutations of the range [__first,__last) as a set of + * @e dictionary sorted sequences ordered by @p __comp. Permutes the current + * sequence into the next one of this set. Returns true if there are more + * sequences to generate. If the sequence is the largest of the set, the + * smallest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__next_permutation + (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + bool + __prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + if (__first == __last) + return false; + _BidirectionalIterator __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) + { + _BidirectionalIterator __ii = __i; + --__i; + if (__comp(__ii, __i)) + { + _BidirectionalIterator __j = __last; + while (!__comp(--__j, __i)) + {} + std::iter_swap(__i, __j); + std::__reverse(__ii, __last, + std::__iterator_category(__first)); + return true; + } + if (__i == __first) + { + std::__reverse(__first, __last, + std::__iterator_category(__first)); + return false; + } + } + } + + /** + * @brief Permute range into the previous @e dictionary ordering. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return False if wrapped to last permutation, true otherwise. + * + * Treats all permutations of the range as a set of @e dictionary sorted + * sequences. Permutes the current sequence into the previous one of this + * set. Returns true if there are more sequences to generate. If the + * sequence is the smallest of the set, the largest is generated and false + * returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__prev_permutation(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Permute range into the previous @e dictionary ordering using + * comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp A comparison functor. + * @return False if wrapped to last permutation, true otherwise. + * + * Treats all permutations of the range [__first,__last) as a set of + * @e dictionary sorted sequences ordered by @p __comp. Permutes the current + * sequence into the previous one of this set. Returns true if there are + * more sequences to generate. If the sequence is the smallest of the set, + * the largest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__prev_permutation(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + // replace + // replace_if + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __replace_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _Predicate __pred, const _Tp& __new_value) + { + for (; __first != __last; ++__first, (void)++__result) + if (__pred(__first)) + *__result = __new_value; + else + *__result = *__first; + return __result; + } + + /** + * @brief Copy a sequence, replacing each element of one value with another + * value. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __old_value The value to be replaced. + * @param __new_value The replacement value. + * @return The end of the output sequence, @p result+(last-first). + * + * Copies each element in the input range @p [__first,__last) to the + * output range @p [__result,__result+(__last-__first)) replacing elements + * equal to @p __old_value with @p __new_value. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + replace_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + const _Tp& __old_value, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__replace_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__iter_equals_val(__old_value), + __new_value); + } + + /** + * @brief Copy a sequence, replacing each value for which a predicate + * returns true with another value. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @param __new_value The replacement value. + * @return The end of the output sequence, @p __result+(__last-__first). + * + * Copies each element in the range @p [__first,__last) to the range + * @p [__result,__result+(__last-__first)) replacing elements for which + * @p __pred returns true with @p __new_value. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + replace_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _Predicate __pred, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__replace_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__pred_iter(__pred), + __new_value); + } + +#if __cplusplus >= 201103L + /** + * @brief Determines whether the elements of a sequence are sorted. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return True if the elements are sorted, false otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last) + { return std::is_sorted_until(__first, __last) == __last; } + + /** + * @brief Determines whether the elements of a sequence are sorted + * according to a comparison functor. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return True if the elements are sorted, false otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { return std::is_sorted_until(__first, __last, __comp) == __last; } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) + return __last; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (__comp(__next, __first)) + return __next; + return __next; + } + + /** + * @brief Determines the end of a sorted sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return An iterator pointing to the last iterator i in [__first, __last) + * for which the range [__first, i) is sorted. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__is_sorted_until(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Determines the end of a sorted sequence using comparison functor. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return An iterator pointing to the last iterator i in [__first, __last) + * for which the range [__first, i) is sorted. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__is_sorted_until(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Determines min and max at once as an ordered pair. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return A pair(__b, __a) if __b is smaller than __a, pair(__a, + * __b) otherwise. + */ + template + _GLIBCXX14_CONSTEXPR + inline pair + minmax(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + + return __b < __a ? pair(__b, __a) + : pair(__a, __b); + } + + /** + * @brief Determines min and max at once as an ordered pair. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor @endlink. + * @return A pair(__b, __a) if __b is smaller than __a, pair(__a, + * __b) otherwise. + */ + template + _GLIBCXX14_CONSTEXPR + inline pair + minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + return __comp(__b, __a) ? pair(__b, __a) + : pair(__a, __b); + } + + template + _GLIBCXX14_CONSTEXPR + pair<_ForwardIterator, _ForwardIterator> + __minmax_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + _ForwardIterator __next = __first; + if (__first == __last + || ++__next == __last) + return std::make_pair(__first, __first); + + _ForwardIterator __min{}, __max{}; + if (__comp(__next, __first)) + { + __min = __next; + __max = __first; + } + else + { + __min = __first; + __max = __next; + } + + __first = __next; + ++__first; + + while (__first != __last) + { + __next = __first; + if (++__next == __last) + { + if (__comp(__first, __min)) + __min = __first; + else if (!__comp(__first, __max)) + __max = __first; + break; + } + + if (__comp(__next, __first)) + { + if (__comp(__next, __min)) + __min = __next; + if (!__comp(__first, __max)) + __max = __first; + } + else + { + if (__comp(__first, __min)) + __min = __first; + if (!__comp(__next, __max)) + __max = __next; + } + + __first = __next; + ++__first; + } + + return std::make_pair(__min, __max); + } + + /** + * @brief Return a pair of iterators pointing to the minimum and maximum + * elements in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return make_pair(m, M), where m is the first iterator i in + * [__first, __last) such that no other element in the range is + * smaller, and where M is the last iterator i in [__first, __last) + * such that no other element in the range is larger. + */ + template + _GLIBCXX14_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + minmax_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__minmax_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return a pair of iterators pointing to the minimum and maximum + * elements in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return make_pair(m, M), where m is the first iterator i in + * [__first, __last) such that no other element in the range is + * smaller, and where M is the last iterator i in [__first, __last) + * such that no other element in the range is larger. + */ + template + _GLIBCXX14_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + minmax_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__minmax_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + // N2722 + DR 915. + template + _GLIBCXX14_CONSTEXPR + inline _Tp + min(initializer_list<_Tp> __l) + { return *std::min_element(__l.begin(), __l.end()); } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + min(initializer_list<_Tp> __l, _Compare __comp) + { return *std::min_element(__l.begin(), __l.end(), __comp); } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + max(initializer_list<_Tp> __l) + { return *std::max_element(__l.begin(), __l.end()); } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + max(initializer_list<_Tp> __l, _Compare __comp) + { return *std::max_element(__l.begin(), __l.end(), __comp); } + + template + _GLIBCXX14_CONSTEXPR + inline pair<_Tp, _Tp> + minmax(initializer_list<_Tp> __l) + { + pair __p = + std::minmax_element(__l.begin(), __l.end()); + return std::make_pair(*__p.first, *__p.second); + } + + template + _GLIBCXX14_CONSTEXPR + inline pair<_Tp, _Tp> + minmax(initializer_list<_Tp> __l, _Compare __comp) + { + pair __p = + std::minmax_element(__l.begin(), __l.end(), __comp); + return std::make_pair(*__p.first, *__p.second); + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __pred A binary predicate. + * @return true if there exists a permutation of the elements in + * the range [__first2, __first2 + (__last1 - __first1)), + * beginning with ForwardIterator2 begin, such that + * equal(__first1, __last1, __begin, __pred) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _BinaryPredicate __pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return std::__is_permutation(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_comp_iter(__pred)); + } + +#if __cplusplus > 201103L + template + _GLIBCXX20_CONSTEXPR + bool + __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) + { + using _Cat1 + = typename iterator_traits<_ForwardIterator1>::iterator_category; + using _Cat2 + = typename iterator_traits<_ForwardIterator2>::iterator_category; + using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>; + using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>; + constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA(); + if (__ra_iters) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!__pred(__first1, __first2)) + break; + + if (__ra_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) + { + if (__scan != std::__find_if(__first1, __scan, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) + continue; // We've seen this one before. + + auto __matches = std::__count_if(__first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); + if (0 == __matches + || std::__count_if(__scan, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) + != __matches) + return false; + } + return true; + } + + /** + * @brief Checks whether a permutaion of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of first range. + * @return true if there exists a permutation of the elements in the range + * [__first2, __last2), beginning with ForwardIterator2 begin, + * such that equal(__first1, __last1, begin) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return + std::__is_permutation(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of first range. + * @param __pred A binary predicate. + * @return true if there exists a permutation of the elements in the range + * [__first2, __last2), beginning with ForwardIterator2 begin, + * such that equal(__first1, __last1, __begin, __pred) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) + { + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__is_permutation(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred)); + } + +#if __cplusplus > 201402L + +#define __cpp_lib_clamp 201603 + + /** + * @brief Returns the value clamped between lo and hi. + * @ingroup sorting_algorithms + * @param __val A value of arbitrary type. + * @param __lo A lower limit of arbitrary type. + * @param __hi An upper limit of arbitrary type. + * @return max(__val, __lo) if __val < __hi or min(__val, __hi) otherwise. + */ + template + constexpr const _Tp& + clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi) + { + __glibcxx_assert(!(__hi < __lo)); + return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val; + } + + /** + * @brief Returns the value clamped between lo and hi. + * @ingroup sorting_algorithms + * @param __val A value of arbitrary type. + * @param __lo A lower limit of arbitrary type. + * @param __hi An upper limit of arbitrary type. + * @param __comp A comparison functor. + * @return max(__val, __lo, __comp) if __comp(__val, __hi) + * or min(__val, __hi, __comp) otherwise. + */ + template + constexpr const _Tp& + clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Compare __comp) + { + __glibcxx_assert(!__comp(__hi, __lo)); + return __comp(__val, __lo) ? __lo : __comp(__hi, __val) ? __hi : __val; + } +#endif // C++17 +#endif // C++14 + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + /** + * @brief Generate two uniformly distributed integers using a + * single distribution invocation. + * @param __b0 The upper bound for the first integer. + * @param __b1 The upper bound for the second integer. + * @param __g A UniformRandomBitGenerator. + * @return A pair (i, j) with i and j uniformly distributed + * over [0, __b0) and [0, __b1), respectively. + * + * Requires: __b0 * __b1 <= __g.max() - __g.min(). + * + * Using uniform_int_distribution with a range that is very + * small relative to the range of the generator ends up wasting + * potentially expensively generated randomness, since + * uniform_int_distribution does not store leftover randomness + * between invocations. + * + * If we know we want two integers in ranges that are sufficiently + * small, we can compose the ranges, use a single distribution + * invocation, and significantly reduce the waste. + */ + template + pair<_IntType, _IntType> + __gen_two_uniform_ints(_IntType __b0, _IntType __b1, + _UniformRandomBitGenerator&& __g) + { + _IntType __x + = uniform_int_distribution<_IntType>{0, (__b0 * __b1) - 1}(__g); + return std::make_pair(__x / __b1, __x % __b1); + } + + /** + * @brief Shuffle the elements of a sequence using a uniform random + * number generator. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __g A UniformRandomNumberGenerator (26.5.1.3). + * @return Nothing. + * + * Reorders the elements in the range @p [__first,__last) using @p __g to + * provide random numbers. + */ + template + void + shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, + _UniformRandomNumberGenerator&& __g) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return; + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + typedef typename std::make_unsigned<_DistanceType>::type __ud_type; + typedef typename std::uniform_int_distribution<__ud_type> __distr_type; + typedef typename __distr_type::param_type __p_type; + + typedef typename remove_reference<_UniformRandomNumberGenerator>::type + _Gen; + typedef typename common_type::type + __uc_type; + + const __uc_type __urngrange = __g.max() - __g.min(); + const __uc_type __urange = __uc_type(__last - __first); + + if (__urngrange / __urange >= __urange) + // I.e. (__urngrange >= __urange * __urange) but without wrap issues. + { + _RandomAccessIterator __i = __first + 1; + + // Since we know the range isn't empty, an even number of elements + // means an uneven number of elements /to swap/, in which case we + // do the first one up front: + + if ((__urange % 2) == 0) + { + __distr_type __d{0, 1}; + std::iter_swap(__i++, __first + __d(__g)); + } + + // Now we know that __last - __i is even, so we do the rest in pairs, + // using a single distribution invocation to produce swap positions + // for two successive elements at a time: + + while (__i != __last) + { + const __uc_type __swap_range = __uc_type(__i - __first) + 1; + + const pair<__uc_type, __uc_type> __pospos = + __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g); + + std::iter_swap(__i++, __first + __pospos.first); + std::iter_swap(__i++, __first + __pospos.second); + } + + return; + } + + __distr_type __d; + + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + std::iter_swap(__i, __first + __d(__g, __p_type(0, __i - __first))); + } +#endif + +#endif // C++11 + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + /** + * @brief Apply a function to every element of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __f A unary function object. + * @return @p __f + * + * Applies the function object @p __f to each element in the range + * @p [first,last). @p __f must not modify the order of the sequence. + * If @p __f has a return value it is ignored. + */ + template + _GLIBCXX20_CONSTEXPR + _Function + for_each(_InputIterator __first, _InputIterator __last, _Function __f) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + for (; __first != __last; ++__first) + __f(*__first); + return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant. + } + +#if __cplusplus >= 201703L + /** + * @brief Apply a function to every element of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __n A value convertible to an integer. + * @param __f A unary function object. + * @return `__first+__n` + * + * Applies the function object `__f` to each element in the range + * `[first, first+n)`. `__f` must not modify the order of the sequence. + * If `__f` has a return value it is ignored. + */ + template + _GLIBCXX20_CONSTEXPR + _InputIterator + for_each_n(_InputIterator __first, _Size __n, _Function __f) + { + auto __n2 = std::__size_to_integer(__n); + using _Cat = typename iterator_traits<_InputIterator>::iterator_category; + if constexpr (is_base_of_v) + { + if (__n2 <= 0) + return __first; + auto __last = __first + __n2; + std::for_each(__first, __last, std::move(__f)); + return __last; + } + else + { + while (__n2-->0) + { + __f(*__first); + ++__first; + } + return __first; + } + } +#endif // C++17 + + /** + * @brief Find the first occurrence of a value in a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __val The value to find. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @c *i == @p __val, or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + find(_InputIterator __first, _InputIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__val)); + } + + /** + * @brief Find the first element in a sequence for which a + * predicate is true. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @p __pred(*i) is true, or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + find_if(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Find element from a set in a sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of match candidates. + * @param __last2 End of match candidates. + * @return The first iterator @c i in the range + * @p [__first1,__last1) such that @c *i == @p *(i2) such that i2 is an + * iterator in [__first2,__last2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for an element that is + * equal to some element in the range [__first2,__last2). If + * found, returns an iterator in the range [__first1,__last1), + * otherwise returns @p __last1. + */ + template + _GLIBCXX20_CONSTEXPR + _InputIterator + find_first_of(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, _ForwardIterator __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + for (; __first1 != __last1; ++__first1) + for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) + if (*__first1 == *__iter) + return __first1; + return __last1; + } + + /** + * @brief Find element from a set in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of match candidates. + * @param __last2 End of match candidates. + * @param __comp Predicate to use. + * @return The first iterator @c i in the range + * @p [__first1,__last1) such that @c comp(*i, @p *(i2)) is true + * and i2 is an iterator in [__first2,__last2), or @p __last1 if no + * such iterator exists. + * + + * Searches the range @p [__first1,__last1) for an element that is + * equal to some element in the range [__first2,__last2). If + * found, returns an iterator in the range [__first1,__last1), + * otherwise returns @p __last1. + */ + template + _GLIBCXX20_CONSTEXPR + _InputIterator + find_first_of(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, _ForwardIterator __last2, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + for (; __first1 != __last1; ++__first1) + for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) + if (__comp(*__first1, *__iter)) + return __first1; + return __last1; + } + + /** + * @brief Find two adjacent values in a sequence that are equal. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return The first iterator @c i such that @c i and @c i+1 are both + * valid iterators in @p [__first,__last) and such that @c *i == @c *(i+1), + * or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + adjacent_find(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__adjacent_find(__first, __last, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Find two adjacent values in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __binary_pred A binary predicate. + * @return The first iterator @c i such that @c i and @c i+1 are both + * valid iterators in @p [__first,__last) and such that + * @p __binary_pred(*i,*(i+1)) is true, or @p __last if no such iterator + * exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + adjacent_find(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__adjacent_find(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + + /** + * @brief Count the number of copies of a value in a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __value The value to be counted. + * @return The number of iterators @c i in the range @p [__first,__last) + * for which @c *i == @p __value + */ + template + _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::difference_type + count(_InputIterator __first, _InputIterator __last, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__count_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Count the elements of a sequence for which a predicate is true. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The number of iterators @c i in the range @p [__first,__last) + * for which @p __pred(*i) is true. + */ + template + _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::difference_type + count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__count_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Search a sequence for a matching sub-sequence. + * @ingroup non_mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @param __last2 A forward iterator. + * @return The first iterator @c i in the range @p + * [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == @p + * *(__first2+N) for each @c N in the range @p + * [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) and returns an iterator to the first element + * of the sub-sequence, or @p __last1 if the sub-sequence is not + * found. + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. + * + * This means that the returned iterator @c i will be in the range + * @p [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__search(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Search a sequence for a matching sub-sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @param __last2 A forward iterator. + * @param __predicate A binary predicate. + * @return The first iterator @c i in the range + * @p [__first1,__last1-(__last2-__first2)) such that + * @p __predicate(*(i+N),*(__first2+N)) is true for each @c N in the range + * @p [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2), using @p __predicate to determine equality, + * and returns an iterator to the first element of the + * sub-sequence, or @p __last1 if no such iterator exists. + * + * @see search(_ForwardIter1, _ForwardIter1, _ForwardIter2, _ForwardIter2) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __predicate) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__search(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__predicate)); + } + + /** + * @brief Search a sequence for a number of consecutive values. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __count The number of consecutive values. + * @param __val The value to find. + * @return The first iterator @c i in the range @p + * [__first,__last-__count) such that @c *(i+N) == @p __val for + * each @c N in the range @p [0,__count), or @p __last if no such + * iterator exists. + * + * Searches the range @p [__first,__last) for @p count consecutive elements + * equal to @p __val. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__search_n(__first, __last, __count, + __gnu_cxx::__ops::__iter_equals_val(__val)); + } + + + /** + * @brief Search a sequence for a number of consecutive values using a + * predicate. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __count The number of consecutive values. + * @param __val The value to find. + * @param __binary_pred A binary predicate. + * @return The first iterator @c i in the range @p + * [__first,__last-__count) such that @p + * __binary_pred(*(i+N),__val) is true for each @c N in the range + * @p [0,__count), or @p __last if no such iterator exists. + * + * Searches the range @p [__first,__last) for @p __count + * consecutive elements for which the predicate returns true. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, const _Tp& __val, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__search_n(__first, __last, __count, + __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val)); + } + +#if __cplusplus > 201402L + /** @brief Search a sequence using a Searcher object. + * + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __searcher A callable object. + * @return @p __searcher(__first,__last).first + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search(_ForwardIterator __first, _ForwardIterator __last, + const _Searcher& __searcher) + { return __searcher(__first, __last).first; } +#endif + + /** + * @brief Perform an operation on a sequence. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __unary_op A unary operator. + * @return An output iterator equal to @p __result+(__last-__first). + * + * Applies the operator to each element in the input range and assigns + * the results to successive elements of the output sequence. + * Evaluates @p *(__result+N)=unary_op(*(__first+N)) for each @c N in the + * range @p [0,__last-__first). + * + * @p unary_op must not alter its argument. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _UnaryOperation __unary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _UnaryOperation" + __typeof__(__unary_op(*__first))>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first, (void)++__result) + *__result = __unary_op(*__first); + return __result; + } + + /** + * @brief Perform an operation on corresponding elements of two sequences. + * @ingroup mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __result An output iterator. + * @param __binary_op A binary operator. + * @return An output iterator equal to @p result+(last-first). + * + * Applies the operator to the corresponding elements in the two + * input ranges and assigns the results to successive elements of the + * output sequence. + * Evaluates @p + * *(__result+N)=__binary_op(*(__first1+N),*(__first2+N)) for each + * @c N in the range @p [0,__last1-__first1). + * + * @p binary_op must not alter either of its arguments. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _OutputIterator __result, + _BinaryOperation __binary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _BinaryOperation" + __typeof__(__binary_op(*__first1,*__first2))>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2, ++__result) + *__result = __binary_op(*__first1, *__first2); + return __result; + } + + /** + * @brief Replace each occurrence of one value in a sequence with another + * value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __old_value The value to be replaced. + * @param __new_value The replacement value. + * @return replace() returns no value. + * + * For each iterator @c i in the range @p [__first,__last) if @c *i == + * @p __old_value then the assignment @c *i = @p __new_value is performed. + */ + template + _GLIBCXX20_CONSTEXPR + void + replace(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __old_value, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (*__first == __old_value) + *__first = __new_value; + } + + /** + * @brief Replace each value in a sequence for which a predicate returns + * true with another value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate. + * @param __new_value The replacement value. + * @return replace_if() returns no value. + * + * For each iterator @c i in the range @p [__first,__last) if @p __pred(*i) + * is true then the assignment @c *i = @p __new_value is performed. + */ + template + _GLIBCXX20_CONSTEXPR + void + replace_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + *__first = __new_value; + } + + /** + * @brief Assign the result of a function object to each value in a + * sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __gen A function object taking no arguments and returning + * std::iterator_traits<_ForwardIterator>::value_type + * @return generate() returns no value. + * + * Performs the assignment @c *i = @p __gen() for each @c i in the range + * @p [__first,__last). + */ + template + _GLIBCXX20_CONSTEXPR + void + generate(_ForwardIterator __first, _ForwardIterator __last, + _Generator __gen) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_GeneratorConcept<_Generator, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + *__first = __gen(); + } + + /** + * @brief Assign the result of a function object to each value in a + * sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __n The length of the sequence. + * @param __gen A function object taking no arguments and returning + * std::iterator_traits<_ForwardIterator>::value_type + * @return The end of the sequence, @p __first+__n + * + * Performs the assignment @c *i = @p __gen() for each @c i in the range + * @p [__first,__first+__n). + * + * If @p __n is negative, the function does nothing and returns @p __first. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 865. More algorithms that throw away information + // DR 426. search_n(), fill_n(), and generate_n() with negative n + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + generate_n(_OutputIterator __first, _Size __n, _Generator __gen) + { + // concept requirements + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _Generator" + __typeof__(__gen())>) + + typedef __decltype(std::__size_to_integer(__n)) _IntSize; + for (_IntSize __niter = std::__size_to_integer(__n); + __niter > 0; --__niter, (void) ++__first) + *__first = __gen(); + return __first; + } + + /** + * @brief Copy a sequence, removing consecutive duplicate values. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) to the range + * beginning at @p __result, except that only the first element is copied + * from groups of consecutive elements that compare equal. + * unique_copy() is stable, so the relative order of elements that are + * copied is unchanged. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 241. Does unique_copy() require CopyConstructible and Assignable? + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 538. 241 again: Does unique_copy() require CopyConstructible and + * Assignable? + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + return std::__unique_copy(__first, __last, __result, + __gnu_cxx::__ops::__iter_equal_to_iter(), + std::__iterator_category(__first), + std::__iterator_category(__result)); + } + + /** + * @brief Copy a sequence, removing consecutive values using a predicate. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __binary_pred A binary predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) to the range + * beginning at @p __result, except that only the first element is copied + * from groups of consecutive elements for which @p __binary_pred returns + * true. + * unique_copy() is stable, so the relative order of elements that are + * copied is unchanged. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 241. Does unique_copy() require CopyConstructible and Assignable? + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryPredicate __binary_pred) + { + // concept requirements -- predicates checked later + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + return std::__unique_copy(__first, __last, __result, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred), + std::__iterator_category(__first), + std::__iterator_category(__result)); + } + +#if _GLIBCXX_HOSTED + /** + * @brief Randomly shuffle the elements of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return Nothing. + * + * Reorder the elements in the range @p [__first,__last) using a random + * distribution, so that every possible ordering of the sequence is + * equally likely. + */ + template + inline void + random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first != __last) + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + // XXX rand() % N is not uniformly distributed + _RandomAccessIterator __j = __first + + std::rand() % ((__i - __first) + 1); + if (__i != __j) + std::iter_swap(__i, __j); + } + } +#endif + + /** + * @brief Shuffle the elements of a sequence using a random number + * generator. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __rand The RNG functor or function. + * @return Nothing. + * + * Reorders the elements in the range @p [__first,__last) using @p __rand to + * provide a random distribution. Calling @p __rand(N) for a positive + * integer @p N should return a randomly chosen integer from the + * range [0,N). + */ + template + void + random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, +#if __cplusplus >= 201103L + _RandomNumberGenerator&& __rand) +#else + _RandomNumberGenerator& __rand) +#endif + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return; + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + _RandomAccessIterator __j = __first + __rand((__i - __first) + 1); + if (__i != __j) + std::iter_swap(__i, __j); + } + } + + + /** + * @brief Move elements for which a predicate is true to the beginning + * of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate functor. + * @return An iterator @p middle such that @p __pred(i) is true for each + * iterator @p i in the range @p [__first,middle) and false for each @p i + * in the range @p [middle,__last). + * + * @p __pred must not modify its operand. @p partition() does not preserve + * the relative ordering of elements in each group, use + * @p stable_partition() if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__partition(__first, __last, __pred, + std::__iterator_category(__first)); + } + + + /** + * @brief Sort the smallest elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the smallest @p (__middle-__first) elements in the range + * @p [first,last) and moves them to the range @p [__first,__middle). The + * order of the remaining elements in the range @p [__middle,__last) is + * undefined. + * After the sort if @e i and @e j are iterators in the range + * @p [__first,__middle) such that i precedes j and @e k is an iterator in + * the range @p [__middle,__last) then *j<*i and *k<*i are both false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__partial_sort(__first, __middle, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the smallest elements of a sequence using a predicate + * for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the smallest @p (__middle-__first) elements in the range + * @p [__first,__last) and moves them to the range @p [__first,__middle). The + * order of the remaining elements in the range @p [__middle,__last) is + * undefined. + * After the sort if @e i and @e j are iterators in the range + * @p [__first,__middle) such that i precedes j and @e k is an iterator in + * the range @p [__middle,__last) then @p *__comp(j,*i) and @p __comp(*k,*i) + * are both false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__partial_sort(__first, __middle, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Sort a sequence just enough to find a particular position. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __nth Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Rearranges the elements in the range @p [__first,__last) so that @p *__nth + * is the same element that would have been in that position had the + * whole sequence been sorted. The elements either side of @p *__nth are + * not completely sorted, but for any iterator @e i in the range + * @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it + * holds that *j < *i is false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __nth); + __glibcxx_requires_valid_range(__nth, __last); + __glibcxx_requires_irreflexive(__first, __last); + + if (__first == __last || __nth == __last) + return; + + std::__introselect(__first, __nth, __last, + std::__lg(__last - __first) * 2, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort a sequence just enough to find a particular position + * using a predicate for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __nth Another iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Rearranges the elements in the range @p [__first,__last) so that @p *__nth + * is the same element that would have been in that position had the + * whole sequence been sorted. The elements either side of @p *__nth are + * not completely sorted, but for any iterator @e i in the range + * @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it + * holds that @p __comp(*j,*i) is false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __nth); + __glibcxx_requires_valid_range(__nth, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + if (__first == __last || __nth == __last) + return; + + std::__introselect(__first, __nth, __last, + std::__lg(__last - __first) * 2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Sort the elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that for each iterator @e i in the range @p [__first,__last-1), + * *(i+1)<*i is false. + * + * The relative ordering of equivalent elements is not preserved, use + * @p stable_sort() if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the elements of a sequence using a predicate for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that @p __comp(*(i+1),*i) is false for every iterator @e i in the + * range @p [__first,__last-1). + * + * The relative ordering of equivalent elements is not preserved, use + * @p stable_sort() if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + ++__result; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Merges two sorted ranges. + * @ingroup sorting_algorithms + * @param __first1 An iterator. + * @param __first2 Another iterator. + * @param __last1 Another iterator. + * @param __last2 Another iterator. + * @param __result An iterator pointing to the end of the merged range. + * @return An output iterator equal to @p __result + (__last1 - __first1) + * + (__last2 - __first2). + * + * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into + * the sorted range @p [__result, __result + (__last1-__first1) + + * (__last2-__first2)). Both input ranges must be sorted, and the + * output range must not overlap with either of the input ranges. + * The sort is @e stable, that is, for equivalent elements in the + * two ranges, elements from the first range will always come + * before elements from the second. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__merge(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Merges two sorted ranges. + * @ingroup sorting_algorithms + * @param __first1 An iterator. + * @param __first2 Another iterator. + * @param __last1 Another iterator. + * @param __last2 Another iterator. + * @param __result An iterator pointing to the end of the merged range. + * @param __comp A functor to use for comparisons. + * @return An output iterator equal to @p __result + (__last1 - __first1) + * + (__last2 - __first2). + * + * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into + * the sorted range @p [__result, __result + (__last1-__first1) + + * (__last2-__first2)). Both input ranges must be sorted, and the + * output range must not overlap with either of the input ranges. + * The sort is @e stable, that is, for equivalent elements in the + * two ranges, elements from the first range will always come + * before elements from the second. + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__merge(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + inline void + __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + typedef _Temporary_buffer<_RandomAccessIterator, _ValueType> _TmpBuf; + _TmpBuf __buf(__first, std::distance(__first, __last)); + + if (__buf.begin() == 0) + std::__inplace_stable_sort(__first, __last, __comp); + else + std::__stable_sort_adaptive(__first, __last, __buf.begin(), + _DistanceType(__buf.size()), __comp); + } + + /** + * @brief Sort the elements of a sequence, preserving the relative order + * of equivalent elements. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that for each iterator @p i in the range @p [__first,__last-1), + * @p *(i+1)<*i is false. + * + * The relative ordering of equivalent elements is preserved, so any two + * elements @p x and @p y in the range @p [__first,__last) such that + * @p x + inline void + stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + _GLIBCXX_STD_A::__stable_sort(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the elements of a sequence using a predicate for comparison, + * preserving the relative order of equivalent elements. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that for each iterator @p i in the range @p [__first,__last-1), + * @p __comp(*(i+1),*i) is false. + * + * The relative ordering of equivalent elements is preserved, so any two + * elements @p x and @p y in the range @p [__first,__last) such that + * @p __comp(x,y) is false and @p __comp(y,x) is false will have the same + * relative ordering after calling @p stable_sort(). + */ + template + inline void + stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + _GLIBCXX_STD_A::__stable_sort(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + } + else if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Return the union of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * each range in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other, + * that element is copied and the iterator advanced. If an element is + * contained in both ranges, the element from the first range is copied and + * both ranges advance. The output range may not overlap either input + * range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_union(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the union of two sorted ranges using a comparison functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * each range in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other + * according to @p __comp, that element is copied and the iterator advanced. + * If an equivalent element according to @p __comp is contained in both + * ranges, the element from the first range is copied and both ranges + * advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_union(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + ++__first1; + else if (__comp(__first2, __first1)) + ++__first2; + else + { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + return __result; + } + + /** + * @brief Return the intersection of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * both ranges in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other, + * that iterator advances. If an element is contained in both ranges, the + * element from the first range is copied and both ranges advance. The + * output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the intersection of two sorted ranges using comparison + * functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * both ranges in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other + * according to @p __comp, that iterator advances. If an element is + * contained in both ranges according to @p __comp, the element from the + * first range is copied and both ranges advance. The output range may not + * overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (__comp(__first2, __first1)) + ++__first2; + else + { + ++__first1; + ++__first2; + } + return std::copy(__first1, __last1, __result); + } + + /** + * @brief Return the difference of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * the first range but not the second in order to the output range. + * Iterators increment for each range. When the current element of the + * first range is less than the second, that element is copied and the + * iterator advances. If the current element of the second range is less, + * the iterator advances, but no element is copied. If an element is + * contained in both ranges, no elements are copied and both ranges + * advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the difference of two sorted ranges using comparison + * functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * the first range but not the second in order to the output range. + * Iterators increment for each range. When the current element of the + * first range is less than the second according to @p __comp, that element + * is copied and the iterator advances. If the current element of the + * second range is less, no element is copied and the iterator advances. + * If an element is contained in both ranges according to @p __comp, no + * elements are copied and both ranges advance. The output range may not + * overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_symmetric_difference(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + ++__result; + } + else + { + ++__first1; + ++__first2; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Return the symmetric difference of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * one range but not the other in order to the output range. Iterators + * increment for each range. When the current element of one range is less + * than the other, that element is copied and the iterator advances. If an + * element is contained in both ranges, no elements are copied and both + * ranges advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the symmetric difference of two sorted ranges using + * comparison functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * one range but not the other in order to the output range. Iterators + * increment for each range. When the current element of one range is less + * than the other according to @p comp, that element is copied and the + * iterator advances. If an element is contained in both ranges according + * to @p __comp, no elements are copied and both ranges advance. The output + * range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX14_CONSTEXPR + _ForwardIterator + __min_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) + return __first; + _ForwardIterator __result = __first; + while (++__first != __last) + if (__comp(__first, __result)) + __result = __first; + return __result; + } + + /** + * @brief Return the minimum element in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return Iterator referencing the first instance of the smallest value. + */ + template + _GLIBCXX14_CONSTEXPR + _ForwardIterator + inline min_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return _GLIBCXX_STD_A::__min_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the minimum element in a range using comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return Iterator referencing the first instance of the smallest value + * according to __comp. + */ + template + _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + min_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return _GLIBCXX_STD_A::__min_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX14_CONSTEXPR + _ForwardIterator + __max_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) return __first; + _ForwardIterator __result = __first; + while (++__first != __last) + if (__comp(__result, __first)) + __result = __first; + return __result; + } + + /** + * @brief Return the maximum element in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return Iterator referencing the first instance of the largest value. + */ + template + _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + max_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return _GLIBCXX_STD_A::__max_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the maximum element in a range using comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return Iterator referencing the first instance of the largest value + * according to __comp. + */ + template + _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + max_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return _GLIBCXX_STD_A::__max_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cplusplus >= 201402L + /// Reservoir sampling algorithm. + template + _RandomAccessIterator + __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag, + _RandomAccessIterator __out, random_access_iterator_tag, + _Size __n, _UniformRandomBitGenerator&& __g) + { + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + __distrib_type __d{}; + _Size __sample_sz = 0; + while (__first != __last && __sample_sz != __n) + { + __out[__sample_sz++] = *__first; + ++__first; + } + for (auto __pop_sz = __sample_sz; __first != __last; + ++__first, (void) ++__pop_sz) + { + const auto __k = __d(__g, __param_type{0, __pop_sz}); + if (__k < __n) + __out[__k] = *__first; + } + return __out + __sample_sz; + } + + /// Selection sampling algorithm. + template + _OutputIterator + __sample(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag, + _OutputIterator __out, _Cat, + _Size __n, _UniformRandomBitGenerator&& __g) + { + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + using _USize = make_unsigned_t<_Size>; + using _Gen = remove_reference_t<_UniformRandomBitGenerator>; + using __uc_type = common_type_t; + + if (__first == __last) + return __out; + + __distrib_type __d{}; + _Size __unsampled_sz = std::distance(__first, __last); + __n = std::min(__n, __unsampled_sz); + + // If possible, we use __gen_two_uniform_ints to efficiently produce + // two random numbers using a single distribution invocation: + + const __uc_type __urngrange = __g.max() - __g.min(); + if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz)) + // I.e. (__urngrange >= __unsampled_sz * __unsampled_sz) but without + // wrapping issues. + { + while (__n != 0 && __unsampled_sz >= 2) + { + const pair<_Size, _Size> __p = + __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g); + + --__unsampled_sz; + if (__p.first < __n) + { + *__out++ = *__first; + --__n; + } + + ++__first; + + if (__n == 0) break; + + --__unsampled_sz; + if (__p.second < __n) + { + *__out++ = *__first; + --__n; + } + + ++__first; + } + } + + // The loop above is otherwise equivalent to this one-at-a-time version: + + for (; __n != 0; ++__first) + if (__d(__g, __param_type{0, --__unsampled_sz}) < __n) + { + *__out++ = *__first; + --__n; + } + return __out; + } + +#if __cplusplus > 201402L +#define __cpp_lib_sample 201603 + /// Take a random sample from a population. + template + _SampleIterator + sample(_PopulationIterator __first, _PopulationIterator __last, + _SampleIterator __out, _Distance __n, + _UniformRandomBitGenerator&& __g) + { + using __pop_cat = typename + std::iterator_traits<_PopulationIterator>::iterator_category; + using __samp_cat = typename + std::iterator_traits<_SampleIterator>::iterator_category; + + static_assert( + __or_, + is_convertible<__samp_cat, random_access_iterator_tag>>::value, + "output range must use a RandomAccessIterator when input range" + " does not meet the ForwardIterator requirements"); + + static_assert(is_integral<_Distance>::value, + "sample size must be an integer type"); + + typename iterator_traits<_PopulationIterator>::difference_type __d = __n; + return _GLIBCXX_STD_A:: + __sample(__first, __last, __pop_cat{}, __out, __samp_cat{}, __d, + std::forward<_UniformRandomBitGenerator>(__g)); + } +#endif // C++17 +#endif // C++14 + +_GLIBCXX_END_NAMESPACE_ALGO +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_ALGO_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h b/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h new file mode 100644 index 000000000..dd2bd1727 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h @@ -0,0 +1,1959 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_algobase.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _STL_ALGOBASE_H +#define _STL_ALGOBASE_H 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // For std::swap +#include +#if __cplusplus >= 201103L +# include +#endif +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /* + * A constexpr wrapper for __builtin_memcmp. + * @param __num The number of elements of type _Tp (not bytes). + */ + template + _GLIBCXX14_CONSTEXPR + inline int + __memcmp(const _Tp* __first1, const _Up* __first2, size_t __num) + { +#if __cplusplus >= 201103L + static_assert(sizeof(_Tp) == sizeof(_Up), "can be compared with memcmp"); +#endif +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + for(; __num > 0; ++__first1, ++__first2, --__num) + if (*__first1 != *__first2) + return *__first1 < *__first2 ? -1 : 1; + return 0; + } + else +#endif + return __builtin_memcmp(__first1, __first2, sizeof(_Tp) * __num); + } + +#if __cplusplus < 201103L + // See http://gcc.gnu.org/ml/libstdc++/2004-08/msg00167.html: in a + // nutshell, we are partially implementing the resolution of DR 187, + // when it's safe, i.e., the value_types are equal. + template + struct __iter_swap + { + template + static void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + typedef typename iterator_traits<_ForwardIterator1>::value_type + _ValueType1; + _ValueType1 __tmp = *__a; + *__a = *__b; + *__b = __tmp; + } + }; + + template<> + struct __iter_swap + { + template + static void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + swap(*__a, *__b); + } + }; +#endif // C++03 + + /** + * @brief Swaps the contents of two iterators. + * @ingroup mutating_algorithms + * @param __a An iterator. + * @param __b Another iterator. + * @return Nothing. + * + * This function swaps the values pointed to by two iterators, not the + * iterators themselves. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator1>) + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator2>) + +#if __cplusplus < 201103L + typedef typename iterator_traits<_ForwardIterator1>::value_type + _ValueType1; + typedef typename iterator_traits<_ForwardIterator2>::value_type + _ValueType2; + + __glibcxx_function_requires(_ConvertibleConcept<_ValueType1, + _ValueType2>) + __glibcxx_function_requires(_ConvertibleConcept<_ValueType2, + _ValueType1>) + + typedef typename iterator_traits<_ForwardIterator1>::reference + _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator2>::reference + _ReferenceType2; + std::__iter_swap<__are_same<_ValueType1, _ValueType2>::__value + && __are_same<_ValueType1&, _ReferenceType1>::__value + && __are_same<_ValueType2&, _ReferenceType2>::__value>:: + iter_swap(__a, __b); +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 187. iter_swap underspecified + swap(*__a, *__b); +#endif + } + + /** + * @brief Swap the elements of two sequences. + * @ingroup mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @return An iterator equal to @p first2+(last1-first1). + * + * Swaps each element in the range @p [first1,last1) with the + * corresponding element in the range @p [first2,(last1-first1)). + * The ranges must not overlap. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator2 + swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator1>) + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + std::iter_swap(__first1, __first2); + return __first2; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return The lesser of the parameters. + * + * This is the simple classic generic implementation. It will work on + * temporary expressions, since they are only evaluated once, unlike a + * preprocessor macro. + */ + template + _GLIBCXX14_CONSTEXPR + inline const _Tp& + min(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + //return __b < __a ? __b : __a; + if (__b < __a) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return The greater of the parameters. + * + * This is the simple classic generic implementation. It will work on + * temporary expressions, since they are only evaluated once, unlike a + * preprocessor macro. + */ + template + _GLIBCXX14_CONSTEXPR + inline const _Tp& + max(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + //return __a < __b ? __b : __a; + if (__a < __b) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The lesser of the parameters. + * + * This will work on temporary expressions, since they are only evaluated + * once, unlike a preprocessor macro. + */ + template + _GLIBCXX14_CONSTEXPR + inline const _Tp& + min(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + //return __comp(__b, __a) ? __b : __a; + if (__comp(__b, __a)) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The greater of the parameters. + * + * This will work on temporary expressions, since they are only evaluated + * once, unlike a preprocessor macro. + */ + template + _GLIBCXX14_CONSTEXPR + inline const _Tp& + max(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + //return __comp(__a, __b) ? __b : __a; + if (__comp(__a, __b)) + return __b; + return __a; + } + + // Fallback implementation of the function in bits/stl_iterator.h used to + // remove the __normal_iterator wrapper. See copy, fill, ... + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __niter_base(_Iterator __it) + _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) + { return __it; } + + // Reverse the __niter_base transformation to get a + // __normal_iterator back again (this assumes that __normal_iterator + // is only used to wrap random access iterators, like pointers). + template + _GLIBCXX20_CONSTEXPR + inline _From + __niter_wrap(_From __from, _To __res) + { return __from + (__res - std::__niter_base(__from)); } + + // No need to wrap, iterator already has the right type. + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __niter_wrap(const _Iterator&, _Iterator __res) + { return __res; } + + // All of these auxiliary structs serve two purposes. (1) Replace + // calls to copy with memmove whenever possible. (Memmove, not memcpy, + // because the input and output ranges are permitted to overlap.) + // (2) If we're using random access iterators, then write the loop as + // a for loop with an explicit count. + + template + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + for (; __first != __last; ++__result, (void)++__first) + *__result = *__first; + return __result; + } + }; + +#if __cplusplus >= 201103L + template + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + for (; __first != __last; ++__result, (void)++__first) + *__result = std::move(*__first); + return __result; + } + }; +#endif + + template<> + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::difference_type _Distance; + for(_Distance __n = __last - __first; __n > 0; --__n) + { + *__result = *__first; + ++__first; + ++__result; + } + return __result; + } + }; + +#if __cplusplus >= 201103L + template<> + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::difference_type _Distance; + for(_Distance __n = __last - __first; __n > 0; --__n) + { + *__result = std::move(*__first); + ++__first; + ++__result; + } + return __result; + } + }; +#endif + + template + struct __copy_move<_IsMove, true, random_access_iterator_tag> + { + template + _GLIBCXX20_CONSTEXPR + static _Tp* + __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) + { +#if __cplusplus >= 201103L + using __assignable = conditional<_IsMove, + is_move_assignable<_Tp>, + is_copy_assignable<_Tp>>; + // trivial types can have deleted assignment + static_assert( __assignable::type::value, "type is not assignable" ); +#endif + const ptrdiff_t _Num = __last - __first; + if (_Num) + __builtin_memmove(__result, __first, sizeof(_Tp) * _Num); + return __result + _Num; + } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a2(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::iterator_category _Category; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__copy_move<_IsMove, false, _Category>:: + __copy_m(__first, __last, __result); +#endif + return std::__copy_move<_IsMove, __memcpyable<_OI, _II>::__value, + _Category>::__copy_m(__first, __last, __result); + } + +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + struct _Deque_iterator; + +_GLIBCXX_END_NAMESPACE_CONTAINER + + template + _OI + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _OI); + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_a1(_II, _II, _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a1(_II __first, _II __last, _OI __result) + { return std::__copy_move_a2<_IsMove>(__first, __last, __result); } + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a(_II __first, _II __last, _OI __result) + { + return std::__niter_wrap(__result, + std::__copy_move_a1<_IsMove>(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result))); + } + + /** + * @brief Copies the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return result + (last - first) + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). Result may not be contained within + * [first,last); the copy_backward function should be used instead. + * + * Note that the end of the output range is permitted to be contained + * within [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OI + copy(_II __first, _II __last, _OI __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II>) + __glibcxx_function_requires(_OutputIteratorConcept<_OI, + typename iterator_traits<_II>::value_type>) + __glibcxx_requires_can_increment_range(__first, __last, __result); + + return std::__copy_move_a<__is_move_iterator<_II>::__value> + (std::__miter_base(__first), std::__miter_base(__last), __result); + } + +#if __cplusplus >= 201103L + /** + * @brief Moves the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return result + (last - first) + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). Result may not be contained within + * [first,last); the move_backward function should be used instead. + * + * Note that the end of the output range is permitted to be contained + * within [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OI + move(_II __first, _II __last, _OI __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II>) + __glibcxx_function_requires(_OutputIteratorConcept<_OI, + typename iterator_traits<_II>::value_type>) + __glibcxx_requires_can_increment_range(__first, __last, __result); + + return std::__copy_move_a(std::__miter_base(__first), + std::__miter_base(__last), __result); + } + +#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::move(_Tp, _Up, _Vp) +#else +#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::copy(_Tp, _Up, _Vp) +#endif + + template + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + while (__first != __last) + *--__result = *--__last; + return __result; + } + }; + +#if __cplusplus >= 201103L + template + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + while (__first != __last) + *--__result = std::move(*--__last); + return __result; + } + }; +#endif + + template<> + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + typename iterator_traits<_BI1>::difference_type + __n = __last - __first; + for (; __n > 0; --__n) + *--__result = *--__last; + return __result; + } + }; + +#if __cplusplus >= 201103L + template<> + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + typename iterator_traits<_BI1>::difference_type + __n = __last - __first; + for (; __n > 0; --__n) + *--__result = std::move(*--__last); + return __result; + } + }; +#endif + + template + struct __copy_move_backward<_IsMove, true, random_access_iterator_tag> + { + template + _GLIBCXX20_CONSTEXPR + static _Tp* + __copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result) + { +#if __cplusplus >= 201103L + using __assignable = conditional<_IsMove, + is_move_assignable<_Tp>, + is_copy_assignable<_Tp>>; + // trivial types can have deleted assignment + static_assert( __assignable::type::value, "type is not assignable" ); +#endif + const ptrdiff_t _Num = __last - __first; + if (_Num) + __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num); + return __result - _Num; + } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + __copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result) + { + typedef typename iterator_traits<_BI1>::iterator_category _Category; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__copy_move_backward<_IsMove, false, _Category>:: + __copy_move_b(__first, __last, __result); +#endif + return std::__copy_move_backward<_IsMove, + __memcpyable<_BI2, _BI1>::__value, + _Category>::__copy_move_b(__first, + __last, + __result); + } + + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + __copy_move_backward_a1(_BI1 __first, _BI1 __last, _BI2 __result) + { return std::__copy_move_backward_a2<_IsMove>(__first, __last, __result); } + + template + _OI + __copy_move_backward_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _OI); + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_backward_a1( + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_backward_a1(_II, _II, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_backward_a(_II __first, _II __last, _OI __result) + { + return std::__niter_wrap(__result, + std::__copy_move_backward_a1<_IsMove> + (std::__niter_base(__first), std::__niter_base(__last), + std::__niter_base(__result))); + } + + /** + * @brief Copies the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result A bidirectional iterator. + * @return result - (last - first) + * + * The function has the same effect as copy, but starts at the end of the + * range and works its way to the start, returning the start of the result. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + * + * Result may not be in the range (first,last]. Use copy instead. Note + * that the start of the output range may overlap [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) + __glibcxx_function_requires(_ConvertibleConcept< + typename iterator_traits<_BI1>::value_type, + typename iterator_traits<_BI2>::value_type>) + __glibcxx_requires_can_decrement_range(__first, __last, __result); + + return std::__copy_move_backward_a<__is_move_iterator<_BI1>::__value> + (std::__miter_base(__first), std::__miter_base(__last), __result); + } + +#if __cplusplus >= 201103L + /** + * @brief Moves the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result A bidirectional iterator. + * @return result - (last - first) + * + * The function has the same effect as move, but starts at the end of the + * range and works its way to the start, returning the start of the result. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + * + * Result may not be in the range (first,last]. Use move instead. Note + * that the start of the output range may overlap [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + move_backward(_BI1 __first, _BI1 __last, _BI2 __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) + __glibcxx_function_requires(_ConvertibleConcept< + typename iterator_traits<_BI1>::value_type, + typename iterator_traits<_BI2>::value_type>) + __glibcxx_requires_can_decrement_range(__first, __last, __result); + + return std::__copy_move_backward_a(std::__miter_base(__first), + std::__miter_base(__last), + __result); + } + +#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::move_backward(_Tp, _Up, _Vp) +#else +#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::copy_backward(_Tp, _Up, _Vp) +#endif + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if::__value, void>::__type + __fill_a1(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + for (; __first != __last; ++__first) + *__first = __value; + } + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, void>::__type + __fill_a1(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + const _Tp __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + } + + // Specialization: for char types we can use memset. + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, void>::__type + __fill_a1(_Tp* __first, _Tp* __last, const _Tp& __c) + { + const _Tp __tmp = __c; +#if __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + for (; __first != __last; ++__first) + *__first = __tmp; + return; + } +#endif + if (const size_t __len = __last - __first) + __builtin_memset(__first, static_cast(__tmp), __len); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __fill_a1(::__gnu_cxx::__normal_iterator<_Ite, _Cont> __first, + ::__gnu_cxx::__normal_iterator<_Ite, _Cont> __last, + const _Tp& __value) + { std::__fill_a1(__first.base(), __last.base(), __value); } + + template + void + __fill_a1(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&, + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&, + const _VTp&); + + template + _GLIBCXX20_CONSTEXPR + inline void + __fill_a(_FIte __first, _FIte __last, const _Tp& __value) + { std::__fill_a1(__first, __last, __value); } + + /** + * @brief Fills the range [first,last) with copies of value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __value A reference-to-const of arbitrary type. + * @return Nothing. + * + * This function fills a range with copies of the same value. For char + * types filling contiguous areas of memory, this becomes an inline call + * to @c memset or @c wmemset. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_requires_valid_range(__first, __last); + + std::__fill_a(__first, __last, __value); + } + + // Used by fill_n, generate_n, etc. to convert _Size to an integral type: + inline _GLIBCXX_CONSTEXPR int + __size_to_integer(int __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned + __size_to_integer(unsigned __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long + __size_to_integer(long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned long + __size_to_integer(unsigned long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(long long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned long long + __size_to_integer(unsigned long long __n) { return __n; } + +#if defined(__GLIBCXX_TYPE_INT_N_0) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0 + __size_to_integer(__GLIBCXX_TYPE_INT_N_0 __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_0 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_0 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1 + __size_to_integer(__GLIBCXX_TYPE_INT_N_1 __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_1 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_1 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2 + __size_to_integer(__GLIBCXX_TYPE_INT_N_2 __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_2 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_2 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_3 + __size_to_integer(__GLIBCXX_TYPE_INT_N_3 __n) { return __n; } + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_3 __n) { return __n; } +#endif + + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(float __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(double __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(long double __n) { return __n; } +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(__float128 __n) { return __n; } +#endif + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if::__value, _OutputIterator>::__type + __fill_n_a1(_OutputIterator __first, _Size __n, const _Tp& __value) + { + for (; __n > 0; --__n, (void) ++__first) + *__first = __value; + return __first; + } + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, _OutputIterator>::__type + __fill_n_a1(_OutputIterator __first, _Size __n, const _Tp& __value) + { + const _Tp __tmp = __value; + for (; __n > 0; --__n, (void) ++__first) + *__first = __tmp; + return __first; + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::output_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + return __fill_n_a1(__first, __n, __value); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::input_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + return __fill_n_a1(__first, __n, __value); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::random_access_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + if (__n <= 0) + return __first; + + __glibcxx_requires_can_increment(__first, __n); + + std::__fill_a(__first, __first + __n, __value); + return __first + __n; + } + + /** + * @brief Fills the range [first,first+n) with copies of value. + * @ingroup mutating_algorithms + * @param __first An output iterator. + * @param __n The count of copies to perform. + * @param __value A reference-to-const of arbitrary type. + * @return The iterator at first+n. + * + * This function fills a range with copies of the same value. For char + * types filling contiguous areas of memory, this becomes an inline call + * to @c memset or @c wmemset. + * + * If @p __n is negative, the function does nothing. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 865. More algorithms that throw away information + // DR 426. search_n(), fill_n(), and generate_n() with negative n + template + _GLIBCXX20_CONSTEXPR + inline _OI + fill_n(_OI __first, _Size __n, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_OutputIteratorConcept<_OI, _Tp>) + + return std::__fill_n_a(__first, std::__size_to_integer(__n), __value, + std::__iterator_category(__first)); + } + + template + struct __equal + { + template + _GLIBCXX20_CONSTEXPR + static bool + equal(_II1 __first1, _II1 __last1, _II2 __first2) + { + for (; __first1 != __last1; ++__first1, (void) ++__first2) + if (!(*__first1 == *__first2)) + return false; + return true; + } + }; + + template<> + struct __equal + { + template + _GLIBCXX20_CONSTEXPR + static bool + equal(const _Tp* __first1, const _Tp* __last1, const _Tp* __first2) + { + if (const size_t __len = (__last1 - __first1)) + return !std::__memcmp(__first1, __first2, __len); + return true; + } + }; + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _II); + + template + bool + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_II, _II, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>); + + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal_aux1(_II1 __first1, _II1 __last1, _II2 __first2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + const bool __simple = ((__is_integer<_ValueType1>::__value + || __is_pointer<_ValueType1>::__value) + && __memcmpable<_II1, _II2>::__value); + return std::__equal<__simple>::equal(__first1, __last1, __first2); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2) + { + return std::__equal_aux1(std::__niter_base(__first1), + std::__niter_base(__last1), + std::__niter_base(__first2)); + } + + template + struct __lc_rai + { + template + _GLIBCXX20_CONSTEXPR + static _II1 + __newlast1(_II1, _II1 __last1, _II2, _II2) + { return __last1; } + + template + _GLIBCXX20_CONSTEXPR + static bool + __cnd2(_II __first, _II __last) + { return __first != __last; } + }; + + template<> + struct __lc_rai + { + template + _GLIBCXX20_CONSTEXPR + static _RAI1 + __newlast1(_RAI1 __first1, _RAI1 __last1, + _RAI2 __first2, _RAI2 __last2) + { + const typename iterator_traits<_RAI1>::difference_type + __diff1 = __last1 - __first1; + const typename iterator_traits<_RAI2>::difference_type + __diff2 = __last2 - __first2; + return __diff2 < __diff1 ? __first1 + __diff2 : __last1; + } + + template + static _GLIBCXX20_CONSTEXPR bool + __cnd2(_RAI, _RAI) + { return true; } + }; + + template + _GLIBCXX20_CONSTEXPR + bool + __lexicographical_compare_impl(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2, + _Compare __comp) + { + typedef typename iterator_traits<_II1>::iterator_category _Category1; + typedef typename iterator_traits<_II2>::iterator_category _Category2; + typedef std::__lc_rai<_Category1, _Category2> __rai_type; + + __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2); + for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2); + ++__first1, (void)++__first2) + { + if (__comp(__first1, __first2)) + return true; + if (__comp(__first2, __first1)) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + + template + struct __lexicographical_compare + { + template + _GLIBCXX20_CONSTEXPR + static bool + __lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + using __gnu_cxx::__ops::__iter_less_iter; + return std::__lexicographical_compare_impl(__first1, __last1, + __first2, __last2, + __iter_less_iter()); + } + }; + + template<> + struct __lexicographical_compare + { + template + _GLIBCXX20_CONSTEXPR + static bool + __lc(const _Tp* __first1, const _Tp* __last1, + const _Up* __first2, const _Up* __last2) + { + const size_t __len1 = __last1 - __first1; + const size_t __len2 = __last2 - __first2; + if (const size_t __len = std::min(__len1, __len2)) + if (int __result = std::__memcmp(__first1, __first2, __len)) + return __result < 0; + return __len1 < __len2; + } + }; + + template + _GLIBCXX20_CONSTEXPR + inline bool + __lexicographical_compare_aux(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; + const bool __simple = + (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value + && __is_pointer<_II1>::__value + && __is_pointer<_II2>::__value +#if __cplusplus > 201703L && __cpp_lib_concepts + // For C++20 iterator_traits::value_type is non-volatile + // so __is_byte could be true, but we can't use memcmp with + // volatile data. + && !is_volatile_v>> + && !is_volatile_v>> +#endif + ); + + return std::__lexicographical_compare<__simple>::__lc(__first1, __last1, + __first2, __last2); + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp(__middle, __val)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + /** + * @brief Finds the first position in which @a val could be inserted + * without changing the ordering. + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An iterator pointing to the first element not less + * than @a val, or end() if every element is less than + * @a val. + * @ingroup binary_search_algorithms + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + + return std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val()); + } + + /// This is a helper function for the sort routines and for random.tcc. + // Precondition: __n > 0. + inline _GLIBCXX_CONSTEXPR int + __lg(int __n) + { return (int)sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } + + inline _GLIBCXX_CONSTEXPR unsigned + __lg(unsigned __n) + { return (int)sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } + + inline _GLIBCXX_CONSTEXPR long + __lg(long __n) + { return (int)sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } + + inline _GLIBCXX_CONSTEXPR unsigned long + __lg(unsigned long __n) + { return (int)sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } + + inline _GLIBCXX_CONSTEXPR long long + __lg(long long __n) + { return (int)sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } + + inline _GLIBCXX_CONSTEXPR unsigned long long + __lg(unsigned long long __n) + { return (int)sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @return A boolean true or false. + * + * This compares the elements of two ranges using @c == and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + equal(_II1 __first1, _II1 __last1, _II2 __first2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_II1>::value_type, + typename iterator_traits<_II2>::value_type>) + __glibcxx_requires_can_increment_range(__first1, __last1, __first2); + + return std::__equal_aux(__first1, __last1, __first2); + } + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A boolean true or false. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + equal(_IIter1 __first1, _IIter1 __last1, + _IIter2 __first2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!bool(__binary_pred(*__first1, *__first2))) + return false; + return true; + } + +#if __cplusplus >= 201103L + // 4-iterator version of std::equal for use in C++11. + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + using _RATag = random_access_iterator_tag; + using _Cat1 = typename iterator_traits<_II1>::iterator_category; + using _Cat2 = typename iterator_traits<_II2>::iterator_category; + using _RAIters = __and_, is_same<_Cat2, _RATag>>; + if (_RAIters()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + return _GLIBCXX_STD_A::equal(__first1, __last1, __first2); + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(*__first1 == *__first2)) + return false; + return __first1 == __last1 && __first2 == __last2; + } + + // 4-iterator version of std::equal for use in C++11. + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2, + _BinaryPredicate __binary_pred) + { + using _RATag = random_access_iterator_tag; + using _Cat1 = typename iterator_traits<_II1>::iterator_category; + using _Cat2 = typename iterator_traits<_II2>::iterator_category; + using _RAIters = __and_, is_same<_Cat2, _RATag>>; + if (_RAIters()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + return _GLIBCXX_STD_A::equal(__first1, __last1, __first2, + __binary_pred); + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!bool(__binary_pred(*__first1, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } +#endif // C++11 + +#if __cplusplus > 201103L + +#define __cpp_lib_robust_nonmodifying_seq_ops 201304 + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A boolean true or false. + * + * This compares the elements of two ranges using @c == and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + equal(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_II1>::value_type, + typename iterator_traits<_II2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2); + } + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A boolean true or false. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + equal(_IIter1 __first1, _IIter1 __last1, + _IIter2 __first2, _IIter2 __last2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2, + __binary_pred); + } +#endif // C++14 + + /** + * @brief Performs @b dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A boolean true or false. + * + * Returns true if the sequence of elements defined by the range + * [first1,last1) is lexicographically less than the sequence of elements + * defined by the range [first2,last2). Returns false otherwise. + * (Quoted from [25.3.8]/1.) If the iterators are all character pointers, + * then this is an inline call to @c memcmp. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + lexicographical_compare(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; +#endif + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>) + __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__lexicographical_compare_aux(std::__niter_base(__first1), + std::__niter_base(__last1), + std::__niter_base(__first2), + std::__niter_base(__last2)); + } + + /** + * @brief Performs @b dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return A boolean true or false. + * + * The same as the four-parameter @c lexicographical_compare, but uses the + * comp parameter instead of @c <. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + lexicographical_compare(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__lexicographical_compare_impl + (__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cpp_lib_three_way_comparison + // Iter points to a contiguous range of unsigned narrow character type + // or std::byte, suitable for comparison by memcmp. + template + concept __is_byte_iter = contiguous_iterator<_Iter> + && __is_memcmp_ordered>::__value; + + // Return a struct with two members, initialized to the smaller of x and y + // (or x if they compare equal) and the result of the comparison x <=> y. + template + constexpr auto + __min_cmp(_Tp __x, _Tp __y) + { + struct _Res { + _Tp _M_min; + decltype(__x <=> __y) _M_cmp; + }; + auto __c = __x <=> __y; + if (__c > 0) + return _Res{__y, __c}; + return _Res{__x, __c}; + } + + /** + * @brief Performs dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The comparison category that `__comp(*__first1, *__first2)` + * returns. + */ + template + constexpr auto + lexicographical_compare_three_way(_InputIter1 __first1, + _InputIter1 __last1, + _InputIter2 __first2, + _InputIter2 __last2, + _Comp __comp) + -> decltype(__comp(*__first1, *__first2)) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + +#if __cpp_lib_is_constant_evaluated + using _Cat = decltype(__comp(*__first1, *__first2)); + static_assert(same_as, _Cat>); + + if (!std::is_constant_evaluated()) + if constexpr (same_as<_Comp, __detail::_Synth3way> + || same_as<_Comp, compare_three_way>) + if constexpr (__is_byte_iter<_InputIter1>) + if constexpr (__is_byte_iter<_InputIter2>) + { + const auto [__len, __lencmp] + = std::__min_cmp(__last1 - __first1, __last2 - __first2); + if (__len) + { + const auto __c + = __builtin_memcmp(&*__first1, &*__first2, __len) <=> 0; + if (__c != 0) + return __c; + } + return __lencmp; + } +#endif // is_constant_evaluated + while (__first1 != __last1) + { + if (__first2 == __last2) + return strong_ordering::greater; + if (auto __cmp = __comp(*__first1, *__first2); __cmp != 0) + return __cmp; + ++__first1; + ++__first2; + } + return (__first2 == __last2) <=> true; // See PR 94006 + } + + template + constexpr auto + lexicographical_compare_three_way(_InputIter1 __first1, + _InputIter1 __last1, + _InputIter2 __first2, + _InputIter2 __last2) + { + return std::lexicographical_compare_three_way(__first1, __last1, + __first2, __last2, + compare_three_way{}); + } +#endif // three_way_comparison + + template + _GLIBCXX20_CONSTEXPR + pair<_InputIterator1, _InputIterator2> + __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _BinaryPredicate __binary_pred) + { + while (__first1 != __last1 && __binary_pred(__first1, __first2)) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using @c == and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + +#if __cplusplus > 201103L + + template + _GLIBCXX20_CONSTEXPR + pair<_InputIterator1, _InputIterator2> + __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __binary_pred) + { + while (__first1 != __last1 && __first2 != __last2 + && __binary_pred(__first1, __first2)) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using @c == and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } +#endif + +_GLIBCXX_END_NAMESPACE_ALGO + + /// This is an overload used by find algos for the Input Iterator case. + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + __find_if(_InputIterator __first, _InputIterator __last, + _Predicate __pred, input_iterator_tag) + { + while (__first != __last && !__pred(__first)) + ++__first; + return __first; + } + + /// This is an overload used by find algos for the RAI case. + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __find_if(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Predicate __pred, random_access_iterator_tag) + { + typename iterator_traits<_RandomAccessIterator>::difference_type + __trip_count = (__last - __first) >> 2; + + for (; __trip_count > 0; --__trip_count) + { + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + } + + switch (__last - __first) + { + case 3: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 2: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 1: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 0: + default: + return __last; + } + } + + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __find_if(_Iterator __first, _Iterator __last, _Predicate __pred) + { + return __find_if(__first, __last, __pred, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { + typename iterator_traits<_InputIterator>::difference_type __n = 0; + for (; __first != __last; ++__first) + if (__pred(__first)) + ++__n; + return __n; + } + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _BinaryPredicate __pred) + { + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!__pred(__first1, __first2)) + break; + + if (__first1 == __last1) + return true; + + // Establish __last2 assuming equal ranges by iterating over the + // rest of the list. + _ForwardIterator2 __last2 = __first2; + std::advance(__last2, std::distance(__first1, __last1)); + for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) + { + if (__scan != std::__find_if(__first1, __scan, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) + continue; // We've seen this one before. + + auto __matches + = std::__count_if(__first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); + if (0 == __matches || + std::__count_if(__scan, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) + != __matches) + return false; + } + return true; + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @return true if there exists a permutation of the elements in the range + * [__first2, __first2 + (__last1 - __first1)), beginning with + * ForwardIterator2 begin, such that equal(__first1, __last1, begin) + * returns true; otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return std::__is_permutation(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h b/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h new file mode 100644 index 000000000..f245e52b2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h @@ -0,0 +1,1363 @@ +// vector specialization -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1999 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_bvector.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{vector} + */ + +#ifndef _STL_BVECTOR_H +#define _STL_BVECTOR_H 1 + +#if __cplusplus >= 201103L +#include +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + typedef unsigned long _Bit_type; + enum { _S_word_bit = int(__CHAR_BIT__ * sizeof(_Bit_type)) }; + + struct _Bit_reference + { + _Bit_type * _M_p; + _Bit_type _M_mask; + + _Bit_reference(_Bit_type * __x, _Bit_type __y) + : _M_p(__x), _M_mask(__y) { } + + _Bit_reference() _GLIBCXX_NOEXCEPT : _M_p(0), _M_mask(0) { } + +#if __cplusplus >= 201103L + _Bit_reference(const _Bit_reference&) = default; +#endif + + operator bool() const _GLIBCXX_NOEXCEPT + { return !!(*_M_p & _M_mask); } + + _Bit_reference& + operator=(bool __x) _GLIBCXX_NOEXCEPT + { + if (__x) + *_M_p |= _M_mask; + else + *_M_p &= ~_M_mask; + return *this; + } + + _Bit_reference& + operator=(const _Bit_reference& __x) _GLIBCXX_NOEXCEPT + { return *this = bool(__x); } + + bool + operator==(const _Bit_reference& __x) const + { return bool(*this) == bool(__x); } + + bool + operator<(const _Bit_reference& __x) const + { return !bool(*this) && bool(__x); } + + void + flip() _GLIBCXX_NOEXCEPT + { *_M_p ^= _M_mask; } + }; + +#if __cplusplus >= 201103L + inline void + swap(_Bit_reference __x, _Bit_reference __y) noexcept + { + bool __tmp = __x; + __x = __y; + __y = __tmp; + } + + inline void + swap(_Bit_reference __x, bool& __y) noexcept + { + bool __tmp = __x; + __x = __y; + __y = __tmp; + } + + inline void + swap(bool& __x, _Bit_reference __y) noexcept + { + bool __tmp = __x; + __x = __y; + __y = __tmp; + } +#endif + + struct _Bit_iterator_base + : public std::iterator + { + _Bit_type * _M_p; + unsigned int _M_offset; + + _Bit_iterator_base(_Bit_type * __x, unsigned int __y) + : _M_p(__x), _M_offset(__y) { } + + void + _M_bump_up() + { + if (_M_offset++ == int(_S_word_bit) - 1) + { + _M_offset = 0; + ++_M_p; + } + } + + void + _M_bump_down() + { + if (_M_offset-- == 0) + { + _M_offset = int(_S_word_bit) - 1; + --_M_p; + } + } + + void + _M_incr(ptrdiff_t __i) + { + difference_type __n = __i + _M_offset; + _M_p += __n / int(_S_word_bit); + __n = __n % int(_S_word_bit); + if (__n < 0) + { + __n += int(_S_word_bit); + --_M_p; + } + _M_offset = static_cast(__n); + } + + friend _GLIBCXX20_CONSTEXPR bool + operator==(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return __x._M_p == __y._M_p && __x._M_offset == __y._M_offset; } + +#if __cpp_lib_three_way_comparison + friend constexpr strong_ordering + operator<=>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + noexcept + { + if (const auto __cmp = __x._M_p <=> __y._M_p; __cmp != 0) + return __cmp; + return __x._M_offset <=> __y._M_offset; + } +#else + friend bool + operator<(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { + return __x._M_p < __y._M_p + || (__x._M_p == __y._M_p && __x._M_offset < __y._M_offset); + } + + friend bool + operator!=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return !(__x == __y); } + + friend bool + operator>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return __y < __x; } + + friend bool + operator<=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return !(__y < __x); } + + friend bool + operator>=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return !(__x < __y); } +#endif // three-way comparison + + friend ptrdiff_t + operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { + return (int(_S_word_bit) * (__x._M_p - __y._M_p) + + __x._M_offset - __y._M_offset); + } + }; + + struct _Bit_iterator : public _Bit_iterator_base + { + typedef _Bit_reference reference; +#if __cplusplus > 201703L + typedef void pointer; +#else + typedef _Bit_reference* pointer; +#endif + typedef _Bit_iterator iterator; + + _Bit_iterator() : _Bit_iterator_base(0, 0) { } + + _Bit_iterator(_Bit_type * __x, unsigned int __y) + : _Bit_iterator_base(__x, __y) { } + + iterator + _M_const_cast() const + { return *this; } + + reference + operator*() const + { return reference(_M_p, 1UL << _M_offset); } + + iterator& + operator++() + { + _M_bump_up(); + return *this; + } + + iterator + operator++(int) + { + iterator __tmp = *this; + _M_bump_up(); + return __tmp; + } + + iterator& + operator--() + { + _M_bump_down(); + return *this; + } + + iterator + operator--(int) + { + iterator __tmp = *this; + _M_bump_down(); + return __tmp; + } + + iterator& + operator+=(difference_type __i) + { + _M_incr(__i); + return *this; + } + + iterator& + operator-=(difference_type __i) + { + *this += -__i; + return *this; + } + + reference + operator[](difference_type __i) const + { return *(*this + __i); } + + friend iterator + operator+(const iterator& __x, difference_type __n) + { + iterator __tmp = __x; + __tmp += __n; + return __tmp; + } + + friend iterator + operator+(difference_type __n, const iterator& __x) + { return __x + __n; } + + friend iterator + operator-(const iterator& __x, difference_type __n) + { + iterator __tmp = __x; + __tmp -= __n; + return __tmp; + } + }; + + struct _Bit_const_iterator : public _Bit_iterator_base + { + typedef bool reference; + typedef bool const_reference; +#if __cplusplus > 201703L + typedef void pointer; +#else + typedef const bool* pointer; +#endif + typedef _Bit_const_iterator const_iterator; + + _Bit_const_iterator() : _Bit_iterator_base(0, 0) { } + + _Bit_const_iterator(_Bit_type * __x, unsigned int __y) + : _Bit_iterator_base(__x, __y) { } + + _Bit_const_iterator(const _Bit_iterator& __x) + : _Bit_iterator_base(__x._M_p, __x._M_offset) { } + + _Bit_iterator + _M_const_cast() const + { return _Bit_iterator(_M_p, _M_offset); } + + const_reference + operator*() const + { return _Bit_reference(_M_p, 1UL << _M_offset); } + + const_iterator& + operator++() + { + _M_bump_up(); + return *this; + } + + const_iterator + operator++(int) + { + const_iterator __tmp = *this; + _M_bump_up(); + return __tmp; + } + + const_iterator& + operator--() + { + _M_bump_down(); + return *this; + } + + const_iterator + operator--(int) + { + const_iterator __tmp = *this; + _M_bump_down(); + return __tmp; + } + + const_iterator& + operator+=(difference_type __i) + { + _M_incr(__i); + return *this; + } + + const_iterator& + operator-=(difference_type __i) + { + *this += -__i; + return *this; + } + + const_reference + operator[](difference_type __i) const + { return *(*this + __i); } + + friend const_iterator + operator+(const const_iterator& __x, difference_type __n) + { + const_iterator __tmp = __x; + __tmp += __n; + return __tmp; + } + + friend const_iterator + operator-(const const_iterator& __x, difference_type __n) + { + const_iterator __tmp = __x; + __tmp -= __n; + return __tmp; + } + + friend const_iterator + operator+(difference_type __n, const const_iterator& __x) + { return __x + __n; } + }; + + inline void + __fill_bvector(_Bit_type * __v, + unsigned int __first, unsigned int __last, bool __x) + { + const _Bit_type __fmask = ~0ul << __first; + const _Bit_type __lmask = ~0ul >> (_S_word_bit - __last); + const _Bit_type __mask = __fmask & __lmask; + + if (__x) + *__v |= __mask; + else + *__v &= ~__mask; + } + + inline void + fill(_Bit_iterator __first, _Bit_iterator __last, const bool& __x) + { + if (__first._M_p != __last._M_p) + { + _Bit_type* __first_p = __first._M_p; + if (__first._M_offset != 0) + __fill_bvector(__first_p++, __first._M_offset, _S_word_bit, __x); + + __builtin_memset(__first_p, __x ? ~0 : 0, + (__last._M_p - __first_p) * sizeof(_Bit_type)); + + if (__last._M_offset != 0) + __fill_bvector(__last._M_p, 0, __last._M_offset, __x); + } + else if (__first._M_offset != __last._M_offset) + __fill_bvector(__first._M_p, __first._M_offset, __last._M_offset, __x); + } + + template + struct _Bvector_base + { + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Bit_type>::other _Bit_alloc_type; + typedef typename __gnu_cxx::__alloc_traits<_Bit_alloc_type> + _Bit_alloc_traits; + typedef typename _Bit_alloc_traits::pointer _Bit_pointer; + + struct _Bvector_impl_data + { + _Bit_iterator _M_start; + _Bit_iterator _M_finish; + _Bit_pointer _M_end_of_storage; + + _Bvector_impl_data() _GLIBCXX_NOEXCEPT + : _M_start(), _M_finish(), _M_end_of_storage() + { } + +#if __cplusplus >= 201103L + _Bvector_impl_data(_Bvector_impl_data&& __x) noexcept + : _M_start(__x._M_start), _M_finish(__x._M_finish) + , _M_end_of_storage(__x._M_end_of_storage) + { __x._M_reset(); } + + void + _M_move_data(_Bvector_impl_data&& __x) noexcept + { + this->_M_start = __x._M_start; + this->_M_finish = __x._M_finish; + this->_M_end_of_storage = __x._M_end_of_storage; + __x._M_reset(); + } +#endif + + void + _M_reset() _GLIBCXX_NOEXCEPT + { + _M_start = _M_finish = _Bit_iterator(); + _M_end_of_storage = _Bit_pointer(); + } + }; + + struct _Bvector_impl + : public _Bit_alloc_type, public _Bvector_impl_data + { + public: + _Bvector_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Bit_alloc_type>::value) + : _Bit_alloc_type() + { } + + _Bvector_impl(const _Bit_alloc_type& __a) _GLIBCXX_NOEXCEPT + : _Bit_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + _Bvector_impl(_Bvector_impl&&) = default; +#endif + + _Bit_type* + _M_end_addr() const _GLIBCXX_NOEXCEPT + { + if (this->_M_end_of_storage) + return std::__addressof(this->_M_end_of_storage[-1]) + 1; + return 0; + } + }; + + public: + typedef _Alloc allocator_type; + + _Bit_alloc_type& + _M_get_Bit_allocator() _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + const _Bit_alloc_type& + _M_get_Bit_allocator() const _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_get_Bit_allocator()); } + +#if __cplusplus >= 201103L + _Bvector_base() = default; +#else + _Bvector_base() { } +#endif + + _Bvector_base(const allocator_type& __a) + : _M_impl(__a) { } + +#if __cplusplus >= 201103L + _Bvector_base(_Bvector_base&&) = default; +#endif + + ~_Bvector_base() + { this->_M_deallocate(); } + + protected: + _Bvector_impl _M_impl; + + _Bit_pointer + _M_allocate(size_t __n) + { return _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n)); } + + void + _M_deallocate() + { + if (_M_impl._M_start._M_p) + { + const size_t __n = _M_impl._M_end_addr() - _M_impl._M_start._M_p; + _Bit_alloc_traits::deallocate(_M_impl, + _M_impl._M_end_of_storage - __n, + __n); + _M_impl._M_reset(); + } + } + +#if __cplusplus >= 201103L + void + _M_move_data(_Bvector_base&& __x) noexcept + { _M_impl._M_move_data(std::move(__x._M_impl)); } +#endif + + static size_t + _S_nword(size_t __n) + { return (__n + int(_S_word_bit) - 1) / int(_S_word_bit); } + }; + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +// Declare a partial specialization of vector. +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * @brief A specialization of vector for booleans which offers fixed time + * access to individual elements in any order. + * + * @ingroup sequences + * + * @tparam _Alloc Allocator type. + * + * Note that vector does not actually meet the requirements for being + * a container. This is because the reference and pointer types are not + * really references and pointers to bool. See DR96 for details. @see + * vector for function documentation. + * + * In some terminology a %vector can be described as a dynamic + * C-style array, it offers fast and efficient access to individual + * elements in any order and saves the user from worrying about + * memory and size allocation. Subscripting ( @c [] ) access is + * also provided as with C-style arrays. + */ + template + class vector : protected _Bvector_base<_Alloc> + { + typedef _Bvector_base<_Alloc> _Base; + typedef typename _Base::_Bit_pointer _Bit_pointer; + typedef typename _Base::_Bit_alloc_traits _Bit_alloc_traits; + +#if __cplusplus >= 201103L + friend struct std::hash; +#endif + + public: + typedef bool value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Bit_reference reference; + typedef bool const_reference; + typedef _Bit_reference* pointer; + typedef const bool* const_pointer; + typedef _Bit_iterator iterator; + typedef _Bit_const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef _Alloc allocator_type; + + allocator_type + get_allocator() const + { return _Base::get_allocator(); } + + protected: + using _Base::_M_allocate; + using _Base::_M_deallocate; + using _Base::_S_nword; + using _Base::_M_get_Bit_allocator; + + public: +#if __cplusplus >= 201103L + vector() = default; +#else + vector() { } +#endif + + explicit + vector(const allocator_type& __a) + : _Base(__a) { } + +#if __cplusplus >= 201103L + explicit + vector(size_type __n, const allocator_type& __a = allocator_type()) + : vector(__n, false, __a) + { } + + vector(size_type __n, const bool& __value, + const allocator_type& __a = allocator_type()) +#else + explicit + vector(size_type __n, const bool& __value = bool(), + const allocator_type& __a = allocator_type()) +#endif + : _Base(__a) + { + _M_initialize(__n); + _M_initialize_value(__value); + } + + vector(const vector& __x) + : _Base(_Bit_alloc_traits::_S_select_on_copy(__x._M_get_Bit_allocator())) + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); + } + +#if __cplusplus >= 201103L + vector(vector&&) = default; + + vector(vector&& __x, const allocator_type& __a) + noexcept(_Bit_alloc_traits::_S_always_equal()) + : _Base(__a) + { + if (__x.get_allocator() == __a) + this->_M_move_data(std::move(__x)); + else + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), begin()); + __x.clear(); + } + } + + vector(const vector& __x, const allocator_type& __a) + : _Base(__a) + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); + } + + vector(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_initialize_range(__l.begin(), __l.end(), + random_access_iterator_tag()); + } +#endif + +#if __cplusplus >= 201103L + template> + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { _M_initialize_dispatch(__first, __last, __false_type()); } +#else + template + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } +#endif + + ~vector() _GLIBCXX_NOEXCEPT { } + + vector& + operator=(const vector& __x) + { + if (&__x == this) + return *this; +#if __cplusplus >= 201103L + if (_Bit_alloc_traits::_S_propagate_on_copy_assign()) + { + if (this->_M_get_Bit_allocator() != __x._M_get_Bit_allocator()) + { + this->_M_deallocate(); + std::__alloc_on_copy(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + _M_initialize(__x.size()); + } + else + std::__alloc_on_copy(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } +#endif + if (__x.size() > capacity()) + { + this->_M_deallocate(); + _M_initialize(__x.size()); + } + this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(), + begin()); + return *this; + } + +#if __cplusplus >= 201103L + vector& + operator=(vector&& __x) noexcept(_Bit_alloc_traits::_S_nothrow_move()) + { + if (_Bit_alloc_traits::_S_propagate_on_move_assign() + || this->_M_get_Bit_allocator() == __x._M_get_Bit_allocator()) + { + this->_M_deallocate(); + this->_M_move_data(std::move(__x)); + std::__alloc_on_move(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } + else + { + if (__x.size() > capacity()) + { + this->_M_deallocate(); + _M_initialize(__x.size()); + } + this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(), + begin()); + __x.clear(); + } + return *this; + } + + vector& + operator=(initializer_list __l) + { + this->assign (__l.begin(), __l.end()); + return *this; + } +#endif + + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + void + assign(size_type __n, const bool& __x) + { _M_fill_assign(__n, __x); } + +#if __cplusplus >= 201103L + template> + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#else + template + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + void + assign(initializer_list __l) + { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); } +#endif + + iterator + begin() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_start._M_p, 0); } + + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_start._M_p, 0); } + + iterator + end() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish; } + + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish; } + + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(begin()); } + +#if __cplusplus >= 201103L + const_iterator + cbegin() const noexcept + { return const_iterator(this->_M_impl._M_start._M_p, 0); } + + const_iterator + cend() const noexcept + { return this->_M_impl._M_finish; } + + const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } +#endif + + size_type + size() const _GLIBCXX_NOEXCEPT + { return size_type(end() - begin()); } + + size_type + max_size() const _GLIBCXX_NOEXCEPT + { + const size_type __isize = + __gnu_cxx::__numeric_traits::__max + - int(_S_word_bit) + 1; + const size_type __asize + = _Bit_alloc_traits::max_size(_M_get_Bit_allocator()); + return (__asize <= __isize / int(_S_word_bit) + ? __asize * int(_S_word_bit) : __isize); + } + + size_type + capacity() const _GLIBCXX_NOEXCEPT + { return size_type(const_iterator(this->_M_impl._M_end_addr(), 0) + - begin()); } + + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return begin() == end(); } + + reference + operator[](size_type __n) + { + return *iterator(this->_M_impl._M_start._M_p + + __n / int(_S_word_bit), __n % int(_S_word_bit)); + } + + const_reference + operator[](size_type __n) const + { + return *const_iterator(this->_M_impl._M_start._M_p + + __n / int(_S_word_bit), __n % int(_S_word_bit)); + } + + protected: + void + _M_range_check(size_type __n) const + { + if (__n >= this->size()) + __throw_out_of_range_fmt(__N("vector::_M_range_check: __n " + "(which is %zu) >= this->size() " + "(which is %zu)"), + __n, this->size()); + } + + public: + reference + at(size_type __n) + { _M_range_check(__n); return (*this)[__n]; } + + const_reference + at(size_type __n) const + { _M_range_check(__n); return (*this)[__n]; } + + void + reserve(size_type __n) + { + if (__n > max_size()) + __throw_length_error(__N("vector::reserve")); + if (capacity() < __n) + _M_reallocate(__n); + } + + reference + front() + { return *begin(); } + + const_reference + front() const + { return *begin(); } + + reference + back() + { return *(end() - 1); } + + const_reference + back() const + { return *(end() - 1); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + // N.B. DR 464 says nothing about vector but we need something + // here due to the way we are implementing DR 464 in the debug-mode + // vector class. + void + data() _GLIBCXX_NOEXCEPT { } + + void + push_back(bool __x) + { + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) + *this->_M_impl._M_finish++ = __x; + else + _M_insert_aux(end(), __x); + } + + void + swap(vector& __x) _GLIBCXX_NOEXCEPT + { + std::swap(this->_M_impl._M_start, __x._M_impl._M_start); + std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish); + std::swap(this->_M_impl._M_end_of_storage, + __x._M_impl._M_end_of_storage); + _Bit_alloc_traits::_S_on_swap(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } + + // [23.2.5]/1, third-to-last entry in synopsis listing + static void + swap(reference __x, reference __y) _GLIBCXX_NOEXCEPT + { + bool __tmp = __x; + __x = __y; + __y = __tmp; + } + + iterator +#if __cplusplus >= 201103L + insert(const_iterator __position, const bool& __x = bool()) +#else + insert(iterator __position, const bool& __x = bool()) +#endif + { + const difference_type __n = __position - begin(); + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr() + && __position == end()) + *this->_M_impl._M_finish++ = __x; + else + _M_insert_aux(__position._M_const_cast(), __x); + return begin() + __n; + } + +#if __cplusplus >= 201103L + template> + iterator + insert(const_iterator __position, + _InputIterator __first, _InputIterator __last) + { + difference_type __offset = __position - cbegin(); + _M_insert_dispatch(__position._M_const_cast(), + __first, __last, __false_type()); + return begin() + __offset; + } +#else + template + void + insert(iterator __position, + _InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_insert_dispatch(__position, __first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + iterator + insert(const_iterator __position, size_type __n, const bool& __x) + { + difference_type __offset = __position - cbegin(); + _M_fill_insert(__position._M_const_cast(), __n, __x); + return begin() + __offset; + } +#else + void + insert(iterator __position, size_type __n, const bool& __x) + { _M_fill_insert(__position, __n, __x); } +#endif + +#if __cplusplus >= 201103L + iterator + insert(const_iterator __p, initializer_list __l) + { return this->insert(__p, __l.begin(), __l.end()); } +#endif + + void + pop_back() + { --this->_M_impl._M_finish; } + + iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) +#else + erase(iterator __position) +#endif + { return _M_erase(__position._M_const_cast()); } + + iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) +#else + erase(iterator __first, iterator __last) +#endif + { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } + + void + resize(size_type __new_size, bool __x = bool()) + { + if (__new_size < size()) + _M_erase_at_end(begin() + difference_type(__new_size)); + else + insert(end(), __new_size - size(), __x); + } + +#if __cplusplus >= 201103L + void + shrink_to_fit() + { _M_shrink_to_fit(); } +#endif + + void + flip() _GLIBCXX_NOEXCEPT + { + _Bit_type * const __end = this->_M_impl._M_end_addr(); + for (_Bit_type * __p = this->_M_impl._M_start._M_p; __p != __end; ++__p) + *__p = ~*__p; + } + + void + clear() _GLIBCXX_NOEXCEPT + { _M_erase_at_end(begin()); } + +#if __cplusplus >= 201103L + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args) + { + push_back(bool(__args...)); +#if __cplusplus > 201402L + return back(); +#endif + } + + template + iterator + emplace(const_iterator __pos, _Args&&... __args) + { return insert(__pos, bool(__args...)); } +#endif + + protected: + // Precondition: __first._M_offset == 0 && __result._M_offset == 0. + iterator + _M_copy_aligned(const_iterator __first, const_iterator __last, + iterator __result) + { + _Bit_type* __q = std::copy(__first._M_p, __last._M_p, __result._M_p); + return std::copy(const_iterator(__last._M_p, 0), __last, + iterator(__q, 0)); + } + + void + _M_initialize(size_type __n) + { + if (__n) + { + _Bit_pointer __q = this->_M_allocate(__n); + this->_M_impl._M_end_of_storage = __q + _S_nword(__n); + this->_M_impl._M_start = iterator(std::__addressof(*__q), 0); + } + else + { + this->_M_impl._M_end_of_storage = _Bit_pointer(); + this->_M_impl._M_start = iterator(0, 0); + } + this->_M_impl._M_finish = this->_M_impl._M_start + difference_type(__n); + + } + + void + _M_initialize_value(bool __x) + { + if (_Bit_type* __p = this->_M_impl._M_start._M_p) + __builtin_memset(__p, __x ? ~0 : 0, + (this->_M_impl._M_end_addr() - __p) + * sizeof(_Bit_type)); + } + + void + _M_reallocate(size_type __n); + +#if __cplusplus >= 201103L + bool + _M_shrink_to_fit(); +#endif + + // Check whether it's an integral type. If so, it's not an iterator. + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { + _M_initialize(static_cast(__n)); + _M_initialize_value(__x); + } + + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { _M_initialize_range(__first, __last, + std::__iterator_category(__first)); } + + template + void + _M_initialize_range(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + for (; __first != __last; ++__first) + push_back(*__first); + } + + template + void + _M_initialize_range(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __n = std::distance(__first, __last); + _M_initialize(__n); + std::copy(__first, __last, this->_M_impl._M_start); + } + +#if __cplusplus < 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#endif + + void + _M_fill_assign(size_t __n, bool __x) + { + if (__n > size()) + { + _M_initialize_value(__x); + insert(end(), __n - size(), __x); + } + else + { + _M_erase_at_end(begin() + __n); + _M_initialize_value(__x); + } + } + + template + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + iterator __cur = begin(); + for (; __first != __last && __cur != end(); ++__cur, (void)++__first) + *__cur = *__first; + if (__first == __last) + _M_erase_at_end(__cur); + else + insert(end(), __first, __last); + } + + template + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __len = std::distance(__first, __last); + if (__len < size()) + _M_erase_at_end(std::copy(__first, __last, begin())); + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, size()); + std::copy(__first, __mid, begin()); + insert(end(), __mid, __last); + } + } + + // Check whether it's an integral type. If so, it's not an iterator. + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, + __true_type) + { _M_fill_insert(__pos, __n, __x); } + + template + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) + { _M_insert_range(__pos, __first, __last, + std::__iterator_category(__first)); } + + void + _M_fill_insert(iterator __position, size_type __n, bool __x); + + template + void + _M_insert_range(iterator __pos, _InputIterator __first, + _InputIterator __last, std::input_iterator_tag) + { + for (; __first != __last; ++__first) + { + __pos = insert(__pos, *__first); + ++__pos; + } + } + + template + void + _M_insert_range(iterator __position, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag); + + void + _M_insert_aux(iterator __position, bool __x); + + size_type + _M_check_len(size_type __n, const char* __s) const + { + if (max_size() - size() < __n) + __throw_length_error(__N(__s)); + + const size_type __len = size() + std::max(size(), __n); + return (__len < size() || __len > max_size()) ? max_size() : __len; + } + + void + _M_erase_at_end(iterator __pos) + { this->_M_impl._M_finish = __pos; } + + iterator + _M_erase(iterator __pos); + + iterator + _M_erase(iterator __first, iterator __last); + }; + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // DR 1182. + /// std::hash specialization for vector. + template + struct hash<_GLIBCXX_STD_C::vector> + : public __hash_base> + { + size_t + operator()(const _GLIBCXX_STD_C::vector&) const noexcept; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +}// namespace std + +#endif // C++11 + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_construct.h b/resources/sources/avr-libstdcpp/include/bits/stl_construct.h new file mode 100644 index 000000000..72a7cb471 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_construct.h @@ -0,0 +1,256 @@ +// nonstandard construct and destroy functions -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_construct.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_CONSTRUCT_H +#define _STL_CONSTRUCT_H 1 + +#include +#include +#include // for iterator_traits +#include // for advance + +/* This file provides the C++17 functions std::destroy_at, std::destroy, and + * std::destroy_n, and the C++20 function std::construct_at. + * It also provides std::_Construct, std::_Destroy,and std::_Destroy_n functions + * which are defined in all standard modes and so can be used in C++98-14 code. + * The _Destroy functions will dispatch to destroy_at during constant + * evaluation, because calls to that function are intercepted by the compiler + * to allow use in constant expressions. + */ + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201703L + template + _GLIBCXX20_CONSTEXPR inline void + destroy_at(_Tp* __location) + { + if constexpr (__cplusplus > 201703L && is_array_v<_Tp>) + { + for (auto& __x : *__location) + std::destroy_at(std::__addressof(__x)); + } + else + __location->~_Tp(); + } + +#if __cplusplus > 201703L + template + constexpr auto + construct_at(_Tp* __location, _Args&&... __args) + noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...))) + -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...)) + { return ::new((void*)__location) _Tp(std::forward<_Args>(__args)...); } +#endif // C++20 +#endif// C++17 + + /** + * Constructs an object in existing memory by invoking an allocated + * object's constructor with an initializer. + */ +#if __cplusplus >= 201103L + template + inline void + _Construct(_Tp* __p, _Args&&... __args) + { ::new(static_cast(__p)) _Tp(std::forward<_Args>(__args)...); } +#else + template + inline void + _Construct(_T1* __p, const _T2& __value) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_]allocator::construct + ::new(static_cast(__p)) _T1(__value); + } +#endif + + template + inline void + _Construct_novalue(_T1* __p) + { ::new(static_cast(__p)) _T1; } + + template + _GLIBCXX20_CONSTEXPR void + _Destroy(_ForwardIterator __first, _ForwardIterator __last); + + /** + * Destroy the object pointed to by a pointer type. + */ + template + _GLIBCXX14_CONSTEXPR inline void + _Destroy(_Tp* __pointer) + { +#if __cplusplus > 201703L + std::destroy_at(__pointer); +#else + __pointer->~_Tp(); +#endif + } + + template + struct _Destroy_aux + { + template + static _GLIBCXX20_CONSTEXPR void + __destroy(_ForwardIterator __first, _ForwardIterator __last) + { + for (; __first != __last; ++__first) + std::_Destroy(std::__addressof(*__first)); + } + }; + + template<> + struct _Destroy_aux + { + template + static void + __destroy(_ForwardIterator, _ForwardIterator) { } + }; + + /** + * Destroy a range of objects. If the value_type of the object has + * a trivial destructor, the compiler should optimize all of this + * away, otherwise the objects' destructors must be invoked. + */ + template + _GLIBCXX20_CONSTEXPR inline void + _Destroy(_ForwardIterator __first, _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; +#if __cplusplus >= 201103L + // A deleted destructor is trivial, this ensures we reject such types: + static_assert(is_destructible<_Value_type>::value, + "value type is destructible"); +#endif +#if __cplusplus > 201703L && defined __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return _Destroy_aux::__destroy(__first, __last); +#endif + std::_Destroy_aux<__has_trivial_destructor(_Value_type)>:: + __destroy(__first, __last); + } + + template + struct _Destroy_n_aux + { + template + static _GLIBCXX20_CONSTEXPR _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + for (; __count > 0; (void)++__first, --__count) + std::_Destroy(std::__addressof(*__first)); + return __first; + } + }; + + template<> + struct _Destroy_n_aux + { + template + static _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + std::advance(__first, __count); + return __first; + } + }; + + /** + * Destroy a range of objects. If the value_type of the object has + * a trivial destructor, the compiler should optimize all of this + * away, otherwise the objects' destructors must be invoked. + */ + template + _GLIBCXX20_CONSTEXPR inline _ForwardIterator + _Destroy_n(_ForwardIterator __first, _Size __count) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; +#if __cplusplus >= 201103L + // A deleted destructor is trivial, this ensures we reject such types: + static_assert(is_destructible<_Value_type>::value, + "value type is destructible"); +#endif +#if __cplusplus > 201703L && defined __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return _Destroy_n_aux::__destroy_n(__first, __count); +#endif + return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>:: + __destroy_n(__first, __count); + } + +#if __cplusplus >= 201703L + template + _GLIBCXX20_CONSTEXPR inline void + destroy(_ForwardIterator __first, _ForwardIterator __last) + { + std::_Destroy(__first, __last); + } + + template + _GLIBCXX20_CONSTEXPR inline _ForwardIterator + destroy_n(_ForwardIterator __first, _Size __count) + { + return std::_Destroy_n(__first, __count); + } +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_CONSTRUCT_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_deque.h b/resources/sources/avr-libstdcpp/include/bits/stl_deque.h new file mode 100644 index 000000000..3959dd789 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_deque.h @@ -0,0 +1,2330 @@ +// Deque implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_deque.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{deque} + */ + +#ifndef _STL_DEQUE_H +#define _STL_DEQUE_H 1 + +#include +#include +#include +#if __cplusplus >= 201103L +#include +#include // for __is_bitwise_relocatable +#endif +#if __cplusplus > 201703L +# include +#endif + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * @brief This function controls the size of memory nodes. + * @param __size The size of an element. + * @return The number (not byte size) of elements per node. + * + * This function started off as a compiler kludge from SGI, but + * seems to be a useful wrapper around a repeated constant + * expression. The @b 512 is tunable (and no other code needs to + * change), but no investigation has been done since inheriting the + * SGI code. Touch _GLIBCXX_DEQUE_BUF_SIZE only if you know what + * you are doing, however: changing it breaks the binary + * compatibility!! + */ + +#ifndef _GLIBCXX_DEQUE_BUF_SIZE +#define _GLIBCXX_DEQUE_BUF_SIZE 512 +#endif + + _GLIBCXX_CONSTEXPR inline size_t + __deque_buf_size(size_t __size) + { return (__size < _GLIBCXX_DEQUE_BUF_SIZE + ? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1)); } + + + /** + * @brief A deque::iterator. + * + * Quite a bit of intelligence here. Much of the functionality of + * deque is actually passed off to this class. A deque holds two + * of these internally, marking its valid range. Access to + * elements is done as offsets of either of those two, relying on + * operator overloading in this class. + * + * All the functions are op overloads except for _M_set_node. + */ + template + struct _Deque_iterator + { +#if __cplusplus < 201103L + typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; + typedef _Tp* _Elt_pointer; + typedef _Tp** _Map_pointer; +#else + private: + template + using __iter = _Deque_iterator<_Tp, _CvTp&, __ptr_rebind<_Ptr, _CvTp>>; + public: + typedef __iter<_Tp> iterator; + typedef __iter const_iterator; + typedef __ptr_rebind<_Ptr, _Tp> _Elt_pointer; + typedef __ptr_rebind<_Ptr, _Elt_pointer> _Map_pointer; +#endif + + static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT + { return __deque_buf_size(sizeof(_Tp)); } + + typedef std::random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Deque_iterator _Self; + + _Elt_pointer _M_cur; + _Elt_pointer _M_first; + _Elt_pointer _M_last; + _Map_pointer _M_node; + + _Deque_iterator(_Elt_pointer __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT + : _M_cur(__x), _M_first(*__y), + _M_last(*__y + _S_buffer_size()), _M_node(__y) { } + + _Deque_iterator() _GLIBCXX_NOEXCEPT + : _M_cur(), _M_first(), _M_last(), _M_node() { } + +#if __cplusplus < 201103L + // Conversion from iterator to const_iterator. + _Deque_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT + : _M_cur(__x._M_cur), _M_first(__x._M_first), + _M_last(__x._M_last), _M_node(__x._M_node) { } +#else + // Conversion from iterator to const_iterator. + template, + is_same<_Iter, iterator>>> + _Deque_iterator(const _Iter& __x) noexcept + : _M_cur(__x._M_cur), _M_first(__x._M_first), + _M_last(__x._M_last), _M_node(__x._M_node) { } + + _Deque_iterator(const _Deque_iterator& __x) noexcept + : _M_cur(__x._M_cur), _M_first(__x._M_first), + _M_last(__x._M_last), _M_node(__x._M_node) { } + + _Deque_iterator& operator=(const _Deque_iterator&) = default; +#endif + + iterator + _M_const_cast() const _GLIBCXX_NOEXCEPT + { return iterator(_M_cur, _M_node); } + + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *_M_cur; } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return _M_cur; } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + ++_M_cur; + if (_M_cur == _M_last) + { + _M_set_node(_M_node + 1); + _M_cur = _M_first; + } + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + ++*this; + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + if (_M_cur == _M_first) + { + _M_set_node(_M_node - 1); + _M_cur = _M_last; + } + --_M_cur; + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + --*this; + return __tmp; + } + + _Self& + operator+=(difference_type __n) _GLIBCXX_NOEXCEPT + { + const difference_type __offset = __n + (_M_cur - _M_first); + if (__offset >= 0 && __offset < difference_type(_S_buffer_size())) + _M_cur += __n; + else + { + const difference_type __node_offset = + __offset > 0 ? __offset / difference_type(_S_buffer_size()) + : -difference_type((-__offset - 1) + / _S_buffer_size()) - 1; + _M_set_node(_M_node + __node_offset); + _M_cur = _M_first + (__offset - __node_offset + * difference_type(_S_buffer_size())); + } + return *this; + } + + _Self& + operator-=(difference_type __n) _GLIBCXX_NOEXCEPT + { return *this += -__n; } + + reference + operator[](difference_type __n) const _GLIBCXX_NOEXCEPT + { return *(*this + __n); } + + /** + * Prepares to traverse new_node. Sets everything except + * _M_cur, which should therefore be set by the caller + * immediately afterwards, based on _M_first and _M_last. + */ + void + _M_set_node(_Map_pointer __new_node) _GLIBCXX_NOEXCEPT + { + _M_node = __new_node; + _M_first = *__new_node; + _M_last = _M_first + difference_type(_S_buffer_size()); + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_cur == __y._M_cur; } + + // Note: we also provide overloads whose operands are of the same type in + // order to avoid ambiguous overload resolution when std::rel_ops + // operators are in scope (for additional details, see libstdc++/3628) + template + friend bool + operator==(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return __x._M_cur == __y._M_cur; } + +#if __cpp_lib_three_way_comparison + friend strong_ordering + operator<=>(const _Self& __x, const _Self& __y) noexcept + { + if (const auto __cmp = __x._M_node <=> __y._M_node; __cmp != 0) + return __cmp; + return __x._M_cur <=> __y._M_cur; + } +#else + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return !(__x == __y); } + + template + friend bool + operator!=(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return !(__x == __y); } + + friend bool + operator<(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { + return (__x._M_node == __y._M_node) + ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); + } + + template + friend bool + operator<(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { + return (__x._M_node == __y._M_node) + ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); + } + + friend bool + operator>(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __y < __x; } + + template + friend bool + operator>(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return __y < __x; } + + friend bool + operator<=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return !(__y < __x); } + + template + friend bool + operator<=(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return !(__y < __x); } + + friend bool + operator>=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return !(__x < __y); } + + template + friend bool + operator>=(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return !(__x < __y); } +#endif // three-way comparison + + friend difference_type + operator-(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { + return difference_type(_S_buffer_size()) + * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) + + (__y._M_last - __y._M_cur); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template + friend difference_type + operator-(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT + { + return difference_type(_S_buffer_size()) + * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) + + (__y._M_last - __y._M_cur); + } + + friend _Self + operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT + { + _Self __tmp = __x; + __tmp += __n; + return __tmp; + } + + friend _Self + operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT + { + _Self __tmp = __x; + __tmp -= __n; + return __tmp; + } + + friend _Self + operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT + { return __x + __n; } + }; + + /** + * Deque base class. This class provides the unified face for %deque's + * allocation. This class's constructor and destructor allocate and + * deallocate (but do not initialize) storage. This makes %exception + * safety easier. + * + * Nothing in this class ever constructs or destroys an actual Tp element. + * (Deque handles that itself.) Only/All memory management is performed + * here. + */ + template + class _Deque_base + { + protected: + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Tp>::other _Tp_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; + +#if __cplusplus < 201103L + typedef _Tp* _Ptr; + typedef const _Tp* _Ptr_const; +#else + typedef typename _Alloc_traits::pointer _Ptr; + typedef typename _Alloc_traits::const_pointer _Ptr_const; +#endif + + typedef typename _Alloc_traits::template rebind<_Ptr>::other + _Map_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits; + + typedef _Alloc allocator_type; + + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_get_Tp_allocator()); } + + typedef _Deque_iterator<_Tp, _Tp&, _Ptr> iterator; + typedef _Deque_iterator<_Tp, const _Tp&, _Ptr_const> const_iterator; + + _Deque_base() + : _M_impl() + { _M_initialize_map(0); } + + _Deque_base(size_t __num_elements) + : _M_impl() + { _M_initialize_map(__num_elements); } + + _Deque_base(const allocator_type& __a, size_t __num_elements) + : _M_impl(__a) + { _M_initialize_map(__num_elements); } + + _Deque_base(const allocator_type& __a) + : _M_impl(__a) + { /* Caller must initialize map. */ } + +#if __cplusplus >= 201103L + _Deque_base(_Deque_base&& __x) + : _M_impl(std::move(__x._M_get_Tp_allocator())) + { + _M_initialize_map(0); + if (__x._M_impl._M_map) + this->_M_impl._M_swap_data(__x._M_impl); + } + + _Deque_base(_Deque_base&& __x, const allocator_type& __a) + : _M_impl(std::move(__x._M_impl), _Tp_alloc_type(__a)) + { __x._M_initialize_map(0); } + + _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_t __n) + : _M_impl(__a) + { + if (__x.get_allocator() == __a) + { + if (__x._M_impl._M_map) + { + _M_initialize_map(0); + this->_M_impl._M_swap_data(__x._M_impl); + } + } + else + { + _M_initialize_map(__n); + } + } +#endif + + ~_Deque_base() _GLIBCXX_NOEXCEPT; + + typedef typename iterator::_Map_pointer _Map_pointer; + + struct _Deque_impl_data + { + _Map_pointer _M_map; + size_t _M_map_size; + iterator _M_start; + iterator _M_finish; + + _Deque_impl_data() _GLIBCXX_NOEXCEPT + : _M_map(), _M_map_size(), _M_start(), _M_finish() + { } + +#if __cplusplus >= 201103L + _Deque_impl_data(const _Deque_impl_data&) = default; + _Deque_impl_data& + operator=(const _Deque_impl_data&) = default; + + _Deque_impl_data(_Deque_impl_data&& __x) noexcept + : _Deque_impl_data(__x) + { __x = _Deque_impl_data(); } +#endif + + void + _M_swap_data(_Deque_impl_data& __x) _GLIBCXX_NOEXCEPT + { + // Do not use std::swap(_M_start, __x._M_start), etc as it loses + // information used by TBAA. + std::swap(*this, __x); + } + }; + + // This struct encapsulates the implementation of the std::deque + // standard container and at the same time makes use of the EBO + // for empty allocators. + struct _Deque_impl + : public _Tp_alloc_type, public _Deque_impl_data + { + _Deque_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Tp_alloc_type>::value) + : _Tp_alloc_type() + { } + + _Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT + : _Tp_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + _Deque_impl(_Deque_impl&&) = default; + + _Deque_impl(_Tp_alloc_type&& __a) noexcept + : _Tp_alloc_type(std::move(__a)) + { } + + _Deque_impl(_Deque_impl&& __d, _Tp_alloc_type&& __a) + : _Tp_alloc_type(std::move(__a)), _Deque_impl_data(std::move(__d)) + { } +#endif + }; + + _Tp_alloc_type& + _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + const _Tp_alloc_type& + _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + _Map_alloc_type + _M_get_map_allocator() const _GLIBCXX_NOEXCEPT + { return _Map_alloc_type(_M_get_Tp_allocator()); } + + _Ptr + _M_allocate_node() + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits; + return _Traits::allocate(_M_impl, __deque_buf_size(sizeof(_Tp))); + } + + void + _M_deallocate_node(_Ptr __p) _GLIBCXX_NOEXCEPT + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits; + _Traits::deallocate(_M_impl, __p, __deque_buf_size(sizeof(_Tp))); + } + + _Map_pointer + _M_allocate_map(size_t __n) + { + _Map_alloc_type __map_alloc = _M_get_map_allocator(); + return _Map_alloc_traits::allocate(__map_alloc, __n); + } + + void + _M_deallocate_map(_Map_pointer __p, size_t __n) _GLIBCXX_NOEXCEPT + { + _Map_alloc_type __map_alloc = _M_get_map_allocator(); + _Map_alloc_traits::deallocate(__map_alloc, __p, __n); + } + + void _M_initialize_map(size_t); + void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish); + void _M_destroy_nodes(_Map_pointer __nstart, + _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT; + enum { _S_initial_map_size = 8 }; + + _Deque_impl _M_impl; + }; + + template + _Deque_base<_Tp, _Alloc>:: + ~_Deque_base() _GLIBCXX_NOEXCEPT + { + if (this->_M_impl._M_map) + { + _M_destroy_nodes(this->_M_impl._M_start._M_node, + this->_M_impl._M_finish._M_node + 1); + _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); + } + } + + /** + * @brief Layout storage. + * @param __num_elements The count of T's for which to allocate space + * at first. + * @return Nothing. + * + * The initial underlying memory layout is a bit complicated... + */ + template + void + _Deque_base<_Tp, _Alloc>:: + _M_initialize_map(size_t __num_elements) + { + const size_t __num_nodes = (__num_elements / __deque_buf_size(sizeof(_Tp)) + + 1); + + this->_M_impl._M_map_size = std::max((size_t) _S_initial_map_size, + size_t(__num_nodes + 2)); + this->_M_impl._M_map = _M_allocate_map(this->_M_impl._M_map_size); + + // For "small" maps (needing less than _M_map_size nodes), allocation + // starts in the middle elements and grows outwards. So nstart may be + // the beginning of _M_map, but for small maps it may be as far in as + // _M_map+3. + + _Map_pointer __nstart = (this->_M_impl._M_map + + (this->_M_impl._M_map_size - __num_nodes) / 2); + _Map_pointer __nfinish = __nstart + __num_nodes; + + __try + { _M_create_nodes(__nstart, __nfinish); } + __catch(...) + { + _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); + this->_M_impl._M_map = _Map_pointer(); + this->_M_impl._M_map_size = 0; + __throw_exception_again; + } + + this->_M_impl._M_start._M_set_node(__nstart); + this->_M_impl._M_finish._M_set_node(__nfinish - 1); + this->_M_impl._M_start._M_cur = _M_impl._M_start._M_first; + this->_M_impl._M_finish._M_cur = (this->_M_impl._M_finish._M_first + + __num_elements + % __deque_buf_size(sizeof(_Tp))); + } + + template + void + _Deque_base<_Tp, _Alloc>:: + _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish) + { + _Map_pointer __cur; + __try + { + for (__cur = __nstart; __cur < __nfinish; ++__cur) + *__cur = this->_M_allocate_node(); + } + __catch(...) + { + _M_destroy_nodes(__nstart, __cur); + __throw_exception_again; + } + } + + template + void + _Deque_base<_Tp, _Alloc>:: + _M_destroy_nodes(_Map_pointer __nstart, + _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT + { + for (_Map_pointer __n = __nstart; __n < __nfinish; ++__n) + _M_deallocate_node(*__n); + } + + /** + * @brief A standard container using fixed-size memory allocation and + * constant-time manipulation of elements at either end. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements. + * + * In previous HP/SGI versions of deque, there was an extra template + * parameter so users could control the node size. This extension turned + * out to violate the C++ standard (it can be detected using template + * template parameters), and it was removed. + * + * Here's how a deque manages memory. Each deque has 4 members: + * + * - Tp** _M_map + * - size_t _M_map_size + * - iterator _M_start, _M_finish + * + * map_size is at least 8. %map is an array of map_size + * pointers-to-@a nodes. (The name %map has nothing to do with the + * std::map class, and @b nodes should not be confused with + * std::list's usage of @a node.) + * + * A @a node has no specific type name as such, but it is referred + * to as @a node in this file. It is a simple array-of-Tp. If Tp + * is very large, there will be one Tp element per node (i.e., an + * @a array of one). For non-huge Tp's, node size is inversely + * related to Tp size: the larger the Tp, the fewer Tp's will fit + * in a node. The goal here is to keep the total size of a node + * relatively small and constant over different Tp's, to improve + * allocator efficiency. + * + * Not every pointer in the %map array will point to a node. If + * the initial number of elements in the deque is small, the + * /middle/ %map pointers will be valid, and the ones at the edges + * will be unused. This same situation will arise as the %map + * grows: available %map pointers, if any, will be on the ends. As + * new nodes are created, only a subset of the %map's pointers need + * to be copied @a outward. + * + * Class invariants: + * - For any nonsingular iterator i: + * - i.node points to a member of the %map array. (Yes, you read that + * correctly: i.node does not actually point to a node.) The member of + * the %map array is what actually points to the node. + * - i.first == *(i.node) (This points to the node (first Tp element).) + * - i.last == i.first + node_size + * - i.cur is a pointer in the range [i.first, i.last). NOTE: + * the implication of this is that i.cur is always a dereferenceable + * pointer, even if i is a past-the-end iterator. + * - Start and Finish are always nonsingular iterators. NOTE: this + * means that an empty deque must have one node, a deque with > + class deque : protected _Deque_base<_Tp, _Alloc> + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Tp>::value, + "std::deque must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::deque must have the same value_type as its allocator"); +# endif +#endif + + typedef _Deque_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef typename _Base::_Alloc_traits _Alloc_traits; + typedef typename _Base::_Map_pointer _Map_pointer; + + public: + typedef _Tp value_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + typedef typename _Base::iterator iterator; + typedef typename _Base::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + private: + static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT + { return __deque_buf_size(sizeof(_Tp)); } + + // Functions controlling memory layout, and nothing else. + using _Base::_M_initialize_map; + using _Base::_M_create_nodes; + using _Base::_M_destroy_nodes; + using _Base::_M_allocate_node; + using _Base::_M_deallocate_node; + using _Base::_M_allocate_map; + using _Base::_M_deallocate_map; + using _Base::_M_get_Tp_allocator; + + /** + * A total of four data members accumulated down the hierarchy. + * May be accessed via _M_impl.* + */ + using _Base::_M_impl; + + public: + // [23.2.1.1] construct/copy/destroy + // (assign() and get_allocator() are also listed in this section) + + /** + * @brief Creates a %deque with no elements. + */ +#if __cplusplus >= 201103L + deque() = default; +#else + deque() { } +#endif + + /** + * @brief Creates a %deque with no elements. + * @param __a An allocator object. + */ + explicit + deque(const allocator_type& __a) + : _Base(__a, 0) { } + +#if __cplusplus >= 201103L + /** + * @brief Creates a %deque with default constructed elements. + * @param __n The number of elements to initially create. + * @param __a An allocator. + * + * This constructor fills the %deque with @a n default + * constructed elements. + */ + explicit + deque(size_type __n, const allocator_type& __a = allocator_type()) + : _Base(__a, _S_check_init_len(__n, __a)) + { _M_default_initialize(); } + + /** + * @brief Creates a %deque with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator. + * + * This constructor fills the %deque with @a __n copies of @a __value. + */ + deque(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) + : _Base(__a, _S_check_init_len(__n, __a)) + { _M_fill_initialize(__value); } +#else + /** + * @brief Creates a %deque with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator. + * + * This constructor fills the %deque with @a __n copies of @a __value. + */ + explicit + deque(size_type __n, const value_type& __value = value_type(), + const allocator_type& __a = allocator_type()) + : _Base(__a, _S_check_init_len(__n, __a)) + { _M_fill_initialize(__value); } +#endif + + /** + * @brief %Deque copy constructor. + * @param __x A %deque of identical element and allocator types. + * + * The newly-created %deque uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). + */ + deque(const deque& __x) + : _Base(_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()), + __x.size()) + { std::__uninitialized_copy_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); } + +#if __cplusplus >= 201103L + /** + * @brief %Deque move constructor. + * + * The newly-created %deque contains the exact contents of the + * moved instance. + * The contents of the moved instance are a valid, but unspecified + * %deque. + */ + deque(deque&&) = default; + + /// Copy constructor with alternative allocator + deque(const deque& __x, const allocator_type& __a) + : _Base(__a, __x.size()) + { std::__uninitialized_copy_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); } + + /// Move constructor with alternative allocator + deque(deque&& __x, const allocator_type& __a) + : deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{}) + { } + + private: + deque(deque&& __x, const allocator_type& __a, true_type) + : _Base(std::move(__x), __a) + { } + + deque(deque&& __x, const allocator_type& __a, false_type) + : _Base(std::move(__x), __a, __x.size()) + { + if (__x.get_allocator() != __a && !__x.empty()) + { + std::__uninitialized_move_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); + __x.clear(); + } + } + + public: + /** + * @brief Builds a %deque from an initializer list. + * @param __l An initializer_list. + * @param __a An allocator object. + * + * Create a %deque consisting of copies of the elements in the + * initializer_list @a __l. + * + * This will call the element type's copy constructor N times + * (where N is __l.size()) and do no memory reallocation. + */ + deque(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_range_initialize(__l.begin(), __l.end(), + random_access_iterator_tag()); + } +#endif + + /** + * @brief Builds a %deque from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __a An allocator object. + * + * Create a %deque consisting of copies of the elements from [__first, + * __last). + * + * If the iterators are forward, bidirectional, or random-access, then + * this will call the elements' copy constructor N times (where N is + * distance(__first,__last)) and do no memory reallocation. But if only + * input iterators are used, then this will do at most 2N calls to the + * copy constructor, and logN memory reallocations. + */ +#if __cplusplus >= 201103L + template> + deque(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#else + template + deque(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } +#endif + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~deque() + { _M_destroy_data(begin(), end(), _M_get_Tp_allocator()); } + + /** + * @brief %Deque assignment operator. + * @param __x A %deque of identical element and allocator types. + * + * All the elements of @a x are copied. + * + * The newly-created %deque uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). + */ + deque& + operator=(const deque& __x); + +#if __cplusplus >= 201103L + /** + * @brief %Deque move assignment operator. + * @param __x A %deque of identical element and allocator types. + * + * The contents of @a __x are moved into this deque (without copying, + * if the allocators permit it). + * @a __x is a valid, but unspecified %deque. + */ + deque& + operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal()) + { + using __always_equal = typename _Alloc_traits::is_always_equal; + _M_move_assign1(std::move(__x), __always_equal{}); + return *this; + } + + /** + * @brief Assigns an initializer list to a %deque. + * @param __l An initializer_list. + * + * This function fills a %deque with copies of the elements in the + * initializer_list @a __l. + * + * Note that the assignment completely changes the %deque and that the + * resulting %deque's size is the same as the number of elements + * assigned. + */ + deque& + operator=(initializer_list __l) + { + _M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); + return *this; + } +#endif + + /** + * @brief Assigns a given value to a %deque. + * @param __n Number of elements to be assigned. + * @param __val Value to be assigned. + * + * This function fills a %deque with @a n copies of the given + * value. Note that the assignment completely changes the + * %deque and that the resulting %deque's size is the same as + * the number of elements assigned. + */ + void + assign(size_type __n, const value_type& __val) + { _M_fill_assign(__n, __val); } + + /** + * @brief Assigns a range to a %deque. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function fills a %deque with copies of the elements in the + * range [__first,__last). + * + * Note that the assignment completely changes the %deque and that the + * resulting %deque's size is the same as the number of elements + * assigned. + */ +#if __cplusplus >= 201103L + template> + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#else + template + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Assigns an initializer list to a %deque. + * @param __l An initializer_list. + * + * This function fills a %deque with copies of the elements in the + * initializer_list @a __l. + * + * Note that the assignment completely changes the %deque and that the + * resulting %deque's size is the same as the number of elements + * assigned. + */ + void + assign(initializer_list __l) + { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); } +#endif + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return _Base::get_allocator(); } + + // iterators + /** + * Returns a read/write iterator that points to the first element in the + * %deque. Iteration is done in ordinary element order. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_start; } + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %deque. Iteration is done in ordinary element order. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_start; } + + /** + * Returns a read/write iterator that points one past the last + * element in the %deque. Iteration is done in ordinary + * element order. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish; } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %deque. Iteration is done in + * ordinary element order. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish; } + + /** + * Returns a read/write reverse iterator that points to the + * last element in the %deque. Iteration is done in reverse + * element order. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to the last element in the %deque. Iteration is done in + * reverse element order. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read/write reverse iterator that points to one + * before the first element in the %deque. Iteration is done + * in reverse element order. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(this->_M_impl._M_start); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to one before the first element in the %deque. Iteration is + * done in reverse element order. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(this->_M_impl._M_start); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %deque. Iteration is done in ordinary element order. + */ + const_iterator + cbegin() const noexcept + { return this->_M_impl._M_start; } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %deque. Iteration is done in + * ordinary element order. + */ + const_iterator + cend() const noexcept + { return this->_M_impl._M_finish; } + + /** + * Returns a read-only (constant) reverse iterator that points + * to the last element in the %deque. Iteration is done in + * reverse element order. + */ + const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to one before the first element in the %deque. Iteration is + * done in reverse element order. + */ + const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(this->_M_impl._M_start); } +#endif + + // [23.2.1.2] capacity + /** Returns the number of elements in the %deque. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish - this->_M_impl._M_start; } + + /** Returns the size() of the largest possible %deque. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _S_max_size(_M_get_Tp_allocator()); } + +#if __cplusplus >= 201103L + /** + * @brief Resizes the %deque to the specified number of elements. + * @param __new_size Number of elements the %deque should contain. + * + * This function will %resize the %deque to the specified + * number of elements. If the number is smaller than the + * %deque's current size the %deque is truncated, otherwise + * default constructed elements are appended. + */ + void + resize(size_type __new_size) + { + const size_type __len = size(); + if (__new_size > __len) + _M_default_append(__new_size - __len); + else if (__new_size < __len) + _M_erase_at_end(this->_M_impl._M_start + + difference_type(__new_size)); + } + + /** + * @brief Resizes the %deque to the specified number of elements. + * @param __new_size Number of elements the %deque should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %deque to the specified + * number of elements. If the number is smaller than the + * %deque's current size the %deque is truncated, otherwise the + * %deque is extended and new elements are populated with given + * data. + */ + void + resize(size_type __new_size, const value_type& __x) +#else + /** + * @brief Resizes the %deque to the specified number of elements. + * @param __new_size Number of elements the %deque should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %deque to the specified + * number of elements. If the number is smaller than the + * %deque's current size the %deque is truncated, otherwise the + * %deque is extended and new elements are populated with given + * data. + */ + void + resize(size_type __new_size, value_type __x = value_type()) +#endif + { + const size_type __len = size(); + if (__new_size > __len) + _M_fill_insert(this->_M_impl._M_finish, __new_size - __len, __x); + else if (__new_size < __len) + _M_erase_at_end(this->_M_impl._M_start + + difference_type(__new_size)); + } + +#if __cplusplus >= 201103L + /** A non-binding request to reduce memory use. */ + void + shrink_to_fit() noexcept + { _M_shrink_to_fit(); } +#endif + + /** + * Returns true if the %deque is empty. (Thus begin() would + * equal end().) + */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish == this->_M_impl._M_start; } + + // element access + /** + * @brief Subscript access to the data contained in the %deque. + * @param __n The index of the element for which data should be + * accessed. + * @return Read/write reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and + * out_of_range lookups are not defined. (For checked lookups + * see at().) + */ + reference + operator[](size_type __n) _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_subscript(__n); + return this->_M_impl._M_start[difference_type(__n)]; + } + + /** + * @brief Subscript access to the data contained in the %deque. + * @param __n The index of the element for which data should be + * accessed. + * @return Read-only (constant) reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and + * out_of_range lookups are not defined. (For checked lookups + * see at().) + */ + const_reference + operator[](size_type __n) const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_subscript(__n); + return this->_M_impl._M_start[difference_type(__n)]; + } + + protected: + /// Safety check used only from at(). + void + _M_range_check(size_type __n) const + { + if (__n >= this->size()) + __throw_out_of_range_fmt(__N("deque::_M_range_check: __n " + "(which is %zu)>= this->size() " + "(which is %zu)"), + __n, this->size()); + } + + public: + /** + * @brief Provides access to the data contained in the %deque. + * @param __n The index of the element for which data should be + * accessed. + * @return Read/write reference to data. + * @throw std::out_of_range If @a __n is an invalid index. + * + * This function provides for safer data access. The parameter + * is first checked that it is in the range of the deque. The + * function throws out_of_range if the check fails. + */ + reference + at(size_type __n) + { + _M_range_check(__n); + return (*this)[__n]; + } + + /** + * @brief Provides access to the data contained in the %deque. + * @param __n The index of the element for which data should be + * accessed. + * @return Read-only (constant) reference to data. + * @throw std::out_of_range If @a __n is an invalid index. + * + * This function provides for safer data access. The parameter is first + * checked that it is in the range of the deque. The function throws + * out_of_range if the check fails. + */ + const_reference + at(size_type __n) const + { + _M_range_check(__n); + return (*this)[__n]; + } + + /** + * Returns a read/write reference to the data at the first + * element of the %deque. + */ + reference + front() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *begin(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %deque. + */ + const_reference + front() const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *begin(); + } + + /** + * Returns a read/write reference to the data at the last element of the + * %deque. + */ + reference + back() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + iterator __tmp = end(); + --__tmp; + return *__tmp; + } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %deque. + */ + const_reference + back() const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + const_iterator __tmp = end(); + --__tmp; + return *__tmp; + } + + // [23.2.1.2] modifiers + /** + * @brief Add data to the front of the %deque. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the front of the %deque and assigns the given + * data to it. Due to the nature of a %deque this operation + * can be done in constant time. + */ + void + push_front(const value_type& __x) + { + if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) + { + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_start._M_cur - 1, + __x); + --this->_M_impl._M_start._M_cur; + } + else + _M_push_front_aux(__x); + } + +#if __cplusplus >= 201103L + void + push_front(value_type&& __x) + { emplace_front(std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_front(_Args&&... __args); +#endif + + /** + * @brief Add data to the end of the %deque. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the end of the %deque and assigns the given data + * to it. Due to the nature of a %deque this operation can be + * done in constant time. + */ + void + push_back(const value_type& __x) + { + if (this->_M_impl._M_finish._M_cur + != this->_M_impl._M_finish._M_last - 1) + { + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_finish._M_cur, __x); + ++this->_M_impl._M_finish._M_cur; + } + else + _M_push_back_aux(__x); + } + +#if __cplusplus >= 201103L + void + push_back(value_type&& __x) + { emplace_back(std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args); +#endif + + /** + * @brief Removes first element. + * + * This is a typical stack operation. It shrinks the %deque by one. + * + * Note that no data is returned, and if the first element's data is + * needed, it should be retrieved before pop_front() is called. + */ + void + pop_front() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + if (this->_M_impl._M_start._M_cur + != this->_M_impl._M_start._M_last - 1) + { + _Alloc_traits::destroy(_M_get_Tp_allocator(), + this->_M_impl._M_start._M_cur); + ++this->_M_impl._M_start._M_cur; + } + else + _M_pop_front_aux(); + } + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %deque by one. + * + * Note that no data is returned, and if the last element's data is + * needed, it should be retrieved before pop_back() is called. + */ + void + pop_back() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + if (this->_M_impl._M_finish._M_cur + != this->_M_impl._M_finish._M_first) + { + --this->_M_impl._M_finish._M_cur; + _Alloc_traits::destroy(_M_get_Tp_allocator(), + this->_M_impl._M_finish._M_cur); + } + else + _M_pop_back_aux(); + } + +#if __cplusplus >= 201103L + /** + * @brief Inserts an object in %deque before specified iterator. + * @param __position A const_iterator into the %deque. + * @param __args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) before the specified location. + */ + template + iterator + emplace(const_iterator __position, _Args&&... __args); + + /** + * @brief Inserts given value into %deque before specified iterator. + * @param __position A const_iterator into the %deque. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before the + * specified location. + */ + iterator + insert(const_iterator __position, const value_type& __x); +#else + /** + * @brief Inserts given value into %deque before specified iterator. + * @param __position An iterator into the %deque. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before the + * specified location. + */ + iterator + insert(iterator __position, const value_type& __x); +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts given rvalue into %deque before specified iterator. + * @param __position A const_iterator into the %deque. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given rvalue before the + * specified location. + */ + iterator + insert(const_iterator __position, value_type&& __x) + { return emplace(__position, std::move(__x)); } + + /** + * @brief Inserts an initializer list into the %deque. + * @param __p An iterator into the %deque. + * @param __l An initializer_list. + * @return An iterator that points to the inserted data. + * + * This function will insert copies of the data in the + * initializer_list @a __l into the %deque before the location + * specified by @a __p. This is known as list insert. + */ + iterator + insert(const_iterator __p, initializer_list __l) + { + auto __offset = __p - cbegin(); + _M_range_insert_aux(__p._M_const_cast(), __l.begin(), __l.end(), + std::random_access_iterator_tag()); + return begin() + __offset; + } + + /** + * @brief Inserts a number of copies of given data into the %deque. + * @param __position A const_iterator into the %deque. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a specified number of copies of the given + * data before the location specified by @a __position. + */ + iterator + insert(const_iterator __position, size_type __n, const value_type& __x) + { + difference_type __offset = __position - cbegin(); + _M_fill_insert(__position._M_const_cast(), __n, __x); + return begin() + __offset; + } +#else + /** + * @brief Inserts a number of copies of given data into the %deque. + * @param __position An iterator into the %deque. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * + * This function will insert a specified number of copies of the given + * data before the location specified by @a __position. + */ + void + insert(iterator __position, size_type __n, const value_type& __x) + { _M_fill_insert(__position, __n, __x); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a range into the %deque. + * @param __position A const_iterator into the %deque. + * @param __first An input iterator. + * @param __last An input iterator. + * @return An iterator that points to the inserted data. + * + * This function will insert copies of the data in the range + * [__first,__last) into the %deque before the location specified + * by @a __position. This is known as range insert. + */ + template> + iterator + insert(const_iterator __position, _InputIterator __first, + _InputIterator __last) + { + difference_type __offset = __position - cbegin(); + _M_range_insert_aux(__position._M_const_cast(), __first, __last, + std::__iterator_category(__first)); + return begin() + __offset; + } +#else + /** + * @brief Inserts a range into the %deque. + * @param __position An iterator into the %deque. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function will insert copies of the data in the range + * [__first,__last) into the %deque before the location specified + * by @a __position. This is known as range insert. + */ + template + void + insert(iterator __position, _InputIterator __first, + _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_insert_dispatch(__position, __first, __last, _Integral()); + } +#endif + + /** + * @brief Remove element at given position. + * @param __position Iterator pointing to element to be erased. + * @return An iterator pointing to the next element (or end()). + * + * This function will erase the element at the given position and thus + * shorten the %deque by one. + * + * The user is cautioned that + * this function only erases the element, and that if the element is + * itself a pointer, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) +#else + erase(iterator __position) +#endif + { return _M_erase(__position._M_const_cast()); } + + /** + * @brief Remove a range of elements. + * @param __first Iterator pointing to the first element to be erased. + * @param __last Iterator pointing to one past the last element to be + * erased. + * @return An iterator pointing to the element pointed to by @a last + * prior to erasing (or end()). + * + * This function will erase the elements in the range + * [__first,__last) and shorten the %deque accordingly. + * + * The user is cautioned that + * this function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) +#else + erase(iterator __first, iterator __last) +#endif + { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } + + /** + * @brief Swaps data with another %deque. + * @param __x A %deque of the same element and allocator types. + * + * This exchanges the elements between two deques in constant time. + * (Four pointers, so it should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(d1,d2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(deque& __x) _GLIBCXX_NOEXCEPT + { +#if __cplusplus >= 201103L + __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value + || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()); +#endif + _M_impl._M_swap_data(__x._M_impl); + _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + } + + /** + * Erases all the elements. Note that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_erase_at_end(begin()); } + + protected: + // Internal constructor functions follow. + +#if __cplusplus < 201103L + // called by the range constructor to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { + _M_initialize_map(_S_check_init_len(static_cast(__n), + _M_get_Tp_allocator())); + _M_fill_initialize(__x); + } + + // called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#endif + + static size_t + _S_check_init_len(size_t __n, const allocator_type& __a) + { + if (__n > _S_max_size(__a)) + __throw_length_error( + __N("cannot create std::deque larger than max_size()")); + return __n; + } + + static size_type + _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT + { + const size_t __diffmax = __gnu_cxx::__numeric_traits::__max; + const size_t __allocmax = _Alloc_traits::max_size(__a); + return (std::min)(__diffmax, __allocmax); + } + + // called by the second initialize_dispatch above + //@{ + /** + * @brief Fills the deque with whatever is in [first,last). + * @param __first An input iterator. + * @param __last An input iterator. + * @return Nothing. + * + * If the iterators are actually forward iterators (or better), then the + * memory layout can be done all at once. Else we move forward using + * push_back on each value from the iterator. + */ + template + void + _M_range_initialize(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag); + + // called by the second initialize_dispatch above + template + void + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag); + //@} + + /** + * @brief Fills the %deque with copies of value. + * @param __value Initial value. + * @return Nothing. + * @pre _M_start and _M_finish have already been initialized, + * but none of the %deque's elements have yet been constructed. + * + * This function is called only when the user provides an explicit size + * (with or without an explicit exemplar value). + */ + void + _M_fill_initialize(const value_type& __value); + +#if __cplusplus >= 201103L + // called by deque(n). + void + _M_default_initialize(); +#endif + + // Internal assign functions follow. The *_aux functions do the actual + // assignment work for the range versions. + +#if __cplusplus < 201103L + // called by the range assign to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + + // called by the range assign to implement [23.1.1]/9 + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#endif + + // called by the second assign_dispatch above + template + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag); + + // called by the second assign_dispatch above + template + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __len = std::distance(__first, __last); + if (__len > size()) + { + _ForwardIterator __mid = __first; + std::advance(__mid, size()); + std::copy(__first, __mid, begin()); + _M_range_insert_aux(end(), __mid, __last, + std::__iterator_category(__first)); + } + else + _M_erase_at_end(std::copy(__first, __last, begin())); + } + + // Called by assign(n,t), and the range assign when it turns out + // to be the same thing. + void + _M_fill_assign(size_type __n, const value_type& __val) + { + if (__n > size()) + { + std::fill(begin(), end(), __val); + _M_fill_insert(end(), __n - size(), __val); + } + else + { + _M_erase_at_end(begin() + difference_type(__n)); + std::fill(begin(), end(), __val); + } + } + + //@{ + /// Helper functions for push_* and pop_*. +#if __cplusplus < 201103L + void _M_push_back_aux(const value_type&); + + void _M_push_front_aux(const value_type&); +#else + template + void _M_push_back_aux(_Args&&... __args); + + template + void _M_push_front_aux(_Args&&... __args); +#endif + + void _M_pop_back_aux(); + + void _M_pop_front_aux(); + //@} + + // Internal insert functions follow. The *_aux functions do the actual + // insertion work when all shortcuts fail. + +#if __cplusplus < 201103L + // called by the range insert to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_insert_dispatch(iterator __pos, + _Integer __n, _Integer __x, __true_type) + { _M_fill_insert(__pos, __n, __x); } + + // called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) + { + _M_range_insert_aux(__pos, __first, __last, + std::__iterator_category(__first)); + } +#endif + + // called by the second insert_dispatch above + template + void + _M_range_insert_aux(iterator __pos, _InputIterator __first, + _InputIterator __last, std::input_iterator_tag); + + // called by the second insert_dispatch above + template + void + _M_range_insert_aux(iterator __pos, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag); + + // Called by insert(p,n,x), and the range insert when it turns out to be + // the same thing. Can use fill functions in optimal situations, + // otherwise passes off to insert_aux(p,n,x). + void + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); + + // called by insert(p,x) +#if __cplusplus < 201103L + iterator + _M_insert_aux(iterator __pos, const value_type& __x); +#else + template + iterator + _M_insert_aux(iterator __pos, _Args&&... __args); +#endif + + // called by insert(p,n,x) via fill_insert + void + _M_insert_aux(iterator __pos, size_type __n, const value_type& __x); + + // called by range_insert_aux for forward iterators + template + void + _M_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + size_type __n); + + + // Internal erase functions follow. + + void + _M_destroy_data_aux(iterator __first, iterator __last); + + // Called by ~deque(). + // NB: Doesn't deallocate the nodes. + template + void + _M_destroy_data(iterator __first, iterator __last, const _Alloc1&) + { _M_destroy_data_aux(__first, __last); } + + void + _M_destroy_data(iterator __first, iterator __last, + const std::allocator<_Tp>&) + { + if (!__has_trivial_destructor(value_type)) + _M_destroy_data_aux(__first, __last); + } + + // Called by erase(q1, q2). + void + _M_erase_at_begin(iterator __pos) + { + _M_destroy_data(begin(), __pos, _M_get_Tp_allocator()); + _M_destroy_nodes(this->_M_impl._M_start._M_node, __pos._M_node); + this->_M_impl._M_start = __pos; + } + + // Called by erase(q1, q2), resize(), clear(), _M_assign_aux, + // _M_fill_assign, operator=. + void + _M_erase_at_end(iterator __pos) + { + _M_destroy_data(__pos, end(), _M_get_Tp_allocator()); + _M_destroy_nodes(__pos._M_node + 1, + this->_M_impl._M_finish._M_node + 1); + this->_M_impl._M_finish = __pos; + } + + iterator + _M_erase(iterator __pos); + + iterator + _M_erase(iterator __first, iterator __last); + +#if __cplusplus >= 201103L + // Called by resize(sz). + void + _M_default_append(size_type __n); + + bool + _M_shrink_to_fit(); +#endif + + //@{ + /// Memory-handling helpers for the previous internal insert functions. + iterator + _M_reserve_elements_at_front(size_type __n) + { + const size_type __vacancies = this->_M_impl._M_start._M_cur + - this->_M_impl._M_start._M_first; + if (__n > __vacancies) + _M_new_elements_at_front(__n - __vacancies); + return this->_M_impl._M_start - difference_type(__n); + } + + iterator + _M_reserve_elements_at_back(size_type __n) + { + const size_type __vacancies = (this->_M_impl._M_finish._M_last + - this->_M_impl._M_finish._M_cur) - 1; + if (__n > __vacancies) + _M_new_elements_at_back(__n - __vacancies); + return this->_M_impl._M_finish + difference_type(__n); + } + + void + _M_new_elements_at_front(size_type __new_elements); + + void + _M_new_elements_at_back(size_type __new_elements); + //@} + + + //@{ + /** + * @brief Memory-handling helpers for the major %map. + * + * Makes sure the _M_map has space for new nodes. Does not + * actually add the nodes. Can invalidate _M_map pointers. + * (And consequently, %deque iterators.) + */ + void + _M_reserve_map_at_back(size_type __nodes_to_add = 1) + { + if (__nodes_to_add + 1 > this->_M_impl._M_map_size + - (this->_M_impl._M_finish._M_node - this->_M_impl._M_map)) + _M_reallocate_map(__nodes_to_add, false); + } + + void + _M_reserve_map_at_front(size_type __nodes_to_add = 1) + { + if (__nodes_to_add > size_type(this->_M_impl._M_start._M_node + - this->_M_impl._M_map)) + _M_reallocate_map(__nodes_to_add, true); + } + + void + _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front); + //@} + +#if __cplusplus >= 201103L + // Constant-time, nothrow move assignment when source object's memory + // can be moved because the allocators are equal. + void + _M_move_assign1(deque&& __x, /* always equal: */ true_type) noexcept + { + this->_M_impl._M_swap_data(__x._M_impl); + __x.clear(); + std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); + } + + // When the allocators are not equal the operation could throw, because + // we might need to allocate a new map for __x after moving from it + // or we might need to allocate new elements for *this. + void + _M_move_assign1(deque&& __x, /* always equal: */ false_type) + { + constexpr bool __move_storage = + _Alloc_traits::_S_propagate_on_move_assign(); + _M_move_assign2(std::move(__x), __bool_constant<__move_storage>()); + } + + // Destroy all elements and deallocate all memory, then replace + // with elements created from __args. + template + void + _M_replace_map(_Args&&... __args) + { + // Create new data first, so if allocation fails there are no effects. + deque __newobj(std::forward<_Args>(__args)...); + // Free existing storage using existing allocator. + clear(); + _M_deallocate_node(*begin()._M_node); // one node left after clear() + _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); + this->_M_impl._M_map = nullptr; + this->_M_impl._M_map_size = 0; + // Take ownership of replacement memory. + this->_M_impl._M_swap_data(__newobj._M_impl); + } + + // Do move assignment when the allocator propagates. + void + _M_move_assign2(deque&& __x, /* propagate: */ true_type) + { + // Make a copy of the original allocator state. + auto __alloc = __x._M_get_Tp_allocator(); + // The allocator propagates so storage can be moved from __x, + // leaving __x in a valid empty state with a moved-from allocator. + _M_replace_map(std::move(__x)); + // Move the corresponding allocator state too. + _M_get_Tp_allocator() = std::move(__alloc); + } + + // Do move assignment when it may not be possible to move source + // object's memory, resulting in a linear-time operation. + void + _M_move_assign2(deque&& __x, /* propagate: */ false_type) + { + if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator()) + { + // The allocators are equal so storage can be moved from __x, + // leaving __x in a valid empty state with its current allocator. + _M_replace_map(std::move(__x), __x.get_allocator()); + } + else + { + // The rvalue's allocator cannot be moved and is not equal, + // so we need to individually move each element. + _M_assign_aux(std::make_move_iterator(__x.begin()), + std::make_move_iterator(__x.end()), + std::random_access_iterator_tag()); + __x.clear(); + } + } +#endif + }; + +#if __cpp_deduction_guides >= 201606 + template::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + deque(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> deque<_ValT, _Allocator>; +#endif + + /** + * @brief Deque equality comparison. + * @param __x A %deque. + * @param __y A %deque of the same type as @a __x. + * @return True iff the size and elements of the deques are equal. + * + * This is an equivalence relation. It is linear in the size of the + * deques. Deques are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return __x.size() == __y.size() + && std::equal(__x.begin(), __x.end(), __y.begin()); } + +#if __cpp_lib_three_way_comparison + /** + * @brief Deque ordering relation. + * @param __x A `deque`. + * @param __y A `deque` of the same type as `__x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Tp> + operator<=>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + /** + * @brief Deque ordering relation. + * @param __x A %deque. + * @param __y A %deque of the same type as @a __x. + * @return True iff @a x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * deques. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } + + /// Based on operator== + template + inline bool + operator!=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::deque::swap(). + template + inline void + swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +#undef _GLIBCXX_DEQUE_BUF_SIZE + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus >= 201103L + // std::allocator is safe, but it is not the only allocator + // for which this is valid. + template + struct __is_bitwise_relocatable<_GLIBCXX_STD_C::deque<_Tp>> + : true_type { }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_DEQUE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_function.h b/resources/sources/avr-libstdcpp/include/bits/stl_function.h new file mode 100644 index 000000000..77f8ccb05 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_function.h @@ -0,0 +1,1395 @@ +// Functor implementations -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_function.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _STL_FUNCTION_H +#define _STL_FUNCTION_H 1 + +#if __cplusplus > 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // 20.3.1 base classes + /** @defgroup functors Function Objects + * @ingroup utilities + * + * Function objects, or @e functors, are objects with an @c operator() + * defined and accessible. They can be passed as arguments to algorithm + * templates and used in place of a function pointer. Not only is the + * resulting expressiveness of the library increased, but the generated + * code can be more efficient than what you might write by hand. When we + * refer to @a functors, then, generally we include function pointers in + * the description as well. + * + * Often, functors are only created as temporaries passed to algorithm + * calls, rather than being created as named variables. + * + * Two examples taken from the standard itself follow. To perform a + * by-element addition of two vectors @c a and @c b containing @c double, + * and put the result in @c a, use + * \code + * transform (a.begin(), a.end(), b.begin(), a.begin(), plus()); + * \endcode + * To negate every element in @c a, use + * \code + * transform(a.begin(), a.end(), a.begin(), negate()); + * \endcode + * The addition and negation functions will be inlined directly. + * + * The standard functors are derived from structs named @c unary_function + * and @c binary_function. These two classes contain nothing but typedefs, + * to aid in generic (template) programming. If you write your own + * functors, you might consider doing the same. + * + * @{ + */ + /** + * This is one of the @link functors functor base classes@endlink. + */ + template + struct unary_function + { + /// @c argument_type is the type of the argument + typedef _Arg argument_type; + + /// @c result_type is the return type + typedef _Result result_type; + }; + + /** + * This is one of the @link functors functor base classes@endlink. + */ + template + struct binary_function + { + /// @c first_argument_type is the type of the first argument + typedef _Arg1 first_argument_type; + + /// @c second_argument_type is the type of the second argument + typedef _Arg2 second_argument_type; + + /// @c result_type is the return type + typedef _Result result_type; + }; + /** @} */ + + // 20.3.2 arithmetic + /** @defgroup arithmetic_functors Arithmetic Classes + * @ingroup functors + * + * Because basic math often needs to be done during an algorithm, + * the library provides functors for those operations. See the + * documentation for @link functors the base classes@endlink + * for examples of their use. + * + * @{ + */ + +#if __cplusplus > 201103L + struct __is_transparent; // undefined + + template + struct plus; + + template + struct minus; + + template + struct multiplies; + + template + struct divides; + + template + struct modulus; + + template + struct negate; +#endif + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct plus : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x + __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct minus : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x - __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct multiplies : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x * __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct divides : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x / __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct modulus : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x % __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct negate : public unary_function<_Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x) const + { return -__x; } + }; + +#if __cplusplus > 201103L + +#define __cpp_lib_transparent_operators 201510 + + template<> + struct plus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) + std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) + std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) + std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct minus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) - std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) - std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) - std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct multiplies + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) * std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) * std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) * std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct divides + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) / std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) / std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) / std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct modulus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) % std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) % std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) % std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct negate + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(-std::forward<_Tp>(__t))) + -> decltype(-std::forward<_Tp>(__t)) + { return -std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif + /** @} */ + + // 20.3.3 comparisons + /** @defgroup comparison_functors Comparison Classes + * @ingroup functors + * + * The library provides six wrapper functors for all the basic comparisons + * in C++, like @c <. + * + * @{ + */ +#if __cplusplus > 201103L + template + struct equal_to; + + template + struct not_equal_to; + + template + struct greater; + + template + struct less; + + template + struct greater_equal; + + template + struct less_equal; +#endif + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct equal_to : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x == __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct not_equal_to : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x != __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct greater : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x > __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct less : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x < __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct greater_equal : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x >= __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct less_equal : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x <= __y; } + }; + + // Partial specialization of std::greater for pointers. + template + struct greater<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) +#else + if (__builtin_constant_p(__x > __y)) +#endif + return __x > __y; +#endif + return (__UINTPTR_TYPE__)__x > (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::less for pointers. + template + struct less<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) +#else + if (__builtin_constant_p(__x < __y)) +#endif + return __x < __y; +#endif + return (__UINTPTR_TYPE__)__x < (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::greater_equal for pointers. + template + struct greater_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) +#else + if (__builtin_constant_p(__x >= __y)) +#endif + return __x >= __y; +#endif + return (__UINTPTR_TYPE__)__x >= (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::less_equal for pointers. + template + struct less_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) +#else + if (__builtin_constant_p(__x <= __y)) +#endif + return __x <= __y; +#endif + return (__UINTPTR_TYPE__)__x <= (__UINTPTR_TYPE__)__y; + } + }; + +#if __cplusplus >= 201402L + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct equal_to + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) == std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) == std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct not_equal_to + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) != std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) != std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) != std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct greater + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) > std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) > std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return greater>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) > std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return greater{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator> member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator>(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator>(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator> for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator>(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator>(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct less + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) < std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) < std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return less>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) < std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return less{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator< member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator<(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator<(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator< for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator<(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator<(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct greater_equal + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) >= std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) >= std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return greater_equal>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) >= std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return greater_equal{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator>= member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator>=(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator>=(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator>= for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator>=(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator>=(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct less_equal + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) <= std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) <= std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return less_equal>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) <= std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return less_equal{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator<= member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator<=(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator<=(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator<= for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator<=(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator<=(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; +#endif // C++14 + /** @} */ + + // 20.3.4 logical operations + /** @defgroup logical_functors Boolean Operations Classes + * @ingroup functors + * + * Here are wrapper functors for Boolean operations: @c &&, @c ||, + * and @c !. + * + * @{ + */ +#if __cplusplus > 201103L + template + struct logical_and; + + template + struct logical_or; + + template + struct logical_not; +#endif + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_and : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x && __y; } + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_or : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x || __y; } + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_not : public unary_function<_Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x) const + { return !__x; } + }; + +#if __cplusplus > 201103L + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_and + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) && std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) && std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) && std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_or + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) || std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) || std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) || std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_not + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(!std::forward<_Tp>(__t))) + -> decltype(!std::forward<_Tp>(__t)) + { return !std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif + /** @} */ + +#if __cplusplus > 201103L + template + struct bit_and; + + template + struct bit_or; + + template + struct bit_xor; + + template + struct bit_not; +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 660. Missing Bitwise Operations. + template + struct bit_and : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x & __y; } + }; + + template + struct bit_or : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x | __y; } + }; + + template + struct bit_xor : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x ^ __y; } + }; + + template + struct bit_not : public unary_function<_Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x) const + { return ~__x; } + }; + +#if __cplusplus > 201103L + template <> + struct bit_and + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) & std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) & std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) & std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_or + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) | std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) | std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) | std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_xor + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) ^ std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_not + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(~std::forward<_Tp>(__t))) + -> decltype(~std::forward<_Tp>(__t)) + { return ~std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif + + // 20.3.5 negators + /** @defgroup negators Negators + * @ingroup functors + * + * The functions @c not1 and @c not2 each take a predicate functor + * and return an instance of @c unary_negate or + * @c binary_negate, respectively. These classes are functors whose + * @c operator() performs the stored predicate function and then returns + * the negation of the result. + * + * For example, given a vector of integers and a trivial predicate, + * \code + * struct IntGreaterThanThree + * : public std::unary_function + * { + * bool operator() (int x) { return x > 3; } + * }; + * + * std::find_if (v.begin(), v.end(), not1(IntGreaterThanThree())); + * \endcode + * The call to @c find_if will locate the first index (i) of @c v for which + * !(v[i] > 3) is true. + * + * The not1/unary_negate combination works on predicates taking a single + * argument. The not2/binary_negate combination works on predicates which + * take two arguments. + * + * @{ + */ + /// One of the @link negators negation functors@endlink. + template + class unary_negate + : public unary_function + { + protected: + _Predicate _M_pred; + + public: + _GLIBCXX14_CONSTEXPR + explicit + unary_negate(const _Predicate& __x) : _M_pred(__x) { } + + _GLIBCXX14_CONSTEXPR + bool + operator()(const typename _Predicate::argument_type& __x) const + { return !_M_pred(__x); } + }; + + /// One of the @link negators negation functors@endlink. + template + _GLIBCXX14_CONSTEXPR + inline unary_negate<_Predicate> + not1(const _Predicate& __pred) + { return unary_negate<_Predicate>(__pred); } + + /// One of the @link negators negation functors@endlink. + template + class binary_negate + : public binary_function + { + protected: + _Predicate _M_pred; + + public: + _GLIBCXX14_CONSTEXPR + explicit + binary_negate(const _Predicate& __x) : _M_pred(__x) { } + + _GLIBCXX14_CONSTEXPR + bool + operator()(const typename _Predicate::first_argument_type& __x, + const typename _Predicate::second_argument_type& __y) const + { return !_M_pred(__x, __y); } + }; + + /// One of the @link negators negation functors@endlink. + template + _GLIBCXX14_CONSTEXPR + inline binary_negate<_Predicate> + not2(const _Predicate& __pred) + { return binary_negate<_Predicate>(__pred); } + /** @} */ + + // 20.3.7 adaptors pointers functions + /** @defgroup pointer_adaptors Adaptors for pointers to functions + * @ingroup functors + * + * The advantage of function objects over pointers to functions is that + * the objects in the standard library declare nested typedefs describing + * their argument and result types with uniform names (e.g., @c result_type + * from the base classes @c unary_function and @c binary_function). + * Sometimes those typedefs are required, not just optional. + * + * Adaptors are provided to turn pointers to unary (single-argument) and + * binary (double-argument) functions into function objects. The + * long-winded functor @c pointer_to_unary_function is constructed with a + * function pointer @c f, and its @c operator() called with argument @c x + * returns @c f(x). The functor @c pointer_to_binary_function does the same + * thing, but with a double-argument @c f and @c operator(). + * + * The function @c ptr_fun takes a pointer-to-function @c f and constructs + * an instance of the appropriate functor. + * + * @{ + */ + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + class pointer_to_unary_function : public unary_function<_Arg, _Result> + { + protected: + _Result (*_M_ptr)(_Arg); + + public: + pointer_to_unary_function() { } + + explicit + pointer_to_unary_function(_Result (*__x)(_Arg)) + : _M_ptr(__x) { } + + _Result + operator()(_Arg __x) const + { return _M_ptr(__x); } + }; + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + inline pointer_to_unary_function<_Arg, _Result> + ptr_fun(_Result (*__x)(_Arg)) + { return pointer_to_unary_function<_Arg, _Result>(__x); } + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + class pointer_to_binary_function + : public binary_function<_Arg1, _Arg2, _Result> + { + protected: + _Result (*_M_ptr)(_Arg1, _Arg2); + + public: + pointer_to_binary_function() { } + + explicit + pointer_to_binary_function(_Result (*__x)(_Arg1, _Arg2)) + : _M_ptr(__x) { } + + _Result + operator()(_Arg1 __x, _Arg2 __y) const + { return _M_ptr(__x, __y); } + }; + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + inline pointer_to_binary_function<_Arg1, _Arg2, _Result> + ptr_fun(_Result (*__x)(_Arg1, _Arg2)) + { return pointer_to_binary_function<_Arg1, _Arg2, _Result>(__x); } + /** @} */ + + template + struct _Identity + : public unary_function<_Tp, _Tp> + { + _Tp& + operator()(_Tp& __x) const + { return __x; } + + const _Tp& + operator()(const _Tp& __x) const + { return __x; } + }; + + // Partial specialization, avoids confusing errors in e.g. std::set. + template struct _Identity : _Identity<_Tp> { }; + + template + struct _Select1st + : public unary_function<_Pair, typename _Pair::first_type> + { + typename _Pair::first_type& + operator()(_Pair& __x) const + { return __x.first; } + + const typename _Pair::first_type& + operator()(const _Pair& __x) const + { return __x.first; } + +#if __cplusplus >= 201103L + template + typename _Pair2::first_type& + operator()(_Pair2& __x) const + { return __x.first; } + + template + const typename _Pair2::first_type& + operator()(const _Pair2& __x) const + { return __x.first; } +#endif + }; + + template + struct _Select2nd + : public unary_function<_Pair, typename _Pair::second_type> + { + typename _Pair::second_type& + operator()(_Pair& __x) const + { return __x.second; } + + const typename _Pair::second_type& + operator()(const _Pair& __x) const + { return __x.second; } + }; + + // 20.3.8 adaptors pointers members + /** @defgroup memory_adaptors Adaptors for pointers to members + * @ingroup functors + * + * There are a total of 8 = 2^3 function objects in this family. + * (1) Member functions taking no arguments vs member functions taking + * one argument. + * (2) Call through pointer vs call through reference. + * (3) Const vs non-const member function. + * + * All of this complexity is in the function objects themselves. You can + * ignore it by using the helper function mem_fun and mem_fun_ref, + * which create whichever type of adaptor is appropriate. + * + * @{ + */ + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class mem_fun_t : public unary_function<_Tp*, _Ret> + { + public: + explicit + mem_fun_t(_Ret (_Tp::*__pf)()) + : _M_f(__pf) { } + + _Ret + operator()(_Tp* __p) const + { return (__p->*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)(); + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class const_mem_fun_t : public unary_function + { + public: + explicit + const_mem_fun_t(_Ret (_Tp::*__pf)() const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp* __p) const + { return (__p->*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)() const; + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class mem_fun_ref_t : public unary_function<_Tp, _Ret> + { + public: + explicit + mem_fun_ref_t(_Ret (_Tp::*__pf)()) + : _M_f(__pf) { } + + _Ret + operator()(_Tp& __r) const + { return (__r.*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)(); + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class const_mem_fun_ref_t : public unary_function<_Tp, _Ret> + { + public: + explicit + const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp& __r) const + { return (__r.*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)() const; + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class mem_fun1_t : public binary_function<_Tp*, _Arg, _Ret> + { + public: + explicit + mem_fun1_t(_Ret (_Tp::*__pf)(_Arg)) + : _M_f(__pf) { } + + _Ret + operator()(_Tp* __p, _Arg __x) const + { return (__p->*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg); + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class const_mem_fun1_t : public binary_function + { + public: + explicit + const_mem_fun1_t(_Ret (_Tp::*__pf)(_Arg) const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp* __p, _Arg __x) const + { return (__p->*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg) const; + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class mem_fun1_ref_t : public binary_function<_Tp, _Arg, _Ret> + { + public: + explicit + mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg)) + : _M_f(__pf) { } + + _Ret + operator()(_Tp& __r, _Arg __x) const + { return (__r.*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg); + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class const_mem_fun1_ref_t : public binary_function<_Tp, _Arg, _Ret> + { + public: + explicit + const_mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg) const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp& __r, _Arg __x) const + { return (__r.*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg) const; + }; + + // Mem_fun adaptor helper functions. There are only two: + // mem_fun and mem_fun_ref. + template + inline mem_fun_t<_Ret, _Tp> + mem_fun(_Ret (_Tp::*__f)()) + { return mem_fun_t<_Ret, _Tp>(__f); } + + template + inline const_mem_fun_t<_Ret, _Tp> + mem_fun(_Ret (_Tp::*__f)() const) + { return const_mem_fun_t<_Ret, _Tp>(__f); } + + template + inline mem_fun_ref_t<_Ret, _Tp> + mem_fun_ref(_Ret (_Tp::*__f)()) + { return mem_fun_ref_t<_Ret, _Tp>(__f); } + + template + inline const_mem_fun_ref_t<_Ret, _Tp> + mem_fun_ref(_Ret (_Tp::*__f)() const) + { return const_mem_fun_ref_t<_Ret, _Tp>(__f); } + + template + inline mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun(_Ret (_Tp::*__f)(_Arg)) + { return mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + inline const_mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun(_Ret (_Tp::*__f)(_Arg) const) + { return const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + inline mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun_ref(_Ret (_Tp::*__f)(_Arg)) + { return mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + + template + inline const_mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun_ref(_Ret (_Tp::*__f)(_Arg) const) + { return const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + + /** @} */ + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if (__cplusplus < 201103L) || _GLIBCXX_USE_DEPRECATED +# include +#endif + +#endif /* _STL_FUNCTION_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_heap.h b/resources/sources/avr-libstdcpp/include/bits/stl_heap.h new file mode 100644 index 000000000..52e3a3b44 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_heap.h @@ -0,0 +1,583 @@ +// Heap implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_heap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{queue} + */ + +#ifndef _STL_HEAP_H +#define _STL_HEAP_H 1 + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup heap_algorithms Heap + * @ingroup sorting_algorithms + */ + + template + _GLIBCXX20_CONSTEXPR + _Distance + __is_heap_until(_RandomAccessIterator __first, _Distance __n, + _Compare& __comp) + { + _Distance __parent = 0; + for (_Distance __child = 1; __child < __n; ++__child) + { + if (__comp(__first + __parent, __first + __child)) + return __child; + if ((__child & 1) == 0) + ++__parent; + } + return __n; + } + + // __is_heap, a predicate testing whether or not a range is a heap. + // This function is an extension, not part of the C++ standard. + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _Distance __n) + { + __gnu_cxx::__ops::_Iter_less_iter __comp; + return std::__is_heap_until(__first, __n, __comp) == __n; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n) + { + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __n, __cmp) == __n; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { return std::__is_heap(__first, std::distance(__first, __last)); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + return std::__is_heap(__first, _GLIBCXX_MOVE(__comp), + std::distance(__first, __last)); + } + + // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap, + // + is_heap and is_heap_until in C++0x. + + template + _GLIBCXX20_CONSTEXPR + void + __push_heap(_RandomAccessIterator __first, + _Distance __holeIndex, _Distance __topIndex, _Tp __value, + _Compare& __comp) + { + _Distance __parent = (__holeIndex - 1) / 2; + while (__holeIndex > __topIndex && __comp(__first + __parent, __value)) + { + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent)); + __holeIndex = __parent; + __parent = (__holeIndex - 1) / 2; + } + *(__first + __holeIndex) = _GLIBCXX_MOVE(__value); + } + + /** + * @brief Push an element onto a heap. + * @param __first Start of heap. + * @param __last End of heap + element. + * @ingroup heap_algorithms + * + * This operation pushes the element at last-1 onto the valid heap + * over the range [__first,__last-1). After completion, + * [__first,__last) is a valid heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last - 1); + + __gnu_cxx::__ops::_Iter_less_val __comp; + _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); + std::__push_heap(__first, _DistanceType((__last - __first) - 1), + _DistanceType(0), _GLIBCXX_MOVE(__value), __comp); + } + + /** + * @brief Push an element onto a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap + element. + * @param __comp Comparison functor. + * @ingroup heap_algorithms + * + * This operation pushes the element at __last-1 onto the valid + * heap over the range [__first,__last-1). After completion, + * [__first,__last) is a valid heap. Compare operations are + * performed using comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_heap_pred(__first, __last - 1, __comp); + + __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) + __cmp(_GLIBCXX_MOVE(__comp)); + _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); + std::__push_heap(__first, _DistanceType((__last - __first) - 1), + _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, + _Distance __len, _Tp __value, _Compare __comp) + { + const _Distance __topIndex = __holeIndex; + _Distance __secondChild = __holeIndex; + while (__secondChild < (__len - 1) / 2) + { + __secondChild = 2 * (__secondChild + 1); + if (__comp(__first + __secondChild, + __first + (__secondChild - 1))) + __secondChild--; + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild)); + __holeIndex = __secondChild; + } + if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2) + { + __secondChild = 2 * (__secondChild + 1); + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + + (__secondChild - 1))); + __holeIndex = __secondChild - 1; + } + __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) + __cmp(_GLIBCXX_MOVE(__comp)); + std::__push_heap(__first, __holeIndex, __topIndex, + _GLIBCXX_MOVE(__value), __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _RandomAccessIterator __result, _Compare& __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + _ValueType __value = _GLIBCXX_MOVE(*__result); + *__result = _GLIBCXX_MOVE(*__first); + std::__adjust_heap(__first, _DistanceType(0), + _DistanceType(__last - __first), + _GLIBCXX_MOVE(__value), __comp); + } + + /** + * @brief Pop an element off a heap. + * @param __first Start of heap. + * @param __last End of heap. + * @pre [__first, __last) is a valid, non-empty range. + * @ingroup heap_algorithms + * + * This operation pops the top of the heap. The elements __first + * and __last-1 are swapped and [__first,__last-1) is made into a + * heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_non_empty_range(__first, __last); + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last); + + if (__last - __first > 1) + { + --__last; + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__pop_heap(__first, __last, __last, __comp); + } + } + + /** + * @brief Pop an element off a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation pops the top of the heap. The elements __first + * and __last-1 are swapped and [__first,__last-1) is made into a + * heap. Comparisons are made using comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + pop_heap(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_non_empty_range(__first, __last); + __glibcxx_requires_heap_pred(__first, __last, __comp); + + if (__last - __first > 1) + { + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + --__last; + std::__pop_heap(__first, __last, __last, __cmp); + } + } + + template + _GLIBCXX20_CONSTEXPR + void + __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare& __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + if (__last - __first < 2) + return; + + const _DistanceType __len = __last - __first; + _DistanceType __parent = (__len - 2) / 2; + while (true) + { + _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent)); + std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value), + __comp); + if (__parent == 0) + return; + __parent--; + } + } + + /** + * @brief Construct a heap over a range. + * @param __first Start of heap. + * @param __last End of heap. + * @ingroup heap_algorithms + * + * This operation makes the elements in [__first,__last) into a heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__make_heap(__first, __last, __comp); + } + + /** + * @brief Construct a heap over a range using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation makes the elements in [__first,__last) into a heap. + * Comparisons are made using __comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + std::__make_heap(__first, __last, __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare& __comp) + { + while (__last - __first > 1) + { + --__last; + std::__pop_heap(__first, __last, __last, __comp); + } + } + + /** + * @brief Sort a heap. + * @param __first Start of heap. + * @param __last End of heap. + * @ingroup heap_algorithms + * + * This operation sorts the valid heap in the range [__first,__last). + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__sort_heap(__first, __last, __comp); + } + + /** + * @brief Sort a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation sorts the valid heap in the range [__first,__last). + * Comparisons are made using __comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_heap_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + std::__sort_heap(__first, __last, __cmp); + } + +#if __cplusplus >= 201103L + /** + * @brief Search the end of a heap. + * @param __first Start of range. + * @param __last End of range. + * @return An iterator pointing to the first element not in the heap. + * @ingroup heap_algorithms + * + * This operation returns the last iterator i in [__first, __last) for which + * the range [__first, i) is a heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + return __first + + std::__is_heap_until(__first, std::distance(__first, __last), __comp); + } + + /** + * @brief Search the end of a heap using comparison functor. + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor to use. + * @return An iterator pointing to the first element not in the heap. + * @ingroup heap_algorithms + * + * This operation returns the last iterator i in [__first, __last) for which + * the range [__first, i) is a heap. Comparisons are made using __comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return __first + + std::__is_heap_until(__first, std::distance(__first, __last), __cmp); + } + + /** + * @brief Determines whether a range is a heap. + * @param __first Start of range. + * @param __last End of range. + * @return True if range is a heap, false otherwise. + * @ingroup heap_algorithms + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { return std::is_heap_until(__first, __last) == __last; } + + /** + * @brief Determines whether a range is a heap using comparison functor. + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor to use. + * @return True if range is a heap, false otherwise. + * @ingroup heap_algorithms + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + const auto __dist = std::distance(__first, __last); + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __dist, __cmp) == __dist; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_HEAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h new file mode 100644 index 000000000..7d293ce3f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h @@ -0,0 +1,2238 @@ +// Iterators -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file implements reverse_iterator, back_insert_iterator, + * front_insert_iterator, insert_iterator, __normal_iterator, and their + * supporting functions and overloaded operators. + */ + +#ifndef _STL_ITERATOR_H +#define _STL_ITERATOR_H 1 + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +# include +#endif + +#if __cplusplus > 201703L +# define __cpp_lib_array_constexpr 201811L +# define __cpp_lib_constexpr_iterator 201811L +#elif __cplusplus == 201703L +# define __cpp_lib_array_constexpr 201803L +#endif + +#if __cplusplus > 201703L +# include +# include +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup iterators + * @{ + */ + +#if __cplusplus > 201703L && __cpp_lib_concepts + namespace __detail + { + // Weaken iterator_category _Cat to _Limit if it is derived from that, + // otherwise use _Otherwise. + template + using __clamp_iter_cat + = conditional_t, _Limit, _Otherwise>; + } +#endif + + // 24.4.1 Reverse iterators + /** + * Bidirectional and random access iterators have corresponding reverse + * %iterator adaptors that iterate through the data structure in the + * opposite direction. They have the same signatures as the corresponding + * iterators. The fundamental relation between a reverse %iterator and its + * corresponding %iterator @c i is established by the identity: + * @code + * &*(reverse_iterator(i)) == &*(i - 1) + * @endcode + * + * This mapping is dictated by the fact that while there is always a + * pointer past the end of an array, there might not be a valid pointer + * before the beginning of an array. [24.4.1]/1,2 + * + * Reverse iterators can be tricky and surprising at first. Their + * semantics make sense, however, and the trickiness is a side effect of + * the requirement that the iterators must be safe. + */ + template + class reverse_iterator + : public iterator::iterator_category, + typename iterator_traits<_Iterator>::value_type, + typename iterator_traits<_Iterator>::difference_type, + typename iterator_traits<_Iterator>::pointer, + typename iterator_traits<_Iterator>::reference> + { + protected: + _Iterator current; + + typedef iterator_traits<_Iterator> __traits_type; + + public: + typedef _Iterator iterator_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::pointer pointer; + typedef typename __traits_type::reference reference; + +#if __cplusplus > 201703L && __cpp_lib_concepts + using iterator_concept + = conditional_t, + random_access_iterator_tag, + bidirectional_iterator_tag>; + using iterator_category + = __detail::__clamp_iter_cat; +#endif + + /** + * The default constructor value-initializes member @p current. + * If it is a pointer, that means it is zero-initialized. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 235 No specification of default ctor for reverse_iterator + // 1012. reverse_iterator default ctor should value initialize + _GLIBCXX17_CONSTEXPR + reverse_iterator() : current() { } + + /** + * This %iterator will move in the opposite direction that @p x does. + */ + explicit _GLIBCXX17_CONSTEXPR + reverse_iterator(iterator_type __x) : current(__x) { } + + /** + * The copy constructor is normal. + */ + _GLIBCXX17_CONSTEXPR + reverse_iterator(const reverse_iterator& __x) + : current(__x.current) { } + +#if __cplusplus >= 201103L + reverse_iterator& operator=(const reverse_iterator&) = default; +#endif + + /** + * A %reverse_iterator across other types can be copied if the + * underlying %iterator can be converted to the type of @c current. + */ + template + _GLIBCXX17_CONSTEXPR + reverse_iterator(const reverse_iterator<_Iter>& __x) + : current(__x.base()) { } + + /** + * @return @c current, the %iterator used for underlying work. + */ + _GLIBCXX17_CONSTEXPR iterator_type + base() const + { return current; } + + /** + * @return A reference to the value at @c --current + * + * This requires that @c --current is dereferenceable. + * + * @warning This implementation requires that for an iterator of the + * underlying iterator type, @c x, a reference obtained by + * @c *x remains valid after @c x has been modified or + * destroyed. This is a bug: http://gcc.gnu.org/PR51823 + */ + _GLIBCXX17_CONSTEXPR reference + operator*() const + { + _Iterator __tmp = current; + return *--__tmp; + } + + /** + * @return A pointer to the value at @c --current + * + * This requires that @c --current is dereferenceable. + */ + _GLIBCXX17_CONSTEXPR pointer + operator->() const +#if __cplusplus > 201703L && __cpp_concepts >= 201907L + requires is_pointer_v<_Iterator> + || requires(const _Iterator __i) { __i.operator->(); } +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 1052. operator-> should also support smart pointers + _Iterator __tmp = current; + --__tmp; + return _S_to_pointer(__tmp); + } + + /** + * @return @c *this + * + * Decrements the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator++() + { + --current; + return *this; + } + + /** + * @return The original value of @c *this + * + * Decrements the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator++(int) + { + reverse_iterator __tmp = *this; + --current; + return __tmp; + } + + /** + * @return @c *this + * + * Increments the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator--() + { + ++current; + return *this; + } + + /** + * @return A reverse_iterator with the previous value of @c *this + * + * Increments the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator--(int) + { + reverse_iterator __tmp = *this; + ++current; + return __tmp; + } + + /** + * @return A reverse_iterator that refers to @c current - @a __n + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator+(difference_type __n) const + { return reverse_iterator(current - __n); } + + /** + * @return *this + * + * Moves the underlying iterator backwards @a __n steps. + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator+=(difference_type __n) + { + current -= __n; + return *this; + } + + /** + * @return A reverse_iterator that refers to @c current - @a __n + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator-(difference_type __n) const + { return reverse_iterator(current + __n); } + + /** + * @return *this + * + * Moves the underlying iterator forwards @a __n steps. + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator-=(difference_type __n) + { + current += __n; + return *this; + } + + /** + * @return The value at @c current - @a __n - 1 + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reference + operator[](difference_type __n) const + { return *(*this + __n); } + +#if __cplusplus > 201703L && __cpp_lib_concepts + friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const reverse_iterator& __i) + noexcept(is_nothrow_copy_constructible_v<_Iterator> + && noexcept(ranges::iter_move(--std::declval<_Iterator&>()))) + { + auto __tmp = __i.base(); + return ranges::iter_move(--__tmp); + } + + template _Iter2> + friend constexpr void + iter_swap(const reverse_iterator& __x, + const reverse_iterator<_Iter2>& __y) + noexcept(is_nothrow_copy_constructible_v<_Iterator> + && is_nothrow_copy_constructible_v<_Iter2> + && noexcept(ranges::iter_swap(--std::declval<_Iterator&>(), + --std::declval<_Iter2&>()))) + { + auto __xtmp = __x.base(); + auto __ytmp = __y.base(); + ranges::iter_swap(--__xtmp, --__ytmp); + } +#endif + + private: + template + static _GLIBCXX17_CONSTEXPR _Tp* + _S_to_pointer(_Tp* __p) + { return __p; } + + template + static _GLIBCXX17_CONSTEXPR pointer + _S_to_pointer(_Tp __t) + { return __t.operator->(); } + }; + + //@{ + /** + * @param __x A %reverse_iterator. + * @param __y A %reverse_iterator. + * @return A simple bool. + * + * Reverse iterators forward comparisons to their underlying base() + * iterators. + * + */ +#if __cplusplus <= 201703L || ! defined __cpp_lib_concepts + template + inline _GLIBCXX17_CONSTEXPR bool + operator==(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __x.base() == __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() < __x.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x == __y); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y < __x; } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__y < __x); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x < __y); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 280. Comparison of reverse_iterator to const reverse_iterator. + template + inline _GLIBCXX17_CONSTEXPR bool + operator==(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() == __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() < __x.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__x == __y); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y < __x; } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__y < __x); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__x < __y); } +#else // C++20 + template + constexpr bool + operator==(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() == __y.base() } -> convertible_to; } + { return __x.base() == __y.base(); } + + template + constexpr bool + operator!=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() != __y.base() } -> convertible_to; } + { return __x.base() != __y.base(); } + + template + constexpr bool + operator<(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() > __y.base() } -> convertible_to; } + { return __x.base() > __y.base(); } + + template + constexpr bool + operator>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() < __y.base() } -> convertible_to; } + { return __x.base() < __y.base(); } + + template + constexpr bool + operator<=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() >= __y.base() } -> convertible_to; } + { return __x.base() >= __y.base(); } + + template + constexpr bool + operator>=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() <= __y.base() } -> convertible_to; } + { return __x.base() <= __y.base(); } + + template _IteratorR> + constexpr compare_three_way_result_t<_IteratorL, _IteratorR> + operator<=>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() <=> __x.base(); } +#endif // C++20 + //@} + +#if __cplusplus < 201103L + template + inline typename reverse_iterator<_Iterator>::difference_type + operator-(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() - __x.base(); } + + template + inline typename reverse_iterator<_IteratorL>::difference_type + operator-(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() - __x.base(); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 685. reverse_iterator/move_iterator difference has invalid signatures + template + inline _GLIBCXX17_CONSTEXPR auto + operator-(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + -> decltype(__y.base() - __x.base()) + { return __y.base() - __x.base(); } +#endif + + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + operator+(typename reverse_iterator<_Iterator>::difference_type __n, + const reverse_iterator<_Iterator>& __x) + { return reverse_iterator<_Iterator>(__x.base() - __n); } + +#if __cplusplus >= 201103L + // Same as C++14 make_reverse_iterator but used in C++11 mode too. + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + __make_reverse_iterator(_Iterator __i) + { return reverse_iterator<_Iterator>(__i); } + +# if __cplusplus >= 201402L +# define __cpp_lib_make_reverse_iterator 201402 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 2285. make_reverse_iterator + /// Generator function for reverse_iterator. + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + make_reverse_iterator(_Iterator __i) + { return reverse_iterator<_Iterator>(__i); } + +# if __cplusplus > 201703L && defined __cpp_lib_concepts + template + requires (!sized_sentinel_for<_Iterator1, _Iterator2>) + inline constexpr bool + disable_sized_sentinel_for, + reverse_iterator<_Iterator2>> = true; +# endif // C++20 +# endif // C++14 + + template + _GLIBCXX20_CONSTEXPR + auto + __niter_base(reverse_iterator<_Iterator> __it) + -> decltype(__make_reverse_iterator(__niter_base(__it.base()))) + { return __make_reverse_iterator(__niter_base(__it.base())); } + + template + struct __is_move_iterator > + : __is_move_iterator<_Iterator> + { }; + + template + _GLIBCXX20_CONSTEXPR + auto + __miter_base(reverse_iterator<_Iterator> __it) + -> decltype(__make_reverse_iterator(__miter_base(__it.base()))) + { return __make_reverse_iterator(__miter_base(__it.base())); } +#endif // C++11 + + // 24.4.2.2.1 back_insert_iterator + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator appends it to the container using + * push_back. + * + * Tip: Using the back_inserter function to create these iterators can + * save typing. + */ + template + class back_insert_iterator + : public iterator + { + protected: + _Container* container; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; + + constexpr back_insert_iterator() noexcept : container(nullptr) { } +#endif + + /// The only way to create this %iterator is with a container. + explicit _GLIBCXX20_CONSTEXPR + back_insert_iterator(_Container& __x) + : container(std::__addressof(__x)) { } + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator doesn't really have a @a position in the + * container (you can think of the position as being permanently at + * the end, if you like). Assigning a value to the %iterator will + * always append the value to the end of the container. + */ +#if __cplusplus < 201103L + back_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_back(__value); + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator=(const typename _Container::value_type& __value) + { + container->push_back(__value); + return *this; + } + + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator=(typename _Container::value_type&& __value) + { + container->push_back(std::move(__value)); + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + back_insert_iterator + operator++(int) + { return *this; } + }; + + /** + * @param __x A container of arbitrary type. + * @return An instance of back_insert_iterator working on @p __x. + * + * This wrapper function helps in creating back_insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template + _GLIBCXX20_CONSTEXPR + inline back_insert_iterator<_Container> + back_inserter(_Container& __x) + { return back_insert_iterator<_Container>(__x); } + + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator prepends it to the container using + * push_front. + * + * Tip: Using the front_inserter function to create these iterators can + * save typing. + */ + template + class front_insert_iterator + : public iterator + { + protected: + _Container* container; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; + + constexpr front_insert_iterator() noexcept : container(nullptr) { } +#endif + + /// The only way to create this %iterator is with a container. + explicit _GLIBCXX20_CONSTEXPR + front_insert_iterator(_Container& __x) + : container(std::__addressof(__x)) { } + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator doesn't really have a @a position in the + * container (you can think of the position as being permanently at + * the front, if you like). Assigning a value to the %iterator will + * always prepend the value to the front of the container. + */ +#if __cplusplus < 201103L + front_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_front(__value); + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator=(const typename _Container::value_type& __value) + { + container->push_front(__value); + return *this; + } + + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator=(typename _Container::value_type&& __value) + { + container->push_front(std::move(__value)); + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + front_insert_iterator + operator++(int) + { return *this; } + }; + + /** + * @param __x A container of arbitrary type. + * @return An instance of front_insert_iterator working on @p x. + * + * This wrapper function helps in creating front_insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template + _GLIBCXX20_CONSTEXPR + inline front_insert_iterator<_Container> + front_inserter(_Container& __x) + { return front_insert_iterator<_Container>(__x); } + + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator inserts it in the container at the + * %iterator's position, rather than overwriting the value at that + * position. + * + * (Sequences will actually insert a @e copy of the value before the + * %iterator's position.) + * + * Tip: Using the inserter function to create these iterators can + * save typing. + */ + template + class insert_iterator + : public iterator + { +#if __cplusplus > 201703L && defined __cpp_lib_concepts + using _Iter = std::__detail::__range_iter_t<_Container>; + + protected: + _Container* container = nullptr; + _Iter iter = _Iter(); +#else + typedef typename _Container::iterator _Iter; + + protected: + _Container* container; + _Iter iter; +#endif + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; + +#if __cplusplus > 201703L && defined __cpp_lib_concepts + using difference_type = ptrdiff_t; + + insert_iterator() = default; +#endif + + /** + * The only way to create this %iterator is with a container and an + * initial position (a normal %iterator into the container). + */ + _GLIBCXX20_CONSTEXPR + insert_iterator(_Container& __x, _Iter __i) + : container(std::__addressof(__x)), iter(__i) {} + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator maintains its own position in the + * container. Assigning a value to the %iterator will insert the + * value into the container at the place before the %iterator. + * + * The position is maintained such that subsequent assignments will + * insert values immediately after one another. For example, + * @code + * // vector v contains A and Z + * + * insert_iterator i (v, ++v.begin()); + * i = 1; + * i = 2; + * i = 3; + * + * // vector v contains A, 1, 2, 3, and Z + * @endcode + */ +#if __cplusplus < 201103L + insert_iterator& + operator=(typename _Container::const_reference __value) + { + iter = container->insert(iter, __value); + ++iter; + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator=(const typename _Container::value_type& __value) + { + iter = container->insert(iter, __value); + ++iter; + return *this; + } + + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator=(typename _Container::value_type&& __value) + { + iter = container->insert(iter, std::move(__value)); + ++iter; + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator++(int) + { return *this; } + }; + + /** + * @param __x A container of arbitrary type. + * @param __i An iterator into the container. + * @return An instance of insert_iterator working on @p __x. + * + * This wrapper function helps in creating insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ +#if __cplusplus > 201703L && defined __cpp_lib_concepts + template + constexpr insert_iterator<_Container> + inserter(_Container& __x, std::__detail::__range_iter_t<_Container> __i) + { return insert_iterator<_Container>(__x, __i); } +#else + template + inline insert_iterator<_Container> + inserter(_Container& __x, _Iterator __i) + { + return insert_iterator<_Container>(__x, + typename _Container::iterator(__i)); + } +#endif + + // @} group iterators + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // This iterator adapter is @a normal in the sense that it does not + // change the semantics of any of the operators of its iterator + // parameter. Its primary purpose is to convert an iterator that is + // not a class, e.g. a pointer, into an iterator that is a class. + // The _Container parameter exists solely so that different containers + // using this template can instantiate different types, even if the + // _Iterator parameter is the same. + template + class __normal_iterator + { + protected: + _Iterator _M_current; + + typedef std::iterator_traits<_Iterator> __traits_type; + + public: + typedef _Iterator iterator_type; + typedef typename __traits_type::iterator_category iterator_category; + typedef typename __traits_type::value_type value_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::reference reference; + typedef typename __traits_type::pointer pointer; + +#if __cplusplus > 201703L && __cpp_lib_concepts + using iterator_concept = std::__detail::__iter_concept<_Iterator>; +#endif + + _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT + : _M_current(_Iterator()) { } + + explicit _GLIBCXX20_CONSTEXPR + __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT + : _M_current(__i) { } + + // Allow iterator to const_iterator conversion + template + _GLIBCXX20_CONSTEXPR + __normal_iterator(const __normal_iterator<_Iter, + typename __enable_if< + (std::__are_same<_Iter, typename _Container::pointer>::__value), + _Container>::__type>& __i) _GLIBCXX_NOEXCEPT + : _M_current(__i.base()) { } + + // Forward iterator requirements + _GLIBCXX20_CONSTEXPR + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *_M_current; } + + _GLIBCXX20_CONSTEXPR + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return _M_current; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator++() _GLIBCXX_NOEXCEPT + { + ++_M_current; + return *this; + } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator++(int) _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current++); } + + // Bidirectional iterator requirements + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator--() _GLIBCXX_NOEXCEPT + { + --_M_current; + return *this; + } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator--(int) _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current--); } + + // Random access iterator requirements + _GLIBCXX20_CONSTEXPR + reference + operator[](difference_type __n) const _GLIBCXX_NOEXCEPT + { return _M_current[__n]; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator+=(difference_type __n) _GLIBCXX_NOEXCEPT + { _M_current += __n; return *this; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator+(difference_type __n) const _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current + __n); } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator-=(difference_type __n) _GLIBCXX_NOEXCEPT + { _M_current -= __n; return *this; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator-(difference_type __n) const _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current - __n); } + + _GLIBCXX20_CONSTEXPR + const _Iterator& + base() const _GLIBCXX_NOEXCEPT + { return _M_current; } + }; + + // Note: In what follows, the left- and right-hand-side iterators are + // allowed to vary in types (conceptually in cv-qualification) so that + // comparison between cv-qualified and non-cv-qualified iterators be + // valid. However, the greedy and unfriendly operators in std::rel_ops + // will make overload resolution ambiguous (when in scope) if we don't + // provide overloads whose operands are of the same type. Can someone + // remind me what generic programming is about? -- Gaby + +#if __cpp_lib_three_way_comparison + template + requires requires (_IteratorL __lhs, _IteratorR __rhs) + { { __lhs == __rhs } -> std::convertible_to; } + constexpr bool + operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + noexcept(noexcept(__lhs.base() == __rhs.base())) + { return __lhs.base() == __rhs.base(); } + + template + constexpr std::__detail::__synth3way_t<_IteratorR, _IteratorL> + operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) + { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } +#else + // Forward iterator requirements + template + _GLIBCXX20_CONSTEXPR + inline bool + operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() == __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator==(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() == __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() != __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() != __rhs.base(); } + + // Random access iterator requirements + template + inline bool + operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() < __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator<(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() < __rhs.base(); } + + template + inline bool + operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() > __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator>(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() > __rhs.base(); } + + template + inline bool + operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() <= __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() <= __rhs.base(); } + + template + inline bool + operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() >= __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() >= __rhs.base(); } +#endif // three-way comparison + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template +#if __cplusplus >= 201103L + // DR 685. + _GLIBCXX20_CONSTEXPR + inline auto + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept + -> decltype(__lhs.base() - __rhs.base()) +#else + inline typename __normal_iterator<_IteratorL, _Container>::difference_type + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) +#endif + { return __lhs.base() - __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline typename __normal_iterator<_Iterator, _Container>::difference_type + operator-(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() - __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline __normal_iterator<_Iterator, _Container> + operator+(typename __normal_iterator<_Iterator, _Container>::difference_type + __n, const __normal_iterator<_Iterator, _Container>& __i) + _GLIBCXX_NOEXCEPT + { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + _GLIBCXX20_CONSTEXPR + _Iterator + __niter_base(__gnu_cxx::__normal_iterator<_Iterator, _Container> __it) + _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) + { return __it.base(); } + +#if __cplusplus >= 201103L + /** + * @addtogroup iterators + * @{ + */ + +#if __cplusplus > 201703L && __cpp_lib_concepts + template + class move_sentinel + { + public: + constexpr + move_sentinel() + noexcept(is_nothrow_default_constructible_v<_Sent>) + : _M_last() { } + + constexpr explicit + move_sentinel(_Sent __s) + noexcept(is_nothrow_move_constructible_v<_Sent>) + : _M_last(std::move(__s)) { } + + template requires convertible_to + constexpr + move_sentinel(const move_sentinel<_S2>& __s) + noexcept(is_nothrow_constructible_v<_Sent, const _S2&>) + : _M_last(__s.base()) + { } + + template requires assignable_from<_Sent&, const _S2&> + constexpr move_sentinel& + operator=(const move_sentinel<_S2>& __s) + noexcept(is_nothrow_assignable_v<_Sent, const _S2&>) + { + _M_last = __s.base(); + return *this; + } + + constexpr _Sent + base() const + noexcept(is_nothrow_copy_constructible_v<_Sent>) + { return _M_last; } + + private: + _Sent _M_last; + }; +#endif // C++20 + + // 24.4.3 Move iterators + /** + * Class template move_iterator is an iterator adapter with the same + * behavior as the underlying iterator except that its dereference + * operator implicitly converts the value returned by the underlying + * iterator's dereference operator to an rvalue reference. Some + * generic algorithms can be called with move iterators to replace + * copying with moving. + */ + template + class move_iterator + { + _Iterator _M_current; + + using __traits_type = iterator_traits<_Iterator>; +#if __cplusplus > 201703L && __cpp_lib_concepts + using __base_cat = typename __traits_type::iterator_category; +#else + using __base_ref = typename __traits_type::reference; +#endif + + public: + using iterator_type = _Iterator; + +#if __cplusplus > 201703L && __cpp_lib_concepts + using iterator_concept = input_iterator_tag; + using iterator_category + = __detail::__clamp_iter_cat<__base_cat, random_access_iterator_tag>; + using value_type = iter_value_t<_Iterator>; + using difference_type = iter_difference_t<_Iterator>; + using pointer = _Iterator; + using reference = iter_rvalue_reference_t<_Iterator>; +#else + typedef typename __traits_type::iterator_category iterator_category; + typedef typename __traits_type::value_type value_type; + typedef typename __traits_type::difference_type difference_type; + // NB: DR 680. + typedef _Iterator pointer; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2106. move_iterator wrapping iterators returning prvalues + typedef typename conditional::value, + typename remove_reference<__base_ref>::type&&, + __base_ref>::type reference; +#endif + + _GLIBCXX17_CONSTEXPR + move_iterator() + : _M_current() { } + + explicit _GLIBCXX17_CONSTEXPR + move_iterator(iterator_type __i) + : _M_current(std::move(__i)) { } + + template + _GLIBCXX17_CONSTEXPR + move_iterator(const move_iterator<_Iter>& __i) + : _M_current(__i.base()) { } + +#if __cplusplus <= 201703L + _GLIBCXX17_CONSTEXPR iterator_type + base() const + { return _M_current; } +#else + constexpr iterator_type + base() const & +#if __cpp_lib_concepts + requires copy_constructible +#endif + { return _M_current; } + + constexpr iterator_type + base() && + { return std::move(_M_current); } +#endif + + _GLIBCXX17_CONSTEXPR reference + operator*() const +#if __cplusplus > 201703L && __cpp_lib_concepts + { return ranges::iter_move(_M_current); } +#else + { return static_cast(*_M_current); } +#endif + + _GLIBCXX17_CONSTEXPR pointer + operator->() const + { return _M_current; } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator++() + { + ++_M_current; + return *this; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator++(int) + { + move_iterator __tmp = *this; + ++_M_current; + return __tmp; + } + +#if __cpp_lib_concepts + constexpr void + operator++(int) requires (!forward_iterator<_Iterator>) + { ++_M_current; } +#endif + + _GLIBCXX17_CONSTEXPR move_iterator& + operator--() + { + --_M_current; + return *this; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator--(int) + { + move_iterator __tmp = *this; + --_M_current; + return __tmp; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator+(difference_type __n) const + { return move_iterator(_M_current + __n); } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator+=(difference_type __n) + { + _M_current += __n; + return *this; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator-(difference_type __n) const + { return move_iterator(_M_current - __n); } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator-=(difference_type __n) + { + _M_current -= __n; + return *this; + } + + _GLIBCXX17_CONSTEXPR reference + operator[](difference_type __n) const +#if __cplusplus > 201703L && __cpp_lib_concepts + { return ranges::iter_move(_M_current + __n); } +#else + { return std::move(_M_current[__n]); } +#endif + +#if __cplusplus > 201703L && __cpp_lib_concepts + template _Sent> + friend constexpr bool + operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { return __x.base() == __y.base(); } + + template _Sent> + friend constexpr iter_difference_t<_Iterator> + operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) + { return __x.base() - __y.base(); } + + template _Sent> + friend constexpr iter_difference_t<_Iterator> + operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { return __x.base() - __y.base(); } + + friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const move_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + template _Iter2> + friend constexpr void + iter_swap(const move_iterator& __x, const move_iterator<_Iter2>& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + { return ranges::iter_swap(__x._M_current, __y._M_current); } +#endif // C++20 + }; + + template + inline _GLIBCXX17_CONSTEXPR bool + operator==(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __x.base() == __y.base() } -> convertible_to; } +#endif + { return __x.base() == __y.base(); } + +#if __cpp_lib_three_way_comparison + template _IteratorR> + constexpr compare_three_way_result_t<_IteratorL, _IteratorR> + operator<=>(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + { return __x.base() <=> __y.base(); } +#else + template + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + { return !(__x == __y); } +#endif + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __x.base() < __y.base() } -> convertible_to; } +#endif + { return __x.base() < __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __y.base() < __x.base() } -> convertible_to; } +#endif + { return !(__y < __x); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __y.base() < __x.base() } -> convertible_to; } +#endif + { return __y < __x; } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __x.base() < __y.base() } -> convertible_to; } +#endif + { return !(__x < __y); } + +#if ! (__cplusplus > 201703L && __cpp_lib_concepts) + // Note: See __normal_iterator operators note from Gaby to understand + // why we have these extra overloads for some move_iterator operators. + + // These extra overloads are not needed in C++20, because the ones above + // are constrained with a requires-clause and so overload resolution will + // prefer them to greedy unconstrained function templates. + + template + inline _GLIBCXX17_CONSTEXPR bool + operator==(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __x.base() == __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__x == __y); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __x.base() < __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__y < __x); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __y < __x; } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__x < __y); } +#endif // ! C++20 + + // DR 685. + template + inline _GLIBCXX17_CONSTEXPR auto + operator-(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + -> decltype(__x.base() - __y.base()) + { return __x.base() - __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> + operator+(typename move_iterator<_Iterator>::difference_type __n, + const move_iterator<_Iterator>& __x) + { return __x + __n; } + + template + inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> + make_move_iterator(_Iterator __i) + { return move_iterator<_Iterator>(std::move(__i)); } + + template::value_type>::value, + _Iterator, move_iterator<_Iterator>>::type> + inline _GLIBCXX17_CONSTEXPR _ReturnType + __make_move_if_noexcept_iterator(_Iterator __i) + { return _ReturnType(__i); } + + // Overload for pointers that matches std::move_if_noexcept more closely, + // returning a constant iterator when we don't want to move. + template::value, + const _Tp*, move_iterator<_Tp*>>::type> + inline _GLIBCXX17_CONSTEXPR _ReturnType + __make_move_if_noexcept_iterator(_Tp* __i) + { return _ReturnType(__i); } + +#if __cplusplus > 201703L && __cpp_lib_concepts + // [iterators.common] Common iterators + + namespace __detail + { + template + concept __common_iter_has_arrow = indirectly_readable + && (requires(const _It& __it) { __it.operator->(); } + || is_reference_v> + || constructible_from, iter_reference_t<_It>>); + + } // namespace __detail + + /// An iterator/sentinel adaptor for representing a non-common range. + template _Sent> + requires (!same_as<_It, _Sent>) && copyable<_It> + class common_iterator + { + template + static constexpr bool + _S_noexcept1() + { + if constexpr (is_trivially_default_constructible_v<_Tp>) + return is_nothrow_assignable_v<_Tp, _Up>; + else + return is_nothrow_constructible_v<_Tp, _Up>; + } + + template + static constexpr bool + _S_noexcept() + { return _S_noexcept1<_It, _It2>() && _S_noexcept1<_Sent, _Sent2>(); } + + class _Proxy + { + iter_value_t<_It> _M_keep; + + _Proxy(iter_reference_t<_It>&& __x) + : _M_keep(std::move(__x)) { } + + friend class common_iterator; + + public: + const iter_value_t<_It>* + operator->() const + { return std::__addressof(_M_keep); } + }; + + public: + constexpr + common_iterator() + noexcept(is_nothrow_default_constructible_v<_It>) + : _M_it(), _M_index(0) + { } + + constexpr + common_iterator(_It __i) + noexcept(is_nothrow_move_constructible_v<_It>) + : _M_it(std::move(__i)), _M_index(0) + { } + + constexpr + common_iterator(_Sent __s) + noexcept(is_nothrow_move_constructible_v<_Sent>) + : _M_sent(std::move(__s)), _M_index(1) + { } + + template + requires convertible_to + && convertible_to + constexpr + common_iterator(const common_iterator<_It2, _Sent2>& __x) + noexcept(_S_noexcept()) + : _M_valueless(), _M_index(__x._M_index) + { + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = std::move(__x._M_it); + else + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = std::move(__x._M_sent); + else + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + } + } + + constexpr + common_iterator(const common_iterator& __x) + noexcept(_S_noexcept()) + : _M_valueless(), _M_index(__x._M_index) + { + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = std::move(__x._M_it); + else + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = std::move(__x._M_sent); + else + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + } + } + + common_iterator& + operator=(const common_iterator& __x) + noexcept(is_nothrow_copy_assignable_v<_It> + && is_nothrow_copy_assignable_v<_Sent> + && is_nothrow_copy_constructible_v<_It> + && is_nothrow_copy_constructible_v<_Sent>) + { + return this->operator=<_It, _Sent>(__x); + } + + template + requires convertible_to + && convertible_to + && assignable_from<_It&, const _It2&> + && assignable_from<_Sent&, const _Sent2&> + common_iterator& + operator=(const common_iterator<_It2, _Sent2>& __x) + noexcept(is_nothrow_constructible_v<_It, const _It2&> + && is_nothrow_constructible_v<_Sent, const _Sent2&> + && is_nothrow_assignable_v<_It, const _It2&> + && is_nothrow_assignable_v<_Sent, const _Sent2&>) + { + switch(_M_index << 2 | __x._M_index) + { + case 0b0000: + _M_it = __x._M_it; + break; + case 0b0101: + _M_sent = __x._M_sent; + break; + case 0b0001: + _M_it.~_It(); + _M_index = -1; + [[fallthrough]]; + case 0b1001: + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + _M_index = 1; + break; + case 0b0100: + _M_sent.~_Sent(); + _M_index = -1; + [[fallthrough]]; + case 0b1000: + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + _M_index = 0; + break; + default: + __glibcxx_assert(__x._M_has_value()); + __builtin_unreachable(); + } + return *this; + } + + ~common_iterator() + { + switch (_M_index) + { + case 0: + _M_it.~_It(); + break; + case 1: + _M_sent.~_Sent(); + break; + } + } + + decltype(auto) + operator*() + { + __glibcxx_assert(_M_index == 0); + return *_M_it; + } + + decltype(auto) + operator*() const requires __detail::__dereferenceable + { + __glibcxx_assert(_M_index == 0); + return *_M_it; + } + + decltype(auto) + operator->() const requires __detail::__common_iter_has_arrow<_It> + { + __glibcxx_assert(_M_index == 0); + if constexpr (is_pointer_v<_It> || requires { _M_it.operator->(); }) + return _M_it; + else if constexpr (is_reference_v>) + { + auto&& __tmp = *_M_it; + return std::__addressof(__tmp); + } + else + return _Proxy{*_M_it}; + } + + common_iterator& + operator++() + { + __glibcxx_assert(_M_index == 0); + ++_M_it; + return *this; + } + + decltype(auto) + operator++(int) + { + __glibcxx_assert(_M_index == 0); + if constexpr (forward_iterator<_It>) + { + common_iterator __tmp = *this; + ++*this; + return __tmp; + } + else + return _M_it++; + } + + template _Sent2> + requires sentinel_for<_Sent, _It2> + friend bool + operator==(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0000: + case 0b0101: + return true; + case 0b0001: + return __x._M_it == __y._M_sent; + case 0b0100: + return __x._M_sent == __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + template _Sent2> + requires sentinel_for<_Sent, _It2> && equality_comparable_with<_It, _It2> + friend bool + operator==(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0101: + return true; + case 0b0000: + return __x._M_it == __y._M_it; + case 0b0001: + return __x._M_it == __y._M_sent; + case 0b0100: + return __x._M_sent == __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + template _It2, sized_sentinel_for<_It> _Sent2> + requires sized_sentinel_for<_Sent, _It2> + friend iter_difference_t<_It2> + operator-(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0101: + return 0; + case 0b0000: + return __x._M_it - __y._M_it; + case 0b0001: + return __x._M_it - __y._M_sent; + case 0b0100: + return __x._M_sent - __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + friend iter_rvalue_reference_t<_It> + iter_move(const common_iterator& __i) + noexcept(noexcept(ranges::iter_move(std::declval()))) + requires input_iterator<_It> + { + __glibcxx_assert(__i._M_index == 0); + return ranges::iter_move(__i._M_it); + } + + template _It2, typename _Sent2> + friend void + iter_swap(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + noexcept(noexcept(ranges::iter_swap(std::declval(), + std::declval()))) + { + __glibcxx_assert(__x._M_index == 0); + __glibcxx_assert(__y._M_index == 0); + return ranges::iter_swap(__x._M_it, __y._M_it); + } + + private: + template _Sent2> + friend class common_iterator; + + bool _M_has_value() const noexcept { return _M_index < 2; } + + union + { + _It _M_it; + _Sent _M_sent; + unsigned char _M_valueless; + }; + unsigned char _M_index; // 0==_M_it, 1==_M_sent, 2==valueless + }; + + template + struct incrementable_traits> + { + using difference_type = iter_difference_t<_It>; + }; + + namespace __detail + { + // FIXME: This has to be at namespace-scope because of PR 92103. + template + struct __common_iter_ptr + { + using type = void; + }; + + template + requires __detail::__common_iter_has_arrow<_It> + struct __common_iter_ptr<_It, _Sent> + { + using common_iterator = std::common_iterator<_It, _Sent>; + + using type + = decltype(std::declval().operator->()); + }; + } // namespace __detail + + template + struct iterator_traits> + { + using iterator_concept = conditional_t, + forward_iterator_tag, input_iterator_tag>; + using iterator_category = __detail::__clamp_iter_cat< + typename iterator_traits<_It>::iterator_category, + forward_iterator_tag, input_iterator_tag>; + using value_type = iter_value_t<_It>; + using difference_type = iter_difference_t<_It>; + using pointer = typename __detail::__common_iter_ptr<_It, _Sent>::type; + using reference = iter_reference_t<_It>; + }; + + // [iterators.counted] Counted iterators + + /// An iterator adaptor that keeps track of the distance to the end. + template + class counted_iterator + { + public: + using iterator_type = _It; + + constexpr counted_iterator() = default; + + constexpr + counted_iterator(_It __i, iter_difference_t<_It> __n) + : _M_current(std::move(__i)), _M_length(__n) + { __glibcxx_assert(__n >= 0); } + + template + requires convertible_to + constexpr + counted_iterator(const counted_iterator<_It2>& __x) + : _M_current(__x._M_current), _M_length(__x._M_length) + { } + + template + requires assignable_from<_It&, const _It2&> + constexpr counted_iterator& + operator=(const counted_iterator<_It2>& __x) + { + _M_current = __x._M_current; + _M_length = __x._M_length; + return *this; + } + + constexpr _It + base() const & + noexcept(is_nothrow_copy_constructible_v<_It>) + requires copy_constructible<_It> + { return _M_current; } + + constexpr _It + base() && + noexcept(is_nothrow_move_constructible_v<_It>) + { return std::move(_M_current); } + + constexpr iter_difference_t<_It> + count() const noexcept { return _M_length; } + + constexpr decltype(auto) + operator*() + noexcept(noexcept(*_M_current)) + { return *_M_current; } + + constexpr decltype(auto) + operator*() const + noexcept(noexcept(*_M_current)) + requires __detail::__dereferenceable + { return *_M_current; } + + constexpr counted_iterator& + operator++() + { + __glibcxx_assert(_M_length > 0); + ++_M_current; + --_M_length; + return *this; + } + + decltype(auto) + operator++(int) + { + __glibcxx_assert(_M_length > 0); + --_M_length; + __try + { + return _M_current++; + } __catch(...) { + ++_M_length; + __throw_exception_again; + } + + } + + constexpr counted_iterator + operator++(int) requires forward_iterator<_It> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr counted_iterator& + operator--() requires bidirectional_iterator<_It> + { + --_M_current; + ++_M_length; + return *this; + } + + constexpr counted_iterator + operator--(int) requires bidirectional_iterator<_It> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr counted_iterator + operator+(iter_difference_t<_It> __n) const + requires random_access_iterator<_It> + { return counted_iterator(_M_current + __n, _M_length - __n); } + + friend constexpr counted_iterator + operator+(iter_difference_t<_It> __n, const counted_iterator& __x) + requires random_access_iterator<_It> + { return __x + __n; } + + constexpr counted_iterator& + operator+=(iter_difference_t<_It> __n) + requires random_access_iterator<_It> + { + __glibcxx_assert(__n <= _M_length); + _M_current += __n; + _M_length -= __n; + return *this; + } + + constexpr counted_iterator + operator-(iter_difference_t<_It> __n) const + requires random_access_iterator<_It> + { return counted_iterator(_M_current - __n, _M_length + __n); } + + template _It2> + friend constexpr iter_difference_t<_It2> + operator-(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __y._M_length - __x._M_length; } + + friend constexpr iter_difference_t<_It> + operator-(const counted_iterator& __x, default_sentinel_t) + { return -__x._M_length; } + + friend constexpr iter_difference_t<_It> + operator-(default_sentinel_t, const counted_iterator& __y) + { return __y._M_length; } + + constexpr counted_iterator& + operator-=(iter_difference_t<_It> __n) + requires random_access_iterator<_It> + { + __glibcxx_assert(-__n <= _M_length); + _M_current -= __n; + _M_length += __n; + return *this; + } + + constexpr decltype(auto) + operator[](iter_difference_t<_It> __n) const + noexcept(noexcept(_M_current[__n])) + requires random_access_iterator<_It> + { + __glibcxx_assert(__n < _M_length); + return _M_current[__n]; + } + + template _It2> + friend constexpr bool + operator==(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __x._M_length == __y._M_length; } + + friend constexpr bool + operator==(const counted_iterator& __x, default_sentinel_t) + { return __x._M_length == 0; } + + template _It2> + friend constexpr strong_ordering + operator<=>(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __y._M_length <=> __x._M_length; } + + private: + template friend class counted_iterator; + + _It _M_current = _It(); + iter_difference_t<_It> _M_length = 0; + + friend constexpr iter_rvalue_reference_t<_It> + iter_move(const counted_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + requires input_iterator<_It> + { return ranges::iter_move(__i._M_current); } + + template _It2> + friend constexpr void + iter_swap(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + { ranges::iter_swap(__x._M_current, __y._M_current); } + }; + + template + struct incrementable_traits> + { + using difference_type = iter_difference_t<_It>; + }; + + template + struct iterator_traits> : iterator_traits<_It> + { + using pointer = void; + }; +#endif // C++20 + + // @} group iterators + + template + auto + __niter_base(move_iterator<_Iterator> __it) + -> decltype(make_move_iterator(__niter_base(__it.base()))) + { return make_move_iterator(__niter_base(__it.base())); } + + template + struct __is_move_iterator > + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template + auto + __miter_base(move_iterator<_Iterator> __it) + -> decltype(__miter_base(__it.base())) + { return __miter_base(__it.base()); } + +#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter) +#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) \ + std::__make_move_if_noexcept_iterator(_Iter) +#else +#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) (_Iter) +#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter) +#endif // C++11 + +#if __cpp_deduction_guides >= 201606 + // These helper traits are used for deduction guides + // of associative containers. + template + using __iter_key_t = remove_const_t< + typename iterator_traits<_InputIterator>::value_type::first_type>; + + template + using __iter_val_t = + typename iterator_traits<_InputIterator>::value_type::second_type; + + template + struct pair; + + template + using __iter_to_alloc_t = + pair>, + __iter_val_t<_InputIterator>>; +#endif // __cpp_deduction_guides + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h new file mode 100644 index 000000000..076b7781c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h @@ -0,0 +1,239 @@ +// Functions used by iterators -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator_base_funcs.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file contains all of the general iterator-related utility + * functions, such as distance() and advance(). + */ + +#ifndef _STL_ITERATOR_BASE_FUNCS_H +#define _STL_ITERATOR_BASE_FUNCS_H 1 + +#pragma GCC system_header + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + // Forward declaration for the overloads of __distance. + template struct _List_iterator; + template struct _List_const_iterator; +_GLIBCXX_END_NAMESPACE_CONTAINER + + template + inline _GLIBCXX14_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + __distance(_InputIterator __first, _InputIterator __last, + input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + + typename iterator_traits<_InputIterator>::difference_type __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } + + template + inline _GLIBCXX14_CONSTEXPR + typename iterator_traits<_RandomAccessIterator>::difference_type + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + return __last - __first; + } + +#if _GLIBCXX_USE_CXX11_ABI + // Forward declaration because of the qualified call in distance. + template + ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_iterator<_Tp>, + _GLIBCXX_STD_C::_List_iterator<_Tp>, + input_iterator_tag); + + template + ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>, + _GLIBCXX_STD_C::_List_const_iterator<_Tp>, + input_iterator_tag); +#endif + + /** + * @brief A generalization of pointer arithmetic. + * @param __first An input iterator. + * @param __last An input iterator. + * @return The distance between them. + * + * Returns @c n such that __first + n == __last. This requires + * that @p __last must be reachable from @p __first. Note that @c + * n may be negative. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. + */ + template + inline _GLIBCXX17_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + distance(_InputIterator __first, _InputIterator __last) + { + // concept requirements -- taken care of in __distance + return std::__distance(__first, __last, + std::__iterator_category(__first)); + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_InputIterator& __i, _Distance __n, input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_assert(__n >= 0); + while (__n--) + ++__i; + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_BidirectionalIterator& __i, _Distance __n, + bidirectional_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + if (__n > 0) + while (__n--) + ++__i; + else + while (__n++) + --__i; + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_RandomAccessIterator& __i, _Distance __n, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + if (__builtin_constant_p(__n) && __n == 1) + ++__i; + else if (__builtin_constant_p(__n) && __n == -1) + --__i; + else + __i += __n; + } + + /** + * @brief A generalization of pointer arithmetic. + * @param __i An input iterator. + * @param __n The @a delta by which to change @p __i. + * @return Nothing. + * + * This increments @p i by @p n. For bidirectional and random access + * iterators, @p __n may be negative, in which case @p __i is decremented. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. + */ + template + inline _GLIBCXX17_CONSTEXPR void + advance(_InputIterator& __i, _Distance __n) + { + // concept requirements -- taken care of in __advance + typename iterator_traits<_InputIterator>::difference_type __d = __n; + std::__advance(__i, __d, std::__iterator_category(__i)); + } + +#if __cplusplus >= 201103L + + template + inline _GLIBCXX17_CONSTEXPR _InputIterator + next(_InputIterator __x, typename + iterator_traits<_InputIterator>::difference_type __n = 1) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + std::advance(__x, __n); + return __x; + } + + template + inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator + prev(_BidirectionalIterator __x, typename + iterator_traits<_BidirectionalIterator>::difference_type __n = 1) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + std::advance(__x, -__n); + return __x; + } + +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_ITERATOR_BASE_FUNCS_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h new file mode 100644 index 000000000..aa02af59d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h @@ -0,0 +1,271 @@ +// Types used in iterator implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator_base_types.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file contains all of the general iterator-related utility types, + * such as iterator_traits and struct iterator. + */ + +#ifndef _STL_ITERATOR_BASE_TYPES_H +#define _STL_ITERATOR_BASE_TYPES_H 1 + +#pragma GCC system_header + +#include + +#if __cplusplus >= 201103L +# include // For __void_t, is_convertible +#endif + +#if __cplusplus > 201703L && __cpp_concepts >= 201907L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup iterators Iterators + * Abstractions for uniform iterating through various underlying types. + */ + //@{ + + /** + * @defgroup iterator_tags Iterator Tags + * These are empty types, used to distinguish different iterators. The + * distinction is not made by what they contain, but simply by what they + * are. Different underlying algorithms can then be used based on the + * different operations supported by different iterator types. + */ + //@{ + /// Marking input iterators. + struct input_iterator_tag { }; + + /// Marking output iterators. + struct output_iterator_tag { }; + + /// Forward iterators support a superset of input iterator operations. + struct forward_iterator_tag : public input_iterator_tag { }; + + /// Bidirectional iterators support a superset of forward iterator + /// operations. + struct bidirectional_iterator_tag : public forward_iterator_tag { }; + + /// Random-access iterators support a superset of bidirectional + /// iterator operations. + struct random_access_iterator_tag : public bidirectional_iterator_tag { }; + +#if __cplusplus > 201703L + /// Contiguous iterators point to objects stored contiguously in memory. + struct contiguous_iterator_tag : public random_access_iterator_tag { }; +#endif + //@} + + /** + * @brief Common %iterator class. + * + * This class does nothing but define nested typedefs. %Iterator classes + * can inherit from this class to save some work. The typedefs are then + * used in specializations and overloading. + * + * In particular, there are no default implementations of requirements + * such as @c operator++ and the like. (How could there be?) + */ + template + struct iterator + { + /// One of the @link iterator_tags tag types@endlink. + typedef _Category iterator_category; + /// The type "pointed to" by the iterator. + typedef _Tp value_type; + /// Distance between iterators is represented as this type. + typedef _Distance difference_type; + /// This type represents a pointer-to-value_type. + typedef _Pointer pointer; + /// This type represents a reference-to-value_type. + typedef _Reference reference; + }; + + /** + * @brief Traits class for iterators. + * + * This class does nothing but define nested typedefs. The general + * version simply @a forwards the nested typedefs from the Iterator + * argument. Specialized versions for pointers and pointers-to-const + * provide tighter, more correct semantics. + */ + template + struct iterator_traits; + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14 + template> + struct __iterator_traits { }; + +#if ! __cpp_lib_concepts + + template + struct __iterator_traits<_Iterator, + __void_t> + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; +#endif // ! concepts + + template + struct iterator_traits + : public __iterator_traits<_Iterator> { }; + +#else // ! C++11 + template + struct iterator_traits + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; +#endif // C++11 + +#if __cplusplus > 201703L + /// Partial specialization for object pointer types. + template +#if __cpp_concepts >= 201907L + requires is_object_v<_Tp> +#endif + struct iterator_traits<_Tp*> + { + using iterator_concept = contiguous_iterator_tag; + using iterator_category = random_access_iterator_tag; + using value_type = remove_cv_t<_Tp>; + using difference_type = ptrdiff_t; + using pointer = _Tp*; + using reference = _Tp&; + }; +#else + /// Partial specialization for pointer types. + template + struct iterator_traits<_Tp*> + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef _Tp& reference; + }; + + /// Partial specialization for const pointer types. + template + struct iterator_traits + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + }; +#endif + + /** + * This function is not a part of the C++ standard but is syntactic + * sugar for internal library use only. + */ + template + inline _GLIBCXX_CONSTEXPR + typename iterator_traits<_Iter>::iterator_category + __iterator_category(const _Iter&) + { return typename iterator_traits<_Iter>::iterator_category(); } + + //@} + +#if __cplusplus >= 201103L + template + using __iterator_category_t + = typename iterator_traits<_Iter>::iterator_category; + + template + using _RequireInputIter = + __enable_if_t, + input_iterator_tag>::value>; + + template> + struct __is_random_access_iter + : is_base_of + { + typedef is_base_of _Base; + enum { __value = _Base::value }; + }; +#else + template, + typename _Cat = typename _Traits::iterator_category> + struct __is_random_access_iter + { enum { __value = __is_base_of(random_access_iterator_tag, _Cat) }; }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_ITERATOR_BASE_TYPES_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_list.h b/resources/sources/avr-libstdcpp/include/bits/stl_list.h new file mode 100644 index 000000000..e7135e3e7 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_list.h @@ -0,0 +1,2127 @@ +// List implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_list.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{list} + */ + +#ifndef _STL_LIST_H +#define _STL_LIST_H 1 + +#include +#include +#if __cplusplus >= 201103L +#include +#include +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + namespace __detail + { + // Supporting structures are split into common and templated + // types; the latter publicly inherits from the former in an + // effort to reduce code duplication. This results in some + // "needless" static_cast'ing later on, but it's all safe + // downcasting. + + /// Common part of a node in the %list. + struct _List_node_base + { + _List_node_base* _M_next; + _List_node_base* _M_prev; + + static void + swap(_List_node_base& __x, _List_node_base& __y) _GLIBCXX_USE_NOEXCEPT; + + void + _M_transfer(_List_node_base* const __first, + _List_node_base* const __last) _GLIBCXX_USE_NOEXCEPT; + + void + _M_reverse() _GLIBCXX_USE_NOEXCEPT; + + void + _M_hook(_List_node_base* const __position) _GLIBCXX_USE_NOEXCEPT; + + void + _M_unhook() _GLIBCXX_USE_NOEXCEPT; + }; + + /// The %list node header. + struct _List_node_header : public _List_node_base + { +#if _GLIBCXX_USE_CXX11_ABI + std::size_t _M_size; +#endif + + _List_node_header() _GLIBCXX_NOEXCEPT + { _M_init(); } + +#if __cplusplus >= 201103L + _List_node_header(_List_node_header&& __x) noexcept + : _List_node_base{ __x._M_next, __x._M_prev } +# if _GLIBCXX_USE_CXX11_ABI + , _M_size(__x._M_size) +# endif + { + if (__x._M_base()->_M_next == __x._M_base()) + this->_M_next = this->_M_prev = this; + else + { + this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base(); + __x._M_init(); + } + } + + void + _M_move_nodes(_List_node_header&& __x) + { + _List_node_base* const __xnode = __x._M_base(); + if (__xnode->_M_next == __xnode) + _M_init(); + else + { + _List_node_base* const __node = this->_M_base(); + __node->_M_next = __xnode->_M_next; + __node->_M_prev = __xnode->_M_prev; + __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node; +# if _GLIBCXX_USE_CXX11_ABI + _M_size = __x._M_size; +# endif + __x._M_init(); + } + } +#endif + + void + _M_init() _GLIBCXX_NOEXCEPT + { + this->_M_next = this->_M_prev = this; +#if _GLIBCXX_USE_CXX11_ABI + this->_M_size = 0; +#endif + } + + private: + _List_node_base* _M_base() { return this; } + }; + } // namespace detail + +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /// An actual node in the %list. + template + struct _List_node : public __detail::_List_node_base + { +#if __cplusplus >= 201103L + __gnu_cxx::__aligned_membuf<_Tp> _M_storage; + _Tp* _M_valptr() { return _M_storage._M_ptr(); } + _Tp const* _M_valptr() const { return _M_storage._M_ptr(); } +#else + _Tp _M_data; + _Tp* _M_valptr() { return std::__addressof(_M_data); } + _Tp const* _M_valptr() const { return std::__addressof(_M_data); } +#endif + }; + + /** + * @brief A list::iterator. + * + * All the functions are op overloads. + */ + template + struct _List_iterator + { + typedef _List_iterator<_Tp> _Self; + typedef _List_node<_Tp> _Node; + + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Tp* pointer; + typedef _Tp& reference; + + _List_iterator() _GLIBCXX_NOEXCEPT + : _M_node() { } + + explicit + _List_iterator(__detail::_List_node_base* __x) _GLIBCXX_NOEXCEPT + : _M_node(__x) { } + + _Self + _M_const_cast() const _GLIBCXX_NOEXCEPT + { return *this; } + + // Must downcast from _List_node_base to _List_node to get to value. + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *static_cast<_Node*>(_M_node)->_M_valptr(); } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return static_cast<_Node*>(_M_node)->_M_valptr(); } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + _M_node = _M_node->_M_next; + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _M_node->_M_next; + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + _M_node = _M_node->_M_prev; + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _M_node->_M_prev; + return __tmp; + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node == __y._M_node; } + +#if __cpp_impl_three_way_comparison < 201907L + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node != __y._M_node; } +#endif + + // The only member points to the %list element. + __detail::_List_node_base* _M_node; + }; + + /** + * @brief A list::const_iterator. + * + * All the functions are op overloads. + */ + template + struct _List_const_iterator + { + typedef _List_const_iterator<_Tp> _Self; + typedef const _List_node<_Tp> _Node; + typedef _List_iterator<_Tp> iterator; + + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + + _List_const_iterator() _GLIBCXX_NOEXCEPT + : _M_node() { } + + explicit + _List_const_iterator(const __detail::_List_node_base* __x) + _GLIBCXX_NOEXCEPT + : _M_node(__x) { } + + _List_const_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT + : _M_node(__x._M_node) { } + + iterator + _M_const_cast() const _GLIBCXX_NOEXCEPT + { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); } + + // Must downcast from List_node_base to _List_node to get to value. + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *static_cast<_Node*>(_M_node)->_M_valptr(); } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return static_cast<_Node*>(_M_node)->_M_valptr(); } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + _M_node = _M_node->_M_next; + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _M_node->_M_next; + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + _M_node = _M_node->_M_prev; + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _M_node->_M_prev; + return __tmp; + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node == __y._M_node; } + +#if __cpp_impl_three_way_comparison < 201907L + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node != __y._M_node; } +#endif + + // The only member points to the %list element. + const __detail::_List_node_base* _M_node; + }; + +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + /// See bits/stl_deque.h's _Deque_base for an explanation. + template + class _List_base + { + protected: + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Tp>::other _Tp_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tp_alloc_traits; + typedef typename _Tp_alloc_traits::template + rebind<_List_node<_Tp> >::other _Node_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; + +#if !_GLIBCXX_INLINE_VERSION + static size_t + _S_distance(const __detail::_List_node_base* __first, + const __detail::_List_node_base* __last) + { + size_t __n = 0; + while (__first != __last) + { + __first = __first->_M_next; + ++__n; + } + return __n; + } +#endif + + struct _List_impl + : public _Node_alloc_type + { + __detail::_List_node_header _M_node; + + _List_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Node_alloc_type>::value) + : _Node_alloc_type() + { } + + _List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT + : _Node_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + _List_impl(_List_impl&&) = default; + + _List_impl(_Node_alloc_type&& __a, _List_impl&& __x) + : _Node_alloc_type(std::move(__a)), _M_node(std::move(__x._M_node)) + { } + + _List_impl(_Node_alloc_type&& __a) noexcept + : _Node_alloc_type(std::move(__a)) + { } +#endif + }; + + _List_impl _M_impl; + +#if _GLIBCXX_USE_CXX11_ABI + size_t _M_get_size() const { return _M_impl._M_node._M_size; } + + void _M_set_size(size_t __n) { _M_impl._M_node._M_size = __n; } + + void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; } + + void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; } + +# if !_GLIBCXX_INLINE_VERSION + size_t + _M_distance(const __detail::_List_node_base* __first, + const __detail::_List_node_base* __last) const + { return _S_distance(__first, __last); } + + // return the stored size + size_t _M_node_count() const { return _M_get_size(); } +# endif +#else + // dummy implementations used when the size is not stored + size_t _M_get_size() const { return 0; } + void _M_set_size(size_t) { } + void _M_inc_size(size_t) { } + void _M_dec_size(size_t) { } + +# if !_GLIBCXX_INLINE_VERSION + size_t _M_distance(const void*, const void*) const { return 0; } + + // count the number of nodes + size_t _M_node_count() const + { + return _S_distance(_M_impl._M_node._M_next, + std::__addressof(_M_impl._M_node)); + } +# endif +#endif + + typename _Node_alloc_traits::pointer + _M_get_node() + { return _Node_alloc_traits::allocate(_M_impl, 1); } + + void + _M_put_node(typename _Node_alloc_traits::pointer __p) _GLIBCXX_NOEXCEPT + { _Node_alloc_traits::deallocate(_M_impl, __p, 1); } + + public: + typedef _Alloc allocator_type; + + _Node_alloc_type& + _M_get_Node_allocator() _GLIBCXX_NOEXCEPT + { return _M_impl; } + + const _Node_alloc_type& + _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT + { return _M_impl; } + +#if __cplusplus >= 201103L + _List_base() = default; +#else + _List_base() { } +#endif + + _List_base(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT + : _M_impl(__a) + { } + +#if __cplusplus >= 201103L + _List_base(_List_base&&) = default; + +# if !_GLIBCXX_INLINE_VERSION + _List_base(_List_base&& __x, _Node_alloc_type&& __a) + : _M_impl(std::move(__a)) + { + if (__x._M_get_Node_allocator() == _M_get_Node_allocator()) + _M_move_nodes(std::move(__x)); + // else caller must move individual elements. + } +# endif + + // Used when allocator is_always_equal. + _List_base(_Node_alloc_type&& __a, _List_base&& __x) + : _M_impl(std::move(__a), std::move(__x._M_impl)) + { } + + // Used when allocator !is_always_equal. + _List_base(_Node_alloc_type&& __a) + : _M_impl(std::move(__a)) + { } + + void + _M_move_nodes(_List_base&& __x) + { _M_impl._M_node._M_move_nodes(std::move(__x._M_impl._M_node)); } +#endif + + // This is what actually destroys the list. + ~_List_base() _GLIBCXX_NOEXCEPT + { _M_clear(); } + + void + _M_clear() _GLIBCXX_NOEXCEPT; + + void + _M_init() _GLIBCXX_NOEXCEPT + { this->_M_impl._M_node._M_init(); } + }; + + /** + * @brief A standard container with linear time access to elements, + * and fixed time insertion/deletion at any point in the sequence. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements with the + * %exception of @c at and @c operator[]. + * + * This is a @e doubly @e linked %list. Traversal up and down the + * %list requires linear time, but adding and removing elements (or + * @e nodes) is done in constant time, regardless of where the + * change takes place. Unlike std::vector and std::deque, + * random-access iterators are not provided, so subscripting ( @c + * [] ) access is not allowed. For algorithms which only need + * sequential access, this lack makes no difference. + * + * Also unlike the other standard containers, std::list provides + * specialized algorithms %unique to linked lists, such as + * splicing, sorting, and in-place reversal. + * + * A couple points on memory allocation for list: + * + * First, we never actually allocate a Tp, we allocate + * List_node's and trust [20.1.5]/4 to DTRT. This is to ensure + * that after elements from %list are spliced into + * %list, destroying the memory of the second %list is a + * valid operation, i.e., Alloc1 giveth and Alloc2 taketh away. + * + * Second, a %list conceptually represented as + * @code + * A <---> B <---> C <---> D + * @endcode + * is actually circular; a link exists between A and D. The %list + * class holds (as its only data member) a private list::iterator + * pointing to @e D, not to @e A! To get to the head of the %list, + * we start at the tail and move forward by one. When this member + * iterator's next/previous pointers refer to itself, the %list is + * %empty. + */ + template > + class list : protected _List_base<_Tp, _Alloc> + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Tp>::value, + "std::list must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::list must have the same value_type as its allocator"); +# endif +#endif + + typedef _List_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits; + typedef typename _Base::_Node_alloc_type _Node_alloc_type; + typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; + + public: + typedef _Tp value_type; + typedef typename _Tp_alloc_traits::pointer pointer; + typedef typename _Tp_alloc_traits::const_pointer const_pointer; + typedef typename _Tp_alloc_traits::reference reference; + typedef typename _Tp_alloc_traits::const_reference const_reference; + typedef _List_iterator<_Tp> iterator; + typedef _List_const_iterator<_Tp> const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + protected: + // Note that pointers-to-_Node's can be ctor-converted to + // iterator types. + typedef _List_node<_Tp> _Node; + + using _Base::_M_impl; + using _Base::_M_put_node; + using _Base::_M_get_node; + using _Base::_M_get_Node_allocator; + + /** + * @param __args An instance of user data. + * + * Allocates space for a new node and constructs a copy of + * @a __args in it. + */ +#if __cplusplus < 201103L + _Node* + _M_create_node(const value_type& __x) + { + _Node* __p = this->_M_get_node(); + __try + { + _Tp_alloc_type __alloc(_M_get_Node_allocator()); + __alloc.construct(__p->_M_valptr(), __x); + } + __catch(...) + { + _M_put_node(__p); + __throw_exception_again; + } + return __p; + } +#else + template + _Node* + _M_create_node(_Args&&... __args) + { + auto __p = this->_M_get_node(); + auto& __alloc = _M_get_Node_allocator(); + __allocated_ptr<_Node_alloc_type> __guard{__alloc, __p}; + _Node_alloc_traits::construct(__alloc, __p->_M_valptr(), + std::forward<_Args>(__args)...); + __guard = nullptr; + return __p; + } +#endif + +#if _GLIBCXX_USE_CXX11_ABI + static size_t + _S_distance(const_iterator __first, const_iterator __last) + { return std::distance(__first, __last); } + + // return the stored size + size_t + _M_node_count() const + { return this->_M_get_size(); } +#else + // dummy implementations used when the size is not stored + static size_t + _S_distance(const_iterator, const_iterator) + { return 0; } + + // count the number of nodes + size_t + _M_node_count() const + { return std::distance(begin(), end()); } +#endif + + public: + // [23.2.2.1] construct/copy/destroy + // (assign() and get_allocator() are also listed in this section) + + /** + * @brief Creates a %list with no elements. + */ +#if __cplusplus >= 201103L + list() = default; +#else + list() { } +#endif + + /** + * @brief Creates a %list with no elements. + * @param __a An allocator object. + */ + explicit + list(const allocator_type& __a) _GLIBCXX_NOEXCEPT + : _Base(_Node_alloc_type(__a)) { } + +#if __cplusplus >= 201103L + /** + * @brief Creates a %list with default constructed elements. + * @param __n The number of elements to initially create. + * @param __a An allocator object. + * + * This constructor fills the %list with @a __n default + * constructed elements. + */ + explicit + list(size_type __n, const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_default_initialize(__n); } + + /** + * @brief Creates a %list with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator object. + * + * This constructor fills the %list with @a __n copies of @a __value. + */ + list(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_fill_initialize(__n, __value); } +#else + /** + * @brief Creates a %list with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator object. + * + * This constructor fills the %list with @a __n copies of @a __value. + */ + explicit + list(size_type __n, const value_type& __value = value_type(), + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_fill_initialize(__n, __value); } +#endif + + /** + * @brief %List copy constructor. + * @param __x A %list of identical element and allocator types. + * + * The newly-created %list uses a copy of the allocation object used + * by @a __x (unless the allocator traits dictate a different object). + */ + list(const list& __x) + : _Base(_Node_alloc_traits:: + _S_select_on_copy(__x._M_get_Node_allocator())) + { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } + +#if __cplusplus >= 201103L + /** + * @brief %List move constructor. + * + * The newly-created %list contains the exact contents of the moved + * instance. The contents of the moved instance are a valid, but + * unspecified %list. + */ + list(list&&) = default; + + /** + * @brief Builds a %list from an initializer_list + * @param __l An initializer_list of value_type. + * @param __a An allocator object. + * + * Create a %list consisting of copies of the elements in the + * initializer_list @a __l. This is linear in __l.size(). + */ + list(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); } + + list(const list& __x, const allocator_type& __a) + : _Base(_Node_alloc_type(__a)) + { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } + + private: + list(list&& __x, const allocator_type& __a, true_type) noexcept + : _Base(_Node_alloc_type(__a), std::move(__x)) + { } + + list(list&& __x, const allocator_type& __a, false_type) + : _Base(_Node_alloc_type(__a)) + { + if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator()) + this->_M_move_nodes(std::move(__x)); + else + insert(begin(), std::__make_move_if_noexcept_iterator(__x.begin()), + std::__make_move_if_noexcept_iterator(__x.end())); + } + + public: + list(list&& __x, const allocator_type& __a) + noexcept(_Node_alloc_traits::_S_always_equal()) + : list(std::move(__x), __a, + typename _Node_alloc_traits::is_always_equal{}) + { } +#endif + + /** + * @brief Builds a %list from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __a An allocator object. + * + * Create a %list consisting of copies of the elements from + * [@a __first,@a __last). This is linear in N (where N is + * distance(@a __first,@a __last)). + */ +#if __cplusplus >= 201103L + template> + list(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_initialize_dispatch(__first, __last, __false_type()); } +#else + template + list(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + /** + * No explicit dtor needed as the _Base dtor takes care of + * things. The _Base dtor only erases the elements, and note + * that if the elements themselves are pointers, the pointed-to + * memory is not touched in any way. Managing the pointer is + * the user's responsibility. + */ + ~list() = default; +#endif + + /** + * @brief %List assignment operator. + * @param __x A %list of identical element and allocator types. + * + * All the elements of @a __x are copied. + * + * Whether the allocator is copied depends on the allocator traits. + */ + list& + operator=(const list& __x); + +#if __cplusplus >= 201103L + /** + * @brief %List move assignment operator. + * @param __x A %list of identical element and allocator types. + * + * The contents of @a __x are moved into this %list (without copying). + * + * Afterwards @a __x is a valid, but unspecified %list + * + * Whether the allocator is moved depends on the allocator traits. + */ + list& + operator=(list&& __x) + noexcept(_Node_alloc_traits::_S_nothrow_move()) + { + constexpr bool __move_storage = + _Node_alloc_traits::_S_propagate_on_move_assign() + || _Node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); + return *this; + } + + /** + * @brief %List initializer list assignment operator. + * @param __l An initializer_list of value_type. + * + * Replace the contents of the %list with copies of the elements + * in the initializer_list @a __l. This is linear in l.size(). + */ + list& + operator=(initializer_list __l) + { + this->assign(__l.begin(), __l.end()); + return *this; + } +#endif + + /** + * @brief Assigns a given value to a %list. + * @param __n Number of elements to be assigned. + * @param __val Value to be assigned. + * + * This function fills a %list with @a __n copies of the given + * value. Note that the assignment completely changes the %list + * and that the resulting %list's size is the same as the number + * of elements assigned. + */ + void + assign(size_type __n, const value_type& __val) + { _M_fill_assign(__n, __val); } + + /** + * @brief Assigns a range to a %list. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function fills a %list with copies of the elements in the + * range [@a __first,@a __last). + * + * Note that the assignment completely changes the %list and + * that the resulting %list's size is the same as the number of + * elements assigned. + */ +#if __cplusplus >= 201103L + template> + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_dispatch(__first, __last, __false_type()); } +#else + template + void + assign(_InputIterator __first, _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Assigns an initializer_list to a %list. + * @param __l An initializer_list of value_type. + * + * Replace the contents of the %list with copies of the elements + * in the initializer_list @a __l. This is linear in __l.size(). + */ + void + assign(initializer_list __l) + { this->_M_assign_dispatch(__l.begin(), __l.end(), __false_type()); } +#endif + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_Base::_M_get_Node_allocator()); } + + // iterators + /** + * Returns a read/write iterator that points to the first element in the + * %list. Iteration is done in ordinary element order. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_node._M_next); } + + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %list. Iteration is done in ordinary + * element order. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_node._M_next); } + + /** + * Returns a read/write iterator that points one past the last + * element in the %list. Iteration is done in ordinary element + * order. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return iterator(&this->_M_impl._M_node); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %list. Iteration is done in ordinary + * element order. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return const_iterator(&this->_M_impl._M_node); } + + /** + * Returns a read/write reverse iterator that points to the last + * element in the %list. Iteration is done in reverse element + * order. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points to + * the last element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(end()); } + + /** + * Returns a read/write reverse iterator that points to one + * before the first element in the %list. Iteration is done in + * reverse element order. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(begin()); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(begin()); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %list. Iteration is done in ordinary + * element order. + */ + const_iterator + cbegin() const noexcept + { return const_iterator(this->_M_impl._M_node._M_next); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %list. Iteration is done in ordinary + * element order. + */ + const_iterator + cend() const noexcept + { return const_iterator(&this->_M_impl._M_node); } + + /** + * Returns a read-only (constant) reverse iterator that points to + * the last element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } +#endif + + // [23.2.2.2] capacity + /** + * Returns true if the %list is empty. (Thus begin() would equal + * end().) + */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_node._M_next == &this->_M_impl._M_node; } + + /** Returns the number of elements in the %list. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_node_count(); } + + /** Returns the size() of the largest possible %list. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _Node_alloc_traits::max_size(_M_get_Node_allocator()); } + +#if __cplusplus >= 201103L + /** + * @brief Resizes the %list to the specified number of elements. + * @param __new_size Number of elements the %list should contain. + * + * This function will %resize the %list to the specified number + * of elements. If the number is smaller than the %list's + * current size the %list is truncated, otherwise default + * constructed elements are appended. + */ + void + resize(size_type __new_size); + + /** + * @brief Resizes the %list to the specified number of elements. + * @param __new_size Number of elements the %list should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %list to the specified number + * of elements. If the number is smaller than the %list's + * current size the %list is truncated, otherwise the %list is + * extended and new elements are populated with given data. + */ + void + resize(size_type __new_size, const value_type& __x); +#else + /** + * @brief Resizes the %list to the specified number of elements. + * @param __new_size Number of elements the %list should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %list to the specified number + * of elements. If the number is smaller than the %list's + * current size the %list is truncated, otherwise the %list is + * extended and new elements are populated with given data. + */ + void + resize(size_type __new_size, value_type __x = value_type()); +#endif + + // element access + /** + * Returns a read/write reference to the data at the first + * element of the %list. + */ + reference + front() _GLIBCXX_NOEXCEPT + { return *begin(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %list. + */ + const_reference + front() const _GLIBCXX_NOEXCEPT + { return *begin(); } + + /** + * Returns a read/write reference to the data at the last element + * of the %list. + */ + reference + back() _GLIBCXX_NOEXCEPT + { + iterator __tmp = end(); + --__tmp; + return *__tmp; + } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %list. + */ + const_reference + back() const _GLIBCXX_NOEXCEPT + { + const_iterator __tmp = end(); + --__tmp; + return *__tmp; + } + + // [23.2.2.3] modifiers + /** + * @brief Add data to the front of the %list. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the front of the %list and assigns the given data + * to it. Due to the nature of a %list this operation can be + * done in constant time, and does not invalidate iterators and + * references. + */ + void + push_front(const value_type& __x) + { this->_M_insert(begin(), __x); } + +#if __cplusplus >= 201103L + void + push_front(value_type&& __x) + { this->_M_insert(begin(), std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_front(_Args&&... __args) + { + this->_M_insert(begin(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif + } +#endif + + /** + * @brief Removes first element. + * + * This is a typical stack operation. It shrinks the %list by + * one. Due to the nature of a %list this operation can be done + * in constant time, and only invalidates iterators/references to + * the element being removed. + * + * Note that no data is returned, and if the first element's data + * is needed, it should be retrieved before pop_front() is + * called. + */ + void + pop_front() _GLIBCXX_NOEXCEPT + { this->_M_erase(begin()); } + + /** + * @brief Add data to the end of the %list. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the end of the %list and assigns the given data to + * it. Due to the nature of a %list this operation can be done + * in constant time, and does not invalidate iterators and + * references. + */ + void + push_back(const value_type& __x) + { this->_M_insert(end(), __x); } + +#if __cplusplus >= 201103L + void + push_back(value_type&& __x) + { this->_M_insert(end(), std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args) + { + this->_M_insert(end(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif + } +#endif + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %list by + * one. Due to the nature of a %list this operation can be done + * in constant time, and only invalidates iterators/references to + * the element being removed. + * + * Note that no data is returned, and if the last element's data + * is needed, it should be retrieved before pop_back() is called. + */ + void + pop_back() _GLIBCXX_NOEXCEPT + { this->_M_erase(iterator(this->_M_impl._M_node._M_prev)); } + +#if __cplusplus >= 201103L + /** + * @brief Constructs object in %list before specified iterator. + * @param __position A const_iterator into the %list. + * @param __args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) before the specified + * location. Due to the nature of a %list this operation can + * be done in constant time, and does not invalidate iterators + * and references. + */ + template + iterator + emplace(const_iterator __position, _Args&&... __args); + + /** + * @brief Inserts given value into %list before specified iterator. + * @param __position A const_iterator into the %list. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before + * the specified location. Due to the nature of a %list this + * operation can be done in constant time, and does not + * invalidate iterators and references. + */ + iterator + insert(const_iterator __position, const value_type& __x); +#else + /** + * @brief Inserts given value into %list before specified iterator. + * @param __position An iterator into the %list. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before + * the specified location. Due to the nature of a %list this + * operation can be done in constant time, and does not + * invalidate iterators and references. + */ + iterator + insert(iterator __position, const value_type& __x); +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts given rvalue into %list before specified iterator. + * @param __position A const_iterator into the %list. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given rvalue before + * the specified location. Due to the nature of a %list this + * operation can be done in constant time, and does not + * invalidate iterators and references. + */ + iterator + insert(const_iterator __position, value_type&& __x) + { return emplace(__position, std::move(__x)); } + + /** + * @brief Inserts the contents of an initializer_list into %list + * before specified const_iterator. + * @param __p A const_iterator into the %list. + * @param __l An initializer_list of value_type. + * @return An iterator pointing to the first element inserted + * (or __position). + * + * This function will insert copies of the data in the + * initializer_list @a l into the %list before the location + * specified by @a p. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + iterator + insert(const_iterator __p, initializer_list __l) + { return this->insert(__p, __l.begin(), __l.end()); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a number of copies of given data into the %list. + * @param __position A const_iterator into the %list. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * @return An iterator pointing to the first element inserted + * (or __position). + * + * This function will insert a specified number of copies of the + * given data before the location specified by @a position. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + iterator + insert(const_iterator __position, size_type __n, const value_type& __x); +#else + /** + * @brief Inserts a number of copies of given data into the %list. + * @param __position An iterator into the %list. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * + * This function will insert a specified number of copies of the + * given data before the location specified by @a position. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + void + insert(iterator __position, size_type __n, const value_type& __x) + { + list __tmp(__n, __x, get_allocator()); + splice(__position, __tmp); + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a range into the %list. + * @param __position A const_iterator into the %list. + * @param __first An input iterator. + * @param __last An input iterator. + * @return An iterator pointing to the first element inserted + * (or __position). + * + * This function will insert copies of the data in the range [@a + * first,@a last) into the %list before the location specified by + * @a position. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + template> + iterator + insert(const_iterator __position, _InputIterator __first, + _InputIterator __last); +#else + /** + * @brief Inserts a range into the %list. + * @param __position An iterator into the %list. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function will insert copies of the data in the range [@a + * first,@a last) into the %list before the location specified by + * @a position. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + template + void + insert(iterator __position, _InputIterator __first, + _InputIterator __last) + { + list __tmp(__first, __last, get_allocator()); + splice(__position, __tmp); + } +#endif + + /** + * @brief Remove element at given position. + * @param __position Iterator pointing to element to be erased. + * @return An iterator pointing to the next element (or end()). + * + * This function will erase the element at the given position and thus + * shorten the %list by one. + * + * Due to the nature of a %list this operation can be done in + * constant time, and only invalidates iterators/references to + * the element being removed. The user is also cautioned that + * this function only erases the element, and that if the element + * is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) noexcept; +#else + erase(iterator __position); +#endif + + /** + * @brief Remove a range of elements. + * @param __first Iterator pointing to the first element to be erased. + * @param __last Iterator pointing to one past the last element to be + * erased. + * @return An iterator pointing to the element pointed to by @a last + * prior to erasing (or end()). + * + * This function will erase the elements in the range @a + * [first,last) and shorten the %list accordingly. + * + * This operation is linear time in the size of the range and only + * invalidates iterators/references to the element being removed. + * The user is also cautioned that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) noexcept +#else + erase(iterator __first, iterator __last) +#endif + { + while (__first != __last) + __first = erase(__first); + return __last._M_const_cast(); + } + + /** + * @brief Swaps data with another %list. + * @param __x A %list of the same element and allocator types. + * + * This exchanges the elements between two lists in constant + * time. Note that the global std::swap() function is + * specialized such that std::swap(l1,l2) will feed to this + * function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(list& __x) _GLIBCXX_NOEXCEPT + { + __detail::_List_node_base::swap(this->_M_impl._M_node, + __x._M_impl._M_node); + + size_t __xsize = __x._M_get_size(); + __x._M_set_size(this->_M_get_size()); + this->_M_set_size(__xsize); + + _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(), + __x._M_get_Node_allocator()); + } + + /** + * Erases all the elements. Note that this function only erases + * the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { + _Base::_M_clear(); + _Base::_M_init(); + } + + // [23.2.2.4] list operations + /** + * @brief Insert contents of another %list. + * @param __position Iterator referencing the element to insert before. + * @param __x Source list. + * + * The elements of @a __x are inserted in constant time in front of + * the element referenced by @a __position. @a __x becomes an empty + * list. + * + * Requires this != @a __x. + */ + void +#if __cplusplus >= 201103L + splice(const_iterator __position, list&& __x) noexcept +#else + splice(iterator __position, list& __x) +#endif + { + if (!__x.empty()) + { + _M_check_equal_allocators(__x); + + this->_M_transfer(__position._M_const_cast(), + __x.begin(), __x.end()); + + this->_M_inc_size(__x._M_get_size()); + __x._M_set_size(0); + } + } + +#if __cplusplus >= 201103L + void + splice(const_iterator __position, list& __x) noexcept + { splice(__position, std::move(__x)); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Insert element from another %list. + * @param __position Const_iterator referencing the element to + * insert before. + * @param __x Source list. + * @param __i Const_iterator referencing the element to move. + * + * Removes the element in list @a __x referenced by @a __i and + * inserts it into the current list before @a __position. + */ + void + splice(const_iterator __position, list&& __x, const_iterator __i) noexcept +#else + /** + * @brief Insert element from another %list. + * @param __position Iterator referencing the element to insert before. + * @param __x Source list. + * @param __i Iterator referencing the element to move. + * + * Removes the element in list @a __x referenced by @a __i and + * inserts it into the current list before @a __position. + */ + void + splice(iterator __position, list& __x, iterator __i) +#endif + { + iterator __j = __i._M_const_cast(); + ++__j; + if (__position == __i || __position == __j) + return; + + if (this != std::__addressof(__x)) + _M_check_equal_allocators(__x); + + this->_M_transfer(__position._M_const_cast(), + __i._M_const_cast(), __j); + + this->_M_inc_size(1); + __x._M_dec_size(1); + } + +#if __cplusplus >= 201103L + /** + * @brief Insert element from another %list. + * @param __position Const_iterator referencing the element to + * insert before. + * @param __x Source list. + * @param __i Const_iterator referencing the element to move. + * + * Removes the element in list @a __x referenced by @a __i and + * inserts it into the current list before @a __position. + */ + void + splice(const_iterator __position, list& __x, const_iterator __i) noexcept + { splice(__position, std::move(__x), __i); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Insert range from another %list. + * @param __position Const_iterator referencing the element to + * insert before. + * @param __x Source list. + * @param __first Const_iterator referencing the start of range in x. + * @param __last Const_iterator referencing the end of range in x. + * + * Removes elements in the range [__first,__last) and inserts them + * before @a __position in constant time. + * + * Undefined if @a __position is in [__first,__last). + */ + void + splice(const_iterator __position, list&& __x, const_iterator __first, + const_iterator __last) noexcept +#else + /** + * @brief Insert range from another %list. + * @param __position Iterator referencing the element to insert before. + * @param __x Source list. + * @param __first Iterator referencing the start of range in x. + * @param __last Iterator referencing the end of range in x. + * + * Removes elements in the range [__first,__last) and inserts them + * before @a __position in constant time. + * + * Undefined if @a __position is in [__first,__last). + */ + void + splice(iterator __position, list& __x, iterator __first, + iterator __last) +#endif + { + if (__first != __last) + { + if (this != std::__addressof(__x)) + _M_check_equal_allocators(__x); + + size_t __n = _S_distance(__first, __last); + this->_M_inc_size(__n); + __x._M_dec_size(__n); + + this->_M_transfer(__position._M_const_cast(), + __first._M_const_cast(), + __last._M_const_cast()); + } + } + +#if __cplusplus >= 201103L + /** + * @brief Insert range from another %list. + * @param __position Const_iterator referencing the element to + * insert before. + * @param __x Source list. + * @param __first Const_iterator referencing the start of range in x. + * @param __last Const_iterator referencing the end of range in x. + * + * Removes elements in the range [__first,__last) and inserts them + * before @a __position in constant time. + * + * Undefined if @a __position is in [__first,__last). + */ + void + splice(const_iterator __position, list& __x, const_iterator __first, + const_iterator __last) noexcept + { splice(__position, std::move(__x), __first, __last); } +#endif + + private: +#if __cplusplus > 201703L +# define __cpp_lib_list_remove_return_type 201806L + typedef size_type __remove_return_type; +# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG \ + __attribute__((__abi_tag__("__cxx20"))) +#else + typedef void __remove_return_type; +# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG +#endif + public: + + /** + * @brief Remove all elements equal to value. + * @param __value The value to remove. + * + * Removes every element in the list equal to @a value. + * Remaining elements stay in list order. Note that this + * function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type + remove(const _Tp& __value); + + /** + * @brief Remove all elements satisfying a predicate. + * @tparam _Predicate Unary predicate function or object. + * + * Removes every element in the list for which the predicate + * returns true. Remaining elements stay in list order. Note + * that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + template + __remove_return_type + remove_if(_Predicate); + + /** + * @brief Remove consecutive duplicate elements. + * + * For each consecutive set of elements with the same value, + * remove all but the first one. Remaining elements stay in + * list order. Note that this function only erases the + * elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + */ + _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type + unique(); + + /** + * @brief Remove consecutive elements satisfying a predicate. + * @tparam _BinaryPredicate Binary predicate function or object. + * + * For each consecutive set of elements [first,last) that + * satisfy predicate(first,i) where i is an iterator in + * [first,last), remove all but the first one. Remaining + * elements stay in list order. Note that this function only + * erases the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + template + __remove_return_type + unique(_BinaryPredicate); + +#undef _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG + + /** + * @brief Merge sorted lists. + * @param __x Sorted list to merge. + * + * Assumes that both @a __x and this list are sorted according to + * operator<(). Merges elements of @a __x into this list in + * sorted order, leaving @a __x empty when complete. Elements in + * this list precede elements in @a __x that are equal. + */ +#if __cplusplus >= 201103L + void + merge(list&& __x); + + void + merge(list& __x) + { merge(std::move(__x)); } +#else + void + merge(list& __x); +#endif + + /** + * @brief Merge sorted lists according to comparison function. + * @tparam _StrictWeakOrdering Comparison function defining + * sort order. + * @param __x Sorted list to merge. + * @param __comp Comparison functor. + * + * Assumes that both @a __x and this list are sorted according to + * StrictWeakOrdering. Merges elements of @a __x into this list + * in sorted order, leaving @a __x empty when complete. Elements + * in this list precede elements in @a __x that are equivalent + * according to StrictWeakOrdering(). + */ +#if __cplusplus >= 201103L + template + void + merge(list&& __x, _StrictWeakOrdering __comp); + + template + void + merge(list& __x, _StrictWeakOrdering __comp) + { merge(std::move(__x), __comp); } +#else + template + void + merge(list& __x, _StrictWeakOrdering __comp); +#endif + + /** + * @brief Reverse the elements in list. + * + * Reverse the order of elements in the list in linear time. + */ + void + reverse() _GLIBCXX_NOEXCEPT + { this->_M_impl._M_node._M_reverse(); } + + /** + * @brief Sort the elements. + * + * Sorts the elements of this list in NlogN time. Equivalent + * elements remain in list order. + */ + void + sort(); + + /** + * @brief Sort the elements according to comparison function. + * + * Sorts the elements of this list in NlogN time. Equivalent + * elements remain in list order. + */ + template + void + sort(_StrictWeakOrdering); + + protected: + // Internal constructor functions follow. + + // Called by the range constructor to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { _M_fill_initialize(static_cast(__n), __x); } + + // Called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else + push_back(*__first); +#endif + } + + // Called by list(n,v,a), and the range constructor when it turns out + // to be the same thing. + void + _M_fill_initialize(size_type __n, const value_type& __x) + { + for (; __n; --__n) + push_back(__x); + } + +#if __cplusplus >= 201103L + // Called by list(n). + void + _M_default_initialize(size_type __n) + { + for (; __n; --__n) + emplace_back(); + } + + // Called by resize(sz). + void + _M_default_append(size_type __n); +#endif + + // Internal assign functions follow. + + // Called by the range assign to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + + // Called by the range assign to implement [23.1.1]/9 + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type); + + // Called by assign(n,t), and the range assign when it turns out + // to be the same thing. + void + _M_fill_assign(size_type __n, const value_type& __val); + + + // Moves the elements from [first,last) before position. + void + _M_transfer(iterator __position, iterator __first, iterator __last) + { __position._M_node->_M_transfer(__first._M_node, __last._M_node); } + + // Inserts new element at position given and with value given. +#if __cplusplus < 201103L + void + _M_insert(iterator __position, const value_type& __x) + { + _Node* __tmp = _M_create_node(__x); + __tmp->_M_hook(__position._M_node); + this->_M_inc_size(1); + } +#else + template + void + _M_insert(iterator __position, _Args&&... __args) + { + _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...); + __tmp->_M_hook(__position._M_node); + this->_M_inc_size(1); + } +#endif + + // Erases element at position given. + void + _M_erase(iterator __position) _GLIBCXX_NOEXCEPT + { + this->_M_dec_size(1); + __position._M_node->_M_unhook(); + _Node* __n = static_cast<_Node*>(__position._M_node); +#if __cplusplus >= 201103L + _Node_alloc_traits::destroy(_M_get_Node_allocator(), __n->_M_valptr()); +#else + _Tp_alloc_type(_M_get_Node_allocator()).destroy(__n->_M_valptr()); +#endif + + _M_put_node(__n); + } + + // To implement the splice (and merge) bits of N1599. + void + _M_check_equal_allocators(list& __x) _GLIBCXX_NOEXCEPT + { + if (std::__alloc_neq:: + _S_do_it(_M_get_Node_allocator(), __x._M_get_Node_allocator())) + __builtin_abort(); + } + + // Used to implement resize. + const_iterator + _M_resize_pos(size_type& __new_size) const; + +#if __cplusplus >= 201103L + void + _M_move_assign(list&& __x, true_type) noexcept + { + this->_M_clear(); + this->_M_move_nodes(std::move(__x)); + std::__alloc_on_move(this->_M_get_Node_allocator(), + __x._M_get_Node_allocator()); + } + + void + _M_move_assign(list&& __x, false_type) + { + if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator()) + _M_move_assign(std::move(__x), true_type{}); + else + // The rvalue's allocator cannot be moved, or is not equal, + // so we need to individually move each element. + _M_assign_dispatch(std::make_move_iterator(__x.begin()), + std::make_move_iterator(__x.end()), + __false_type{}); + } +#endif + }; + +#if __cpp_deduction_guides >= 201606 + template::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + list(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> list<_ValT, _Allocator>; +#endif + +_GLIBCXX_END_NAMESPACE_CXX11 + + /** + * @brief List equality comparison. + * @param __x A %list. + * @param __y A %list of the same type as @a __x. + * @return True iff the size and elements of the lists are equal. + * + * This is an equivalence relation. It is linear in the size of + * the lists. Lists are considered equivalent if their sizes are + * equal, and if corresponding elements compare equal. + */ + template + inline bool + operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { +#if _GLIBCXX_USE_CXX11_ABI + if (__x.size() != __y.size()) + return false; +#endif + + typedef typename list<_Tp, _Alloc>::const_iterator const_iterator; + const_iterator __end1 = __x.end(); + const_iterator __end2 = __y.end(); + + const_iterator __i1 = __x.begin(); + const_iterator __i2 = __y.begin(); + while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) + { + ++__i1; + ++__i2; + } + return __i1 == __end1 && __i2 == __end2; + } + +#if __cpp_lib_three_way_comparison +/** + * @brief List ordering relation. + * @param __x A `list`. + * @param __y A `list` of the same type as `__x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Tp> + operator<=>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + /** + * @brief List ordering relation. + * @param __x A %list. + * @param __y A %list of the same type as @a __x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * lists. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } + + /// Based on operator== + template + inline bool + operator!=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::list::swap(). + template + inline void + swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if _GLIBCXX_USE_CXX11_ABI + + // Detect when distance is used to compute the size of the whole list. + template + inline ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_iterator<_Tp> __first, + _GLIBCXX_STD_C::_List_iterator<_Tp> __last, + input_iterator_tag __tag) + { + typedef _GLIBCXX_STD_C::_List_const_iterator<_Tp> _CIter; + return std::__distance(_CIter(__first), _CIter(__last), __tag); + } + + template + inline ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp> __first, + _GLIBCXX_STD_C::_List_const_iterator<_Tp> __last, + input_iterator_tag) + { + typedef __detail::_List_node_header _Sentinel; + _GLIBCXX_STD_C::_List_const_iterator<_Tp> __beyond = __last; + ++__beyond; + const bool __whole = __first == __beyond; + if (__builtin_constant_p (__whole) && __whole) + return static_cast(__last._M_node)->_M_size; + + ptrdiff_t __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_LIST_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_map.h b/resources/sources/avr-libstdcpp/include/bits/stl_map.h new file mode 100644 index 000000000..2772d1146 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_map.h @@ -0,0 +1,1568 @@ +// Map implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_map.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{map} + */ + +#ifndef _STL_MAP_H +#define _STL_MAP_H 1 + +#include +#include +#if __cplusplus >= 201103L +#include +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + class multimap; + + /** + * @brief A standard container made up of (key,value) pairs, which can be + * retrieved based on a key, in logarithmic time. + * + * @ingroup associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Compare Comparison function object type, defaults to less<_Key>. + * @tparam _Alloc Allocator type, defaults to + * allocator. + * + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using unique keys). + * For a @c map the key_type is Key, the mapped_type is T, and the + * value_type is std::pair. + * + * Maps support bidirectional iterators. + * + * The private tree data is declared exactly the same way for map and + * multimap; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + */ + template , + typename _Alloc = std::allocator > > + class map + { + public: + typedef _Key key_type; + typedef _Tp mapped_type; + typedef std::pair value_type; + typedef _Compare key_compare; + typedef _Alloc allocator_type; + + private: +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires4(_Compare, bool, _Key, _Key, + _BinaryFunctionConcept) + __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L +#if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::map must have the same value_type as its allocator"); +#endif +#endif + + public: + class value_compare + : public std::binary_function + { + friend class map<_Key, _Tp, _Compare, _Alloc>; + protected: + _Compare comp; + + value_compare(_Compare __c) + : comp(__c) { } + + public: + bool operator()(const value_type& __x, const value_type& __y) const + { return comp(__x.first, __y.first); } + }; + + private: + /// This turns a red-black tree into a [multi]map. + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind::other _Pair_alloc_type; + + typedef _Rb_tree, + key_compare, _Pair_alloc_type> _Rep_type; + + /// The actual tree structure. + _Rep_type _M_t; + + typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits; + + public: + // many of these are specified differently in ISO, but the following are + // "functionally equivalent" + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + typedef typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; + using insert_return_type = typename _Rep_type::insert_return_type; +#endif + + // [23.3.1.1] construct/copy/destroy + // (get_allocator() is also listed in this section) + + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + map() : _M_t() { } +#else + map() = default; +#endif + + /** + * @brief Creates a %map with no elements. + * @param __comp A comparison object. + * @param __a An allocator object. + */ + explicit + map(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) { } + + /** + * @brief %Map copy constructor. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + map(const map& __x) + : _M_t(__x._M_t) { } +#else + map(const map&) = default; + + /** + * @brief %Map move constructor. + * + * The newly-created %map contains the exact contents of the moved + * instance. The moved instance is a valid, but unspecified, %map. + */ + map(map&&) = default; + + /** + * @brief Builds a %map from an initializer_list. + * @param __l An initializer_list. + * @param __comp A comparison object. + * @param __a An allocator object. + * + * Create a %map consisting of copies of the elements in the + * initializer_list @a __l. + * This is linear in N if the range is already sorted, and NlogN + * otherwise (where N is @a __l.size()). + */ + map(initializer_list __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) + { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } + + /// Allocator-extended default constructor. + explicit + map(const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) { } + + /// Allocator-extended copy constructor. + map(const map& __m, const allocator_type& __a) + : _M_t(__m._M_t, _Pair_alloc_type(__a)) { } + + /// Allocator-extended move constructor. + map(map&& __m, const allocator_type& __a) + noexcept(is_nothrow_copy_constructible<_Compare>::value + && _Alloc_traits::_S_always_equal()) + : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { } + + /// Allocator-extended initialier-list constructor. + map(initializer_list __l, const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) + { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } + + /// Allocator-extended range constructor. + template + map(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) + { _M_t._M_insert_range_unique(__first, __last); } +#endif + + /** + * @brief Builds a %map from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * + * Create a %map consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is + * already sorted, and NlogN otherwise (where N is + * distance(__first,__last)). + */ + template + map(_InputIterator __first, _InputIterator __last) + : _M_t() + { _M_t._M_insert_range_unique(__first, __last); } + + /** + * @brief Builds a %map from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %map consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is + * already sorted, and NlogN otherwise (where N is + * distance(__first,__last)). + */ + template + map(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) + { _M_t._M_insert_range_unique(__first, __last); } + +#if __cplusplus >= 201103L + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~map() = default; +#endif + + /** + * @brief %Map assignment operator. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + map& + operator=(const map& __x) + { + _M_t = __x._M_t; + return *this; + } +#else + map& + operator=(const map&) = default; + + /// Move assignment operator. + map& + operator=(map&&) = default; + + /** + * @brief %Map list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %map with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %map and + * that the resulting %map's size is the same as the number + * of elements assigned. + */ + map& + operator=(initializer_list __l) + { + _M_t._M_assign_unique(__l.begin(), __l.end()); + return *this; + } +#endif + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_t.get_allocator()); } + + // iterators + /** + * Returns a read/write iterator that points to the first pair in the + * %map. + * Iteration is done in ascending order according to the keys. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %map. Iteration is done in ascending order according to the + * keys. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read/write iterator that points one past the last + * pair in the %map. Iteration is done in ascending order + * according to the keys. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %map. Iteration is done in ascending order according to + * the keys. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read/write reverse iterator that points to the last pair in + * the %map. Iteration is done in descending order according to the + * keys. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %map. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first pair in the %map. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %map. Iteration is done in descending + * order according to the keys. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %map. Iteration is done in ascending order according to the + * keys. + */ + const_iterator + cbegin() const noexcept + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %map. Iteration is done in ascending order according to + * the keys. + */ + const_iterator + cend() const noexcept + { return _M_t.end(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %map. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator + crbegin() const noexcept + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %map. Iteration is done in descending + * order according to the keys. + */ + const_reverse_iterator + crend() const noexcept + { return _M_t.rend(); } +#endif + + // capacity + /** Returns true if the %map is empty. (Thus begin() would equal + * end().) + */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_t.empty(); } + + /** Returns the size of the %map. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_t.size(); } + + /** Returns the maximum size of the %map. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _M_t.max_size(); } + + // [23.3.1.2] element access + /** + * @brief Subscript ( @c [] ) access to %map data. + * @param __k The key for which data should be retrieved. + * @return A reference to the data of the (key,data) %pair. + * + * Allows for easy lookup with the subscript ( @c [] ) + * operator. Returns data associated with the key specified in + * subscript. If the key does not exist, a pair with that key + * is created using default values, which is then returned. + * + * Lookup requires logarithmic time. + */ + mapped_type& + operator[](const key_type& __k) + { + // concept requirements + __glibcxx_function_requires(_DefaultConstructibleConcept) + + iterator __i = lower_bound(__k); + // __i->first is greater than or equivalent to __k. + if (__i == end() || key_comp()(__k, (*__i).first)) +#if __cplusplus >= 201103L + __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct, + std::tuple(__k), + std::tuple<>()); +#else + __i = insert(__i, value_type(__k, mapped_type())); +#endif + return (*__i).second; + } + +#if __cplusplus >= 201103L + mapped_type& + operator[](key_type&& __k) + { + // concept requirements + __glibcxx_function_requires(_DefaultConstructibleConcept) + + iterator __i = lower_bound(__k); + // __i->first is greater than or equivalent to __k. + if (__i == end() || key_comp()(__k, (*__i).first)) + __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::tuple<>()); + return (*__i).second; + } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + /** + * @brief Access to %map data. + * @param __k The key for which data should be retrieved. + * @return A reference to the data whose key is equivalent to @a __k, if + * such a data is present in the %map. + * @throw std::out_of_range If no such data is present. + */ + mapped_type& + at(const key_type& __k) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + __throw_out_of_range(__N("map::at")); + return (*__i).second; + } + + const mapped_type& + at(const key_type& __k) const + { + const_iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + __throw_out_of_range(__N("map::at")); + return (*__i).second; + } + + // modifiers +#if __cplusplus >= 201103L + /** + * @brief Attempts to build and insert a std::pair into the %map. + * + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to build and insert a (key, value) %pair into + * the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * + * Insertion requires logarithmic time. + */ + template + std::pair + emplace(_Args&&... __args) + { return _M_t._M_emplace_unique(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to build and insert a std::pair into the %map. + * + * @param __pos An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * @return An iterator that points to the element with key of the + * std::pair built from @a __args (may or may not be that + * std::pair). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { + return _M_t._M_emplace_hint_unique(__pos, + std::forward<_Args>(__args)...); + } +#endif + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_unique(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); } + + template + friend class std::_Rb_tree_merge_helper; + + template + void + merge(map<_Key, _Tp, _Cmp2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(map<_Key, _Tp, _Cmp2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(multimap<_Key, _Tp, _Cmp2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(multimap<_Key, _Tp, _Cmp2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus > 201402L +#define __cpp_lib_map_try_emplace 201411 + /** + * @brief Attempts to build and insert a std::pair into the %map. + * + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __args Arguments used to generate the .second for a new pair + * instance. + * + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to build and insert a (key, value) %pair into + * the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * If a %pair is not inserted, this function has no effect. + * + * Insertion requires logarithmic time. + */ + template + pair + try_emplace(const key_type& __k, _Args&&... __args) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return {__i, true}; + } + return {__i, false}; + } + + // move-capable overload + template + pair + try_emplace(key_type&& __k, _Args&&... __args) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return {__i, true}; + } + return {__i, false}; + } + + /** + * @brief Attempts to build and insert a std::pair into the %map. + * + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __args Arguments used to generate the .second for a new pair + * instance. + * @return An iterator that points to the element with key of the + * std::pair built from @a __args (may or may not be that + * std::pair). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument + * try_emplace() does. However, if insertion did not take place, + * this function has no effect. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + try_emplace(const_iterator __hint, const key_type& __k, + _Args&&... __args) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + __i = emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + else + __i = iterator(__true_hint.first); + return __i; + } + + // move-capable overload + template + iterator + try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + __i = emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + else + __i = iterator(__true_hint.first); + return __i; + } +#endif + + /** + * @brief Attempts to insert a std::pair into the %map. + * @param __x Pair to be inserted (see std::make_pair for easy + * creation of pairs). + * + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is + * a bool that is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * + * Insertion requires logarithmic time. + * @{ + */ + std::pair + insert(const value_type& __x) + { return _M_t._M_insert_unique(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + std::pair + insert(value_type&& __x) + { return _M_t._M_insert_unique(std::move(__x)); } + + template + __enable_if_t::value, + pair> + insert(_Pair&& __x) + { return _M_t._M_emplace_unique(std::forward<_Pair>(__x)); } +#endif + // @} + +#if __cplusplus >= 201103L + /** + * @brief Attempts to insert a list of std::pairs into the %map. + * @param __list A std::initializer_list of pairs to be + * inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(std::initializer_list __list) + { insert(__list.begin(), __list.end()); } +#endif + + /** + * @brief Attempts to insert a std::pair into the %map. + * @param __position An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + + * This function is not concerned about whether the insertion + * took place, and thus does not return a boolean like the + * single-argument insert() does. Note that the first + * parameter is only a hint and can potentially improve the + * performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + * @{ + */ + iterator +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { return _M_t._M_insert_unique_(__position, __x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_unique_(__position, std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(const_iterator __position, _Pair&& __x) + { + return _M_t._M_emplace_hint_unique(__position, + std::forward<_Pair>(__x)); + } +#endif + // @} + + /** + * @brief Template function that attempts to insert a range of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_range_unique(__first, __last); } + +#if __cplusplus > 201402L + /** + * @brief Attempts to insert or assign a std::pair into the %map. + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __obj Argument used to generate the .second for a pair + * instance. + * + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is + * a bool that is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * If the %pair was already in the %map, the .second of the %pair + * is assigned from __obj. + * + * Insertion requires logarithmic time. + */ + template + pair + insert_or_assign(const key_type& __k, _Obj&& __obj) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } + + // move-capable overload + template + pair + insert_or_assign(key_type&& __k, _Obj&& __obj) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } + + /** + * @brief Attempts to insert or assign a std::pair into the %map. + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __obj Argument used to generate the .second for a pair + * instance. + * + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + * This function attempts to insert a (key, value) %pair into the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * If the %pair was already in the %map, the .second of the %pair + * is assigned from __obj. + * + * Insertion requires logarithmic time. + */ + template + iterator + insert_or_assign(const_iterator __hint, + const key_type& __k, _Obj&& __obj) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + { + return emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + __i = iterator(__true_hint.first); + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } + + // move-capable overload + template + iterator + insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + { + return emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + __i = iterator(__true_hint.first); + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases an element from a %map. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given + * iterator, from a %map. Note that this function only erases + * the element, and that if the element is itself a pointer, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + * + * @{ + */ + iterator + erase(const_iterator __position) + { return _M_t.erase(__position); } + + // LWG 2059 + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(iterator __position) + { return _M_t.erase(__position); } + // @} +#else + /** + * @brief Erases an element from a %map. + * @param __position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given + * iterator, from a %map. Note that this function only erases + * the element, and that if the element is itself a pointer, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + */ + void + erase(iterator __position) + { _M_t.erase(__position); } +#endif + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * a %map. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_t.erase(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [first,last) range of elements from a %map. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from a %map. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_t.erase(__first, __last); } +#else + /** + * @brief Erases a [__first,__last) range of elements from a %map. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * + * This function erases a sequence of elements from a %map. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } +#endif + + /** + * @brief Swaps data with another %map. + * @param __x A %map of the same element and allocator types. + * + * This exchanges the elements between two maps in constant + * time. (It is only swapping a pointer, an integer, and an + * instance of the @c Compare type (which itself is often + * stateless and empty), so it should be quite fast.) Note + * that the global std::swap() function is specialized such + * that std::swap(m1,m2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(map& __x) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { _M_t.swap(__x._M_t); } + + /** + * Erases all elements in a %map. Note that this function only + * erases the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_t.clear(); } + + // observers + /** + * Returns the key comparison object out of which the %map was + * constructed. + */ + key_compare + key_comp() const + { return _M_t.key_comp(); } + + /** + * Returns a value comparison object, built from the key comparison + * object out of which the %map was constructed. + */ + value_compare + value_comp() const + { return value_compare(_M_t.key_comp()); } + + // [23.3.1.3] map operations + + //@{ + /** + * @brief Tries to locate an element in a %map. + * @param __x Key of (key, value) %pair to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after %pair. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + + iterator + find(const key_type& __x) + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x)) + { return _M_t._M_find_tr(__x); } +#endif + //@} + + //@{ + /** + * @brief Tries to locate an element in a %map. + * @param __x Key of (key, value) %pair to be located. + * @return Read-only (constant) iterator pointing to sought-after + * element, or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns a constant + * iterator pointing to the sought after %pair. If unsuccessful it + * returns the past-the-end ( @c end() ) iterator. + */ + + const_iterator + find(const key_type& __x) const + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x)) + { return _M_t._M_find_tr(__x); } +#endif + //@} + + //@{ + /** + * @brief Finds the number of elements with given key. + * @param __x Key of (key, value) pairs to be located. + * @return Number of elements with specified key. + * + * This function only makes sense for multimaps; for map the result will + * either be 0 (not present) or 1 (present). + */ + size_type + count(const key_type& __x) const + { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } + +#if __cplusplus > 201103L + template + auto + count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) + { return _M_t._M_count_tr(__x); } +#endif + //@} + +#if __cplusplus > 201703L + //@{ + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of (key, value) pairs to be located. + * @return True if there is an element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_t.find(__x) != _M_t.end(); } + + template + auto + contains(const _Kt& __x) const + -> decltype(_M_t._M_find_tr(__x), void(), true) + { return _M_t._M_find_tr(__x) != _M_t.end(); } + //@} +#endif + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to first element equal to or greater + * than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first element + * equal to or greater than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + const_iterator + lower_bound(const key_type& __x) const + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to the first element + * greater than key, or end(). + */ + iterator + upper_bound(const key_type& __x) + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first iterator + * greater than key, or end(). + */ + const_iterator + upper_bound(const key_type& __x) const + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key of (key, value) pairs to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + * + * This function probably only makes sense for multimaps. + */ + std::pair + equal_range(const key_type& __x) + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key of (key, value) pairs to be located. + * @return Pair of read-only (constant) iterators that possibly points + * to the subsequence matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + * + * This function probably only makes sense for multimaps. + */ + std::pair + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) const + -> decltype(pair( + _M_t._M_equal_range_tr(__x))) + { + return pair( + _M_t._M_equal_range_tr(__x)); + } +#endif + //@} + + template + friend bool + operator==(const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); + +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t> + operator<=>(const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); +#else + template + friend bool + operator<(const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); +#endif + }; + + +#if __cpp_deduction_guides >= 201606 + + template>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + map(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + _Compare, _Allocator>; + + template, + typename _Allocator = allocator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + map(initializer_list>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> map<_Key, _Tp, _Compare, _Allocator>; + + template , + typename = _RequireAllocator<_Allocator>> + map(_InputIterator, _InputIterator, _Allocator) + -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + less<__iter_key_t<_InputIterator>>, _Allocator>; + + template> + map(initializer_list>, _Allocator) + -> map<_Key, _Tp, less<_Key>, _Allocator>; + +#endif // deduction guides + + /** + * @brief Map equality comparison. + * @param __x A %map. + * @param __y A %map of the same type as @a x. + * @return True iff the size and elements of the maps are equal. + * + * This is an equivalence relation. It is linear in the size of the + * maps. Maps are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t == __y._M_t; } + +#if __cpp_lib_three_way_comparison + /** + * @brief Map ordering relation. + * @param __x A `map`. + * @param __y A `map` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t> + operator<=>(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else + /** + * @brief Map ordering relation. + * @param __x A %map. + * @param __y A %map of the same type as @a x. + * @return True iff @a x is lexicographically less than @a y. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t < __y._M_t; } + + /// Based on operator== + template + inline bool + operator!=(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::map::swap(). + template + inline void + swap(map<_Key, _Tp, _Compare, _Alloc>& __x, + map<_Key, _Tp, _Compare, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::map access to internals of compatible maps. + template + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_MAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h b/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h new file mode 100644 index 000000000..65f4d0117 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h @@ -0,0 +1,1233 @@ +// Multimap implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_multimap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{map} + */ + +#ifndef _STL_MULTIMAP_H +#define _STL_MULTIMAP_H 1 + +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + class map; + + /** + * @brief A standard container made up of (key,value) pairs, which can be + * retrieved based on a key, in logarithmic time. + * + * @ingroup associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Compare Comparison function object type, defaults to less<_Key>. + * @tparam _Alloc Allocator type, defaults to + * allocator. + * + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using equivalent + * keys). For a @c multimap the key_type is Key, the mapped_type + * is T, and the value_type is std::pair. + * + * Multimaps support bidirectional iterators. + * + * The private tree data is declared exactly the same way for map and + * multimap; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + */ + template , + typename _Alloc = std::allocator > > + class multimap + { + public: + typedef _Key key_type; + typedef _Tp mapped_type; + typedef std::pair value_type; + typedef _Compare key_compare; + typedef _Alloc allocator_type; + + private: +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires4(_Compare, bool, _Key, _Key, + _BinaryFunctionConcept) + __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L +#if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::multimap must have the same value_type as its allocator"); +#endif +#endif + + public: + class value_compare + : public std::binary_function + { + friend class multimap<_Key, _Tp, _Compare, _Alloc>; + protected: + _Compare comp; + + value_compare(_Compare __c) + : comp(__c) { } + + public: + bool operator()(const value_type& __x, const value_type& __y) const + { return comp(__x.first, __y.first); } + }; + + private: + /// This turns a red-black tree into a [multi]map. + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind::other _Pair_alloc_type; + + typedef _Rb_tree, + key_compare, _Pair_alloc_type> _Rep_type; + /// The actual tree structure. + _Rep_type _M_t; + + typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits; + + public: + // many of these are specified differently in ISO, but the following are + // "functionally equivalent" + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + typedef typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; +#endif + + // [23.3.2] construct/copy/destroy + // (get_allocator() is also listed in this section) + + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + multimap() : _M_t() { } +#else + multimap() = default; +#endif + + /** + * @brief Creates a %multimap with no elements. + * @param __comp A comparison object. + * @param __a An allocator object. + */ + explicit + multimap(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) { } + + /** + * @brief %Multimap copy constructor. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + multimap(const multimap& __x) + : _M_t(__x._M_t) { } +#else + multimap(const multimap&) = default; + + /** + * @brief %Multimap move constructor. + * + * The newly-created %multimap contains the exact contents of the + * moved instance. The moved instance is a valid, but unspecified + * %multimap. + */ + multimap(multimap&&) = default; + + /** + * @brief Builds a %multimap from an initializer_list. + * @param __l An initializer_list. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %multimap consisting of copies of the elements from + * the initializer_list. This is linear in N if the list is already + * sorted, and NlogN otherwise (where N is @a __l.size()). + */ + multimap(initializer_list __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) + { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } + + /// Allocator-extended default constructor. + explicit + multimap(const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) { } + + /// Allocator-extended copy constructor. + multimap(const multimap& __m, const allocator_type& __a) + : _M_t(__m._M_t, _Pair_alloc_type(__a)) { } + + /// Allocator-extended move constructor. + multimap(multimap&& __m, const allocator_type& __a) + noexcept(is_nothrow_copy_constructible<_Compare>::value + && _Alloc_traits::_S_always_equal()) + : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { } + + /// Allocator-extended initialier-list constructor. + multimap(initializer_list __l, const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) + { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } + + /// Allocator-extended range constructor. + template + multimap(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) + { _M_t._M_insert_range_equal(__first, __last); } +#endif + + /** + * @brief Builds a %multimap from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * + * Create a %multimap consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(__first,__last)). + */ + template + multimap(_InputIterator __first, _InputIterator __last) + : _M_t() + { _M_t._M_insert_range_equal(__first, __last); } + + /** + * @brief Builds a %multimap from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %multimap consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(__first,__last)). + */ + template + multimap(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) + { _M_t._M_insert_range_equal(__first, __last); } + +#if __cplusplus >= 201103L + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~multimap() = default; +#endif + + /** + * @brief %Multimap assignment operator. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + multimap& + operator=(const multimap& __x) + { + _M_t = __x._M_t; + return *this; + } +#else + multimap& + operator=(const multimap&) = default; + + /// Move assignment operator. + multimap& + operator=(multimap&&) = default; + + /** + * @brief %Multimap list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %multimap with copies of the elements + * in the initializer list @a __l. + * + * Note that the assignment completely changes the %multimap and + * that the resulting %multimap's size is the same as the number + * of elements assigned. + */ + multimap& + operator=(initializer_list __l) + { + _M_t._M_assign_equal(__l.begin(), __l.end()); + return *this; + } +#endif + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_t.get_allocator()); } + + // iterators + /** + * Returns a read/write iterator that points to the first pair in the + * %multimap. Iteration is done in ascending order according to the + * keys. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %multimap. Iteration is done in ascending order according to + * the keys. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read/write iterator that points one past the last pair in + * the %multimap. Iteration is done in ascending order according to the + * keys. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %multimap. Iteration is done in ascending order according + * to the keys. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read/write reverse iterator that points to the last pair in + * the %multimap. Iteration is done in descending order according to the + * keys. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %multimap. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first pair in the %multimap. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %multimap. Iteration is done in + * descending order according to the keys. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %multimap. Iteration is done in ascending order according to + * the keys. + */ + const_iterator + cbegin() const noexcept + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %multimap. Iteration is done in ascending order according + * to the keys. + */ + const_iterator + cend() const noexcept + { return _M_t.end(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %multimap. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator + crbegin() const noexcept + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %multimap. Iteration is done in + * descending order according to the keys. + */ + const_reverse_iterator + crend() const noexcept + { return _M_t.rend(); } +#endif + + // capacity + /** Returns true if the %multimap is empty. */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_t.empty(); } + + /** Returns the size of the %multimap. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_t.size(); } + + /** Returns the maximum size of the %multimap. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _M_t.max_size(); } + + // modifiers +#if __cplusplus >= 201103L + /** + * @brief Build and insert a std::pair into the %multimap. + * + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * + * @return An iterator that points to the inserted (key,value) pair. + * + * This function builds and inserts a (key, value) %pair into the + * %multimap. + * Contrary to a std::map the %multimap does not rely on unique keys and + * thus multiple pairs with the same key can be inserted. + * + * Insertion requires logarithmic time. + */ + template + iterator + emplace(_Args&&... __args) + { return _M_t._M_emplace_equal(std::forward<_Args>(__args)...); } + + /** + * @brief Builds and inserts a std::pair into the %multimap. + * + * @param __pos An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the %multimap. + * Contrary to a std::map the %multimap does not rely on unique keys and + * thus multiple pairs with the same key can be inserted. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { + return _M_t._M_emplace_hint_equal(__pos, + std::forward<_Args>(__args)...); + } +#endif + + /** + * @brief Inserts a std::pair into the %multimap. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the %multimap. + * Contrary to a std::map the %multimap does not rely on unique keys and + * thus multiple pairs with the same key can be inserted. + * + * Insertion requires logarithmic time. + * @{ + */ + iterator + insert(const value_type& __x) + { return _M_t._M_insert_equal(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(value_type&& __x) + { return _M_t._M_insert_equal(std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(_Pair&& __x) + { return _M_t._M_emplace_equal(std::forward<_Pair>(__x)); } +#endif + // @} + + /** + * @brief Inserts a std::pair into the %multimap. + * @param __position An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the %multimap. + * Contrary to a std::map the %multimap does not rely on unique keys and + * thus multiple pairs with the same key can be inserted. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires logarithmic time (if the hint is not taken). + * @{ + */ + iterator +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { return _M_t._M_insert_equal_(__position, __x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_equal_(__position, std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(const_iterator __position, _Pair&& __x) + { + return _M_t._M_emplace_hint_equal(__position, + std::forward<_Pair>(__x)); + } +#endif + // @} + + /** + * @brief A template function that attempts to insert a range + * of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_range_equal(__first, __last); } + +#if __cplusplus >= 201103L + /** + * @brief Attempts to insert a list of std::pairs into the %multimap. + * @param __l A std::initializer_list of pairs to be + * inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { this->insert(__l.begin(), __l.end()); } +#endif + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_equal(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); } + + template + friend class std::_Rb_tree_merge_helper; + + template + void + merge(multimap<_Key, _Tp, _Cmp2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(multimap<_Key, _Tp, _Cmp2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(map<_Key, _Tp, _Cmp2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(map<_Key, _Tp, _Cmp2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases an element from a %multimap. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from a %multimap. Note that this function only erases the element, + * and that if the element is itself a pointer, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + * + * @{ + */ + iterator + erase(const_iterator __position) + { return _M_t.erase(__position); } + + // LWG 2059. + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(iterator __position) + { return _M_t.erase(__position); } + // @} +#else + /** + * @brief Erases an element from a %multimap. + * @param __position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, + * from a %multimap. Note that this function only erases the element, + * and that if the element is itself a pointer, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __position) + { _M_t.erase(__position); } +#endif + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all elements located by the given key from a + * %multimap. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_t.erase(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [first,last) range of elements from a %multimap. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to be + * erased . + * @return The iterator @a __last. + * + * This function erases a sequence of elements from a %multimap. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_t.erase(__first, __last); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [first,last) range of elements from a %multimap. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * + * This function erases a sequence of elements from a %multimap. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } +#endif + + /** + * @brief Swaps data with another %multimap. + * @param __x A %multimap of the same element and allocator types. + * + * This exchanges the elements between two multimaps in constant time. + * (It is only swapping a pointer, an integer, and an instance of + * the @c Compare type (which itself is often stateless and empty), so it + * should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(m1,m2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(multimap& __x) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { _M_t.swap(__x._M_t); } + + /** + * Erases all elements in a %multimap. Note that this function only + * erases the elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_t.clear(); } + + // observers + /** + * Returns the key comparison object out of which the %multimap + * was constructed. + */ + key_compare + key_comp() const + { return _M_t.key_comp(); } + + /** + * Returns a value comparison object, built from the key comparison + * object out of which the %multimap was constructed. + */ + value_compare + value_comp() const + { return value_compare(_M_t.key_comp()); } + + // multimap operations + + //@{ + /** + * @brief Tries to locate an element in a %multimap. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to sought-after element, + * or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after %pair. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x)) + { return _M_t._M_find_tr(__x); } +#endif + //@} + + //@{ + /** + * @brief Tries to locate an element in a %multimap. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to sought-after + * element, or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns a constant + * iterator pointing to the sought after %pair. If unsuccessful it + * returns the past-the-end ( @c end() ) iterator. + */ + const_iterator + find(const key_type& __x) const + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x)) + { return _M_t._M_find_tr(__x); } +#endif + //@} + + //@{ + /** + * @brief Finds the number of elements with given key. + * @param __x Key of (key, value) pairs to be located. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const + { return _M_t.count(__x); } + +#if __cplusplus > 201103L + template + auto + count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) + { return _M_t._M_count_tr(__x); } +#endif + //@} + +#if __cplusplus > 201703L + //@{ + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of (key, value) pairs to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_t.find(__x) != _M_t.end(); } + + template + auto + contains(const _Kt& __x) const + -> decltype(_M_t._M_find_tr(__x), void(), true) + { return _M_t._M_find_tr(__x) != _M_t.end(); } + //@} +#endif + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to first element equal to or greater + * than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first element + * equal to or greater than key, or end(). + * + * This function returns the first element of a subsequence of + * elements that matches the given key. If unsuccessful the + * iterator will point to the next greatest element or, if no + * such greater element exists, to end(). + */ + const_iterator + lower_bound(const key_type& __x) const + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to the first element + * greater than key, or end(). + */ + iterator + upper_bound(const key_type& __x) + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first iterator + * greater than key, or end(). + */ + const_iterator + upper_bound(const key_type& __x) const + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key of (key, value) pairs to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + */ + std::pair + equal_range(const key_type& __x) + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key of (key, value) pairs to be located. + * @return Pair of read-only (constant) iterators that possibly points + * to the subsequence matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + */ + std::pair + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) const + -> decltype(pair( + _M_t._M_equal_range_tr(__x))) + { + return pair( + _M_t._M_equal_range_tr(__x)); + } +#endif + //@} + + template + friend bool + operator==(const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); + +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t> + operator<=>(const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); +#else + template + friend bool + operator<(const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); +#endif + }; + +#if __cpp_deduction_guides >= 201606 + + template>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + multimap(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + _Compare, _Allocator>; + + template, + typename _Allocator = allocator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + multimap(initializer_list>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<_Key, _Tp, _Compare, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + multimap(_InputIterator, _InputIterator, _Allocator) + -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + less<__iter_key_t<_InputIterator>>, _Allocator>; + + template> + multimap(initializer_list>, _Allocator) + -> multimap<_Key, _Tp, less<_Key>, _Allocator>; + +#endif // deduction guides + + /** + * @brief Multimap equality comparison. + * @param __x A %multimap. + * @param __y A %multimap of the same type as @a __x. + * @return True iff the size and elements of the maps are equal. + * + * This is an equivalence relation. It is linear in the size of the + * multimaps. Multimaps are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t == __y._M_t; } + +#if __cpp_lib_three_way_comparison + /** + * @brief Multimap ordering relation. + * @param __x A `multimap`. + * @param __y A `multimap` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t> + operator<=>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else + /** + * @brief Multimap ordering relation. + * @param __x A %multimap. + * @param __y A %multimap of the same type as @a __x. + * @return True iff @a x is lexicographically less than @a y. + * + * This is a total ordering relation. It is linear in the size of the + * multimaps. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t < __y._M_t; } + + /// Based on operator== + template + inline bool + operator!=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::multimap::swap(). + template + inline void + swap(multimap<_Key, _Tp, _Compare, _Alloc>& __x, + multimap<_Key, _Tp, _Compare, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::multimap access to internals of compatible maps. + template + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_MULTIMAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h b/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h new file mode 100644 index 000000000..bf6ae7de0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h @@ -0,0 +1,1075 @@ +// Multiset implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_multiset.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{set} + */ + +#ifndef _STL_MULTISET_H +#define _STL_MULTISET_H 1 + +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + class set; + + /** + * @brief A standard container made up of elements, which can be retrieved + * in logarithmic time. + * + * @ingroup associative_containers + * + * + * @tparam _Key Type of key objects. + * @tparam _Compare Comparison function object type, defaults to less<_Key>. + * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using equivalent + * keys). For a @c multiset the key_type and value_type are Key. + * + * Multisets support bidirectional iterators. + * + * The private tree data is declared exactly the same way for set and + * multiset; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + */ + template , + typename _Alloc = std::allocator<_Key> > + class multiset + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Key, _SGIAssignableConcept) +# endif + __glibcxx_class_requires4(_Compare, bool, _Key, _Key, + _BinaryFunctionConcept) + __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Key>::value, + "std::multiset must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::multiset must have the same value_type as its allocator"); +# endif +#endif + + public: + // typedefs: + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; + typedef _Alloc allocator_type; + + private: + /// This turns a red-black tree into a [multi]set. + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Key>::other _Key_alloc_type; + + typedef _Rb_tree, + key_compare, _Key_alloc_type> _Rep_type; + /// The actual tree structure. + _Rep_type _M_t; + + typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits; + + public: + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 103. set::iterator is required to be modifiable, + // but this allows modification of keys. + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; +#endif + + // allocation/deallocation + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + multiset() : _M_t() { } +#else + multiset() = default; +#endif + + /** + * @brief Creates a %multiset with no elements. + * @param __comp Comparator to use. + * @param __a An allocator object. + */ + explicit + multiset(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) { } + + /** + * @brief Builds a %multiset from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * + * Create a %multiset consisting of copies of the elements from + * [first,last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(__first,__last)). + */ + template + multiset(_InputIterator __first, _InputIterator __last) + : _M_t() + { _M_t._M_insert_range_equal(__first, __last); } + + /** + * @brief Builds a %multiset from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %multiset consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(__first,__last)). + */ + template + multiset(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) + { _M_t._M_insert_range_equal(__first, __last); } + + /** + * @brief %Multiset copy constructor. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + multiset(const multiset& __x) + : _M_t(__x._M_t) { } +#else + multiset(const multiset&) = default; + + /** + * @brief %Multiset move constructor. + * + * The newly-created %multiset contains the exact contents of the + * moved instance. The moved instance is a valid, but unspecified + * %multiset. + */ + multiset(multiset&&) = default; + + /** + * @brief Builds a %multiset from an initializer_list. + * @param __l An initializer_list. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %multiset consisting of copies of the elements from + * the list. This is linear in N if the list is already sorted, + * and NlogN otherwise (where N is @a __l.size()). + */ + multiset(initializer_list __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) + { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } + + /// Allocator-extended default constructor. + explicit + multiset(const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) { } + + /// Allocator-extended copy constructor. + multiset(const multiset& __m, const allocator_type& __a) + : _M_t(__m._M_t, _Key_alloc_type(__a)) { } + + /// Allocator-extended move constructor. + multiset(multiset&& __m, const allocator_type& __a) + noexcept(is_nothrow_copy_constructible<_Compare>::value + && _Alloc_traits::_S_always_equal()) + : _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { } + + /// Allocator-extended initialier-list constructor. + multiset(initializer_list __l, const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) + { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } + + /// Allocator-extended range constructor. + template + multiset(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) + { _M_t._M_insert_range_equal(__first, __last); } + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~multiset() = default; +#endif + + /** + * @brief %Multiset assignment operator. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + multiset& + operator=(const multiset& __x) + { + _M_t = __x._M_t; + return *this; + } +#else + multiset& + operator=(const multiset&) = default; + + /// Move assignment operator. + multiset& + operator=(multiset&&) = default; + + /** + * @brief %Multiset list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %multiset with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %multiset and + * that the resulting %multiset's size is the same as the number + * of elements assigned. + */ + multiset& + operator=(initializer_list __l) + { + _M_t._M_assign_equal(__l.begin(), __l.end()); + return *this; + } +#endif + + // accessors: + + /// Returns the comparison object. + key_compare + key_comp() const + { return _M_t.key_comp(); } + /// Returns the comparison object. + value_compare + value_comp() const + { return _M_t.key_comp(); } + /// Returns the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_t.get_allocator()); } + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %multiset. Iteration is done in ascending order + * according to the keys. + */ + iterator + begin() const _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %multiset. Iteration is done in ascending order + * according to the keys. + */ + iterator + end() const _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last element in the %multiset. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last element in the %multiset. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %multiset. Iteration is done in ascending order + * according to the keys. + */ + iterator + cbegin() const noexcept + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %multiset. Iteration is done in ascending order + * according to the keys. + */ + iterator + cend() const noexcept + { return _M_t.end(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last element in the %multiset. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + crbegin() const noexcept + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last element in the %multiset. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + crend() const noexcept + { return _M_t.rend(); } +#endif + + /// Returns true if the %set is empty. + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_t.empty(); } + + /// Returns the size of the %set. + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_t.size(); } + + /// Returns the maximum size of the %set. + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _M_t.max_size(); } + + /** + * @brief Swaps data with another %multiset. + * @param __x A %multiset of the same element and allocator types. + * + * This exchanges the elements between two multisets in constant time. + * (It is only swapping a pointer, an integer, and an instance of the @c + * Compare type (which itself is often stateless and empty), so it should + * be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(s1,s2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(multiset& __x) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { _M_t.swap(__x._M_t); } + + // insert/erase +#if __cplusplus >= 201103L + /** + * @brief Builds and inserts an element into the %multiset. + * @param __args Arguments used to generate the element instance to be + * inserted. + * @return An iterator that points to the inserted element. + * + * This function inserts an element into the %multiset. Contrary + * to a std::set the %multiset does not rely on unique keys and thus + * multiple copies of the same element can be inserted. + * + * Insertion requires logarithmic time. + */ + template + iterator + emplace(_Args&&... __args) + { return _M_t._M_emplace_equal(std::forward<_Args>(__args)...); } + + /** + * @brief Builds and inserts an element into the %multiset. + * @param __pos An iterator that serves as a hint as to where the + * element should be inserted. + * @param __args Arguments used to generate the element instance to be + * inserted. + * @return An iterator that points to the inserted element. + * + * This function inserts an element into the %multiset. Contrary + * to a std::set the %multiset does not rely on unique keys and thus + * multiple copies of the same element can be inserted. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { + return _M_t._M_emplace_hint_equal(__pos, + std::forward<_Args>(__args)...); + } +#endif + + /** + * @brief Inserts an element into the %multiset. + * @param __x Element to be inserted. + * @return An iterator that points to the inserted element. + * + * This function inserts an element into the %multiset. Contrary + * to a std::set the %multiset does not rely on unique keys and thus + * multiple copies of the same element can be inserted. + * + * Insertion requires logarithmic time. + */ + iterator + insert(const value_type& __x) + { return _M_t._M_insert_equal(__x); } + +#if __cplusplus >= 201103L + iterator + insert(value_type&& __x) + { return _M_t._M_insert_equal(std::move(__x)); } +#endif + + /** + * @brief Inserts an element into the %multiset. + * @param __position An iterator that serves as a hint as to where the + * element should be inserted. + * @param __x Element to be inserted. + * @return An iterator that points to the inserted element. + * + * This function inserts an element into the %multiset. Contrary + * to a std::set the %multiset does not rely on unique keys and thus + * multiple copies of the same element can be inserted. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + iterator + insert(const_iterator __position, const value_type& __x) + { return _M_t._M_insert_equal_(__position, __x); } + +#if __cplusplus >= 201103L + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_equal_(__position, std::move(__x)); } +#endif + + /** + * @brief A template function that tries to insert a range of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_range_equal(__first, __last); } + +#if __cplusplus >= 201103L + /** + * @brief Attempts to insert a list of elements into the %multiset. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { this->insert(__l.begin(), __l.end()); } +#endif + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_equal(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); } + + template + friend class std::_Rb_tree_merge_helper; + + template + void + merge(multiset<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(multiset<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(set<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(set<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases an element from a %multiset. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from a %multiset. Note that this function only erases the element, + * and that if the element is itself a pointer, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __position) + { return _M_t.erase(__position); } +#else + /** + * @brief Erases an element from a %multiset. + * @param __position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, + * from a %multiset. Note that this function only erases the element, + * and that if the element is itself a pointer, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __position) + { _M_t.erase(__position); } +#endif + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all elements located by the given key from a + * %multiset. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_t.erase(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [first,last) range of elements from a %multiset. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a last. + * + * This function erases a sequence of elements from a %multiset. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_t.erase(__first, __last); } +#else + /** + * @brief Erases a [first,last) range of elements from a %multiset. + * @param first Iterator pointing to the start of the range to be + * erased. + * @param last Iterator pointing to the end of the range to be erased. + * + * This function erases a sequence of elements from a %multiset. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } +#endif + + /** + * Erases all elements in a %multiset. Note that this function only + * erases the elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_t.clear(); } + + // multiset operations: + + //@{ + /** + * @brief Finds the number of elements with given key. + * @param __x Key of elements to be located. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const + { return _M_t.count(__x); } + +#if __cplusplus > 201103L + template + auto + count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) + { return _M_t._M_count_tr(__x); } +#endif + //@} + +#if __cplusplus > 201703L + //@{ + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_t.find(__x) != _M_t.end(); } + + template + auto + contains(const _Kt& __x) const + -> decltype(_M_t._M_find_tr(__x), void(), true) + { return _M_t._M_find_tr(__x) != _M_t.end(); } + //@} +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + //@{ + /** + * @brief Tries to locate an element in a %set. + * @param __x Element to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_t.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) + -> decltype(iterator{_M_t._M_find_tr(__x)}) + { return iterator{_M_t._M_find_tr(__x)}; } + + template + auto + find(const _Kt& __x) const + -> decltype(const_iterator{_M_t._M_find_tr(__x)}) + { return const_iterator{_M_t._M_find_tr(__x)}; } +#endif + //@} + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key to be located. + * @return Iterator pointing to first element equal to or greater + * than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) + { return _M_t.lower_bound(__x); } + + const_iterator + lower_bound(const key_type& __x) const + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } + + template + auto + lower_bound(const _Kt& __x) const + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key to be located. + * @return Iterator pointing to the first element + * greater than key, or end(). + */ + iterator + upper_bound(const key_type& __x) + { return _M_t.upper_bound(__x); } + + const_iterator + upper_bound(const key_type& __x) const + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } + + template + auto + upper_bound(const _Kt& __x) const + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + * + * This function probably only makes sense for multisets. + */ + std::pair + equal_range(const key_type& __x) + { return _M_t.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } + + template + auto + equal_range(const _Kt& __x) const + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } +#endif + //@} + + template + friend bool + operator==(const multiset<_K1, _C1, _A1>&, + const multiset<_K1, _C1, _A1>&); + +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t<_K1> + operator<=>(const multiset<_K1, _C1, _A1>&, + const multiset<_K1, _C1, _A1>&); +#else + template + friend bool + operator< (const multiset<_K1, _C1, _A1>&, + const multiset<_K1, _C1, _A1>&); +#endif + }; + +#if __cpp_deduction_guides >= 201606 + + template::value_type>, + typename _Allocator = + allocator::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + multiset(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset::value_type, + _Compare, _Allocator>; + + template, + typename _Allocator = allocator<_Key>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + multiset(initializer_list<_Key>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset<_Key, _Compare, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + multiset(_InputIterator, _InputIterator, _Allocator) + -> multiset::value_type, + less::value_type>, + _Allocator>; + + template> + multiset(initializer_list<_Key>, _Allocator) + -> multiset<_Key, less<_Key>, _Allocator>; + +#endif // deduction guides + + /** + * @brief Multiset equality comparison. + * @param __x A %multiset. + * @param __y A %multiset of the same type as @a __x. + * @return True iff the size and elements of the multisets are equal. + * + * This is an equivalence relation. It is linear in the size of the + * multisets. + * Multisets are considered equivalent if their sizes are equal, and if + * corresponding elements compare equal. + */ + template + inline bool + operator==(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return __x._M_t == __y._M_t; } + +#if __cpp_lib_three_way_comparison + /** + * @brief Multiset ordering relation. + * @param __x A `multiset`. + * @param __y A `multiset` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Key> + operator<=>(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else + /** + * @brief Multiset ordering relation. + * @param __x A %multiset. + * @param __y A %multiset of the same type as @a __x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * sets. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return __x._M_t < __y._M_t; } + + /// Returns !(x == y). + template + inline bool + operator!=(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return !(__x == __y); } + + /// Returns y < x. + template + inline bool + operator>(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y) + { return __y < __x; } + + /// Returns !(y < x) + template + inline bool + operator<=(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return !(__y < __x); } + + /// Returns !(x < y) + template + inline bool + operator>=(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::multiset::swap(). + template + inline void + swap(multiset<_Key, _Compare, _Alloc>& __x, + multiset<_Key, _Compare, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::multiset access to internals of compatible sets. + template + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_MULTISET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h b/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h new file mode 100644 index 000000000..f95c86a0d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h @@ -0,0 +1,413 @@ +// Numeric functions implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_numeric.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{numeric} + */ + +#ifndef _STL_NUMERIC_H +#define _STL_NUMERIC_H 1 + +#include +#include +#include // For _GLIBCXX_MOVE + + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @defgroup numeric_ops Generalized Numeric operations + * @ingroup algorithms + */ + +#if __cplusplus >= 201103L + /** + * @brief Create a range of sequentially increasing values. + * + * For each element in the range @p [first,last) assigns @p value and + * increments @p value as if by @p ++value. + * + * @param __first Start of range. + * @param __last End of range. + * @param __value Starting value. + * @return Nothing. + * @ingroup numeric_ops + */ + template + _GLIBCXX20_CONSTEXPR + void + iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + { + *__first = __value; + ++__value; + } + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + +#if __cplusplus > 201703L +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// DR 2055. std::move in std::accumulate and other algorithms +# define _GLIBCXX_MOVE_IF_20(_E) std::move(_E) +#else +# define _GLIBCXX_MOVE_IF_20(_E) _E +#endif + + /// @addtogroup numeric_ops + /// @{ + + /** + * @brief Accumulate values in a range. + * + * Accumulates the values in the range [first,last) using operator+(). The + * initial value is @a init. The values are processed in order. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @return The final sum. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + __init = _GLIBCXX_MOVE_IF_20(__init) + *__first; + return __init; + } + + /** + * @brief Accumulate values in a range with operation. + * + * Accumulates the values in the range `[first,last)` using the function + * object `__binary_op`. The initial value is `__init`. The values are + * processed in order. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op Function object to accumulate with. + * @return The final sum. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + __init = __binary_op(_GLIBCXX_MOVE_IF_20(__init), *__first); + return __init; + } + + /** + * @brief Compute inner product of two ranges. + * + * Starting with an initial value of @p __init, multiplies successive + * elements from the two ranges and adds each product into the accumulated + * value using operator+(). The values in the ranges are processed in + * order. + * + * @param __first1 Start of range 1. + * @param __last1 End of range 1. + * @param __first2 Start of range 2. + * @param __init Starting value to add other values to. + * @return The final inner product. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + inner_product(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + __init = _GLIBCXX_MOVE_IF_20(__init) + (*__first1 * *__first2); + return __init; + } + + /** + * @brief Compute inner product of two ranges. + * + * Starting with an initial value of @p __init, applies @p __binary_op2 to + * successive elements from the two ranges and accumulates each result into + * the accumulated value using @p __binary_op1. The values in the ranges are + * processed in order. + * + * @param __first1 Start of range 1. + * @param __last1 End of range 1. + * @param __first2 Start of range 2. + * @param __init Starting value to add other values to. + * @param __binary_op1 Function object to accumulate with. + * @param __binary_op2 Function object to apply to pairs of input values. + * @return The final inner product. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + inner_product(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init, + _BinaryOperation1 __binary_op1, + _BinaryOperation2 __binary_op2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + __init = __binary_op1(_GLIBCXX_MOVE_IF_20(__init), + __binary_op2(*__first1, *__first2)); + return __init; + } + + /** + * @brief Return list of partial sums + * + * Accumulates the values in the range [first,last) using the @c + operator. + * As each successive input value is added into the total, that partial sum + * is written to @p __result. Therefore, the first value in @p __result is + * the first value of the input, the second value in @p __result is the sum + * of the first and second input values, and so on. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @return Iterator pointing just beyond the values written to __result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + partial_sum(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + __value = _GLIBCXX_MOVE_IF_20(__value) + *__first; + *++__result = __value; + } + return ++__result; + } + + /** + * @brief Return list of partial sums + * + * Accumulates the values in the range [first,last) using @p __binary_op. + * As each successive input value is added into the total, that partial sum + * is written to @p __result. Therefore, the first value in @p __result is + * the first value of the input, the second value in @p __result is the sum + * of the first and second input values, and so on. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @param __binary_op Function object. + * @return Iterator pointing just beyond the values written to __result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + partial_sum(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + __value = __binary_op(_GLIBCXX_MOVE_IF_20(__value), *__first); + *++__result = __value; + } + return ++__result; + } + + /** + * @brief Return differences between adjacent values. + * + * Computes the difference between adjacent values in the range + * [first,last) using operator-() and writes the result to @p __result. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sums. + * @return Iterator pointing just beyond the values written to result. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 539. partial_sum and adjacent_difference should mention requirements + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + adjacent_difference(_InputIterator __first, + _InputIterator __last, _OutputIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + _ValueType __tmp = *__first; + *++__result = __tmp - _GLIBCXX_MOVE_IF_20(__value); + __value = _GLIBCXX_MOVE(__tmp); + } + return ++__result; + } + + /** + * @brief Return differences between adjacent values. + * + * Computes the difference between adjacent values in the range + * [__first,__last) using the function object @p __binary_op and writes the + * result to @p __result. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @param __binary_op Function object. + * @return Iterator pointing just beyond the values written to result. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 539. partial_sum and adjacent_difference should mention requirements + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + adjacent_difference(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + _ValueType __tmp = *__first; + *++__result = __binary_op(__tmp, _GLIBCXX_MOVE_IF_20(__value)); + __value = _GLIBCXX_MOVE(__tmp); + } + return ++__result; + } + + // @} group numeric_ops + +#undef _GLIBCXX_MOVE_IF_20 + +_GLIBCXX_END_NAMESPACE_ALGO +} // namespace std + +#endif /* _STL_NUMERIC_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_pair.h b/resources/sources/avr-libstdcpp/include/bits/stl_pair.h new file mode 100644 index 000000000..491c59907 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_pair.h @@ -0,0 +1,586 @@ +// Pair implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_pair.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + */ + +#ifndef _STL_PAIR_H +#define _STL_PAIR_H 1 + +#include // for std::move / std::forward, and std::swap + +#if __cplusplus >= 201103L +# include // for std::__decay_and_strip, std::is_reference_v +#endif +#if __cplusplus > 201703L +# include +# define __cpp_lib_constexpr_utility 201811L +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + +#if __cplusplus >= 201103L + /// Tag type for piecewise construction of std::pair objects. + struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; + + /// Tag for piecewise construction of std::pair objects. + _GLIBCXX17_INLINE constexpr piecewise_construct_t piecewise_construct = + piecewise_construct_t(); + + /// @cond undocumented + + // Forward declarations. + template + class tuple; + + template + struct _Index_tuple; + + // Concept utility functions, reused in conditionally-explicit + // constructors. + // See PR 70437, don't look at is_constructible or + // is_convertible if the types are the same to + // avoid querying those properties for incomplete types. + template + struct _PCC + { + template + static constexpr bool _ConstructiblePair() + { + return __and_, + is_constructible<_T2, const _U2&>>::value; + } + + template + static constexpr bool _ImplicitlyConvertiblePair() + { + return __and_, + is_convertible>::value; + } + + template + static constexpr bool _MoveConstructiblePair() + { + return __and_, + is_constructible<_T2, _U2&&>>::value; + } + + template + static constexpr bool _ImplicitlyMoveConvertiblePair() + { + return __and_, + is_convertible<_U2&&, _T2>>::value; + } + + template + static constexpr bool _CopyMovePair() + { + using __do_converts = __and_, + is_convertible<_U2&&, _T2>>; + using __converts = typename conditional<__implicit, + __do_converts, + __not_<__do_converts>>::type; + return __and_, + is_constructible<_T2, _U2&&>, + __converts + >::value; + } + + template + static constexpr bool _MoveCopyPair() + { + using __do_converts = __and_, + is_convertible>; + using __converts = typename conditional<__implicit, + __do_converts, + __not_<__do_converts>>::type; + return __and_, + is_constructible<_T2, const _U2&&>, + __converts + >::value; + } + }; + + template + struct _PCC + { + template + static constexpr bool _ConstructiblePair() + { + return false; + } + + template + static constexpr bool _ImplicitlyConvertiblePair() + { + return false; + } + + template + static constexpr bool _MoveConstructiblePair() + { + return false; + } + + template + static constexpr bool _ImplicitlyMoveConvertiblePair() + { + return false; + } + }; +#endif // C++11 + + template class __pair_base + { +#if __cplusplus >= 201103L + template friend struct pair; + __pair_base() = default; + ~__pair_base() = default; + __pair_base(const __pair_base&) = default; + __pair_base& operator=(const __pair_base&) = delete; +#endif // C++11 + }; + + /// @endcond + + /** + * @brief Struct holding two objects of arbitrary type. + * + * @tparam _T1 Type of first object. + * @tparam _T2 Type of second object. + * + * + */ + template + struct pair + : private __pair_base<_T1, _T2> + { + typedef _T1 first_type; ///< The type of the `first` member + typedef _T2 second_type; ///< The type of the `second` member + + _T1 first; ///< The first member + _T2 second; ///< The second member + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 265. std::pair::pair() effects overly restrictive + /** The default constructor creates @c first and @c second using their + * respective default constructors. */ +#if __cplusplus >= 201103L + template , + __is_implicitly_default_constructible<_U2>> + ::value, bool>::type = true> +#endif + _GLIBCXX_CONSTEXPR pair() + : first(), second() { } + +#if __cplusplus >= 201103L + template , + is_default_constructible<_U2>, + __not_< + __and_<__is_implicitly_default_constructible<_U1>, + __is_implicitly_default_constructible<_U2>>>> + ::value, bool>::type = false> + explicit constexpr pair() + : first(), second() { } +#endif + +#if __cplusplus < 201103L + /// Two objects may be passed to a @c pair constructor to be copied. + pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } +#else + // Shortcut for constraining the templates that don't take pairs. + /// @cond undocumented + using _PCCP = _PCC; + /// @endcond + + /// Construct from two const lvalues, allowing implicit conversions. + template() + && _PCCP::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } + + /// Construct from two const lvalues, disallowing implicit conversions. + template() + && !_PCCP::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } +#endif + +#if __cplusplus < 201103L + /// There is also a templated constructor to convert from other pairs. + template + pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) { } +#else + // Shortcut for constraining the templates that take pairs. + /// @cond undocumented + template + using _PCCFP = _PCC::value + || !is_same<_T2, _U2>::value, + _T1, _T2>; + /// @endcond + + template::template + _ConstructiblePair<_U1, _U2>() + && _PCCFP<_U1, _U2>::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) { } + + template::template + _ConstructiblePair<_U1, _U2>() + && !_PCCFP<_U1, _U2>::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) { } +#endif + +#if __cplusplus >= 201103L + constexpr pair(const pair&) = default; ///< Copy constructor + constexpr pair(pair&&) = default; ///< Move constructor + + // DR 811. + template(), + bool>::type=true> + constexpr pair(_U1&& __x, const _T2& __y) + : first(std::forward<_U1>(__x)), second(__y) { } + + template(), + bool>::type=false> + explicit constexpr pair(_U1&& __x, const _T2& __y) + : first(std::forward<_U1>(__x)), second(__y) { } + + template(), + bool>::type=true> + constexpr pair(const _T1& __x, _U2&& __y) + : first(__x), second(std::forward<_U2>(__y)) { } + + template(), + bool>::type=false> + explicit pair(const _T1& __x, _U2&& __y) + : first(__x), second(std::forward<_U2>(__y)) { } + + template() + && _PCCP::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(_U1&& __x, _U2&& __y) + : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } + + template() + && !_PCCP::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(_U1&& __x, _U2&& __y) + : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } + + + template::template + _MoveConstructiblePair<_U1, _U2>() + && _PCCFP<_U1, _U2>::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(pair<_U1, _U2>&& __p) + : first(std::forward<_U1>(__p.first)), + second(std::forward<_U2>(__p.second)) { } + + template::template + _MoveConstructiblePair<_U1, _U2>() + && !_PCCFP<_U1, _U2>::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(pair<_U1, _U2>&& __p) + : first(std::forward<_U1>(__p.first)), + second(std::forward<_U2>(__p.second)) { } + + template + _GLIBCXX20_CONSTEXPR + pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>); + + _GLIBCXX20_CONSTEXPR pair& + operator=(typename conditional< + __and_, + is_copy_assignable<_T2>>::value, + const pair&, const __nonesuch&>::type __p) + { + first = __p.first; + second = __p.second; + return *this; + } + + _GLIBCXX20_CONSTEXPR pair& + operator=(typename conditional< + __and_, + is_move_assignable<_T2>>::value, + pair&&, __nonesuch&&>::type __p) + noexcept(__and_, + is_nothrow_move_assignable<_T2>>::value) + { + first = std::forward(__p.first); + second = std::forward(__p.second); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + typename enable_if<__and_, + is_assignable<_T2&, const _U2&>>::value, + pair&>::type + operator=(const pair<_U1, _U2>& __p) + { + first = __p.first; + second = __p.second; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + typename enable_if<__and_, + is_assignable<_T2&, _U2&&>>::value, + pair&>::type + operator=(pair<_U1, _U2>&& __p) + { + first = std::forward<_U1>(__p.first); + second = std::forward<_U2>(__p.second); + return *this; + } + + /// Swap the first members and then the second members. + _GLIBCXX20_CONSTEXPR void + swap(pair& __p) + noexcept(__and_<__is_nothrow_swappable<_T1>, + __is_nothrow_swappable<_T2>>::value) + { + using std::swap; + swap(first, __p.first); + swap(second, __p.second); + } + + private: + template + _GLIBCXX20_CONSTEXPR + pair(tuple<_Args1...>&, tuple<_Args2...>&, + _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>); +#endif // C++11 + }; + + /// @relates pair @{ + +#if __cpp_deduction_guides >= 201606 + template pair(_T1, _T2) -> pair<_T1, _T2>; +#endif + + /// Two pairs of the same type are equal iff their members are equal. + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __x.first == __y.first && __x.second == __y.second; } + +#if __cpp_lib_three_way_comparison && __cpp_lib_concepts + template + constexpr common_comparison_category_t<__detail::__synth3way_t<_T1>, + __detail::__synth3way_t<_T2>> + operator<=>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { + if (auto __c = __detail::__synth3way(__x.first, __y.first); __c != 0) + return __c; + return __detail::__synth3way(__x.second, __y.second); + } +#else + /** Defines a lexicographical order for pairs. + * + * For two pairs of the same type, `P` is ordered before `Q` if + * `P.first` is less than `Q.first`, or if `P.first` and `Q.first` + * are equivalent (neither is less than the other) and `P.second` is less + * than `Q.second`. + */ + template + inline _GLIBCXX_CONSTEXPR bool + operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __x.first < __y.first + || (!(__y.first < __x.first) && __x.second < __y.second); } + + /// Uses @c operator== to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__x == __y); } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __y < __x; } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__y < __x); } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__x < __y); } +#endif // !(three_way_comparison && concepts) + +#if __cplusplus >= 201103L + /** Swap overload for pairs. Calls std::pair::swap(). + * + * @note This std::swap overload is not declared in C++03 mode, + * which has performance implications, e.g. see https://gcc.gnu.org/PR38466 + */ + template + _GLIBCXX20_CONSTEXPR inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_T1>, + __is_swappable<_T2>>::value>::type +#else + void +#endif + swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + typename enable_if, + __is_swappable<_T2>>::value>::type + swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete; +#endif +#endif // __cplusplus >= 201103L + + // @} relates pair + + /** + * @brief A convenience wrapper for creating a pair from two objects. + * @param __x The first object. + * @param __y The second object. + * @return A newly-constructed pair<> object of the appropriate type. + * + * The C++98 standard says the objects are passed by reference-to-const, + * but C++03 says they are passed by value (this was LWG issue #181). + * + * Since C++11 they have been passed by forwarding reference and then + * forwarded to the new members of the pair. To create a pair with a + * member of reference type, pass a `reference_wrapper` to this function. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 181. make_pair() unintended behavior +#if __cplusplus >= 201103L + // NB: DR 706. + template + constexpr pair::__type, + typename __decay_and_strip<_T2>::__type> + make_pair(_T1&& __x, _T2&& __y) + { + typedef typename __decay_and_strip<_T1>::__type __ds_type1; + typedef typename __decay_and_strip<_T2>::__type __ds_type2; + typedef pair<__ds_type1, __ds_type2> __pair_type; + return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y)); + } +#else + template + inline pair<_T1, _T2> + make_pair(_T1 __x, _T2 __y) + { return pair<_T1, _T2>(__x, __y); } +#endif + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_PAIR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_queue.h b/resources/sources/avr-libstdcpp/include/bits/stl_queue.h new file mode 100644 index 000000000..8635d4267 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_queue.h @@ -0,0 +1,753 @@ +// Queue implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_queue.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{queue} + */ + +#ifndef _STL_QUEUE_H +#define _STL_QUEUE_H 1 + +#include +#include +#if __cplusplus >= 201103L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief A standard container giving FIFO behavior. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Sequence Type of underlying sequence, defaults to deque<_Tp>. + * + * Meets many of the requirements of a + * container, + * but does not define anything to do with iterators. Very few of the + * other standard container interfaces are defined. + * + * This is not a true container, but an @e adaptor. It holds another + * container, and provides a wrapper interface to that container. The + * wrapper is what enforces strict first-in-first-out %queue behavior. + * + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::deque, but it can be any type + * that supports @c front, @c back, @c push_back, and @c pop_front, + * such as std::list or an appropriate user-defined type. + * + * Members not found in @a normal containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c push and + * @c pop, which are standard %queue/FIFO operations. + */ + template > + class queue + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Sequence::value_type _Sequence_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires(_Sequence, _FrontInsertionSequenceConcept) + __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) + __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) +#endif + + template + friend bool + operator==(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); + + template + friend bool + operator<(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); + +#if __cpp_lib_three_way_comparison + template + friend compare_three_way_result_t<_Seq1> + operator<=>(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); +#endif + +#if __cplusplus >= 201103L + template + using _Uses = typename + enable_if::value>::type; + +#if __cplusplus >= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2566. Requirements on the first template parameter of container + // adaptors + static_assert(is_same<_Tp, typename _Sequence::value_type>::value, + "value_type must be the same as the underlying container"); +#endif // C++17 +#endif // C++11 + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + protected: + /* Maintainers wondering why this isn't uglified as per style + * guidelines should note that this name is specified in the standard, + * C++98 [23.2.3.1]. + * (Why? Presumably for the same reason that it's protected instead + * of private: to allow derivation. But none of the other + * containers allow for derivation. Odd.) + */ + /// @c c is the underlying container. + _Sequence c; + + public: + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + explicit + queue(const _Sequence& __c = _Sequence()) + : c(__c) { } +#else + template::value>::type> + queue() + : c() { } + + explicit + queue(const _Sequence& __c) + : c(__c) { } + + explicit + queue(_Sequence&& __c) + : c(std::move(__c)) { } + + template> + explicit + queue(const _Alloc& __a) + : c(__a) { } + + template> + queue(const _Sequence& __c, const _Alloc& __a) + : c(__c, __a) { } + + template> + queue(_Sequence&& __c, const _Alloc& __a) + : c(std::move(__c), __a) { } + + template> + queue(const queue& __q, const _Alloc& __a) + : c(__q.c, __a) { } + + template> + queue(queue&& __q, const _Alloc& __a) + : c(std::move(__q.c), __a) { } +#endif + + /** + * Returns true if the %queue is empty. + */ + _GLIBCXX_NODISCARD bool + empty() const + { return c.empty(); } + + /** Returns the number of elements in the %queue. */ + size_type + size() const + { return c.size(); } + + /** + * Returns a read/write reference to the data at the first + * element of the %queue. + */ + reference + front() + { + __glibcxx_requires_nonempty(); + return c.front(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %queue. + */ + const_reference + front() const + { + __glibcxx_requires_nonempty(); + return c.front(); + } + + /** + * Returns a read/write reference to the data at the last + * element of the %queue. + */ + reference + back() + { + __glibcxx_requires_nonempty(); + return c.back(); + } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %queue. + */ + const_reference + back() const + { + __glibcxx_requires_nonempty(); + return c.back(); + } + + /** + * @brief Add data to the end of the %queue. + * @param __x Data to be added. + * + * This is a typical %queue operation. The function creates an + * element at the end of the %queue and assigns the given data + * to it. The time complexity of the operation depends on the + * underlying sequence. + */ + void + push(const value_type& __x) + { c.push_back(__x); } + +#if __cplusplus >= 201103L + void + push(value_type&& __x) + { c.push_back(std::move(__x)); } + +#if __cplusplus > 201402L + template + decltype(auto) + emplace(_Args&&... __args) + { return c.emplace_back(std::forward<_Args>(__args)...); } +#else + template + void + emplace(_Args&&... __args) + { c.emplace_back(std::forward<_Args>(__args)...); } +#endif +#endif + + /** + * @brief Removes first element. + * + * This is a typical %queue operation. It shrinks the %queue by one. + * The time complexity of the operation depends on the underlying + * sequence. + * + * Note that no data is returned, and if the first element's + * data is needed, it should be retrieved before pop() is + * called. + */ + void + pop() + { + __glibcxx_requires_nonempty(); + c.pop_front(); + } + +#if __cplusplus >= 201103L + void + swap(queue& __q) +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + noexcept(__is_nothrow_swappable<_Sequence>::value) +#else + noexcept(__is_nothrow_swappable<_Tp>::value) +#endif + { + using std::swap; + swap(c, __q.c); + } +#endif // __cplusplus >= 201103L + }; + +#if __cpp_deduction_guides >= 201606 + template> + queue(_Container) -> queue; + + template, + typename = _RequireAllocator<_Allocator>> + queue(_Container, _Allocator) + -> queue; +#endif + + /** + * @brief Queue equality comparison. + * @param __x A %queue. + * @param __y A %queue of the same type as @a __x. + * @return True iff the size and elements of the queues are equal. + * + * This is an equivalence relation. Complexity and semantics depend on the + * underlying sequence type, but the expected rules are: this relation is + * linear in the size of the sequences, and queues are considered equivalent + * if their sequences compare equal. + */ + template + inline bool + operator==(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return __x.c == __y.c; } + + /** + * @brief Queue ordering relation. + * @param __x A %queue. + * @param __y A %queue of the same type as @a x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is an total ordering relation. Complexity and semantics + * depend on the underlying sequence type, but the expected rules + * are: this relation is linear in the size of the sequences, the + * elements must be comparable with @c <, and + * std::lexicographical_compare() is usually used to make the + * determination. + */ + template + inline bool + operator<(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return __x.c < __y.c; } + + /// Based on operator== + template + inline bool + operator!=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return !(__x < __y); } + +#if __cpp_lib_three_way_comparison + template + inline compare_three_way_result_t<_Seq> + operator<=>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return __x.c <=> __y.c; } +#endif + +#if __cplusplus >= 201103L + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Seq>::value>::type +#else + void +#endif + swap(queue<_Tp, _Seq>& __x, queue<_Tp, _Seq>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + struct uses_allocator, _Alloc> + : public uses_allocator<_Seq, _Alloc>::type { }; +#endif // __cplusplus >= 201103L + + /** + * @brief A standard container automatically sorting its contents. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Sequence Type of underlying sequence, defaults to vector<_Tp>. + * @tparam _Compare Comparison function object type, defaults to + * less<_Sequence::value_type>. + * + * This is not a true container, but an @e adaptor. It holds + * another container, and provides a wrapper interface to that + * container. The wrapper is what enforces priority-based sorting + * and %queue behavior. Very few of the standard container/sequence + * interface requirements are met (e.g., iterators). + * + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::vector, but it can be + * any type that supports @c front(), @c push_back, @c pop_back, + * and random-access iterators, such as std::deque or an + * appropriate user-defined type. + * + * The third template parameter supplies the means of making + * priority comparisons. It defaults to @c less but + * can be anything defining a strict weak ordering. + * + * Members not found in @a normal containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c + * push, @c pop, and @c top, which are standard %queue operations. + * + * @note No equality/comparison operators are provided for + * %priority_queue. + * + * @note Sorting of the elements takes place as they are added to, + * and removed from, the %priority_queue using the + * %priority_queue's member functions. If you access the elements + * by other means, and change their data such that the sorting + * order would be different, the %priority_queue will not re-sort + * the elements for you. (How could it know to do so?) + */ + template, + typename _Compare = less > + class priority_queue + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Sequence::value_type _Sequence_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires(_Sequence, _SequenceConcept) + __glibcxx_class_requires(_Sequence, _RandomAccessContainerConcept) + __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) + __glibcxx_class_requires4(_Compare, bool, _Tp, _Tp, + _BinaryFunctionConcept) +#endif + +#if __cplusplus >= 201103L + template + using _Uses = typename + enable_if::value>::type; + +#if __cplusplus >= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2566. Requirements on the first template parameter of container + // adaptors + static_assert(is_same<_Tp, typename _Sequence::value_type>::value, + "value_type must be the same as the underlying container"); +#endif // C++17 +#endif // C++11 + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 2684. priority_queue lacking comparator typedef + typedef _Compare value_compare; + + protected: + // See queue::c for notes on these names. + _Sequence c; + _Compare comp; + + public: + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + explicit + priority_queue(const _Compare& __x = _Compare(), + const _Sequence& __s = _Sequence()) + : c(__s), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } +#else + template, + is_default_constructible<_Seq>>::value>::type> + priority_queue() + : c(), comp() { } + + explicit + priority_queue(const _Compare& __x, const _Sequence& __s) + : c(__s), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } + + explicit + priority_queue(const _Compare& __x, _Sequence&& __s = _Sequence()) + : c(std::move(__s)), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } + + template> + explicit + priority_queue(const _Alloc& __a) + : c(__a), comp() { } + + template> + priority_queue(const _Compare& __x, const _Alloc& __a) + : c(__a), comp(__x) { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2537. Constructors [...] taking allocators should call make_heap + template> + priority_queue(const _Compare& __x, const _Sequence& __c, + const _Alloc& __a) + : c(__c, __a), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } + + template> + priority_queue(const _Compare& __x, _Sequence&& __c, const _Alloc& __a) + : c(std::move(__c), __a), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } + + template> + priority_queue(const priority_queue& __q, const _Alloc& __a) + : c(__q.c, __a), comp(__q.comp) { } + + template> + priority_queue(priority_queue&& __q, const _Alloc& __a) + : c(std::move(__q.c), __a), comp(std::move(__q.comp)) { } +#endif + + /** + * @brief Builds a %queue from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __x A comparison functor describing a strict weak ordering. + * @param __s An initial sequence with which to start. + * + * Begins by copying @a __s, inserting a copy of the elements + * from @a [first,last) into the copy of @a __s, then ordering + * the copy according to @a __x. + * + * For more information on function objects, see the + * documentation on @link functors functor base + * classes@endlink. + */ +#if __cplusplus < 201103L + template + priority_queue(_InputIterator __first, _InputIterator __last, + const _Compare& __x = _Compare(), + const _Sequence& __s = _Sequence()) + : c(__s), comp(__x) + { + __glibcxx_requires_valid_range(__first, __last); + c.insert(c.end(), __first, __last); + std::make_heap(c.begin(), c.end(), comp); + } +#else + template + priority_queue(_InputIterator __first, _InputIterator __last, + const _Compare& __x, + const _Sequence& __s) + : c(__s), comp(__x) + { + __glibcxx_requires_valid_range(__first, __last); + c.insert(c.end(), __first, __last); + std::make_heap(c.begin(), c.end(), comp); + } + + template + priority_queue(_InputIterator __first, _InputIterator __last, + const _Compare& __x = _Compare(), + _Sequence&& __s = _Sequence()) + : c(std::move(__s)), comp(__x) + { + __glibcxx_requires_valid_range(__first, __last); + c.insert(c.end(), __first, __last); + std::make_heap(c.begin(), c.end(), comp); + } +#endif + + /** + * Returns true if the %queue is empty. + */ + _GLIBCXX_NODISCARD bool + empty() const + { return c.empty(); } + + /** Returns the number of elements in the %queue. */ + size_type + size() const + { return c.size(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %queue. + */ + const_reference + top() const + { + __glibcxx_requires_nonempty(); + return c.front(); + } + + /** + * @brief Add data to the %queue. + * @param __x Data to be added. + * + * This is a typical %queue operation. + * The time complexity of the operation depends on the underlying + * sequence. + */ + void + push(const value_type& __x) + { + c.push_back(__x); + std::push_heap(c.begin(), c.end(), comp); + } + +#if __cplusplus >= 201103L + void + push(value_type&& __x) + { + c.push_back(std::move(__x)); + std::push_heap(c.begin(), c.end(), comp); + } + + template + void + emplace(_Args&&... __args) + { + c.emplace_back(std::forward<_Args>(__args)...); + std::push_heap(c.begin(), c.end(), comp); + } +#endif + + /** + * @brief Removes first element. + * + * This is a typical %queue operation. It shrinks the %queue + * by one. The time complexity of the operation depends on the + * underlying sequence. + * + * Note that no data is returned, and if the first element's + * data is needed, it should be retrieved before pop() is + * called. + */ + void + pop() + { + __glibcxx_requires_nonempty(); + std::pop_heap(c.begin(), c.end(), comp); + c.pop_back(); + } + +#if __cplusplus >= 201103L + void + swap(priority_queue& __pq) + noexcept(__and_< +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + __is_nothrow_swappable<_Sequence>, +#else + __is_nothrow_swappable<_Tp>, +#endif + __is_nothrow_swappable<_Compare> + >::value) + { + using std::swap; + swap(c, __pq.c); + swap(comp, __pq.comp); + } +#endif // __cplusplus >= 201103L + }; + +#if __cpp_deduction_guides >= 201606 + template, + typename = _RequireNotAllocator<_Container>> + priority_queue(_Compare, _Container) + -> priority_queue; + + template::value_type, + typename _Compare = less<_ValT>, + typename _Container = vector<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireNotAllocator<_Container>> + priority_queue(_InputIterator, _InputIterator, _Compare = _Compare(), + _Container = _Container()) + -> priority_queue<_ValT, _Container, _Compare>; + + template, + typename = _RequireNotAllocator<_Container>, + typename = _RequireAllocator<_Allocator>> + priority_queue(_Compare, _Container, _Allocator) + -> priority_queue; +#endif + + // No equality/comparison operators are provided for priority_queue. + +#if __cplusplus >= 201103L + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_Sequence>, + __is_swappable<_Compare>>::value>::type +#else + void +#endif + swap(priority_queue<_Tp, _Sequence, _Compare>& __x, + priority_queue<_Tp, _Sequence, _Compare>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + struct uses_allocator, _Alloc> + : public uses_allocator<_Sequence, _Alloc>::type { }; +#endif // __cplusplus >= 201103L + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_QUEUE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h b/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h new file mode 100644 index 000000000..df7a5f9df --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h @@ -0,0 +1,123 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_raw_storage_iter.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_RAW_STORAGE_ITERATOR_H +#define _STL_RAW_STORAGE_ITERATOR_H 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * This iterator class lets algorithms store their results into + * uninitialized memory. + */ + template + class raw_storage_iterator + : public iterator + { + protected: + _OutputIterator _M_iter; + + public: + explicit + raw_storage_iterator(_OutputIterator __x) + : _M_iter(__x) {} + + raw_storage_iterator& + operator*() { return *this; } + + raw_storage_iterator& + operator=(const _Tp& __element) + { + std::_Construct(std::__addressof(*_M_iter), __element); + return *this; + } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2127. Move-construction with raw_storage_iterator + raw_storage_iterator& + operator=(_Tp&& __element) + { + std::_Construct(std::__addressof(*_M_iter), std::move(__element)); + return *this; + } +#endif + + raw_storage_iterator& + operator++() + { + ++_M_iter; + return *this; + } + + raw_storage_iterator + operator++(int) + { + raw_storage_iterator __tmp = *this; + ++_M_iter; + return __tmp; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2454. Add raw_storage_iterator::base() member + _OutputIterator base() const { return _M_iter; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_relops.h b/resources/sources/avr-libstdcpp/include/bits/stl_relops.h new file mode 100644 index 000000000..3b0afea8a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_relops.h @@ -0,0 +1,133 @@ +// std::rel_ops implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the, 2009 Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1996,1997 + * Silicon Graphics + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file bits/stl_relops.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + * + * Inclusion of this file has been removed from + * all of the other STL headers for safety reasons, except std_utility.h. + * For more information, see the thread of about twenty messages starting + * with http://gcc.gnu.org/ml/libstdc++/2001-01/msg00223.html, or + * http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.ambiguous_overloads + * + * Short summary: the rel_ops operators should be avoided for the present. + */ + +#ifndef _STL_RELOPS_H +#define _STL_RELOPS_H 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + namespace rel_ops + { + /** @namespace std::rel_ops + * @brief The generated relational operators are sequestered here. + */ + + /** + * @brief Defines @c != for arbitrary types, in terms of @c ==. + * @param __x A thing. + * @param __y Another thing. + * @return __x != __y + * + * This function uses @c == to determine its result. + */ + template + inline bool + operator!=(const _Tp& __x, const _Tp& __y) + { return !(__x == __y); } + + /** + * @brief Defines @c > for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x > __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator>(const _Tp& __x, const _Tp& __y) + { return __y < __x; } + + /** + * @brief Defines @c <= for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x <= __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator<=(const _Tp& __x, const _Tp& __y) + { return !(__y < __x); } + + /** + * @brief Defines @c >= for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x >= __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator>=(const _Tp& __x, const _Tp& __y) + { return !(__x < __y); } + } // namespace rel_ops + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_RELOPS_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_set.h b/resources/sources/avr-libstdcpp/include/bits/stl_set.h new file mode 100644 index 000000000..da4266508 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_set.h @@ -0,0 +1,1086 @@ +// Set implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_set.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{set} + */ + +#ifndef _STL_SET_H +#define _STL_SET_H 1 + +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + class multiset; + + /** + * @brief A standard container made up of unique keys, which can be + * retrieved in logarithmic time. + * + * @ingroup associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Compare Comparison function object type, defaults to less<_Key>. + * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using unique keys). + * + * Sets support bidirectional iterators. + * + * The private tree data is declared exactly the same way for set and + * multiset; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + */ + template, + typename _Alloc = std::allocator<_Key> > + class set + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Key, _SGIAssignableConcept) +# endif + __glibcxx_class_requires4(_Compare, bool, _Key, _Key, + _BinaryFunctionConcept) + __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Key>::value, + "std::set must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::set must have the same value_type as its allocator"); +# endif +#endif + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; + typedef _Alloc allocator_type; + //@} + + private: + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Key>::other _Key_alloc_type; + + typedef _Rb_tree, + key_compare, _Key_alloc_type> _Rep_type; + _Rep_type _M_t; // Red-black tree representing set. + + typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits; + + public: + //@{ + /// Iterator-related typedefs. + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 103. set::iterator is required to be modifiable, + // but this allows modification of keys. + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; + using insert_return_type = typename _Rep_type::insert_return_type; +#endif + + // allocation/deallocation + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + set() : _M_t() { } +#else + set() = default; +#endif + + /** + * @brief Creates a %set with no elements. + * @param __comp Comparator to use. + * @param __a An allocator object. + */ + explicit + set(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) { } + + /** + * @brief Builds a %set from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * + * Create a %set consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is + * already sorted, and NlogN otherwise (where N is + * distance(__first,__last)). + */ + template + set(_InputIterator __first, _InputIterator __last) + : _M_t() + { _M_t._M_insert_range_unique(__first, __last); } + + /** + * @brief Builds a %set from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %set consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is + * already sorted, and NlogN otherwise (where N is + * distance(__first,__last)). + */ + template + set(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) + { _M_t._M_insert_range_unique(__first, __last); } + + /** + * @brief %Set copy constructor. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + set(const set& __x) + : _M_t(__x._M_t) { } +#else + set(const set&) = default; + + /** + * @brief %Set move constructor + * + * The newly-created %set contains the exact contents of the moved + * instance. The moved instance is a valid, but unspecified, %set. + */ + set(set&&) = default; + + /** + * @brief Builds a %set from an initializer_list. + * @param __l An initializer_list. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %set consisting of copies of the elements in the list. + * This is linear in N if the list is already sorted, and NlogN + * otherwise (where N is @a __l.size()). + */ + set(initializer_list __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) + { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } + + /// Allocator-extended default constructor. + explicit + set(const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) { } + + /// Allocator-extended copy constructor. + set(const set& __x, const allocator_type& __a) + : _M_t(__x._M_t, _Key_alloc_type(__a)) { } + + /// Allocator-extended move constructor. + set(set&& __x, const allocator_type& __a) + noexcept(is_nothrow_copy_constructible<_Compare>::value + && _Alloc_traits::_S_always_equal()) + : _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { } + + /// Allocator-extended initialier-list constructor. + set(initializer_list __l, const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) + { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } + + /// Allocator-extended range constructor. + template + set(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) + { _M_t._M_insert_range_unique(__first, __last); } + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~set() = default; +#endif + + /** + * @brief %Set assignment operator. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + set& + operator=(const set& __x) + { + _M_t = __x._M_t; + return *this; + } +#else + set& + operator=(const set&) = default; + + /// Move assignment operator. + set& + operator=(set&&) = default; + + /** + * @brief %Set list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %set with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %set and + * that the resulting %set's size is the same as the number + * of elements assigned. + */ + set& + operator=(initializer_list __l) + { + _M_t._M_assign_unique(__l.begin(), __l.end()); + return *this; + } +#endif + + // accessors: + + /// Returns the comparison object with which the %set was constructed. + key_compare + key_comp() const + { return _M_t.key_comp(); } + /// Returns the comparison object with which the %set was constructed. + value_compare + value_comp() const + { return _M_t.key_comp(); } + /// Returns the allocator object with which the %set was constructed. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_t.get_allocator()); } + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %set. Iteration is done in ascending order according + * to the keys. + */ + iterator + begin() const _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %set. Iteration is done in ascending order according + * to the keys. + */ + iterator + end() const _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points to the last + * element in the %set. Iteration is done in descending order according + * to the keys. + */ + reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %set. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %set. Iteration is done in ascending order according + * to the keys. + */ + iterator + cbegin() const noexcept + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %set. Iteration is done in ascending order according + * to the keys. + */ + iterator + cend() const noexcept + { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points to the last + * element in the %set. Iteration is done in descending order according + * to the keys. + */ + reverse_iterator + crbegin() const noexcept + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %set. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + crend() const noexcept + { return _M_t.rend(); } +#endif + + /// Returns true if the %set is empty. + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_t.empty(); } + + /// Returns the size of the %set. + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_t.size(); } + + /// Returns the maximum size of the %set. + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _M_t.max_size(); } + + /** + * @brief Swaps data with another %set. + * @param __x A %set of the same element and allocator types. + * + * This exchanges the elements between two sets in constant + * time. (It is only swapping a pointer, an integer, and an + * instance of the @c Compare type (which itself is often + * stateless and empty), so it should be quite fast.) Note + * that the global std::swap() function is specialized such + * that std::swap(s1,s2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(set& __x) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { _M_t.swap(__x._M_t); } + + // insert/erase +#if __cplusplus >= 201103L + /** + * @brief Attempts to build and insert an element into the %set. + * @param __args Arguments used to generate an element. + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted element, and the second is a bool + * that is true if the element was actually inserted. + * + * This function attempts to build and insert an element into the %set. + * A %set relies on unique keys and thus an element is only inserted if + * it is not already present in the %set. + * + * Insertion requires logarithmic time. + */ + template + std::pair + emplace(_Args&&... __args) + { return _M_t._M_emplace_unique(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to insert an element into the %set. + * @param __pos An iterator that serves as a hint as to where the + * element should be inserted. + * @param __args Arguments used to generate the element to be + * inserted. + * @return An iterator that points to the element with key equivalent to + * the one generated from @a __args (may or may not be the + * element itself). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { + return _M_t._M_emplace_hint_unique(__pos, + std::forward<_Args>(__args)...); + } +#endif + + /** + * @brief Attempts to insert an element into the %set. + * @param __x Element to be inserted. + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted element, and the second is a bool + * that is true if the element was actually inserted. + * + * This function attempts to insert an element into the %set. A %set + * relies on unique keys and thus an element is only inserted if it is + * not already present in the %set. + * + * Insertion requires logarithmic time. + */ + std::pair + insert(const value_type& __x) + { + std::pair __p = + _M_t._M_insert_unique(__x); + return std::pair(__p.first, __p.second); + } + +#if __cplusplus >= 201103L + std::pair + insert(value_type&& __x) + { + std::pair __p = + _M_t._M_insert_unique(std::move(__x)); + return std::pair(__p.first, __p.second); + } +#endif + + /** + * @brief Attempts to insert an element into the %set. + * @param __position An iterator that serves as a hint as to where the + * element should be inserted. + * @param __x Element to be inserted. + * @return An iterator that points to the element with key of + * @a __x (may or may not be the element passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument insert() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + iterator + insert(const_iterator __position, const value_type& __x) + { return _M_t._M_insert_unique_(__position, __x); } + +#if __cplusplus >= 201103L + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_unique_(__position, std::move(__x)); } +#endif + + /** + * @brief A template function that attempts to insert a range + * of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_range_unique(__first, __last); } + +#if __cplusplus >= 201103L + /** + * @brief Attempts to insert a list of elements into the %set. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { this->insert(__l.begin(), __l.end()); } +#endif + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_unique(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); } + + template + friend class std::_Rb_tree_merge_helper; + + template + void + merge(set<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(set<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(multiset<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(multiset<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases an element from a %set. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from a %set. Note that this function only erases the element, and + * that if the element is itself a pointer, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __position) + { return _M_t.erase(__position); } +#else + /** + * @brief Erases an element from a %set. + * @param position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, + * from a %set. Note that this function only erases the element, and + * that if the element is itself a pointer, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __position) + { _M_t.erase(__position); } +#endif + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * a %set. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_t.erase(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [__first,__last) range of elements from a %set. + * @param __first Iterator pointing to the start of the range to be + * erased. + + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from a %set. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_t.erase(__first, __last); } +#else + /** + * @brief Erases a [first,last) range of elements from a %set. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * + * This function erases a sequence of elements from a %set. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } +#endif + + /** + * Erases all elements in a %set. Note that this function only erases + * the elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_t.clear(); } + + // set operations: + + //@{ + /** + * @brief Finds the number of elements. + * @param __x Element to located. + * @return Number of elements with specified key. + * + * This function only makes sense for multisets; for set the result will + * either be 0 (not present) or 1 (present). + */ + size_type + count(const key_type& __x) const + { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } + +#if __cplusplus > 201103L + template + auto + count(const _Kt& __x) const + -> decltype(_M_t._M_count_tr(__x)) + { return _M_t._M_count_tr(__x); } +#endif + //@} + +#if __cplusplus > 201703L + //@{ + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is an element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_t.find(__x) != _M_t.end(); } + + template + auto + contains(const _Kt& __x) const + -> decltype(_M_t._M_find_tr(__x), void(), true) + { return _M_t._M_find_tr(__x) != _M_t.end(); } + //@} +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + //@{ + /** + * @brief Tries to locate an element in a %set. + * @param __x Element to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_t.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) + -> decltype(iterator{_M_t._M_find_tr(__x)}) + { return iterator{_M_t._M_find_tr(__x)}; } + + template + auto + find(const _Kt& __x) const + -> decltype(const_iterator{_M_t._M_find_tr(__x)}) + { return const_iterator{_M_t._M_find_tr(__x)}; } +#endif + //@} + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key to be located. + * @return Iterator pointing to first element equal to or greater + * than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) + { return _M_t.lower_bound(__x); } + + const_iterator + lower_bound(const key_type& __x) const + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } + + template + auto + lower_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key to be located. + * @return Iterator pointing to the first element + * greater than key, or end(). + */ + iterator + upper_bound(const key_type& __x) + { return _M_t.upper_bound(__x); } + + const_iterator + upper_bound(const key_type& __x) const + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } + + template + auto + upper_bound(const _Kt& __x) const + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + * + * This function probably only makes sense for multisets. + */ + std::pair + equal_range(const key_type& __x) + { return _M_t.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } + + template + auto + equal_range(const _Kt& __x) const + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } +#endif + //@} + + template + friend bool + operator==(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); + +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t<_K1> + operator<=>(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); +#else + template + friend bool + operator<(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); +#endif + }; + +#if __cpp_deduction_guides >= 201606 + + template::value_type>, + typename _Allocator = + allocator::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + set(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> set::value_type, + _Compare, _Allocator>; + + template, + typename _Allocator = allocator<_Key>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + set(initializer_list<_Key>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> set<_Key, _Compare, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + set(_InputIterator, _InputIterator, _Allocator) + -> set::value_type, + less::value_type>, + _Allocator>; + + template> + set(initializer_list<_Key>, _Allocator) + -> set<_Key, less<_Key>, _Allocator>; + +#endif // deduction guides + + /** + * @brief Set equality comparison. + * @param __x A %set. + * @param __y A %set of the same type as @a x. + * @return True iff the size and elements of the sets are equal. + * + * This is an equivalence relation. It is linear in the size of the sets. + * Sets are considered equivalent if their sizes are equal, and if + * corresponding elements compare equal. + */ + template + inline bool + operator==(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __x._M_t == __y._M_t; } + +#if __cpp_lib_three_way_comparison + /** + * @brief Set ordering relation. + * @param __x A `set`. + * @param __y A `set` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Key> + operator<=>(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else + /** + * @brief Set ordering relation. + * @param __x A %set. + * @param __y A %set of the same type as @a x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * sets. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __x._M_t < __y._M_t; } + + /// Returns !(x == y). + template + inline bool + operator!=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return !(__x == __y); } + + /// Returns y < x. + template + inline bool + operator>(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __y < __x; } + + /// Returns !(y < x) + template + inline bool + operator<=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return !(__y < __x); } + + /// Returns !(x < y) + template + inline bool + operator>=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::set::swap(). + template + inline void + swap(set<_Key, _Compare, _Alloc>& __x, set<_Key, _Compare, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::set access to internals of compatible sets. + template + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>, _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} //namespace std +#endif /* _STL_SET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_stack.h b/resources/sources/avr-libstdcpp/include/bits/stl_stack.h new file mode 100644 index 000000000..1ce98a94a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_stack.h @@ -0,0 +1,392 @@ +// Stack implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_stack.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{stack} + */ + +#ifndef _STL_STACK_H +#define _STL_STACK_H 1 + +#include +#include +#if __cplusplus >= 201103L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief A standard container giving FILO behavior. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Sequence Type of underlying sequence, defaults to deque<_Tp>. + * + * Meets many of the requirements of a + * container, + * but does not define anything to do with iterators. Very few of the + * other standard container interfaces are defined. + * + * This is not a true container, but an @e adaptor. It holds + * another container, and provides a wrapper interface to that + * container. The wrapper is what enforces strict + * first-in-last-out %stack behavior. + * + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::deque, but it can be + * any type that supports @c back, @c push_back, and @c pop_back, + * such as std::list, std::vector, or an appropriate user-defined + * type. + * + * Members not found in @a normal containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c + * push, @c pop, and @c top, which are standard %stack/FILO + * operations. + */ + template > + class stack + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Sequence::value_type _Sequence_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) + __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) +# endif + __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) +#endif + + template + friend bool + operator==(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); + + template + friend bool + operator<(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); + +#if __cpp_lib_three_way_comparison + template + friend compare_three_way_result_t<_Seq1> + operator<=>(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); +#endif + +#if __cplusplus >= 201103L + template + using _Uses = typename + enable_if::value>::type; + +#if __cplusplus >= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2566. Requirements on the first template parameter of container + // adaptors + static_assert(is_same<_Tp, typename _Sequence::value_type>::value, + "value_type must be the same as the underlying container"); +#endif // C++17 +#endif // C++11 + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + protected: + // See queue::c for notes on this name. + _Sequence c; + + public: + // XXX removed old def ctor, added def arg to this one to match 14882 + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + explicit + stack(const _Sequence& __c = _Sequence()) + : c(__c) { } +#else + template::value>::type> + stack() + : c() { } + + explicit + stack(const _Sequence& __c) + : c(__c) { } + + explicit + stack(_Sequence&& __c) + : c(std::move(__c)) { } + + template> + explicit + stack(const _Alloc& __a) + : c(__a) { } + + template> + stack(const _Sequence& __c, const _Alloc& __a) + : c(__c, __a) { } + + template> + stack(_Sequence&& __c, const _Alloc& __a) + : c(std::move(__c), __a) { } + + template> + stack(const stack& __q, const _Alloc& __a) + : c(__q.c, __a) { } + + template> + stack(stack&& __q, const _Alloc& __a) + : c(std::move(__q.c), __a) { } +#endif + + /** + * Returns true if the %stack is empty. + */ + _GLIBCXX_NODISCARD bool + empty() const + { return c.empty(); } + + /** Returns the number of elements in the %stack. */ + size_type + size() const + { return c.size(); } + + /** + * Returns a read/write reference to the data at the first + * element of the %stack. + */ + reference + top() + { + __glibcxx_requires_nonempty(); + return c.back(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %stack. + */ + const_reference + top() const + { + __glibcxx_requires_nonempty(); + return c.back(); + } + + /** + * @brief Add data to the top of the %stack. + * @param __x Data to be added. + * + * This is a typical %stack operation. The function creates an + * element at the top of the %stack and assigns the given data + * to it. The time complexity of the operation depends on the + * underlying sequence. + */ + void + push(const value_type& __x) + { c.push_back(__x); } + +#if __cplusplus >= 201103L + void + push(value_type&& __x) + { c.push_back(std::move(__x)); } + +#if __cplusplus > 201402L + template + decltype(auto) + emplace(_Args&&... __args) + { return c.emplace_back(std::forward<_Args>(__args)...); } +#else + template + void + emplace(_Args&&... __args) + { c.emplace_back(std::forward<_Args>(__args)...); } +#endif +#endif + + /** + * @brief Removes first element. + * + * This is a typical %stack operation. It shrinks the %stack + * by one. The time complexity of the operation depends on the + * underlying sequence. + * + * Note that no data is returned, and if the first element's + * data is needed, it should be retrieved before pop() is + * called. + */ + void + pop() + { + __glibcxx_requires_nonempty(); + c.pop_back(); + } + +#if __cplusplus >= 201103L + void + swap(stack& __s) +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + noexcept(__is_nothrow_swappable<_Sequence>::value) +#else + noexcept(__is_nothrow_swappable<_Tp>::value) +#endif + { + using std::swap; + swap(c, __s.c); + } +#endif // __cplusplus >= 201103L + }; + +#if __cpp_deduction_guides >= 201606 + template> + stack(_Container) -> stack; + + template, + typename = _RequireAllocator<_Allocator>> + stack(_Container, _Allocator) + -> stack; +#endif + + /** + * @brief Stack equality comparison. + * @param __x A %stack. + * @param __y A %stack of the same type as @a __x. + * @return True iff the size and elements of the stacks are equal. + * + * This is an equivalence relation. Complexity and semantics + * depend on the underlying sequence type, but the expected rules + * are: this relation is linear in the size of the sequences, and + * stacks are considered equivalent if their sequences compare + * equal. + */ + template + inline bool + operator==(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return __x.c == __y.c; } + + /** + * @brief Stack ordering relation. + * @param __x A %stack. + * @param __y A %stack of the same type as @a x. + * @return True iff @a x is lexicographically less than @a __y. + * + * This is an total ordering relation. Complexity and semantics + * depend on the underlying sequence type, but the expected rules + * are: this relation is linear in the size of the sequences, the + * elements must be comparable with @c <, and + * std::lexicographical_compare() is usually used to make the + * determination. + */ + template + inline bool + operator<(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return __x.c < __y.c; } + + /// Based on operator== + template + inline bool + operator!=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return !(__x < __y); } + +#if __cpp_lib_three_way_comparison + template + inline compare_three_way_result_t<_Seq> + operator<=>(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return __x.c <=> __y.c; } +#endif + +#if __cplusplus >= 201103L + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Seq>::value>::type +#else + void +#endif + swap(stack<_Tp, _Seq>& __x, stack<_Tp, _Seq>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + struct uses_allocator, _Alloc> + : public uses_allocator<_Seq, _Alloc>::type { }; +#endif // __cplusplus >= 201103L + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_STACK_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h b/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h new file mode 100644 index 000000000..f6f179604 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h @@ -0,0 +1,284 @@ +// Temporary buffer implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_tempbuf.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_TEMPBUF_H +#define _STL_TEMPBUF_H 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + namespace __detail + { + template + inline void + __return_temporary_buffer(_Tp* __p, + size_t __len __attribute__((__unused__))) + { +#if __cpp_sized_deallocation + ::operator delete(__p, __len * sizeof(_Tp)); +#else + ::operator delete(__p); +#endif + } + } + + /** + * @brief Allocates a temporary buffer. + * @param __len The number of objects of type Tp. + * @return See full description. + * + * Reinventing the wheel, but this time with prettier spokes! + * + * This function tries to obtain storage for @c __len adjacent Tp + * objects. The objects themselves are not constructed, of course. + * A pair<> is returned containing the buffer s address and + * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if + * no storage can be obtained. Note that the capacity obtained + * may be less than that requested if the memory is unavailable; + * you should compare len with the .second return value. + * + * Provides the nothrow exception guarantee. + */ + template + pair<_Tp*, ptrdiff_t> + get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT + { + const ptrdiff_t __max = + __gnu_cxx::__numeric_traits::__max / sizeof(_Tp); + if (__len > __max) + __len = __max; + + while (__len > 0) + { + _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp), + std::nothrow)); + if (__tmp != 0) + return std::pair<_Tp*, ptrdiff_t>(__tmp, __len); + __len /= 2; + } + return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0); + } + + /** + * @brief The companion to get_temporary_buffer(). + * @param __p A buffer previously allocated by get_temporary_buffer. + * @return None. + * + * Frees the memory pointed to by __p. + */ + template + inline void + return_temporary_buffer(_Tp* __p) + { ::operator delete(__p); } + + /** + * This class is used in two places: stl_algo.h and ext/memory, + * where it is wrapped as the temporary_buffer class. See + * temporary_buffer docs for more notes. + */ + template + class _Temporary_buffer + { + // concept requirements + __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept) + + public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef pointer iterator; + typedef ptrdiff_t size_type; + + protected: + size_type _M_original_len; + size_type _M_len; + pointer _M_buffer; + + public: + /// As per Table mumble. + size_type + size() const + { return _M_len; } + + /// Returns the size requested by the constructor; may be >size(). + size_type + requested_size() const + { return _M_original_len; } + + /// As per Table mumble. + iterator + begin() + { return _M_buffer; } + + /// As per Table mumble. + iterator + end() + { return _M_buffer + _M_len; } + + /** + * Constructs a temporary buffer of a size somewhere between + * zero and the given length. + */ + _Temporary_buffer(_ForwardIterator __seed, size_type __original_len); + + ~_Temporary_buffer() + { + std::_Destroy(_M_buffer, _M_buffer + _M_len); + std::__detail::__return_temporary_buffer(_M_buffer, _M_len); + } + + private: + // Disable copy constructor and assignment operator. + _Temporary_buffer(const _Temporary_buffer&); + + void + operator=(const _Temporary_buffer&); + }; + + + template + struct __uninitialized_construct_buf_dispatch + { + template + static void + __ucr(_Pointer __first, _Pointer __last, + _ForwardIterator __seed) + { + if (__first == __last) + return; + + _Pointer __cur = __first; + __try + { + std::_Construct(std::__addressof(*__first), + _GLIBCXX_MOVE(*__seed)); + _Pointer __prev = __cur; + ++__cur; + for(; __cur != __last; ++__cur, ++__prev) + std::_Construct(std::__addressof(*__cur), + _GLIBCXX_MOVE(*__prev)); + *__seed = _GLIBCXX_MOVE(*__prev); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_construct_buf_dispatch + { + template + static void + __ucr(_Pointer, _Pointer, _ForwardIterator) { } + }; + + // Constructs objects in the range [first, last). + // Note that while these new objects will take valid values, + // their exact value is not defined. In particular they may + // be 'moved from'. + // + // While *__seed may be altered during this algorithm, it will have + // the same value when the algorithm finishes, unless one of the + // constructions throws. + // + // Requirements: _Pointer::value_type(_Tp&&) is valid. + template + inline void + __uninitialized_construct_buf(_Pointer __first, _Pointer __last, + _ForwardIterator __seed) + { + typedef typename std::iterator_traits<_Pointer>::value_type + _ValueType; + + std::__uninitialized_construct_buf_dispatch< + __has_trivial_constructor(_ValueType)>:: + __ucr(__first, __last, __seed); + } + + template + _Temporary_buffer<_ForwardIterator, _Tp>:: + _Temporary_buffer(_ForwardIterator __seed, size_type __original_len) + : _M_original_len(__original_len), _M_len(0), _M_buffer(0) + { + std::pair __p( + std::get_temporary_buffer(_M_original_len)); + + if (__p.first) + { + __try + { + std::__uninitialized_construct_buf(__p.first, __p.first + __p.second, + __seed); + _M_buffer = __p.first; + _M_len = __p.second; + } + __catch(...) + { + std::__detail::__return_temporary_buffer(__p.first, __p.second); + __throw_exception_again; + } + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_TEMPBUF_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_tree.h b/resources/sources/avr-libstdcpp/include/bits/stl_tree.h new file mode 100644 index 000000000..5be15afa2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_tree.h @@ -0,0 +1,2644 @@ +// RB tree implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + */ + +/** @file bits/stl_tree.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{map,set} + */ + +#ifndef _STL_TREE_H +#define _STL_TREE_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include +#if __cplusplus >= 201103L +# include +#endif +#if __cplusplus > 201402L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus > 201103L +# define __cpp_lib_generic_associative_lookup 201304 +#endif + + // Red-black tree class, designed for use in implementing STL + // associative containers (set, multiset, map, and multimap). The + // insertion and deletion algorithms are based on those in Cormen, + // Leiserson, and Rivest, Introduction to Algorithms (MIT Press, + // 1990), except that + // + // (1) the header cell is maintained with links not only to the root + // but also to the leftmost node of the tree, to enable constant + // time begin(), and to the rightmost node of the tree, to enable + // linear time performance when used with the generic set algorithms + // (set_union, etc.) + // + // (2) when a node being deleted has two children its successor node + // is relinked into its place, rather than copied, so that the only + // iterators invalidated are those referring to the deleted node. + + enum _Rb_tree_color { _S_red = false, _S_black = true }; + + struct _Rb_tree_node_base + { + typedef _Rb_tree_node_base* _Base_ptr; + typedef const _Rb_tree_node_base* _Const_Base_ptr; + + _Rb_tree_color _M_color; + _Base_ptr _M_parent; + _Base_ptr _M_left; + _Base_ptr _M_right; + + static _Base_ptr + _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } + + static _Const_Base_ptr + _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } + + static _Base_ptr + _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + + static _Const_Base_ptr + _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + }; + + // Helper type offering value initialization guarantee on the compare functor. + template + struct _Rb_tree_key_compare + { + _Key_compare _M_key_compare; + + _Rb_tree_key_compare() + _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Key_compare>::value) + : _M_key_compare() + { } + + _Rb_tree_key_compare(const _Key_compare& __comp) + : _M_key_compare(__comp) + { } + +#if __cplusplus >= 201103L + // Copy constructor added for consistency with C++98 mode. + _Rb_tree_key_compare(const _Rb_tree_key_compare&) = default; + + _Rb_tree_key_compare(_Rb_tree_key_compare&& __x) + noexcept(is_nothrow_copy_constructible<_Key_compare>::value) + : _M_key_compare(__x._M_key_compare) + { } +#endif + }; + + // Helper type to manage default initialization of node count and header. + struct _Rb_tree_header + { + _Rb_tree_node_base _M_header; + size_t _M_node_count; // Keeps track of size of tree. + + _Rb_tree_header() _GLIBCXX_NOEXCEPT + { + _M_header._M_color = _S_red; + _M_reset(); + } + +#if __cplusplus >= 201103L + _Rb_tree_header(_Rb_tree_header&& __x) noexcept + { + if (__x._M_header._M_parent != nullptr) + _M_move_data(__x); + else + { + _M_header._M_color = _S_red; + _M_reset(); + } + } +#endif + + void + _M_move_data(_Rb_tree_header& __from) + { + _M_header._M_color = __from._M_header._M_color; + _M_header._M_parent = __from._M_header._M_parent; + _M_header._M_left = __from._M_header._M_left; + _M_header._M_right = __from._M_header._M_right; + _M_header._M_parent->_M_parent = &_M_header; + _M_node_count = __from._M_node_count; + + __from._M_reset(); + } + + void + _M_reset() + { + _M_header._M_parent = 0; + _M_header._M_left = &_M_header; + _M_header._M_right = &_M_header; + _M_node_count = 0; + } + }; + + template + struct _Rb_tree_node : public _Rb_tree_node_base + { + typedef _Rb_tree_node<_Val>* _Link_type; + +#if __cplusplus < 201103L + _Val _M_value_field; + + _Val* + _M_valptr() + { return std::__addressof(_M_value_field); } + + const _Val* + _M_valptr() const + { return std::__addressof(_M_value_field); } +#else + __gnu_cxx::__aligned_membuf<_Val> _M_storage; + + _Val* + _M_valptr() + { return _M_storage._M_ptr(); } + + const _Val* + _M_valptr() const + { return _M_storage._M_ptr(); } +#endif + }; + + _GLIBCXX_PURE _Rb_tree_node_base* + _Rb_tree_increment(_Rb_tree_node_base* __x) throw (); + + _GLIBCXX_PURE const _Rb_tree_node_base* + _Rb_tree_increment(const _Rb_tree_node_base* __x) throw (); + + _GLIBCXX_PURE _Rb_tree_node_base* + _Rb_tree_decrement(_Rb_tree_node_base* __x) throw (); + + _GLIBCXX_PURE const _Rb_tree_node_base* + _Rb_tree_decrement(const _Rb_tree_node_base* __x) throw (); + + template + struct _Rb_tree_iterator + { + typedef _Tp value_type; + typedef _Tp& reference; + typedef _Tp* pointer; + + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + + typedef _Rb_tree_iterator<_Tp> _Self; + typedef _Rb_tree_node_base::_Base_ptr _Base_ptr; + typedef _Rb_tree_node<_Tp>* _Link_type; + + _Rb_tree_iterator() _GLIBCXX_NOEXCEPT + : _M_node() { } + + explicit + _Rb_tree_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT + : _M_node(__x) { } + + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *static_cast<_Link_type>(_M_node)->_M_valptr(); } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type> (_M_node)->_M_valptr(); } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + _M_node = _Rb_tree_increment(_M_node); + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _Rb_tree_increment(_M_node); + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + _M_node = _Rb_tree_decrement(_M_node); + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _Rb_tree_decrement(_M_node); + return __tmp; + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node == __y._M_node; } + +#if ! __cpp_lib_three_way_comparison + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node != __y._M_node; } +#endif + + _Base_ptr _M_node; + }; + + template + struct _Rb_tree_const_iterator + { + typedef _Tp value_type; + typedef const _Tp& reference; + typedef const _Tp* pointer; + + typedef _Rb_tree_iterator<_Tp> iterator; + + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + + typedef _Rb_tree_const_iterator<_Tp> _Self; + typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr; + typedef const _Rb_tree_node<_Tp>* _Link_type; + + _Rb_tree_const_iterator() _GLIBCXX_NOEXCEPT + : _M_node() { } + + explicit + _Rb_tree_const_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT + : _M_node(__x) { } + + _Rb_tree_const_iterator(const iterator& __it) _GLIBCXX_NOEXCEPT + : _M_node(__it._M_node) { } + + iterator + _M_const_cast() const _GLIBCXX_NOEXCEPT + { return iterator(const_cast(_M_node)); } + + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *static_cast<_Link_type>(_M_node)->_M_valptr(); } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type>(_M_node)->_M_valptr(); } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + _M_node = _Rb_tree_increment(_M_node); + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _Rb_tree_increment(_M_node); + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + _M_node = _Rb_tree_decrement(_M_node); + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _Rb_tree_decrement(_M_node); + return __tmp; + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node == __y._M_node; } + +#if ! __cpp_lib_three_way_comparison + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node != __y._M_node; } +#endif + + _Base_ptr _M_node; + }; + + void + _Rb_tree_insert_and_rebalance(const bool __insert_left, + _Rb_tree_node_base* __x, + _Rb_tree_node_base* __p, + _Rb_tree_node_base& __header) throw (); + + _Rb_tree_node_base* + _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z, + _Rb_tree_node_base& __header) throw (); + +#if __cplusplus >= 201402L + template> + struct __has_is_transparent + { }; + + template + struct __has_is_transparent<_Cmp, _SfinaeType, + __void_t> + { typedef void type; }; + + template + using __has_is_transparent_t + = typename __has_is_transparent<_Cmp, _SfinaeType>::type; +#endif + +#if __cplusplus > 201402L + template + struct _Rb_tree_merge_helper { }; +#endif + + template > + class _Rb_tree + { + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Rb_tree_node<_Val> >::other _Node_allocator; + + typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Alloc_traits; + + protected: + typedef _Rb_tree_node_base* _Base_ptr; + typedef const _Rb_tree_node_base* _Const_Base_ptr; + typedef _Rb_tree_node<_Val>* _Link_type; + typedef const _Rb_tree_node<_Val>* _Const_Link_type; + + private: + // Functor recycling a pool of nodes and using allocation once the pool + // is empty. + struct _Reuse_or_alloc_node + { + _Reuse_or_alloc_node(_Rb_tree& __t) + : _M_root(__t._M_root()), _M_nodes(__t._M_rightmost()), _M_t(__t) + { + if (_M_root) + { + _M_root->_M_parent = 0; + + if (_M_nodes->_M_left) + _M_nodes = _M_nodes->_M_left; + } + else + _M_nodes = 0; + } + +#if __cplusplus >= 201103L + _Reuse_or_alloc_node(const _Reuse_or_alloc_node&) = delete; +#endif + + ~_Reuse_or_alloc_node() + { _M_t._M_erase(static_cast<_Link_type>(_M_root)); } + + template + _Link_type +#if __cplusplus < 201103L + operator()(const _Arg& __arg) +#else + operator()(_Arg&& __arg) +#endif + { + _Link_type __node = static_cast<_Link_type>(_M_extract()); + if (__node) + { + _M_t._M_destroy_node(__node); + _M_t._M_construct_node(__node, _GLIBCXX_FORWARD(_Arg, __arg)); + return __node; + } + + return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); + } + + private: + _Base_ptr + _M_extract() + { + if (!_M_nodes) + return _M_nodes; + + _Base_ptr __node = _M_nodes; + _M_nodes = _M_nodes->_M_parent; + if (_M_nodes) + { + if (_M_nodes->_M_right == __node) + { + _M_nodes->_M_right = 0; + + if (_M_nodes->_M_left) + { + _M_nodes = _M_nodes->_M_left; + + while (_M_nodes->_M_right) + _M_nodes = _M_nodes->_M_right; + + if (_M_nodes->_M_left) + _M_nodes = _M_nodes->_M_left; + } + } + else // __node is on the left. + _M_nodes->_M_left = 0; + } + else + _M_root = 0; + + return __node; + } + + _Base_ptr _M_root; + _Base_ptr _M_nodes; + _Rb_tree& _M_t; + }; + + // Functor similar to the previous one but without any pool of nodes to + // recycle. + struct _Alloc_node + { + _Alloc_node(_Rb_tree& __t) + : _M_t(__t) { } + + template + _Link_type +#if __cplusplus < 201103L + operator()(const _Arg& __arg) const +#else + operator()(_Arg&& __arg) const +#endif + { return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); } + + private: + _Rb_tree& _M_t; + }; + + public: + typedef _Key key_type; + typedef _Val value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + _Node_allocator& + _M_get_Node_allocator() _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + const _Node_allocator& + _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_get_Node_allocator()); } + + protected: + _Link_type + _M_get_node() + { return _Alloc_traits::allocate(_M_get_Node_allocator(), 1); } + + void + _M_put_node(_Link_type __p) _GLIBCXX_NOEXCEPT + { _Alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1); } + +#if __cplusplus < 201103L + void + _M_construct_node(_Link_type __node, const value_type& __x) + { + __try + { get_allocator().construct(__node->_M_valptr(), __x); } + __catch(...) + { + _M_put_node(__node); + __throw_exception_again; + } + } + + _Link_type + _M_create_node(const value_type& __x) + { + _Link_type __tmp = _M_get_node(); + _M_construct_node(__tmp, __x); + return __tmp; + } +#else + template + void + _M_construct_node(_Link_type __node, _Args&&... __args) + { + __try + { + ::new(__node) _Rb_tree_node<_Val>; + _Alloc_traits::construct(_M_get_Node_allocator(), + __node->_M_valptr(), + std::forward<_Args>(__args)...); + } + __catch(...) + { + __node->~_Rb_tree_node<_Val>(); + _M_put_node(__node); + __throw_exception_again; + } + } + + template + _Link_type + _M_create_node(_Args&&... __args) + { + _Link_type __tmp = _M_get_node(); + _M_construct_node(__tmp, std::forward<_Args>(__args)...); + return __tmp; + } +#endif + + void + _M_destroy_node(_Link_type __p) _GLIBCXX_NOEXCEPT + { +#if __cplusplus < 201103L + get_allocator().destroy(__p->_M_valptr()); +#else + _Alloc_traits::destroy(_M_get_Node_allocator(), __p->_M_valptr()); + __p->~_Rb_tree_node<_Val>(); +#endif + } + + void + _M_drop_node(_Link_type __p) _GLIBCXX_NOEXCEPT + { + _M_destroy_node(__p); + _M_put_node(__p); + } + + template + _Link_type + _M_clone_node(_Const_Link_type __x, _NodeGen& __node_gen) + { + _Link_type __tmp = __node_gen(*__x->_M_valptr()); + __tmp->_M_color = __x->_M_color; + __tmp->_M_left = 0; + __tmp->_M_right = 0; + return __tmp; + } + + protected: +#if _GLIBCXX_INLINE_VERSION + template +#else + // Unused _Is_pod_comparator is kept as it is part of mangled name. + template +#endif + struct _Rb_tree_impl + : public _Node_allocator + , public _Rb_tree_key_compare<_Key_compare> + , public _Rb_tree_header + { + typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare; + + _Rb_tree_impl() + _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Node_allocator>::value + && is_nothrow_default_constructible<_Base_key_compare>::value ) + : _Node_allocator() + { } + + _Rb_tree_impl(const _Rb_tree_impl& __x) + : _Node_allocator(_Alloc_traits::_S_select_on_copy(__x)) + , _Base_key_compare(__x._M_key_compare) + { } + +#if __cplusplus < 201103L + _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a) + : _Node_allocator(__a), _Base_key_compare(__comp) + { } +#else + _Rb_tree_impl(_Rb_tree_impl&&) = default; + + explicit + _Rb_tree_impl(_Node_allocator&& __a) + : _Node_allocator(std::move(__a)) + { } + + _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a) + : _Node_allocator(std::move(__a)), + _Base_key_compare(std::move(__x)), + _Rb_tree_header(std::move(__x)) + { } + + _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a) + : _Node_allocator(std::move(__a)), _Base_key_compare(__comp) + { } +#endif + }; + + _Rb_tree_impl<_Compare> _M_impl; + + protected: + _Base_ptr& + _M_root() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_parent; } + + _Const_Base_ptr + _M_root() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_parent; } + + _Base_ptr& + _M_leftmost() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_left; } + + _Const_Base_ptr + _M_leftmost() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_left; } + + _Base_ptr& + _M_rightmost() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_right; } + + _Const_Base_ptr + _M_rightmost() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_right; } + + _Link_type + _M_begin() _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } + + _Const_Link_type + _M_begin() const _GLIBCXX_NOEXCEPT + { + return static_cast<_Const_Link_type> + (this->_M_impl._M_header._M_parent); + } + + _Base_ptr + _M_end() _GLIBCXX_NOEXCEPT + { return &this->_M_impl._M_header; } + + _Const_Base_ptr + _M_end() const _GLIBCXX_NOEXCEPT + { return &this->_M_impl._M_header; } + + static const _Key& + _S_key(_Const_Link_type __x) + { +#if __cplusplus >= 201103L + // If we're asking for the key we're presumably using the comparison + // object, and so this is a good place to sanity check it. + static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{}, + "comparison object must be invocable " + "with two arguments of key type"); +# if __cplusplus >= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2542. Missing const requirements for associative containers + if constexpr (__is_invocable<_Compare&, const _Key&, const _Key&>{}) + static_assert( + is_invocable_v, + "comparison object must be invocable as const"); +# endif // C++17 +#endif // C++11 + + return _KeyOfValue()(*__x->_M_valptr()); + } + + static _Link_type + _S_left(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type>(__x->_M_left); } + + static _Const_Link_type + _S_left(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return static_cast<_Const_Link_type>(__x->_M_left); } + + static _Link_type + _S_right(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type>(__x->_M_right); } + + static _Const_Link_type + _S_right(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return static_cast<_Const_Link_type>(__x->_M_right); } + + static const _Key& + _S_key(_Const_Base_ptr __x) + { return _S_key(static_cast<_Const_Link_type>(__x)); } + + static _Base_ptr + _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return _Rb_tree_node_base::_S_minimum(__x); } + + static _Const_Base_ptr + _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return _Rb_tree_node_base::_S_minimum(__x); } + + static _Base_ptr + _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return _Rb_tree_node_base::_S_maximum(__x); } + + static _Const_Base_ptr + _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return _Rb_tree_node_base::_S_maximum(__x); } + + public: + typedef _Rb_tree_iterator iterator; + typedef _Rb_tree_const_iterator const_iterator; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + +#if __cplusplus > 201402L + using node_type = _Node_handle<_Key, _Val, _Node_allocator>; + using insert_return_type = _Node_insert_return< + conditional_t, const_iterator, iterator>, + node_type>; +#endif + + pair<_Base_ptr, _Base_ptr> + _M_get_insert_unique_pos(const key_type& __k); + + pair<_Base_ptr, _Base_ptr> + _M_get_insert_equal_pos(const key_type& __k); + + pair<_Base_ptr, _Base_ptr> + _M_get_insert_hint_unique_pos(const_iterator __pos, + const key_type& __k); + + pair<_Base_ptr, _Base_ptr> + _M_get_insert_hint_equal_pos(const_iterator __pos, + const key_type& __k); + + private: +#if __cplusplus >= 201103L + template + iterator + _M_insert_(_Base_ptr __x, _Base_ptr __y, _Arg&& __v, _NodeGen&); + + iterator + _M_insert_node(_Base_ptr __x, _Base_ptr __y, _Link_type __z); + + template + iterator + _M_insert_lower(_Base_ptr __y, _Arg&& __v); + + template + iterator + _M_insert_equal_lower(_Arg&& __x); + + iterator + _M_insert_lower_node(_Base_ptr __p, _Link_type __z); + + iterator + _M_insert_equal_lower_node(_Link_type __z); +#else + template + iterator + _M_insert_(_Base_ptr __x, _Base_ptr __y, + const value_type& __v, _NodeGen&); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 233. Insertion hints in associative containers. + iterator + _M_insert_lower(_Base_ptr __y, const value_type& __v); + + iterator + _M_insert_equal_lower(const value_type& __x); +#endif + + template + _Link_type + _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen&); + + template + _Link_type + _M_copy(const _Rb_tree& __x, _NodeGen& __gen) + { + _Link_type __root = _M_copy(__x._M_begin(), _M_end(), __gen); + _M_leftmost() = _S_minimum(__root); + _M_rightmost() = _S_maximum(__root); + _M_impl._M_node_count = __x._M_impl._M_node_count; + return __root; + } + + _Link_type + _M_copy(const _Rb_tree& __x) + { + _Alloc_node __an(*this); + return _M_copy(__x, __an); + } + + void + _M_erase(_Link_type __x); + + iterator + _M_lower_bound(_Link_type __x, _Base_ptr __y, + const _Key& __k); + + const_iterator + _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y, + const _Key& __k) const; + + iterator + _M_upper_bound(_Link_type __x, _Base_ptr __y, + const _Key& __k); + + const_iterator + _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y, + const _Key& __k) const; + + public: + // allocation/deallocation +#if __cplusplus < 201103L + _Rb_tree() { } +#else + _Rb_tree() = default; +#endif + + _Rb_tree(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_impl(__comp, _Node_allocator(__a)) { } + + _Rb_tree(const _Rb_tree& __x) + : _M_impl(__x._M_impl) + { + if (__x._M_root() != 0) + _M_root() = _M_copy(__x); + } + +#if __cplusplus >= 201103L + _Rb_tree(const allocator_type& __a) + : _M_impl(_Node_allocator(__a)) + { } + + _Rb_tree(const _Rb_tree& __x, const allocator_type& __a) + : _M_impl(__x._M_impl._M_key_compare, _Node_allocator(__a)) + { + if (__x._M_root() != nullptr) + _M_root() = _M_copy(__x); + } + + _Rb_tree(_Rb_tree&&) = default; + + _Rb_tree(_Rb_tree&& __x, const allocator_type& __a) + : _Rb_tree(std::move(__x), _Node_allocator(__a)) + { } + + private: + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type) + noexcept(is_nothrow_default_constructible<_Compare>::value) + : _M_impl(std::move(__x._M_impl), std::move(__a)) + { } + + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type) + : _M_impl(__x._M_impl._M_key_compare, std::move(__a)) + { + if (__x._M_root() != nullptr) + _M_move_data(__x, false_type{}); + } + + public: + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a) + noexcept( noexcept( + _Rb_tree(std::declval<_Rb_tree&&>(), std::declval<_Node_allocator&&>(), + std::declval())) ) + : _Rb_tree(std::move(__x), std::move(__a), + typename _Alloc_traits::is_always_equal{}) + { } +#endif + + ~_Rb_tree() _GLIBCXX_NOEXCEPT + { _M_erase(_M_begin()); } + + _Rb_tree& + operator=(const _Rb_tree& __x); + + // Accessors. + _Compare + key_comp() const + { return _M_impl._M_key_compare; } + + iterator + begin() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_header._M_left); } + + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_header._M_left); } + + iterator + end() _GLIBCXX_NOEXCEPT + { return iterator(&this->_M_impl._M_header); } + + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return const_iterator(&this->_M_impl._M_header); } + + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(begin()); } + + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_impl._M_node_count == 0; } + + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_impl._M_node_count; } + + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _Alloc_traits::max_size(_M_get_Node_allocator()); } + + void + swap(_Rb_tree& __t) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value); + + // Insert/erase. +#if __cplusplus >= 201103L + template + pair + _M_insert_unique(_Arg&& __x); + + template + iterator + _M_insert_equal(_Arg&& __x); + + template + iterator + _M_insert_unique_(const_iterator __pos, _Arg&& __x, _NodeGen&); + + template + iterator + _M_insert_unique_(const_iterator __pos, _Arg&& __x) + { + _Alloc_node __an(*this); + return _M_insert_unique_(__pos, std::forward<_Arg>(__x), __an); + } + + template + iterator + _M_insert_equal_(const_iterator __pos, _Arg&& __x, _NodeGen&); + + template + iterator + _M_insert_equal_(const_iterator __pos, _Arg&& __x) + { + _Alloc_node __an(*this); + return _M_insert_equal_(__pos, std::forward<_Arg>(__x), __an); + } + + template + pair + _M_emplace_unique(_Args&&... __args); + + template + iterator + _M_emplace_equal(_Args&&... __args); + + template + iterator + _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args); + + template + iterator + _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args); + + template + using __same_value_type + = is_same::value_type>; + + template + __enable_if_t<__same_value_type<_InputIterator>::value> + _M_insert_range_unique(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_insert_unique_(end(), *__first, __an); + } + + template + __enable_if_t::value> + _M_insert_range_unique(_InputIterator __first, _InputIterator __last) + { + for (; __first != __last; ++__first) + _M_emplace_unique(*__first); + } + + template + __enable_if_t<__same_value_type<_InputIterator>::value> + _M_insert_range_equal(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_insert_equal_(end(), *__first, __an); + } + + template + __enable_if_t::value> + _M_insert_range_equal(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_emplace_equal(*__first); + } +#else + pair + _M_insert_unique(const value_type& __x); + + iterator + _M_insert_equal(const value_type& __x); + + template + iterator + _M_insert_unique_(const_iterator __pos, const value_type& __x, + _NodeGen&); + + iterator + _M_insert_unique_(const_iterator __pos, const value_type& __x) + { + _Alloc_node __an(*this); + return _M_insert_unique_(__pos, __x, __an); + } + + template + iterator + _M_insert_equal_(const_iterator __pos, const value_type& __x, + _NodeGen&); + iterator + _M_insert_equal_(const_iterator __pos, const value_type& __x) + { + _Alloc_node __an(*this); + return _M_insert_equal_(__pos, __x, __an); + } + + template + void + _M_insert_range_unique(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_insert_unique_(end(), *__first, __an); + } + + template + void + _M_insert_range_equal(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_insert_equal_(end(), *__first, __an); + } +#endif + + private: + void + _M_erase_aux(const_iterator __position); + + void + _M_erase_aux(const_iterator __first, const_iterator __last); + + public: +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __position) + { + __glibcxx_assert(__position != end()); + const_iterator __result = __position; + ++__result; + _M_erase_aux(__position); + return __result._M_const_cast(); + } + + // LWG 2059. + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(iterator __position) + { + __glibcxx_assert(__position != end()); + iterator __result = __position; + ++__result; + _M_erase_aux(__position); + return __result; + } +#else + void + erase(iterator __position) + { + __glibcxx_assert(__position != end()); + _M_erase_aux(__position); + } + + void + erase(const_iterator __position) + { + __glibcxx_assert(__position != end()); + _M_erase_aux(__position); + } +#endif + + size_type + erase(const key_type& __x); + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __first, const_iterator __last) + { + _M_erase_aux(__first, __last); + return __last._M_const_cast(); + } +#else + void + erase(iterator __first, iterator __last) + { _M_erase_aux(__first, __last); } + + void + erase(const_iterator __first, const_iterator __last) + { _M_erase_aux(__first, __last); } +#endif + + void + clear() _GLIBCXX_NOEXCEPT + { + _M_erase(_M_begin()); + _M_impl._M_reset(); + } + + // Set operations. + iterator + find(const key_type& __k); + + const_iterator + find(const key_type& __k) const; + + size_type + count(const key_type& __k) const; + + iterator + lower_bound(const key_type& __k) + { return _M_lower_bound(_M_begin(), _M_end(), __k); } + + const_iterator + lower_bound(const key_type& __k) const + { return _M_lower_bound(_M_begin(), _M_end(), __k); } + + iterator + upper_bound(const key_type& __k) + { return _M_upper_bound(_M_begin(), _M_end(), __k); } + + const_iterator + upper_bound(const key_type& __k) const + { return _M_upper_bound(_M_begin(), _M_end(), __k); } + + pair + equal_range(const key_type& __k); + + pair + equal_range(const key_type& __k) const; + +#if __cplusplus >= 201402L + template> + iterator + _M_find_tr(const _Kt& __k) + { + const _Rb_tree* __const_this = this; + return __const_this->_M_find_tr(__k)._M_const_cast(); + } + + template> + const_iterator + _M_find_tr(const _Kt& __k) const + { + auto __j = _M_lower_bound_tr(__k); + if (__j != end() && _M_impl._M_key_compare(__k, _S_key(__j._M_node))) + __j = end(); + return __j; + } + + template> + size_type + _M_count_tr(const _Kt& __k) const + { + auto __p = _M_equal_range_tr(__k); + return std::distance(__p.first, __p.second); + } + + template> + iterator + _M_lower_bound_tr(const _Kt& __k) + { + const _Rb_tree* __const_this = this; + return __const_this->_M_lower_bound_tr(__k)._M_const_cast(); + } + + template> + const_iterator + _M_lower_bound_tr(const _Kt& __k) const + { + auto __x = _M_begin(); + auto __y = _M_end(); + while (__x != 0) + if (!_M_impl._M_key_compare(_S_key(__x), __k)) + { + __y = __x; + __x = _S_left(__x); + } + else + __x = _S_right(__x); + return const_iterator(__y); + } + + template> + iterator + _M_upper_bound_tr(const _Kt& __k) + { + const _Rb_tree* __const_this = this; + return __const_this->_M_upper_bound_tr(__k)._M_const_cast(); + } + + template> + const_iterator + _M_upper_bound_tr(const _Kt& __k) const + { + auto __x = _M_begin(); + auto __y = _M_end(); + while (__x != 0) + if (_M_impl._M_key_compare(__k, _S_key(__x))) + { + __y = __x; + __x = _S_left(__x); + } + else + __x = _S_right(__x); + return const_iterator(__y); + } + + template> + pair + _M_equal_range_tr(const _Kt& __k) + { + const _Rb_tree* __const_this = this; + auto __ret = __const_this->_M_equal_range_tr(__k); + return { __ret.first._M_const_cast(), __ret.second._M_const_cast() }; + } + + template> + pair + _M_equal_range_tr(const _Kt& __k) const + { + auto __low = _M_lower_bound_tr(__k); + auto __high = __low; + auto& __cmp = _M_impl._M_key_compare; + while (__high != end() && !__cmp(__k, _S_key(__high._M_node))) + ++__high; + return { __low, __high }; + } +#endif + + // Debugging. + bool + __rb_verify() const; + +#if __cplusplus >= 201103L + _Rb_tree& + operator=(_Rb_tree&&) + noexcept(_Alloc_traits::_S_nothrow_move() + && is_nothrow_move_assignable<_Compare>::value); + + template + void + _M_assign_unique(_Iterator, _Iterator); + + template + void + _M_assign_equal(_Iterator, _Iterator); + + private: + // Move elements from container with equal allocator. + void + _M_move_data(_Rb_tree& __x, true_type) + { _M_impl._M_move_data(__x._M_impl); } + + // Move elements from container with possibly non-equal allocator, + // which might result in a copy not a move. + void + _M_move_data(_Rb_tree&, false_type); + + // Move assignment from container with equal allocator. + void + _M_move_assign(_Rb_tree&, true_type); + + // Move assignment from container with possibly non-equal allocator, + // which might result in a copy not a move. + void + _M_move_assign(_Rb_tree&, false_type); +#endif + +#if __cplusplus > 201402L + public: + /// Re-insert an extracted node. + insert_return_type + _M_reinsert_node_unique(node_type&& __nh) + { + insert_return_type __ret; + if (__nh.empty()) + __ret.position = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + + auto __res = _M_get_insert_unique_pos(__nh._M_key()); + if (__res.second) + { + __ret.position + = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + __nh._M_ptr = nullptr; + __ret.inserted = true; + } + else + { + __ret.node = std::move(__nh); + __ret.position = iterator(__res.first); + __ret.inserted = false; + } + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_equal(node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_equal_pos(__nh._M_key()); + if (__res.second) + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + else + __ret = _M_insert_equal_lower_node(__nh._M_ptr); + __nh._M_ptr = nullptr; + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_hint_unique(const_iterator __hint, node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_hint_unique_pos(__hint, __nh._M_key()); + if (__res.second) + { + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + __nh._M_ptr = nullptr; + } + else + __ret = iterator(__res.first); + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_hint_equal(const_iterator __hint, node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_hint_equal_pos(__hint, __nh._M_key()); + if (__res.second) + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + else + __ret = _M_insert_equal_lower_node(__nh._M_ptr); + __nh._M_ptr = nullptr; + } + return __ret; + } + + /// Extract a node. + node_type + extract(const_iterator __pos) + { + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_const_cast()._M_node, _M_impl._M_header); + --_M_impl._M_node_count; + return { static_cast<_Link_type>(__ptr), _M_get_Node_allocator() }; + } + + /// Extract a node. + node_type + extract(const key_type& __k) + { + node_type __nh; + auto __pos = find(__k); + if (__pos != end()) + __nh = extract(const_iterator(__pos)); + return __nh; + } + + template + using _Compatible_tree + = _Rb_tree<_Key, _Val, _KeyOfValue, _Compare2, _Alloc>; + + template + friend class _Rb_tree_merge_helper; + + /// Merge from a compatible container into one with unique keys. + template + void + _M_merge_unique(_Compatible_tree<_Compare2>& __src) noexcept + { + using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>; + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + auto __res = _M_get_insert_unique_pos(_KeyOfValue()(*__pos)); + if (__res.second) + { + auto& __src_impl = _Merge_helper::_S_get_impl(__src); + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_node, __src_impl._M_header); + --__src_impl._M_node_count; + _M_insert_node(__res.first, __res.second, + static_cast<_Link_type>(__ptr)); + } + } + } + + /// Merge from a compatible container into one with equivalent keys. + template + void + _M_merge_equal(_Compatible_tree<_Compare2>& __src) noexcept + { + using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>; + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + auto __res = _M_get_insert_equal_pos(_KeyOfValue()(*__pos)); + if (__res.second) + { + auto& __src_impl = _Merge_helper::_S_get_impl(__src); + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_node, __src_impl._M_header); + --__src_impl._M_node_count; + _M_insert_node(__res.first, __res.second, + static_cast<_Link_type>(__ptr)); + } + } + } +#endif // C++17 + + friend bool + operator==(const _Rb_tree& __x, const _Rb_tree& __y) + { + return __x.size() == __y.size() + && std::equal(__x.begin(), __x.end(), __y.begin()); + } + +#if __cpp_lib_three_way_comparison + friend auto + operator<=>(const _Rb_tree& __x, const _Rb_tree& __y) + { + if constexpr (requires { typename __detail::__synth3way_t<_Val>; }) + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + friend bool + operator<(const _Rb_tree& __x, const _Rb_tree& __y) + { + return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); + } + + friend bool _GLIBCXX_DEPRECATED + operator!=(const _Rb_tree& __x, const _Rb_tree& __y) + { return !(__x == __y); } + + friend bool _GLIBCXX_DEPRECATED + operator>(const _Rb_tree& __x, const _Rb_tree& __y) + { return __y < __x; } + + friend bool _GLIBCXX_DEPRECATED + operator<=(const _Rb_tree& __x, const _Rb_tree& __y) + { return !(__y < __x); } + + friend bool _GLIBCXX_DEPRECATED + operator>=(const _Rb_tree& __x, const _Rb_tree& __y) + { return !(__x < __y); } +#endif + }; + + template + inline void + swap(_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x, + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y) + { __x.swap(__y); } + +#if __cplusplus >= 201103L + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_move_data(_Rb_tree& __x, false_type) + { + if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) + _M_move_data(__x, true_type()); + else + { + _Alloc_node __an(*this); + auto __lbd = + [&__an](const value_type& __cval) + { + auto& __val = const_cast(__cval); + return __an(std::move_if_noexcept(__val)); + }; + _M_root() = _M_copy(__x, __lbd); + } + } + + template + inline void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_move_assign(_Rb_tree& __x, true_type) + { + clear(); + if (__x._M_root() != nullptr) + _M_move_data(__x, true_type()); + std::__alloc_on_move(_M_get_Node_allocator(), + __x._M_get_Node_allocator()); + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_move_assign(_Rb_tree& __x, false_type) + { + if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) + return _M_move_assign(__x, true_type{}); + + // Try to move each node reusing existing nodes and copying __x nodes + // structure. + _Reuse_or_alloc_node __roan(*this); + _M_impl._M_reset(); + if (__x._M_root() != nullptr) + { + auto __lbd = + [&__roan](const value_type& __cval) + { + auto& __val = const_cast(__cval); + return __roan(std::move(__val)); + }; + _M_root() = _M_copy(__x, __lbd); + __x.clear(); + } + } + + template + inline _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + operator=(_Rb_tree&& __x) + noexcept(_Alloc_traits::_S_nothrow_move() + && is_nothrow_move_assignable<_Compare>::value) + { + _M_impl._M_key_compare = std::move(__x._M_impl._M_key_compare); + _M_move_assign(__x, __bool_constant<_Alloc_traits::_S_nothrow_move()>()); + return *this; + } + + template + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_assign_unique(_Iterator __first, _Iterator __last) + { + _Reuse_or_alloc_node __roan(*this); + _M_impl._M_reset(); + for (; __first != __last; ++__first) + _M_insert_unique_(end(), *__first, __roan); + } + + template + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_assign_equal(_Iterator __first, _Iterator __last) + { + _Reuse_or_alloc_node __roan(*this); + _M_impl._M_reset(); + for (; __first != __last; ++__first) + _M_insert_equal_(end(), *__first, __roan); + } +#endif + + template + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + operator=(const _Rb_tree& __x) + { + if (this != &__x) + { + // Note that _Key may be a constant type. +#if __cplusplus >= 201103L + if (_Alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_get_Node_allocator(); + auto& __that_alloc = __x._M_get_Node_allocator(); + if (!_Alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // Replacement allocator cannot free existing storage, we need + // to erase nodes first. + clear(); + std::__alloc_on_copy(__this_alloc, __that_alloc); + } + } +#endif + + _Reuse_or_alloc_node __roan(*this); + _M_impl._M_reset(); + _M_impl._M_key_compare = __x._M_impl._M_key_compare; + if (__x._M_root() != 0) + _M_root() = _M_copy(__x, __roan); + } + + return *this; + } + + template +#if __cplusplus >= 201103L + template +#else + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_(_Base_ptr __x, _Base_ptr __p, +#if __cplusplus >= 201103L + _Arg&& __v, +#else + const _Val& __v, +#endif + _NodeGen& __node_gen) + { + bool __insert_left = (__x != 0 || __p == _M_end() + || _M_impl._M_key_compare(_KeyOfValue()(__v), + _S_key(__p))); + + _Link_type __z = __node_gen(_GLIBCXX_FORWARD(_Arg, __v)); + + _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, + this->_M_impl._M_header); + ++_M_impl._M_node_count; + return iterator(__z); + } + + template +#if __cplusplus >= 201103L + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: +#if __cplusplus >= 201103L + _M_insert_lower(_Base_ptr __p, _Arg&& __v) +#else + _M_insert_lower(_Base_ptr __p, const _Val& __v) +#endif + { + bool __insert_left = (__p == _M_end() + || !_M_impl._M_key_compare(_S_key(__p), + _KeyOfValue()(__v))); + + _Link_type __z = _M_create_node(_GLIBCXX_FORWARD(_Arg, __v)); + + _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, + this->_M_impl._M_header); + ++_M_impl._M_node_count; + return iterator(__z); + } + + template +#if __cplusplus >= 201103L + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: +#if __cplusplus >= 201103L + _M_insert_equal_lower(_Arg&& __v) +#else + _M_insert_equal_lower(const _Val& __v) +#endif + { + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + while (__x != 0) + { + __y = __x; + __x = !_M_impl._M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ? + _S_left(__x) : _S_right(__x); + } + return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v)); + } + + template + template + typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Link_type + _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>:: + _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen& __node_gen) + { + // Structural copy. __x and __p must be non-null. + _Link_type __top = _M_clone_node(__x, __node_gen); + __top->_M_parent = __p; + + __try + { + if (__x->_M_right) + __top->_M_right = _M_copy(_S_right(__x), __top, __node_gen); + __p = __top; + __x = _S_left(__x); + + while (__x != 0) + { + _Link_type __y = _M_clone_node(__x, __node_gen); + __p->_M_left = __y; + __y->_M_parent = __p; + if (__x->_M_right) + __y->_M_right = _M_copy(_S_right(__x), __y, __node_gen); + __p = __y; + __x = _S_left(__x); + } + } + __catch(...) + { + _M_erase(__top); + __throw_exception_again; + } + return __top; + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_erase(_Link_type __x) + { + // Erase without rebalancing. + while (__x != 0) + { + _M_erase(_S_right(__x)); + _Link_type __y = _S_left(__x); + _M_drop_node(__x); + __x = __y; + } + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_lower_bound(_Link_type __x, _Base_ptr __y, + const _Key& __k) + { + while (__x != 0) + if (!_M_impl._M_key_compare(_S_key(__x), __k)) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + return iterator(__y); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::const_iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y, + const _Key& __k) const + { + while (__x != 0) + if (!_M_impl._M_key_compare(_S_key(__x), __k)) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + return const_iterator(__y); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_upper_bound(_Link_type __x, _Base_ptr __y, + const _Key& __k) + { + while (__x != 0) + if (_M_impl._M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + return iterator(__y); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::const_iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y, + const _Key& __k) const + { + while (__x != 0) + if (_M_impl._M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + return const_iterator(__y); + } + + template + pair::iterator, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + equal_range(const _Key& __k) + { + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + while (__x != 0) + { + if (_M_impl._M_key_compare(_S_key(__x), __k)) + __x = _S_right(__x); + else if (_M_impl._M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + { + _Link_type __xu(__x); + _Base_ptr __yu(__y); + __y = __x, __x = _S_left(__x); + __xu = _S_right(__xu); + return pair(_M_lower_bound(__x, __y, __k), + _M_upper_bound(__xu, __yu, __k)); + } + } + return pair(iterator(__y), + iterator(__y)); + } + + template + pair::const_iterator, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::const_iterator> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + equal_range(const _Key& __k) const + { + _Const_Link_type __x = _M_begin(); + _Const_Base_ptr __y = _M_end(); + while (__x != 0) + { + if (_M_impl._M_key_compare(_S_key(__x), __k)) + __x = _S_right(__x); + else if (_M_impl._M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + { + _Const_Link_type __xu(__x); + _Const_Base_ptr __yu(__y); + __y = __x, __x = _S_left(__x); + __xu = _S_right(__xu); + return pair(_M_lower_bound(__x, __y, __k), + _M_upper_bound(__xu, __yu, __k)); + } + } + return pair(const_iterator(__y), + const_iterator(__y)); + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + swap(_Rb_tree& __t) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { + if (_M_root() == 0) + { + if (__t._M_root() != 0) + _M_impl._M_move_data(__t._M_impl); + } + else if (__t._M_root() == 0) + __t._M_impl._M_move_data(_M_impl); + else + { + std::swap(_M_root(),__t._M_root()); + std::swap(_M_leftmost(),__t._M_leftmost()); + std::swap(_M_rightmost(),__t._M_rightmost()); + + _M_root()->_M_parent = _M_end(); + __t._M_root()->_M_parent = __t._M_end(); + std::swap(this->_M_impl._M_node_count, __t._M_impl._M_node_count); + } + // No need to swap header's color as it does not change. + std::swap(this->_M_impl._M_key_compare, __t._M_impl._M_key_compare); + + _Alloc_traits::_S_on_swap(_M_get_Node_allocator(), + __t._M_get_Node_allocator()); + } + + template + pair::_Base_ptr, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::_Base_ptr> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_get_insert_unique_pos(const key_type& __k) + { + typedef pair<_Base_ptr, _Base_ptr> _Res; + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + bool __comp = true; + while (__x != 0) + { + __y = __x; + __comp = _M_impl._M_key_compare(__k, _S_key(__x)); + __x = __comp ? _S_left(__x) : _S_right(__x); + } + iterator __j = iterator(__y); + if (__comp) + { + if (__j == begin()) + return _Res(__x, __y); + else + --__j; + } + if (_M_impl._M_key_compare(_S_key(__j._M_node), __k)) + return _Res(__x, __y); + return _Res(__j._M_node, 0); + } + + template + pair::_Base_ptr, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::_Base_ptr> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_get_insert_equal_pos(const key_type& __k) + { + typedef pair<_Base_ptr, _Base_ptr> _Res; + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + while (__x != 0) + { + __y = __x; + __x = _M_impl._M_key_compare(__k, _S_key(__x)) ? + _S_left(__x) : _S_right(__x); + } + return _Res(__x, __y); + } + + template +#if __cplusplus >= 201103L + template +#endif + pair::iterator, bool> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: +#if __cplusplus >= 201103L + _M_insert_unique(_Arg&& __v) +#else + _M_insert_unique(const _Val& __v) +#endif + { + typedef pair _Res; + pair<_Base_ptr, _Base_ptr> __res + = _M_get_insert_unique_pos(_KeyOfValue()(__v)); + + if (__res.second) + { + _Alloc_node __an(*this); + return _Res(_M_insert_(__res.first, __res.second, + _GLIBCXX_FORWARD(_Arg, __v), __an), + true); + } + + return _Res(iterator(__res.first), false); + } + + template +#if __cplusplus >= 201103L + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: +#if __cplusplus >= 201103L + _M_insert_equal(_Arg&& __v) +#else + _M_insert_equal(const _Val& __v) +#endif + { + pair<_Base_ptr, _Base_ptr> __res + = _M_get_insert_equal_pos(_KeyOfValue()(__v)); + _Alloc_node __an(*this); + return _M_insert_(__res.first, __res.second, + _GLIBCXX_FORWARD(_Arg, __v), __an); + } + + template + pair::_Base_ptr, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::_Base_ptr> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_get_insert_hint_unique_pos(const_iterator __position, + const key_type& __k) + { + iterator __pos = __position._M_const_cast(); + typedef pair<_Base_ptr, _Base_ptr> _Res; + + // end() + if (__pos._M_node == _M_end()) + { + if (size() > 0 + && _M_impl._M_key_compare(_S_key(_M_rightmost()), __k)) + return _Res(0, _M_rightmost()); + else + return _M_get_insert_unique_pos(__k); + } + else if (_M_impl._M_key_compare(__k, _S_key(__pos._M_node))) + { + // First, try before... + iterator __before = __pos; + if (__pos._M_node == _M_leftmost()) // begin() + return _Res(_M_leftmost(), _M_leftmost()); + else if (_M_impl._M_key_compare(_S_key((--__before)._M_node), __k)) + { + if (_S_right(__before._M_node) == 0) + return _Res(0, __before._M_node); + else + return _Res(__pos._M_node, __pos._M_node); + } + else + return _M_get_insert_unique_pos(__k); + } + else if (_M_impl._M_key_compare(_S_key(__pos._M_node), __k)) + { + // ... then try after. + iterator __after = __pos; + if (__pos._M_node == _M_rightmost()) + return _Res(0, _M_rightmost()); + else if (_M_impl._M_key_compare(__k, _S_key((++__after)._M_node))) + { + if (_S_right(__pos._M_node) == 0) + return _Res(0, __pos._M_node); + else + return _Res(__after._M_node, __after._M_node); + } + else + return _M_get_insert_unique_pos(__k); + } + else + // Equivalent keys. + return _Res(__pos._M_node, 0); + } + + template +#if __cplusplus >= 201103L + template +#else + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_unique_(const_iterator __position, +#if __cplusplus >= 201103L + _Arg&& __v, +#else + const _Val& __v, +#endif + _NodeGen& __node_gen) + { + pair<_Base_ptr, _Base_ptr> __res + = _M_get_insert_hint_unique_pos(__position, _KeyOfValue()(__v)); + + if (__res.second) + return _M_insert_(__res.first, __res.second, + _GLIBCXX_FORWARD(_Arg, __v), + __node_gen); + return iterator(__res.first); + } + + template + pair::_Base_ptr, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::_Base_ptr> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_get_insert_hint_equal_pos(const_iterator __position, const key_type& __k) + { + iterator __pos = __position._M_const_cast(); + typedef pair<_Base_ptr, _Base_ptr> _Res; + + // end() + if (__pos._M_node == _M_end()) + { + if (size() > 0 + && !_M_impl._M_key_compare(__k, _S_key(_M_rightmost()))) + return _Res(0, _M_rightmost()); + else + return _M_get_insert_equal_pos(__k); + } + else if (!_M_impl._M_key_compare(_S_key(__pos._M_node), __k)) + { + // First, try before... + iterator __before = __pos; + if (__pos._M_node == _M_leftmost()) // begin() + return _Res(_M_leftmost(), _M_leftmost()); + else if (!_M_impl._M_key_compare(__k, _S_key((--__before)._M_node))) + { + if (_S_right(__before._M_node) == 0) + return _Res(0, __before._M_node); + else + return _Res(__pos._M_node, __pos._M_node); + } + else + return _M_get_insert_equal_pos(__k); + } + else + { + // ... then try after. + iterator __after = __pos; + if (__pos._M_node == _M_rightmost()) + return _Res(0, _M_rightmost()); + else if (!_M_impl._M_key_compare(_S_key((++__after)._M_node), __k)) + { + if (_S_right(__pos._M_node) == 0) + return _Res(0, __pos._M_node); + else + return _Res(__after._M_node, __after._M_node); + } + else + return _Res(0, 0); + } + } + + template +#if __cplusplus >= 201103L + template +#else + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_equal_(const_iterator __position, +#if __cplusplus >= 201103L + _Arg&& __v, +#else + const _Val& __v, +#endif + _NodeGen& __node_gen) + { + pair<_Base_ptr, _Base_ptr> __res + = _M_get_insert_hint_equal_pos(__position, _KeyOfValue()(__v)); + + if (__res.second) + return _M_insert_(__res.first, __res.second, + _GLIBCXX_FORWARD(_Arg, __v), + __node_gen); + + return _M_insert_equal_lower(_GLIBCXX_FORWARD(_Arg, __v)); + } + +#if __cplusplus >= 201103L + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_node(_Base_ptr __x, _Base_ptr __p, _Link_type __z) + { + bool __insert_left = (__x != 0 || __p == _M_end() + || _M_impl._M_key_compare(_S_key(__z), + _S_key(__p))); + + _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, + this->_M_impl._M_header); + ++_M_impl._M_node_count; + return iterator(__z); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_lower_node(_Base_ptr __p, _Link_type __z) + { + bool __insert_left = (__p == _M_end() + || !_M_impl._M_key_compare(_S_key(__p), + _S_key(__z))); + + _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, + this->_M_impl._M_header); + ++_M_impl._M_node_count; + return iterator(__z); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_equal_lower_node(_Link_type __z) + { + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + while (__x != 0) + { + __y = __x; + __x = !_M_impl._M_key_compare(_S_key(__x), _S_key(__z)) ? + _S_left(__x) : _S_right(__x); + } + return _M_insert_lower_node(__y, __z); + } + + template + template + pair::iterator, bool> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_emplace_unique(_Args&&... __args) + { + _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); + + __try + { + typedef pair _Res; + auto __res = _M_get_insert_unique_pos(_S_key(__z)); + if (__res.second) + return _Res(_M_insert_node(__res.first, __res.second, __z), true); + + _M_drop_node(__z); + return _Res(iterator(__res.first), false); + } + __catch(...) + { + _M_drop_node(__z); + __throw_exception_again; + } + } + + template + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_emplace_equal(_Args&&... __args) + { + _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); + + __try + { + auto __res = _M_get_insert_equal_pos(_S_key(__z)); + return _M_insert_node(__res.first, __res.second, __z); + } + __catch(...) + { + _M_drop_node(__z); + __throw_exception_again; + } + } + + template + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args) + { + _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); + + __try + { + auto __res = _M_get_insert_hint_unique_pos(__pos, _S_key(__z)); + + if (__res.second) + return _M_insert_node(__res.first, __res.second, __z); + + _M_drop_node(__z); + return iterator(__res.first); + } + __catch(...) + { + _M_drop_node(__z); + __throw_exception_again; + } + } + + template + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args) + { + _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); + + __try + { + auto __res = _M_get_insert_hint_equal_pos(__pos, _S_key(__z)); + + if (__res.second) + return _M_insert_node(__res.first, __res.second, __z); + + return _M_insert_equal_lower_node(__z); + } + __catch(...) + { + _M_drop_node(__z); + __throw_exception_again; + } + } +#endif + + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_erase_aux(const_iterator __position) + { + _Link_type __y = + static_cast<_Link_type>(_Rb_tree_rebalance_for_erase + (const_cast<_Base_ptr>(__position._M_node), + this->_M_impl._M_header)); + _M_drop_node(__y); + --_M_impl._M_node_count; + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_erase_aux(const_iterator __first, const_iterator __last) + { + if (__first == begin() && __last == end()) + clear(); + else + while (__first != __last) + _M_erase_aux(__first++); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + erase(const _Key& __x) + { + pair __p = equal_range(__x); + const size_type __old_size = size(); + _M_erase_aux(__p.first, __p.second); + return __old_size - size(); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + find(const _Key& __k) + { + iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k); + return (__j == end() + || _M_impl._M_key_compare(__k, + _S_key(__j._M_node))) ? end() : __j; + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::const_iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + find(const _Key& __k) const + { + const_iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k); + return (__j == end() + || _M_impl._M_key_compare(__k, + _S_key(__j._M_node))) ? end() : __j; + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + count(const _Key& __k) const + { + pair __p = equal_range(__k); + const size_type __n = std::distance(__p.first, __p.second); + return __n; + } + + _GLIBCXX_PURE unsigned int + _Rb_tree_black_count(const _Rb_tree_node_base* __node, + const _Rb_tree_node_base* __root) throw (); + + template + bool + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const + { + if (_M_impl._M_node_count == 0 || begin() == end()) + return _M_impl._M_node_count == 0 && begin() == end() + && this->_M_impl._M_header._M_left == _M_end() + && this->_M_impl._M_header._M_right == _M_end(); + + unsigned int __len = _Rb_tree_black_count(_M_leftmost(), _M_root()); + for (const_iterator __it = begin(); __it != end(); ++__it) + { + _Const_Link_type __x = static_cast<_Const_Link_type>(__it._M_node); + _Const_Link_type __L = _S_left(__x); + _Const_Link_type __R = _S_right(__x); + + if (__x->_M_color == _S_red) + if ((__L && __L->_M_color == _S_red) + || (__R && __R->_M_color == _S_red)) + return false; + + if (__L && _M_impl._M_key_compare(_S_key(__x), _S_key(__L))) + return false; + if (__R && _M_impl._M_key_compare(_S_key(__R), _S_key(__x))) + return false; + + if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len) + return false; + } + + if (_M_leftmost() != _Rb_tree_node_base::_S_minimum(_M_root())) + return false; + if (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root())) + return false; + return true; + } + +#if __cplusplus > 201402L + // Allow access to internals of compatible _Rb_tree specializations. + template + struct _Rb_tree_merge_helper<_Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>; + + static auto& + _S_get_impl(_Rb_tree<_Key, _Val, _Sel, _Cmp2, _Alloc>& __tree) + { return __tree._M_impl; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h b/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h new file mode 100644 index 000000000..3109a8946 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h @@ -0,0 +1,1041 @@ +// Raw memory manipulators -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_uninitialized.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_UNINITIALIZED_H +#define _STL_UNINITIALIZED_H 1 + +#if __cplusplus > 201402L +#include +#endif + +#if __cplusplus >= 201103L +#include +#endif + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @addtogroup memory + * @{ + */ + + /// @cond undocumented + + template + struct __uninitialized_copy + { + template + static _ForwardIterator + __uninit_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + _ForwardIterator __cur = __result; + __try + { + for (; __first != __last; ++__first, (void)++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_copy + { + template + static _ForwardIterator + __uninit_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { return std::copy(__first, __last, __result); } + }; + + /// @endcond + + /** + * @brief Copies the range [first,last) into result. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return __result + (__first - __last) + * + * Like copy(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type + _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType2; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // Trivial types can have deleted copy constructor, but the std::copy + // optimization that uses memmove would happily "copy" them anyway. + static_assert(is_constructible<_ValueType2, decltype(*__first)>::value, + "result type must be constructible from value type of input range"); + + typedef typename iterator_traits<_InputIterator>::reference _RefType1; + typedef typename iterator_traits<_ForwardIterator>::reference _RefType2; + // Trivial types can have deleted assignment, so using std::copy + // would be ill-formed. Require assignability before using std::copy: + const bool __assignable = is_assignable<_RefType2, _RefType1>::value; +#endif + + return std::__uninitialized_copy<__is_trivial(_ValueType1) + && __is_trivial(_ValueType2) + && __assignable>:: + __uninit_copy(__first, __last, __result); + } + + /// @cond undocumented + + template + struct __uninitialized_fill + { + template + static void + __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct(std::__addressof(*__cur), __x); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_fill + { + template + static void + __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { std::fill(__first, __last, __x); } + }; + + /// @endcond + + /** + * @brief Copies the value x into the range [first,last). + * @param __first An input iterator. + * @param __last An input iterator. + * @param __x The source value. + * @return Nothing. + * + * Like fill(), but does not require an initialized output range. + */ + template + inline void + uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // Trivial types can have deleted copy constructor, but the std::fill + // optimization that uses memmove would happily "copy" them anyway. + static_assert(is_constructible<_ValueType, const _Tp&>::value, + "result type must be constructible from input type"); + + // Trivial types can have deleted assignment, so using std::fill + // would be ill-formed. Require assignability before using std::fill: + const bool __assignable = is_copy_assignable<_ValueType>::value; +#endif + + std::__uninitialized_fill<__is_trivial(_ValueType) && __assignable>:: + __uninit_fill(__first, __last, __x); + } + + /// @cond undocumented + + template + struct __uninitialized_fill_n + { + template + static _ForwardIterator + __uninit_fill_n(_ForwardIterator __first, _Size __n, + const _Tp& __x) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct(std::__addressof(*__cur), __x); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_fill_n + { + template + static _ForwardIterator + __uninit_fill_n(_ForwardIterator __first, _Size __n, + const _Tp& __x) + { return std::fill_n(__first, __n, __x); } + }; + + /// @endcond + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 1339. uninitialized_fill_n should return the end of its range + /** + * @brief Copies the value x into the range [first,first+n). + * @param __first An input iterator. + * @param __n The number of copies to make. + * @param __x The source value. + * @return Nothing. + * + * Like fill_n(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // Trivial types can have deleted copy constructor, but the std::fill + // optimization that uses memmove would happily "copy" them anyway. + static_assert(is_constructible<_ValueType, const _Tp&>::value, + "result type must be constructible from input type"); + + // Trivial types can have deleted assignment, so using std::fill + // would be ill-formed. Require assignability before using std::fill: + const bool __assignable = is_copy_assignable<_ValueType>::value; +#endif + return __uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>:: + __uninit_fill_n(__first, __n, __x); + } + + /// @cond undocumented + + // Extensions: versions of uninitialized_copy, uninitialized_fill, + // and uninitialized_fill_n that take an allocator parameter. + // We dispatch back to the standard versions when we're given the + // default allocator. For nondefault allocators we do not use + // any of the POD optimizations. + + template + _ForwardIterator + __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + { + _ForwardIterator __cur = __result; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __first != __last; ++__first, (void)++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, allocator<_Tp>&) + { return std::uninitialized_copy(__first, __last, __result); } + + template + inline _ForwardIterator + __uninitialized_move_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + { + return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), + __result, __alloc); + } + + template + inline _ForwardIterator + __uninitialized_move_if_noexcept_a(_InputIterator __first, + _InputIterator __last, + _ForwardIterator __result, + _Allocator& __alloc) + { + return std::__uninitialized_copy_a + (_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc); + } + + template + void + __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x, _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __cur != __last; ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), __x); + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline void + __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x, allocator<_Tp2>&) + { std::uninitialized_fill(__first, __last, __x); } + + template + _ForwardIterator + __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, + const _Tp& __x, _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __n > 0; --__n, (void) ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), __x); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, + const _Tp& __x, allocator<_Tp2>&) + { return std::uninitialized_fill_n(__first, __n, __x); } + + + // Extensions: __uninitialized_copy_move, __uninitialized_move_copy, + // __uninitialized_fill_move, __uninitialized_move_fill. + // All of these algorithms take a user-supplied allocator, which is used + // for construction and destruction. + + // __uninitialized_copy_move + // Copies [first1, last1) into [result, result + (last1 - first1)), and + // move [first2, last2) into + // [result, result + (last1 - first1) + (last2 - first2)). + template + inline _ForwardIterator + __uninitialized_copy_move(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _ForwardIterator __result, + _Allocator& __alloc) + { + _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1, + __result, + __alloc); + __try + { + return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_move_copy + // Moves [first1, last1) into [result, result + (last1 - first1)), and + // copies [first2, last2) into + // [result, result + (last1 - first1) + (last2 - first2)). + template + inline _ForwardIterator + __uninitialized_move_copy(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _ForwardIterator __result, + _Allocator& __alloc) + { + _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1, + __result, + __alloc); + __try + { + return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_fill_move + // Fills [result, mid) with x, and moves [first, last) into + // [mid, mid + (last - first)). + template + inline _ForwardIterator + __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid, + const _Tp& __x, _InputIterator __first, + _InputIterator __last, _Allocator& __alloc) + { + std::__uninitialized_fill_a(__result, __mid, __x, __alloc); + __try + { + return std::__uninitialized_move_a(__first, __last, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_move_fill + // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and + // fills [first2 + (last1 - first1), last2) with x. + template + inline void + __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, + _ForwardIterator __last2, const _Tp& __x, + _Allocator& __alloc) + { + _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1, + __first2, + __alloc); + __try + { + std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc); + } + __catch(...) + { + std::_Destroy(__first2, __mid2, __alloc); + __throw_exception_again; + } + } + + /// @endcond + +#if __cplusplus >= 201103L + /// @cond undocumented + + // Extensions: __uninitialized_default, __uninitialized_default_n, + // __uninitialized_default_a, __uninitialized_default_n_a. + + template + struct __uninitialized_default_1 + { + template + static void + __uninit_default(_ForwardIterator __first, _ForwardIterator __last) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct(std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_1 + { + template + static void + __uninit_default(_ForwardIterator __first, _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + std::fill(__first, __last, _ValueType()); + } + }; + + template + struct __uninitialized_default_n_1 + { + template + static _ForwardIterator + __uninit_default_n(_ForwardIterator __first, _Size __n) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_n_1 + { + template + static _ForwardIterator + __uninit_default_n(_ForwardIterator __first, _Size __n) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + return std::fill_n(__first, __n, _ValueType()); + } + }; + + // __uninitialized_default + // Fills [first, last) with std::distance(first, last) default + // constructed value_types(s). + template + inline void + __uninitialized_default(_ForwardIterator __first, + _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; + + std::__uninitialized_default_1<__is_trivial(_ValueType) + && __assignable>:: + __uninit_default(__first, __last); + } + + // __uninitialized_default_n + // Fills [first, first + n) with n default constructed value_type(s). + template + inline _ForwardIterator + __uninitialized_default_n(_ForwardIterator __first, _Size __n) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; + + return __uninitialized_default_n_1<__is_trivial(_ValueType) + && __assignable>:: + __uninit_default_n(__first, __n); + } + + + // __uninitialized_default_a + // Fills [first, last) with std::distance(first, last) default + // constructed value_types(s), constructed with the allocator alloc. + template + void + __uninitialized_default_a(_ForwardIterator __first, + _ForwardIterator __last, + _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __cur != __last; ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline void + __uninitialized_default_a(_ForwardIterator __first, + _ForwardIterator __last, + allocator<_Tp>&) + { std::__uninitialized_default(__first, __last); } + + + // __uninitialized_default_n_a + // Fills [first, first + n) with n default constructed value_types(s), + // constructed with the allocator alloc. + template + _ForwardIterator + __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, + _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __n > 0; --__n, (void) ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, + allocator<_Tp>&) + { return std::__uninitialized_default_n(__first, __n); } + + template + struct __uninitialized_default_novalue_1 + { + template + static void + __uninit_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_novalue_1 + { + template + static void + __uninit_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + } + }; + + template + struct __uninitialized_default_novalue_n_1 + { + template + static _ForwardIterator + __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_novalue_n_1 + { + template + static _ForwardIterator + __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) + { return std::next(__first, __n); } + }; + + // __uninitialized_default_novalue + // Fills [first, last) with std::distance(first, last) default-initialized + // value_types(s). + template + inline void + __uninitialized_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + std::__uninitialized_default_novalue_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue(__first, __last); + } + + // __uninitialized_default_n + // Fills [first, first + n) with n default-initialized value_type(s). + template + inline _ForwardIterator + __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + return __uninitialized_default_novalue_n_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue_n(__first, __n); + } + + template + _ForwardIterator + __uninitialized_copy_n(_InputIterator __first, _Size __n, + _ForwardIterator __result, input_iterator_tag) + { + _ForwardIterator __cur = __result; + __try + { + for (; __n > 0; --__n, (void) ++__first, ++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n, + _ForwardIterator __result, + random_access_iterator_tag) + { return std::uninitialized_copy(__first, __first + __n, __result); } + + template + pair<_InputIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result, input_iterator_tag) + { + _ForwardIterator __cur = __result; + __try + { + for (; __n > 0; --__n, (void) ++__first, ++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return {__first, __cur}; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + inline pair<_RandomAccessIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n, + _ForwardIterator __result, + random_access_iterator_tag) + { + auto __second_res = uninitialized_copy(__first, __first + __n, __result); + auto __first_res = std::next(__first, __n); + return {__first_res, __second_res}; + } + + /// @endcond + + /** + * @brief Copies the range [first,first+n) into result. + * @param __first An input iterator. + * @param __n The number of elements to copy. + * @param __result An output iterator. + * @return __result + __n + * + * Like copy_n(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_copy_n(_InputIterator __first, _Size __n, + _ForwardIterator __result) + { return std::__uninitialized_copy_n(__first, __n, __result, + std::__iterator_category(__first)); } + + /// @cond undocumented + template + inline pair<_InputIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result) + { + return + std::__uninitialized_copy_n_pair(__first, __n, __result, + std::__iterator_category(__first)); + } + /// @endcond +#endif + +#if __cplusplus >= 201703L +# define __cpp_lib_raw_memory_algorithms 201606L + + /** + * @brief Default-initializes objects in the range [first,last). + * @param __first A forward iterator. + * @param __last A forward iterator. + */ + template + inline void + uninitialized_default_construct(_ForwardIterator __first, + _ForwardIterator __last) + { + __uninitialized_default_novalue(__first, __last); + } + + /** + * @brief Default-initializes objects in the range [first,first+count). + * @param __first A forward iterator. + * @param __count The number of objects to construct. + * @return __first + __count + */ + template + inline _ForwardIterator + uninitialized_default_construct_n(_ForwardIterator __first, _Size __count) + { + return __uninitialized_default_novalue_n(__first, __count); + } + + /** + * @brief Value-initializes objects in the range [first,last). + * @param __first A forward iterator. + * @param __last A forward iterator. + */ + template + inline void + uninitialized_value_construct(_ForwardIterator __first, + _ForwardIterator __last) + { + return __uninitialized_default(__first, __last); + } + + /** + * @brief Value-initializes objects in the range [first,first+count). + * @param __first A forward iterator. + * @param __count The number of objects to construct. + * @return __result + __count + */ + template + inline _ForwardIterator + uninitialized_value_construct_n(_ForwardIterator __first, _Size __count) + { + return __uninitialized_default_n(__first, __count); + } + + /** + * @brief Move-construct from the range [first,last) into result. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return __result + (__first - __last) + */ + template + inline _ForwardIterator + uninitialized_move(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + return std::uninitialized_copy + (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result); + } + + /** + * @brief Move-construct from the range [first,first+count) into result. + * @param __first An input iterator. + * @param __count The number of objects to initialize. + * @param __result An output iterator. + * @return __result + __count + */ + template + inline pair<_InputIterator, _ForwardIterator> + uninitialized_move_n(_InputIterator __first, _Size __count, + _ForwardIterator __result) + { + auto __res = std::__uninitialized_copy_n_pair + (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + __count, __result); + return {__res.first.base(), __res.second}; + } +#endif // C++17 + +#if __cplusplus >= 201103L + /// @cond undocumented + + template + inline void + __relocate_object_a(_Tp* __restrict __dest, _Up* __restrict __orig, + _Allocator& __alloc) + noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc, + __dest, std::move(*__orig))) + && noexcept(std::allocator_traits<_Allocator>::destroy( + __alloc, std::__addressof(*__orig)))) + { + typedef std::allocator_traits<_Allocator> __traits; + __traits::construct(__alloc, __dest, std::move(*__orig)); + __traits::destroy(__alloc, std::__addressof(*__orig)); + } + + // This class may be specialized for specific types. + // Also known as is_trivially_relocatable. + template + struct __is_bitwise_relocatable + : is_trivial<_Tp> { }; + + template + inline __enable_if_t::value, _Tp*> + __relocate_a_1(_Tp* __first, _Tp* __last, + _Tp* __result, allocator<_Up>&) noexcept + { + ptrdiff_t __count = __last - __first; + if (__count > 0) + __builtin_memmove(__result, __first, __count * sizeof(_Tp)); + return __result + __count; + } + + template + inline _ForwardIterator + __relocate_a_1(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + noexcept(noexcept(std::__relocate_object_a(std::addressof(*__result), + std::addressof(*__first), + __alloc))) + { + typedef typename iterator_traits<_InputIterator>::value_type + _ValueType; + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType2; + static_assert(std::is_same<_ValueType, _ValueType2>::value, + "relocation is only possible for values of the same type"); + _ForwardIterator __cur = __result; + for (; __first != __last; ++__first, (void)++__cur) + std::__relocate_object_a(std::__addressof(*__cur), + std::__addressof(*__first), __alloc); + return __cur; + } + + template + inline _ForwardIterator + __relocate_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + noexcept(noexcept(__relocate_a_1(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result), __alloc))) + { + return __relocate_a_1(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result), __alloc); + } + + /// @endcond +#endif + + // @} group memory + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_UNINITIALIZED_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_vector.h b/resources/sources/avr-libstdcpp/include/bits/stl_vector.h new file mode 100644 index 000000000..d3f1b1fae --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_vector.h @@ -0,0 +1,1985 @@ +// Vector implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_vector.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{vector} + */ + +#ifndef _STL_VECTOR_H +#define _STL_VECTOR_H 1 + +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif +#if __cplusplus > 201703L +# include +#endif + +#include + +#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR +extern "C" void +__sanitizer_annotate_contiguous_container(const void*, const void*, + const void*, const void*); +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /// See bits/stl_deque.h's _Deque_base for an explanation. + template + struct _Vector_base + { + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Tp>::other _Tp_alloc_type; + typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer + pointer; + + struct _Vector_impl_data + { + pointer _M_start; + pointer _M_finish; + pointer _M_end_of_storage; + + _Vector_impl_data() _GLIBCXX_NOEXCEPT + : _M_start(), _M_finish(), _M_end_of_storage() + { } + +#if __cplusplus >= 201103L + _Vector_impl_data(_Vector_impl_data&& __x) noexcept + : _M_start(__x._M_start), _M_finish(__x._M_finish), + _M_end_of_storage(__x._M_end_of_storage) + { __x._M_start = __x._M_finish = __x._M_end_of_storage = pointer(); } +#endif + + void + _M_copy_data(_Vector_impl_data const& __x) _GLIBCXX_NOEXCEPT + { + _M_start = __x._M_start; + _M_finish = __x._M_finish; + _M_end_of_storage = __x._M_end_of_storage; + } + + void + _M_swap_data(_Vector_impl_data& __x) _GLIBCXX_NOEXCEPT + { + // Do not use std::swap(_M_start, __x._M_start), etc as it loses + // information used by TBAA. + _Vector_impl_data __tmp; + __tmp._M_copy_data(*this); + _M_copy_data(__x); + __x._M_copy_data(__tmp); + } + }; + + struct _Vector_impl + : public _Tp_alloc_type, public _Vector_impl_data + { + _Vector_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Tp_alloc_type>::value) + : _Tp_alloc_type() + { } + + _Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT + : _Tp_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + // Not defaulted, to enforce noexcept(true) even when + // !is_nothrow_move_constructible<_Tp_alloc_type>. + _Vector_impl(_Vector_impl&& __x) noexcept + : _Tp_alloc_type(std::move(__x)), _Vector_impl_data(std::move(__x)) + { } + + _Vector_impl(_Tp_alloc_type&& __a) noexcept + : _Tp_alloc_type(std::move(__a)) + { } + + _Vector_impl(_Tp_alloc_type&& __a, _Vector_impl&& __rv) noexcept + : _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv)) + { } +#endif + +#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR + template + struct _Asan + { + typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type> + ::size_type size_type; + + static void _S_shrink(_Vector_impl&, size_type) { } + static void _S_on_dealloc(_Vector_impl&) { } + + typedef _Vector_impl& _Reinit; + + struct _Grow + { + _Grow(_Vector_impl&, size_type) { } + void _M_grew(size_type) { } + }; + }; + + // Enable ASan annotations for memory obtained from std::allocator. + template + struct _Asan > + { + typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type> + ::size_type size_type; + + // Adjust ASan annotation for [_M_start, _M_end_of_storage) to + // mark end of valid region as __curr instead of __prev. + static void + _S_adjust(_Vector_impl& __impl, pointer __prev, pointer __curr) + { + __sanitizer_annotate_contiguous_container(__impl._M_start, + __impl._M_end_of_storage, __prev, __curr); + } + + static void + _S_grow(_Vector_impl& __impl, size_type __n) + { _S_adjust(__impl, __impl._M_finish, __impl._M_finish + __n); } + + static void + _S_shrink(_Vector_impl& __impl, size_type __n) + { _S_adjust(__impl, __impl._M_finish + __n, __impl._M_finish); } + + static void + _S_on_dealloc(_Vector_impl& __impl) + { + if (__impl._M_start) + _S_adjust(__impl, __impl._M_finish, __impl._M_end_of_storage); + } + + // Used on reallocation to tell ASan unused capacity is invalid. + struct _Reinit + { + explicit _Reinit(_Vector_impl& __impl) : _M_impl(__impl) + { + // Mark unused capacity as valid again before deallocating it. + _S_on_dealloc(_M_impl); + } + + ~_Reinit() + { + // Mark unused capacity as invalid after reallocation. + if (_M_impl._M_start) + _S_adjust(_M_impl, _M_impl._M_end_of_storage, + _M_impl._M_finish); + } + + _Vector_impl& _M_impl; + +#if __cplusplus >= 201103L + _Reinit(const _Reinit&) = delete; + _Reinit& operator=(const _Reinit&) = delete; +#endif + }; + + // Tell ASan when unused capacity is initialized to be valid. + struct _Grow + { + _Grow(_Vector_impl& __impl, size_type __n) + : _M_impl(__impl), _M_n(__n) + { _S_grow(_M_impl, __n); } + + ~_Grow() { if (_M_n) _S_shrink(_M_impl, _M_n); } + + void _M_grew(size_type __n) { _M_n -= __n; } + +#if __cplusplus >= 201103L + _Grow(const _Grow&) = delete; + _Grow& operator=(const _Grow&) = delete; +#endif + private: + _Vector_impl& _M_impl; + size_type _M_n; + }; + }; + +#define _GLIBCXX_ASAN_ANNOTATE_REINIT \ + typename _Base::_Vector_impl::template _Asan<>::_Reinit const \ + __attribute__((__unused__)) __reinit_guard(this->_M_impl) +#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) \ + typename _Base::_Vector_impl::template _Asan<>::_Grow \ + __attribute__((__unused__)) __grow_guard(this->_M_impl, (n)) +#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) __grow_guard._M_grew(n) +#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) \ + _Base::_Vector_impl::template _Asan<>::_S_shrink(this->_M_impl, n) +#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC \ + _Base::_Vector_impl::template _Asan<>::_S_on_dealloc(this->_M_impl) +#else // ! (_GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR) +#define _GLIBCXX_ASAN_ANNOTATE_REINIT +#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) +#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) +#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) +#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC +#endif // _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR + }; + + public: + typedef _Alloc allocator_type; + + _Tp_alloc_type& + _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + const _Tp_alloc_type& + _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_get_Tp_allocator()); } + +#if __cplusplus >= 201103L + _Vector_base() = default; +#else + _Vector_base() { } +#endif + + _Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPT + : _M_impl(__a) { } + + // Kept for ABI compatibility. +#if !_GLIBCXX_INLINE_VERSION + _Vector_base(size_t __n) + : _M_impl() + { _M_create_storage(__n); } +#endif + + _Vector_base(size_t __n, const allocator_type& __a) + : _M_impl(__a) + { _M_create_storage(__n); } + +#if __cplusplus >= 201103L + _Vector_base(_Vector_base&&) = default; + + // Kept for ABI compatibility. +# if !_GLIBCXX_INLINE_VERSION + _Vector_base(_Tp_alloc_type&& __a) noexcept + : _M_impl(std::move(__a)) { } + + _Vector_base(_Vector_base&& __x, const allocator_type& __a) + : _M_impl(__a) + { + if (__x.get_allocator() == __a) + this->_M_impl._M_swap_data(__x._M_impl); + else + { + size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start; + _M_create_storage(__n); + } + } +# endif + + _Vector_base(const allocator_type& __a, _Vector_base&& __x) + : _M_impl(_Tp_alloc_type(__a), std::move(__x._M_impl)) + { } +#endif + + ~_Vector_base() _GLIBCXX_NOEXCEPT + { + _M_deallocate(_M_impl._M_start, + _M_impl._M_end_of_storage - _M_impl._M_start); + } + + public: + _Vector_impl _M_impl; + + pointer + _M_allocate(size_t __n) + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; + return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer(); + } + + void + _M_deallocate(pointer __p, size_t __n) + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; + if (__p) + _Tr::deallocate(_M_impl, __p, __n); + } + + protected: + void + _M_create_storage(size_t __n) + { + this->_M_impl._M_start = this->_M_allocate(__n); + this->_M_impl._M_finish = this->_M_impl._M_start; + this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; + } + }; + + /** + * @brief A standard container which offers fixed time access to + * individual elements in any order. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements with the + * %exception of @c push_front and @c pop_front. + * + * In some terminology a %vector can be described as a dynamic + * C-style array, it offers fast and efficient access to individual + * elements in any order and saves the user from worrying about + * memory and size allocation. Subscripting ( @c [] ) access is + * also provided as with C-style arrays. + */ + template > + class vector : protected _Vector_base<_Tp, _Alloc> + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // Concept requirements. + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Tp>::value, + "std::vector must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::vector must have the same value_type as its allocator"); +# endif +#endif + + typedef _Vector_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; + + public: + typedef _Tp value_type; + typedef typename _Base::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + typedef __gnu_cxx::__normal_iterator iterator; + typedef __gnu_cxx::__normal_iterator + const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + private: +#if __cplusplus >= 201103L + static constexpr bool + _S_nothrow_relocate(true_type) + { + return noexcept(std::__relocate_a(std::declval(), + std::declval(), + std::declval(), + std::declval<_Tp_alloc_type&>())); + } + + static constexpr bool + _S_nothrow_relocate(false_type) + { return false; } + + static constexpr bool + _S_use_relocate() + { + // Instantiating std::__relocate_a might cause an error outside the + // immediate context (in __relocate_object_a's noexcept-specifier), + // so only do it if we know the type can be move-inserted into *this. + return _S_nothrow_relocate(__is_move_insertable<_Tp_alloc_type>{}); + } + + static pointer + _S_do_relocate(pointer __first, pointer __last, pointer __result, + _Tp_alloc_type& __alloc, true_type) noexcept + { + return std::__relocate_a(__first, __last, __result, __alloc); + } + + static pointer + _S_do_relocate(pointer, pointer, pointer __result, + _Tp_alloc_type&, false_type) noexcept + { return __result; } + + static pointer + _S_relocate(pointer __first, pointer __last, pointer __result, + _Tp_alloc_type& __alloc) noexcept + { + using __do_it = __bool_constant<_S_use_relocate()>; + return _S_do_relocate(__first, __last, __result, __alloc, __do_it{}); + } +#endif // C++11 + + protected: + using _Base::_M_allocate; + using _Base::_M_deallocate; + using _Base::_M_impl; + using _Base::_M_get_Tp_allocator; + + public: + // [23.2.4.1] construct/copy/destroy + // (assign() and get_allocator() are also listed in this section) + + /** + * @brief Creates a %vector with no elements. + */ +#if __cplusplus >= 201103L + vector() = default; +#else + vector() { } +#endif + + /** + * @brief Creates a %vector with no elements. + * @param __a An allocator object. + */ + explicit + vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT + : _Base(__a) { } + +#if __cplusplus >= 201103L + /** + * @brief Creates a %vector with default constructed elements. + * @param __n The number of elements to initially create. + * @param __a An allocator. + * + * This constructor fills the %vector with @a __n default + * constructed elements. + */ + explicit + vector(size_type __n, const allocator_type& __a = allocator_type()) + : _Base(_S_check_init_len(__n, __a), __a) + { _M_default_initialize(__n); } + + /** + * @brief Creates a %vector with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator. + * + * This constructor fills the %vector with @a __n copies of @a __value. + */ + vector(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) + : _Base(_S_check_init_len(__n, __a), __a) + { _M_fill_initialize(__n, __value); } +#else + /** + * @brief Creates a %vector with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator. + * + * This constructor fills the %vector with @a __n copies of @a __value. + */ + explicit + vector(size_type __n, const value_type& __value = value_type(), + const allocator_type& __a = allocator_type()) + : _Base(_S_check_init_len(__n, __a), __a) + { _M_fill_initialize(__n, __value); } +#endif + + /** + * @brief %Vector copy constructor. + * @param __x A %vector of identical element and allocator types. + * + * All the elements of @a __x are copied, but any unused capacity in + * @a __x will not be copied + * (i.e. capacity() == size() in the new %vector). + * + * The newly-created %vector uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). + */ + vector(const vector& __x) + : _Base(__x.size(), + _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator())) + { + this->_M_impl._M_finish = + std::__uninitialized_copy_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); + } + +#if __cplusplus >= 201103L + /** + * @brief %Vector move constructor. + * + * The newly-created %vector contains the exact contents of the + * moved instance. + * The contents of the moved instance are a valid, but unspecified + * %vector. + */ + vector(vector&&) noexcept = default; + + /// Copy constructor with alternative allocator + vector(const vector& __x, const allocator_type& __a) + : _Base(__x.size(), __a) + { + this->_M_impl._M_finish = + std::__uninitialized_copy_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); + } + + private: + vector(vector&& __rv, const allocator_type& __m, true_type) noexcept + : _Base(__m, std::move(__rv)) + { } + + vector(vector&& __rv, const allocator_type& __m, false_type) + : _Base(__m) + { + if (__rv.get_allocator() == __m) + this->_M_impl._M_swap_data(__rv._M_impl); + else if (!__rv.empty()) + { + this->_M_create_storage(__rv.size()); + this->_M_impl._M_finish = + std::__uninitialized_move_a(__rv.begin(), __rv.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); + __rv.clear(); + } + } + + public: + /// Move constructor with alternative allocator + vector(vector&& __rv, const allocator_type& __m) + noexcept( noexcept( + vector(std::declval(), std::declval(), + std::declval())) ) + : vector(std::move(__rv), __m, typename _Alloc_traits::is_always_equal{}) + { } + + /** + * @brief Builds a %vector from an initializer list. + * @param __l An initializer_list. + * @param __a An allocator. + * + * Create a %vector consisting of copies of the elements in the + * initializer_list @a __l. + * + * This will call the element type's copy constructor N times + * (where N is @a __l.size()) and do no memory reallocation. + */ + vector(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_range_initialize(__l.begin(), __l.end(), + random_access_iterator_tag()); + } +#endif + + /** + * @brief Builds a %vector from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __a An allocator. + * + * Create a %vector consisting of copies of the elements from + * [first,last). + * + * If the iterators are forward, bidirectional, or + * random-access, then this will call the elements' copy + * constructor N times (where N is distance(first,last)) and do + * no memory reallocation. But if only input iterators are + * used, then this will do at most 2N calls to the copy + * constructor, and logN memory reallocations. + */ +#if __cplusplus >= 201103L + template> + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#else + template + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } +#endif + + /** + * The dtor only erases the elements, and note that if the + * elements themselves are pointers, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + ~vector() _GLIBCXX_NOEXCEPT + { + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC; + } + + /** + * @brief %Vector assignment operator. + * @param __x A %vector of identical element and allocator types. + * + * All the elements of @a __x are copied, but any unused capacity in + * @a __x will not be copied. + * + * Whether the allocator is copied depends on the allocator traits. + */ + vector& + operator=(const vector& __x); + +#if __cplusplus >= 201103L + /** + * @brief %Vector move assignment operator. + * @param __x A %vector of identical element and allocator types. + * + * The contents of @a __x are moved into this %vector (without copying, + * if the allocators permit it). + * Afterwards @a __x is a valid, but unspecified %vector. + * + * Whether the allocator is moved depends on the allocator traits. + */ + vector& + operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move()) + { + constexpr bool __move_storage = + _Alloc_traits::_S_propagate_on_move_assign() + || _Alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); + return *this; + } + + /** + * @brief %Vector list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %vector with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %vector and + * that the resulting %vector's size is the same as the number + * of elements assigned. + */ + vector& + operator=(initializer_list __l) + { + this->_M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); + return *this; + } +#endif + + /** + * @brief Assigns a given value to a %vector. + * @param __n Number of elements to be assigned. + * @param __val Value to be assigned. + * + * This function fills a %vector with @a __n copies of the given + * value. Note that the assignment completely changes the + * %vector and that the resulting %vector's size is the same as + * the number of elements assigned. + */ + void + assign(size_type __n, const value_type& __val) + { _M_fill_assign(__n, __val); } + + /** + * @brief Assigns a range to a %vector. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function fills a %vector with copies of the elements in the + * range [__first,__last). + * + * Note that the assignment completely changes the %vector and + * that the resulting %vector's size is the same as the number + * of elements assigned. + */ +#if __cplusplus >= 201103L + template> + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_dispatch(__first, __last, __false_type()); } +#else + template + void + assign(_InputIterator __first, _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Assigns an initializer list to a %vector. + * @param __l An initializer_list. + * + * This function fills a %vector with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %vector and + * that the resulting %vector's size is the same as the number + * of elements assigned. + */ + void + assign(initializer_list __l) + { + this->_M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); + } +#endif + + /// Get a copy of the memory allocation object. + using _Base::get_allocator; + + // iterators + /** + * Returns a read/write iterator that points to the first + * element in the %vector. Iteration is done in ordinary + * element order. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_start); } + + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %vector. Iteration is done in ordinary + * element order. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_start); } + + /** + * Returns a read/write iterator that points one past the last + * element in the %vector. Iteration is done in ordinary + * element order. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_finish); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %vector. Iteration is done in + * ordinary element order. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read/write reverse iterator that points to the + * last element in the %vector. Iteration is done in reverse + * element order. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to the last element in the %vector. Iteration is done in + * reverse element order. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(end()); } + + /** + * Returns a read/write reverse iterator that points to one + * before the first element in the %vector. Iteration is done + * in reverse element order. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(begin()); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to one before the first element in the %vector. Iteration + * is done in reverse element order. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(begin()); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %vector. Iteration is done in ordinary + * element order. + */ + const_iterator + cbegin() const noexcept + { return const_iterator(this->_M_impl._M_start); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %vector. Iteration is done in + * ordinary element order. + */ + const_iterator + cend() const noexcept + { return const_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to the last element in the %vector. Iteration is done in + * reverse element order. + */ + const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to one before the first element in the %vector. Iteration + * is done in reverse element order. + */ + const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } +#endif + + // [23.2.4.2] capacity + /** Returns the number of elements in the %vector. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); } + + /** Returns the size() of the largest possible %vector. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _S_max_size(_M_get_Tp_allocator()); } + +#if __cplusplus >= 201103L + /** + * @brief Resizes the %vector to the specified number of elements. + * @param __new_size Number of elements the %vector should contain. + * + * This function will %resize the %vector to the specified + * number of elements. If the number is smaller than the + * %vector's current size the %vector is truncated, otherwise + * default constructed elements are appended. + */ + void + resize(size_type __new_size) + { + if (__new_size > size()) + _M_default_append(__new_size - size()); + else if (__new_size < size()) + _M_erase_at_end(this->_M_impl._M_start + __new_size); + } + + /** + * @brief Resizes the %vector to the specified number of elements. + * @param __new_size Number of elements the %vector should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %vector to the specified + * number of elements. If the number is smaller than the + * %vector's current size the %vector is truncated, otherwise + * the %vector is extended and new elements are populated with + * given data. + */ + void + resize(size_type __new_size, const value_type& __x) + { + if (__new_size > size()) + _M_fill_insert(end(), __new_size - size(), __x); + else if (__new_size < size()) + _M_erase_at_end(this->_M_impl._M_start + __new_size); + } +#else + /** + * @brief Resizes the %vector to the specified number of elements. + * @param __new_size Number of elements the %vector should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %vector to the specified + * number of elements. If the number is smaller than the + * %vector's current size the %vector is truncated, otherwise + * the %vector is extended and new elements are populated with + * given data. + */ + void + resize(size_type __new_size, value_type __x = value_type()) + { + if (__new_size > size()) + _M_fill_insert(end(), __new_size - size(), __x); + else if (__new_size < size()) + _M_erase_at_end(this->_M_impl._M_start + __new_size); + } +#endif + +#if __cplusplus >= 201103L + /** A non-binding request to reduce capacity() to size(). */ + void + shrink_to_fit() + { _M_shrink_to_fit(); } +#endif + + /** + * Returns the total number of elements that the %vector can + * hold before needing to allocate more memory. + */ + size_type + capacity() const _GLIBCXX_NOEXCEPT + { return size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); } + + /** + * Returns true if the %vector is empty. (Thus begin() would + * equal end().) + */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return begin() == end(); } + + /** + * @brief Attempt to preallocate enough memory for specified number of + * elements. + * @param __n Number of elements required. + * @throw std::length_error If @a n exceeds @c max_size(). + * + * This function attempts to reserve enough memory for the + * %vector to hold the specified number of elements. If the + * number requested is more than max_size(), length_error is + * thrown. + * + * The advantage of this function is that if optimal code is a + * necessity and the user can determine the number of elements + * that will be required, the user can reserve the memory in + * %advance, and thus prevent a possible reallocation of memory + * and copying of %vector data. + */ + void + reserve(size_type __n); + + // element access + /** + * @brief Subscript access to the data contained in the %vector. + * @param __n The index of the element for which data should be + * accessed. + * @return Read/write reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and + * out_of_range lookups are not defined. (For checked lookups + * see at().) + */ + reference + operator[](size_type __n) _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_subscript(__n); + return *(this->_M_impl._M_start + __n); + } + + /** + * @brief Subscript access to the data contained in the %vector. + * @param __n The index of the element for which data should be + * accessed. + * @return Read-only (constant) reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and + * out_of_range lookups are not defined. (For checked lookups + * see at().) + */ + const_reference + operator[](size_type __n) const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_subscript(__n); + return *(this->_M_impl._M_start + __n); + } + + protected: + /// Safety check used only from at(). + void + _M_range_check(size_type __n) const + { + if (__n >= this->size()) + __throw_out_of_range_fmt(__N("vector::_M_range_check: __n " + "(which is %zu) >= this->size() " + "(which is %zu)"), + __n, this->size()); + } + + public: + /** + * @brief Provides access to the data contained in the %vector. + * @param __n The index of the element for which data should be + * accessed. + * @return Read/write reference to data. + * @throw std::out_of_range If @a __n is an invalid index. + * + * This function provides for safer data access. The parameter + * is first checked that it is in the range of the vector. The + * function throws out_of_range if the check fails. + */ + reference + at(size_type __n) + { + _M_range_check(__n); + return (*this)[__n]; + } + + /** + * @brief Provides access to the data contained in the %vector. + * @param __n The index of the element for which data should be + * accessed. + * @return Read-only (constant) reference to data. + * @throw std::out_of_range If @a __n is an invalid index. + * + * This function provides for safer data access. The parameter + * is first checked that it is in the range of the vector. The + * function throws out_of_range if the check fails. + */ + const_reference + at(size_type __n) const + { + _M_range_check(__n); + return (*this)[__n]; + } + + /** + * Returns a read/write reference to the data at the first + * element of the %vector. + */ + reference + front() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *begin(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %vector. + */ + const_reference + front() const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *begin(); + } + + /** + * Returns a read/write reference to the data at the last + * element of the %vector. + */ + reference + back() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *(end() - 1); + } + + /** + * Returns a read-only (constant) reference to the data at the + * last element of the %vector. + */ + const_reference + back() const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *(end() - 1); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + // data access + /** + * Returns a pointer such that [data(), data() + size()) is a valid + * range. For a non-empty %vector, data() == &front(). + */ + _Tp* + data() _GLIBCXX_NOEXCEPT + { return _M_data_ptr(this->_M_impl._M_start); } + + const _Tp* + data() const _GLIBCXX_NOEXCEPT + { return _M_data_ptr(this->_M_impl._M_start); } + + // [23.2.4.3] modifiers + /** + * @brief Add data to the end of the %vector. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the end of the %vector and assigns the given data + * to it. Due to the nature of a %vector this operation can be + * done in constant time if the %vector has preallocated space + * available. + */ + void + push_back(const value_type& __x) + { + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + __x); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + _M_realloc_insert(end(), __x); + } + +#if __cplusplus >= 201103L + void + push_back(value_type&& __x) + { emplace_back(std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args); +#endif + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %vector by one. + * + * Note that no data is returned, and if the last element's + * data is needed, it should be retrieved before pop_back() is + * called. + */ + void + pop_back() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + --this->_M_impl._M_finish; + _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); + _GLIBCXX_ASAN_ANNOTATE_SHRINK(1); + } + +#if __cplusplus >= 201103L + /** + * @brief Inserts an object in %vector before specified iterator. + * @param __position A const_iterator into the %vector. + * @param __args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) before the specified location. + * Note that this kind of operation could be expensive for a %vector + * and if it is frequently used the user should consider using + * std::list. + */ + template + iterator + emplace(const_iterator __position, _Args&&... __args) + { return _M_emplace_aux(__position, std::forward<_Args>(__args)...); } + + /** + * @brief Inserts given value into %vector before specified iterator. + * @param __position A const_iterator into the %vector. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before + * the specified location. Note that this kind of operation + * could be expensive for a %vector and if it is frequently + * used the user should consider using std::list. + */ + iterator + insert(const_iterator __position, const value_type& __x); +#else + /** + * @brief Inserts given value into %vector before specified iterator. + * @param __position An iterator into the %vector. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before + * the specified location. Note that this kind of operation + * could be expensive for a %vector and if it is frequently + * used the user should consider using std::list. + */ + iterator + insert(iterator __position, const value_type& __x); +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts given rvalue into %vector before specified iterator. + * @param __position A const_iterator into the %vector. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given rvalue before + * the specified location. Note that this kind of operation + * could be expensive for a %vector and if it is frequently + * used the user should consider using std::list. + */ + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_insert_rval(__position, std::move(__x)); } + + /** + * @brief Inserts an initializer_list into the %vector. + * @param __position An iterator into the %vector. + * @param __l An initializer_list. + * + * This function will insert copies of the data in the + * initializer_list @a l into the %vector before the location + * specified by @a position. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + iterator + insert(const_iterator __position, initializer_list __l) + { + auto __offset = __position - cbegin(); + _M_range_insert(begin() + __offset, __l.begin(), __l.end(), + std::random_access_iterator_tag()); + return begin() + __offset; + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a number of copies of given data into the %vector. + * @param __position A const_iterator into the %vector. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a specified number of copies of + * the given data before the location specified by @a position. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + iterator + insert(const_iterator __position, size_type __n, const value_type& __x) + { + difference_type __offset = __position - cbegin(); + _M_fill_insert(begin() + __offset, __n, __x); + return begin() + __offset; + } +#else + /** + * @brief Inserts a number of copies of given data into the %vector. + * @param __position An iterator into the %vector. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * + * This function will insert a specified number of copies of + * the given data before the location specified by @a position. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + void + insert(iterator __position, size_type __n, const value_type& __x) + { _M_fill_insert(__position, __n, __x); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a range into the %vector. + * @param __position A const_iterator into the %vector. + * @param __first An input iterator. + * @param __last An input iterator. + * @return An iterator that points to the inserted data. + * + * This function will insert copies of the data in the range + * [__first,__last) into the %vector before the location specified + * by @a pos. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + template> + iterator + insert(const_iterator __position, _InputIterator __first, + _InputIterator __last) + { + difference_type __offset = __position - cbegin(); + _M_insert_dispatch(begin() + __offset, + __first, __last, __false_type()); + return begin() + __offset; + } +#else + /** + * @brief Inserts a range into the %vector. + * @param __position An iterator into the %vector. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function will insert copies of the data in the range + * [__first,__last) into the %vector before the location specified + * by @a pos. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + template + void + insert(iterator __position, _InputIterator __first, + _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_insert_dispatch(__position, __first, __last, _Integral()); + } +#endif + + /** + * @brief Remove element at given position. + * @param __position Iterator pointing to element to be erased. + * @return An iterator pointing to the next element (or end()). + * + * This function will erase the element at the given position and thus + * shorten the %vector by one. + * + * Note This operation could be expensive and if it is + * frequently used the user should consider using std::list. + * The user is also cautioned that this function only erases + * the element, and that if the element is itself a pointer, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) + { return _M_erase(begin() + (__position - cbegin())); } +#else + erase(iterator __position) + { return _M_erase(__position); } +#endif + + /** + * @brief Remove a range of elements. + * @param __first Iterator pointing to the first element to be erased. + * @param __last Iterator pointing to one past the last element to be + * erased. + * @return An iterator pointing to the element pointed to by @a __last + * prior to erasing (or end()). + * + * This function will erase the elements in the range + * [__first,__last) and shorten the %vector accordingly. + * + * Note This operation could be expensive and if it is + * frequently used the user should consider using std::list. + * The user is also cautioned that this function only erases + * the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) + { + const auto __beg = begin(); + const auto __cbeg = cbegin(); + return _M_erase(__beg + (__first - __cbeg), __beg + (__last - __cbeg)); + } +#else + erase(iterator __first, iterator __last) + { return _M_erase(__first, __last); } +#endif + + /** + * @brief Swaps data with another %vector. + * @param __x A %vector of the same element and allocator types. + * + * This exchanges the elements between two vectors in constant time. + * (Three pointers, so it should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(v1,v2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(vector& __x) _GLIBCXX_NOEXCEPT + { +#if __cplusplus >= 201103L + __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value + || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()); +#endif + this->_M_impl._M_swap_data(__x._M_impl); + _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + } + + /** + * Erases all the elements. Note that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_erase_at_end(this->_M_impl._M_start); } + + protected: + /** + * Memory expansion handler. Uses the member allocation function to + * obtain @a n bytes of memory, and then copies [first,last) into it. + */ + template + pointer + _M_allocate_and_copy(size_type __n, + _ForwardIterator __first, _ForwardIterator __last) + { + pointer __result = this->_M_allocate(__n); + __try + { + std::__uninitialized_copy_a(__first, __last, __result, + _M_get_Tp_allocator()); + return __result; + } + __catch(...) + { + _M_deallocate(__result, __n); + __throw_exception_again; + } + } + + + // Internal constructor functions follow. + + // Called by the range constructor to implement [23.1.1]/9 + +#if __cplusplus < 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type) + { + this->_M_impl._M_start = _M_allocate(_S_check_init_len( + static_cast(__n), _M_get_Tp_allocator())); + this->_M_impl._M_end_of_storage = + this->_M_impl._M_start + static_cast(__n); + _M_fill_initialize(static_cast(__n), __value); + } + + // Called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#endif + + // Called by the second initialize_dispatch above + template + void + _M_range_initialize(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + __try { + for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else + push_back(*__first); +#endif + } __catch(...) { + clear(); + __throw_exception_again; + } + } + + // Called by the second initialize_dispatch above + template + void + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __n = std::distance(__first, __last); + this->_M_impl._M_start + = this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator())); + this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; + this->_M_impl._M_finish = + std::__uninitialized_copy_a(__first, __last, + this->_M_impl._M_start, + _M_get_Tp_allocator()); + } + + // Called by the first initialize_dispatch above and by the + // vector(n,value,a) constructor. + void + _M_fill_initialize(size_type __n, const value_type& __value) + { + this->_M_impl._M_finish = + std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value, + _M_get_Tp_allocator()); + } + +#if __cplusplus >= 201103L + // Called by the vector(n) constructor. + void + _M_default_initialize(size_type __n) + { + this->_M_impl._M_finish = + std::__uninitialized_default_n_a(this->_M_impl._M_start, __n, + _M_get_Tp_allocator()); + } +#endif + + // Internal assign functions follow. The *_aux functions do the actual + // assignment work for the range versions. + + // Called by the range assign to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + + // Called by the range assign to implement [23.1.1]/9 + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } + + // Called by the second assign_dispatch above + template + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag); + + // Called by the second assign_dispatch above + template + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag); + + // Called by assign(n,t), and the range assign when it turns out + // to be the same thing. + void + _M_fill_assign(size_type __n, const value_type& __val); + + // Internal insert functions follow. + + // Called by the range insert to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, + __true_type) + { _M_fill_insert(__pos, __n, __val); } + + // Called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, _InputIterator __first, + _InputIterator __last, __false_type) + { + _M_range_insert(__pos, __first, __last, + std::__iterator_category(__first)); + } + + // Called by the second insert_dispatch above + template + void + _M_range_insert(iterator __pos, _InputIterator __first, + _InputIterator __last, std::input_iterator_tag); + + // Called by the second insert_dispatch above + template + void + _M_range_insert(iterator __pos, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag); + + // Called by insert(p,n,x), and the range insert when it turns out to be + // the same thing. + void + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); + +#if __cplusplus >= 201103L + // Called by resize(n). + void + _M_default_append(size_type __n); + + bool + _M_shrink_to_fit(); +#endif + +#if __cplusplus < 201103L + // Called by insert(p,x) + void + _M_insert_aux(iterator __position, const value_type& __x); + + void + _M_realloc_insert(iterator __position, const value_type& __x); +#else + // A value_type object constructed with _Alloc_traits::construct() + // and destroyed with _Alloc_traits::destroy(). + struct _Temporary_value + { + template + explicit + _Temporary_value(vector* __vec, _Args&&... __args) : _M_this(__vec) + { + _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(), + std::forward<_Args>(__args)...); + } + + ~_Temporary_value() + { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); } + + value_type& + _M_val() { return *_M_ptr(); } + + private: + _Tp* + _M_ptr() { return reinterpret_cast<_Tp*>(&__buf); } + + vector* _M_this; + typename aligned_storage::type __buf; + }; + + // Called by insert(p,x) and other functions when insertion needs to + // reallocate or move existing elements. _Arg is either _Tp& or _Tp. + template + void + _M_insert_aux(iterator __position, _Arg&& __arg); + + template + void + _M_realloc_insert(iterator __position, _Args&&... __args); + + // Either move-construct at the end, or forward to _M_insert_aux. + iterator + _M_insert_rval(const_iterator __position, value_type&& __v); + + // Try to emplace at the end, otherwise forward to _M_insert_aux. + template + iterator + _M_emplace_aux(const_iterator __position, _Args&&... __args); + + // Emplacing an rvalue of the correct type can use _M_insert_rval. + iterator + _M_emplace_aux(const_iterator __position, value_type&& __v) + { return _M_insert_rval(__position, std::move(__v)); } +#endif + + // Called by _M_fill_insert, _M_insert_aux etc. + size_type + _M_check_len(size_type __n, const char* __s) const + { + if (max_size() - size() < __n) + __throw_length_error(__N(__s)); + + const size_type __len = size() + (std::max)(size(), __n); + return (__len < size() || __len > max_size()) ? max_size() : __len; + } + + // Called by constructors to check initial size. + static size_type + _S_check_init_len(size_type __n, const allocator_type& __a) + { + if (__n > _S_max_size(_Tp_alloc_type(__a))) + __throw_length_error( + __N("cannot create std::vector larger than max_size()")); + return __n; + } + + static size_type + _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT + { + // std::distance(begin(), end()) cannot be greater than PTRDIFF_MAX, + // and realistically we can't store more than PTRDIFF_MAX/sizeof(T) + // (even if std::allocator_traits::max_size says we can). + const size_t __diffmax + = __gnu_cxx::__numeric_traits::__max / sizeof(_Tp); + const size_t __allocmax = _Alloc_traits::max_size(__a); + return (std::min)(__diffmax, __allocmax); + } + + // Internal erase functions follow. + + // Called by erase(q1,q2), clear(), resize(), _M_fill_assign, + // _M_assign_aux. + void + _M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT + { + if (size_type __n = this->_M_impl._M_finish - __pos) + { + std::_Destroy(__pos, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __pos; + _GLIBCXX_ASAN_ANNOTATE_SHRINK(__n); + } + } + + iterator + _M_erase(iterator __position); + + iterator + _M_erase(iterator __first, iterator __last); + +#if __cplusplus >= 201103L + private: + // Constant-time move assignment when source object's memory can be + // moved, either because the source's allocator will move too + // or because the allocators are equal. + void + _M_move_assign(vector&& __x, true_type) noexcept + { + vector __tmp(get_allocator()); + this->_M_impl._M_swap_data(__x._M_impl); + __tmp._M_impl._M_swap_data(__x._M_impl); + std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); + } + + // Do move assignment when it might not be possible to move source + // object's memory, resulting in a linear-time operation. + void + _M_move_assign(vector&& __x, false_type) + { + if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator()) + _M_move_assign(std::move(__x), true_type()); + else + { + // The rvalue's allocator cannot be moved and is not equal, + // so we need to individually move each element. + this->_M_assign_aux(std::make_move_iterator(__x.begin()), + std::make_move_iterator(__x.end()), + std::random_access_iterator_tag()); + __x.clear(); + } + } +#endif + + template + _Up* + _M_data_ptr(_Up* __ptr) const _GLIBCXX_NOEXCEPT + { return __ptr; } + +#if __cplusplus >= 201103L + template + typename std::pointer_traits<_Ptr>::element_type* + _M_data_ptr(_Ptr __ptr) const + { return empty() ? nullptr : std::__to_address(__ptr); } +#else + template + _Up* + _M_data_ptr(_Up* __ptr) _GLIBCXX_NOEXCEPT + { return __ptr; } + + template + value_type* + _M_data_ptr(_Ptr __ptr) + { return empty() ? (value_type*)0 : __ptr.operator->(); } + + template + const value_type* + _M_data_ptr(_Ptr __ptr) const + { return empty() ? (const value_type*)0 : __ptr.operator->(); } +#endif + }; + +#if __cpp_deduction_guides >= 201606 + template::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + vector(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> vector<_ValT, _Allocator>; +#endif + + /** + * @brief Vector equality comparison. + * @param __x A %vector. + * @param __y A %vector of the same type as @a __x. + * @return True iff the size and elements of the vectors are equal. + * + * This is an equivalence relation. It is linear in the size of the + * vectors. Vectors are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return (__x.size() == __y.size() + && std::equal(__x.begin(), __x.end(), __y.begin())); } + +#if __cpp_lib_three_way_comparison + /** + * @brief Vector ordering relation. + * @param __x A `vector`. + * @param __y A `vector` of the same type as `__x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Tp> + operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + /** + * @brief Vector ordering relation. + * @param __x A %vector. + * @param __y A %vector of the same type as @a __x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * vectors. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } + + /// Based on operator== + template + inline bool + operator!=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::vector::swap(). + template + inline void + swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus >= 201703L + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing a + // vector into a variant, but only if move assignment cannot throw. + template + struct _Never_valueless_alt<_GLIBCXX_STD_C::vector<_Tp, _Alloc>> + : std::is_nothrow_move_assignable<_GLIBCXX_STD_C::vector<_Tp, _Alloc>> + { }; + } // namespace __detail::__variant +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_VECTOR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/string_view.tcc b/resources/sources/avr-libstdcpp/include/bits/string_view.tcc new file mode 100644 index 000000000..88d9371f1 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/string_view.tcc @@ -0,0 +1,229 @@ +// Components for manipulating non-owning sequences of characters -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/string_view.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{string_view} + */ + +// +// N3762 basic_string_view library +// + +#ifndef _GLIBCXX_STRING_VIEW_TCC +#define _GLIBCXX_STRING_VIEW_TCC 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find(const _CharT* __str, size_type __pos, size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + + if (__n == 0) + return __pos <= this->_M_len ? __pos : npos; + + if (__n <= this->_M_len) + { + for (; __pos <= this->_M_len - __n; ++__pos) + if (traits_type::eq(this->_M_str[__pos], __str[0]) + && traits_type::compare(this->_M_str + __pos + 1, + __str + 1, __n - 1) == 0) + return __pos; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find(_CharT __c, size_type __pos) const noexcept + { + size_type __ret = npos; + if (__pos < this->_M_len) + { + const size_type __n = this->_M_len - __pos; + const _CharT* __p = traits_type::find(this->_M_str + __pos, __n, __c); + if (__p) + __ret = __p - this->_M_str; + } + return __ret; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + + if (__n <= this->_M_len) + { + __pos = std::min(size_type(this->_M_len - __n), __pos); + do + { + if (traits_type::compare(this->_M_str + __pos, __str, __n) == 0) + return __pos; + } + while (__pos-- > 0); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + rfind(_CharT __c, size_type __pos) const noexcept + { + size_type __size = this->_M_len; + if (__size > 0) + { + if (--__size > __pos) + __size = __pos; + for (++__size; __size-- > 0; ) + if (traits_type::eq(this->_M_str[__size], __c)) + return __size; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + for (; __n && __pos < this->_M_len; ++__pos) + { + const _CharT* __p = traits_type::find(__str, __n, + this->_M_str[__pos]); + if (__p) + return __pos; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + size_type __size = this->size(); + if (__size && __n) + { + if (--__size > __pos) + __size = __pos; + do + { + if (traits_type::find(__str, __n, this->_M_str[__size])) + return __size; + } + while (__size-- != 0); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_not_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + for (; __pos < this->_M_len; ++__pos) + if (!traits_type::find(__str, __n, this->_M_str[__pos])) + return __pos; + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_not_of(_CharT __c, size_type __pos) const noexcept + { + for (; __pos < this->_M_len; ++__pos) + if (!traits_type::eq(this->_M_str[__pos], __c)) + return __pos; + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_not_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + size_type __size = this->_M_len; + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::find(__str, __n, this->_M_str[__size])) + return __size; + } + while (__size--); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_not_of(_CharT __c, size_type __pos) const noexcept + { + size_type __size = this->_M_len; + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::eq(this->_M_str[__size], __c)) + return __size; + } + while (__size--); + } + return npos; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cplusplus <= 201402L + +#endif // _GLIBCXX_STRING_VIEW_TCC diff --git a/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h b/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h new file mode 100644 index 000000000..e3d7934e9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h @@ -0,0 +1,395 @@ +// Class template uniform_int_distribution -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** + * @file bits/uniform_int_dist.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{random} + */ + +#ifndef _GLIBCXX_BITS_UNIFORM_INT_DIST_H +#define _GLIBCXX_BITS_UNIFORM_INT_DIST_H + +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#ifdef __cpp_lib_concepts + /// Requirements for a uniform random bit generator. + template + concept uniform_random_bit_generator + = invocable<_Gen&> && unsigned_integral> + && requires + { + { _Gen::min() } -> same_as>; + { _Gen::max() } -> same_as>; + requires bool_constant<(_Gen::min() < _Gen::max())>::value; + }; +#endif + + namespace __detail + { + /* Determine whether number is a power of 2. */ + template + inline bool + _Power_of_2(_Tp __x) + { + return ((__x - 1) & __x) == 0; + } + } + + /** + * @brief Uniform discrete distribution for random numbers. + * A discrete random distribution on the range @f$[min, max]@f$ with equal + * probability throughout the range. + */ + template + class uniform_int_distribution + { + static_assert(std::is_integral<_IntType>::value, + "template argument must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + /** Parameter type. */ + struct param_type + { + typedef uniform_int_distribution<_IntType> distribution_type; + + param_type() : param_type(0) { } + + explicit + param_type(_IntType __a, + _IntType __b = numeric_limits<_IntType>::max()) + : _M_a(__a), _M_b(__b) + { + __glibcxx_assert(_M_a <= _M_b); + } + + result_type + a() const + { return _M_a; } + + result_type + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _IntType _M_a; + _IntType _M_b; + }; + + public: + /** + * @brief Constructs a uniform distribution object. + */ + uniform_int_distribution() : uniform_int_distribution(0) { } + + /** + * @brief Constructs a uniform distribution object. + */ + explicit + uniform_int_distribution(_IntType __a, + _IntType __b = numeric_limits<_IntType>::max()) + : _M_param(__a, __b) + { } + + explicit + uniform_int_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for the uniform integer distribution. + */ + void + reset() { } + + result_type + a() const + { return _M_param.a(); } + + result_type + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the inclusive lower bound of the distribution range. + */ + result_type + min() const + { return this->a(); } + + /** + * @brief Returns the inclusive upper bound of the distribution range. + */ + result_type + max() const + { return this->b(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two uniform integer distributions have + * the same parameters. + */ + friend bool + operator==(const uniform_int_distribution& __d1, + const uniform_int_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + template + template + typename uniform_int_distribution<_IntType>::result_type + uniform_int_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + typedef typename _UniformRandomNumberGenerator::result_type + _Gresult_type; + typedef typename std::make_unsigned::type __utype; + typedef typename std::common_type<_Gresult_type, __utype>::type + __uctype; + + const __uctype __urngmin = __urng.min(); + const __uctype __urngmax = __urng.max(); + const __uctype __urngrange = __urngmax - __urngmin; + const __uctype __urange + = __uctype(__param.b()) - __uctype(__param.a()); + + __uctype __ret; + + if (__urngrange > __urange) + { + // downscaling + const __uctype __uerange = __urange + 1; // __urange can be zero + const __uctype __scaling = __urngrange / __uerange; + const __uctype __past = __uerange * __scaling; + do + __ret = __uctype(__urng()) - __urngmin; + while (__ret >= __past); + __ret /= __scaling; + } + else if (__urngrange < __urange) + { + // upscaling + /* + Note that every value in [0, urange] + can be written uniquely as + + (urngrange + 1) * high + low + + where + + high in [0, urange / (urngrange + 1)] + + and + + low in [0, urngrange]. + */ + __uctype __tmp; // wraparound control + do + { + const __uctype __uerngrange = __urngrange + 1; + __tmp = (__uerngrange * operator() + (__urng, param_type(0, __urange / __uerngrange))); + __ret = __tmp + (__uctype(__urng()) - __urngmin); + } + while (__ret > __urange || __ret < __tmp); + } + else + __ret = __uctype(__urng()) - __urngmin; + + return __ret + __param.a(); + } + + + template + template + void + uniform_int_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typedef typename _UniformRandomNumberGenerator::result_type + _Gresult_type; + typedef typename std::make_unsigned::type __utype; + typedef typename std::common_type<_Gresult_type, __utype>::type + __uctype; + + const __uctype __urngmin = __urng.min(); + const __uctype __urngmax = __urng.max(); + const __uctype __urngrange = __urngmax - __urngmin; + const __uctype __urange + = __uctype(__param.b()) - __uctype(__param.a()); + + __uctype __ret; + + if (__urngrange > __urange) + { + if (__detail::_Power_of_2(__urngrange + 1) + && __detail::_Power_of_2(__urange + 1)) + { + while (__f != __t) + { + __ret = __uctype(__urng()) - __urngmin; + *__f++ = (__ret & __urange) + __param.a(); + } + } + else + { + // downscaling + const __uctype __uerange = __urange + 1; // __urange can be zero + const __uctype __scaling = __urngrange / __uerange; + const __uctype __past = __uerange * __scaling; + while (__f != __t) + { + do + __ret = __uctype(__urng()) - __urngmin; + while (__ret >= __past); + *__f++ = __ret / __scaling + __param.a(); + } + } + } + else if (__urngrange < __urange) + { + // upscaling + /* + Note that every value in [0, urange] + can be written uniquely as + + (urngrange + 1) * high + low + + where + + high in [0, urange / (urngrange + 1)] + + and + + low in [0, urngrange]. + */ + __uctype __tmp; // wraparound control + while (__f != __t) + { + do + { + const __uctype __uerngrange = __urngrange + 1; + __tmp = (__uerngrange * operator() + (__urng, param_type(0, __urange / __uerngrange))); + __ret = __tmp + (__uctype(__urng()) - __urngmin); + } + while (__ret > __urange || __ret < __tmp); + *__f++ = __ret; + } + } + else + while (__f != __t) + *__f++ = __uctype(__urng()) - __urngmin + __param.a(); + } + + // operator!= and operator<< and operator>> are defined in + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/unique_lock.h b/resources/sources/avr-libstdcpp/include/bits/unique_lock.h new file mode 100644 index 000000000..82eef44d6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/unique_lock.h @@ -0,0 +1,243 @@ +// std::unique_lock implementation -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unique_lock.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{mutex} + */ + +#ifndef _GLIBCXX_UNIQUE_LOCK_H +#define _GLIBCXX_UNIQUE_LOCK_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include // for std::swap + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @brief A movable scoped lock type. + * + * A unique_lock controls mutex ownership within a scope. Ownership of the + * mutex can be delayed until after construction and can be transferred + * to another unique_lock by move construction or move assignment. If a + * mutex lock is owned when the destructor runs ownership will be released. + * + * @ingroup mutexes + */ + template + class unique_lock + { + public: + typedef _Mutex mutex_type; + + unique_lock() noexcept + : _M_device(0), _M_owns(false) + { } + + explicit unique_lock(mutex_type& __m) + : _M_device(std::__addressof(__m)), _M_owns(false) + { + lock(); + _M_owns = true; + } + + unique_lock(mutex_type& __m, defer_lock_t) noexcept + : _M_device(std::__addressof(__m)), _M_owns(false) + { } + + unique_lock(mutex_type& __m, try_to_lock_t) + : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock()) + { } + + unique_lock(mutex_type& __m, adopt_lock_t) noexcept + : _M_device(std::__addressof(__m)), _M_owns(true) + { + // XXX calling thread owns mutex + } + + template + unique_lock(mutex_type& __m, + const chrono::time_point<_Clock, _Duration>& __atime) + : _M_device(std::__addressof(__m)), + _M_owns(_M_device->try_lock_until(__atime)) + { } + + template + unique_lock(mutex_type& __m, + const chrono::duration<_Rep, _Period>& __rtime) + : _M_device(std::__addressof(__m)), + _M_owns(_M_device->try_lock_for(__rtime)) + { } + + ~unique_lock() + { + if (_M_owns) + unlock(); + } + + unique_lock(const unique_lock&) = delete; + unique_lock& operator=(const unique_lock&) = delete; + + unique_lock(unique_lock&& __u) noexcept + : _M_device(__u._M_device), _M_owns(__u._M_owns) + { + __u._M_device = 0; + __u._M_owns = false; + } + + unique_lock& operator=(unique_lock&& __u) noexcept + { + if(_M_owns) + unlock(); + + unique_lock(std::move(__u)).swap(*this); + + __u._M_device = 0; + __u._M_owns = false; + + return *this; + } + + void + lock() + { + if (!_M_device) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + else + { + _M_device->lock(); + _M_owns = true; + } + } + + bool + try_lock() + { + if (!_M_device) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + else + { + _M_owns = _M_device->try_lock(); + return _M_owns; + } + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + if (!_M_device) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + else + { + _M_owns = _M_device->try_lock_until(__atime); + return _M_owns; + } + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + if (!_M_device) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + else + { + _M_owns = _M_device->try_lock_for(__rtime); + return _M_owns; + } + } + + void + unlock() + { + if (!_M_owns) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_device) + { + _M_device->unlock(); + _M_owns = false; + } + } + + void + swap(unique_lock& __u) noexcept + { + std::swap(_M_device, __u._M_device); + std::swap(_M_owns, __u._M_owns); + } + + mutex_type* + release() noexcept + { + mutex_type* __ret = _M_device; + _M_device = 0; + _M_owns = false; + return __ret; + } + + bool + owns_lock() const noexcept + { return _M_owns; } + + explicit operator bool() const noexcept + { return owns_lock(); } + + mutex_type* + mutex() const noexcept + { return _M_device; } + + private: + mutex_type* _M_device; + bool _M_owns; + }; + + /// Swap overload for unique_lock objects. + /// @relates unique_lock + template + inline void + swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 +#endif // _GLIBCXX_UNIQUE_LOCK_H diff --git a/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h b/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h new file mode 100644 index 000000000..0f100c593 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h @@ -0,0 +1,995 @@ +// unique_ptr implementation -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unique_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _UNIQUE_PTR_H +#define _UNIQUE_PTR_H 1 + +#include +#include +#include +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup pointer_abstractions + * @{ + */ + +#if _GLIBCXX_USE_DEPRECATED +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + template class auto_ptr; +#pragma GCC diagnostic pop +#endif + + /// Primary template of default_delete, used by unique_ptr for single objects + template + struct default_delete + { + /// Default constructor + constexpr default_delete() noexcept = default; + + /** @brief Converting constructor. + * + * Allows conversion from a deleter for objects of another type, `_Up`, + * only if `_Up*` is convertible to `_Tp*`. + */ + template>> + default_delete(const default_delete<_Up>&) noexcept { } + + /// Calls `delete __ptr` + void + operator()(_Tp* __ptr) const + { + static_assert(!is_void<_Tp>::value, + "can't delete pointer to incomplete type"); + static_assert(sizeof(_Tp)>0, + "can't delete pointer to incomplete type"); + delete __ptr; + } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 740 - omit specialization for array objects with a compile time length + + /// Specialization of default_delete for arrays, used by `unique_ptr` + template + struct default_delete<_Tp[]> + { + public: + /// Default constructor + constexpr default_delete() noexcept = default; + + /** @brief Converting constructor. + * + * Allows conversion from a deleter for arrays of another type, such as + * a const-qualified version of `_Tp`. + * + * Conversions from types derived from `_Tp` are not allowed because + * it is undefined to `delete[]` an array of derived types through a + * pointer to the base type. + */ + template>> + default_delete(const default_delete<_Up[]>&) noexcept { } + + /// Calls `delete[] __ptr` + template + typename enable_if::value>::type + operator()(_Up* __ptr) const + { + static_assert(sizeof(_Tp)>0, + "can't delete pointer to incomplete type"); + delete [] __ptr; + } + }; + + /// @cond undocumented + + // Manages the pointer and deleter of a unique_ptr + template + class __uniq_ptr_impl + { + template + struct _Ptr + { + using type = _Up*; + }; + + template + struct + _Ptr<_Up, _Ep, __void_t::type::pointer>> + { + using type = typename remove_reference<_Ep>::type::pointer; + }; + + public: + using _DeleterConstraint = enable_if< + __and_<__not_>, + is_default_constructible<_Dp>>::value>; + + using pointer = typename _Ptr<_Tp, _Dp>::type; + + static_assert( !is_rvalue_reference<_Dp>::value, + "unique_ptr's deleter type must be a function object type" + " or an lvalue reference type" ); + + __uniq_ptr_impl() = default; + __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } + + template + __uniq_ptr_impl(pointer __p, _Del&& __d) + : _M_t(__p, std::forward<_Del>(__d)) { } + + __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept + : _M_t(std::move(__u._M_t)) + { __u._M_ptr() = nullptr; } + + __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept + { + reset(__u.release()); + _M_deleter() = std::forward<_Dp>(__u._M_deleter()); + return *this; + } + + pointer& _M_ptr() { return std::get<0>(_M_t); } + pointer _M_ptr() const { return std::get<0>(_M_t); } + _Dp& _M_deleter() { return std::get<1>(_M_t); } + const _Dp& _M_deleter() const { return std::get<1>(_M_t); } + + void reset(pointer __p) noexcept + { + const pointer __old_p = _M_ptr(); + _M_ptr() = __p; + if (__old_p) + _M_deleter()(__old_p); + } + + pointer release() noexcept + { + pointer __p = _M_ptr(); + _M_ptr() = nullptr; + return __p; + } + + void + swap(__uniq_ptr_impl& __rhs) noexcept + { + using std::swap; + swap(this->_M_ptr(), __rhs._M_ptr()); + swap(this->_M_deleter(), __rhs._M_deleter()); + } + + private: + tuple _M_t; + }; + + // Defines move construction + assignment as either defaulted or deleted. + template ::value, + bool = is_move_assignable<_Dp>::value> + struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = default; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = default; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = delete; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = delete; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; + }; + /// @endcond + + /// 20.7.1.2 unique_ptr for single objects. + template > + class unique_ptr + { + template + using _DeleterConstraint = + typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; + + __uniq_ptr_data<_Tp, _Dp> _M_t; + + public: + using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; + using element_type = _Tp; + using deleter_type = _Dp; + + private: + // helper template for detecting a safe conversion from another + // unique_ptr + template + using __safe_conversion_up = __and_< + is_convertible::pointer, pointer>, + __not_> + >; + + public: + // Constructors. + + /// Default constructor, creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr() noexcept + : _M_t() + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * + * The deleter will be value-initialized. + */ + template> + explicit + unique_ptr(pointer __p) noexcept + : _M_t(__p) + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p __d + */ + template>> + unique_ptr(pointer __p, const deleter_type& __d) noexcept + : _M_t(__p, __d) { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * @param __d An rvalue reference to a (non-reference) deleter. + * + * The deleter will be initialized with @p std::move(__d) + */ + template>> + unique_ptr(pointer __p, + __enable_if_t::value, + _Del&&> __d) noexcept + : _M_t(__p, std::move(__d)) + { } + + template::type> + unique_ptr(pointer, + __enable_if_t::value, + _DelUnref&&>) = delete; + + /// Creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr(nullptr_t) noexcept + : _M_t() + { } + + // Move constructors. + + /// Move constructor. + unique_ptr(unique_ptr&&) = default; + + /** @brief Converting constructor from another type + * + * Requires that the pointer owned by @p __u is convertible to the + * type of pointer owned by this object, @p __u does not own an array, + * and @p __u has a compatible deleter type. + */ + template, + typename conditional::value, + is_same<_Ep, _Dp>, + is_convertible<_Ep, _Dp>>::type>> + unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept + : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) + { } + +#if _GLIBCXX_USE_DEPRECATED +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /// Converting constructor from @c auto_ptr + template, is_same<_Dp, default_delete<_Tp>>>> + unique_ptr(auto_ptr<_Up>&& __u) noexcept; +#pragma GCC diagnostic pop +#endif + + /// Destructor, invokes the deleter if the stored pointer is not null. + ~unique_ptr() noexcept + { + static_assert(__is_invocable::value, + "unique_ptr's deleter must be invocable with a pointer"); + auto& __ptr = _M_t._M_ptr(); + if (__ptr != nullptr) + get_deleter()(std::move(__ptr)); + __ptr = pointer(); + } + + // Assignment. + + /** @brief Move assignment operator. + * + * Invokes the deleter if this object owns a pointer. + */ + unique_ptr& operator=(unique_ptr&&) = default; + + /** @brief Assignment from another type. + * + * @param __u The object to transfer ownership from, which owns a + * convertible pointer to a non-array object. + * + * Invokes the deleter if this object owns a pointer. + */ + template + typename enable_if< __and_< + __safe_conversion_up<_Up, _Ep>, + is_assignable + >::value, + unique_ptr&>::type + operator=(unique_ptr<_Up, _Ep>&& __u) noexcept + { + reset(__u.release()); + get_deleter() = std::forward<_Ep>(__u.get_deleter()); + return *this; + } + + /// Reset the %unique_ptr to empty, invoking the deleter if necessary. + unique_ptr& + operator=(nullptr_t) noexcept + { + reset(); + return *this; + } + + // Observers. + + /// Dereference the stored pointer. + typename add_lvalue_reference::type + operator*() const + { + __glibcxx_assert(get() != pointer()); + return *get(); + } + + /// Return the stored pointer. + pointer + operator->() const noexcept + { + _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); + return get(); + } + + /// Return the stored pointer. + pointer + get() const noexcept + { return _M_t._M_ptr(); } + + /// Return a reference to the stored deleter. + deleter_type& + get_deleter() noexcept + { return _M_t._M_deleter(); } + + /// Return a reference to the stored deleter. + const deleter_type& + get_deleter() const noexcept + { return _M_t._M_deleter(); } + + /// Return @c true if the stored pointer is not null. + explicit operator bool() const noexcept + { return get() == pointer() ? false : true; } + + // Modifiers. + + /// Release ownership of any stored pointer. + pointer + release() noexcept + { return _M_t.release(); } + + /** @brief Replace the stored pointer. + * + * @param __p The new pointer to store. + * + * The deleter will be invoked if a pointer is already owned. + */ + void + reset(pointer __p = pointer()) noexcept + { + static_assert(__is_invocable::value, + "unique_ptr's deleter must be invocable with a pointer"); + _M_t.reset(std::move(__p)); + } + + /// Exchange the pointer and deleter with another object. + void + swap(unique_ptr& __u) noexcept + { + static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); + _M_t.swap(__u._M_t); + } + + // Disable copy from lvalue. + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + }; + + /// 20.7.1.3 unique_ptr for array objects with a runtime length + // [unique.ptr.runtime] + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 740 - omit specialization for array objects with a compile time length + template + class unique_ptr<_Tp[], _Dp> + { + template + using _DeleterConstraint = + typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; + + __uniq_ptr_data<_Tp, _Dp> _M_t; + + template + using __remove_cv_t = typename remove_cv<_Up>::type; + + // like is_base_of<_Tp, _Up> but false if unqualified types are the same + template + using __is_derived_Tp + = __and_< is_base_of<_Tp, _Up>, + __not_, __remove_cv_t<_Up>>> >; + + public: + using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; + using element_type = _Tp; + using deleter_type = _Dp; + + // helper template for detecting a safe conversion from another + // unique_ptr + template, + typename _UP_pointer = typename _UPtr::pointer, + typename _UP_element_type = typename _UPtr::element_type> + using __safe_conversion_up = __and_< + is_array<_Up>, + is_same, + is_same<_UP_pointer, _UP_element_type*>, + is_convertible<_UP_element_type(*)[], element_type(*)[]> + >; + + // helper template for detecting a safe conversion from a raw pointer + template + using __safe_conversion_raw = __and_< + __or_<__or_, + is_same<_Up, nullptr_t>>, + __and_, + is_same, + is_convertible< + typename remove_pointer<_Up>::type(*)[], + element_type(*)[]> + > + > + >; + + // Constructors. + + /// Default constructor, creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr() noexcept + : _M_t() + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * + * The deleter will be value-initialized. + */ + template, + typename = typename enable_if< + __safe_conversion_raw<_Up>::value, bool>::type> + explicit + unique_ptr(_Up __p) noexcept + : _M_t(__p) + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p __d + */ + template, + is_copy_constructible<_Del>>> + unique_ptr(_Up __p, const deleter_type& __d) noexcept + : _M_t(__p, __d) { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p std::move(__d) + */ + template, + is_move_constructible<_Del>>> + unique_ptr(_Up __p, + __enable_if_t::value, + _Del&&> __d) noexcept + : _M_t(std::move(__p), std::move(__d)) + { } + + template::type, + typename = _Require<__safe_conversion_raw<_Up>>> + unique_ptr(_Up, + __enable_if_t::value, + _DelUnref&&>) = delete; + + /// Move constructor. + unique_ptr(unique_ptr&&) = default; + + /// Creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr(nullptr_t) noexcept + : _M_t() + { } + + template, + typename conditional::value, + is_same<_Ep, _Dp>, + is_convertible<_Ep, _Dp>>::type>> + unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept + : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) + { } + + /// Destructor, invokes the deleter if the stored pointer is not null. + ~unique_ptr() + { + auto& __ptr = _M_t._M_ptr(); + if (__ptr != nullptr) + get_deleter()(__ptr); + __ptr = pointer(); + } + + // Assignment. + + /** @brief Move assignment operator. + * + * Invokes the deleter if this object owns a pointer. + */ + unique_ptr& + operator=(unique_ptr&&) = default; + + /** @brief Assignment from another type. + * + * @param __u The object to transfer ownership from, which owns a + * convertible pointer to an array object. + * + * Invokes the deleter if this object owns a pointer. + */ + template + typename + enable_if<__and_<__safe_conversion_up<_Up, _Ep>, + is_assignable + >::value, + unique_ptr&>::type + operator=(unique_ptr<_Up, _Ep>&& __u) noexcept + { + reset(__u.release()); + get_deleter() = std::forward<_Ep>(__u.get_deleter()); + return *this; + } + + /// Reset the %unique_ptr to empty, invoking the deleter if necessary. + unique_ptr& + operator=(nullptr_t) noexcept + { + reset(); + return *this; + } + + // Observers. + + /// Access an element of owned array. + typename std::add_lvalue_reference::type + operator[](size_t __i) const + { + __glibcxx_assert(get() != pointer()); + return get()[__i]; + } + + /// Return the stored pointer. + pointer + get() const noexcept + { return _M_t._M_ptr(); } + + /// Return a reference to the stored deleter. + deleter_type& + get_deleter() noexcept + { return _M_t._M_deleter(); } + + /// Return a reference to the stored deleter. + const deleter_type& + get_deleter() const noexcept + { return _M_t._M_deleter(); } + + /// Return @c true if the stored pointer is not null. + explicit operator bool() const noexcept + { return get() == pointer() ? false : true; } + + // Modifiers. + + /// Release ownership of any stored pointer. + pointer + release() noexcept + { return _M_t.release(); } + + /** @brief Replace the stored pointer. + * + * @param __p The new pointer to store. + * + * The deleter will be invoked if a pointer is already owned. + */ + template , + __and_, + is_pointer<_Up>, + is_convertible< + typename remove_pointer<_Up>::type(*)[], + element_type(*)[] + > + > + > + >> + void + reset(_Up __p) noexcept + { _M_t.reset(std::move(__p)); } + + void reset(nullptr_t = nullptr) noexcept + { reset(pointer()); } + + /// Exchange the pointer and deleter with another object. + void + swap(unique_ptr& __u) noexcept + { + static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); + _M_t.swap(__u._M_t); + } + + // Disable copy from lvalue. + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + }; + + /// @relates unique_ptr @{ + + /// Swap overload for unique_ptr + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Dp>::value>::type +#else + void +#endif + swap(unique_ptr<_Tp, _Dp>& __x, + unique_ptr<_Tp, _Dp>& __y) noexcept + { __x.swap(__y); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + typename enable_if::value>::type + swap(unique_ptr<_Tp, _Dp>&, + unique_ptr<_Tp, _Dp>&) = delete; +#endif + + /// Equality operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator==(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return __x.get() == __y.get(); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept + { return !__x; } + +#ifndef __cpp_lib_three_way_comparison + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept + { return !__x; } + + /// Inequality operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator!=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return __x.get() != __y.get(); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept + { return (bool)__x; } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept + { return (bool)__x; } +#endif // three way comparison + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator<(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { + typedef typename + std::common_type::pointer, + typename unique_ptr<_Up, _Ep>::pointer>::type _CT; + return std::less<_CT>()(__x.get(), __y.get()); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + return std::less::pointer>()(__x.get(), + nullptr); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { + return std::less::pointer>()(nullptr, + __x.get()); + } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator<=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return !(__y < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { return !(nullptr < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { return !(__x < nullptr); } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator>(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return (__y < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + return std::less::pointer>()(nullptr, + __x.get()); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { + return std::less::pointer>()(__x.get(), + nullptr); + } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator>=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return !(__x < __y); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { return !(__x < nullptr); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { return !(nullptr < __x); } + +#ifdef __cpp_lib_three_way_comparison + template + requires three_way_comparable_with::pointer, + typename unique_ptr<_Up, _Ep>::pointer> + inline + compare_three_way_result_t::pointer, + typename unique_ptr<_Up, _Ep>::pointer> + operator<=>(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return compare_three_way()(__x.get(), __y.get()); } + + template + requires three_way_comparable::pointer> + inline + compare_three_way_result_t::pointer> + operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + using pointer = typename unique_ptr<_Tp, _Dp>::pointer; + return compare_three_way()(__x.get(), static_cast(nullptr)); + } +#endif + // @} relates unique_ptr + + /// @cond undocumented + template::__enable_hash_call> + struct __uniq_ptr_hash +#if ! _GLIBCXX_INLINE_VERSION + : private __poison_hash<_Ptr> +#endif + { + size_t + operator()(const _Up& __u) const + noexcept(noexcept(std::declval>()(std::declval<_Ptr>()))) + { return hash<_Ptr>()(__u.get()); } + }; + + template + struct __uniq_ptr_hash<_Up, _Ptr, false> + : private __poison_hash<_Ptr> + { }; + /// @endcond + + /// std::hash specialization for unique_ptr. + template + struct hash> + : public __hash_base>, + public __uniq_ptr_hash> + { }; + +#if __cplusplus >= 201402L + /// @relates unique_ptr @{ +#define __cpp_lib_make_unique 201304 + + /// @cond undocumented + + template + struct _MakeUniq + { typedef unique_ptr<_Tp> __single_object; }; + + template + struct _MakeUniq<_Tp[]> + { typedef unique_ptr<_Tp[]> __array; }; + + template + struct _MakeUniq<_Tp[_Bound]> + { struct __invalid_type { }; }; + + /// @endcond + + /// std::make_unique for single objects + template + inline typename _MakeUniq<_Tp>::__single_object + make_unique(_Args&&... __args) + { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } + + /// std::make_unique for arrays of unknown bound + template + inline typename _MakeUniq<_Tp>::__array + make_unique(size_t __num) + { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } + + /// Disable std::make_unique for arrays of known bound + template + inline typename _MakeUniq<_Tp>::__invalid_type + make_unique(_Args&&...) = delete; + // @} relates unique_ptr +#endif // C++14 + + // @} group pointer_abstractions + +#if __cplusplus >= 201703L + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing a + // unique_ptr into a variant. + template + struct _Never_valueless_alt> + : std::true_type + { }; + } // namespace __detail::__variant +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _UNIQUE_PTR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/unordered_map.h b/resources/sources/avr-libstdcpp/include/bits/unordered_map.h new file mode 100644 index 000000000..0071d62e4 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/unordered_map.h @@ -0,0 +1,2171 @@ +// unordered_map implementation -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unordered_map.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{unordered_map} + */ + +#ifndef _UNORDERED_MAP_H +#define _UNORDERED_MAP_H + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /// Base types for unordered_map. + template + using __umap_traits = __detail::_Hashtable_traits<_Cache, false, true>; + + template, + typename _Pred = std::equal_to<_Key>, + typename _Alloc = std::allocator >, + typename _Tr = __umap_traits<__cache_default<_Key, _Hash>::value>> + using __umap_hashtable = _Hashtable<_Key, std::pair, + _Alloc, __detail::_Select1st, + _Pred, _Hash, + __detail::_Mod_range_hashing, + __detail::_Default_ranged_hash, + __detail::_Prime_rehash_policy, _Tr>; + + /// Base types for unordered_multimap. + template + using __ummap_traits = __detail::_Hashtable_traits<_Cache, false, false>; + + template, + typename _Pred = std::equal_to<_Key>, + typename _Alloc = std::allocator >, + typename _Tr = __ummap_traits<__cache_default<_Key, _Hash>::value>> + using __ummap_hashtable = _Hashtable<_Key, std::pair, + _Alloc, __detail::_Select1st, + _Pred, _Hash, + __detail::_Mod_range_hashing, + __detail::_Default_ranged_hash, + __detail::_Prime_rehash_policy, _Tr>; + + template + class unordered_multimap; + + /** + * @brief A standard container composed of unique keys (containing + * at most one of each key value) that associates values of another type + * with the keys. + * + * @ingroup unordered_associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Pred Predicate function object type, defaults + * to equal_to<_Value>. + * @tparam _Alloc Allocator type, defaults to + * std::allocator>. + * + * Meets the requirements of a container, and + * unordered associative container + * + * The resulting value type of the container is std::pair. + * + * Base is _Hashtable, dispatched at compile time via template + * alias __umap_hashtable. + */ + template, + typename _Pred = equal_to<_Key>, + typename _Alloc = allocator>> + class unordered_map + { + typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable; + _Hashtable _M_h; + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef typename _Hashtable::key_type key_type; + typedef typename _Hashtable::value_type value_type; + typedef typename _Hashtable::mapped_type mapped_type; + typedef typename _Hashtable::hasher hasher; + typedef typename _Hashtable::key_equal key_equal; + typedef typename _Hashtable::allocator_type allocator_type; + //@} + + //@{ + /// Iterator-related typedefs. + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; + typedef typename _Hashtable::iterator iterator; + typedef typename _Hashtable::const_iterator const_iterator; + typedef typename _Hashtable::local_iterator local_iterator; + typedef typename _Hashtable::const_local_iterator const_local_iterator; + typedef typename _Hashtable::size_type size_type; + typedef typename _Hashtable::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; + using insert_return_type = typename _Hashtable::insert_return_type; +#endif + + //construct/destroy/copy + + /// Default constructor. + unordered_map() = default; + + /** + * @brief Default constructor creates no elements. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + */ + explicit + unordered_map(size_type __n, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__n, __hf, __eql, __a) + { } + + /** + * @brief Builds an %unordered_map from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_map consisting of copies of the elements from + * [__first,__last). This is linear in N (where N is + * distance(__first,__last)). + */ + template + unordered_map(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__first, __last, __n, __hf, __eql, __a) + { } + + /// Copy constructor. + unordered_map(const unordered_map&) = default; + + /// Move constructor. + unordered_map(unordered_map&&) = default; + + /** + * @brief Creates an %unordered_map with no elements. + * @param __a An allocator object. + */ + explicit + unordered_map(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_map to copy. + * @param __a An allocator object. + */ + unordered_map(const unordered_map& __umap, + const allocator_type& __a) + : _M_h(__umap._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_map to move. + * @param __a An allocator object. + */ + unordered_map(unordered_map&& __umap, + const allocator_type& __a) + : _M_h(std::move(__umap._M_h), __a) + { } + + /** + * @brief Builds an %unordered_map from an initializer_list. + * @param __l An initializer_list. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_map consisting of copies of the elements in the + * list. This is linear in N (where N is @a __l.size()). + */ + unordered_map(initializer_list __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__l, __n, __hf, __eql, __a) + { } + + unordered_map(size_type __n, const allocator_type& __a) + : unordered_map(__n, hasher(), key_equal(), __a) + { } + + unordered_map(size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_map(__n, __hf, key_equal(), __a) + { } + + template + unordered_map(_InputIterator __first, _InputIterator __last, + size_type __n, + const allocator_type& __a) + : unordered_map(__first, __last, __n, hasher(), key_equal(), __a) + { } + + template + unordered_map(_InputIterator __first, _InputIterator __last, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_map(__first, __last, __n, __hf, key_equal(), __a) + { } + + unordered_map(initializer_list __l, + size_type __n, + const allocator_type& __a) + : unordered_map(__l, __n, hasher(), key_equal(), __a) + { } + + unordered_map(initializer_list __l, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_map(__l, __n, __hf, key_equal(), __a) + { } + + /// Copy assignment operator. + unordered_map& + operator=(const unordered_map&) = default; + + /// Move assignment operator. + unordered_map& + operator=(unordered_map&&) = default; + + /** + * @brief %Unordered_map list assignment operator. + * @param __l An initializer_list. + * + * This function fills an %unordered_map with copies of the elements in + * the initializer list @a __l. + * + * Note that the assignment completely changes the %unordered_map and + * that the resulting %unordered_map's size is the same as the number + * of elements assigned. + */ + unordered_map& + operator=(initializer_list __l) + { + _M_h = __l; + return *this; + } + + /// Returns the allocator object used by the %unordered_map. + allocator_type + get_allocator() const noexcept + { return _M_h.get_allocator(); } + + // size and capacity: + + /// Returns true if the %unordered_map is empty. + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return _M_h.empty(); } + + /// Returns the size of the %unordered_map. + size_type + size() const noexcept + { return _M_h.size(); } + + /// Returns the maximum size of the %unordered_map. + size_type + max_size() const noexcept + { return _M_h.max_size(); } + + // iterators. + + /** + * Returns a read/write iterator that points to the first element in the + * %unordered_map. + */ + iterator + begin() noexcept + { return _M_h.begin(); } + + //@{ + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_map. + */ + const_iterator + begin() const noexcept + { return _M_h.begin(); } + + const_iterator + cbegin() const noexcept + { return _M_h.begin(); } + //@} + + /** + * Returns a read/write iterator that points one past the last element in + * the %unordered_map. + */ + iterator + end() noexcept + { return _M_h.end(); } + + //@{ + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_map. + */ + const_iterator + end() const noexcept + { return _M_h.end(); } + + const_iterator + cend() const noexcept + { return _M_h.end(); } + //@} + + // modifiers. + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_map. + * + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to build and insert a (key, value) %pair into + * the %unordered_map. + * An %unordered_map relies on unique keys and thus a %pair is only + * inserted if its first element (the key) is not already present in the + * %unordered_map. + * + * Insertion requires amortized constant time. + */ + template + std::pair + emplace(_Args&&... __args) + { return _M_h.emplace(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_map. + * + * @param __pos An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * @return An iterator that points to the element with key of the + * std::pair built from @a __args (may or may not be that + * std::pair). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator, node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)).position; } + +#define __cpp_lib_unordered_map_try_emplace 201411 + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_map. + * + * @param __k Key to use for finding a possibly existing pair in + * the unordered_map. + * @param __args Arguments used to generate the .second for a + * new pair instance. + * + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to build and insert a (key, value) %pair into + * the %unordered_map. + * An %unordered_map relies on unique keys and thus a %pair is only + * inserted if its first element (the key) is not already present in the + * %unordered_map. + * If a %pair is not inserted, this function has no effect. + * + * Insertion requires amortized constant time. + */ + template + pair + try_emplace(const key_type& __k, _Args&&... __args) + { + iterator __i = find(__k); + if (__i == end()) + { + __i = emplace(std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)) + .first; + return {__i, true}; + } + return {__i, false}; + } + + // move-capable overload + template + pair + try_emplace(key_type&& __k, _Args&&... __args) + { + iterator __i = find(__k); + if (__i == end()) + { + __i = emplace(std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)) + .first; + return {__i, true}; + } + return {__i, false}; + } + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_map. + * + * @param __hint An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __k Key to use for finding a possibly existing pair in + * the unordered_map. + * @param __args Arguments used to generate the .second for a + * new pair instance. + * @return An iterator that points to the element with key of the + * std::pair built from @a __args (may or may not be that + * std::pair). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. However, if insertion did not take place, + * this function has no effect. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + template + iterator + try_emplace(const_iterator __hint, const key_type& __k, + _Args&&... __args) + { + iterator __i = find(__k); + if (__i == end()) + __i = emplace_hint(__hint, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return __i; + } + + // move-capable overload + template + iterator + try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) + { + iterator __i = find(__k); + if (__i == end()) + __i = emplace_hint(__hint, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return __i; + } +#endif // C++17 + + //@{ + /** + * @brief Attempts to insert a std::pair into the %unordered_map. + + * @param __x Pair to be inserted (see std::make_pair for easy + * creation of pairs). + * + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is + * a bool that is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the + * %unordered_map. An %unordered_map relies on unique keys and thus a + * %pair is only inserted if its first element (the key) is not already + * present in the %unordered_map. + * + * Insertion requires amortized constant time. + */ + std::pair + insert(const value_type& __x) + { return _M_h.insert(__x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + std::pair + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + + template + __enable_if_t::value, + pair> + insert(_Pair&& __x) + { return _M_h.emplace(std::forward<_Pair>(__x)); } + //@} + + //@{ + /** + * @brief Attempts to insert a std::pair into the %unordered_map. + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument insert() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + iterator + insert(const_iterator __hint, const value_type& __x) + { return _M_h.insert(__hint, __x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(const_iterator __hint, _Pair&& __x) + { return _M_h.emplace_hint(__hint, std::forward<_Pair>(__x)); } + //@} + + /** + * @brief A template function that attempts to insert a range of + * elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_h.insert(__first, __last); } + + /** + * @brief Attempts to insert a list of elements into the %unordered_map. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { _M_h.insert(__l); } + + +#if __cplusplus > 201402L + /** + * @brief Attempts to insert a std::pair into the %unordered_map. + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __obj Argument used to generate the .second for a pair + * instance. + * + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is + * a bool that is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the + * %unordered_map. An %unordered_map relies on unique keys and thus a + * %pair is only inserted if its first element (the key) is not already + * present in the %unordered_map. + * If the %pair was already in the %unordered_map, the .second of + * the %pair is assigned from __obj. + * + * Insertion requires amortized constant time. + */ + template + pair + insert_or_assign(const key_type& __k, _Obj&& __obj) + { + iterator __i = find(__k); + if (__i == end()) + { + __i = emplace(std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple(std::forward<_Obj>(__obj))) + .first; + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } + + // move-capable overload + template + pair + insert_or_assign(key_type&& __k, _Obj&& __obj) + { + iterator __i = find(__k); + if (__i == end()) + { + __i = emplace(std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple(std::forward<_Obj>(__obj))) + .first; + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } + + /** + * @brief Attempts to insert a std::pair into the %unordered_map. + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __k Key to use for finding a possibly existing pair in + * the unordered_map. + * @param __obj Argument used to generate the .second for a pair + * instance. + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument insert() + * does. + * If the %pair was already in the %unordered map, the .second of + * the %pair is assigned from __obj. + * Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + template + iterator + insert_or_assign(const_iterator __hint, const key_type& __k, + _Obj&& __obj) + { + iterator __i = find(__k); + if (__i == end()) + { + return emplace_hint(__hint, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } + + // move-capable overload + template + iterator + insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) + { + iterator __i = find(__k); + if (__i == end()) + { + return emplace_hint(__hint, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } +#endif + + //@{ + /** + * @brief Erases an element from an %unordered_map. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from an %unordered_map. + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __position) + { return _M_h.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_h.erase(__position); } + //@} + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * an %unordered_map. For an %unordered_map the result of this function + * can only be 0 (not present) or 1 (present). + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_h.erase(__x); } + + /** + * @brief Erases a [__first,__last) range of elements from an + * %unordered_map. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from an %unordered_map. + * Note that this function only erases the elements, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_h.erase(__first, __last); } + + /** + * Erases all elements in an %unordered_map. + * Note that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + clear() noexcept + { _M_h.clear(); } + + /** + * @brief Swaps data with another %unordered_map. + * @param __x An %unordered_map of the same element and allocator + * types. + * + * This exchanges the elements between two %unordered_map in constant + * time. + * Note that the global std::swap() function is specialized such that + * std::swap(m1,m2) will feed to this function. + */ + void + swap(unordered_map& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) + { _M_h.swap(__x._M_h); } + +#if __cplusplus > 201402L + template + friend class std::_Hash_merge_helper; + + template + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + + // observers. + + /// Returns the hash functor object with which the %unordered_map was + /// constructed. + hasher + hash_function() const + { return _M_h.hash_function(); } + + /// Returns the key comparison object with which the %unordered_map was + /// constructed. + key_equal + key_eq() const + { return _M_h.key_eq(); } + + // lookup. + + //@{ + /** + * @brief Tries to locate an element in an %unordered_map. + * @param __x Key to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_h.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_h.find(__x); } + //@} + + /** + * @brief Finds the number of elements. + * @param __x Key to count. + * @return Number of elements with specified key. + * + * This function only makes sense for %unordered_multimap; for + * %unordered_map the result will either be 0 (not present) or 1 + * (present). + */ + size_type + count(const key_type& __x) const + { return _M_h.count(__x); } + +#if __cplusplus > 201703L + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_h.find(__x) != _M_h.end(); } +#endif + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function probably only makes sense for %unordered_multimap. + */ + std::pair + equal_range(const key_type& __x) + { return _M_h.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_h.equal_range(__x); } + //@} + + //@{ + /** + * @brief Subscript ( @c [] ) access to %unordered_map data. + * @param __k The key for which data should be retrieved. + * @return A reference to the data of the (key,data) %pair. + * + * Allows for easy lookup with the subscript ( @c [] )operator. Returns + * data associated with the key specified in subscript. If the key does + * not exist, a pair with that key is created using default values, which + * is then returned. + * + * Lookup requires constant time. + */ + mapped_type& + operator[](const key_type& __k) + { return _M_h[__k]; } + + mapped_type& + operator[](key_type&& __k) + { return _M_h[std::move(__k)]; } + //@} + + //@{ + /** + * @brief Access to %unordered_map data. + * @param __k The key for which data should be retrieved. + * @return A reference to the data whose key is equal to @a __k, if + * such a data is present in the %unordered_map. + * @throw std::out_of_range If no such data is present. + */ + mapped_type& + at(const key_type& __k) + { return _M_h.at(__k); } + + const mapped_type& + at(const key_type& __k) const + { return _M_h.at(__k); } + //@} + + // bucket interface. + + /// Returns the number of buckets of the %unordered_map. + size_type + bucket_count() const noexcept + { return _M_h.bucket_count(); } + + /// Returns the maximum number of buckets of the %unordered_map. + size_type + max_bucket_count() const noexcept + { return _M_h.max_bucket_count(); } + + /* + * @brief Returns the number of elements in a given bucket. + * @param __n A bucket index. + * @return The number of elements in the bucket. + */ + size_type + bucket_size(size_type __n) const + { return _M_h.bucket_size(__n); } + + /* + * @brief Returns the bucket index of a given element. + * @param __key A key instance. + * @return The key bucket index. + */ + size_type + bucket(const key_type& __key) const + { return _M_h.bucket(__key); } + + /** + * @brief Returns a read/write iterator pointing to the first bucket + * element. + * @param __n The bucket index. + * @return A read/write local iterator. + */ + local_iterator + begin(size_type __n) + { return _M_h.begin(__n); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to the first + * bucket element. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + const_local_iterator + begin(size_type __n) const + { return _M_h.begin(__n); } + + const_local_iterator + cbegin(size_type __n) const + { return _M_h.cbegin(__n); } + //@} + + /** + * @brief Returns a read/write iterator pointing to one past the last + * bucket elements. + * @param __n The bucket index. + * @return A read/write local iterator. + */ + local_iterator + end(size_type __n) + { return _M_h.end(__n); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to one past + * the last bucket elements. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + const_local_iterator + end(size_type __n) const + { return _M_h.end(__n); } + + const_local_iterator + cend(size_type __n) const + { return _M_h.cend(__n); } + //@} + + // hash policy. + + /// Returns the average number of elements per bucket. + float + load_factor() const noexcept + { return _M_h.load_factor(); } + + /// Returns a positive number that the %unordered_map tries to keep the + /// load factor less than or equal to. + float + max_load_factor() const noexcept + { return _M_h.max_load_factor(); } + + /** + * @brief Change the %unordered_map maximum load factor. + * @param __z The new maximum load factor. + */ + void + max_load_factor(float __z) + { _M_h.max_load_factor(__z); } + + /** + * @brief May rehash the %unordered_map. + * @param __n The new number of buckets. + * + * Rehash will occur only if the new number of buckets respect the + * %unordered_map maximum load factor. + */ + void + rehash(size_type __n) + { _M_h.rehash(__n); } + + /** + * @brief Prepare the %unordered_map for a specified number of + * elements. + * @param __n Number of elements required. + * + * Same as rehash(ceil(n / max_load_factor())). + */ + void + reserve(size_type __n) + { _M_h.reserve(__n); } + + template + friend bool + operator==(const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&, + const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&); + }; + +#if __cpp_deduction_guides >= 201606 + + template>, + typename _Pred = equal_to<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + _Hash, _Pred, _Allocator>; + + template, + typename _Pred = equal_to<_Key>, + typename _Allocator = allocator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list>, + typename unordered_map::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<_Key, _Tp, _Hash, _Pred, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map::size_type, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, + _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, + _Allocator>; + + template, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map::size_type, + _Hash, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template> + unordered_map(initializer_list>, + typename unordered_map::size_type, + _Allocator) + -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template> + unordered_map(initializer_list>, _Allocator) + -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list>, + typename unordered_map::size_type, + _Hash, _Allocator) + -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; + +#endif + + /** + * @brief A standard container composed of equivalent keys + * (possibly containing multiple of each key value) that associates + * values of another type with the keys. + * + * @ingroup unordered_associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Pred Predicate function object type, defaults + * to equal_to<_Value>. + * @tparam _Alloc Allocator type, defaults to + * std::allocator>. + * + * Meets the requirements of a container, and + * unordered associative container + * + * The resulting value type of the container is std::pair. + * + * Base is _Hashtable, dispatched at compile time via template + * alias __ummap_hashtable. + */ + template, + typename _Pred = equal_to<_Key>, + typename _Alloc = allocator>> + class unordered_multimap + { + typedef __ummap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable; + _Hashtable _M_h; + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef typename _Hashtable::key_type key_type; + typedef typename _Hashtable::value_type value_type; + typedef typename _Hashtable::mapped_type mapped_type; + typedef typename _Hashtable::hasher hasher; + typedef typename _Hashtable::key_equal key_equal; + typedef typename _Hashtable::allocator_type allocator_type; + //@} + + //@{ + /// Iterator-related typedefs. + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; + typedef typename _Hashtable::iterator iterator; + typedef typename _Hashtable::const_iterator const_iterator; + typedef typename _Hashtable::local_iterator local_iterator; + typedef typename _Hashtable::const_local_iterator const_local_iterator; + typedef typename _Hashtable::size_type size_type; + typedef typename _Hashtable::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; +#endif + + //construct/destroy/copy + + /// Default constructor. + unordered_multimap() = default; + + /** + * @brief Default constructor creates no elements. + * @param __n Mnimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + */ + explicit + unordered_multimap(size_type __n, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__n, __hf, __eql, __a) + { } + + /** + * @brief Builds an %unordered_multimap from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_multimap consisting of copies of the elements + * from [__first,__last). This is linear in N (where N is + * distance(__first,__last)). + */ + template + unordered_multimap(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__first, __last, __n, __hf, __eql, __a) + { } + + /// Copy constructor. + unordered_multimap(const unordered_multimap&) = default; + + /// Move constructor. + unordered_multimap(unordered_multimap&&) = default; + + /** + * @brief Creates an %unordered_multimap with no elements. + * @param __a An allocator object. + */ + explicit + unordered_multimap(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_multimap to copy. + * @param __a An allocator object. + */ + unordered_multimap(const unordered_multimap& __ummap, + const allocator_type& __a) + : _M_h(__ummap._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_multimap to move. + * @param __a An allocator object. + */ + unordered_multimap(unordered_multimap&& __ummap, + const allocator_type& __a) + : _M_h(std::move(__ummap._M_h), __a) + { } + + /** + * @brief Builds an %unordered_multimap from an initializer_list. + * @param __l An initializer_list. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_multimap consisting of copies of the elements in + * the list. This is linear in N (where N is @a __l.size()). + */ + unordered_multimap(initializer_list __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__l, __n, __hf, __eql, __a) + { } + + unordered_multimap(size_type __n, const allocator_type& __a) + : unordered_multimap(__n, hasher(), key_equal(), __a) + { } + + unordered_multimap(size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multimap(__n, __hf, key_equal(), __a) + { } + + template + unordered_multimap(_InputIterator __first, _InputIterator __last, + size_type __n, + const allocator_type& __a) + : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a) + { } + + template + unordered_multimap(_InputIterator __first, _InputIterator __last, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) + { } + + unordered_multimap(initializer_list __l, + size_type __n, + const allocator_type& __a) + : unordered_multimap(__l, __n, hasher(), key_equal(), __a) + { } + + unordered_multimap(initializer_list __l, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multimap(__l, __n, __hf, key_equal(), __a) + { } + + /// Copy assignment operator. + unordered_multimap& + operator=(const unordered_multimap&) = default; + + /// Move assignment operator. + unordered_multimap& + operator=(unordered_multimap&&) = default; + + /** + * @brief %Unordered_multimap list assignment operator. + * @param __l An initializer_list. + * + * This function fills an %unordered_multimap with copies of the + * elements in the initializer list @a __l. + * + * Note that the assignment completely changes the %unordered_multimap + * and that the resulting %unordered_multimap's size is the same as the + * number of elements assigned. + */ + unordered_multimap& + operator=(initializer_list __l) + { + _M_h = __l; + return *this; + } + + /// Returns the allocator object used by the %unordered_multimap. + allocator_type + get_allocator() const noexcept + { return _M_h.get_allocator(); } + + // size and capacity: + + /// Returns true if the %unordered_multimap is empty. + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return _M_h.empty(); } + + /// Returns the size of the %unordered_multimap. + size_type + size() const noexcept + { return _M_h.size(); } + + /// Returns the maximum size of the %unordered_multimap. + size_type + max_size() const noexcept + { return _M_h.max_size(); } + + // iterators. + + /** + * Returns a read/write iterator that points to the first element in the + * %unordered_multimap. + */ + iterator + begin() noexcept + { return _M_h.begin(); } + + //@{ + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_multimap. + */ + const_iterator + begin() const noexcept + { return _M_h.begin(); } + + const_iterator + cbegin() const noexcept + { return _M_h.begin(); } + //@} + + /** + * Returns a read/write iterator that points one past the last element in + * the %unordered_multimap. + */ + iterator + end() noexcept + { return _M_h.end(); } + + //@{ + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_multimap. + */ + const_iterator + end() const noexcept + { return _M_h.end(); } + + const_iterator + cend() const noexcept + { return _M_h.end(); } + //@} + + // modifiers. + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_multimap. + * + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * + * @return An iterator that points to the inserted pair. + * + * This function attempts to build and insert a (key, value) %pair into + * the %unordered_multimap. + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace(_Args&&... __args) + { return _M_h.emplace(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_multimap. + * + * @param __pos An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * @return An iterator that points to the element with key of the + * std::pair built from @a __args. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } + + //@{ + /** + * @brief Inserts a std::pair into the %unordered_multimap. + * @param __x Pair to be inserted (see std::make_pair for easy + * creation of pairs). + * + * @return An iterator that points to the inserted pair. + * + * Insertion requires amortized constant time. + */ + iterator + insert(const value_type& __x) + { return _M_h.insert(__x); } + + iterator + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(_Pair&& __x) + { return _M_h.emplace(std::forward<_Pair>(__x)); } + //@} + + //@{ + /** + * @brief Inserts a std::pair into the %unordered_multimap. + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + iterator + insert(const_iterator __hint, const value_type& __x) + { return _M_h.insert(__hint, __x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(const_iterator __hint, _Pair&& __x) + { return _M_h.emplace_hint(__hint, std::forward<_Pair>(__x)); } + //@} + + /** + * @brief A template function that attempts to insert a range of + * elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_h.insert(__first, __last); } + + /** + * @brief Attempts to insert a list of elements into the + * %unordered_multimap. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { _M_h.insert(__l); } + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } +#endif // C++17 + + //@{ + /** + * @brief Erases an element from an %unordered_multimap. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from an %unordered_multimap. + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __position) + { return _M_h.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_h.erase(__position); } + //@} + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of elements to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * an %unordered_multimap. + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_h.erase(__x); } + + /** + * @brief Erases a [__first,__last) range of elements from an + * %unordered_multimap. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from an + * %unordered_multimap. + * Note that this function only erases the elements, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_h.erase(__first, __last); } + + /** + * Erases all elements in an %unordered_multimap. + * Note that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + clear() noexcept + { _M_h.clear(); } + + /** + * @brief Swaps data with another %unordered_multimap. + * @param __x An %unordered_multimap of the same element and allocator + * types. + * + * This exchanges the elements between two %unordered_multimap in + * constant time. + * Note that the global std::swap() function is specialized such that + * std::swap(m1,m2) will feed to this function. + */ + void + swap(unordered_multimap& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) + { _M_h.swap(__x._M_h); } + +#if __cplusplus > 201402L + template + friend class std::_Hash_merge_helper; + + template + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + + // observers. + + /// Returns the hash functor object with which the %unordered_multimap + /// was constructed. + hasher + hash_function() const + { return _M_h.hash_function(); } + + /// Returns the key comparison object with which the %unordered_multimap + /// was constructed. + key_equal + key_eq() const + { return _M_h.key_eq(); } + + // lookup. + + //@{ + /** + * @brief Tries to locate an element in an %unordered_multimap. + * @param __x Key to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_h.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_h.find(__x); } + //@} + + /** + * @brief Finds the number of elements. + * @param __x Key to count. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const + { return _M_h.count(__x); } + +#if __cplusplus > 201703L + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_h.find(__x) != _M_h.end(); } +#endif + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + */ + std::pair + equal_range(const key_type& __x) + { return _M_h.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_h.equal_range(__x); } + //@} + + // bucket interface. + + /// Returns the number of buckets of the %unordered_multimap. + size_type + bucket_count() const noexcept + { return _M_h.bucket_count(); } + + /// Returns the maximum number of buckets of the %unordered_multimap. + size_type + max_bucket_count() const noexcept + { return _M_h.max_bucket_count(); } + + /* + * @brief Returns the number of elements in a given bucket. + * @param __n A bucket index. + * @return The number of elements in the bucket. + */ + size_type + bucket_size(size_type __n) const + { return _M_h.bucket_size(__n); } + + /* + * @brief Returns the bucket index of a given element. + * @param __key A key instance. + * @return The key bucket index. + */ + size_type + bucket(const key_type& __key) const + { return _M_h.bucket(__key); } + + /** + * @brief Returns a read/write iterator pointing to the first bucket + * element. + * @param __n The bucket index. + * @return A read/write local iterator. + */ + local_iterator + begin(size_type __n) + { return _M_h.begin(__n); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to the first + * bucket element. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + const_local_iterator + begin(size_type __n) const + { return _M_h.begin(__n); } + + const_local_iterator + cbegin(size_type __n) const + { return _M_h.cbegin(__n); } + //@} + + /** + * @brief Returns a read/write iterator pointing to one past the last + * bucket elements. + * @param __n The bucket index. + * @return A read/write local iterator. + */ + local_iterator + end(size_type __n) + { return _M_h.end(__n); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to one past + * the last bucket elements. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + const_local_iterator + end(size_type __n) const + { return _M_h.end(__n); } + + const_local_iterator + cend(size_type __n) const + { return _M_h.cend(__n); } + //@} + + // hash policy. + + /// Returns the average number of elements per bucket. + float + load_factor() const noexcept + { return _M_h.load_factor(); } + + /// Returns a positive number that the %unordered_multimap tries to keep + /// the load factor less than or equal to. + float + max_load_factor() const noexcept + { return _M_h.max_load_factor(); } + + /** + * @brief Change the %unordered_multimap maximum load factor. + * @param __z The new maximum load factor. + */ + void + max_load_factor(float __z) + { _M_h.max_load_factor(__z); } + + /** + * @brief May rehash the %unordered_multimap. + * @param __n The new number of buckets. + * + * Rehash will occur only if the new number of buckets respect the + * %unordered_multimap maximum load factor. + */ + void + rehash(size_type __n) + { _M_h.rehash(__n); } + + /** + * @brief Prepare the %unordered_multimap for a specified number of + * elements. + * @param __n Number of elements required. + * + * Same as rehash(ceil(n / max_load_factor())). + */ + void + reserve(size_type __n) + { _M_h.reserve(__n); } + + template + friend bool + operator==(const unordered_multimap<_Key1, _Tp1, + _Hash1, _Pred1, _Alloc1>&, + const unordered_multimap<_Key1, _Tp1, + _Hash1, _Pred1, _Alloc1>&); + }; + +#if __cpp_deduction_guides >= 201606 + + template>, + typename _Pred = equal_to<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, _Pred, + _Allocator>; + + template, + typename _Pred = equal_to<_Key>, + typename _Allocator = allocator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list>, + unordered_multimap::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap::size_type, _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap::size_type, _Hash, + _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template> + unordered_multimap(initializer_list>, + unordered_multimap::size_type, + _Allocator) + -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template> + unordered_multimap(initializer_list>, _Allocator) + -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list>, + unordered_multimap::size_type, + _Hash, _Allocator) + -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; + +#endif + + template + inline void + swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + inline void + swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + inline bool + operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return __x._M_h._M_equal(__y._M_h); } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline bool + operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } +#endif + + template + inline bool + operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return __x._M_h._M_equal(__y._M_h); } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline bool + operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } +#endif + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::unordered_map access to internals of compatible maps. + template + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template + using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>; + template + using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>; + + friend unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + + static auto& + _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + }; + + // Allow std::unordered_multimap access to internals of compatible maps. + template + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template + using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>; + template + using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>; + + friend unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + + static auto& + _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _UNORDERED_MAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/unordered_set.h b/resources/sources/avr-libstdcpp/include/bits/unordered_set.h new file mode 100644 index 000000000..c9c9e9f38 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/unordered_set.h @@ -0,0 +1,1783 @@ +// unordered_set implementation -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unordered_set.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{unordered_set} + */ + +#ifndef _UNORDERED_SET_H +#define _UNORDERED_SET_H + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /// Base types for unordered_set. + template + using __uset_traits = __detail::_Hashtable_traits<_Cache, true, true>; + + template, + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value>, + typename _Tr = __uset_traits<__cache_default<_Value, _Hash>::value>> + using __uset_hashtable = _Hashtable<_Value, _Value, _Alloc, + __detail::_Identity, _Pred, _Hash, + __detail::_Mod_range_hashing, + __detail::_Default_ranged_hash, + __detail::_Prime_rehash_policy, _Tr>; + + /// Base types for unordered_multiset. + template + using __umset_traits = __detail::_Hashtable_traits<_Cache, true, false>; + + template, + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value>, + typename _Tr = __umset_traits<__cache_default<_Value, _Hash>::value>> + using __umset_hashtable = _Hashtable<_Value, _Value, _Alloc, + __detail::_Identity, + _Pred, _Hash, + __detail::_Mod_range_hashing, + __detail::_Default_ranged_hash, + __detail::_Prime_rehash_policy, _Tr>; + + template + class unordered_multiset; + + /** + * @brief A standard container composed of unique keys (containing + * at most one of each key value) in which the elements' keys are + * the elements themselves. + * + * @ingroup unordered_associative_containers + * + * @tparam _Value Type of key objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + + * @tparam _Pred Predicate function object type, defaults to + * equal_to<_Value>. + * + * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * + * Meets the requirements of a container, and + * unordered associative container + * + * Base is _Hashtable, dispatched at compile time via template + * alias __uset_hashtable. + */ + template, + typename _Pred = equal_to<_Value>, + typename _Alloc = allocator<_Value>> + class unordered_set + { + typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; + _Hashtable _M_h; + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef typename _Hashtable::key_type key_type; + typedef typename _Hashtable::value_type value_type; + typedef typename _Hashtable::hasher hasher; + typedef typename _Hashtable::key_equal key_equal; + typedef typename _Hashtable::allocator_type allocator_type; + //@} + + //@{ + /// Iterator-related typedefs. + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; + typedef typename _Hashtable::iterator iterator; + typedef typename _Hashtable::const_iterator const_iterator; + typedef typename _Hashtable::local_iterator local_iterator; + typedef typename _Hashtable::const_local_iterator const_local_iterator; + typedef typename _Hashtable::size_type size_type; + typedef typename _Hashtable::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; + using insert_return_type = typename _Hashtable::insert_return_type; +#endif + + // construct/destroy/copy + + /// Default constructor. + unordered_set() = default; + + /** + * @brief Default constructor creates no elements. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + */ + explicit + unordered_set(size_type __n, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__n, __hf, __eql, __a) + { } + + /** + * @brief Builds an %unordered_set from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_set consisting of copies of the elements from + * [__first,__last). This is linear in N (where N is + * distance(__first,__last)). + */ + template + unordered_set(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__first, __last, __n, __hf, __eql, __a) + { } + + /// Copy constructor. + unordered_set(const unordered_set&) = default; + + /// Move constructor. + unordered_set(unordered_set&&) = default; + + /** + * @brief Creates an %unordered_set with no elements. + * @param __a An allocator object. + */ + explicit + unordered_set(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_set to copy. + * @param __a An allocator object. + */ + unordered_set(const unordered_set& __uset, + const allocator_type& __a) + : _M_h(__uset._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_set to move. + * @param __a An allocator object. + */ + unordered_set(unordered_set&& __uset, + const allocator_type& __a) + : _M_h(std::move(__uset._M_h), __a) + { } + + /** + * @brief Builds an %unordered_set from an initializer_list. + * @param __l An initializer_list. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_set consisting of copies of the elements in the + * list. This is linear in N (where N is @a __l.size()). + */ + unordered_set(initializer_list __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__l, __n, __hf, __eql, __a) + { } + + unordered_set(size_type __n, const allocator_type& __a) + : unordered_set(__n, hasher(), key_equal(), __a) + { } + + unordered_set(size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_set(__n, __hf, key_equal(), __a) + { } + + template + unordered_set(_InputIterator __first, _InputIterator __last, + size_type __n, + const allocator_type& __a) + : unordered_set(__first, __last, __n, hasher(), key_equal(), __a) + { } + + template + unordered_set(_InputIterator __first, _InputIterator __last, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_set(__first, __last, __n, __hf, key_equal(), __a) + { } + + unordered_set(initializer_list __l, + size_type __n, + const allocator_type& __a) + : unordered_set(__l, __n, hasher(), key_equal(), __a) + { } + + unordered_set(initializer_list __l, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_set(__l, __n, __hf, key_equal(), __a) + { } + + /// Copy assignment operator. + unordered_set& + operator=(const unordered_set&) = default; + + /// Move assignment operator. + unordered_set& + operator=(unordered_set&&) = default; + + /** + * @brief %Unordered_set list assignment operator. + * @param __l An initializer_list. + * + * This function fills an %unordered_set with copies of the elements in + * the initializer list @a __l. + * + * Note that the assignment completely changes the %unordered_set and + * that the resulting %unordered_set's size is the same as the number + * of elements assigned. + */ + unordered_set& + operator=(initializer_list __l) + { + _M_h = __l; + return *this; + } + + /// Returns the allocator object used by the %unordered_set. + allocator_type + get_allocator() const noexcept + { return _M_h.get_allocator(); } + + // size and capacity: + + /// Returns true if the %unordered_set is empty. + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return _M_h.empty(); } + + /// Returns the size of the %unordered_set. + size_type + size() const noexcept + { return _M_h.size(); } + + /// Returns the maximum size of the %unordered_set. + size_type + max_size() const noexcept + { return _M_h.max_size(); } + + // iterators. + + //@{ + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_set. + */ + iterator + begin() noexcept + { return _M_h.begin(); } + + const_iterator + begin() const noexcept + { return _M_h.begin(); } + //@} + + //@{ + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_set. + */ + iterator + end() noexcept + { return _M_h.end(); } + + const_iterator + end() const noexcept + { return _M_h.end(); } + //@} + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_set. + */ + const_iterator + cbegin() const noexcept + { return _M_h.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_set. + */ + const_iterator + cend() const noexcept + { return _M_h.end(); } + + // modifiers. + + /** + * @brief Attempts to build and insert an element into the + * %unordered_set. + * @param __args Arguments used to generate an element. + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted element, and the second is a bool + * that is true if the element was actually inserted. + * + * This function attempts to build and insert an element into the + * %unordered_set. An %unordered_set relies on unique keys and thus an + * element is only inserted if it is not already present in the + * %unordered_set. + * + * Insertion requires amortized constant time. + */ + template + std::pair + emplace(_Args&&... __args) + { return _M_h.emplace(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to insert an element into the %unordered_set. + * @param __pos An iterator that serves as a hint as to where the + * element should be inserted. + * @param __args Arguments used to generate the element to be + * inserted. + * @return An iterator that points to the element with key equivalent to + * the one generated from @a __args (may or may not be the + * element itself). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } + + //@{ + /** + * @brief Attempts to insert an element into the %unordered_set. + * @param __x Element to be inserted. + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted element, and the second is a bool + * that is true if the element was actually inserted. + * + * This function attempts to insert an element into the %unordered_set. + * An %unordered_set relies on unique keys and thus an element is only + * inserted if it is not already present in the %unordered_set. + * + * Insertion requires amortized constant time. + */ + std::pair + insert(const value_type& __x) + { return _M_h.insert(__x); } + + std::pair + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + //@} + + //@{ + /** + * @brief Attempts to insert an element into the %unordered_set. + * @param __hint An iterator that serves as a hint as to where the + * element should be inserted. + * @param __x Element to be inserted. + * @return An iterator that points to the element with key of + * @a __x (may or may not be the element passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument insert() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires amortized constant. + */ + iterator + insert(const_iterator __hint, const value_type& __x) + { return _M_h.insert(__hint, __x); } + + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + //@} + + /** + * @brief A template function that attempts to insert a range of + * elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_h.insert(__first, __last); } + + /** + * @brief Attempts to insert a list of elements into the %unordered_set. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { _M_h.insert(__l); } + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator, node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)).position; } +#endif // C++17 + + //@{ + /** + * @brief Erases an element from an %unordered_set. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from an %unordered_set. Note that this function only erases the + * element, and that if the element is itself a pointer, the pointed-to + * memory is not touched in any way. Managing the pointer is the user's + * responsibility. + */ + iterator + erase(const_iterator __position) + { return _M_h.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_h.erase(__position); } + //@} + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * an %unordered_set. For an %unordered_set the result of this function + * can only be 0 (not present) or 1 (present). + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_h.erase(__x); } + + /** + * @brief Erases a [__first,__last) range of elements from an + * %unordered_set. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from an %unordered_set. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_h.erase(__first, __last); } + + /** + * Erases all elements in an %unordered_set. Note that this function only + * erases the elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + void + clear() noexcept + { _M_h.clear(); } + + /** + * @brief Swaps data with another %unordered_set. + * @param __x An %unordered_set of the same element and allocator + * types. + * + * This exchanges the elements between two sets in constant time. + * Note that the global std::swap() function is specialized such that + * std::swap(s1,s2) will feed to this function. + */ + void + swap(unordered_set& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) + { _M_h.swap(__x._M_h); } + +#if __cplusplus > 201402L + template + friend class std::_Hash_merge_helper; + + template + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + + // observers. + + /// Returns the hash functor object with which the %unordered_set was + /// constructed. + hasher + hash_function() const + { return _M_h.hash_function(); } + + /// Returns the key comparison object with which the %unordered_set was + /// constructed. + key_equal + key_eq() const + { return _M_h.key_eq(); } + + // lookup. + + //@{ + /** + * @brief Tries to locate an element in an %unordered_set. + * @param __x Element to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_h.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_h.find(__x); } + //@} + + /** + * @brief Finds the number of elements. + * @param __x Element to located. + * @return Number of elements with specified key. + * + * This function only makes sense for unordered_multisets; for + * unordered_set the result will either be 0 (not present) or 1 + * (present). + */ + size_type + count(const key_type& __x) const + { return _M_h.count(__x); } + +#if __cplusplus > 201703L + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_h.find(__x) != _M_h.end(); } +#endif + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function probably only makes sense for multisets. + */ + std::pair + equal_range(const key_type& __x) + { return _M_h.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_h.equal_range(__x); } + //@} + + // bucket interface. + + /// Returns the number of buckets of the %unordered_set. + size_type + bucket_count() const noexcept + { return _M_h.bucket_count(); } + + /// Returns the maximum number of buckets of the %unordered_set. + size_type + max_bucket_count() const noexcept + { return _M_h.max_bucket_count(); } + + /* + * @brief Returns the number of elements in a given bucket. + * @param __n A bucket index. + * @return The number of elements in the bucket. + */ + size_type + bucket_size(size_type __n) const + { return _M_h.bucket_size(__n); } + + /* + * @brief Returns the bucket index of a given element. + * @param __key A key instance. + * @return The key bucket index. + */ + size_type + bucket(const key_type& __key) const + { return _M_h.bucket(__key); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to the first + * bucket element. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + local_iterator + begin(size_type __n) + { return _M_h.begin(__n); } + + const_local_iterator + begin(size_type __n) const + { return _M_h.begin(__n); } + + const_local_iterator + cbegin(size_type __n) const + { return _M_h.cbegin(__n); } + //@} + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to one past + * the last bucket elements. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + local_iterator + end(size_type __n) + { return _M_h.end(__n); } + + const_local_iterator + end(size_type __n) const + { return _M_h.end(__n); } + + const_local_iterator + cend(size_type __n) const + { return _M_h.cend(__n); } + //@} + + // hash policy. + + /// Returns the average number of elements per bucket. + float + load_factor() const noexcept + { return _M_h.load_factor(); } + + /// Returns a positive number that the %unordered_set tries to keep the + /// load factor less than or equal to. + float + max_load_factor() const noexcept + { return _M_h.max_load_factor(); } + + /** + * @brief Change the %unordered_set maximum load factor. + * @param __z The new maximum load factor. + */ + void + max_load_factor(float __z) + { _M_h.max_load_factor(__z); } + + /** + * @brief May rehash the %unordered_set. + * @param __n The new number of buckets. + * + * Rehash will occur only if the new number of buckets respect the + * %unordered_set maximum load factor. + */ + void + rehash(size_type __n) + { _M_h.rehash(__n); } + + /** + * @brief Prepare the %unordered_set for a specified number of + * elements. + * @param __n Number of elements required. + * + * Same as rehash(ceil(n / max_load_factor())). + */ + void + reserve(size_type __n) + { _M_h.reserve(__n); } + + template + friend bool + operator==(const unordered_set<_Value1, _Hash1, _Pred1, _Alloc1>&, + const unordered_set<_Value1, _Hash1, _Pred1, _Alloc1>&); + }; + +#if __cpp_deduction_guides >= 201606 + + template::value_type>, + typename _Pred = + equal_to::value_type>, + typename _Allocator = + allocator::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set::value_type, + _Hash, _Pred, _Allocator>; + + template, + typename _Pred = equal_to<_Tp>, + typename _Allocator = allocator<_Tp>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set::size_type, _Allocator) + -> unordered_set::value_type, + hash< + typename iterator_traits<_InputIterator>::value_type>, + equal_to< + typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set::size_type, + _Hash, _Allocator) + -> unordered_set::value_type, + _Hash, + equal_to< + typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template> + unordered_set(initializer_list<_Tp>, + unordered_set::size_type, _Allocator) + -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set::size_type, _Hash, _Allocator) + -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; + +#endif + + /** + * @brief A standard container composed of equivalent keys + * (possibly containing multiple of each key value) in which the + * elements' keys are the elements themselves. + * + * @ingroup unordered_associative_containers + * + * @tparam _Value Type of key objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Pred Predicate function object type, defaults + * to equal_to<_Value>. + * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * + * Meets the requirements of a container, and + * unordered associative container + * + * Base is _Hashtable, dispatched at compile time via template + * alias __umset_hashtable. + */ + template, + typename _Pred = equal_to<_Value>, + typename _Alloc = allocator<_Value>> + class unordered_multiset + { + typedef __umset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; + _Hashtable _M_h; + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef typename _Hashtable::key_type key_type; + typedef typename _Hashtable::value_type value_type; + typedef typename _Hashtable::hasher hasher; + typedef typename _Hashtable::key_equal key_equal; + typedef typename _Hashtable::allocator_type allocator_type; + //@} + + //@{ + /// Iterator-related typedefs. + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; + typedef typename _Hashtable::iterator iterator; + typedef typename _Hashtable::const_iterator const_iterator; + typedef typename _Hashtable::local_iterator local_iterator; + typedef typename _Hashtable::const_local_iterator const_local_iterator; + typedef typename _Hashtable::size_type size_type; + typedef typename _Hashtable::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; +#endif + + // construct/destroy/copy + + /// Default constructor. + unordered_multiset() = default; + + /** + * @brief Default constructor creates no elements. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + */ + explicit + unordered_multiset(size_type __n, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__n, __hf, __eql, __a) + { } + + /** + * @brief Builds an %unordered_multiset from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_multiset consisting of copies of the elements + * from [__first,__last). This is linear in N (where N is + * distance(__first,__last)). + */ + template + unordered_multiset(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__first, __last, __n, __hf, __eql, __a) + { } + + /// Copy constructor. + unordered_multiset(const unordered_multiset&) = default; + + /// Move constructor. + unordered_multiset(unordered_multiset&&) = default; + + /** + * @brief Builds an %unordered_multiset from an initializer_list. + * @param __l An initializer_list. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_multiset consisting of copies of the elements in + * the list. This is linear in N (where N is @a __l.size()). + */ + unordered_multiset(initializer_list __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__l, __n, __hf, __eql, __a) + { } + + /// Copy assignment operator. + unordered_multiset& + operator=(const unordered_multiset&) = default; + + /// Move assignment operator. + unordered_multiset& + operator=(unordered_multiset&&) = default; + + /** + * @brief Creates an %unordered_multiset with no elements. + * @param __a An allocator object. + */ + explicit + unordered_multiset(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_multiset to copy. + * @param __a An allocator object. + */ + unordered_multiset(const unordered_multiset& __umset, + const allocator_type& __a) + : _M_h(__umset._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __umset Input %unordered_multiset to move. + * @param __a An allocator object. + */ + unordered_multiset(unordered_multiset&& __umset, + const allocator_type& __a) + : _M_h(std::move(__umset._M_h), __a) + { } + + unordered_multiset(size_type __n, const allocator_type& __a) + : unordered_multiset(__n, hasher(), key_equal(), __a) + { } + + unordered_multiset(size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multiset(__n, __hf, key_equal(), __a) + { } + + template + unordered_multiset(_InputIterator __first, _InputIterator __last, + size_type __n, + const allocator_type& __a) + : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a) + { } + + template + unordered_multiset(_InputIterator __first, _InputIterator __last, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a) + { } + + unordered_multiset(initializer_list __l, + size_type __n, + const allocator_type& __a) + : unordered_multiset(__l, __n, hasher(), key_equal(), __a) + { } + + unordered_multiset(initializer_list __l, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multiset(__l, __n, __hf, key_equal(), __a) + { } + + /** + * @brief %Unordered_multiset list assignment operator. + * @param __l An initializer_list. + * + * This function fills an %unordered_multiset with copies of the elements + * in the initializer list @a __l. + * + * Note that the assignment completely changes the %unordered_multiset + * and that the resulting %unordered_multiset's size is the same as the + * number of elements assigned. + */ + unordered_multiset& + operator=(initializer_list __l) + { + _M_h = __l; + return *this; + } + + /// Returns the allocator object used by the %unordered_multiset. + allocator_type + get_allocator() const noexcept + { return _M_h.get_allocator(); } + + // size and capacity: + + /// Returns true if the %unordered_multiset is empty. + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return _M_h.empty(); } + + /// Returns the size of the %unordered_multiset. + size_type + size() const noexcept + { return _M_h.size(); } + + /// Returns the maximum size of the %unordered_multiset. + size_type + max_size() const noexcept + { return _M_h.max_size(); } + + // iterators. + + //@{ + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_multiset. + */ + iterator + begin() noexcept + { return _M_h.begin(); } + + const_iterator + begin() const noexcept + { return _M_h.begin(); } + //@} + + //@{ + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_multiset. + */ + iterator + end() noexcept + { return _M_h.end(); } + + const_iterator + end() const noexcept + { return _M_h.end(); } + //@} + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_multiset. + */ + const_iterator + cbegin() const noexcept + { return _M_h.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_multiset. + */ + const_iterator + cend() const noexcept + { return _M_h.end(); } + + // modifiers. + + /** + * @brief Builds and insert an element into the %unordered_multiset. + * @param __args Arguments used to generate an element. + * @return An iterator that points to the inserted element. + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace(_Args&&... __args) + { return _M_h.emplace(std::forward<_Args>(__args)...); } + + /** + * @brief Inserts an element into the %unordered_multiset. + * @param __pos An iterator that serves as a hint as to where the + * element should be inserted. + * @param __args Arguments used to generate the element to be + * inserted. + * @return An iterator that points to the inserted element. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } + + //@{ + /** + * @brief Inserts an element into the %unordered_multiset. + * @param __x Element to be inserted. + * @return An iterator that points to the inserted element. + * + * Insertion requires amortized constant time. + */ + iterator + insert(const value_type& __x) + { return _M_h.insert(__x); } + + iterator + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + //@} + + //@{ + /** + * @brief Inserts an element into the %unordered_multiset. + * @param __hint An iterator that serves as a hint as to where the + * element should be inserted. + * @param __x Element to be inserted. + * @return An iterator that points to the inserted element. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires amortized constant. + */ + iterator + insert(const_iterator __hint, const value_type& __x) + { return _M_h.insert(__hint, __x); } + + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + //@} + + /** + * @brief A template function that inserts a range of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_h.insert(__first, __last); } + + /** + * @brief Inserts a list of elements into the %unordered_multiset. + * @param __l A std::initializer_list of elements to be + * inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { _M_h.insert(__l); } + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } +#endif // C++17 + + //@{ + /** + * @brief Erases an element from an %unordered_multiset. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from an %unordered_multiset. + * + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __position) + { return _M_h.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_h.erase(__position); } + //@} + + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * an %unordered_multiset. + * + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_h.erase(__x); } + + /** + * @brief Erases a [__first,__last) range of elements from an + * %unordered_multiset. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from an + * %unordered_multiset. + * + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_h.erase(__first, __last); } + + /** + * Erases all elements in an %unordered_multiset. + * + * Note that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + clear() noexcept + { _M_h.clear(); } + + /** + * @brief Swaps data with another %unordered_multiset. + * @param __x An %unordered_multiset of the same element and allocator + * types. + * + * This exchanges the elements between two sets in constant time. + * Note that the global std::swap() function is specialized such that + * std::swap(s1,s2) will feed to this function. + */ + void + swap(unordered_multiset& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) + { _M_h.swap(__x._M_h); } + +#if __cplusplus > 201402L + template + friend class std::_Hash_merge_helper; + + template + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + + // observers. + + /// Returns the hash functor object with which the %unordered_multiset + /// was constructed. + hasher + hash_function() const + { return _M_h.hash_function(); } + + /// Returns the key comparison object with which the %unordered_multiset + /// was constructed. + key_equal + key_eq() const + { return _M_h.key_eq(); } + + // lookup. + + //@{ + /** + * @brief Tries to locate an element in an %unordered_multiset. + * @param __x Element to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_h.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_h.find(__x); } + //@} + + /** + * @brief Finds the number of elements. + * @param __x Element to located. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const + { return _M_h.count(__x); } + +#if __cplusplus > 201703L + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_h.find(__x) != _M_h.end(); } +#endif + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + */ + std::pair + equal_range(const key_type& __x) + { return _M_h.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_h.equal_range(__x); } + //@} + + // bucket interface. + + /// Returns the number of buckets of the %unordered_multiset. + size_type + bucket_count() const noexcept + { return _M_h.bucket_count(); } + + /// Returns the maximum number of buckets of the %unordered_multiset. + size_type + max_bucket_count() const noexcept + { return _M_h.max_bucket_count(); } + + /* + * @brief Returns the number of elements in a given bucket. + * @param __n A bucket index. + * @return The number of elements in the bucket. + */ + size_type + bucket_size(size_type __n) const + { return _M_h.bucket_size(__n); } + + /* + * @brief Returns the bucket index of a given element. + * @param __key A key instance. + * @return The key bucket index. + */ + size_type + bucket(const key_type& __key) const + { return _M_h.bucket(__key); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to the first + * bucket element. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + local_iterator + begin(size_type __n) + { return _M_h.begin(__n); } + + const_local_iterator + begin(size_type __n) const + { return _M_h.begin(__n); } + + const_local_iterator + cbegin(size_type __n) const + { return _M_h.cbegin(__n); } + //@} + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to one past + * the last bucket elements. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + local_iterator + end(size_type __n) + { return _M_h.end(__n); } + + const_local_iterator + end(size_type __n) const + { return _M_h.end(__n); } + + const_local_iterator + cend(size_type __n) const + { return _M_h.cend(__n); } + //@} + + // hash policy. + + /// Returns the average number of elements per bucket. + float + load_factor() const noexcept + { return _M_h.load_factor(); } + + /// Returns a positive number that the %unordered_multiset tries to keep the + /// load factor less than or equal to. + float + max_load_factor() const noexcept + { return _M_h.max_load_factor(); } + + /** + * @brief Change the %unordered_multiset maximum load factor. + * @param __z The new maximum load factor. + */ + void + max_load_factor(float __z) + { _M_h.max_load_factor(__z); } + + /** + * @brief May rehash the %unordered_multiset. + * @param __n The new number of buckets. + * + * Rehash will occur only if the new number of buckets respect the + * %unordered_multiset maximum load factor. + */ + void + rehash(size_type __n) + { _M_h.rehash(__n); } + + /** + * @brief Prepare the %unordered_multiset for a specified number of + * elements. + * @param __n Number of elements required. + * + * Same as rehash(ceil(n / max_load_factor())). + */ + void + reserve(size_type __n) + { _M_h.reserve(__n); } + + template + friend bool + operator==(const unordered_multiset<_Value1, _Hash1, _Pred1, _Alloc1>&, + const unordered_multiset<_Value1, _Hash1, _Pred1, _Alloc1>&); + }; + + +#if __cpp_deduction_guides >= 201606 + + template::value_type>, + typename _Pred = + equal_to::value_type>, + typename _Allocator = + allocator::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multiset::value_type, + _Hash, _Pred, _Allocator>; + + template, + typename _Pred = equal_to<_Tp>, + typename _Allocator = allocator<_Tp>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset::size_type, _Allocator) + -> unordered_multiset::value_type, + hash::value_type>, + equal_to::value_type>, + _Allocator>; + + template, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset::size_type, + _Hash, _Allocator) + -> unordered_multiset::value_type, + _Hash, + equal_to< + typename + iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset::size_type, _Allocator) + -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset::size_type, _Hash, _Allocator) + -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; + +#endif + + template + inline void + swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + inline void + swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + inline bool + operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + { return __x._M_h._M_equal(__y._M_h); } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline bool + operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } +#endif + + template + inline bool + operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + { return __x._M_h._M_equal(__y._M_h); } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline bool + operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } +#endif + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::unordered_set access to internals of compatible sets. + template + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_set<_Val, _Hash1, _Eq1, _Alloc>, _Hash2, _Eq2> + { + private: + template + using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>; + template + using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>; + + friend unordered_set<_Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + + static auto& + _S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + }; + + // Allow std::unordered_multiset access to internals of compatible sets. + template + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template + using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>; + template + using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>; + + friend unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + + static auto& + _S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _UNORDERED_SET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h b/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h new file mode 100644 index 000000000..1832d40d6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h @@ -0,0 +1,195 @@ +// Uses-allocator Construction -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#ifndef _USES_ALLOCATOR_H +#define _USES_ALLOCATOR_H 1 + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // This is used for std::experimental::erased_type from Library Fundamentals. + struct __erased_type { }; + + // This also supports the "type-erased allocator" protocol from the + // Library Fundamentals TS, where allocator_type is erased_type. + // The second condition will always be false for types not using the TS. + template + using __is_erased_or_convertible + = __or_, is_same<_Tp, __erased_type>>; + + /// [allocator.tag] + struct allocator_arg_t { explicit allocator_arg_t() = default; }; + + _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg = + allocator_arg_t(); + + template> + struct __uses_allocator_helper + : false_type { }; + + template + struct __uses_allocator_helper<_Tp, _Alloc, + __void_t> + : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type + { }; + + /// [allocator.uses.trait] + template + struct uses_allocator + : __uses_allocator_helper<_Tp, _Alloc>::type + { }; + + struct __uses_alloc_base { }; + + struct __uses_alloc0 : __uses_alloc_base + { + struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a; + }; + + template + struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; }; + + template + struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; }; + + template + struct __uses_alloc; + + template + struct __uses_alloc + : conditional< + is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value, + __uses_alloc1<_Alloc>, + __uses_alloc2<_Alloc>>::type + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2586. Wrong value category used in scoped_allocator_adaptor::construct + static_assert(__or_< + is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>, + is_constructible<_Tp, _Args..., const _Alloc&>>::value, + "construction with an allocator must be possible" + " if uses_allocator is true"); + }; + + template + struct __uses_alloc + : __uses_alloc0 { }; + + template + using __uses_alloc_t = + __uses_alloc::value, _Tp, _Alloc, _Args...>; + + template + _GLIBCXX20_CONSTEXPR + inline __uses_alloc_t<_Tp, _Alloc, _Args...> + __use_alloc(const _Alloc& __a) + { + __uses_alloc_t<_Tp, _Alloc, _Args...> __ret; + __ret._M_a = std::__addressof(__a); + return __ret; + } + + template + void + __use_alloc(const _Alloc&&) = delete; + +#if __cplusplus > 201402L + template + inline constexpr bool uses_allocator_v = + uses_allocator<_Tp, _Alloc>::value; +#endif // C++17 + + template class _Predicate, + typename _Tp, typename _Alloc, typename... _Args> + struct __is_uses_allocator_predicate + : conditional::value, + __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>, + _Predicate<_Tp, _Args..., _Alloc>>, + _Predicate<_Tp, _Args...>>::type { }; + + template + struct __is_uses_allocator_constructible + : __is_uses_allocator_predicate + { }; + +#if __cplusplus >= 201402L + template + _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v = + __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; +#endif // C++14 + + template + struct __is_nothrow_uses_allocator_constructible + : __is_uses_allocator_predicate + { }; + + +#if __cplusplus >= 201402L + template + _GLIBCXX17_INLINE constexpr bool + __is_nothrow_uses_allocator_constructible_v = + __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; +#endif // C++14 + + template + void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr, + _Args&&... __args) + { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); } + + template + void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr, + _Args&&... __args) + { + ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a, + std::forward<_Args>(__args)...); + } + + template + void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr, + _Args&&... __args) + { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); } + + template + void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr, + _Args&&... __args) + { + std::__uses_allocator_construct_impl( + std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr, + std::forward<_Args>(__args)...); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_after.h b/resources/sources/avr-libstdcpp/include/bits/valarray_after.h new file mode 100644 index 000000000..cf84e17e5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/valarray_after.h @@ -0,0 +1,556 @@ +// The template and inlines for the -*- C++ -*- internal _Meta class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/valarray_after.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _VALARRAY_AFTER_H +#define _VALARRAY_AFTER_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __detail +{ + // + // gslice_array closure. + // + template + class _GBase + { + public: + typedef typename _Dom::value_type value_type; + + _GBase (const _Dom& __e, const valarray& __i) + : _M_expr (__e), _M_index(__i) {} + + value_type + operator[] (size_t __i) const + { return _M_expr[_M_index[__i]]; } + + size_t + size () const + { return _M_index.size(); } + + private: + typename _ValArrayRef<_Dom>::__type _M_expr; + const valarray& _M_index; + }; + + template + class _GBase<_Array<_Tp> > + { + public: + typedef _Tp value_type; + + _GBase (_Array<_Tp> __a, const valarray& __i) + : _M_array (__a), _M_index(__i) {} + + value_type + operator[] (size_t __i) const + { return _M_array._M_data[_M_index[__i]]; } + + size_t + size () const + { return _M_index.size(); } + + private: + const _Array<_Tp> _M_array; + const valarray& _M_index; + }; + + template + struct _GClos<_Expr, _Dom> + : _GBase<_Dom> + { + typedef _GBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _GClos (const _Dom& __e, const valarray& __i) + : _Base (__e, __i) {} + }; + + template + struct _GClos<_ValArray, _Tp> + : _GBase<_Array<_Tp> > + { + typedef _GBase<_Array<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _GClos (_Array<_Tp> __a, const valarray& __i) + : _Base (__a, __i) {} + }; + + // + // indirect_array closure + // + template + class _IBase + { + public: + typedef typename _Dom::value_type value_type; + + _IBase (const _Dom& __e, const valarray& __i) + : _M_expr (__e), _M_index (__i) {} + + value_type + operator[] (size_t __i) const + { return _M_expr[_M_index[__i]]; } + + size_t + size() const + { return _M_index.size(); } + + private: + typename _ValArrayRef<_Dom>::__type _M_expr; + const valarray& _M_index; + }; + + template + struct _IClos<_Expr, _Dom> + : _IBase<_Dom> + { + typedef _IBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _IClos (const _Dom& __e, const valarray& __i) + : _Base (__e, __i) {} + }; + + template + struct _IClos<_ValArray, _Tp> + : _IBase > + { + typedef _IBase > _Base; + typedef _Tp value_type; + + _IClos (const valarray<_Tp>& __a, const valarray& __i) + : _Base (__a, __i) {} + }; +} // namespace __detail + + // + // class _Expr + // + template + class _Expr + { + public: + typedef _Tp value_type; + + _Expr(const _Clos&); + + const _Clos& operator()() const; + + value_type operator[](size_t) const; + valarray operator[](slice) const; + valarray operator[](const gslice&) const; + valarray operator[](const valarray&) const; + valarray operator[](const valarray&) const; + + _Expr<_UnClos<__unary_plus, std::_Expr, _Clos>, value_type> + operator+() const; + + _Expr<_UnClos<__negate, std::_Expr, _Clos>, value_type> + operator-() const; + + _Expr<_UnClos<__bitwise_not, std::_Expr, _Clos>, value_type> + operator~() const; + + _Expr<_UnClos<__logical_not, std::_Expr, _Clos>, bool> + operator!() const; + + size_t size() const; + value_type sum() const; + + valarray shift(int) const; + valarray cshift(int) const; + + value_type min() const; + value_type max() const; + + valarray apply(value_type (*)(const value_type&)) const; + valarray apply(value_type (*)(value_type)) const; + + private: + const _Clos _M_closure; + }; + + template + inline + _Expr<_Clos, _Tp>::_Expr(const _Clos& __c) : _M_closure(__c) {} + + template + inline const _Clos& + _Expr<_Clos, _Tp>::operator()() const + { return _M_closure; } + + template + inline _Tp + _Expr<_Clos, _Tp>::operator[](size_t __i) const + { return _M_closure[__i]; } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::operator[](slice __s) const + { + valarray<_Tp> __v = valarray<_Tp>(*this)[__s]; + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::operator[](const gslice& __gs) const + { + valarray<_Tp> __v = valarray<_Tp>(*this)[__gs]; + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::operator[](const valarray& __m) const + { + valarray<_Tp> __v = valarray<_Tp>(*this)[__m]; + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::operator[](const valarray& __i) const + { + valarray<_Tp> __v = valarray<_Tp>(*this)[__i]; + return __v; + } + + template + inline size_t + _Expr<_Clos, _Tp>::size() const + { return _M_closure.size(); } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::shift(int __n) const + { + valarray<_Tp> __v = valarray<_Tp>(*this).shift(__n); + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::cshift(int __n) const + { + valarray<_Tp> __v = valarray<_Tp>(*this).cshift(__n); + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::apply(_Tp __f(const _Tp&)) const + { + valarray<_Tp> __v = valarray<_Tp>(*this).apply(__f); + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::apply(_Tp __f(_Tp)) const + { + valarray<_Tp> __v = valarray<_Tp>(*this).apply(__f); + return __v; + } + + // XXX: replace this with a more robust summation algorithm. + template + inline _Tp + _Expr<_Clos, _Tp>::sum() const + { + size_t __n = _M_closure.size(); + if (__n == 0) + return _Tp(); + else + { + _Tp __s = _M_closure[--__n]; + while (__n != 0) + __s += _M_closure[--__n]; + return __s; + } + } + + template + inline _Tp + _Expr<_Clos, _Tp>::min() const + { return __valarray_min(_M_closure); } + + template + inline _Tp + _Expr<_Clos, _Tp>::max() const + { return __valarray_max(_M_closure); } + + template + inline _Expr<_UnClos<__logical_not, _Expr, _Dom>, bool> + _Expr<_Dom, _Tp>::operator!() const + { + typedef _UnClos<__logical_not, std::_Expr, _Dom> _Closure; + return _Expr<_Closure, bool>(_Closure(this->_M_closure)); + } + +#define _DEFINE_EXPR_UNARY_OPERATOR(_Op, _Name) \ + template \ + inline _Expr<_UnClos<_Name, std::_Expr, _Dom>, _Tp> \ + _Expr<_Dom, _Tp>::operator _Op() const \ + { \ + typedef _UnClos<_Name, std::_Expr, _Dom> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(this->_M_closure)); \ + } + + _DEFINE_EXPR_UNARY_OPERATOR(+, __unary_plus) + _DEFINE_EXPR_UNARY_OPERATOR(-, __negate) + _DEFINE_EXPR_UNARY_OPERATOR(~, __bitwise_not) + +#undef _DEFINE_EXPR_UNARY_OPERATOR + +#define _DEFINE_EXPR_BINARY_OPERATOR(_Op, _Name) \ + template \ + inline _Expr<_BinClos<_Name, _Expr, _Expr, _Dom1, _Dom2>, \ + typename __fun<_Name, typename _Dom1::value_type>::result_type> \ + operator _Op(const _Expr<_Dom1, typename _Dom1::value_type>& __v, \ + const _Expr<_Dom2, typename _Dom2::value_type>& __w) \ + { \ + typedef typename _Dom1::value_type _Arg; \ + typedef typename __fun<_Name, _Arg>::result_type _Value; \ + typedef _BinClos<_Name, _Expr, _Expr, _Dom1, _Dom2> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__v(), __w())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _Expr, _Constant, _Dom, \ + typename _Dom::value_type>, \ + typename __fun<_Name, typename _Dom::value_type>::result_type> \ + operator _Op(const _Expr<_Dom, typename _Dom::value_type>& __v, \ + const typename _Dom::value_type& __t) \ + { \ + typedef typename _Dom::value_type _Arg; \ + typedef typename __fun<_Name, _Arg>::result_type _Value; \ + typedef _BinClos<_Name, _Expr, _Constant, _Dom, _Arg> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__v(), __t)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _Constant, _Expr, \ + typename _Dom::value_type, _Dom>, \ + typename __fun<_Name, typename _Dom::value_type>::result_type> \ + operator _Op(const typename _Dom::value_type& __t, \ + const _Expr<_Dom, typename _Dom::value_type>& __v) \ + { \ + typedef typename _Dom::value_type _Arg; \ + typedef typename __fun<_Name, _Arg>::result_type _Value; \ + typedef _BinClos<_Name, _Constant, _Expr, _Arg, _Dom> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__t, __v())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _Expr, _ValArray, \ + _Dom, typename _Dom::value_type>, \ + typename __fun<_Name, typename _Dom::value_type>::result_type> \ + operator _Op(const _Expr<_Dom,typename _Dom::value_type>& __e, \ + const valarray& __v) \ + { \ + typedef typename _Dom::value_type _Arg; \ + typedef typename __fun<_Name, _Arg>::result_type _Value; \ + typedef _BinClos<_Name, _Expr, _ValArray, _Dom, _Arg> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__e(), __v)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _ValArray, _Expr, \ + typename _Dom::value_type, _Dom>, \ + typename __fun<_Name, typename _Dom::value_type>::result_type> \ + operator _Op(const valarray& __v, \ + const _Expr<_Dom, typename _Dom::value_type>& __e) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef typename __fun<_Name, _Tp>::result_type _Value; \ + typedef _BinClos<_Name, _ValArray, _Expr, _Tp, _Dom> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__v, __e ())); \ + } + + _DEFINE_EXPR_BINARY_OPERATOR(+, __plus) + _DEFINE_EXPR_BINARY_OPERATOR(-, __minus) + _DEFINE_EXPR_BINARY_OPERATOR(*, __multiplies) + _DEFINE_EXPR_BINARY_OPERATOR(/, __divides) + _DEFINE_EXPR_BINARY_OPERATOR(%, __modulus) + _DEFINE_EXPR_BINARY_OPERATOR(^, __bitwise_xor) + _DEFINE_EXPR_BINARY_OPERATOR(&, __bitwise_and) + _DEFINE_EXPR_BINARY_OPERATOR(|, __bitwise_or) + _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left) + _DEFINE_EXPR_BINARY_OPERATOR(>>, __shift_right) + _DEFINE_EXPR_BINARY_OPERATOR(&&, __logical_and) + _DEFINE_EXPR_BINARY_OPERATOR(||, __logical_or) + _DEFINE_EXPR_BINARY_OPERATOR(==, __equal_to) + _DEFINE_EXPR_BINARY_OPERATOR(!=, __not_equal_to) + _DEFINE_EXPR_BINARY_OPERATOR(<, __less) + _DEFINE_EXPR_BINARY_OPERATOR(>, __greater) + _DEFINE_EXPR_BINARY_OPERATOR(<=, __less_equal) + _DEFINE_EXPR_BINARY_OPERATOR(>=, __greater_equal) + +#undef _DEFINE_EXPR_BINARY_OPERATOR + +#define _DEFINE_EXPR_UNARY_FUNCTION(_Name, _UName) \ + template \ + inline _Expr<_UnClos<_UName, _Expr, _Dom>, \ + typename _Dom::value_type> \ + _Name(const _Expr<_Dom, typename _Dom::value_type>& __e) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _UnClos<_UName, _Expr, _Dom> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__e())); \ + } \ + \ + template \ + inline _Expr<_UnClos<_UName, _ValArray, _Tp>, _Tp> \ + _Name(const valarray<_Tp>& __v) \ + { \ + typedef _UnClos<_UName, _ValArray, _Tp> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__v)); \ + } + + _DEFINE_EXPR_UNARY_FUNCTION(abs, _Abs) + _DEFINE_EXPR_UNARY_FUNCTION(cos, _Cos) + _DEFINE_EXPR_UNARY_FUNCTION(acos, _Acos) + _DEFINE_EXPR_UNARY_FUNCTION(cosh, _Cosh) + _DEFINE_EXPR_UNARY_FUNCTION(sin, _Sin) + _DEFINE_EXPR_UNARY_FUNCTION(asin, _Asin) + _DEFINE_EXPR_UNARY_FUNCTION(sinh, _Sinh) + _DEFINE_EXPR_UNARY_FUNCTION(tan, _Tan) + _DEFINE_EXPR_UNARY_FUNCTION(tanh, _Tanh) + _DEFINE_EXPR_UNARY_FUNCTION(atan, _Atan) + _DEFINE_EXPR_UNARY_FUNCTION(exp, _Exp) + _DEFINE_EXPR_UNARY_FUNCTION(log, _Log) + _DEFINE_EXPR_UNARY_FUNCTION(log10, _Log10) + _DEFINE_EXPR_UNARY_FUNCTION(sqrt, _Sqrt) + +#undef _DEFINE_EXPR_UNARY_FUNCTION + +#define _DEFINE_EXPR_BINARY_FUNCTION(_Fun, _UFun) \ + template \ + inline _Expr<_BinClos<_UFun, _Expr, _Expr, _Dom1, _Dom2>, \ + typename _Dom1::value_type> \ + _Fun(const _Expr<_Dom1, typename _Dom1::value_type>& __e1, \ + const _Expr<_Dom2, typename _Dom2::value_type>& __e2) \ + { \ + typedef typename _Dom1::value_type _Tp; \ + typedef _BinClos<_UFun, _Expr, _Expr, _Dom1, _Dom2> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__e1(), __e2())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _Expr, _ValArray, _Dom, \ + typename _Dom::value_type>, \ + typename _Dom::value_type> \ + _Fun(const _Expr<_Dom, typename _Dom::value_type>& __e, \ + const valarray& __v) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_UFun, _Expr, _ValArray, _Dom, _Tp> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__e(), __v)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _ValArray, _Expr, \ + typename _Dom::value_type, _Dom>, \ + typename _Dom::value_type> \ + _Fun(const valarray& __v, \ + const _Expr<_Dom, typename _Dom::value_type>& __e) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_UFun, _ValArray, _Expr, _Tp, _Dom> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__v, __e())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _Expr, _Constant, _Dom, \ + typename _Dom::value_type>, \ + typename _Dom::value_type> \ + _Fun(const _Expr<_Dom, typename _Dom::value_type>& __e, \ + const typename _Dom::value_type& __t) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_UFun, _Expr, _Constant, _Dom, _Tp> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__e(), __t)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _Constant, _Expr, \ + typename _Dom::value_type, _Dom>, \ + typename _Dom::value_type> \ + _Fun(const typename _Dom::value_type& __t, \ + const _Expr<_Dom, typename _Dom::value_type>& __e) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_UFun, _Constant, _Expr, _Tp, _Dom> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__t, __e())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _ValArray, _ValArray, _Tp, _Tp>, _Tp> \ + _Fun(const valarray<_Tp>& __v, const valarray<_Tp>& __w) \ + { \ + typedef _BinClos<_UFun, _ValArray, _ValArray, _Tp, _Tp> _Closure;\ + return _Expr<_Closure, _Tp>(_Closure(__v, __w)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _ValArray, _Constant, _Tp, _Tp>, _Tp> \ + _Fun(const valarray<_Tp>& __v, \ + const typename valarray<_Tp>::value_type& __t) \ + { \ + typedef _BinClos<_UFun, _ValArray, _Constant, _Tp, _Tp> _Closure;\ + return _Expr<_Closure, _Tp>(_Closure(__v, __t)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _Constant, _ValArray, _Tp, _Tp>, _Tp> \ + _Fun(const typename valarray<_Tp>::value_type& __t, \ + const valarray<_Tp>& __v) \ + { \ + typedef _BinClos<_UFun, _Constant, _ValArray, _Tp, _Tp> _Closure;\ + return _Expr<_Closure, _Tp>(_Closure(__t, __v)); \ + } + +_DEFINE_EXPR_BINARY_FUNCTION(atan2, _Atan2) +_DEFINE_EXPR_BINARY_FUNCTION(pow, _Pow) + +#undef _DEFINE_EXPR_BINARY_FUNCTION + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _CPP_VALARRAY_AFTER_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_array.h b/resources/sources/avr-libstdcpp/include/bits/valarray_array.h new file mode 100644 index 000000000..041fbbe25 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/valarray_array.h @@ -0,0 +1,677 @@ +// The template and inlines for the -*- C++ -*- internal _Array helper class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/valarray_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _VALARRAY_ARRAY_H +#define _VALARRAY_ARRAY_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // + // Helper functions on raw pointers + // + + // We get memory the old fashioned way + template + _Tp* + __valarray_get_storage(size_t) __attribute__((__malloc__)); + + template + inline _Tp* + __valarray_get_storage(size_t __n) + { return static_cast<_Tp*>(operator new(__n * sizeof(_Tp))); } + + // Return memory to the system + inline void + __valarray_release_memory(void* __p) + { operator delete(__p); } + + // Turn a raw-memory into an array of _Tp filled with _Tp() + // This is required in 'valarray v(n);' + template + struct _Array_default_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(_Tp* __b, _Tp* __e) + { + while (__b != __e) + new(__b++) _Tp(); + } + }; + + template + struct _Array_default_ctor<_Tp, true> + { + // For fundamental types, it suffices to say 'memset()' + inline static void + _S_do_it(_Tp* __b, _Tp* __e) + { __builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp)); } + }; + + template + inline void + __valarray_default_construct(_Tp* __b, _Tp* __e) + { + _Array_default_ctor<_Tp, __is_scalar<_Tp>::__value>::_S_do_it(__b, __e); + } + + // Turn a raw-memory into an array of _Tp filled with __t + // This is the required in valarray v(n, t). Also + // used in valarray<>::resize(). + template + struct _Array_init_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t) + { + while (__b != __e) + new(__b++) _Tp(__t); + } + }; + + template + struct _Array_init_ctor<_Tp, true> + { + inline static void + _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t) + { + while (__b != __e) + *__b++ = __t; + } + }; + + template + inline void + __valarray_fill_construct(_Tp* __b, _Tp* __e, const _Tp __t) + { + _Array_init_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __t); + } + + // + // copy-construct raw array [__o, *) from plain array [__b, __e) + // We can't just say 'memcpy()' + // + template + struct _Array_copy_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) + { + while (__b != __e) + new(__o++) _Tp(*__b++); + } + }; + + template + struct _Array_copy_ctor<_Tp, true> + { + inline static void + _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) + { + if (__b) + __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp)); + } + }; + + template + inline void + __valarray_copy_construct(const _Tp* __b, const _Tp* __e, + _Tp* __restrict__ __o) + { + _Array_copy_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __o); + } + + // copy-construct raw array [__o, *) from strided array __a[<__n : __s>] + template + inline void + __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n, + size_t __s, _Tp* __restrict__ __o) + { + if (__is_trivial(_Tp)) + while (__n--) + { + *__o++ = *__a; + __a += __s; + } + else + while (__n--) + { + new(__o++) _Tp(*__a); + __a += __s; + } + } + + // copy-construct raw array [__o, *) from indexed array __a[__i[<__n>]] + template + inline void + __valarray_copy_construct (const _Tp* __restrict__ __a, + const size_t* __restrict__ __i, + _Tp* __restrict__ __o, size_t __n) + { + if (__is_trivial(_Tp)) + while (__n--) + *__o++ = __a[*__i++]; + else + while (__n--) + new (__o++) _Tp(__a[*__i++]); + } + + // Do the necessary cleanup when we're done with arrays. + template + inline void + __valarray_destroy_elements(_Tp* __b, _Tp* __e) + { + if (!__is_trivial(_Tp)) + while (__b != __e) + { + __b->~_Tp(); + ++__b; + } + } + + // Fill a plain array __a[<__n>] with __t + template + inline void + __valarray_fill(_Tp* __restrict__ __a, size_t __n, const _Tp& __t) + { + while (__n--) + *__a++ = __t; + } + + // fill strided array __a[<__n-1 : __s>] with __t + template + inline void + __valarray_fill(_Tp* __restrict__ __a, size_t __n, + size_t __s, const _Tp& __t) + { + for (size_t __i = 0; __i < __n; ++__i, __a += __s) + *__a = __t; + } + + // fill indirect array __a[__i[<__n>]] with __i + template + inline void + __valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i, + size_t __n, const _Tp& __t) + { + for (size_t __j = 0; __j < __n; ++__j, ++__i) + __a[*__i] = __t; + } + + // copy plain array __a[<__n>] in __b[<__n>] + // For non-fundamental types, it is wrong to say 'memcpy()' + template + struct _Array_copier + { + inline static void + _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) + { + while(__n--) + *__b++ = *__a++; + } + }; + + template + struct _Array_copier<_Tp, true> + { + inline static void + _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) + { + if (__n != 0) + __builtin_memcpy(__b, __a, __n * sizeof (_Tp)); + } + }; + + // Copy a plain array __a[<__n>] into a play array __b[<>] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, size_t __n, + _Tp* __restrict__ __b) + { + _Array_copier<_Tp, __is_trivial(_Tp)>::_S_do_it(__a, __n, __b); + } + + // Copy strided array __a[<__n : __s>] in plain __b[<__n>] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, size_t __n, size_t __s, + _Tp* __restrict__ __b) + { + for (size_t __i = 0; __i < __n; ++__i, ++__b, __a += __s) + *__b = *__a; + } + + // Copy a plain array __a[<__n>] into a strided array __b[<__n : __s>] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, _Tp* __restrict__ __b, + size_t __n, size_t __s) + { + for (size_t __i = 0; __i < __n; ++__i, ++__a, __b += __s) + *__b = *__a; + } + + // Copy strided array __src[<__n : __s1>] into another + // strided array __dst[< : __s2>]. Their sizes must match. + template + inline void + __valarray_copy(const _Tp* __restrict__ __src, size_t __n, size_t __s1, + _Tp* __restrict__ __dst, size_t __s2) + { + for (size_t __i = 0; __i < __n; ++__i) + __dst[__i * __s2] = __src[__i * __s1]; + } + + // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, + const size_t* __restrict__ __i, + _Tp* __restrict__ __b, size_t __n) + { + for (size_t __j = 0; __j < __n; ++__j, ++__b, ++__i) + *__b = __a[*__i]; + } + + // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, size_t __n, + _Tp* __restrict__ __b, const size_t* __restrict__ __i) + { + for (size_t __j = 0; __j < __n; ++__j, ++__a, ++__i) + __b[*__i] = *__a; + } + + // Copy the __n first elements of an indexed array __src[<__i>] into + // another indexed array __dst[<__j>]. + template + inline void + __valarray_copy(const _Tp* __restrict__ __src, size_t __n, + const size_t* __restrict__ __i, + _Tp* __restrict__ __dst, const size_t* __restrict__ __j) + { + for (size_t __k = 0; __k < __n; ++__k) + __dst[*__j++] = __src[*__i++]; + } + + // + // Compute the sum of elements in range [__f, __l) which must not be empty. + // This is a naive algorithm. It suffers from cancelling. + // In the future try to specialize for _Tp = float, double, long double + // using a more accurate algorithm. + // + template + inline _Tp + __valarray_sum(const _Tp* __f, const _Tp* __l) + { + _Tp __r = *__f++; + while (__f != __l) + __r += *__f++; + return __r; + } + + // Compute the min/max of an array-expression + template + inline typename _Ta::value_type + __valarray_min(const _Ta& __a) + { + size_t __s = __a.size(); + typedef typename _Ta::value_type _Value_type; + _Value_type __r = __s == 0 ? _Value_type() : __a[0]; + for (size_t __i = 1; __i < __s; ++__i) + { + _Value_type __t = __a[__i]; + if (__t < __r) + __r = __t; + } + return __r; + } + + template + inline typename _Ta::value_type + __valarray_max(const _Ta& __a) + { + size_t __s = __a.size(); + typedef typename _Ta::value_type _Value_type; + _Value_type __r = __s == 0 ? _Value_type() : __a[0]; + for (size_t __i = 1; __i < __s; ++__i) + { + _Value_type __t = __a[__i]; + if (__t > __r) + __r = __t; + } + return __r; + } + + // + // Helper class _Array, first layer of valarray abstraction. + // All operations on valarray should be forwarded to this class + // whenever possible. -- gdr + // + + template + struct _Array + { + explicit _Array(_Tp* const __restrict__); + explicit _Array(const valarray<_Tp>&); + _Array(const _Tp* __restrict__, size_t); + + _Tp* begin() const; + + _Tp* const __restrict__ _M_data; + }; + + + // Copy-construct plain array __b[<__n>] from indexed array __a[__i[<__n>]] + template + inline void + __valarray_copy_construct(_Array<_Tp> __a, _Array __i, + _Array<_Tp> __b, size_t __n) + { std::__valarray_copy_construct(__a._M_data, __i._M_data, + __b._M_data, __n); } + + // Copy-construct plain array __b[<__n>] from strided array __a[<__n : __s>] + template + inline void + __valarray_copy_construct(_Array<_Tp> __a, size_t __n, size_t __s, + _Array<_Tp> __b) + { std::__valarray_copy_construct(__a._M_data, __n, __s, __b._M_data); } + + template + inline void + __valarray_fill (_Array<_Tp> __a, size_t __n, const _Tp& __t) + { std::__valarray_fill(__a._M_data, __n, __t); } + + template + inline void + __valarray_fill(_Array<_Tp> __a, size_t __n, size_t __s, const _Tp& __t) + { std::__valarray_fill(__a._M_data, __n, __s, __t); } + + template + inline void + __valarray_fill(_Array<_Tp> __a, _Array __i, + size_t __n, const _Tp& __t) + { std::__valarray_fill(__a._M_data, __i._M_data, __n, __t); } + + // Copy a plain array __a[<__n>] into a play array __b[<>] + template + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) + { std::__valarray_copy(__a._M_data, __n, __b._M_data); } + + // Copy strided array __a[<__n : __s>] in plain __b[<__n>] + template + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s, _Array<_Tp> __b) + { std::__valarray_copy(__a._M_data, __n, __s, __b._M_data); } + + // Copy a plain array __a[<__n>] into a strided array __b[<__n : __s>] + template + inline void + __valarray_copy(_Array<_Tp> __a, _Array<_Tp> __b, size_t __n, size_t __s) + { __valarray_copy(__a._M_data, __b._M_data, __n, __s); } + + // Copy strided array __src[<__n : __s1>] into another + // strided array __dst[< : __s2>]. Their sizes must match. + template + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s1, + _Array<_Tp> __b, size_t __s2) + { std::__valarray_copy(__a._M_data, __n, __s1, __b._M_data, __s2); } + + // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] + template + inline void + __valarray_copy(_Array<_Tp> __a, _Array __i, + _Array<_Tp> __b, size_t __n) + { std::__valarray_copy(__a._M_data, __i._M_data, __b._M_data, __n); } + + // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]] + template + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, + _Array __i) + { std::__valarray_copy(__a._M_data, __n, __b._M_data, __i._M_data); } + + // Copy the __n first elements of an indexed array __src[<__i>] into + // another indexed array __dst[<__j>]. + template + inline void + __valarray_copy(_Array<_Tp> __src, size_t __n, _Array __i, + _Array<_Tp> __dst, _Array __j) + { + std::__valarray_copy(__src._M_data, __n, __i._M_data, + __dst._M_data, __j._M_data); + } + + template + inline + _Array<_Tp>::_Array(_Tp* const __restrict__ __p) + : _M_data (__p) {} + + template + inline + _Array<_Tp>::_Array(const valarray<_Tp>& __v) + : _M_data (__v._M_data) {} + + template + inline + _Array<_Tp>::_Array(const _Tp* __restrict__ __b, size_t __s) + : _M_data(__valarray_get_storage<_Tp>(__s)) + { std::__valarray_copy_construct(__b, __s, _M_data); } + + template + inline _Tp* + _Array<_Tp>::begin () const + { return _M_data; } + +#define _DEFINE_ARRAY_FUNCTION(_Op, _Name) \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, const _Tp& __t) \ + { \ + for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; ++__p) \ + *__p _Op##= __t; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) \ + { \ + _Tp* __p = __a._M_data; \ + for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; ++__p, ++__q) \ + *__p _Op##= *__q; \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ + { \ + _Tp* __p(__a._M_data); \ + for (size_t __i = 0; __i < __n; ++__i, ++__p) \ + *__p _Op##= __e[__i]; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, size_t __s, \ + _Array<_Tp> __b) \ + { \ + _Tp* __q(__b._M_data); \ + for (_Tp* __p = __a._M_data; __p < __a._M_data + __s * __n; \ + __p += __s, ++__q) \ + *__p _Op##= *__q; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array<_Tp> __b, \ + size_t __n, size_t __s) \ + { \ + _Tp* __q(__b._M_data); \ + for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; \ + ++__p, __q += __s) \ + *__p _Op##= *__q; \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __s, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ + { \ + _Tp* __p(__a._M_data); \ + for (size_t __i = 0; __i < __n; ++__i, __p += __s) \ + *__p _Op##= __e[__i]; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array __i, \ + _Array<_Tp> __b, size_t __n) \ + { \ + _Tp* __q(__b._M_data); \ + for (size_t* __j = __i._M_data; __j < __i._M_data + __n; \ + ++__j, ++__q) \ + __a._M_data[*__j] _Op##= *__q; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, \ + _Array<_Tp> __b, _Array __i) \ + { \ + _Tp* __p(__a._M_data); \ + for (size_t* __j = __i._M_data; __j<__i._M_data + __n; \ + ++__j, ++__p) \ + *__p _Op##= __b._M_data[*__j]; \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array __i, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ + { \ + size_t* __j(__i._M_data); \ + for (size_t __k = 0; __k<__n; ++__k, ++__j) \ + __a._M_data[*__j] _Op##= __e[__k]; \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array __m, \ + _Array<_Tp> __b, size_t __n) \ + { \ + bool* __ok(__m._M_data); \ + _Tp* __p(__a._M_data); \ + for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; \ + ++__q, ++__ok, ++__p) \ + { \ + while (! *__ok) \ + { \ + ++__ok; \ + ++__p; \ + } \ + *__p _Op##= *__q; \ + } \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, \ + _Array<_Tp> __b, _Array __m) \ + { \ + bool* __ok(__m._M_data); \ + _Tp* __q(__b._M_data); \ + for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; \ + ++__p, ++__ok, ++__q) \ + { \ + while (! *__ok) \ + { \ + ++__ok; \ + ++__q; \ + } \ + *__p _Op##= *__q; \ + } \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array __m, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ + { \ + bool* __ok(__m._M_data); \ + _Tp* __p(__a._M_data); \ + for (size_t __i = 0; __i < __n; ++__i, ++__ok, ++__p) \ + { \ + while (! *__ok) \ + { \ + ++__ok; \ + ++__p; \ + } \ + *__p _Op##= __e[__i]; \ + } \ + } + + _DEFINE_ARRAY_FUNCTION(+, __plus) + _DEFINE_ARRAY_FUNCTION(-, __minus) + _DEFINE_ARRAY_FUNCTION(*, __multiplies) + _DEFINE_ARRAY_FUNCTION(/, __divides) + _DEFINE_ARRAY_FUNCTION(%, __modulus) + _DEFINE_ARRAY_FUNCTION(^, __bitwise_xor) + _DEFINE_ARRAY_FUNCTION(|, __bitwise_or) + _DEFINE_ARRAY_FUNCTION(&, __bitwise_and) + _DEFINE_ARRAY_FUNCTION(<<, __shift_left) + _DEFINE_ARRAY_FUNCTION(>>, __shift_right) + +#undef _DEFINE_ARRAY_FUNCTION + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +# include + +#endif /* _ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc b/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc new file mode 100644 index 000000000..f97b780bc --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc @@ -0,0 +1,244 @@ +// The template and inlines for the -*- C++ -*- internal _Array helper class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/valarray_array.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _VALARRAY_ARRAY_TCC +#define _VALARRAY_ARRAY_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + void + __valarray_fill(_Array<_Tp> __a, size_t __n, _Array __m, + const _Tp& __t) + { + _Tp* __p = __a._M_data; + bool* __ok (__m._M_data); + for (size_t __i=0; __i < __n; ++__i, ++__ok, ++__p) + { + while (!*__ok) + { + ++__ok; + ++__p; + } + *__p = __t; + } + } + + // Copy n elements of a into consecutive elements of b. When m is + // false, the corresponding element of a is skipped. m must contain + // at least n true elements. a must contain at least n elements and + // enough elements to match up with m through the nth true element + // of m. I.e. if n is 10, m has 15 elements with 5 false followed + // by 10 true, a must have 15 elements. + template + void + __valarray_copy(_Array<_Tp> __a, _Array __m, _Array<_Tp> __b, + size_t __n) + { + _Tp* __p (__a._M_data); + bool* __ok (__m._M_data); + for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; + ++__q, ++__ok, ++__p) + { + while (! *__ok) + { + ++__ok; + ++__p; + } + *__q = *__p; + } + } + + // Copy n consecutive elements from a into elements of b. Elements + // of b are skipped if the corresponding element of m is false. m + // must contain at least n true elements. b must have at least as + // many elements as the index of the nth true element of m. I.e. if + // m has 15 elements with 5 false followed by 10 true, b must have + // at least 15 elements. + template + void + __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, + _Array __m) + { + _Tp* __q (__b._M_data); + bool* __ok (__m._M_data); + for (_Tp* __p = __a._M_data; __p < __a._M_data+__n; + ++__p, ++__ok, ++__q) + { + while (! *__ok) + { + ++__ok; + ++__q; + } + *__q = *__p; + } + } + + // Copy n elements from a into elements of b. Elements of a are + // skipped if the corresponding element of m is false. Elements of + // b are skipped if the corresponding element of k is false. m and + // k must contain at least n true elements. a and b must have at + // least as many elements as the index of the nth true element of m. + template + void + __valarray_copy(_Array<_Tp> __a, _Array __m, size_t __n, + _Array<_Tp> __b, _Array __k) + { + _Tp* __p (__a._M_data); + _Tp* __q (__b._M_data); + bool* __srcok (__m._M_data); + bool* __dstok (__k._M_data); + for (size_t __i = 0; __i < __n; + ++__srcok, ++__p, ++__dstok, ++__q, ++__i) + { + while (! *__srcok) + { + ++__srcok; + ++__p; + } + while (! *__dstok) + { + ++__dstok; + ++__q; + } + *__q = *__p; + } + } + + // Copy n consecutive elements of e into consecutive elements of a. + // I.e. a[i] = e[i]. + template + void + __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, _Array<_Tp> __a) + { + _Tp* __p (__a._M_data); + for (size_t __i = 0; __i < __n; ++__i, ++__p) + *__p = __e[__i]; + } + + // Copy n consecutive elements of e into elements of a using stride + // s. I.e., a[0] = e[0], a[s] = e[1], a[2*s] = e[2]. + template + void + __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, size_t __s) + { + _Tp* __p (__a._M_data); + for (size_t __i = 0; __i < __n; ++__i, __p += __s) + *__p = __e[__i]; + } + + // Copy n consecutive elements of e into elements of a indexed by + // contents of i. I.e., a[i[0]] = e[0]. + template + void + __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, _Array __i) + { + size_t* __j (__i._M_data); + for (size_t __k = 0; __k < __n; ++__k, ++__j) + __a._M_data[*__j] = __e[__k]; + } + + // Copy n elements of e indexed by contents of f into elements of a + // indexed by contents of i. I.e., a[i[0]] = e[f[0]]. + template + void + __valarray_copy(_Array<_Tp> __e, _Array __f, + size_t __n, + _Array<_Tp> __a, _Array __i) + { + size_t* __g (__f._M_data); + size_t* __j (__i._M_data); + for (size_t __k = 0; __k < __n; ++__k, ++__j, ++__g) + __a._M_data[*__j] = __e._M_data[*__g]; + } + + // Copy n consecutive elements of e into elements of a. Elements of + // a are skipped if the corresponding element of m is false. m must + // have at least n true elements and a must have at least as many + // elements as the index of the nth true element of m. I.e. if m + // has 5 false followed by 10 true elements and n == 10, a must have + // at least 15 elements. + template + void + __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, _Array __m) + { + bool* __ok (__m._M_data); + _Tp* __p (__a._M_data); + for (size_t __i = 0; __i < __n; ++__i, ++__ok, ++__p) + { + while (! *__ok) + { + ++__ok; + ++__p; + } + *__p = __e[__i]; + } + } + + + template + void + __valarray_copy_construct(const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a) + { + _Tp* __p (__a._M_data); + for (size_t __i = 0; __i < __n; ++__i, ++__p) + new (__p) _Tp(__e[__i]); + } + + + template + void + __valarray_copy_construct(_Array<_Tp> __a, _Array __m, + _Array<_Tp> __b, size_t __n) + { + _Tp* __p (__a._M_data); + bool* __ok (__m._M_data); + for (_Tp* __q = __b._M_data; __q < __b._M_data+__n; ++__q, ++__ok, ++__p) + { + while (! *__ok) + { + ++__ok; + ++__p; + } + new (__q) _Tp(*__p); + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _VALARRAY_ARRAY_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_before.h b/resources/sources/avr-libstdcpp/include/bits/valarray_before.h new file mode 100644 index 000000000..5c1c1c82a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/valarray_before.h @@ -0,0 +1,758 @@ +// The template and inlines for the -*- C++ -*- internal _Meta class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/valarray_before.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _VALARRAY_BEFORE_H +#define _VALARRAY_BEFORE_H 1 + +#pragma GCC system_header + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // + // Implementing a loosened valarray return value is tricky. + // First we need to meet 26.3.1/3: we should not add more than + // two levels of template nesting. Therefore we resort to template + // template to "flatten" loosened return value types. + // At some point we use partial specialization to remove one level + // template nesting due to _Expr<> + // + + // This class is NOT defined. It doesn't need to. + template class _Constant; + + // Implementations of unary functions applied to valarray<>s. + // I use hard-coded object functions here instead of a generic + // approach like pointers to function: + // 1) correctness: some functions take references, others values. + // we can't deduce the correct type afterwards. + // 2) efficiency -- object functions can be easily inlined + // 3) be Koenig-lookup-friendly + + struct _Abs + { + template + _Tp operator()(const _Tp& __t) const + { return abs(__t); } + }; + + struct _Cos + { + template + _Tp operator()(const _Tp& __t) const + { return cos(__t); } + }; + + struct _Acos + { + template + _Tp operator()(const _Tp& __t) const + { return acos(__t); } + }; + + struct _Cosh + { + template + _Tp operator()(const _Tp& __t) const + { return cosh(__t); } + }; + + struct _Sin + { + template + _Tp operator()(const _Tp& __t) const + { return sin(__t); } + }; + + struct _Asin + { + template + _Tp operator()(const _Tp& __t) const + { return asin(__t); } + }; + + struct _Sinh + { + template + _Tp operator()(const _Tp& __t) const + { return sinh(__t); } + }; + + struct _Tan + { + template + _Tp operator()(const _Tp& __t) const + { return tan(__t); } + }; + + struct _Atan + { + template + _Tp operator()(const _Tp& __t) const + { return atan(__t); } + }; + + struct _Tanh + { + template + _Tp operator()(const _Tp& __t) const + { return tanh(__t); } + }; + + struct _Exp + { + template + _Tp operator()(const _Tp& __t) const + { return exp(__t); } + }; + + struct _Log + { + template + _Tp operator()(const _Tp& __t) const + { return log(__t); } + }; + + struct _Log10 + { + template + _Tp operator()(const _Tp& __t) const + { return log10(__t); } + }; + + struct _Sqrt + { + template + _Tp operator()(const _Tp& __t) const + { return sqrt(__t); } + }; + + // In the past, we used to tailor operator applications semantics + // to the specialization of standard function objects (i.e. plus<>, etc.) + // That is incorrect. Therefore we provide our own surrogates. + + struct __unary_plus + { + template + _Tp operator()(const _Tp& __t) const + { return +__t; } + }; + + struct __negate + { + template + _Tp operator()(const _Tp& __t) const + { return -__t; } + }; + + struct __bitwise_not + { + template + _Tp operator()(const _Tp& __t) const + { return ~__t; } + }; + + struct __plus + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x + __y; } + }; + + struct __minus + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x - __y; } + }; + + struct __multiplies + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x * __y; } + }; + + struct __divides + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x / __y; } + }; + + struct __modulus + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x % __y; } + }; + + struct __bitwise_xor + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x ^ __y; } + }; + + struct __bitwise_and + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x & __y; } + }; + + struct __bitwise_or + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x | __y; } + }; + + struct __shift_left + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x << __y; } + }; + + struct __shift_right + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x >> __y; } + }; + + struct __logical_and + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x && __y; } + }; + + struct __logical_or + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x || __y; } + }; + + struct __logical_not + { + template + bool operator()(const _Tp& __x) const + { return !__x; } + }; + + struct __equal_to + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x == __y; } + }; + + struct __not_equal_to + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x != __y; } + }; + + struct __less + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x < __y; } + }; + + struct __greater + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x > __y; } + }; + + struct __less_equal + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x <= __y; } + }; + + struct __greater_equal + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x >= __y; } + }; + + // The few binary functions we miss. + struct _Atan2 + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return atan2(__x, __y); } + }; + + struct _Pow + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return pow(__x, __y); } + }; + + template + struct __fun_with_valarray + { + typedef _Tp result_type; + }; + + template + struct __fun_with_valarray<_Tp, false> + { + // No result type defined for invalid value types. + }; + + // We need these bits in order to recover the return type of + // some functions/operators now that we're no longer using + // function templates. + template + struct __fun : __fun_with_valarray<_Tp> + { + }; + + // several specializations for relational operators. + template + struct __fun<__logical_not, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__logical_and, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__logical_or, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__less, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__greater, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__less_equal, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__greater_equal, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__equal_to, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__not_equal_to, _Tp> + { + typedef bool result_type; + }; + +namespace __detail +{ + // Closure types already have reference semantics and are often short-lived, + // so store them by value to avoid (some cases of) dangling references to + // out-of-scope temporaries. + template + struct _ValArrayRef + { typedef const _Tp __type; }; + + // Use real references for std::valarray objects. + template + struct _ValArrayRef< valarray<_Tp> > + { typedef const valarray<_Tp>& __type; }; + + // + // Apply function taking a value/const reference closure + // + + template + class _FunBase + { + public: + typedef typename _Dom::value_type value_type; + + _FunBase(const _Dom& __e, value_type __f(_Arg)) + : _M_expr(__e), _M_func(__f) {} + + value_type operator[](size_t __i) const + { return _M_func (_M_expr[__i]); } + + size_t size() const { return _M_expr.size ();} + + private: + typename _ValArrayRef<_Dom>::__type _M_expr; + value_type (*_M_func)(_Arg); + }; + + template + struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type> + { + typedef _FunBase<_Dom, typename _Dom::value_type> _Base; + typedef typename _Base::value_type value_type; + typedef value_type _Tp; + + _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {} + }; + + template + struct _ValFunClos<_ValArray,_Tp> : _FunBase, _Tp> + { + typedef _FunBase, _Tp> _Base; + typedef _Tp value_type; + + _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {} + }; + + template + struct _RefFunClos<_Expr, _Dom> + : _FunBase<_Dom, const typename _Dom::value_type&> + { + typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base; + typedef typename _Base::value_type value_type; + typedef value_type _Tp; + + _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&)) + : _Base(__e, __f) {} + }; + + template + struct _RefFunClos<_ValArray, _Tp> + : _FunBase, const _Tp&> + { + typedef _FunBase, const _Tp&> _Base; + typedef _Tp value_type; + + _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&)) + : _Base(__v, __f) {} + }; + + // + // Unary expression closure. + // + + template + class _UnBase + { + public: + typedef typename _Arg::value_type _Vt; + typedef typename __fun<_Oper, _Vt>::result_type value_type; + + _UnBase(const _Arg& __e) : _M_expr(__e) {} + + value_type operator[](size_t __i) const + { return _Oper()(_M_expr[__i]); } + + size_t size() const { return _M_expr.size(); } + + private: + typename _ValArrayRef<_Arg>::__type _M_expr; + }; + + template + struct _UnClos<_Oper, _Expr, _Dom> + : _UnBase<_Oper, _Dom> + { + typedef _Dom _Arg; + typedef _UnBase<_Oper, _Dom> _Base; + typedef typename _Base::value_type value_type; + + _UnClos(const _Arg& __e) : _Base(__e) {} + }; + + template + struct _UnClos<_Oper, _ValArray, _Tp> + : _UnBase<_Oper, valarray<_Tp> > + { + typedef valarray<_Tp> _Arg; + typedef _UnBase<_Oper, valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _UnClos(const _Arg& __e) : _Base(__e) {} + }; + + + // + // Binary expression closure. + // + + template + class _BinBase + { + public: + typedef typename _FirstArg::value_type _Vt; + typedef typename __fun<_Oper, _Vt>::result_type value_type; + + _BinBase(const _FirstArg& __e1, const _SecondArg& __e2) + : _M_expr1(__e1), _M_expr2(__e2) {} + + value_type operator[](size_t __i) const + { return _Oper()(_M_expr1[__i], _M_expr2[__i]); } + + size_t size() const { return _M_expr1.size(); } + + private: + typename _ValArrayRef<_FirstArg>::__type _M_expr1; + typename _ValArrayRef<_SecondArg>::__type _M_expr2; + }; + + + template + class _BinBase2 + { + public: + typedef typename _Clos::value_type _Vt; + typedef typename __fun<_Oper, _Vt>::result_type value_type; + + _BinBase2(const _Clos& __e, const _Vt& __t) + : _M_expr1(__e), _M_expr2(__t) {} + + value_type operator[](size_t __i) const + { return _Oper()(_M_expr1[__i], _M_expr2); } + + size_t size() const { return _M_expr1.size(); } + + private: + typename _ValArrayRef<_Clos>::__type _M_expr1; + _Vt _M_expr2; + }; + + template + class _BinBase1 + { + public: + typedef typename _Clos::value_type _Vt; + typedef typename __fun<_Oper, _Vt>::result_type value_type; + + _BinBase1(const _Vt& __t, const _Clos& __e) + : _M_expr1(__t), _M_expr2(__e) {} + + value_type operator[](size_t __i) const + { return _Oper()(_M_expr1, _M_expr2[__i]); } + + size_t size() const { return _M_expr2.size(); } + + private: + _Vt _M_expr1; + typename _ValArrayRef<_Clos>::__type _M_expr2; + }; + + template + struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2> + : _BinBase<_Oper, _Dom1, _Dom2> + { + typedef _BinBase<_Oper, _Dom1, _Dom2> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _ValArray, _ValArray, _Tp, _Tp> + : _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > + { + typedef _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w) + : _Base(__v, __w) {} + }; + + template + struct _BinClos<_Oper, _Expr, _ValArray, _Dom, typename _Dom::value_type> + : _BinBase<_Oper, _Dom, valarray > + { + typedef typename _Dom::value_type _Tp; + typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2) + : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _ValArray, _Expr, typename _Dom::value_type, _Dom> + : _BinBase<_Oper, valarray,_Dom> + { + typedef typename _Dom::value_type _Tp; + typedef _BinBase<_Oper, valarray<_Tp>, _Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2) + : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _Expr, _Constant, _Dom, typename _Dom::value_type> + : _BinBase2<_Oper, _Dom> + { + typedef typename _Dom::value_type _Tp; + typedef _BinBase2<_Oper,_Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _Constant, _Expr, typename _Dom::value_type, _Dom> + : _BinBase1<_Oper, _Dom> + { + typedef typename _Dom::value_type _Tp; + typedef _BinBase1<_Oper, _Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _ValArray, _Constant, _Tp, _Tp> + : _BinBase2<_Oper, valarray<_Tp> > + { + typedef _BinBase2<_Oper,valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {} + }; + + template + struct _BinClos<_Oper, _Constant, _ValArray, _Tp, _Tp> + : _BinBase1<_Oper, valarray<_Tp> > + { + typedef _BinBase1<_Oper, valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {} + }; + + // + // slice_array closure. + // + template + class _SBase + { + public: + typedef typename _Dom::value_type value_type; + + _SBase (const _Dom& __e, const slice& __s) + : _M_expr (__e), _M_slice (__s) {} + + value_type + operator[] (size_t __i) const + { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; } + + size_t + size() const + { return _M_slice.size (); } + + private: + typename _ValArrayRef<_Dom>::__type _M_expr; + const slice& _M_slice; + }; + + template + class _SBase<_Array<_Tp> > + { + public: + typedef _Tp value_type; + + _SBase (_Array<_Tp> __a, const slice& __s) + : _M_array (__a._M_data+__s.start()), _M_size (__s.size()), + _M_stride (__s.stride()) {} + + value_type + operator[] (size_t __i) const + { return _M_array._M_data[__i * _M_stride]; } + + size_t + size() const + { return _M_size; } + + private: + const _Array<_Tp> _M_array; + const size_t _M_size; + const size_t _M_stride; + }; + + template + struct _SClos<_Expr, _Dom> + : _SBase<_Dom> + { + typedef _SBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {} + }; + + template + struct _SClos<_ValArray, _Tp> + : _SBase<_Array<_Tp> > + { + typedef _SBase<_Array<_Tp> > _Base; + typedef _Tp value_type; + + _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {} + }; +} // namespace __detail + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _CPP_VALARRAY_BEFORE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/vector.tcc b/resources/sources/avr-libstdcpp/include/bits/vector.tcc new file mode 100644 index 000000000..27e63388f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/vector.tcc @@ -0,0 +1,1008 @@ +// Vector implementation (out of line) -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/vector.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{vector} + */ + +#ifndef _VECTOR_TCC +#define _VECTOR_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + void + vector<_Tp, _Alloc>:: + reserve(size_type __n) + { + if (__n > this->max_size()) + __throw_length_error(__N("vector::reserve")); + if (this->capacity() < __n) + { + const size_type __old_size = size(); + pointer __tmp; +#if __cplusplus >= 201103L + if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) + { + __tmp = this->_M_allocate(__n); + _S_relocate(this->_M_impl._M_start, this->_M_impl._M_finish, + __tmp, _M_get_Tp_allocator()); + } + else +#endif + { + __tmp = _M_allocate_and_copy(__n, + _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start), + _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish)); + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + } + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __tmp; + this->_M_impl._M_finish = __tmp + __old_size; + this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; + } + } + +#if __cplusplus >= 201103L + template + template +#if __cplusplus > 201402L + typename vector<_Tp, _Alloc>::reference +#else + void +#endif + vector<_Tp, _Alloc>:: + emplace_back(_Args&&... __args) + { + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + _M_realloc_insert(end(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif + } +#endif + + template + typename vector<_Tp, _Alloc>::iterator + vector<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { + const size_type __n = __position - begin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == end()) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + __x); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + { +#if __cplusplus >= 201103L + const auto __pos = begin() + (__position - cbegin()); + // __x could be an existing element of this vector, so make a + // copy of it before _M_insert_aux moves elements around. + _Temporary_value __x_copy(this, __x); + _M_insert_aux(__pos, std::move(__x_copy._M_val())); +#else + _M_insert_aux(__position, __x); +#endif + } + else +#if __cplusplus >= 201103L + _M_realloc_insert(begin() + (__position - cbegin()), __x); +#else + _M_realloc_insert(__position, __x); +#endif + + return iterator(this->_M_impl._M_start + __n); + } + + template + typename vector<_Tp, _Alloc>::iterator + vector<_Tp, _Alloc>:: + _M_erase(iterator __position) + { + if (__position + 1 != end()) + _GLIBCXX_MOVE3(__position + 1, end(), __position); + --this->_M_impl._M_finish; + _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); + _GLIBCXX_ASAN_ANNOTATE_SHRINK(1); + return __position; + } + + template + typename vector<_Tp, _Alloc>::iterator + vector<_Tp, _Alloc>:: + _M_erase(iterator __first, iterator __last) + { + if (__first != __last) + { + if (__last != end()) + _GLIBCXX_MOVE3(__last, end(), __first); + _M_erase_at_end(__first.base() + (end() - __last)); + } + return __first; + } + + template + vector<_Tp, _Alloc>& + vector<_Tp, _Alloc>:: + operator=(const vector<_Tp, _Alloc>& __x) + { + if (&__x != this) + { + _GLIBCXX_ASAN_ANNOTATE_REINIT; +#if __cplusplus >= 201103L + if (_Alloc_traits::_S_propagate_on_copy_assign()) + { + if (!_Alloc_traits::_S_always_equal() + && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) + { + // replacement allocator cannot free existing storage + this->clear(); + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = nullptr; + this->_M_impl._M_finish = nullptr; + this->_M_impl._M_end_of_storage = nullptr; + } + std::__alloc_on_copy(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + } +#endif + const size_type __xlen = __x.size(); + if (__xlen > capacity()) + { + pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), + __x.end()); + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __tmp; + this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __xlen; + } + else if (size() >= __xlen) + { + std::_Destroy(std::copy(__x.begin(), __x.end(), begin()), + end(), _M_get_Tp_allocator()); + } + else + { + std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(), + this->_M_impl._M_start); + std::__uninitialized_copy_a(__x._M_impl._M_start + size(), + __x._M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + } + this->_M_impl._M_finish = this->_M_impl._M_start + __xlen; + } + return *this; + } + + template + void + vector<_Tp, _Alloc>:: + _M_fill_assign(size_t __n, const value_type& __val) + { + if (__n > capacity()) + { + vector __tmp(__n, __val, _M_get_Tp_allocator()); + __tmp._M_impl._M_swap_data(this->_M_impl); + } + else if (__n > size()) + { + std::fill(begin(), end(), __val); + const size_type __add = __n - size(); + _GLIBCXX_ASAN_ANNOTATE_GROW(__add); + this->_M_impl._M_finish = + std::__uninitialized_fill_n_a(this->_M_impl._M_finish, + __add, __val, _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__add); + } + else + _M_erase_at_end(std::fill_n(this->_M_impl._M_start, __n, __val)); + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + pointer __cur(this->_M_impl._M_start); + for (; __first != __last && __cur != this->_M_impl._M_finish; + ++__cur, (void)++__first) + *__cur = *__first; + if (__first == __last) + _M_erase_at_end(__cur); + else + _M_range_insert(end(), __first, __last, + std::__iterator_category(__first)); + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __len = std::distance(__first, __last); + + if (__len > capacity()) + { + _S_check_init_len(__len, _M_get_Tp_allocator()); + pointer __tmp(_M_allocate_and_copy(__len, __first, __last)); + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __tmp; + this->_M_impl._M_finish = this->_M_impl._M_start + __len; + this->_M_impl._M_end_of_storage = this->_M_impl._M_finish; + } + else if (size() >= __len) + _M_erase_at_end(std::copy(__first, __last, this->_M_impl._M_start)); + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, size()); + std::copy(__first, __mid, this->_M_impl._M_start); + const size_type __attribute__((__unused__)) __n = __len - size(); + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + this->_M_impl._M_finish = + std::__uninitialized_copy_a(__mid, __last, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + } + } + +#if __cplusplus >= 201103L + template + auto + vector<_Tp, _Alloc>:: + _M_insert_rval(const_iterator __position, value_type&& __v) -> iterator + { + const auto __n = __position - cbegin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == cend()) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::move(__v)); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + _M_insert_aux(begin() + __n, std::move(__v)); + else + _M_realloc_insert(begin() + __n, std::move(__v)); + + return iterator(this->_M_impl._M_start + __n); + } + + template + template + auto + vector<_Tp, _Alloc>:: + _M_emplace_aux(const_iterator __position, _Args&&... __args) + -> iterator + { + const auto __n = __position - cbegin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == cend()) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + { + // We need to construct a temporary because something in __args... + // could alias one of the elements of the container and so we + // need to use it before _M_insert_aux moves elements around. + _Temporary_value __tmp(this, std::forward<_Args>(__args)...); + _M_insert_aux(begin() + __n, std::move(__tmp._M_val())); + } + else + _M_realloc_insert(begin() + __n, std::forward<_Args>(__args)...); + + return iterator(this->_M_impl._M_start + __n); + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_insert_aux(iterator __position, _Arg&& __arg) +#else + template + void + vector<_Tp, _Alloc>:: + _M_insert_aux(iterator __position, const _Tp& __x) +#endif + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + _GLIBCXX_MOVE(*(this->_M_impl._M_finish - 1))); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); +#if __cplusplus < 201103L + _Tp __x_copy = __x; +#endif + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + this->_M_impl._M_finish - 2, + this->_M_impl._M_finish - 1); +#if __cplusplus < 201103L + *__position = __x_copy; +#else + *__position = std::forward<_Arg>(__arg); +#endif + } + +#if __cplusplus >= 201103L + template + template + void + vector<_Tp, _Alloc>:: + _M_realloc_insert(iterator __position, _Args&&... __args) +#else + template + void + vector<_Tp, _Alloc>:: + _M_realloc_insert(iterator __position, const _Tp& __x) +#endif + { + const size_type __len = + _M_check_len(size_type(1), "vector::_M_realloc_insert"); + pointer __old_start = this->_M_impl._M_start; + pointer __old_finish = this->_M_impl._M_finish; + const size_type __elems_before = __position - begin(); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + __try + { + // The order of the three operations is dictated by the C++11 + // case, where the moves could alter a new element belonging + // to the existing vector. This is an issue only for callers + // taking the element by lvalue ref (see last bullet of C++11 + // [res.on.arguments]). + _Alloc_traits::construct(this->_M_impl, + __new_start + __elems_before, +#if __cplusplus >= 201103L + std::forward<_Args>(__args)...); +#else + __x); +#endif + __new_finish = pointer(); + +#if __cplusplus >= 201103L + if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) + { + __new_finish = _S_relocate(__old_start, __position.base(), + __new_start, _M_get_Tp_allocator()); + + ++__new_finish; + + __new_finish = _S_relocate(__position.base(), __old_finish, + __new_finish, _M_get_Tp_allocator()); + } + else +#endif + { + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__old_start, __position.base(), + __new_start, _M_get_Tp_allocator()); + + ++__new_finish; + + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__position.base(), __old_finish, + __new_finish, _M_get_Tp_allocator()); + } + } + __catch(...) + { + if (!__new_finish) + _Alloc_traits::destroy(this->_M_impl, + __new_start + __elems_before); + else + std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } +#if __cplusplus >= 201103L + if _GLIBCXX17_CONSTEXPR (!_S_use_relocate()) +#endif + std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(__old_start, + this->_M_impl._M_end_of_storage - __old_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + + template + void + vector<_Tp, _Alloc>:: + _M_fill_insert(iterator __position, size_type __n, const value_type& __x) + { + if (__n != 0) + { + if (size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_finish) >= __n) + { +#if __cplusplus < 201103L + value_type __x_copy = __x; +#else + _Temporary_value __tmp(this, __x); + value_type& __x_copy = __tmp._M_val(); +#endif + const size_type __elems_after = end() - __position; + pointer __old_finish(this->_M_impl._M_finish); + if (__elems_after > __n) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + std::__uninitialized_move_a(this->_M_impl._M_finish - __n, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __n; + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + __old_finish - __n, __old_finish); + std::fill(__position.base(), __position.base() + __n, + __x_copy); + } + else + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + this->_M_impl._M_finish = + std::__uninitialized_fill_n_a(this->_M_impl._M_finish, + __n - __elems_after, + __x_copy, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after); + std::__uninitialized_move_a(__position.base(), __old_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __elems_after; + _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after); + std::fill(__position.base(), __old_finish, __x_copy); + } + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_fill_insert"); + const size_type __elems_before = __position - begin(); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + __try + { + // See _M_realloc_insert above. + std::__uninitialized_fill_n_a(__new_start + __elems_before, + __n, __x, + _M_get_Tp_allocator()); + __new_finish = pointer(); + + __new_finish + = std::__uninitialized_move_if_noexcept_a + (this->_M_impl._M_start, __position.base(), + __new_start, _M_get_Tp_allocator()); + + __new_finish += __n; + + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__position.base(), this->_M_impl._M_finish, + __new_finish, _M_get_Tp_allocator()); + } + __catch(...) + { + if (!__new_finish) + std::_Destroy(__new_start + __elems_before, + __new_start + __elems_before + __n, + _M_get_Tp_allocator()); + else + std::_Destroy(__new_start, __new_finish, + _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + } + } + +#if __cplusplus >= 201103L + template + void + vector<_Tp, _Alloc>:: + _M_default_append(size_type __n) + { + if (__n != 0) + { + const size_type __size = size(); + size_type __navail = size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_finish); + + if (__size > max_size() || __navail > max_size() - __size) + __builtin_unreachable(); + + if (__navail >= __n) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + this->_M_impl._M_finish = + std::__uninitialized_default_n_a(this->_M_impl._M_finish, + __n, _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_default_append"); + pointer __new_start(this->_M_allocate(__len)); + if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) + { + __try + { + std::__uninitialized_default_n_a(__new_start + __size, + __n, _M_get_Tp_allocator()); + } + __catch(...) + { + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + _S_relocate(this->_M_impl._M_start, this->_M_impl._M_finish, + __new_start, _M_get_Tp_allocator()); + } + else + { + pointer __destroy_from = pointer(); + __try + { + std::__uninitialized_default_n_a(__new_start + __size, + __n, _M_get_Tp_allocator()); + __destroy_from = __new_start + __size; + std::__uninitialized_move_if_noexcept_a( + this->_M_impl._M_start, this->_M_impl._M_finish, + __new_start, _M_get_Tp_allocator()); + } + __catch(...) + { + if (__destroy_from) + std::_Destroy(__destroy_from, __destroy_from + __n, + _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + } + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_start + __size + __n; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + } + } + + template + bool + vector<_Tp, _Alloc>:: + _M_shrink_to_fit() + { + if (capacity() == size()) + return false; + _GLIBCXX_ASAN_ANNOTATE_REINIT; + return std::__shrink_to_fit_aux::_S_do_it(*this); + } +#endif + + template + template + void + vector<_Tp, _Alloc>:: + _M_range_insert(iterator __pos, _InputIterator __first, + _InputIterator __last, std::input_iterator_tag) + { + if (__pos == end()) + { + for (; __first != __last; ++__first) + insert(end(), *__first); + } + else if (__first != __last) + { + vector __tmp(__first, __last, _M_get_Tp_allocator()); + insert(__pos, + _GLIBCXX_MAKE_MOVE_ITERATOR(__tmp.begin()), + _GLIBCXX_MAKE_MOVE_ITERATOR(__tmp.end())); + } + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_range_insert(iterator __position, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag) + { + if (__first != __last) + { + const size_type __n = std::distance(__first, __last); + if (size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_finish) >= __n) + { + const size_type __elems_after = end() - __position; + pointer __old_finish(this->_M_impl._M_finish); + if (__elems_after > __n) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + std::__uninitialized_move_a(this->_M_impl._M_finish - __n, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __n; + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + __old_finish - __n, __old_finish); + std::copy(__first, __last, __position); + } + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, __elems_after); + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + std::__uninitialized_copy_a(__mid, __last, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __n - __elems_after; + _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after); + std::__uninitialized_move_a(__position.base(), + __old_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __elems_after; + _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after); + std::copy(__first, __mid, __position); + } + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_range_insert"); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + __try + { + __new_finish + = std::__uninitialized_move_if_noexcept_a + (this->_M_impl._M_start, __position.base(), + __new_start, _M_get_Tp_allocator()); + __new_finish + = std::__uninitialized_copy_a(__first, __last, + __new_finish, + _M_get_Tp_allocator()); + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__position.base(), this->_M_impl._M_finish, + __new_finish, _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(__new_start, __new_finish, + _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + } + } + + + // vector + template + void + vector:: + _M_reallocate(size_type __n) + { + _Bit_pointer __q = this->_M_allocate(__n); + iterator __start(std::__addressof(*__q), 0); + iterator __finish(_M_copy_aligned(begin(), end(), __start)); + this->_M_deallocate(); + this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; + this->_M_impl._M_end_of_storage = __q + _S_nword(__n); + } + + template + void + vector:: + _M_fill_insert(iterator __position, size_type __n, bool __x) + { + if (__n == 0) + return; + if (capacity() - size() >= __n) + { + std::copy_backward(__position, end(), + this->_M_impl._M_finish + difference_type(__n)); + std::fill(__position, __position + difference_type(__n), __x); + this->_M_impl._M_finish += difference_type(__n); + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_fill_insert"); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); + std::fill(__i, __i + difference_type(__n), __x); + iterator __finish = std::copy(__position, end(), + __i + difference_type(__n)); + this->_M_deallocate(); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); + this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; + } + } + + template + template + void + vector:: + _M_insert_range(iterator __position, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag) + { + if (__first != __last) + { + size_type __n = std::distance(__first, __last); + if (capacity() - size() >= __n) + { + std::copy_backward(__position, end(), + this->_M_impl._M_finish + + difference_type(__n)); + std::copy(__first, __last, __position); + this->_M_impl._M_finish += difference_type(__n); + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_insert_range"); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); + __i = std::copy(__first, __last, __i); + iterator __finish = std::copy(__position, end(), __i); + this->_M_deallocate(); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); + this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; + } + } + } + + template + void + vector:: + _M_insert_aux(iterator __position, bool __x) + { + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) + { + std::copy_backward(__position, this->_M_impl._M_finish, + this->_M_impl._M_finish + 1); + *__position = __x; + ++this->_M_impl._M_finish; + } + else + { + const size_type __len = + _M_check_len(size_type(1), "vector::_M_insert_aux"); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); + *__i++ = __x; + iterator __finish = std::copy(__position, end(), __i); + this->_M_deallocate(); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); + this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; + } + } + + template + typename vector::iterator + vector:: + _M_erase(iterator __position) + { + if (__position + 1 != end()) + std::copy(__position + 1, end(), __position); + --this->_M_impl._M_finish; + return __position; + } + + template + typename vector::iterator + vector:: + _M_erase(iterator __first, iterator __last) + { + if (__first != __last) + _M_erase_at_end(std::copy(__last, end(), __first)); + return __first; + } + +#if __cplusplus >= 201103L + template + bool + vector:: + _M_shrink_to_fit() + { + if (capacity() - size() < int(_S_word_bit)) + return false; + __try + { + _M_reallocate(size()); + return true; + } + __catch(...) + { return false; } + } +#endif + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + size_t + hash<_GLIBCXX_STD_C::vector>:: + operator()(const _GLIBCXX_STD_C::vector& __b) const noexcept + { + size_t __hash = 0; + using _GLIBCXX_STD_C::_S_word_bit; + using _GLIBCXX_STD_C::_Bit_type; + + const size_t __words = __b.size() / _S_word_bit; + if (__words) + { + const size_t __clength = __words * sizeof(_Bit_type); + __hash = std::_Hash_impl::hash(__b._M_impl._M_start._M_p, __clength); + } + + const size_t __extrabits = __b.size() % _S_word_bit; + if (__extrabits) + { + _Bit_type __hiword = *__b._M_impl._M_finish._M_p; + __hiword &= ~((~static_cast<_Bit_type>(0)) << __extrabits); + + const size_t __clength + = (__extrabits + __CHAR_BIT__ - 1) / __CHAR_BIT__; + if (__words) + __hash = std::_Hash_impl::hash(&__hiword, __clength, __hash); + else + __hash = std::_Hash_impl::hash(&__hiword, __clength); + } + + return __hash; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#undef _GLIBCXX_ASAN_ANNOTATE_REINIT +#undef _GLIBCXX_ASAN_ANNOTATE_GROW +#undef _GLIBCXX_ASAN_ANNOTATE_GREW +#undef _GLIBCXX_ASAN_ANNOTATE_SHRINK + +#endif /* _VECTOR_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bitset b/resources/sources/avr-libstdcpp/include/bitset new file mode 100644 index 000000000..dc3910ac6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bitset @@ -0,0 +1,1245 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/bitset + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_BITSET +#define _GLIBCXX_BITSET 1 + +#pragma GCC system_header + +#include // For invalid_argument, out_of_range, + // overflow_error +#include + +#if __cplusplus >= 201103L +# include +#endif + +#define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * __SIZEOF_LONG__) +#define _GLIBCXX_BITSET_WORDS(__n) \ + ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \ + ((__n) % _GLIBCXX_BITSET_BITS_PER_WORD == 0 ? 0 : 1)) + +#define _GLIBCXX_BITSET_BITS_PER_ULL (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * Base class, general case. It is a class invariant that _Nw will be + * nonnegative. + * + * See documentation for bitset. + */ + template + struct _Base_bitset + { + typedef unsigned long _WordT; + + /// 0 is the least significant word. + _WordT _M_w[_Nw]; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + : _M_w() { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long __val) noexcept + : _M_w{ _WordT(__val) +#if __SIZEOF_LONG_LONG__ > __SIZEOF_LONG__ + , _WordT(__val >> _GLIBCXX_BITSET_BITS_PER_WORD) +#endif + } { } +#else + _Base_bitset(unsigned long __val) + : _M_w() + { _M_w[0] = __val; } +#endif + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + _WordT& + _M_getword(size_t __pos) _GLIBCXX_NOEXCEPT + { return _M_w[_S_whichword(__pos)]; } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t __pos) const _GLIBCXX_NOEXCEPT + { return _M_w[_S_whichword(__pos)]; } + +#if __cplusplus >= 201103L + const _WordT* + _M_getdata() const noexcept + { return _M_w; } +#endif + + _WordT& + _M_hiword() _GLIBCXX_NOEXCEPT + { return _M_w[_Nw - 1]; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return _M_w[_Nw - 1]; } + + void + _M_do_and(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] &= __x._M_w[__i]; + } + + void + _M_do_or(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] |= __x._M_w[__i]; + } + + void + _M_do_xor(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] ^= __x._M_w[__i]; + } + + void + _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT; + + void + _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT; + + void + _M_do_flip() _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] = ~_M_w[__i]; + } + + void + _M_do_set() _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] = ~static_cast<_WordT>(0); + } + + void + _M_do_reset() _GLIBCXX_NOEXCEPT + { __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT)); } + + bool + _M_is_equal(const _Base_bitset<_Nw>& __x) const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; ++__i) + if (_M_w[__i] != __x._M_w[__i]) + return false; + return true; + } + + template + bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw - 1; __i++) + if (_M_w[__i] != ~static_cast<_WordT>(0)) + return false; + return _M_hiword() == (~static_cast<_WordT>(0) + >> (_Nw * _GLIBCXX_BITSET_BITS_PER_WORD + - _Nb)); + } + + bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + if (_M_w[__i] != static_cast<_WordT>(0)) + return true; + return false; + } + + size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { + size_t __result = 0; + for (size_t __i = 0; __i < _Nw; __i++) + __result += __builtin_popcountl(_M_w[__i]); + return __result; + } + + unsigned long + _M_do_to_ulong() const; + +#if __cplusplus >= 201103L + unsigned long long + _M_do_to_ullong() const; +#endif + + // find first "on" bit + size_t + _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT; + + // find the next "on" bit that follows "prev" + size_t + _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT; + }; + + // Definitions of non-inline functions from _Base_bitset. + template + void + _Base_bitset<_Nw>::_M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__shift != 0, 1)) + { + const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; + + if (__offset == 0) + for (size_t __n = _Nw - 1; __n >= __wshift; --__n) + _M_w[__n] = _M_w[__n - __wshift]; + else + { + const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD + - __offset); + for (size_t __n = _Nw - 1; __n > __wshift; --__n) + _M_w[__n] = ((_M_w[__n - __wshift] << __offset) + | (_M_w[__n - __wshift - 1] >> __sub_offset)); + _M_w[__wshift] = _M_w[0] << __offset; + } + + std::fill(_M_w + 0, _M_w + __wshift, static_cast<_WordT>(0)); + } + } + + template + void + _Base_bitset<_Nw>::_M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__shift != 0, 1)) + { + const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __limit = _Nw - __wshift - 1; + + if (__offset == 0) + for (size_t __n = 0; __n <= __limit; ++__n) + _M_w[__n] = _M_w[__n + __wshift]; + else + { + const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD + - __offset); + for (size_t __n = 0; __n < __limit; ++__n) + _M_w[__n] = ((_M_w[__n + __wshift] >> __offset) + | (_M_w[__n + __wshift + 1] << __sub_offset)); + _M_w[__limit] = _M_w[_Nw-1] >> __offset; + } + + std::fill(_M_w + __limit + 1, _M_w + _Nw, static_cast<_WordT>(0)); + } + } + + template + unsigned long + _Base_bitset<_Nw>::_M_do_to_ulong() const + { + for (size_t __i = 1; __i < _Nw; ++__i) + if (_M_w[__i]) + __throw_overflow_error(__N("_Base_bitset::_M_do_to_ulong")); + return _M_w[0]; + } + +#if __cplusplus >= 201103L + template + unsigned long long + _Base_bitset<_Nw>::_M_do_to_ullong() const + { + const bool __dw = sizeof(unsigned long long) > sizeof(unsigned long); + for (size_t __i = 1 + __dw; __i < _Nw; ++__i) + if (_M_w[__i]) + __throw_overflow_error(__N("_Base_bitset::_M_do_to_ullong")); + + if (__dw) + return _M_w[0] + (static_cast(_M_w[1]) + << _GLIBCXX_BITSET_BITS_PER_WORD); + return _M_w[0]; + } +#endif + + template + size_t + _Base_bitset<_Nw>:: + _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + { + _WordT __thisword = _M_w[__i]; + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + } + // not found, so return an indication of failure. + return __not_found; + } + + template + size_t + _Base_bitset<_Nw>:: + _M_do_find_next(size_t __prev, size_t __not_found) const _GLIBCXX_NOEXCEPT + { + // make bound inclusive + ++__prev; + + // check out of bounds + if (__prev >= _Nw * _GLIBCXX_BITSET_BITS_PER_WORD) + return __not_found; + + // search first word + size_t __i = _S_whichword(__prev); + _WordT __thisword = _M_w[__i]; + + // mask off bits below bound + __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev); + + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + + // check subsequent words + __i++; + for (; __i < _Nw; __i++) + { + __thisword = _M_w[__i]; + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + } + // not found, so return an indication of failure. + return __not_found; + } // end _M_do_find_next + + /** + * Base class, specialization for a single word. + * + * See documentation for bitset. + */ + template<> + struct _Base_bitset<1> + { + typedef unsigned long _WordT; + _WordT _M_w; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + : _M_w(0) + { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long __val) noexcept +#else + _Base_bitset(unsigned long __val) +#endif + : _M_w(__val) + { } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + _WordT& + _M_getword(size_t) _GLIBCXX_NOEXCEPT + { return _M_w; } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t) const _GLIBCXX_NOEXCEPT + { return _M_w; } + +#if __cplusplus >= 201103L + const _WordT* + _M_getdata() const noexcept + { return &_M_w; } +#endif + + _WordT& + _M_hiword() _GLIBCXX_NOEXCEPT + { return _M_w; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return _M_w; } + + void + _M_do_and(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w &= __x._M_w; } + + void + _M_do_or(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w |= __x._M_w; } + + void + _M_do_xor(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w ^= __x._M_w; } + + void + _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { _M_w <<= __shift; } + + void + _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { _M_w >>= __shift; } + + void + _M_do_flip() _GLIBCXX_NOEXCEPT + { _M_w = ~_M_w; } + + void + _M_do_set() _GLIBCXX_NOEXCEPT + { _M_w = ~static_cast<_WordT>(0); } + + void + _M_do_reset() _GLIBCXX_NOEXCEPT + { _M_w = 0; } + + bool + _M_is_equal(const _Base_bitset<1>& __x) const _GLIBCXX_NOEXCEPT + { return _M_w == __x._M_w; } + + template + bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { return _M_w == (~static_cast<_WordT>(0) + >> (_GLIBCXX_BITSET_BITS_PER_WORD - _Nb)); } + + bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { return _M_w != 0; } + + size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { return __builtin_popcountl(_M_w); } + + unsigned long + _M_do_to_ulong() const _GLIBCXX_NOEXCEPT + { return _M_w; } + +#if __cplusplus >= 201103L + unsigned long long + _M_do_to_ullong() const noexcept + { return _M_w; } +#endif + + size_t + _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT + { + if (_M_w != 0) + return __builtin_ctzl(_M_w); + else + return __not_found; + } + + // find the next "on" bit that follows "prev" + size_t + _M_do_find_next(size_t __prev, size_t __not_found) const + _GLIBCXX_NOEXCEPT + { + ++__prev; + if (__prev >= ((size_t) _GLIBCXX_BITSET_BITS_PER_WORD)) + return __not_found; + + _WordT __x = _M_w >> __prev; + if (__x != 0) + return __builtin_ctzl(__x) + __prev; + else + return __not_found; + } + }; + + /** + * Base class, specialization for no storage (zero-length %bitset). + * + * See documentation for bitset. + */ + template<> + struct _Base_bitset<0> + { + typedef unsigned long _WordT; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long) noexcept +#else + _Base_bitset(unsigned long) +#endif + { } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + // This would normally give access to the data. The bounds-checking + // in the bitset class will prevent the user from getting this far, + // but (1) it must still return an lvalue to compile, and (2) the + // user might call _Unchecked_set directly, in which case this /needs/ + // to fail. Let's not penalize zero-length users unless they actually + // make an unchecked call; all the memory ugliness is therefore + // localized to this single should-never-get-this-far function. + _WordT& + _M_getword(size_t) _GLIBCXX_NOEXCEPT + { + __throw_out_of_range(__N("_Base_bitset::_M_getword")); + return *new _WordT; + } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return 0; } + + void + _M_do_and(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_or(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_xor(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_left_shift(size_t) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_right_shift(size_t) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_flip() _GLIBCXX_NOEXCEPT + { } + + void + _M_do_set() _GLIBCXX_NOEXCEPT + { } + + void + _M_do_reset() _GLIBCXX_NOEXCEPT + { } + + // Are all empty bitsets equal to each other? Are they equal to + // themselves? How to compare a thing which has no state? What is + // the sound of one zero-length bitset clapping? + bool + _M_is_equal(const _Base_bitset<0>&) const _GLIBCXX_NOEXCEPT + { return true; } + + template + bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { return true; } + + bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { return false; } + + size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { return 0; } + + unsigned long + _M_do_to_ulong() const _GLIBCXX_NOEXCEPT + { return 0; } + +#if __cplusplus >= 201103L + unsigned long long + _M_do_to_ullong() const noexcept + { return 0; } +#endif + + // Normally "not found" is the size, but that could also be + // misinterpreted as an index in this corner case. Oh well. + size_t + _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + + size_t + _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + }; + + + // Helper class to zero out the unused high-order bits in the highest word. + template + struct _Sanitize + { + typedef unsigned long _WordT; + + static void + _S_do_sanitize(_WordT& __val) _GLIBCXX_NOEXCEPT + { __val &= ~((~static_cast<_WordT>(0)) << _Extrabits); } + }; + + template<> + struct _Sanitize<0> + { + typedef unsigned long _WordT; + + static void + _S_do_sanitize(_WordT) _GLIBCXX_NOEXCEPT { } + }; + +#if __cplusplus >= 201103L + template + struct _Sanitize_val + { + static constexpr unsigned long long + _S_do_sanitize_val(unsigned long long __val) + { return __val; } + }; + + template + struct _Sanitize_val<_Nb, true> + { + static constexpr unsigned long long + _S_do_sanitize_val(unsigned long long __val) + { return __val & ~((~static_cast(0)) << _Nb); } + }; +#endif + + /** + * @brief The %bitset class represents a @e fixed-size sequence of bits. + * @ingroup utilities + * + * (Note that %bitset does @e not meet the formal requirements of a + * container. Mainly, it lacks iterators.) + * + * The template argument, @a Nb, may be any non-negative number, + * specifying the number of bits (e.g., "0", "12", "1024*1024"). + * + * In the general unoptimized case, storage is allocated in word-sized + * blocks. Let B be the number of bits in a word, then (Nb+(B-1))/B + * words will be used for storage. B - Nb%B bits are unused. (They are + * the high-order bits in the highest word.) It is a class invariant + * that those unused bits are always zero. + * + * If you think of %bitset as a simple array of bits, be + * aware that your mental picture is reversed: a %bitset behaves + * the same way as bits in integers do, with the bit at index 0 in + * the least significant / right-hand position, and the bit at + * index Nb-1 in the most significant / left-hand position. + * Thus, unlike other containers, a %bitset's index counts from + * right to left, to put it very loosely. + * + * + * Also see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_containers.html + * for a description of extensions. + * + * Most of the actual code isn't contained in %bitset<> itself, but in the + * base class _Base_bitset. The base class works with whole words, not with + * individual bits. This allows us to specialize _Base_bitset for the + * important special case where the %bitset is only a single word. + * + * Extra confusion can result due to the fact that the storage for + * _Base_bitset @e is a regular array, and is indexed as such. This is + * carefully encapsulated. + */ + template + class bitset + : private _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> + { + private: + typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base; + typedef unsigned long _WordT; + + void _M_check(size_t __position, const char *__s) const + { + if (__position >= _Nb) + __throw_out_of_range_fmt(__N("%s: __position (which is %zu) " + ">= _Nb (which is %zu)"), + __s, __position, _Nb); + } + + void + _M_do_sanitize() _GLIBCXX_NOEXCEPT + { + typedef _Sanitize<_Nb % _GLIBCXX_BITSET_BITS_PER_WORD> __sanitize_type; + __sanitize_type::_S_do_sanitize(this->_M_hiword()); + } + +#if __cplusplus >= 201103L + friend struct std::hash; +#endif + + public: + /** + * This encapsulates the concept of a single bit. An instance of this + * class is a proxy for an actual bit; this way the individual bit + * operations are done as faster word-size bitwise instructions. + * + * Most users will never need to use this class directly; conversions + * to and from bool are automatic and should be transparent. Overloaded + * operators help to preserve the illusion. + * + * (On a typical system, this bit %reference is 64 + * times the size of an actual bit. Ha.) + */ + class reference + { + friend class bitset; + + _WordT* _M_wp; + size_t _M_bpos; + + // left undefined + reference(); + + public: + reference(bitset& __b, size_t __pos) _GLIBCXX_NOEXCEPT + { + _M_wp = &__b._M_getword(__pos); + _M_bpos = _Base::_S_whichbit(__pos); + } + +#if __cplusplus >= 201103L + reference(const reference&) = default; +#endif + + ~reference() _GLIBCXX_NOEXCEPT + { } + + // For b[i] = __x; + reference& + operator=(bool __x) _GLIBCXX_NOEXCEPT + { + if (__x) + *_M_wp |= _Base::_S_maskbit(_M_bpos); + else + *_M_wp &= ~_Base::_S_maskbit(_M_bpos); + return *this; + } + + // For b[i] = b[__j]; + reference& + operator=(const reference& __j) _GLIBCXX_NOEXCEPT + { + if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos))) + *_M_wp |= _Base::_S_maskbit(_M_bpos); + else + *_M_wp &= ~_Base::_S_maskbit(_M_bpos); + return *this; + } + + // Flips the bit + bool + operator~() const _GLIBCXX_NOEXCEPT + { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) == 0; } + + // For __x = b[i]; + operator bool() const _GLIBCXX_NOEXCEPT + { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; } + + // For b[i].flip(); + reference& + flip() _GLIBCXX_NOEXCEPT + { + *_M_wp ^= _Base::_S_maskbit(_M_bpos); + return *this; + } + }; + friend class reference; + + // 23.3.5.1 constructors: + /// All bits set to zero. + _GLIBCXX_CONSTEXPR bitset() _GLIBCXX_NOEXCEPT + { } + + /// Initial bits bitwise-copied from a single word (others set to zero). +#if __cplusplus >= 201103L + constexpr bitset(unsigned long long __val) noexcept + : _Base(_Sanitize_val<_Nb>::_S_do_sanitize_val(__val)) { } +#else + bitset(unsigned long __val) + : _Base(__val) + { _M_do_sanitize(); } +#endif + + // 23.3.5.2 bitset operations: + //@{ + /** + * Operations on bitsets. + * @param __rhs A same-sized bitset. + * + * These should be self-explanatory. + */ + bitset<_Nb>& + operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_and(__rhs); + return *this; + } + + bitset<_Nb>& + operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_or(__rhs); + return *this; + } + + bitset<_Nb>& + operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_xor(__rhs); + return *this; + } + //@} + + //@{ + /** + * Operations on bitsets. + * @param __position The number of places to shift. + * + * These should be self-explanatory. + */ + bitset<_Nb>& + operator<<=(size_t __position) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__position < _Nb, 1)) + { + this->_M_do_left_shift(__position); + this->_M_do_sanitize(); + } + else + this->_M_do_reset(); + return *this; + } + + bitset<_Nb>& + operator>>=(size_t __position) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__position < _Nb, 1)) + { + this->_M_do_right_shift(__position); + this->_M_do_sanitize(); + } + else + this->_M_do_reset(); + return *this; + } + //@} + + //@{ + /** + * These versions of single-bit set, reset, flip, and test are + * extensions from the SGI version. They do no range checking. + * @ingroup SGIextensions + */ + bitset<_Nb>& + _Unchecked_set(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); + return *this; + } + + bitset<_Nb>& + _Unchecked_set(size_t __pos, int __val) _GLIBCXX_NOEXCEPT + { + if (__val) + this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); + else + this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); + return *this; + } + + bitset<_Nb>& + _Unchecked_reset(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); + return *this; + } + + bitset<_Nb>& + _Unchecked_flip(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos); + return *this; + } + + _GLIBCXX_CONSTEXPR bool + _Unchecked_test(size_t __pos) const _GLIBCXX_NOEXCEPT + { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos)) + != static_cast<_WordT>(0)); } + //@} + + // Set, reset, and flip. + /** + * @brief Sets every bit to true. + */ + bitset<_Nb>& + set() _GLIBCXX_NOEXCEPT + { + this->_M_do_set(); + this->_M_do_sanitize(); + return *this; + } + + /** + * @brief Sets a given bit to a particular value. + * @param __position The index of the bit. + * @param __val Either true or false, defaults to true. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + bitset<_Nb>& + set(size_t __position, bool __val = true) + { + this->_M_check(__position, __N("bitset::set")); + return _Unchecked_set(__position, __val); + } + + /** + * @brief Sets every bit to false. + */ + bitset<_Nb>& + reset() _GLIBCXX_NOEXCEPT + { + this->_M_do_reset(); + return *this; + } + + /** + * @brief Sets a given bit to false. + * @param __position The index of the bit. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + * + * Same as writing @c set(pos,false). + */ + bitset<_Nb>& + reset(size_t __position) + { + this->_M_check(__position, __N("bitset::reset")); + return _Unchecked_reset(__position); + } + + /** + * @brief Toggles every bit to its opposite value. + */ + bitset<_Nb>& + flip() _GLIBCXX_NOEXCEPT + { + this->_M_do_flip(); + this->_M_do_sanitize(); + return *this; + } + + /** + * @brief Toggles a given bit to its opposite value. + * @param __position The index of the bit. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + bitset<_Nb>& + flip(size_t __position) + { + this->_M_check(__position, __N("bitset::flip")); + return _Unchecked_flip(__position); + } + + /// See the no-argument flip(). + bitset<_Nb> + operator~() const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this).flip(); } + + //@{ + /** + * @brief Array-indexing support. + * @param __position Index into the %bitset. + * @return A bool for a const %bitset. For non-const + * bitsets, an instance of the reference proxy class. + * @note These operators do no range checking and throw no exceptions, + * as required by DR 11 to the standard. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS Note that this implementation already + * resolves DR 11 (items 1 and 2), but does not do the range-checking + * required by that DR's resolution. -pme + * The DR has since been changed: range-checking is a precondition + * (users' responsibility), and these functions must not throw. -pme + */ + reference + operator[](size_t __position) + { return reference(*this, __position); } + + _GLIBCXX_CONSTEXPR bool + operator[](size_t __position) const + { return _Unchecked_test(__position); } + //@} + + /** + * @brief Returns a numerical interpretation of the %bitset. + * @return The integral equivalent of the bits. + * @throw std::overflow_error If there are too many bits to be + * represented in an @c unsigned @c long. + */ + unsigned long + to_ulong() const + { return this->_M_do_to_ulong(); } + +#if __cplusplus >= 201103L + unsigned long long + to_ullong() const + { return this->_M_do_to_ullong(); } +#endif + + /// Returns the number of bits which are set. + size_t + count() const _GLIBCXX_NOEXCEPT + { return this->_M_do_count(); } + + /// Returns the total number of bits. + _GLIBCXX_CONSTEXPR size_t + size() const _GLIBCXX_NOEXCEPT + { return _Nb; } + + //@{ + /// These comparisons for equality/inequality are, well, @e bitwise. + bool + operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT + { return this->_M_is_equal(__rhs); } + +#if __cpp_impl_three_way_comparison < 201907L + bool + operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT + { return !this->_M_is_equal(__rhs); } +#endif + //@} + + /** + * @brief Tests the value of a bit. + * @param __position The index of a bit. + * @return The value at @a pos. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + bool + test(size_t __position) const + { + this->_M_check(__position, __N("bitset::test")); + return _Unchecked_test(__position); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 693. std::bitset::all() missing. + /** + * @brief Tests whether all the bits are on. + * @return True if all the bits are set. + */ + bool + all() const _GLIBCXX_NOEXCEPT + { return this->template _M_are_all<_Nb>(); } + + /** + * @brief Tests whether any of the bits are on. + * @return True if at least one bit is set. + */ + bool + any() const _GLIBCXX_NOEXCEPT + { return this->_M_is_any(); } + + /** + * @brief Tests whether any of the bits are on. + * @return True if none of the bits are set. + */ + bool + none() const _GLIBCXX_NOEXCEPT + { return !this->_M_is_any(); } + + //@{ + /// Self-explanatory. + bitset<_Nb> + operator<<(size_t __position) const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this) <<= __position; } + + bitset<_Nb> + operator>>(size_t __position) const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this) >>= __position; } + //@} + + /** + * @brief Finds the index of the first "on" bit. + * @return The index of the first bit set, or size() if not found. + * @ingroup SGIextensions + * @sa _Find_next + */ + size_t + _Find_first() const _GLIBCXX_NOEXCEPT + { return this->_M_do_find_first(_Nb); } + + /** + * @brief Finds the index of the next "on" bit after prev. + * @return The index of the next bit set, or size() if not found. + * @param __prev Where to start searching. + * @ingroup SGIextensions + * @sa _Find_first + */ + size_t + _Find_next(size_t __prev) const _GLIBCXX_NOEXCEPT + { return this->_M_do_find_next(__prev, _Nb); } + }; + + // 23.3.5.3 bitset operations: + //@{ + /** + * @brief Global bitwise operations on bitsets. + * @param __x A bitset. + * @param __y A bitset of the same size as @a __x. + * @return A new bitset. + * + * These should be self-explanatory. + */ + template + inline bitset<_Nb> + operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result &= __y; + return __result; + } + + template + inline bitset<_Nb> + operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result |= __y; + return __result; + } + + template + inline bitset<_Nb> + operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result ^= __y; + return __result; + } + //@} + +_GLIBCXX_END_NAMESPACE_CONTAINER +} // namespace std + +#undef _GLIBCXX_BITSET_WORDS +#undef _GLIBCXX_BITSET_BITS_PER_WORD +#undef _GLIBCXX_BITSET_BITS_PER_ULL + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // DR 1182. + /// std::hash specialization for bitset. + template + struct hash<_GLIBCXX_STD_C::bitset<_Nb>> + : public __hash_base> + { + size_t + operator()(const _GLIBCXX_STD_C::bitset<_Nb>& __b) const noexcept + { + const size_t __clength = (_Nb + __CHAR_BIT__ - 1) / __CHAR_BIT__; + return std::_Hash_impl::hash(__b._M_getdata(), __clength); + } + }; + + template<> + struct hash<_GLIBCXX_STD_C::bitset<0>> + : public __hash_base> + { + size_t + operator()(const _GLIBCXX_STD_C::bitset<0>&) const noexcept + { return 0; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#endif /* _GLIBCXX_BITSET */ diff --git a/resources/sources/avr-libstdcpp/include/cassert b/resources/sources/avr-libstdcpp/include/cassert new file mode 100644 index 000000000..e1c0724b8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cassert @@ -0,0 +1,44 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cassert + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c assert.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 19.2 Assertions +// + +// No include guards on this header... + +#pragma GCC system_header + +#include +#include diff --git a/resources/sources/avr-libstdcpp/include/ccomplex b/resources/sources/avr-libstdcpp/include/ccomplex new file mode 100644 index 000000000..7a9044444 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ccomplex @@ -0,0 +1,42 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ccomplex + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CCOMPLEX +#define _GLIBCXX_CCOMPLEX 1 + +#if __cplusplus < 201103L +# include +#endif + +extern "C++" { +#include +} + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cctype b/resources/sources/avr-libstdcpp/include/cctype new file mode 100644 index 000000000..0881d47c8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cctype @@ -0,0 +1,94 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cctype + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c ctype.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CCTYPE +#define _GLIBCXX_CCTYPE 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef isalnum +#undef isalpha +#undef iscntrl +#undef isdigit +#undef isgraph +#undef islower +#undef isprint +#undef ispunct +#undef isspace +#undef isupper +#undef isxdigit +#undef tolower +#undef toupper + +namespace std +{ + using ::isalnum; + using ::isalpha; + using ::iscntrl; + using ::isdigit; + using ::isgraph; + using ::islower; + using ::isprint; + using ::ispunct; + using ::isspace; + using ::isupper; + using ::isxdigit; + using ::tolower; + using ::toupper; +} // namespace std + +#if __cplusplus >= 201103L + +#ifdef _GLIBCXX_USE_C99_CTYPE_TR1 + +#undef isblank + +namespace std +{ + using ::isblank; +} // namespace std + +#endif // _GLIBCXX_USE_C99_CTYPE_TR1 + +#endif // C++11 + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cerrno b/resources/sources/avr-libstdcpp/include/cerrno new file mode 100644 index 000000000..83cbf24a0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cerrno @@ -0,0 +1,52 @@ +// The -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cerrno + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c errno.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 19.3 Error numbers +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CERRNO +#define _GLIBCXX_CERRNO 1 + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef errno +#define errno errno +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cfenv b/resources/sources/avr-libstdcpp/include/cfenv new file mode 100644 index 000000000..376eea234 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cfenv @@ -0,0 +1,84 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cfenv + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_CFENV +#define _GLIBCXX_CFENV 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +#if _GLIBCXX_HAVE_FENV_H +# include +#endif + +#ifdef _GLIBCXX_USE_C99_FENV_TR1 + +#undef feclearexcept +#undef fegetexceptflag +#undef feraiseexcept +#undef fesetexceptflag +#undef fetestexcept +#undef fegetround +#undef fesetround +#undef fegetenv +#undef feholdexcept +#undef fesetenv +#undef feupdateenv + +namespace std +{ + // types + using ::fenv_t; + using ::fexcept_t; + + // functions + using ::feclearexcept; + using ::fegetexceptflag; + using ::feraiseexcept; + using ::fesetexceptflag; + using ::fetestexcept; + + using ::fegetround; + using ::fesetround; + + using ::fegetenv; + using ::feholdexcept; + using ::fesetenv; + using ::feupdateenv; +} // namespace std + +#endif // _GLIBCXX_USE_C99_FENV_TR1 + +#endif // C++11 + +#endif // _GLIBCXX_CFENV diff --git a/resources/sources/avr-libstdcpp/include/cfloat b/resources/sources/avr-libstdcpp/include/cfloat new file mode 100644 index 000000000..3c20ea8f9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cfloat @@ -0,0 +1,56 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cfloat + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c float.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.2.2 Implementation properties: C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CFLOAT +#define _GLIBCXX_CFLOAT 1 + +#if __cplusplus >= 201103L +# ifndef DECIMAL_DIG +# define DECIMAL_DIG __DECIMAL_DIG__ +# endif +# ifndef FLT_EVAL_METHOD +# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ +# endif +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/chrono b/resources/sources/avr-libstdcpp/include/chrono new file mode 100644 index 000000000..ad8507090 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/chrono @@ -0,0 +1,1131 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/chrono + * This is a Standard C++ Library header. + * @ingroup chrono + */ + +#ifndef _GLIBCXX_CHRONO +#define _GLIBCXX_CHRONO 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include // for literals support. +#if __cplusplus > 201703L +# include +# include +#endif +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup chrono Time + * @ingroup utilities + * + * Classes and functions for time. + * @{ + */ + + /** @namespace std::chrono + * @brief ISO C++ 2011 namespace for date and time utilities + */ + namespace chrono + { + template> + struct duration; + + template + struct time_point; + } + + // 20.11.4.3 specialization of common_type (for duration, sfinae-friendly) + + /// @cond undocumented + + template + struct __duration_common_type + { }; + + template + struct __duration_common_type<_CT, _Period1, _Period2, + __void_t> + { + private: + using __gcd_num = __static_gcd<_Period1::num, _Period2::num>; + using __gcd_den = __static_gcd<_Period1::den, _Period2::den>; + using __cr = typename _CT::type; + using __r = ratio<__gcd_num::value, + (_Period1::den / __gcd_den::value) * _Period2::den>; + + public: + using type = chrono::duration<__cr, __r>; + }; + + template + struct __duration_common_type<__failure_type, _Period1, _Period2> + { typedef __failure_type type; }; + + /// @endcond + + /// Specialization of common_type for chrono::duration types. + /// @relates duration + template + struct common_type, + chrono::duration<_Rep2, _Period2>> + : __duration_common_type, _Period1, _Period2> + { }; + + // 20.11.4.3 specialization of common_type (for time_point, sfinae-friendly) + + /// @cond undocumented + + template + struct __timepoint_common_type + { }; + + template + struct __timepoint_common_type<_CT, _Clock, __void_t> + { + using type = chrono::time_point<_Clock, typename _CT::type>; + }; + + /// @endcond + + /// Specialization of common_type for chrono::time_point types. + /// @relates time_point + template + struct common_type, + chrono::time_point<_Clock, _Duration2>> + : __timepoint_common_type, _Clock> + { }; + + // @} group chrono + + namespace chrono + { + /// @addtogroup chrono + /// @{ + + /// @cond undocumented + + // Primary template for duration_cast impl. + template + struct __duration_cast_impl + { + template + static constexpr _ToDur + __cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::rep __to_rep; + return _ToDur(static_cast<__to_rep>(static_cast<_CR>(__d.count()) + * static_cast<_CR>(_CF::num) + / static_cast<_CR>(_CF::den))); + } + }; + + template + struct __duration_cast_impl<_ToDur, _CF, _CR, true, true> + { + template + static constexpr _ToDur + __cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::rep __to_rep; + return _ToDur(static_cast<__to_rep>(__d.count())); + } + }; + + template + struct __duration_cast_impl<_ToDur, _CF, _CR, true, false> + { + template + static constexpr _ToDur + __cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::rep __to_rep; + return _ToDur(static_cast<__to_rep>( + static_cast<_CR>(__d.count()) / static_cast<_CR>(_CF::den))); + } + }; + + template + struct __duration_cast_impl<_ToDur, _CF, _CR, false, true> + { + template + static constexpr _ToDur + __cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::rep __to_rep; + return _ToDur(static_cast<__to_rep>( + static_cast<_CR>(__d.count()) * static_cast<_CR>(_CF::num))); + } + }; + + template + struct __is_duration + : std::false_type + { }; + + template + struct __is_duration> + : std::true_type + { }; + + template + using __enable_if_is_duration + = typename enable_if<__is_duration<_Tp>::value, _Tp>::type; + + template + using __disable_if_is_duration + = typename enable_if::value, _Tp>::type; + + /// @endcond + + /// duration_cast + template + constexpr __enable_if_is_duration<_ToDur> + duration_cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::period __to_period; + typedef typename _ToDur::rep __to_rep; + typedef ratio_divide<_Period, __to_period> __cf; + typedef typename common_type<__to_rep, _Rep, intmax_t>::type + __cr; + typedef __duration_cast_impl<_ToDur, __cf, __cr, + __cf::num == 1, __cf::den == 1> __dc; + return __dc::__cast(__d); + } + + /// treat_as_floating_point + template + struct treat_as_floating_point + : is_floating_point<_Rep> + { }; + +#if __cplusplus > 201402L + template + inline constexpr bool treat_as_floating_point_v = + treat_as_floating_point<_Rep>::value; +#endif // C++17 + +#if __cplusplus > 201703L + template + struct is_clock; + + template + inline constexpr bool is_clock_v = is_clock<_Tp>::value; + +#if __cpp_lib_concepts + template + struct is_clock : false_type + { }; + + template + requires requires { + typename _Tp::rep; + typename _Tp::period; + typename _Tp::duration; + typename _Tp::time_point::clock; + typename _Tp::time_point::duration; + { &_Tp::is_steady } -> same_as; + { _Tp::now() } -> same_as; + requires same_as>; + requires same_as; + } + struct is_clock<_Tp> : true_type + { }; +#else + template + struct __is_clock_impl : false_type + { }; + + template + struct __is_clock_impl<_Tp, + void_t> + : __and_>, + is_same, + is_same, + is_same>::type + { }; + + template + struct is_clock : __is_clock_impl<_Tp>::type + { }; +#endif +#endif // C++20 + +#if __cplusplus >= 201703L +# define __cpp_lib_chrono 201611 + + template + constexpr __enable_if_is_duration<_ToDur> + floor(const duration<_Rep, _Period>& __d) + { + auto __to = chrono::duration_cast<_ToDur>(__d); + if (__to > __d) + return __to - _ToDur{1}; + return __to; + } + + template + constexpr __enable_if_is_duration<_ToDur> + ceil(const duration<_Rep, _Period>& __d) + { + auto __to = chrono::duration_cast<_ToDur>(__d); + if (__to < __d) + return __to + _ToDur{1}; + return __to; + } + + template + constexpr enable_if_t< + __and_<__is_duration<_ToDur>, + __not_>>::value, + _ToDur> + round(const duration<_Rep, _Period>& __d) + { + _ToDur __t0 = chrono::floor<_ToDur>(__d); + _ToDur __t1 = __t0 + _ToDur{1}; + auto __diff0 = __d - __t0; + auto __diff1 = __t1 - __d; + if (__diff0 == __diff1) + { + if (__t0.count() & 1) + return __t1; + return __t0; + } + else if (__diff0 < __diff1) + return __t0; + return __t1; + } + + template + constexpr + enable_if_t::is_signed, duration<_Rep, _Period>> + abs(duration<_Rep, _Period> __d) + { + if (__d >= __d.zero()) + return __d; + return -__d; + } +#endif // C++17 + + /// duration_values + template + struct duration_values + { + static constexpr _Rep + zero() noexcept + { return _Rep(0); } + + static constexpr _Rep + max() noexcept + { return numeric_limits<_Rep>::max(); } + + static constexpr _Rep + min() noexcept + { return numeric_limits<_Rep>::lowest(); } + }; + + /// @cond undocumented + + template + struct __is_ratio + : std::false_type + { }; + + template + struct __is_ratio> + : std::true_type + { }; + + /// @endcond + + /// duration + template + struct duration + { + private: + template + using __is_float = treat_as_floating_point<_Rep2>; + + // _Period2 is an exact multiple of _Period + template + using __is_harmonic + = __bool_constant::den == 1>; + + public: + + typedef _Rep rep; + typedef _Period period; + + static_assert(!__is_duration<_Rep>::value, "rep cannot be a duration"); + static_assert(__is_ratio<_Period>::value, + "period must be a specialization of ratio"); + static_assert(_Period::num > 0, "period must be positive"); + + // 20.11.5.1 construction / copy / destroy + constexpr duration() = default; + + duration(const duration&) = default; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3050. Conversion specification problem in chrono::duration + template, + __or_<__is_float, __not_<__is_float<_Rep2>>>>> + constexpr explicit duration(const _Rep2& __rep) + : __r(static_cast(__rep)) { } + + template, + __and_<__is_harmonic<_Period2>, + __not_<__is_float<_Rep2>>>>>> + constexpr duration(const duration<_Rep2, _Period2>& __d) + : __r(duration_cast(__d).count()) { } + + ~duration() = default; + duration& operator=(const duration&) = default; + + // 20.11.5.2 observer + constexpr rep + count() const + { return __r; } + + // 20.11.5.3 arithmetic + constexpr duration + operator+() const + { return *this; } + + constexpr duration + operator-() const + { return duration(-__r); } + + _GLIBCXX17_CONSTEXPR duration& + operator++() + { + ++__r; + return *this; + } + + _GLIBCXX17_CONSTEXPR duration + operator++(int) + { return duration(__r++); } + + _GLIBCXX17_CONSTEXPR duration& + operator--() + { + --__r; + return *this; + } + + _GLIBCXX17_CONSTEXPR duration + operator--(int) + { return duration(__r--); } + + _GLIBCXX17_CONSTEXPR duration& + operator+=(const duration& __d) + { + __r += __d.count(); + return *this; + } + + _GLIBCXX17_CONSTEXPR duration& + operator-=(const duration& __d) + { + __r -= __d.count(); + return *this; + } + + _GLIBCXX17_CONSTEXPR duration& + operator*=(const rep& __rhs) + { + __r *= __rhs; + return *this; + } + + _GLIBCXX17_CONSTEXPR duration& + operator/=(const rep& __rhs) + { + __r /= __rhs; + return *this; + } + + // DR 934. + template + _GLIBCXX17_CONSTEXPR + typename enable_if::value, + duration&>::type + operator%=(const rep& __rhs) + { + __r %= __rhs; + return *this; + } + + template + _GLIBCXX17_CONSTEXPR + typename enable_if::value, + duration&>::type + operator%=(const duration& __d) + { + __r %= __d.count(); + return *this; + } + + // 20.11.5.4 special values + static constexpr duration + zero() noexcept + { return duration(duration_values::zero()); } + + static constexpr duration + min() noexcept + { return duration(duration_values::min()); } + + static constexpr duration + max() noexcept + { return duration(duration_values::max()); } + + private: + rep __r; + }; + + /// @relates duration @{ + + /// The sum of two durations. + template + constexpr typename common_type, + duration<_Rep2, _Period2>>::type + operator+(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __cd; + return __cd(__cd(__lhs).count() + __cd(__rhs).count()); + } + + /// The difference between two durations. + template + constexpr typename common_type, + duration<_Rep2, _Period2>>::type + operator-(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __cd; + return __cd(__cd(__lhs).count() - __cd(__rhs).count()); + } + + /// @} + + /// @cond undocumented + + // SFINAE helper to obtain common_type<_Rep1, _Rep2> only if _Rep2 + // is implicitly convertible to it. + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3050. Conversion specification problem in chrono::duration constructor + template::type> + using __common_rep_t = typename + enable_if::value, _CRep>::type; + + /// @endcond + + /// @relates duration @{ + + /// Multiply a duration by a scalar value. + template + constexpr duration<__common_rep_t<_Rep1, _Rep2>, _Period> + operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) + { + typedef duration::type, _Period> + __cd; + return __cd(__cd(__d).count() * __s); + } + + /// Multiply a duration by a scalar value. + template + constexpr duration<__common_rep_t<_Rep2, _Rep1>, _Period> + operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) + { return __d * __s; } + + template + constexpr + duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period> + operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) + { + typedef duration::type, _Period> + __cd; + return __cd(__cd(__d).count() / __s); + } + + template + constexpr typename common_type<_Rep1, _Rep2>::type + operator/(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __cd; + return __cd(__lhs).count() / __cd(__rhs).count(); + } + + // DR 934. + template + constexpr + duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period> + operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) + { + typedef duration::type, _Period> + __cd; + return __cd(__cd(__d).count() % __s); + } + + template + constexpr typename common_type, + duration<_Rep2, _Period2>>::type + operator%(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __cd; + return __cd(__cd(__lhs).count() % __cd(__rhs).count()); + } + + // comparisons + + template + constexpr bool + operator==(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __ct; + return __ct(__lhs).count() == __ct(__rhs).count(); + } + + template + constexpr bool + operator<(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __ct; + return __ct(__lhs).count() < __ct(__rhs).count(); + } + +#if __cpp_lib_three_way_comparison + template + requires three_way_comparable> + constexpr auto + operator<=>(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + using __ct = common_type_t, + duration<_Rep2, _Period2>>; + return __ct(__lhs).count() <=> __ct(__rhs).count(); + } +#else + template + constexpr bool + operator!=(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { return !(__lhs == __rhs); } +#endif + + template + constexpr bool + operator<=(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { return !(__rhs < __lhs); } + + template + constexpr bool + operator>(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { return __rhs < __lhs; } + + template + constexpr bool + operator>=(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { return !(__lhs < __rhs); } + + /// @} + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +# define _GLIBCXX_CHRONO_INT64_T int64_t +#elif defined __INT64_TYPE__ +# define _GLIBCXX_CHRONO_INT64_T __INT64_TYPE__ +#else + static_assert(std::numeric_limits::digits >= 64, + "Representation type for nanoseconds must have at least 64 bits"); +# define _GLIBCXX_CHRONO_INT64_T long long +#endif + + /// nanoseconds + using nanoseconds = duration<_GLIBCXX_CHRONO_INT64_T, nano>; + + /// microseconds + using microseconds = duration<_GLIBCXX_CHRONO_INT64_T, micro>; + + /// milliseconds + using milliseconds = duration<_GLIBCXX_CHRONO_INT64_T, milli>; + + /// seconds + using seconds = duration<_GLIBCXX_CHRONO_INT64_T>; + + /// minutes + using minutes = duration<_GLIBCXX_CHRONO_INT64_T, ratio< 60>>; + + /// hours + using hours = duration<_GLIBCXX_CHRONO_INT64_T, ratio<3600>>; + +#if __cplusplus > 201703L + /// days + using days = duration<_GLIBCXX_CHRONO_INT64_T, ratio<86400>>; + + /// weeks + using weeks = duration<_GLIBCXX_CHRONO_INT64_T, ratio<604800>>; + + /// years + using years = duration<_GLIBCXX_CHRONO_INT64_T, ratio<31556952>>; + + /// months + using months = duration<_GLIBCXX_CHRONO_INT64_T, ratio<2629746>>; +#endif // C++20 + +#undef _GLIBCXX_CHRONO_INT64_T + + /// time_point + template + struct time_point + { + static_assert(__is_duration<_Dur>::value, + "duration must be a specialization of std::chrono::duration"); + + typedef _Clock clock; + typedef _Dur duration; + typedef typename duration::rep rep; + typedef typename duration::period period; + + constexpr time_point() : __d(duration::zero()) + { } + + constexpr explicit time_point(const duration& __dur) + : __d(__dur) + { } + + // conversions + template>> + constexpr time_point(const time_point& __t) + : __d(__t.time_since_epoch()) + { } + + // observer + constexpr duration + time_since_epoch() const + { return __d; } + + // arithmetic + _GLIBCXX17_CONSTEXPR time_point& + operator+=(const duration& __dur) + { + __d += __dur; + return *this; + } + + _GLIBCXX17_CONSTEXPR time_point& + operator-=(const duration& __dur) + { + __d -= __dur; + return *this; + } + + // special values + static constexpr time_point + min() noexcept + { return time_point(duration::min()); } + + static constexpr time_point + max() noexcept + { return time_point(duration::max()); } + + private: + duration __d; + }; + + /// time_point_cast + template + constexpr typename enable_if<__is_duration<_ToDur>::value, + time_point<_Clock, _ToDur>>::type + time_point_cast(const time_point<_Clock, _Dur>& __t) + { + typedef time_point<_Clock, _ToDur> __time_point; + return __time_point(duration_cast<_ToDur>(__t.time_since_epoch())); + } + +#if __cplusplus > 201402L + template + constexpr + enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>> + floor(const time_point<_Clock, _Dur>& __tp) + { + return time_point<_Clock, _ToDur>{ + chrono::floor<_ToDur>(__tp.time_since_epoch())}; + } + + template + constexpr + enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>> + ceil(const time_point<_Clock, _Dur>& __tp) + { + return time_point<_Clock, _ToDur>{ + chrono::ceil<_ToDur>(__tp.time_since_epoch())}; + } + + template + constexpr enable_if_t< + __and_<__is_duration<_ToDur>, + __not_>>::value, + time_point<_Clock, _ToDur>> + round(const time_point<_Clock, _Dur>& __tp) + { + return time_point<_Clock, _ToDur>{ + chrono::round<_ToDur>(__tp.time_since_epoch())}; + } +#endif // C++17 + + /// @relates time_point @{ + + /// Adjust a time point forwards by the given duration. + template + constexpr time_point<_Clock, + typename common_type<_Dur1, duration<_Rep2, _Period2>>::type> + operator+(const time_point<_Clock, _Dur1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<_Dur1,__dur2>::type __ct; + typedef time_point<_Clock, __ct> __time_point; + return __time_point(__lhs.time_since_epoch() + __rhs); + } + + /// Adjust a time point forwards by the given duration. + template + constexpr time_point<_Clock, + typename common_type, _Dur2>::type> + operator+(const duration<_Rep1, _Period1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef typename common_type<__dur1,_Dur2>::type __ct; + typedef time_point<_Clock, __ct> __time_point; + return __time_point(__rhs.time_since_epoch() + __lhs); + } + + /// Adjust a time point backwards by the given duration. + template + constexpr time_point<_Clock, + typename common_type<_Dur1, duration<_Rep2, _Period2>>::type> + operator-(const time_point<_Clock, _Dur1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<_Dur1,__dur2>::type __ct; + typedef time_point<_Clock, __ct> __time_point; + return __time_point(__lhs.time_since_epoch() -__rhs); + } + + /// @} + + /// @relates time_point @{ + + /// The difference between two time points (as a duration) + template + constexpr typename common_type<_Dur1, _Dur2>::type + operator-(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __lhs.time_since_epoch() - __rhs.time_since_epoch(); } + + template + constexpr bool + operator==(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __lhs.time_since_epoch() == __rhs.time_since_epoch(); } + +#if __cpp_lib_three_way_comparison + template _Dur2> + constexpr auto + operator<=>(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __lhs.time_since_epoch() <=> __rhs.time_since_epoch(); } +#else + template + constexpr bool + operator!=(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return !(__lhs == __rhs); } +#endif + + template + constexpr bool + operator<(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __lhs.time_since_epoch() < __rhs.time_since_epoch(); } + + template + constexpr bool + operator<=(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return !(__rhs < __lhs); } + + template + constexpr bool + operator>(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __rhs < __lhs; } + + template + constexpr bool + operator>=(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return !(__lhs < __rhs); } + + // @} + // @} + } // namespace chrono + +#if __cplusplus > 201103L + +#define __cpp_lib_chrono_udls 201304 + + inline namespace literals + { + /** ISO C++ 2014 namespace for suffixes for duration literals. + * + * These suffixes can be used to create `chrono::duration` values with + * tick periods of hours, minutes, seconds, milliseconds, microseconds + * or nanoseconds. For example, `std::chrono::seconds(5)` can be written + * as `5s` after making the suffix visible in the current scope. + * The suffixes can be made visible by a using-directive or + * using-declaration such as: + * - `using namespace std::chrono_literals;` + * - `using namespace std::literals;` + * - `using namespace std::chrono;` + * - `using namespace std;` + * - `using std::chrono_literals::operator""s;` + * + * The result of these suffixes on an integer literal is one of the + * standard typedefs such as `std::chrono::hours`. + * The result on a floating-point literal is a duration type with the + * specified tick period and an unspecified floating-point representation, + * for example `1.5e2ms` might be equivalent to + * `chrono::duration(1.5e2)`. + * + * @ingroup chrono + */ + inline namespace chrono_literals + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" + /// @cond undocumented + template + constexpr _Dur __check_overflow() + { + using _Val = __parse_int::_Parse_int<_Digits...>; + constexpr typename _Dur::rep __repval = _Val::value; + static_assert(__repval >= 0 && __repval == _Val::value, + "literal value cannot be represented by duration type"); + return _Dur(__repval); + } + /// @endcond + + /// Literal suffix for durations representing non-integer hours + constexpr chrono::duration> + operator""h(long double __hours) + { return chrono::duration>{__hours}; } + + /// Literal suffix for durations of type `std::chrono::hours` + template + constexpr chrono::hours + operator""h() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer minutes + constexpr chrono::duration> + operator""min(long double __mins) + { return chrono::duration>{__mins}; } + + /// Literal suffix for durations of type `std::chrono::minutes` + template + constexpr chrono::minutes + operator""min() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer seconds + constexpr chrono::duration + operator""s(long double __secs) + { return chrono::duration{__secs}; } + + /// Literal suffix for durations of type `std::chrono::seconds` + template + constexpr chrono::seconds + operator""s() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer milliseconds + constexpr chrono::duration + operator""ms(long double __msecs) + { return chrono::duration{__msecs}; } + + /// Literal suffix for durations of type `std::chrono::milliseconds` + template + constexpr chrono::milliseconds + operator""ms() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer microseconds + constexpr chrono::duration + operator""us(long double __usecs) + { return chrono::duration{__usecs}; } + + /// Literal suffix for durations of type `std::chrono::microseconds` + template + constexpr chrono::microseconds + operator""us() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer nanoseconds + constexpr chrono::duration + operator""ns(long double __nsecs) + { return chrono::duration{__nsecs}; } + + /// Literal suffix for durations of type `std::chrono::nanoseconds` + template + constexpr chrono::nanoseconds + operator""ns() + { return __check_overflow(); } + +#pragma GCC diagnostic pop + } // inline namespace chrono_literals + } // inline namespace literals + + namespace chrono + { + using namespace literals::chrono_literals; + } // namespace chrono + +#endif // C++14 + + namespace chrono + { + class high_resolution_clock + { + public: + // The high_resolution_clock counter is steady. Each subsequent call + // of std::chrono::high_resolution_clock::now() returns a later time + // than any previous call. + static constexpr bool is_steady = true; + + // Defines the accuracy of the (hardware) high resolution clock. + using duration = chrono::microseconds; + using rep = duration::rep; + using period = duration::period; + using time_point = chrono::time_point; + + static auto to_time_t(const time_point& t) -> std::time_t + { + return static_cast(duration_cast(t.time_since_epoch()).count()); + } + + static auto from_time_t(std::time_t t) -> time_point + { + using local_from_type = chrono::time_point; + + return time_point_cast + ( + static_cast(chrono::seconds(t)) + ); + } + + // !!! PLATFORM AND OS SPECIFIC IMPLEMENTATION !!! + static auto now() noexcept -> time_point; + }; + + #if !defined(MODM_CHRONO_STEADY_CLOCK) + #define MODM_CHRONO_STEADY_CLOCK steady_clock + #endif + + // use high_resolution_clock as steady_clock + using MODM_CHRONO_STEADY_CLOCK = high_resolution_clock; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif //_GLIBCXX_CHRONO diff --git a/resources/sources/avr-libstdcpp/include/cinttypes b/resources/sources/avr-libstdcpp/include/cinttypes new file mode 100644 index 000000000..252ee6926 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cinttypes @@ -0,0 +1,55 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cinttypes + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_CINTTYPES +#define _GLIBCXX_CINTTYPES 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +// For 27.9.2/3 (see C99, Note 184) +#if _GLIBCXX_HAVE_INTTYPES_H +# ifndef __STDC_FORMAT_MACROS +# define _UNDEF__STDC_FORMAT_MACROS +# define __STDC_FORMAT_MACROS +# endif +# include +# ifdef _UNDEF__STDC_FORMAT_MACROS +# undef __STDC_FORMAT_MACROS +# undef _UNDEF__STDC_FORMAT_MACROS +# endif +#endif + +#endif // C++11 + +#endif // _GLIBCXX_CINTTYPES diff --git a/resources/sources/avr-libstdcpp/include/ciso646 b/resources/sources/avr-libstdcpp/include/ciso646 new file mode 100644 index 000000000..05c29e9fb --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ciso646 @@ -0,0 +1,38 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ciso646 + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c iso646.h, + * which is empty in C++. + */ +#ifndef _GLIBCXX_CISO646 +#define _GLIBCXX_CISO646 + +#pragma GCC system_header + +#include +#endif diff --git a/resources/sources/avr-libstdcpp/include/climits b/resources/sources/avr-libstdcpp/include/climits new file mode 100644 index 000000000..09e8fcba2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/climits @@ -0,0 +1,59 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/climits + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c limits.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.2.2 Implementation properties: C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CLIMITS +#define _GLIBCXX_CLIMITS 1 + +#ifndef LLONG_MIN +#define LLONG_MIN (-__LONG_LONG_MAX__ - 1) +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX __LONG_LONG_MAX__ +#endif + +#ifndef ULLONG_MAX +#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cmath b/resources/sources/avr-libstdcpp/include/cmath new file mode 100644 index 000000000..2232ef22b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cmath @@ -0,0 +1,1924 @@ +// -*- C++ -*- C forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cmath + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c math.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 26.5 C library +// + +#pragma GCC system_header + +#include +#include +#include +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include_next +#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include + +#ifndef _GLIBCXX_CMATH +#define _GLIBCXX_CMATH 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef div +#undef acos +#undef asin +#undef atan +#undef atan2 +#undef ceil +#undef cos +#undef cosh +#undef exp +#undef fabs +#undef floor +#undef fmod +#undef frexp +#undef ldexp +#undef log +#undef log10 +#undef modf +#undef pow +#undef sin +#undef sinh +#undef sqrt +#undef tan +#undef tanh + +// Fix float math functions defined as macros in avr libc +#ifdef __AVR__ + +#undef cosf +#undef sinf +#undef tanf +#undef fabsf +#undef fmodf +#undef cbrtf +#undef hypotf +#undef squaref +#undef floorf +#undef ceilf +#undef frexpf +#undef ldexpf +#undef expf +#undef coshf +#undef sinhf +#undef tanhf +#undef acosf +#undef asinf +#undef atanf +#undef atan2f +#undef logf +#undef log10f +#undef powf +#undef isnanf +#undef isinff +#undef isfinitef +#undef copysignf +#undef signbitf +#undef fdimf +#undef fmaf +#undef fmaxf +#undef fminf +#undef truncf +#undef roundf +#undef lroundf +#undef lrintf + +extern "C" +{ + float cosf(float x); + float sinf(float x); + float tanf(float x); + float fabsf(float x); + float fmodf(float x, float y); + float cbrtf(float x); + float hypotf(float x, float y); + float squaref(float x); + float floorf(float x); + float ceilf(float x); + float frexpf(float value, int* exp); + float ldexpf(float x, int exp); + float expf(float x); + float coshf(float x); + float sinhf(float x); + float tanhf(float x); + float acosf(float x); + float asinf(float x); + float atanf(float x); + float atan2f(float y, float x); + float logf(float x); + float log10f(float x); + float powf(float x, float y); + int isnanf(float x); + int isinff(float x); + int isfinitef(float x); + float copysignf(float x, float y); + int signbitf(float x); + float fdimf(float x, float y); + float fmaf(float x, float y, float z); + float fmaxf(float x, float y); + float fminf(float x, float y); + float truncf(float x); + float roundf(float x); + long lroundf(float x); + long lrintf(float x); +} // extern "C" +#endif // __AVR__ + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::acos; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + acos(float __x) + { return __builtin_acosf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + acos(long double __x) + { return __builtin_acosl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + acos(_Tp __x) + { return __builtin_acos(__x); } + + using ::asin; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + asin(float __x) + { return __builtin_asinf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + asin(long double __x) + { return __builtin_asinl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + asin(_Tp __x) + { return __builtin_asin(__x); } + + using ::atan; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + atan(float __x) + { return __builtin_atanf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + atan(long double __x) + { return __builtin_atanl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + atan(_Tp __x) + { return __builtin_atan(__x); } + + using ::atan2; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + atan2(float __y, float __x) + { return __builtin_atan2f(__y, __x); } + + inline _GLIBCXX_CONSTEXPR long double + atan2(long double __y, long double __x) + { return __builtin_atan2l(__y, __x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + atan2(_Tp __y, _Up __x) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return atan2(__type(__y), __type(__x)); + } + + using ::ceil; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + ceil(float __x) + { return __builtin_ceilf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + ceil(long double __x) + { return __builtin_ceill(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + ceil(_Tp __x) + { return __builtin_ceil(__x); } + + using ::cos; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + cos(float __x) + { return __builtin_cosf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + cos(long double __x) + { return __builtin_cosl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + cos(_Tp __x) + { return __builtin_cos(__x); } + + using ::cosh; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + cosh(float __x) + { return __builtin_coshf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + cosh(long double __x) + { return __builtin_coshl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + cosh(_Tp __x) + { return __builtin_cosh(__x); } + + using ::exp; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + exp(float __x) + { return __builtin_expf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + exp(long double __x) + { return __builtin_expl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + exp(_Tp __x) + { return __builtin_exp(__x); } + + using ::fabs; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + fabs(float __x) + { return __builtin_fabsf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + fabs(long double __x) + { return __builtin_fabsl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + fabs(_Tp __x) + { return __builtin_fabs(__x); } + + using ::floor; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + floor(float __x) + { return __builtin_floorf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + floor(long double __x) + { return __builtin_floorl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + floor(_Tp __x) + { return __builtin_floor(__x); } + + using ::fmod; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + fmod(float __x, float __y) + { return __builtin_fmodf(__x, __y); } + + inline _GLIBCXX_CONSTEXPR long double + fmod(long double __x, long double __y) + { return __builtin_fmodl(__x, __y); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmod(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmod(__type(__x), __type(__y)); + } + + using ::frexp; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline float + frexp(float __x, int* __exp) + { return __builtin_frexpf(__x, __exp); } + + inline long double + frexp(long double __x, int* __exp) + { return __builtin_frexpl(__x, __exp); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + frexp(_Tp __x, int* __exp) + { return __builtin_frexp(__x, __exp); } + + using ::ldexp; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + ldexp(float __x, int __exp) + { return __builtin_ldexpf(__x, __exp); } + + inline _GLIBCXX_CONSTEXPR long double + ldexp(long double __x, int __exp) + { return __builtin_ldexpl(__x, __exp); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + ldexp(_Tp __x, int __exp) + { return __builtin_ldexp(__x, __exp); } + + using ::log; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + log(float __x) + { return __builtin_logf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + log(long double __x) + { return __builtin_logl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + log(_Tp __x) + { return __builtin_log(__x); } + + using ::log10; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + log10(float __x) + { return __builtin_log10f(__x); } + + inline _GLIBCXX_CONSTEXPR long double + log10(long double __x) + { return __builtin_log10l(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + log10(_Tp __x) + { return __builtin_log10(__x); } + + using ::modf; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline float + modf(float __x, float* __iptr) + { return __builtin_modff(__x, __iptr); } + + inline long double + modf(long double __x, long double* __iptr) + { return __builtin_modfl(__x, __iptr); } +#endif + + using ::pow; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + pow(float __x, float __y) + { return __builtin_powf(__x, __y); } + + inline _GLIBCXX_CONSTEXPR long double + pow(long double __x, long double __y) + { return __builtin_powl(__x, __y); } + +#if __cplusplus < 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 550. What should the return type of pow(float,int) be? + inline double + pow(double __x, int __i) + { return __builtin_powi(__x, __i); } + + inline float + pow(float __x, int __n) + { return __builtin_powif(__x, __n); } + + inline long double + pow(long double __x, int __n) + { return __builtin_powil(__x, __n); } +#endif +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + pow(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return pow(__type(__x), __type(__y)); + } + + using ::sin; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + sin(float __x) + { return __builtin_sinf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + sin(long double __x) + { return __builtin_sinl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + sin(_Tp __x) + { return __builtin_sin(__x); } + + using ::sinh; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + sinh(float __x) + { return __builtin_sinhf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + sinh(long double __x) + { return __builtin_sinhl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + sinh(_Tp __x) + { return __builtin_sinh(__x); } + + using ::sqrt; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + sqrt(float __x) + { return __builtin_sqrtf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + sqrt(long double __x) + { return __builtin_sqrtl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + sqrt(_Tp __x) + { return __builtin_sqrt(__x); } + + using ::tan; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + tan(float __x) + { return __builtin_tanf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + tan(long double __x) + { return __builtin_tanl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + tan(_Tp __x) + { return __builtin_tan(__x); } + + using ::tanh; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + tanh(float __x) + { return __builtin_tanhf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + tanh(long double __x) + { return __builtin_tanhl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + tanh(_Tp __x) + { return __builtin_tanh(__x); } + +#if _GLIBCXX_USE_C99_MATH +#if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC + +// These are possible macros imported from C99-land. +#undef fpclassify +#undef isfinite +#undef isinf +#undef isnan +#undef isnormal +#undef signbit +#undef isgreater +#undef isgreaterequal +#undef isless +#undef islessequal +#undef islessgreater +#undef isunordered + +#if !defined(FP_NAN) && !defined(FP_INFINITE) && !defined(FP_ZERO) \ + && !defined(FP_SUBNORMAL) && !defined(FP_NORMAL) +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 +#elif !defined(FP_NAN) || !defined(FP_INFINITE) || !defined(FP_ZERO) \ + || !defined(FP_SUBNORMAL) || !defined(FP_NORMAL) +#error "Some floating-point number classification macros are missing." +#error "Either define all of them or define none of them so that can do it." +#endif + +#if __cplusplus >= 201103L + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr int + fpclassify(float __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } + + constexpr int + fpclassify(double __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } + + constexpr int + fpclassify(long double __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + int>::__type + fpclassify(_Tp __x) + { return __x != 0 ? FP_NORMAL : FP_ZERO; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isfinite(float __x) + { return __builtin_isfinite(__x); } + + constexpr bool + isfinite(double __x) + { return __builtin_isfinite(__x); } + + constexpr bool + isfinite(long double __x) + { return __builtin_isfinite(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + isfinite(_Tp __x) + { return true; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isinf(float __x) + { return __builtin_isinf(__x); } + +#if _GLIBCXX_HAVE_OBSOLETE_ISINF \ + && !_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC + using ::isinf; +#else + constexpr bool + isinf(double __x) + { return __builtin_isinf(__x); } +#endif + + constexpr bool + isinf(long double __x) + { return __builtin_isinf(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + isinf(_Tp __x) + { return false; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isnan(float __x) + { return __builtin_isnan(__x); } + +#if _GLIBCXX_HAVE_OBSOLETE_ISNAN \ + && !_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC + using ::isnan; +#else + constexpr bool + isnan(double __x) + { return __builtin_isnan(__x); } +#endif + + constexpr bool + isnan(long double __x) + { return __builtin_isnan(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + isnan(_Tp __x) + { return false; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isnormal(float __x) + { return __builtin_isnormal(__x); } + + constexpr bool + isnormal(double __x) + { return __builtin_isnormal(__x); } + + constexpr bool + isnormal(long double __x) + { return __builtin_isnormal(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + isnormal(_Tp __x) + { return __x != 0 ? true : false; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + // Note: middle-end/36757 is fixed, __builtin_signbit is type-generic. + constexpr bool + signbit(float __x) + { return __builtin_signbit(__x); } + + constexpr bool + signbit(double __x) + { return __builtin_signbit(__x); } + + constexpr bool + signbit(long double __x) + { return __builtin_signbit(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + signbit(_Tp __x) + { return __x < 0 ? true : false; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isgreater(float __x, float __y) + { return __builtin_isgreater(__x, __y); } + + constexpr bool + isgreater(double __x, double __y) + { return __builtin_isgreater(__x, __y); } + + constexpr bool + isgreater(long double __x, long double __y) + { return __builtin_isgreater(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + isgreater(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_isgreater(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isgreaterequal(float __x, float __y) + { return __builtin_isgreaterequal(__x, __y); } + + constexpr bool + isgreaterequal(double __x, double __y) + { return __builtin_isgreaterequal(__x, __y); } + + constexpr bool + isgreaterequal(long double __x, long double __y) + { return __builtin_isgreaterequal(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + isgreaterequal(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_isgreaterequal(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isless(float __x, float __y) + { return __builtin_isless(__x, __y); } + + constexpr bool + isless(double __x, double __y) + { return __builtin_isless(__x, __y); } + + constexpr bool + isless(long double __x, long double __y) + { return __builtin_isless(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + isless(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_isless(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + islessequal(float __x, float __y) + { return __builtin_islessequal(__x, __y); } + + constexpr bool + islessequal(double __x, double __y) + { return __builtin_islessequal(__x, __y); } + + constexpr bool + islessequal(long double __x, long double __y) + { return __builtin_islessequal(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + islessequal(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_islessequal(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + islessgreater(float __x, float __y) + { return __builtin_islessgreater(__x, __y); } + + constexpr bool + islessgreater(double __x, double __y) + { return __builtin_islessgreater(__x, __y); } + + constexpr bool + islessgreater(long double __x, long double __y) + { return __builtin_islessgreater(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + islessgreater(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_islessgreater(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isunordered(float __x, float __y) + { return __builtin_isunordered(__x, __y); } + + constexpr bool + isunordered(double __x, double __y) + { return __builtin_isunordered(__x, __y); } + + constexpr bool + isunordered(long double __x, long double __y) + { return __builtin_isunordered(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + isunordered(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_isunordered(__type(__x), __type(__y)); + } +#endif + +#else + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + fpclassify(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isfinite(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isfinite(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isinf(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isinf(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isnan(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isnan(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isnormal(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isnormal(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + signbit(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_signbit(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isgreater(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isgreater(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isgreaterequal(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isgreaterequal(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isless(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isless(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + islessequal(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_islessequal(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + islessgreater(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_islessgreater(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isunordered(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isunordered(__type(__f1), __type(__f2)); + } + +#endif // C++11 +#endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */ +#endif /* _GLIBCXX_USE_C99_MATH */ + +#if __cplusplus >= 201103L + +#ifdef _GLIBCXX_USE_C99_MATH_TR1 + +#undef acosh +#undef acoshf +#undef acoshl +#undef asinh +#undef asinhf +#undef asinhl +#undef atanh +#undef atanhf +#undef atanhl +#undef cbrt +#undef cbrtf +#undef cbrtl +#undef copysign +#undef copysignf +#undef copysignl +#undef erf +#undef erff +#undef erfl +#undef erfc +#undef erfcf +#undef erfcl +#undef exp2 +#undef exp2f +#undef exp2l +#undef expm1 +#undef expm1f +#undef expm1l +#undef fdim +#undef fdimf +#undef fdiml +#undef fma +#undef fmaf +#undef fmal +#undef fmax +#undef fmaxf +#undef fmaxl +#undef fmin +#undef fminf +#undef fminl +#undef hypot +#undef hypotf +#undef hypotl +#undef ilogb +#undef ilogbf +#undef ilogbl +#undef lgamma +#undef lgammaf +#undef lgammal +#ifndef _GLIBCXX_NO_C99_ROUNDING_FUNCS +#undef llrint +#undef llrintf +#undef llrintl +#undef llround +#undef llroundf +#undef llroundl +#endif +#undef log1p +#undef log1pf +#undef log1pl +#undef log2 +#undef log2f +#undef log2l +#undef logb +#undef logbf +#undef logbl +#undef lrint +#undef lrintf +#undef lrintl +#undef lround +#undef lroundf +#undef lroundl +#undef nan +#undef nanf +#undef nanl +#undef nearbyint +#undef nearbyintf +#undef nearbyintl +#undef nextafter +#undef nextafterf +#undef nextafterl +#undef nexttoward +#undef nexttowardf +#undef nexttowardl +#undef remainder +#undef remainderf +#undef remainderl +#undef remquo +#undef remquof +#undef remquol +#undef rint +#undef rintf +#undef rintl +#undef round +#undef roundf +#undef roundl +#undef scalbln +#undef scalblnf +#undef scalblnl +#undef scalbn +#undef scalbnf +#undef scalbnl +#undef tgamma +#undef tgammaf +#undef tgammal +#undef trunc +#undef truncf +#undef truncl + + // types + using double_t = double; + using float_t = float; + + // functions + + using ::cbrt; + inline float cbrtf(float __x) { return ::cbrt(__x); } + + using ::copysign; + inline float copysignf(float __x, float __y) { return ::copysign(__x, __y); } + + using ::fdim; + inline float fdimf(float __x, float __y) { return ::fdim(__x, __y); } + + using ::fma; + inline float fmaf(float __x, float __y, float __z) { return ::fma(__x, __y, __z); } + + using ::fmax; + inline float fmaxf(float __x, float __y) { return ::fmax(__x, __y); } + + using ::fmin; + inline float fminf(float __x, float __y) { return ::fmin(__x, __y); } + + using ::hypot; + inline float hypotf(float __x, float __y) { return ::hypot(__x, __y); } + +#ifndef _GLIBCXX_NO_C99_ROUNDING_FUNCS + using ::llrint; + using ::llrintf; + using ::llrintl; + + using ::llround; + using ::llroundf; + using ::llroundl; +#endif + + using ::lrint; + inline float lrintf(float __x) { return ::lrint(__x); } + + using ::lround; + inline float lroundf(float __x) { return ::lround(__x); } + + using ::round; + inline float roundf(float __x) { return ::round(__x); } + + using ::trunc; + inline float truncf(float __x) { return ::trunc(__x); } + + /// Additional overloads. +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + acosh(float __x) + { return __builtin_acoshf(__x); } + + constexpr long double + acosh(long double __x) + { return __builtin_acoshl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + acosh(_Tp __x) + { return __builtin_acosh(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + asinh(float __x) + { return __builtin_asinhf(__x); } + + constexpr long double + asinh(long double __x) + { return __builtin_asinhl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + asinh(_Tp __x) + { return __builtin_asinh(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + atanh(float __x) + { return __builtin_atanhf(__x); } + + constexpr long double + atanh(long double __x) + { return __builtin_atanhl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + atanh(_Tp __x) + { return __builtin_atanh(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + cbrt(float __x) + { return __builtin_cbrtf(__x); } + + constexpr long double + cbrt(long double __x) + { return __builtin_cbrtl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + cbrt(_Tp __x) + { return __builtin_cbrt(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + copysign(float __x, float __y) + { return __builtin_copysignf(__x, __y); } + + constexpr long double + copysign(long double __x, long double __y) + { return __builtin_copysignl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + copysign(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return copysign(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + erf(float __x) + { return __builtin_erff(__x); } + + constexpr long double + erf(long double __x) + { return __builtin_erfl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + erf(_Tp __x) + { return __builtin_erf(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + erfc(float __x) + { return __builtin_erfcf(__x); } + + constexpr long double + erfc(long double __x) + { return __builtin_erfcl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + erfc(_Tp __x) + { return __builtin_erfc(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + exp2(float __x) + { return __builtin_exp2f(__x); } + + constexpr long double + exp2(long double __x) + { return __builtin_exp2l(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + exp2(_Tp __x) + { return __builtin_exp2(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + expm1(float __x) + { return __builtin_expm1f(__x); } + + constexpr long double + expm1(long double __x) + { return __builtin_expm1l(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + expm1(_Tp __x) + { return __builtin_expm1(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + fdim(float __x, float __y) + { return __builtin_fdimf(__x, __y); } + + constexpr long double + fdim(long double __x, long double __y) + { return __builtin_fdiml(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fdim(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fdim(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + fma(float __x, float __y, float __z) + { return __builtin_fmaf(__x, __y, __z); } + + constexpr long double + fma(long double __x, long double __y, long double __z) + { return __builtin_fmal(__x, __y, __z); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type + fma(_Tp __x, _Up __y, _Vp __z) + { + typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type; + return fma(__type(__x), __type(__y), __type(__z)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + fmax(float __x, float __y) + { return __builtin_fmaxf(__x, __y); } + + constexpr long double + fmax(long double __x, long double __y) + { return __builtin_fmaxl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmax(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmax(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + fmin(float __x, float __y) + { return __builtin_fminf(__x, __y); } + + constexpr long double + fmin(long double __x, long double __y) + { return __builtin_fminl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmin(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmin(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + hypot(float __x, float __y) + { return __builtin_hypotf(__x, __y); } + + constexpr long double + hypot(long double __x, long double __y) + { return __builtin_hypotl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + hypot(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return hypot(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr int + ilogb(float __x) + { return __builtin_ilogbf(__x); } + + constexpr int + ilogb(long double __x) + { return __builtin_ilogbl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + int>::__type + ilogb(_Tp __x) + { return __builtin_ilogb(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + lgamma(float __x) + { return __builtin_lgammaf(__x); } + + constexpr long double + lgamma(long double __x) + { return __builtin_lgammal(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + lgamma(_Tp __x) + { return __builtin_lgamma(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr long long + llrint(float __x) + { return __builtin_llrintf(__x); } + + constexpr long long + llrint(long double __x) + { return __builtin_llrintl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + long long>::__type + llrint(_Tp __x) + { return __builtin_llrint(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr long long + llround(float __x) + { return __builtin_llroundf(__x); } + + constexpr long long + llround(long double __x) + { return __builtin_llroundl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + long long>::__type + llround(_Tp __x) + { return __builtin_llround(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + log1p(float __x) + { return __builtin_log1pf(__x); } + + constexpr long double + log1p(long double __x) + { return __builtin_log1pl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + log1p(_Tp __x) + { return __builtin_log1p(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + // DR 568. + constexpr float + log2(float __x) + { return __builtin_log2f(__x); } + + constexpr long double + log2(long double __x) + { return __builtin_log2l(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + log2(_Tp __x) + { return __builtin_log2(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + logb(float __x) + { return __builtin_logbf(__x); } + + constexpr long double + logb(long double __x) + { return __builtin_logbl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + logb(_Tp __x) + { return __builtin_logb(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr long + lrint(float __x) + { return __builtin_lrintf(__x); } + + constexpr long + lrint(long double __x) + { return __builtin_lrintl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + long>::__type + lrint(_Tp __x) + { return __builtin_lrint(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr long + lround(float __x) + { return __builtin_lroundf(__x); } + + constexpr long + lround(long double __x) + { return __builtin_lroundl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + long>::__type + lround(_Tp __x) + { return __builtin_lround(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + nearbyint(float __x) + { return __builtin_nearbyintf(__x); } + + constexpr long double + nearbyint(long double __x) + { return __builtin_nearbyintl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + nearbyint(_Tp __x) + { return __builtin_nearbyint(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + nextafter(float __x, float __y) + { return __builtin_nextafterf(__x, __y); } + + constexpr long double + nextafter(long double __x, long double __y) + { return __builtin_nextafterl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + nextafter(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return nextafter(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + nexttoward(float __x, long double __y) + { return __builtin_nexttowardf(__x, __y); } + + constexpr long double + nexttoward(long double __x, long double __y) + { return __builtin_nexttowardl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + nexttoward(_Tp __x, long double __y) + { return __builtin_nexttoward(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + remainder(float __x, float __y) + { return __builtin_remainderf(__x, __y); } + + constexpr long double + remainder(long double __x, long double __y) + { return __builtin_remainderl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + remainder(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return remainder(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + inline float + remquo(float __x, float __y, int* __pquo) + { return __builtin_remquof(__x, __y, __pquo); } + + inline long double + remquo(long double __x, long double __y, int* __pquo) + { return __builtin_remquol(__x, __y, __pquo); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + remquo(_Tp __x, _Up __y, int* __pquo) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return remquo(__type(__x), __type(__y), __pquo); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + rint(float __x) + { return __builtin_rintf(__x); } + + constexpr long double + rint(long double __x) + { return __builtin_rintl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + rint(_Tp __x) + { return __builtin_rint(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + round(float __x) + { return __builtin_roundf(__x); } + + constexpr long double + round(long double __x) + { return __builtin_roundl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + round(_Tp __x) + { return __builtin_round(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + scalbln(float __x, long __ex) + { return __builtin_scalblnf(__x, __ex); } + + constexpr long double + scalbln(long double __x, long __ex) + { return __builtin_scalblnl(__x, __ex); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + scalbln(_Tp __x, long __ex) + { return __builtin_scalbln(__x, __ex); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + scalbn(float __x, int __ex) + { return __builtin_scalbnf(__x, __ex); } + + constexpr long double + scalbn(long double __x, int __ex) + { return __builtin_scalbnl(__x, __ex); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + scalbn(_Tp __x, int __ex) + { return __builtin_scalbn(__x, __ex); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + tgamma(float __x) + { return __builtin_tgammaf(__x); } + + constexpr long double + tgamma(long double __x) + { return __builtin_tgammal(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + tgamma(_Tp __x) + { return __builtin_tgamma(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + trunc(float __x) + { return __builtin_truncf(__x); } + + constexpr long double + trunc(long double __x) + { return __builtin_truncl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + trunc(_Tp __x) + { return __builtin_trunc(__x); } +#endif + +#endif // _GLIBCXX_USE_C99_MATH_TR1 +#endif // C++11 + +#if __cplusplus > 201402L + + // [c.math.hypot3], three-dimensional hypotenuse +#define __cpp_lib_hypot 201603 + + template + inline _Tp + __hypot3(_Tp __x, _Tp __y, _Tp __z) + { + __x = std::abs(__x); + __y = std::abs(__y); + __z = std::abs(__z); + if (_Tp __a = __x < __y ? __y < __z ? __z : __y : __x < __z ? __z : __x) + return __a * std::sqrt((__x / __a) * (__x / __a) + + (__y / __a) * (__y / __a) + + (__z / __a) * (__z / __a)); + else + return {}; + } + + inline float + hypot(float __x, float __y, float __z) + { return std::__hypot3(__x, __y, __z); } + + inline double + hypot(double __x, double __y, double __z) + { return std::__hypot3(__x, __y, __z); } + + inline long double + hypot(long double __x, long double __y, long double __z) + { return std::__hypot3(__x, __y, __z); } + + template + typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type + hypot(_Tp __x, _Up __y, _Vp __z) + { + using __type = typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type; + return std::__hypot3<__type>(__x, __y, __z); + } +#endif // C++17 + +#if __cplusplus > 201703L + // linear interpolation +# define __cpp_lib_interpolate 201902L + + template + constexpr _Fp + __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept + { + if (__a <= 0 && __b >= 0 || __a >= 0 && __b <= 0) + return __t * __b + (1 - __t) * __a; + + if (__t == 1) + return __b; // exact + + // Exact at __t=0, monotonic except near __t=1, + // bounded, determinate, and consistent: + const _Fp __x = __a + __t * (__b - __a); + return __t > 1 == __b > __a + ? (__b < __x ? __x : __b) + : (__b > __x ? __x : __b); // monotonic near __t=1 + } + + constexpr float + lerp(float __a, float __b, float __t) noexcept + { return std::__lerp(__a, __b, __t); } + + constexpr double + lerp(double __a, double __b, double __t) noexcept + { return std::__lerp(__a, __b, __t); } + + constexpr long double + lerp(long double __a, long double __b, long double __t) noexcept + { return std::__lerp(__a, __b, __t); } +#endif // C++20 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +} // extern "C++" + +#endif diff --git a/resources/sources/avr-libstdcpp/include/compare b/resources/sources/avr-libstdcpp/include/compare new file mode 100644 index 000000000..28dfe843e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/compare @@ -0,0 +1,919 @@ +// -*- C++ -*- operator<=> three-way comparison support. + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file compare + * This is a Standard C++ Library header. + */ + +#ifndef _COMPARE +#define _COMPARE + +#pragma GCC system_header + +#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L + +#pragma GCC visibility push(default) + +#include + +#if __cpp_lib_concepts +# define __cpp_lib_three_way_comparison 201907L +#endif + +namespace std +{ + // [cmp.categories], comparison category types + + namespace __cmp_cat + { + using type = signed char; + + enum class _Ord : type { equivalent = 0, less = -1, greater = 1 }; + + enum class _Ncmp : type { _Unordered = 2 }; + + struct __unspec + { + constexpr __unspec(__unspec*) noexcept { } + }; + } + + class partial_ordering + { + // less=0xff, equiv=0x00, greater=0x01, unordered=0x02 + __cmp_cat::type _M_value; + + constexpr explicit + partial_ordering(__cmp_cat::_Ord __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + constexpr explicit + partial_ordering(__cmp_cat::_Ncmp __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + friend class weak_ordering; + friend class strong_ordering; + + public: + // valid values + static const partial_ordering less; + static const partial_ordering equivalent; + static const partial_ordering greater; + static const partial_ordering unordered; + + // comparisons + friend constexpr bool + operator==(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + friend constexpr bool + operator==(partial_ordering, partial_ordering) noexcept = default; + + friend constexpr bool + operator< (partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == -1; } + + friend constexpr bool + operator> (partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 1; } + + friend constexpr bool + operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + friend constexpr bool + operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; } + + friend constexpr bool + operator< (__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __v._M_value == 1; } + + friend constexpr bool + operator> (__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __v._M_value == -1; } + + friend constexpr bool + operator<=(__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; } + + friend constexpr bool + operator>=(__cmp_cat::__unspec, partial_ordering __v) noexcept + { return 0 >= __v._M_value; } + + friend constexpr partial_ordering + operator<=>(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + friend constexpr partial_ordering + operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept + { + if (__v._M_value & 1) + return partial_ordering(__cmp_cat::_Ord(-__v._M_value)); + else + return __v; + } + }; + + // valid values' definitions + inline constexpr partial_ordering + partial_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr partial_ordering + partial_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr partial_ordering + partial_ordering::greater(__cmp_cat::_Ord::greater); + + inline constexpr partial_ordering + partial_ordering::unordered(__cmp_cat::_Ncmp::_Unordered); + + class weak_ordering + { + __cmp_cat::type _M_value; + + constexpr explicit + weak_ordering(__cmp_cat::_Ord __v) noexcept : _M_value(__cmp_cat::type(__v)) + { } + + friend class strong_ordering; + + public: + // valid values + static const weak_ordering less; + static const weak_ordering equivalent; + static const weak_ordering greater; + + constexpr operator partial_ordering() const noexcept + { return partial_ordering(__cmp_cat::_Ord(_M_value)); } + + // comparisons + friend constexpr bool + operator==(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + friend constexpr bool + operator==(weak_ordering, weak_ordering) noexcept = default; + + friend constexpr bool + operator< (weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value < 0; } + + friend constexpr bool + operator> (weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value > 0; } + + friend constexpr bool + operator<=(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + friend constexpr bool + operator>=(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value >= 0; } + + friend constexpr bool + operator< (__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 < __v._M_value; } + + friend constexpr bool + operator> (__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 > __v._M_value; } + + friend constexpr bool + operator<=(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 <= __v._M_value; } + + friend constexpr bool + operator>=(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 >= __v._M_value; } + + friend constexpr weak_ordering + operator<=>(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + friend constexpr weak_ordering + operator<=>(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return weak_ordering(__cmp_cat::_Ord(-__v._M_value)); } + }; + + // valid values' definitions + inline constexpr weak_ordering + weak_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr weak_ordering + weak_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr weak_ordering + weak_ordering::greater(__cmp_cat::_Ord::greater); + + class strong_ordering + { + __cmp_cat::type _M_value; + + constexpr explicit + strong_ordering(__cmp_cat::_Ord __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + public: + // valid values + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering equivalent; + static const strong_ordering greater; + + constexpr operator partial_ordering() const noexcept + { return partial_ordering(__cmp_cat::_Ord(_M_value)); } + + constexpr operator weak_ordering() const noexcept + { return weak_ordering(__cmp_cat::_Ord(_M_value)); } + + // comparisons + friend constexpr bool + operator==(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + friend constexpr bool + operator==(strong_ordering, strong_ordering) noexcept = default; + + friend constexpr bool + operator< (strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value < 0; } + + friend constexpr bool + operator> (strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value > 0; } + + friend constexpr bool + operator<=(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + friend constexpr bool + operator>=(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value >= 0; } + + friend constexpr bool + operator< (__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 < __v._M_value; } + + friend constexpr bool + operator> (__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 > __v._M_value; } + + friend constexpr bool + operator<=(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 <= __v._M_value; } + + friend constexpr bool + operator>=(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 >= __v._M_value; } + + friend constexpr strong_ordering + operator<=>(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + friend constexpr strong_ordering + operator<=>(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return strong_ordering(__cmp_cat::_Ord(-__v._M_value)); } + }; + + // valid values' definitions + inline constexpr strong_ordering + strong_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr strong_ordering + strong_ordering::equal(__cmp_cat::_Ord::equivalent); + + inline constexpr strong_ordering + strong_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr strong_ordering + strong_ordering::greater(__cmp_cat::_Ord::greater); + + + // named comparison functions + constexpr bool + is_eq(partial_ordering __cmp) noexcept + { return __cmp == 0; } + + constexpr bool + is_neq(partial_ordering __cmp) noexcept + { return __cmp != 0; } + + constexpr bool + is_lt (partial_ordering __cmp) noexcept + { return __cmp < 0; } + + constexpr bool + is_lteq(partial_ordering __cmp) noexcept + { return __cmp <= 0; } + + constexpr bool + is_gt (partial_ordering __cmp) noexcept + { return __cmp > 0; } + + constexpr bool + is_gteq(partial_ordering __cmp) noexcept + { return __cmp >= 0; } + + namespace __detail + { + template + inline constexpr unsigned __cmp_cat_id = 1; + template<> + inline constexpr unsigned __cmp_cat_id = 2; + template<> + inline constexpr unsigned __cmp_cat_id = 4; + template<> + inline constexpr unsigned __cmp_cat_id = 8; + + template + constexpr auto __common_cmp_cat() + { + constexpr unsigned __cats = (__cmp_cat_id<_Ts> | ...); + // If any Ti is not a comparison category type, U is void. + if constexpr (__cats & 1) + return; + // Otherwise, if at least one Ti is std::partial_ordering, + // U is std::partial_ordering. + else if constexpr (bool(__cats & __cmp_cat_id)) + return partial_ordering::equivalent; + // Otherwise, if at least one Ti is std::weak_ordering, + // U is std::weak_ordering. + else if constexpr (bool(__cats & __cmp_cat_id)) + return weak_ordering::equivalent; + // Otherwise, U is std::strong_ordering. + else + return strong_ordering::equivalent; + } + } // namespace __detail + + // [cmp.common], common comparison category type + template + struct common_comparison_category + { + using type = decltype(__detail::__common_cmp_cat<_Ts...>()); + }; + + // Partial specializations for one and zero argument cases. + + template + struct common_comparison_category<_Tp> + { using type = void; }; + + template<> + struct common_comparison_category + { using type = partial_ordering; }; + + template<> + struct common_comparison_category + { using type = weak_ordering; }; + + template<> + struct common_comparison_category + { using type = strong_ordering; }; + + template<> + struct common_comparison_category<> + { using type = strong_ordering; }; + + template + using common_comparison_category_t + = typename common_comparison_category<_Ts...>::type; + +#if __cpp_lib_concepts + namespace __detail + { + template + concept __compares_as + = same_as, _Cat>; + } // namespace __detail + + // [cmp.concept], concept three_way_comparable + template + concept three_way_comparable + = __detail::__weakly_eq_cmp_with<_Tp, _Tp> + && __detail::__partially_ordered_with<_Tp, _Tp> + && requires(const remove_reference_t<_Tp>& __a, + const remove_reference_t<_Tp>& __b) + { + { __a <=> __b } -> __detail::__compares_as<_Cat>; + }; + + template + concept three_way_comparable_with + = three_way_comparable<_Tp, _Cat> + && three_way_comparable<_Up, _Cat> + && common_reference_with&, + const remove_reference_t<_Up>&> + && three_way_comparable< + common_reference_t&, + const remove_reference_t<_Up>&>, _Cat> + && __detail::__weakly_eq_cmp_with<_Tp, _Up> + && __detail::__partially_ordered_with<_Tp, _Up> + && requires(const remove_reference_t<_Tp>& __t, + const remove_reference_t<_Up>& __u) + { + { __t <=> __u } -> __detail::__compares_as<_Cat>; + { __u <=> __t } -> __detail::__compares_as<_Cat>; + }; + + namespace __detail + { + template + using __cmp3way_res_t + = decltype(std::declval<_Tp>() <=> std::declval<_Up>()); + + // Implementation of std::compare_three_way_result. + // It is undefined for a program to add specializations of + // std::compare_three_way_result, so the std::compare_three_way_result_t + // alias ignores std::compare_three_way_result and uses + // __detail::__cmp3way_res_impl directly instead. + template + struct __cmp3way_res_impl + { }; + + template + requires requires { typename __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; } + struct __cmp3way_res_impl<_Tp, _Up> + { + using type = __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; + }; + } // namespace __detail + + /// [cmp.result], result of three-way comparison + template + struct compare_three_way_result + : __detail::__cmp3way_res_impl<_Tp, _Up> + { }; + + /// [cmp.result], result of three-way comparison + template + using compare_three_way_result_t + = typename __detail::__cmp3way_res_impl<_Tp, _Up>::type; + + namespace __detail + { + // BUILTIN-PTR-THREE-WAY(T, U) + template + concept __3way_builtin_ptr_cmp + = requires(_Tp&& __t, _Up&& __u) + { static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); } + && convertible_to<_Tp, const volatile void*> + && convertible_to<_Up, const volatile void*> + && ! requires(_Tp&& __t, _Up&& __u) + { operator<=>(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); } + && ! requires(_Tp&& __t, _Up&& __u) + { static_cast<_Tp&&>(__t).operator<=>(static_cast<_Up&&>(__u)); }; + } // namespace __detail + + // [cmp.object], typename compare_three_way + struct compare_three_way + { + template + requires three_way_comparable_with<_Tp, _Up> + || __detail::__3way_builtin_ptr_cmp<_Tp, _Up> + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>())) + { + if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>) + { + auto __pt = static_cast(__t); + auto __pu = static_cast(__u); + if (__builtin_is_constant_evaluated()) + return __pt <=> __pu; + auto __it = reinterpret_cast<__UINTPTR_TYPE__>(__pt); + auto __iu = reinterpret_cast<__UINTPTR_TYPE__>(__pu); + return __it <=> __iu; + } + else + return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); + } + + using is_transparent = void; + }; + + namespace __cmp_cust + { + template + constexpr weak_ordering + __fp_weak_ordering(_Tp __e, _Tp __f) + { + // Returns an integer with the same sign as the argument, and magnitude + // indicating the classification: zero=1 subnorm=2 norm=3 inf=4 nan=5 + auto __cat = [](_Tp __fp) -> int { + const int __sign = __builtin_signbit(__fp) ? -1 : 1; + if (__builtin_isnormal(__fp)) + return (__fp == 0 ? 1 : 3) * __sign; + if (__builtin_isnan(__fp)) + return 5 * __sign; + if (int __inf = __builtin_isinf_sign(__fp)) + return 4 * __inf; + return 2 * __sign; + }; + + auto __po = __e <=> __f; + if (is_lt(__po)) + return weak_ordering::less; + else if (is_gt(__po)) + return weak_ordering::greater; + else if (__po == partial_ordering::equivalent) + return weak_ordering::equivalent; + else // unordered, at least one argument is NaN + { + // return -1 for negative nan, +1 for positive nan, 0 otherwise. + auto __isnan_sign = [](_Tp __fp) -> int { + return __builtin_isnan(__fp) + ? __builtin_signbit(__fp) ? -1 : 1 + : 0; + }; + auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f); + if (is_eq(__ord)) + return weak_ordering::equivalent; + else if (is_lt(__ord)) + return weak_ordering::less; + else + return weak_ordering::greater; + } + } + + template + concept __adl_strong = requires(_Tp&& __t, _Up&& __u) + { + strong_ordering(strong_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + template + concept __adl_weak = requires(_Tp&& __t, _Up&& __u) + { + weak_ordering(weak_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + template + concept __adl_partial = requires(_Tp&& __t, _Up&& __u) + { + partial_ordering(partial_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + template + concept __cmp3way = requires(_Tp&& __t, _Up&& __u, compare_three_way __c) + { + _Ord(__c(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u))); + }; + + template + concept __strongly_ordered + = __adl_strong<_Tp, _Up> + // FIXME: || floating_point> + || __cmp3way; + + class _Strong_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (floating_point>) + return true; + else if constexpr (__adl_strong<_Tp, _Up>) + return noexcept(strong_ordering(strong_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + } + + friend class _Weak_order; + friend class _Strong_fallback; + + public: + template + requires __strongly_ordered<_Tp, _Up> + constexpr strong_ordering + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + /* FIXME: + if constexpr (floating_point>) + return __cmp_cust::__fp_strong_order(__e, __f); + else */ if constexpr (__adl_strong<_Tp, _Up>) + return strong_ordering(strong_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __weakly_ordered + = floating_point> + || __adl_weak<_Tp, _Up> + || __cmp3way + || __strongly_ordered<_Tp, _Up>; + + class _Weak_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (floating_point>) + return true; + else if constexpr (__adl_weak<_Tp, _Up>) + return noexcept(weak_ordering(weak_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order::_S_noexcept<_Tp, _Up>(); + } + + friend class _Partial_order; + friend class _Weak_fallback; + + public: + template + requires __weakly_ordered<_Tp, _Up> + constexpr weak_ordering + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (floating_point>) + return __cmp_cust::__fp_weak_ordering(__e, __f); + else if constexpr (__adl_weak<_Tp, _Up>) + return weak_ordering(weak_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __partially_ordered + = __adl_partial<_Tp, _Up> + || __cmp3way + || __weakly_ordered<_Tp, _Up>; + + class _Partial_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_partial<_Tp, _Up>) + return noexcept(partial_ordering(partial_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order::_S_noexcept<_Tp, _Up>(); + } + + friend class _Partial_fallback; + + public: + template + requires __partially_ordered<_Tp, _Up> + constexpr partial_ordering + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (__adl_partial<_Tp, _Up>) + return partial_ordering(partial_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __op_eq_lt = requires(_Tp&& __t, _Up&& __u) + { + { static_cast<_Tp&&>(__t) == static_cast<_Up&&>(__u) } + -> convertible_to; + { static_cast<_Tp&&>(__t) < static_cast<_Up&&>(__u) } + -> convertible_to; + }; + + class _Strong_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template + requires __strongly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> + constexpr decltype(auto) + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__op_eq_lt<_Tp, _Up>) + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? strong_ordering::equal + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? strong_ordering::less + : strong_ordering::greater; + } + }; + + class _Weak_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template + requires __weakly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> + constexpr decltype(auto) + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__op_eq_lt<_Tp, _Up>) + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? weak_ordering::equivalent + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? weak_ordering::less + : weak_ordering::greater; + } + }; + + class _Partial_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__partially_ordered<_Tp, _Up>) + return _Partial_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template + requires __partially_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> + constexpr decltype(auto) + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (__partially_ordered<_Tp, _Up>) + return _Partial_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__op_eq_lt<_Tp, _Up>) + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? partial_ordering::equivalent + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? partial_ordering::less + : static_cast<_Up&&>(__f) < static_cast<_Tp&&>(__e) + ? partial_ordering::greater + : partial_ordering::unordered; + } + }; + } // namespace __cmp_cust + + // [cmp.alg], comparison algorithms + inline namespace __cmp_alg + { + inline constexpr __cmp_cust::_Strong_order strong_order{}; + + inline constexpr __cmp_cust::_Weak_order weak_order{}; + + inline constexpr __cmp_cust::_Partial_order partial_order{}; + + inline constexpr __cmp_cust::_Strong_fallback + compare_strong_order_fallback{}; + + inline constexpr __cmp_cust::_Weak_fallback + compare_weak_order_fallback{}; + + inline constexpr __cmp_cust::_Partial_fallback + compare_partial_order_fallback{}; + } + + namespace __detail + { + // [expos.only.func] synth-three-way + inline constexpr struct _Synth3way + { + template + static constexpr bool + _S_noexcept(const _Tp* __t = nullptr, const _Up* __u = nullptr) + { + if constexpr (three_way_comparable_with<_Tp, _Up>) + return noexcept(*__t <=> *__u); + else + return noexcept(*__t < *__u) && noexcept(*__u < *__t); + } + + template + constexpr auto + operator()(const _Tp& __t, const _Up& __u) const + noexcept(_S_noexcept<_Tp, _Up>()) + requires requires + { + { __t < __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + } + { + if constexpr (three_way_comparable_with<_Tp, _Up>) + return __t <=> __u; + else + { + if (__t < __u) + return weak_ordering::less; + else if (__u < __t) + return weak_ordering::greater; + else + return weak_ordering::equivalent; + } + } + } __synth3way = {}; + + // [expos.only.func] synth-three-way-result + template + using __synth3way_t + = decltype(__detail::__synth3way(std::declval<_Tp&>(), + std::declval<_Up&>())); + } // namespace __detail +#endif // concepts +} // namespace std + +#pragma GCC visibility pop + +#endif // C++20 + +#endif // _COMPARE diff --git a/resources/sources/avr-libstdcpp/include/complex b/resources/sources/avr-libstdcpp/include/complex new file mode 100644 index 000000000..52f59a19b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/complex @@ -0,0 +1,1931 @@ +// The template and inlines for the -*- C++ -*- complex number classes. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/complex + * This is a Standard C++ Library header. + */ + +// +// ISO C++ 14882: 26.2 Complex Numbers +// Note: this is not a conforming implementation. +// Initially implemented by Ulrich Drepper +// Improved by Gabriel Dos Reis +// + +#ifndef _GLIBCXX_COMPLEX +#define _GLIBCXX_COMPLEX 1 + +#pragma GCC system_header + +#include +#include +#include +#include + +// Get rid of a macro possibly defined in +#undef complex + +#if __cplusplus > 201703L +# define __cpp_lib_constexpr_complex 201711L +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup complex_numbers Complex Numbers + * @ingroup numerics + * + * Classes and functions for complex numbers. + * @{ + */ + + // Forward declarations. + template class complex; + template<> class complex; + template<> class complex; + template<> class complex; + + /// Return magnitude of @a z. + template _Tp abs(const complex<_Tp>&); + /// Return phase angle of @a z. + template _Tp arg(const complex<_Tp>&); + /// Return @a z magnitude squared. + template _Tp _GLIBCXX20_CONSTEXPR norm(const complex<_Tp>&); + + /// Return complex conjugate of @a z. + template + _GLIBCXX20_CONSTEXPR complex<_Tp> conj(const complex<_Tp>&); + /// Return complex with magnitude @a rho and angle @a theta. + template complex<_Tp> polar(const _Tp&, const _Tp& = 0); + + // Transcendentals: + /// Return complex cosine of @a z. + template complex<_Tp> cos(const complex<_Tp>&); + /// Return complex hyperbolic cosine of @a z. + template complex<_Tp> cosh(const complex<_Tp>&); + /// Return complex base e exponential of @a z. + template complex<_Tp> exp(const complex<_Tp>&); + /// Return complex natural logarithm of @a z. + template complex<_Tp> log(const complex<_Tp>&); + /// Return complex base 10 logarithm of @a z. + template complex<_Tp> log10(const complex<_Tp>&); + /// Return @a x to the @a y'th power. + template complex<_Tp> pow(const complex<_Tp>&, int); + /// Return @a x to the @a y'th power. + template complex<_Tp> pow(const complex<_Tp>&, const _Tp&); + /// Return @a x to the @a y'th power. + template complex<_Tp> pow(const complex<_Tp>&, + const complex<_Tp>&); + /// Return @a x to the @a y'th power. + template complex<_Tp> pow(const _Tp&, const complex<_Tp>&); + /// Return complex sine of @a z. + template complex<_Tp> sin(const complex<_Tp>&); + /// Return complex hyperbolic sine of @a z. + template complex<_Tp> sinh(const complex<_Tp>&); + /// Return complex square root of @a z. + template complex<_Tp> sqrt(const complex<_Tp>&); + /// Return complex tangent of @a z. + template complex<_Tp> tan(const complex<_Tp>&); + /// Return complex hyperbolic tangent of @a z. + template complex<_Tp> tanh(const complex<_Tp>&); + + + // 26.2.2 Primary template class complex + /** + * Template to represent complex numbers. + * + * Specializations for float, double, and long double are part of the + * library. Results with any other type are not guaranteed. + * + * @param Tp Type of real and imaginary values. + */ + template + struct complex + { + /// Value typedef. + typedef _Tp value_type; + + /// Default constructor. First parameter is x, second parameter is y. + /// Unspecified parameters default to 0. + _GLIBCXX_CONSTEXPR complex(const _Tp& __r = _Tp(), const _Tp& __i = _Tp()) + : _M_real(__r), _M_imag(__i) { } + + // Let the compiler synthesize the copy constructor +#if __cplusplus >= 201103L + constexpr complex(const complex&) = default; +#endif + + /// Converting constructor. + template + _GLIBCXX_CONSTEXPR complex(const complex<_Up>& __z) + : _M_real(__z.real()), _M_imag(__z.imag()) { } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX_ABI_TAG_CXX11 + constexpr _Tp + real() const { return _M_real; } + + _GLIBCXX_ABI_TAG_CXX11 + constexpr _Tp + imag() const { return _M_imag; } +#else + /// Return real part of complex number. + _Tp& + real() { return _M_real; } + + /// Return real part of complex number. + const _Tp& + real() const { return _M_real; } + + /// Return imaginary part of complex number. + _Tp& + imag() { return _M_imag; } + + /// Return imaginary part of complex number. + const _Tp& + imag() const { return _M_imag; } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX20_CONSTEXPR void + real(_Tp __val) { _M_real = __val; } + + _GLIBCXX20_CONSTEXPR void + imag(_Tp __val) { _M_imag = __val; } + + /// Assign a scalar to this complex number. + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const _Tp&); + + /// Add a scalar to this complex number. + // 26.2.5/1 + _GLIBCXX20_CONSTEXPR complex<_Tp>& + operator+=(const _Tp& __t) + { + _M_real += __t; + return *this; + } + + /// Subtract a scalar from this complex number. + // 26.2.5/3 + _GLIBCXX20_CONSTEXPR complex<_Tp>& + operator-=(const _Tp& __t) + { + _M_real -= __t; + return *this; + } + + /// Multiply this complex number by a scalar. + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const _Tp&); + /// Divide this complex number by a scalar. + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const _Tp&); + + // Let the compiler synthesize the copy assignment operator +#if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR complex& operator=(const complex&) = default; +#endif + + /// Assign another complex number to this one. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const complex<_Up>&); + /// Add another complex number to this one. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator+=(const complex<_Up>&); + /// Subtract another complex number from this one. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator-=(const complex<_Up>&); + /// Multiply this complex number by another. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const complex<_Up>&); + /// Divide this complex number by another. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const complex<_Up>&); + + _GLIBCXX_CONSTEXPR complex __rep() const + { return *this; } + + private: + _Tp _M_real; + _Tp _M_imag; + }; + + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator=(const _Tp& __t) + { + _M_real = __t; + _M_imag = _Tp(); + return *this; + } + + // 26.2.5/5 + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator*=(const _Tp& __t) + { + _M_real *= __t; + _M_imag *= __t; + return *this; + } + + // 26.2.5/7 + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator/=(const _Tp& __t) + { + _M_real /= __t; + _M_imag /= __t; + return *this; + } + + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator=(const complex<_Up>& __z) + { + _M_real = __z.real(); + _M_imag = __z.imag(); + return *this; + } + + // 26.2.5/9 + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator+=(const complex<_Up>& __z) + { + _M_real += __z.real(); + _M_imag += __z.imag(); + return *this; + } + + // 26.2.5/11 + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator-=(const complex<_Up>& __z) + { + _M_real -= __z.real(); + _M_imag -= __z.imag(); + return *this; + } + + // 26.2.5/13 + // XXX: This is a grammar school implementation. + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator*=(const complex<_Up>& __z) + { + const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag(); + _M_imag = _M_real * __z.imag() + _M_imag * __z.real(); + _M_real = __r; + return *this; + } + + // 26.2.5/15 + // XXX: This is a grammar school implementation. + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator/=(const complex<_Up>& __z) + { + const _Tp __r = _M_real * __z.real() + _M_imag * __z.imag(); + const _Tp __n = std::norm(__z); + _M_imag = (_M_imag * __z.real() - _M_real * __z.imag()) / __n; + _M_real = __r / __n; + return *this; + } + + // Operators: + //@{ + /// Return new complex value @a x plus @a y. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r += __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator+(const complex<_Tp>& __x, const _Tp& __y) + { + complex<_Tp> __r = __x; + __r += __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator+(const _Tp& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __y; + __r += __x; + return __r; + } + //@} + + //@{ + /// Return new complex value @a x minus @a y. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r -= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator-(const complex<_Tp>& __x, const _Tp& __y) + { + complex<_Tp> __r = __x; + __r -= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator-(const _Tp& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = -__y; + __r += __x; + return __r; + } + //@} + + //@{ + /// Return new complex value @a x times @a y. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator*(const complex<_Tp>& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r *= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator*(const complex<_Tp>& __x, const _Tp& __y) + { + complex<_Tp> __r = __x; + __r *= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator*(const _Tp& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __y; + __r *= __x; + return __r; + } + //@} + + //@{ + /// Return new complex value @a x divided by @a y. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator/(const complex<_Tp>& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r /= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator/(const complex<_Tp>& __x, const _Tp& __y) + { + complex<_Tp> __r = __x; + __r /= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator/(const _Tp& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r /= __y; + return __r; + } + //@} + + /// Return @a x. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator+(const complex<_Tp>& __x) + { return __x; } + + /// Return complex negation of @a x. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator-(const complex<_Tp>& __x) + { return complex<_Tp>(-__x.real(), -__x.imag()); } + + //@{ + /// Return true if @a x is equal to @a y. + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __x.real() == __y.real() && __x.imag() == __y.imag(); } + + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const complex<_Tp>& __x, const _Tp& __y) + { return __x.real() == __y && __x.imag() == _Tp(); } + +#if !(__cpp_impl_three_way_comparison >= 201907L) + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const _Tp& __x, const complex<_Tp>& __y) + { return __x == __y.real() && _Tp() == __y.imag(); } + //@} + + //@{ + /// Return false if @a x is equal to @a y. + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __x.real() != __y.real() || __x.imag() != __y.imag(); } + + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const complex<_Tp>& __x, const _Tp& __y) + { return __x.real() != __y || __x.imag() != _Tp(); } + + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const _Tp& __x, const complex<_Tp>& __y) + { return __x != __y.real() || _Tp() != __y.imag(); } +#endif + //@} + + // Values +#if __cplusplus >= 201103L + template + constexpr _Tp + real(const complex<_Tp>& __z) + { return __z.real(); } + + template + constexpr _Tp + imag(const complex<_Tp>& __z) + { return __z.imag(); } +#else + template + inline _Tp& + real(complex<_Tp>& __z) + { return __z.real(); } + + template + inline const _Tp& + real(const complex<_Tp>& __z) + { return __z.real(); } + + template + inline _Tp& + imag(complex<_Tp>& __z) + { return __z.imag(); } + + template + inline const _Tp& + imag(const complex<_Tp>& __z) + { return __z.imag(); } +#endif + + // 26.2.7/3 abs(__z): Returns the magnitude of __z. + template + inline _Tp + __complex_abs(const complex<_Tp>& __z) + { + _Tp __x = __z.real(); + _Tp __y = __z.imag(); + const _Tp __s = std::max(abs(__x), abs(__y)); + if (__s == _Tp()) // well ... + return __s; + __x /= __s; + __y /= __s; + return __s * sqrt(__x * __x + __y * __y); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline float + __complex_abs(__complex__ float __z) { return __builtin_cabsf(__z); } + + inline double + __complex_abs(__complex__ double __z) { return __builtin_cabs(__z); } + + inline long double + __complex_abs(const __complex__ long double& __z) + { return __builtin_cabsl(__z); } + + template + inline _Tp + abs(const complex<_Tp>& __z) { return __complex_abs(__z.__rep()); } +#else + template + inline _Tp + abs(const complex<_Tp>& __z) { return __complex_abs(__z); } +#endif + + + // 26.2.7/4: arg(__z): Returns the phase angle of __z. + template + inline _Tp + __complex_arg(const complex<_Tp>& __z) + { return atan2(__z.imag(), __z.real()); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline float + __complex_arg(__complex__ float __z) { return __builtin_cargf(__z); } + + inline double + __complex_arg(__complex__ double __z) { return __builtin_carg(__z); } + + inline long double + __complex_arg(const __complex__ long double& __z) + { return __builtin_cargl(__z); } + + template + inline _Tp + arg(const complex<_Tp>& __z) { return __complex_arg(__z.__rep()); } +#else + template + inline _Tp + arg(const complex<_Tp>& __z) { return __complex_arg(__z); } +#endif + + // 26.2.7/5: norm(__z) returns the squared magnitude of __z. + // As defined, norm() is -not- a norm is the common mathematical + // sense used in numerics. The helper class _Norm_helper<> tries to + // distinguish between builtin floating point and the rest, so as + // to deliver an answer as close as possible to the real value. + template + struct _Norm_helper + { + template + static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return __x * __x + __y * __y; + } + }; + + template<> + struct _Norm_helper + { + template + static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) + { + //_Tp __res = std::abs(__z); + //return __res * __res; + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return __x * __x + __y * __y; + } + }; + + template + inline _GLIBCXX20_CONSTEXPR _Tp + norm(const complex<_Tp>& __z) + { + return _Norm_helper<__is_floating<_Tp>::__value + && !_GLIBCXX_FAST_MATH>::_S_do_it(__z); + } + + template + inline complex<_Tp> + polar(const _Tp& __rho, const _Tp& __theta) + { + __glibcxx_assert( __rho >= 0 ); + return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta)); + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + conj(const complex<_Tp>& __z) + { return complex<_Tp>(__z.real(), -__z.imag()); } + + // Transcendentals + + // 26.2.8/1 cos(__z): Returns the cosine of __z. + template + inline complex<_Tp> + __complex_cos(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(cos(__x) * cosh(__y), -sin(__x) * sinh(__y)); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_cos(__complex__ float __z) { return __builtin_ccosf(__z); } + + inline __complex__ double + __complex_cos(__complex__ double __z) { return __builtin_ccos(__z); } + + inline __complex__ long double + __complex_cos(const __complex__ long double& __z) + { return __builtin_ccosl(__z); } + + template + inline complex<_Tp> + cos(const complex<_Tp>& __z) { return __complex_cos(__z.__rep()); } +#else + template + inline complex<_Tp> + cos(const complex<_Tp>& __z) { return __complex_cos(__z); } +#endif + + // 26.2.8/2 cosh(__z): Returns the hyperbolic cosine of __z. + template + inline complex<_Tp> + __complex_cosh(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(cosh(__x) * cos(__y), sinh(__x) * sin(__y)); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_cosh(__complex__ float __z) { return __builtin_ccoshf(__z); } + + inline __complex__ double + __complex_cosh(__complex__ double __z) { return __builtin_ccosh(__z); } + + inline __complex__ long double + __complex_cosh(const __complex__ long double& __z) + { return __builtin_ccoshl(__z); } + + template + inline complex<_Tp> + cosh(const complex<_Tp>& __z) { return __complex_cosh(__z.__rep()); } +#else + template + inline complex<_Tp> + cosh(const complex<_Tp>& __z) { return __complex_cosh(__z); } +#endif + + // 26.2.8/3 exp(__z): Returns the complex base e exponential of x + template + inline complex<_Tp> + __complex_exp(const complex<_Tp>& __z) + { return std::polar<_Tp>(exp(__z.real()), __z.imag()); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_exp(__complex__ float __z) { return __builtin_cexpf(__z); } + + inline __complex__ double + __complex_exp(__complex__ double __z) { return __builtin_cexp(__z); } + + inline __complex__ long double + __complex_exp(const __complex__ long double& __z) + { return __builtin_cexpl(__z); } + + template + inline complex<_Tp> + exp(const complex<_Tp>& __z) { return __complex_exp(__z.__rep()); } +#else + template + inline complex<_Tp> + exp(const complex<_Tp>& __z) { return __complex_exp(__z); } +#endif + + // 26.2.8/5 log(__z): Returns the natural complex logarithm of __z. + // The branch cut is along the negative axis. + template + inline complex<_Tp> + __complex_log(const complex<_Tp>& __z) + { return complex<_Tp>(log(std::abs(__z)), std::arg(__z)); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_log(__complex__ float __z) { return __builtin_clogf(__z); } + + inline __complex__ double + __complex_log(__complex__ double __z) { return __builtin_clog(__z); } + + inline __complex__ long double + __complex_log(const __complex__ long double& __z) + { return __builtin_clogl(__z); } + + template + inline complex<_Tp> + log(const complex<_Tp>& __z) { return __complex_log(__z.__rep()); } +#else + template + inline complex<_Tp> + log(const complex<_Tp>& __z) { return __complex_log(__z); } +#endif + + template + inline complex<_Tp> + log10(const complex<_Tp>& __z) + { return std::log(__z) / log(_Tp(10.0)); } + + // 26.2.8/10 sin(__z): Returns the sine of __z. + template + inline complex<_Tp> + __complex_sin(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(sin(__x) * cosh(__y), cos(__x) * sinh(__y)); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sin(__complex__ float __z) { return __builtin_csinf(__z); } + + inline __complex__ double + __complex_sin(__complex__ double __z) { return __builtin_csin(__z); } + + inline __complex__ long double + __complex_sin(const __complex__ long double& __z) + { return __builtin_csinl(__z); } + + template + inline complex<_Tp> + sin(const complex<_Tp>& __z) { return __complex_sin(__z.__rep()); } +#else + template + inline complex<_Tp> + sin(const complex<_Tp>& __z) { return __complex_sin(__z); } +#endif + + // 26.2.8/11 sinh(__z): Returns the hyperbolic sine of __z. + template + inline complex<_Tp> + __complex_sinh(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(sinh(__x) * cos(__y), cosh(__x) * sin(__y)); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sinh(__complex__ float __z) { return __builtin_csinhf(__z); } + + inline __complex__ double + __complex_sinh(__complex__ double __z) { return __builtin_csinh(__z); } + + inline __complex__ long double + __complex_sinh(const __complex__ long double& __z) + { return __builtin_csinhl(__z); } + + template + inline complex<_Tp> + sinh(const complex<_Tp>& __z) { return __complex_sinh(__z.__rep()); } +#else + template + inline complex<_Tp> + sinh(const complex<_Tp>& __z) { return __complex_sinh(__z); } +#endif + + // 26.2.8/13 sqrt(__z): Returns the complex square root of __z. + // The branch cut is on the negative axis. + template + complex<_Tp> + __complex_sqrt(const complex<_Tp>& __z) + { + _Tp __x = __z.real(); + _Tp __y = __z.imag(); + + if (__x == _Tp()) + { + _Tp __t = sqrt(abs(__y) / 2); + return complex<_Tp>(__t, __y < _Tp() ? -__t : __t); + } + else + { + _Tp __t = sqrt(2 * (std::abs(__z) + abs(__x))); + _Tp __u = __t / 2; + return __x > _Tp() + ? complex<_Tp>(__u, __y / __t) + : complex<_Tp>(abs(__y) / __t, __y < _Tp() ? -__u : __u); + } + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sqrt(__complex__ float __z) { return __builtin_csqrtf(__z); } + + inline __complex__ double + __complex_sqrt(__complex__ double __z) { return __builtin_csqrt(__z); } + + inline __complex__ long double + __complex_sqrt(const __complex__ long double& __z) + { return __builtin_csqrtl(__z); } + + template + inline complex<_Tp> + sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z.__rep()); } +#else + template + inline complex<_Tp> + sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z); } +#endif + + // 26.2.8/14 tan(__z): Return the complex tangent of __z. + + template + inline complex<_Tp> + __complex_tan(const complex<_Tp>& __z) + { return std::sin(__z) / std::cos(__z); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_tan(__complex__ float __z) { return __builtin_ctanf(__z); } + + inline __complex__ double + __complex_tan(__complex__ double __z) { return __builtin_ctan(__z); } + + inline __complex__ long double + __complex_tan(const __complex__ long double& __z) + { return __builtin_ctanl(__z); } + + template + inline complex<_Tp> + tan(const complex<_Tp>& __z) { return __complex_tan(__z.__rep()); } +#else + template + inline complex<_Tp> + tan(const complex<_Tp>& __z) { return __complex_tan(__z); } +#endif + + + // 26.2.8/15 tanh(__z): Returns the hyperbolic tangent of __z. + + template + inline complex<_Tp> + __complex_tanh(const complex<_Tp>& __z) + { return std::sinh(__z) / std::cosh(__z); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_tanh(__complex__ float __z) { return __builtin_ctanhf(__z); } + + inline __complex__ double + __complex_tanh(__complex__ double __z) { return __builtin_ctanh(__z); } + + inline __complex__ long double + __complex_tanh(const __complex__ long double& __z) + { return __builtin_ctanhl(__z); } + + template + inline complex<_Tp> + tanh(const complex<_Tp>& __z) { return __complex_tanh(__z.__rep()); } +#else + template + inline complex<_Tp> + tanh(const complex<_Tp>& __z) { return __complex_tanh(__z); } +#endif + + + // 26.2.8/9 pow(__x, __y): Returns the complex power base of __x + // raised to the __y-th power. The branch + // cut is on the negative axis. + template + complex<_Tp> + __complex_pow_unsigned(complex<_Tp> __x, unsigned __n) + { + complex<_Tp> __y = __n % 2 ? __x : complex<_Tp>(1); + + while (__n >>= 1) + { + __x *= __x; + if (__n % 2) + __y *= __x; + } + + return __y; + } + + // In C++11 mode we used to implement the resolution of + // DR 844. complex pow return type is ambiguous. + // thus the following overload was disabled in that mode. However, doing + // that causes all sorts of issues, see, for example: + // http://gcc.gnu.org/ml/libstdc++/2013-01/msg00058.html + // and also PR57974. + template + inline complex<_Tp> + pow(const complex<_Tp>& __z, int __n) + { + return __n < 0 + ? complex<_Tp>(1) / std::__complex_pow_unsigned(__z, -(unsigned)__n) + : std::__complex_pow_unsigned(__z, __n); + } + + template + complex<_Tp> + pow(const complex<_Tp>& __x, const _Tp& __y) + { +#if ! _GLIBCXX_USE_C99_COMPLEX + if (__x == _Tp()) + return _Tp(); +#endif + if (__x.imag() == _Tp() && __x.real() > _Tp()) + return pow(__x.real(), __y); + + complex<_Tp> __t = std::log(__x); + return std::polar<_Tp>(exp(__y * __t.real()), __y * __t.imag()); + } + + template + inline complex<_Tp> + __complex_pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __x == _Tp() ? _Tp() : std::exp(__y * std::log(__x)); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_pow(__complex__ float __x, __complex__ float __y) + { return __builtin_cpowf(__x, __y); } + + inline __complex__ double + __complex_pow(__complex__ double __x, __complex__ double __y) + { return __builtin_cpow(__x, __y); } + + inline __complex__ long double + __complex_pow(const __complex__ long double& __x, + const __complex__ long double& __y) + { return __builtin_cpowl(__x, __y); } + + template + inline complex<_Tp> + pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __complex_pow(__x.__rep(), __y.__rep()); } +#else + template + inline complex<_Tp> + pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __complex_pow(__x, __y); } +#endif + + template + inline complex<_Tp> + pow(const _Tp& __x, const complex<_Tp>& __y) + { + return __x > _Tp() ? std::polar<_Tp>(pow(__x, __y.real()), + __y.imag() * log(__x)) + : std::pow(complex<_Tp>(__x), __y); + } + + /// 26.2.3 complex specializations + /// complex specialization + template<> + struct complex + { + typedef float value_type; + typedef __complex__ float _ComplexT; + + _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } + + _GLIBCXX_CONSTEXPR complex(float __r = 0.0f, float __i = 0.0f) +#if __cplusplus >= 201103L + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif + + explicit _GLIBCXX_CONSTEXPR complex(const complex&); + explicit _GLIBCXX_CONSTEXPR complex(const complex&); + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + __attribute ((__abi_tag__ ("cxx11"))) + constexpr float + real() const { return __real__ _M_value; } + + __attribute ((__abi_tag__ ("cxx11"))) + constexpr float + imag() const { return __imag__ _M_value; } +#else + float& + real() { return __real__ _M_value; } + + const float& + real() const { return __real__ _M_value; } + + float& + imag() { return __imag__ _M_value; } + + const float& + imag() const { return __imag__ _M_value; } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX20_CONSTEXPR void + real(float __val) { __real__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR void + imag(float __val) { __imag__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR complex& + operator=(float __f) + { + _M_value = __f; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator+=(float __f) + { + _M_value += __f; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator-=(float __f) + { + _M_value -= __f; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator*=(float __f) + { + _M_value *= __f; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator/=(float __f) + { + _M_value /= __f; + return *this; + } + + // Let the compiler synthesize the copy and assignment + // operator. It always does a pretty good job. +#if __cplusplus >= 201103L + _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; +#endif + + template + _GLIBCXX20_CONSTEXPR complex& + operator=(const complex<_Tp>& __z) + { + __real__ _M_value = __z.real(); + __imag__ _M_value = __z.imag(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator+=(const complex<_Tp>& __z) + { + _M_value += __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator-=(const complex<_Tp>& __z) + { + _M_value -= __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator*=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value *= __t; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator/=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value /= __t; + return *this; + } + + _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } + + private: + _ComplexT _M_value; + }; + + /// 26.2.3 complex specializations + /// complex specialization + template<> + struct complex + { + typedef double value_type; + typedef __complex__ double _ComplexT; + + _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } + + _GLIBCXX_CONSTEXPR complex(double __r = 0.0, double __i = 0.0) +#if __cplusplus >= 201103L + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif + + _GLIBCXX_CONSTEXPR complex(const complex& __z) + : _M_value(__z.__rep()) { } + + explicit _GLIBCXX_CONSTEXPR complex(const complex&); + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + __attribute ((__abi_tag__ ("cxx11"))) + constexpr double + real() const { return __real__ _M_value; } + + __attribute ((__abi_tag__ ("cxx11"))) + constexpr double + imag() const { return __imag__ _M_value; } +#else + double& + real() { return __real__ _M_value; } + + const double& + real() const { return __real__ _M_value; } + + double& + imag() { return __imag__ _M_value; } + + const double& + imag() const { return __imag__ _M_value; } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX20_CONSTEXPR void + real(double __val) { __real__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR void + imag(double __val) { __imag__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR complex& + operator=(double __d) + { + _M_value = __d; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator+=(double __d) + { + _M_value += __d; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator-=(double __d) + { + _M_value -= __d; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator*=(double __d) + { + _M_value *= __d; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator/=(double __d) + { + _M_value /= __d; + return *this; + } + + // The compiler will synthesize this, efficiently. +#if __cplusplus >= 201103L + _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; +#endif + + template + _GLIBCXX20_CONSTEXPR complex& + operator=(const complex<_Tp>& __z) + { + _M_value = __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator+=(const complex<_Tp>& __z) + { + _M_value += __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator-=(const complex<_Tp>& __z) + { + _M_value -= __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator*=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value *= __t; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator/=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value /= __t; + return *this; + } + + _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } + + private: + _ComplexT _M_value; + }; + + /// 26.2.3 complex specializations + /// complex specialization + template<> + struct complex + { + typedef long double value_type; + typedef __complex__ long double _ComplexT; + + _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } + + _GLIBCXX_CONSTEXPR complex(long double __r = 0.0L, + long double __i = 0.0L) +#if __cplusplus >= 201103L + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif + + _GLIBCXX_CONSTEXPR complex(const complex& __z) + : _M_value(__z.__rep()) { } + + _GLIBCXX_CONSTEXPR complex(const complex& __z) + : _M_value(__z.__rep()) { } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + __attribute ((__abi_tag__ ("cxx11"))) + constexpr long double + real() const { return __real__ _M_value; } + + __attribute ((__abi_tag__ ("cxx11"))) + constexpr long double + imag() const { return __imag__ _M_value; } +#else + long double& + real() { return __real__ _M_value; } + + const long double& + real() const { return __real__ _M_value; } + + long double& + imag() { return __imag__ _M_value; } + + const long double& + imag() const { return __imag__ _M_value; } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX20_CONSTEXPR void + real(long double __val) { __real__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR void + imag(long double __val) { __imag__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR complex& + operator=(long double __r) + { + _M_value = __r; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator+=(long double __r) + { + _M_value += __r; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator-=(long double __r) + { + _M_value -= __r; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator*=(long double __r) + { + _M_value *= __r; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator/=(long double __r) + { + _M_value /= __r; + return *this; + } + + // The compiler knows how to do this efficiently +#if __cplusplus >= 201103L + _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; +#endif + + template + _GLIBCXX20_CONSTEXPR complex& + operator=(const complex<_Tp>& __z) + { + _M_value = __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator+=(const complex<_Tp>& __z) + { + _M_value += __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator-=(const complex<_Tp>& __z) + { + _M_value -= __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator*=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value *= __t; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator/=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value /= __t; + return *this; + } + + _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } + + private: + _ComplexT _M_value; + }; + + // These bits have to be at the end of this file, so that the + // specializations have all been defined. + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } + + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } + + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } + + // @} group complex_numbers + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // See ext/type_traits.h for the primary template. + template + struct __promote_2, _Up> + { + public: + typedef std::complex::__type> __type; + }; + + template + struct __promote_2<_Tp, std::complex<_Up> > + { + public: + typedef std::complex::__type> __type; + }; + + template + struct __promote_2, std::complex<_Up> > + { + public: + typedef std::complex::__type> __type; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Forward declarations. + template std::complex<_Tp> acos(const std::complex<_Tp>&); + template std::complex<_Tp> asin(const std::complex<_Tp>&); + template std::complex<_Tp> atan(const std::complex<_Tp>&); + + template std::complex<_Tp> acosh(const std::complex<_Tp>&); + template std::complex<_Tp> asinh(const std::complex<_Tp>&); + template std::complex<_Tp> atanh(const std::complex<_Tp>&); + // DR 595. + template _Tp fabs(const std::complex<_Tp>&); + + template + inline std::complex<_Tp> + __complex_acos(const std::complex<_Tp>& __z) + { + const std::complex<_Tp> __t = std::asin(__z); + const _Tp __pi_2 = 1.5707963267948966192313216916397514L; + return std::complex<_Tp>(__pi_2 - __t.real(), -__t.imag()); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_acos(__complex__ float __z) + { return __builtin_cacosf(__z); } + + inline __complex__ double + __complex_acos(__complex__ double __z) + { return __builtin_cacos(__z); } + + inline __complex__ long double + __complex_acos(const __complex__ long double& __z) + { return __builtin_cacosl(__z); } + + template + inline std::complex<_Tp> + acos(const std::complex<_Tp>& __z) + { return __complex_acos(__z.__rep()); } +#else + /// acos(__z) [8.1.2]. + // Effects: Behaves the same as C99 function cacos, defined + // in subclause 7.3.5.1. + template + inline std::complex<_Tp> + acos(const std::complex<_Tp>& __z) + { return __complex_acos(__z); } +#endif + + template + inline std::complex<_Tp> + __complex_asin(const std::complex<_Tp>& __z) + { + std::complex<_Tp> __t(-__z.imag(), __z.real()); + __t = std::asinh(__t); + return std::complex<_Tp>(__t.imag(), -__t.real()); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_asin(__complex__ float __z) + { return __builtin_casinf(__z); } + + inline __complex__ double + __complex_asin(__complex__ double __z) + { return __builtin_casin(__z); } + + inline __complex__ long double + __complex_asin(const __complex__ long double& __z) + { return __builtin_casinl(__z); } + + template + inline std::complex<_Tp> + asin(const std::complex<_Tp>& __z) + { return __complex_asin(__z.__rep()); } +#else + /// asin(__z) [8.1.3]. + // Effects: Behaves the same as C99 function casin, defined + // in subclause 7.3.5.2. + template + inline std::complex<_Tp> + asin(const std::complex<_Tp>& __z) + { return __complex_asin(__z); } +#endif + + template + std::complex<_Tp> + __complex_atan(const std::complex<_Tp>& __z) + { + const _Tp __r2 = __z.real() * __z.real(); + const _Tp __x = _Tp(1.0) - __r2 - __z.imag() * __z.imag(); + + _Tp __num = __z.imag() + _Tp(1.0); + _Tp __den = __z.imag() - _Tp(1.0); + + __num = __r2 + __num * __num; + __den = __r2 + __den * __den; + + return std::complex<_Tp>(_Tp(0.5) * atan2(_Tp(2.0) * __z.real(), __x), + _Tp(0.25) * log(__num / __den)); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_atan(__complex__ float __z) + { return __builtin_catanf(__z); } + + inline __complex__ double + __complex_atan(__complex__ double __z) + { return __builtin_catan(__z); } + + inline __complex__ long double + __complex_atan(const __complex__ long double& __z) + { return __builtin_catanl(__z); } + + template + inline std::complex<_Tp> + atan(const std::complex<_Tp>& __z) + { return __complex_atan(__z.__rep()); } +#else + /// atan(__z) [8.1.4]. + // Effects: Behaves the same as C99 function catan, defined + // in subclause 7.3.5.3. + template + inline std::complex<_Tp> + atan(const std::complex<_Tp>& __z) + { return __complex_atan(__z); } +#endif + + template + std::complex<_Tp> + __complex_acosh(const std::complex<_Tp>& __z) + { + // Kahan's formula. + return _Tp(2.0) * std::log(std::sqrt(_Tp(0.5) * (__z + _Tp(1.0))) + + std::sqrt(_Tp(0.5) * (__z - _Tp(1.0)))); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_acosh(__complex__ float __z) + { return __builtin_cacoshf(__z); } + + inline __complex__ double + __complex_acosh(__complex__ double __z) + { return __builtin_cacosh(__z); } + + inline __complex__ long double + __complex_acosh(const __complex__ long double& __z) + { return __builtin_cacoshl(__z); } + + template + inline std::complex<_Tp> + acosh(const std::complex<_Tp>& __z) + { return __complex_acosh(__z.__rep()); } +#else + /// acosh(__z) [8.1.5]. + // Effects: Behaves the same as C99 function cacosh, defined + // in subclause 7.3.6.1. + template + inline std::complex<_Tp> + acosh(const std::complex<_Tp>& __z) + { return __complex_acosh(__z); } +#endif + + template + std::complex<_Tp> + __complex_asinh(const std::complex<_Tp>& __z) + { + std::complex<_Tp> __t((__z.real() - __z.imag()) + * (__z.real() + __z.imag()) + _Tp(1.0), + _Tp(2.0) * __z.real() * __z.imag()); + __t = std::sqrt(__t); + + return std::log(__t + __z); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_asinh(__complex__ float __z) + { return __builtin_casinhf(__z); } + + inline __complex__ double + __complex_asinh(__complex__ double __z) + { return __builtin_casinh(__z); } + + inline __complex__ long double + __complex_asinh(const __complex__ long double& __z) + { return __builtin_casinhl(__z); } + + template + inline std::complex<_Tp> + asinh(const std::complex<_Tp>& __z) + { return __complex_asinh(__z.__rep()); } +#else + /// asinh(__z) [8.1.6]. + // Effects: Behaves the same as C99 function casin, defined + // in subclause 7.3.6.2. + template + inline std::complex<_Tp> + asinh(const std::complex<_Tp>& __z) + { return __complex_asinh(__z); } +#endif + + template + std::complex<_Tp> + __complex_atanh(const std::complex<_Tp>& __z) + { + const _Tp __i2 = __z.imag() * __z.imag(); + const _Tp __x = _Tp(1.0) - __i2 - __z.real() * __z.real(); + + _Tp __num = _Tp(1.0) + __z.real(); + _Tp __den = _Tp(1.0) - __z.real(); + + __num = __i2 + __num * __num; + __den = __i2 + __den * __den; + + return std::complex<_Tp>(_Tp(0.25) * (log(__num) - log(__den)), + _Tp(0.5) * atan2(_Tp(2.0) * __z.imag(), __x)); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_atanh(__complex__ float __z) + { return __builtin_catanhf(__z); } + + inline __complex__ double + __complex_atanh(__complex__ double __z) + { return __builtin_catanh(__z); } + + inline __complex__ long double + __complex_atanh(const __complex__ long double& __z) + { return __builtin_catanhl(__z); } + + template + inline std::complex<_Tp> + atanh(const std::complex<_Tp>& __z) + { return __complex_atanh(__z.__rep()); } +#else + /// atanh(__z) [8.1.7]. + // Effects: Behaves the same as C99 function catanh, defined + // in subclause 7.3.6.3. + template + inline std::complex<_Tp> + atanh(const std::complex<_Tp>& __z) + { return __complex_atanh(__z); } +#endif + + template + inline _Tp + /// fabs(__z) [8.1.8]. + // Effects: Behaves the same as C99 function cabs, defined + // in subclause 7.3.8.1. + fabs(const std::complex<_Tp>& __z) + { return std::abs(__z); } + + /// Additional overloads [8.1.9]. + template + inline typename __gnu_cxx::__promote<_Tp>::__type + arg(_Tp __x) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; +#if (_GLIBCXX11_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC) + return std::signbit(__x) ? __type(3.1415926535897932384626433832795029L) + : __type(); +#else + return std::arg(std::complex<__type>(__x)); +#endif + } + + template + _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type + imag(_Tp) + { return _Tp(); } + + template + _GLIBCXX20_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type + norm(_Tp __x) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __type(__x) * __type(__x); + } + + template + _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type + real(_Tp __x) + { return __x; } + + template + inline std::complex::__type> + pow(const std::complex<_Tp>& __x, const _Up& __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return std::pow(std::complex<__type>(__x), __type(__y)); + } + + template + inline std::complex::__type> + pow(const _Tp& __x, const std::complex<_Up>& __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return std::pow(__type(__x), std::complex<__type>(__y)); + } + + template + inline std::complex::__type> + pow(const std::complex<_Tp>& __x, const std::complex<_Up>& __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return std::pow(std::complex<__type>(__x), + std::complex<__type>(__y)); + } + + // Forward declarations. + // DR 781. + template + std::complex<_Tp> proj(const std::complex<_Tp>&); + + // Generic implementation of std::proj, does not work for infinities. + template + inline std::complex<_Tp> + __complex_proj(const std::complex<_Tp>& __z) + { return __z; } + +#if _GLIBCXX_USE_C99_COMPLEX + inline complex + __complex_proj(const complex& __z) + { return __builtin_cprojf(__z.__rep()); } + + inline complex + __complex_proj(const complex& __z) + { return __builtin_cproj(__z.__rep()); } + + inline complex + __complex_proj(const complex& __z) + { return __builtin_cprojl(__z.__rep()); } +#elif defined _GLIBCXX_USE_C99_MATH_TR1 + inline complex + __complex_proj(const complex& __z) + { + if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) + return complex(__builtin_inff(), + __builtin_copysignf(0.0f, __z.imag())); + return __z; + } + + inline complex + __complex_proj(const complex& __z) + { + if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) + return complex(__builtin_inf(), + __builtin_copysign(0.0, __z.imag())); + return __z; + } + + inline complex + __complex_proj(const complex& __z) + { + if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) + return complex(__builtin_infl(), + __builtin_copysignl(0.0l, __z.imag())); + return __z; + } +#endif + + template + inline std::complex<_Tp> + proj(const std::complex<_Tp>& __z) + { return __complex_proj(__z); } + + // Overload for scalars + template + inline std::complex::__type> + proj(_Tp __x) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return std::proj(std::complex<__type>(__x)); + } + + template + inline _GLIBCXX20_CONSTEXPR + std::complex::__type> + conj(_Tp __x) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return std::complex<__type>(__x, -__type()); + } + +#if __cplusplus > 201103L + +inline namespace literals { +inline namespace complex_literals { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" +#define __cpp_lib_complex_udls 201309 + + constexpr std::complex + operator""if(long double __num) + { return std::complex{0.0F, static_cast(__num)}; } + + constexpr std::complex + operator""if(unsigned long long __num) + { return std::complex{0.0F, static_cast(__num)}; } + + constexpr std::complex + operator""i(long double __num) + { return std::complex{0.0, static_cast(__num)}; } + + constexpr std::complex + operator""i(unsigned long long __num) + { return std::complex{0.0, static_cast(__num)}; } + + constexpr std::complex + operator""il(long double __num) + { return std::complex{0.0L, __num}; } + + constexpr std::complex + operator""il(unsigned long long __num) + { return std::complex{0.0L, static_cast(__num)}; } + +#pragma GCC diagnostic pop +} // inline namespace complex_literals +} // inline namespace literals + +#endif // C++14 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif /* _GLIBCXX_COMPLEX */ diff --git a/resources/sources/avr-libstdcpp/include/concepts b/resources/sources/avr-libstdcpp/include/concepts new file mode 100644 index 000000000..e710a5e6e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/concepts @@ -0,0 +1,367 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/concepts + * This is a Standard C++ Library header. + * @ingroup concepts + */ + +#ifndef _GLIBCXX_CONCEPTS +#define _GLIBCXX_CONCEPTS 1 + +#if __cplusplus > 201703L && __cpp_concepts >= 201907L + +#pragma GCC system_header + +/** + * @defgroup concepts Concepts + * @ingroup utilities + * + * Concepts for checking type requirements. + */ + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_concepts 202002L + + // [concepts.lang], language-related concepts + + namespace __detail + { + template + concept __same_as = std::is_same_v<_Tp, _Up>; + } // namespace __detail + + /// [concept.same], concept same_as + template + concept same_as + = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; + + /// [concept.derived], concept derived_from + template + concept derived_from = __is_base_of(_Base, _Derived) + && is_convertible_v; + + /// [concept.convertible], concept convertible_to + template + concept convertible_to = is_convertible_v<_From, _To> + && requires(add_rvalue_reference_t<_From> (&__f)()) { + static_cast<_To>(__f()); + }; + + /// [concept.commonref], concept common_reference_with + template + concept common_reference_with + = same_as, common_reference_t<_Up, _Tp>> + && convertible_to<_Tp, common_reference_t<_Tp, _Up>> + && convertible_to<_Up, common_reference_t<_Tp, _Up>>; + + /// [concept.common], concept common_with + template + concept common_with + = same_as, common_type_t<_Up, _Tp>> + && requires { + static_cast>(std::declval<_Tp>()); + static_cast>(std::declval<_Up>()); + } + && common_reference_with, + add_lvalue_reference_t> + && common_reference_with>, + common_reference_t< + add_lvalue_reference_t, + add_lvalue_reference_t>>; + + // [concepts.arithmetic], arithmetic concepts + + template + concept integral = is_integral_v<_Tp>; + + template + concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; + + template + concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; + + template + concept floating_point = is_floating_point_v<_Tp>; + + namespace __detail + { + template + using __cref = const remove_reference_t<_Tp>&; + + template + concept __class_or_enum + = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; + } // namespace __detail + + /// [concept.assignable], concept assignable_from + template + concept assignable_from + = is_lvalue_reference_v<_Lhs> + && common_reference_with<__detail::__cref<_Lhs>, __detail::__cref<_Rhs>> + && requires(_Lhs __lhs, _Rhs&& __rhs) { + { __lhs = static_cast<_Rhs&&>(__rhs) } -> same_as<_Lhs>; + }; + + /// [concept.destructible], concept destructible + template + concept destructible = is_nothrow_destructible_v<_Tp>; + + /// [concept.constructible], concept constructible_from + template + concept constructible_from + = destructible<_Tp> && is_constructible_v<_Tp, _Args...>; + + /// [concept.defaultinitializable], concept default_initializable + template + concept default_initializable = constructible_from<_Tp> + && requires + { + _Tp{}; + (void) ::new _Tp; + }; + + /// [concept.moveconstructible], concept move_constructible + template + concept move_constructible + = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; + + /// [concept.copyconstructible], concept copy_constructible + template + concept copy_constructible + = move_constructible<_Tp> + && constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> + && constructible_from<_Tp, const _Tp&> && convertible_to + && constructible_from<_Tp, const _Tp> && convertible_to; + + // [concept.swappable], concept swappable + + namespace ranges + { + namespace __cust_swap + { + template void swap(_Tp&, _Tp&) = delete; + + template + concept __adl_swap + = (__detail::__class_or_enum> + || __detail::__class_or_enum>) + && requires(_Tp&& __t, _Up&& __u) { + swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + }; + + struct _Swap + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_swap<_Tp, _Up>) + return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())); + else + return is_nothrow_move_constructible_v> + && is_nothrow_move_assignable_v>; + } + + public: + template + requires __adl_swap<_Tp, _Up> + || (same_as<_Tp, _Up> && is_lvalue_reference_v<_Tp> + && move_constructible> + && assignable_from<_Tp, remove_reference_t<_Tp>>) + constexpr void + operator()(_Tp&& __t, _Up&& __u) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__adl_swap<_Tp, _Up>) + swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + else + { + auto __tmp = static_cast&&>(__t); + __t = static_cast&&>(__u); + __u = static_cast&&>(__tmp); + } + } + + template + requires requires(const _Swap& __swap, _Tp& __e1, _Up& __e2) { + __swap(__e1, __e2); + } + constexpr void + operator()(_Tp (&__e1)[_Num], _Up (&__e2)[_Num]) const + noexcept(noexcept(std::declval()(*__e1, *__e2))) + { + for (size_t __n = 0; __n < _Num; ++__n) + (*this)(__e1[__n], __e2[__n]); + } + }; + } // namespace __cust_swap + + inline namespace __cust + { + inline constexpr __cust_swap::_Swap swap{}; + } // inline namespace __cust + } // namespace ranges + + template + concept swappable + = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; + + template + concept swappable_with = common_reference_with<_Tp, _Up> + && requires(_Tp&& __t, _Up&& __u) { + ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Tp&&>(__t)); + ranges::swap(static_cast<_Up&&>(__u), static_cast<_Up&&>(__u)); + ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + ranges::swap(static_cast<_Up&&>(__u), static_cast<_Tp&&>(__t)); + }; + + // [concepts.object], Object concepts + + template + concept movable = is_object_v<_Tp> && move_constructible<_Tp> + && assignable_from<_Tp&, _Tp> && swappable<_Tp>; + + template + concept copyable = copy_constructible<_Tp> && movable<_Tp> + && assignable_from<_Tp&, _Tp&> && assignable_from<_Tp&, const _Tp&> + && assignable_from<_Tp&, const _Tp>; + + template + concept semiregular = copyable<_Tp> && default_initializable<_Tp>; + + // [concepts.compare], comparison concepts + + // [concept.booleantestable], Boolean testability + namespace __detail + { + template + concept __boolean_testable_impl = convertible_to<_Tp, bool>; + + template + concept __boolean_testable + = __boolean_testable_impl<_Tp> + && requires(_Tp&& __t) + { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; }; + } // namespace __detail + + // [concept.equalitycomparable], concept equality_comparable + + namespace __detail + { + template + concept __weakly_eq_cmp_with + = requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) { + { __t == __u } -> __boolean_testable; + { __t != __u } -> __boolean_testable; + { __u == __t } -> __boolean_testable; + { __u != __t } -> __boolean_testable; + }; + } // namespace __detail + + template + concept equality_comparable = __detail::__weakly_eq_cmp_with<_Tp, _Tp>; + + template + concept equality_comparable_with + = equality_comparable<_Tp> && equality_comparable<_Up> + && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>> + && equality_comparable, + __detail::__cref<_Up>>> + && __detail::__weakly_eq_cmp_with<_Tp, _Up>; + + namespace __detail + { + template + concept __partially_ordered_with + = requires(const remove_reference_t<_Tp>& __t, + const remove_reference_t<_Up>& __u) { + { __t < __u } -> __boolean_testable; + { __t > __u } -> __boolean_testable; + { __t <= __u } -> __boolean_testable; + { __t >= __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + { __u > __t } -> __boolean_testable; + { __u <= __t } -> __boolean_testable; + { __u >= __t } -> __boolean_testable; + }; + } // namespace __detail + + // [concept.totallyordered], concept totally_ordered + template + concept totally_ordered + = equality_comparable<_Tp> + && __detail::__partially_ordered_with<_Tp, _Tp>; + + template + concept totally_ordered_with + = totally_ordered<_Tp> && totally_ordered<_Up> + && equality_comparable_with<_Tp, _Up> + && totally_ordered, + __detail::__cref<_Up>>> + && __detail::__partially_ordered_with<_Tp, _Up>; + + template + concept regular = semiregular<_Tp> && equality_comparable<_Tp>; + + // [concepts.callable], callable concepts + + /// [concept.invocable], concept invocable + template + concept invocable = is_invocable_v<_Fn, _Args...>; + + /// [concept.regularinvocable], concept regular_invocable + template + concept regular_invocable = invocable<_Fn, _Args...>; + + /// [concept.predicate], concept predicate + template + concept predicate = regular_invocable<_Fn, _Args...> + && __detail::__boolean_testable>; + + /// [concept.relation], concept relation + template + concept relation + = predicate<_Rel, _Tp, _Tp> && predicate<_Rel, _Up, _Up> + && predicate<_Rel, _Tp, _Up> && predicate<_Rel, _Up, _Tp>; + + /// [concept.equiv], concept equivalence_relation + template + concept equivalence_relation = relation<_Rel, _Tp, _Up>; + + /// [concept.strictweakorder], concept strict_weak_order + template + concept strict_weak_order = relation<_Rel, _Tp, _Up>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // C++2a + +#endif /* _GLIBCXX_CONCEPTS */ diff --git a/resources/sources/avr-libstdcpp/include/coroutine b/resources/sources/avr-libstdcpp/include/coroutine new file mode 100644 index 000000000..b40a3bcf9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/coroutine @@ -0,0 +1,303 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/coroutine + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_COROUTINE +#define _GLIBCXX_COROUTINE 1 + +#pragma GCC system_header + +// It is very likely that earlier versions would work, but they are untested. +#if __cplusplus >= 201402L + +#include + +/** + * @defgroup coroutines Coroutines + * + * Components for supporting coroutine implementations. + */ + +#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L +# include +# define _COROUTINES_USE_SPACESHIP 1 +#else +# include // for std::less +# define _COROUTINES_USE_SPACESHIP 0 +#endif + +namespace std _GLIBCXX_VISIBILITY (default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cpp_impl_coroutine + +#define __cpp_lib_coroutine 201902L + + inline namespace __n4861 { + + // 17.12.2 coroutine traits + /// [coroutine.traits] + /// [coroutine.traits.primary] + /// If _Result::promise_type is valid and denotes a type then the traits + /// have a single publicly accessible member, otherwise they are empty. + template + struct __coroutine_traits_impl {}; + + template + struct __coroutine_traits_impl<_Result, + __void_t> + { + using promise_type = typename _Result::promise_type; + }; + + template + struct coroutine_traits : __coroutine_traits_impl<_Result> {}; + + // 17.12.3 Class template coroutine_handle + /// [coroutine.handle] + template + struct coroutine_handle; + + template <> struct + coroutine_handle + { + public: + // 17.12.3.1, construct/reset + constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {} + + constexpr coroutine_handle(std::nullptr_t __h) noexcept + : _M_fr_ptr(__h) + {} + + coroutine_handle& operator=(std::nullptr_t) noexcept + { + _M_fr_ptr = nullptr; + return *this; + } + + public: + // 17.12.3.2, export/import + constexpr void* address() const noexcept { return _M_fr_ptr; } + + constexpr static coroutine_handle from_address(void* __a) noexcept + { + coroutine_handle __self; + __self._M_fr_ptr = __a; + return __self; + } + + public: + // 17.12.3.3, observers + constexpr explicit operator bool() const noexcept + { + return bool(_M_fr_ptr); + } + + bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); } + + // 17.12.3.4, resumption + void operator()() const { resume(); } + + void resume() const { __builtin_coro_resume(_M_fr_ptr); } + + void destroy() const { __builtin_coro_destroy(_M_fr_ptr); } + + protected: + void* _M_fr_ptr; + }; + + // 17.12.3.6 Comparison operators + /// [coroutine.handle.compare] + constexpr bool operator==(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return __a.address() == __b.address(); + } + +#if _COROUTINES_USE_SPACESHIP + constexpr strong_ordering + operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { return std::compare_three_way()(__a.address(), __b.address()); } +#else + // These are to enable operation with std=c++14,17. + constexpr bool operator!=(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return !(__a == __b); + } + + constexpr bool operator<(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return less()(__a.address(), __b.address()); + } + + constexpr bool operator>(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return __b < __a; + } + + constexpr bool operator<=(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return !(__a > __b); + } + + constexpr bool operator>=(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return !(__a < __b); + } +#endif + + template + struct coroutine_handle : coroutine_handle<> + { + // 17.12.3.1, construct/reset + using coroutine_handle<>::coroutine_handle; + + static coroutine_handle from_promise(_Promise& p) + { + coroutine_handle __self; + __self._M_fr_ptr + = __builtin_coro_promise((char*) &p, __alignof(_Promise), true); + return __self; + } + + coroutine_handle& operator=(std::nullptr_t) noexcept + { + coroutine_handle<>::operator=(nullptr); + return *this; + } + + // 17.12.3.2, export/import + constexpr static coroutine_handle from_address(void* __a) + { + coroutine_handle __self; + __self._M_fr_ptr = __a; + return __self; + } + + // 17.12.3.5, promise accesss + _Promise& promise() const + { + void* __t + = __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false); + return *static_cast<_Promise*>(__t); + } + }; + + /// [coroutine.noop] + struct noop_coroutine_promise + { + }; + + void __dummy_resume_destroy() __attribute__((__weak__)); + void __dummy_resume_destroy() {} + + struct __noop_coro_frame + { + void (*__r)() = __dummy_resume_destroy; + void (*__d)() = __dummy_resume_destroy; + struct noop_coroutine_promise __p; + } __noop_coro_fr __attribute__((__weak__)); + + // 17.12.4.1 Class noop_coroutine_promise + /// [coroutine.promise.noop] + template <> + struct coroutine_handle : public coroutine_handle<> + { + using _Promise = noop_coroutine_promise; + + public: + // 17.12.4.2.1, observers + constexpr explicit operator bool() const noexcept { return true; } + + constexpr bool done() const noexcept { return false; } + + // 17.12.4.2.2, resumption + void operator()() const noexcept {} + + void resume() const noexcept {} + + void destroy() const noexcept {} + + // 17.12.4.2.3, promise access + _Promise& promise() const + { + return *static_cast<_Promise*>( + __builtin_coro_promise(this->_M_fr_ptr, __alignof(_Promise), false)); + } + + // 17.12.4.2.4, address + private: + friend coroutine_handle noop_coroutine() noexcept; + + coroutine_handle() noexcept { this->_M_fr_ptr = (void*) &__noop_coro_fr; } + }; + + using noop_coroutine_handle = coroutine_handle; + + inline noop_coroutine_handle noop_coroutine() noexcept + { + return noop_coroutine_handle(); + } + + // 17.12.5 Trivial awaitables + /// [coroutine.trivial.awaitables] + struct suspend_always + { + bool await_ready() { return false; } + + void await_suspend(coroutine_handle<>) {} + + void await_resume() {} + }; + + struct suspend_never + { + bool await_ready() { return true; } + + void await_suspend(coroutine_handle<>) {} + + void await_resume() {} + }; + + } // namespace __n4861 + +#else +#error "the coroutine header requires -fcoroutines" +#endif + + _GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 (we are allowing use from at least this) + +#endif // _GLIBCXX_COROUTINE diff --git a/resources/sources/avr-libstdcpp/include/csetjmp b/resources/sources/avr-libstdcpp/include/csetjmp new file mode 100644 index 000000000..c3b77b023 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/csetjmp @@ -0,0 +1,61 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file csetjmp + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c setjmp.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CSETJMP +#define _GLIBCXX_CSETJMP 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef longjmp + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef setjmp +#define setjmp(env) setjmp (env) +#endif + +namespace std +{ + using ::jmp_buf; + using ::longjmp; +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/csignal b/resources/sources/avr-libstdcpp/include/csignal new file mode 100644 index 000000000..7a8841272 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/csignal @@ -0,0 +1,57 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file csignal + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c signal.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CSIGNAL +#define _GLIBCXX_CSIGNAL 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef raise + +namespace std +{ + using ::sig_atomic_t; + using ::signal; + using ::raise; +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cstdalign b/resources/sources/avr-libstdcpp/include/cstdalign new file mode 100644 index 000000000..b4c413a8a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdalign @@ -0,0 +1,44 @@ +// -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdalign + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CSTDALIGN +#define _GLIBCXX_CSTDALIGN 1 + +#if __cplusplus < 201103L +# include +#else +# include +# if _GLIBCXX_HAVE_STDALIGN_H +# include +# endif +#endif + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/cstdarg b/resources/sources/avr-libstdcpp/include/cstdarg new file mode 100644 index 000000000..749c85ec8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdarg @@ -0,0 +1,58 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdarg + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stdarg.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#undef __need___va_list +#include +#include + +#ifndef _GLIBCXX_CSTDARG +#define _GLIBCXX_CSTDARG 1 + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef va_end +#define va_end(ap) va_end (ap) +#endif + +namespace std +{ + using ::va_list; +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cstdbool b/resources/sources/avr-libstdcpp/include/cstdbool new file mode 100644 index 000000000..c76ecca3e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdbool @@ -0,0 +1,44 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdbool + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CSTDBOOL +#define _GLIBCXX_CSTDBOOL 1 + +#if __cplusplus < 201103L +# include +#else +# include +# if _GLIBCXX_HAVE_STDBOOL_H +# include +# endif +#endif + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/cstddef b/resources/sources/avr-libstdcpp/include/cstddef new file mode 100644 index 000000000..ce9cd3e9d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstddef @@ -0,0 +1,181 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cstddef + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stddef.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.1 Types +// + +#ifndef _GLIBCXX_CSTDDEF +#define _GLIBCXX_CSTDDEF 1 + +#pragma GCC system_header + +#undef __need_wchar_t +#undef __need_ptrdiff_t +#undef __need_size_t +#undef __need_NULL +#undef __need_wint_t +#include +#include + +extern "C++" +{ +#if __cplusplus >= 201103L +namespace std +{ + // We handle size_t, ptrdiff_t, and nullptr_t in c++config.h. + using ::max_align_t; +} +#endif // C++11 + +#if __cplusplus >= 201703L +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +#define __cpp_lib_byte 201603 + + /// std::byte + enum class byte : unsigned char {}; + + template struct __byte_operand { }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; +#ifdef _GLIBCXX_USE_WCHAR_T + template<> struct __byte_operand { using __type = byte; }; +#endif +#ifdef _GLIBCXX_USE_CHAR8_T + template<> struct __byte_operand { using __type = byte; }; +#endif + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_0> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_1> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_2> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + + template + using __byte_op_t = typename __byte_operand<_IntegerType>::__type; + + template + constexpr __byte_op_t<_IntegerType> + operator<<(byte __b, _IntegerType __shift) noexcept + { return (byte)(unsigned char)((unsigned)__b << __shift); } + + template + constexpr __byte_op_t<_IntegerType> + operator>>(byte __b, _IntegerType __shift) noexcept + { return (byte)(unsigned char)((unsigned)__b >> __shift); } + + constexpr byte + operator|(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l | (unsigned)__r); } + + constexpr byte + operator&(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l & (unsigned)__r); } + + constexpr byte + operator^(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l ^ (unsigned)__r); } + + constexpr byte + operator~(byte __b) noexcept + { return (byte)(unsigned char)~(unsigned)__b; } + + template + constexpr __byte_op_t<_IntegerType>& + operator<<=(byte& __b, _IntegerType __shift) noexcept + { return __b = __b << __shift; } + + template + constexpr __byte_op_t<_IntegerType>& + operator>>=(byte& __b, _IntegerType __shift) noexcept + { return __b = __b >> __shift; } + + constexpr byte& + operator|=(byte& __l, byte __r) noexcept + { return __l = __l | __r; } + + constexpr byte& + operator&=(byte& __l, byte __r) noexcept + { return __l = __l & __r; } + + constexpr byte& + operator^=(byte& __l, byte __r) noexcept + { return __l = __l ^ __r; } + + template + constexpr _IntegerType + to_integer(__byte_op_t<_IntegerType> __b) noexcept + { return _IntegerType(__b); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 +} // extern "C++" + +#endif // _GLIBCXX_CSTDDEF diff --git a/resources/sources/avr-libstdcpp/include/cstdint b/resources/sources/avr-libstdcpp/include/cstdint new file mode 100644 index 000000000..8e742fa7b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdint @@ -0,0 +1,91 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdint + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_CSTDINT +#define _GLIBCXX_CSTDINT 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +#if _GLIBCXX_HAVE_STDINT_H +# include +#endif + +namespace std +{ +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + using ::int8_t; + using ::int16_t; + using ::int32_t; + using ::int64_t; + + using ::int_fast8_t; + using ::int_fast16_t; + using ::int_fast32_t; + using ::int_fast64_t; + + using ::int_least8_t; + using ::int_least16_t; + using ::int_least32_t; + using ::int_least64_t; + + using ::intmax_t; + using ::intptr_t; + + using ::uint8_t; + using ::uint16_t; + using ::uint32_t; + using ::uint64_t; + + using ::uint_fast8_t; + using ::uint_fast16_t; + using ::uint_fast32_t; + using ::uint_fast64_t; + + using ::uint_least8_t; + using ::uint_least16_t; + using ::uint_least32_t; + using ::uint_least64_t; + + using ::uintmax_t; + using ::uintptr_t; +#else // !_GLIBCXX_USE_C99_STDINT_TR1 + // Define the minimum needed for , etc. + using intmax_t = __INTMAX_TYPE__; + using uintmax_t = __UINTMAX_TYPE__; +#endif // _GLIBCXX_USE_C99_STDINT_TR1 +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_CSTDINT diff --git a/resources/sources/avr-libstdcpp/include/cstdio b/resources/sources/avr-libstdcpp/include/cstdio new file mode 100644 index 000000000..b1dad4e4b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdio @@ -0,0 +1,192 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdio + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stdio.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 27.8.2 C Library files +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CSTDIO +#define _GLIBCXX_CSTDIO 1 + +#if __cplusplus <= 201103L && !defined(_GLIBCXX_HAVE_GETS) +extern "C" char* gets (char* __s) __attribute__((__deprecated__)); +#endif + +// Get rid of those macros defined in in lieu of real functions. +#undef clearerr +#undef fclose +#undef feof +#undef ferror +#undef fflush +#undef fgetc +#undef fgetpos +#undef fgets +#undef fopen +#undef fprintf +#undef fputc +#undef fputs +#undef fread +#undef freopen +#undef fscanf +#undef fseek +#undef fsetpos +#undef ftell +#undef fwrite +#undef getc +#undef getchar +#if __cplusplus <= 201103L +# undef gets +#endif +#undef perror +#undef printf +#undef putc +#undef putchar +#undef puts +#undef remove +#undef rename +#undef rewind +#undef scanf +#undef setbuf +#undef setvbuf +#undef sprintf +#undef sscanf +#undef tmpfile +#undef tmpnam +#undef ungetc +#undef vfprintf +#undef vprintf +#undef vsprintf + +namespace std +{ + using ::FILE; + using ::fpos_t; + + using ::clearerr; + using ::fclose; + using ::feof; + using ::ferror; + using ::fflush; + using ::fgetc; + using ::fgetpos; + using ::fgets; + using ::fopen; + using ::fprintf; + using ::fputc; + using ::fputs; + using ::fread; + using ::freopen; + using ::fscanf; + using ::fseek; + using ::fsetpos; + using ::ftell; + using ::fwrite; + using ::getc; + using ::getchar; +#if __cplusplus <= 201103L + // LWG 2249 + using ::gets; +#endif + using ::perror; + using ::printf; + using ::putc; + using ::putchar; + using ::puts; + using ::remove; + using ::rename; + using ::rewind; + using ::scanf; + using ::setbuf; + using ::setvbuf; + using ::sprintf; + using ::sscanf; + using ::tmpfile; +#if _GLIBCXX_USE_TMPNAM + using ::tmpnam; +#endif + using ::ungetc; + using ::vfprintf; + using ::vprintf; + using ::vsprintf; +} // namespace + +#if _GLIBCXX_USE_C99_STDIO + +#undef snprintf +#undef vfscanf +#undef vscanf +#undef vsnprintf +#undef vsscanf + +namespace __gnu_cxx +{ +#if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC + extern "C" int + (snprintf)(char * __restrict, std::size_t, const char * __restrict, ...) + throw (); + extern "C" int + (vfscanf)(FILE * __restrict, const char * __restrict, __gnuc_va_list); + extern "C" int (vscanf)(const char * __restrict, __gnuc_va_list); + extern "C" int + (vsnprintf)(char * __restrict, std::size_t, const char * __restrict, + __gnuc_va_list) throw (); + extern "C" int + (vsscanf)(const char * __restrict, const char * __restrict, __gnuc_va_list) + throw (); +#endif + +#if !_GLIBCXX_USE_C99_DYNAMIC + using ::snprintf; + using ::vfscanf; + using ::vscanf; + using ::vsnprintf; +#endif +} // namespace __gnu_cxx + +namespace std +{ + using ::__gnu_cxx::snprintf; + using ::__gnu_cxx::vfscanf; + using ::__gnu_cxx::vscanf; + using ::__gnu_cxx::vsnprintf; +} // namespace std + +#endif // _GLIBCXX_USE_C99_STDIO + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cstdlib b/resources/sources/avr-libstdcpp/include/cstdlib new file mode 100644 index 000000000..a349672f2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdlib @@ -0,0 +1,201 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdlib + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stdlib.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include + +#ifndef _GLIBCXX_CSTDLIB +#define _GLIBCXX_CSTDLIB 1 + +#if !_GLIBCXX_HOSTED +// The C standard does not require a freestanding implementation to +// provide . However, the C++ standard does still require +// -- but only the functionality mentioned in +// [lib.support.start.term]. + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + +namespace std +{ + extern "C" void abort(void) throw () _GLIBCXX_NORETURN; + extern "C" int atexit(void (*)(void)) throw (); + extern "C" void exit(int) throw () _GLIBCXX_NORETURN; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT + extern "C" int at_quick_exit(void (*)(void)) throw (); +# endif +# ifdef _GLIBCXX_HAVE_QUICK_EXIT + extern "C" void quick_exit(int) throw() _GLIBCXX_NORETURN; +# endif +#endif +} // namespace std + +#else + +// Need to ensure this finds the C library's not a libstdc++ +// wrapper that might already be installed later in the include search path. +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include_next +#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include + +// Get rid of those macros defined in in lieu of real functions. +#undef abort +#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) +# undef aligned_alloc +#endif +#undef atexit +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT +# undef at_quick_exit +# endif +#endif +#undef atof +#undef atoi +#undef atol +#undef bsearch +#undef calloc +#undef div +#undef exit +#undef free +#undef getenv +#undef labs +#undef ldiv +#undef malloc +#undef mblen +#undef mbstowcs +#undef mbtowc +#undef qsort +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_QUICK_EXIT +# undef quick_exit +# endif +#endif +#undef rand +#undef realloc +#undef srand +#undef strtod +#undef strtol +#undef strtoul +#undef system +#undef wcstombs +#undef wctomb + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::div_t; + using ::ldiv_t; + + using ::abort; +#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) + using ::aligned_alloc; +#endif + using ::atexit; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT + using ::at_quick_exit; +# endif +#endif + using ::atof; + using ::atoi; + using ::atol; + using ::bsearch; + using ::calloc; + using ::div; + using ::exit; + using ::free; + using ::getenv; + using ::labs; + using ::ldiv; + using ::malloc; +#ifdef _GLIBCXX_HAVE_MBSTATE_T + using ::mblen; + using ::mbstowcs; + using ::mbtowc; +#endif // _GLIBCXX_HAVE_MBSTATE_T + using ::qsort; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_QUICK_EXIT + using ::quick_exit; +# endif +#endif + using ::rand; + using ::realloc; + using ::srand; + using ::strtod; + using ::strtol; + using ::strtoul; + using ::system; +#ifdef _GLIBCXX_USE_WCHAR_T + using ::wcstombs; + using ::wctomb; +#endif // _GLIBCXX_USE_WCHAR_T + +#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO + inline ldiv_t + div(long __i, long __j) { return ldiv(__i, __j); } +#endif + + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if _GLIBCXX_USE_C99_STDLIB + +#undef _Exit +#undef llabs +#undef lldiv +#undef atoll +#undef strtoll +#undef strtoull +#undef strtof +#undef strtold + +#endif // _GLIBCXX_USE_C99_STDLIB + +} // extern "C++" + +#endif // !_GLIBCXX_HOSTED + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cstring b/resources/sources/avr-libstdcpp/include/cstring new file mode 100644 index 000000000..02199a8e9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstring @@ -0,0 +1,126 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cstring + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c string.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CSTRING +#define _GLIBCXX_CSTRING 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef memchr +#undef memcmp +#undef memcpy +#undef memmove +#undef memset +#undef strcat +#undef strchr +#undef strcmp +#undef strcoll +#undef strcpy +#undef strcspn +#undef strerror +#undef strlen +#undef strncat +#undef strncmp +#undef strncpy +#undef strpbrk +#undef strrchr +#undef strspn +#undef strstr +#undef strtok +#undef strxfrm + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::memchr; + using ::memcmp; + using ::memcpy; + using ::memmove; + using ::memset; + using ::strcat; + using ::strcmp; + using ::strcoll; + using ::strcpy; + using ::strcspn; + using ::strerror; + using ::strlen; + using ::strncat; + using ::strncmp; + using ::strncpy; + using ::strspn; + using ::strtok; + using ::strxfrm; + using ::strchr; + using ::strpbrk; + using ::strrchr; + using ::strstr; + +#ifndef __CORRECT_ISO_CPP_STRING_H_PROTO + inline void* + memchr(void* __s, int __c, size_t __n) + { return __builtin_memchr(__s, __c, __n); } + + inline char* + strchr(char* __s, int __n) + { return __builtin_strchr(__s, __n); } + + inline char* + strpbrk(char* __s1, const char* __s2) + { return __builtin_strpbrk(__s1, __s2); } + + inline char* + strrchr(char* __s, int __n) + { return __builtin_strrchr(__s, __n); } + + inline char* + strstr(char* __s1, const char* __s2) + { return __builtin_strstr(__s1, __s2); } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ctgmath b/resources/sources/avr-libstdcpp/include/ctgmath new file mode 100644 index 000000000..6ee36036e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ctgmath @@ -0,0 +1,44 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ctgmath + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CTGMATH +#define _GLIBCXX_CTGMATH 1 + +#if __cplusplus < 201103L +# include +#else +# include +extern "C++" { +# include +} +#endif + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/ctime b/resources/sources/avr-libstdcpp/include/ctime new file mode 100644 index 000000000..abac94027 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ctime @@ -0,0 +1,84 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ctime + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c time.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.5 Date and time +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CTIME +#define _GLIBCXX_CTIME 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef clock +#undef difftime +#undef mktime +#undef time +#undef asctime +#undef ctime +#undef gmtime +#undef localtime +#undef strftime + +namespace std +{ + using ::clock_t; + using ::time_t; + using ::tm; + + using ::clock; + using ::difftime; + using ::mktime; + using ::time; + using ::asctime; + using ::ctime; + using ::gmtime; + using ::localtime; + using ::strftime; +} // namespace + +#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_TIMESPEC_GET) +#undef timespec_get +namespace std +{ + using ::timespec; + using ::timespec_get; +} // namespace std +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cuchar b/resources/sources/avr-libstdcpp/include/cuchar new file mode 100644 index 000000000..fc26715e2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cuchar @@ -0,0 +1,77 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 2015-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cuchar + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c uchar.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882:2011 21.8 +// + +#ifndef _GLIBCXX_CUCHAR +#define _GLIBCXX_CUCHAR 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +#if _GLIBCXX_USE_C11_UCHAR_CXX11 + +#include + +// Get rid of those macros defined in in lieu of real functions. +#undef mbrtoc16 +#undef c16rtomb +#undef mbrtoc32 +#undef c32rtomb + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::mbrtoc16; + using ::c16rtomb; + using ::mbrtoc32; + using ::c32rtomb; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _GLIBCXX_USE_C11_UCHAR_CXX11 + +#endif // C++11 + +#endif // _GLIBCXX_CUCHAR diff --git a/resources/sources/avr-libstdcpp/include/cwchar b/resources/sources/avr-libstdcpp/include/cwchar new file mode 100644 index 000000000..21857fa2d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cwchar @@ -0,0 +1,306 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cwchar + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c wchar.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 21.4 +// + +#pragma GCC system_header + +#include + +#if _GLIBCXX_HAVE_WCHAR_H +#include +#endif + +#ifndef _GLIBCXX_CWCHAR +#define _GLIBCXX_CWCHAR 1 + +// Need to do a bit of trickery here with mbstate_t as char_traits +// assumes it is in wchar.h, regardless of wchar_t specializations. +#ifndef _GLIBCXX_HAVE_MBSTATE_T +extern "C" +{ + typedef struct + { + int __fill[6]; + } mbstate_t; +} +#endif + +namespace std +{ + using ::mbstate_t; +} // namespace std + +// Get rid of those macros defined in in lieu of real functions. +#undef btowc +#undef fgetwc +#undef fgetws +#undef fputwc +#undef fputws +#undef fwide +#undef fwprintf +#undef fwscanf +#undef getwc +#undef getwchar +#undef mbrlen +#undef mbrtowc +#undef mbsinit +#undef mbsrtowcs +#undef putwc +#undef putwchar +#undef swprintf +#undef swscanf +#undef ungetwc +#undef vfwprintf +#if _GLIBCXX_HAVE_VFWSCANF +# undef vfwscanf +#endif +#undef vswprintf +#if _GLIBCXX_HAVE_VSWSCANF +# undef vswscanf +#endif +#undef vwprintf +#if _GLIBCXX_HAVE_VWSCANF +# undef vwscanf +#endif +#undef wcrtomb +#undef wcscat +#undef wcschr +#undef wcscmp +#undef wcscoll +#undef wcscpy +#undef wcscspn +#undef wcsftime +#undef wcslen +#undef wcsncat +#undef wcsncmp +#undef wcsncpy +#undef wcspbrk +#undef wcsrchr +#undef wcsrtombs +#undef wcsspn +#undef wcsstr +#undef wcstod +#if _GLIBCXX_HAVE_WCSTOF +# undef wcstof +#endif +#undef wcstok +#undef wcstol +#undef wcstoul +#undef wcsxfrm +#undef wctob +#undef wmemchr +#undef wmemcmp +#undef wmemcpy +#undef wmemmove +#undef wmemset +#undef wprintf +#undef wscanf + +#if _GLIBCXX_USE_WCHAR_T + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::wint_t; + + using ::btowc; + using ::fgetwc; + using ::fgetws; + using ::fputwc; + using ::fputws; + using ::fwide; + using ::fwprintf; + using ::fwscanf; + using ::getwc; + using ::getwchar; + using ::mbrlen; + using ::mbrtowc; + using ::mbsinit; + using ::mbsrtowcs; + using ::putwc; + using ::putwchar; +#ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF + using ::swprintf; +#endif + using ::swscanf; + using ::ungetwc; + using ::vfwprintf; +#if _GLIBCXX_HAVE_VFWSCANF + using ::vfwscanf; +#endif +#ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF + using ::vswprintf; +#endif +#if _GLIBCXX_HAVE_VSWSCANF + using ::vswscanf; +#endif + using ::vwprintf; +#if _GLIBCXX_HAVE_VWSCANF + using ::vwscanf; +#endif + using ::wcrtomb; + using ::wcscat; + using ::wcscmp; + using ::wcscoll; + using ::wcscpy; + using ::wcscspn; + using ::wcsftime; + using ::wcslen; + using ::wcsncat; + using ::wcsncmp; + using ::wcsncpy; + using ::wcsrtombs; + using ::wcsspn; + using ::wcstod; +#if _GLIBCXX_HAVE_WCSTOF + using ::wcstof; +#endif + using ::wcstok; + using ::wcstol; + using ::wcstoul; + using ::wcsxfrm; + using ::wctob; + using ::wmemcmp; + using ::wmemcpy; + using ::wmemmove; + using ::wmemset; + using ::wprintf; + using ::wscanf; + using ::wcschr; + using ::wcspbrk; + using ::wcsrchr; + using ::wcsstr; + using ::wmemchr; + +#ifndef __CORRECT_ISO_CPP_WCHAR_H_PROTO + inline wchar_t* + wcschr(wchar_t* __p, wchar_t __c) + { return wcschr(const_cast(__p), __c); } + + inline wchar_t* + wcspbrk(wchar_t* __s1, const wchar_t* __s2) + { return wcspbrk(const_cast(__s1), __s2); } + + inline wchar_t* + wcsrchr(wchar_t* __p, wchar_t __c) + { return wcsrchr(const_cast(__p), __c); } + + inline wchar_t* + wcsstr(wchar_t* __s1, const wchar_t* __s2) + { return wcsstr(const_cast(__s1), __s2); } + + inline wchar_t* + wmemchr(wchar_t* __p, wchar_t __c, size_t __n) + { return wmemchr(const_cast(__p), __c, __n); } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#if _GLIBCXX_USE_C99_WCHAR + +#undef wcstold +#undef wcstoll +#undef wcstoull + +namespace __gnu_cxx +{ +#if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC + extern "C" long double + (wcstold)(const wchar_t * __restrict, wchar_t ** __restrict) throw (); +#endif +#if !_GLIBCXX_USE_C99_DYNAMIC + using ::wcstold; +#endif +#if _GLIBCXX_USE_C99_LONG_LONG_CHECK || _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + extern "C" long long int + (wcstoll)(const wchar_t * __restrict, wchar_t ** __restrict, int) throw (); + extern "C" unsigned long long int + (wcstoull)(const wchar_t * __restrict, wchar_t ** __restrict, int) throw (); +#endif +#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + using ::wcstoll; + using ::wcstoull; +#endif +} // namespace __gnu_cxx + +namespace std +{ + using ::__gnu_cxx::wcstold; + using ::__gnu_cxx::wcstoll; + using ::__gnu_cxx::wcstoull; +} // namespace + +#endif + +#endif //_GLIBCXX_USE_WCHAR_T + +#if __cplusplus >= 201103L + +#ifdef _GLIBCXX_USE_WCHAR_T + +namespace std +{ +#if _GLIBCXX_HAVE_WCSTOF + using std::wcstof; +#endif +#if _GLIBCXX_HAVE_VFWSCANF + using std::vfwscanf; +#endif +#if _GLIBCXX_HAVE_VSWSCANF + using std::vswscanf; +#endif +#if _GLIBCXX_HAVE_VWSCANF + using std::vwscanf; +#endif + +#if _GLIBCXX_USE_C99_WCHAR + using std::wcstold; + using std::wcstoll; + using std::wcstoull; +#endif +} // namespace + +#endif // _GLIBCXX_USE_WCHAR_T + +#endif // C++11 + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cwctype b/resources/sources/avr-libstdcpp/include/cwctype new file mode 100644 index 000000000..5190ce81a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cwctype @@ -0,0 +1,110 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cwctype + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c wctype.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: +// + +#pragma GCC system_header + +#include + +#if _GLIBCXX_HAVE_WCTYPE_H + +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 10 +// Work around glibc BZ 9694 +#include +#endif + +#include +#endif // _GLIBCXX_HAVE_WCTYPE_H + +#ifndef _GLIBCXX_CWCTYPE +#define _GLIBCXX_CWCTYPE 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef iswalnum +#undef iswalpha +#if _GLIBCXX_HAVE_ISWBLANK +# undef iswblank +#endif +#undef iswcntrl +#undef iswctype +#undef iswdigit +#undef iswgraph +#undef iswlower +#undef iswprint +#undef iswpunct +#undef iswspace +#undef iswupper +#undef iswxdigit +#undef towctrans +#undef towlower +#undef towupper +#undef wctrans +#undef wctype + +#if _GLIBCXX_USE_WCHAR_T + +namespace std +{ + using ::wctrans_t; + using ::wctype_t; + using ::wint_t; + + using ::iswalnum; + using ::iswalpha; +#if _GLIBCXX_HAVE_ISWBLANK + using ::iswblank; +#endif + using ::iswcntrl; + using ::iswctype; + using ::iswdigit; + using ::iswgraph; + using ::iswlower; + using ::iswprint; + using ::iswpunct; + using ::iswspace; + using ::iswupper; + using ::iswxdigit; + using ::towctrans; + using ::towlower; + using ::towupper; + using ::wctrans; + using ::wctype; +} // namespace + +#endif //_GLIBCXX_USE_WCHAR_T + +#endif // _GLIBCXX_CWCTYPE diff --git a/resources/sources/avr-libstdcpp/include/debug/assertions.h b/resources/sources/avr-libstdcpp/include/debug/assertions.h new file mode 100644 index 000000000..fb52e4414 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/assertions.h @@ -0,0 +1,68 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/assertions.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_ASSERTIONS_H +#define _GLIBCXX_DEBUG_ASSERTIONS_H 1 + +#ifndef _GLIBCXX_DEBUG + +# define _GLIBCXX_DEBUG_ASSERT(_Condition) +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) +# define _GLIBCXX_DEBUG_ONLY(_Statement) + +#endif + +#ifndef _GLIBCXX_ASSERTIONS +# define __glibcxx_requires_non_empty_range(_First,_Last) +# define __glibcxx_requires_nonempty() +# define __glibcxx_requires_subscript(_N) +#else + +// Verify that [_First, _Last) forms a non-empty iterator range. +# define __glibcxx_requires_non_empty_range(_First,_Last) \ + __glibcxx_assert(__builtin_expect(_First != _Last, true)) +# define __glibcxx_requires_subscript(_N) \ + __glibcxx_assert(__builtin_expect(_N < this->size(), true)) +// Verify that the container is nonempty +# define __glibcxx_requires_nonempty() \ + __glibcxx_assert(__builtin_expect(!this->empty(), true)) +#endif + +#ifdef _GLIBCXX_DEBUG +# define _GLIBCXX_DEBUG_ASSERT(_Condition) __glibcxx_assert(_Condition) + +# ifdef _GLIBCXX_DEBUG_PEDANTIC +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) _GLIBCXX_DEBUG_ASSERT(_Condition) +# else +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) +# endif + +# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement +#endif + +#endif // _GLIBCXX_DEBUG_ASSERTIONS diff --git a/resources/sources/avr-libstdcpp/include/debug/debug.h b/resources/sources/avr-libstdcpp/include/debug/debug.h new file mode 100644 index 000000000..5c858e1a8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/debug.h @@ -0,0 +1,137 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/debug.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MACRO_SWITCH_H +#define _GLIBCXX_DEBUG_MACRO_SWITCH_H 1 + +/** Macros and namespaces used by the implementation outside of debug + * wrappers to verify certain properties. The __glibcxx_requires_xxx + * macros are merely wrappers around the __glibcxx_check_xxx wrappers + * when we are compiling with debug mode, but disappear when we are + * in release mode so that there is no checking performed in, e.g., + * the standard library algorithms. +*/ + +#include + +// Debug mode namespaces. + +/** + * @namespace std::__debug + * @brief GNU debug code, replaces standard behavior with debug behavior. + */ +namespace std +{ + namespace __debug { } +} + +/** @namespace __gnu_debug + * @brief GNU debug classes for public use. +*/ +namespace __gnu_debug +{ + using namespace std::__debug; + + template + struct _Safe_iterator; +} + +#ifndef _GLIBCXX_DEBUG + +# define __glibcxx_requires_cond(_Cond,_Msg) +# define __glibcxx_requires_valid_range(_First,_Last) +# define __glibcxx_requires_can_increment(_First,_Size) +# define __glibcxx_requires_can_increment_range(_First1,_Last1,_First2) +# define __glibcxx_requires_can_decrement_range(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted(_First,_Last) +# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) +# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) +# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_heap(_First,_Last) +# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) +# define __glibcxx_requires_string(_String) +# define __glibcxx_requires_string_len(_String,_Len) +# define __glibcxx_requires_irreflexive(_First,_Last) +# define __glibcxx_requires_irreflexive2(_First,_Last) +# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) +# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) + +#else + +# include + +# define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg) +# define __glibcxx_requires_valid_range(_First,_Last) \ + __glibcxx_check_valid_range(_First,_Last) +# define __glibcxx_requires_can_increment(_First,_Size) \ + __glibcxx_check_can_increment(_First,_Size) +# define __glibcxx_requires_can_increment_range(_First1,_Last1,_First2) \ + __glibcxx_check_can_increment_range(_First1,_Last1,_First2) +# define __glibcxx_requires_can_decrement_range(_First1,_Last1,_First2) \ + __glibcxx_check_can_decrement_range(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted(_First,_Last) \ + __glibcxx_check_sorted(_First,_Last) +# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) \ + __glibcxx_check_sorted_pred(_First,_Last,_Pred) +# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) \ + __glibcxx_check_sorted_set(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ + __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) +# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) \ + __glibcxx_check_partitioned_lower(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) \ + __glibcxx_check_partitioned_upper(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ + __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ + __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_heap(_First,_Last) \ + __glibcxx_check_heap(_First,_Last) +# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) \ + __glibcxx_check_heap_pred(_First,_Last,_Pred) +# define __glibcxx_requires_string(_String) __glibcxx_check_string(_String) +# define __glibcxx_requires_string_len(_String,_Len) \ + __glibcxx_check_string_len(_String,_Len) +# define __glibcxx_requires_irreflexive(_First,_Last) \ + __glibcxx_check_irreflexive(_First,_Last) +# define __glibcxx_requires_irreflexive2(_First,_Last) \ + __glibcxx_check_irreflexive2(_First,_Last) +# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) \ + __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) +# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) \ + __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) + +# include + +#endif + +#endif // _GLIBCXX_DEBUG_MACRO_SWITCH_H diff --git a/resources/sources/avr-libstdcpp/include/debug/formatter.h b/resources/sources/avr-libstdcpp/include/debug/formatter.h new file mode 100644 index 000000000..bb9b3e565 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/formatter.h @@ -0,0 +1,593 @@ +// Debug-mode error formatting implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/formatter.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_FORMATTER_H +#define _GLIBCXX_DEBUG_FORMATTER_H 1 + +#include + +#if __cpp_rtti +# include +# define _GLIBCXX_TYPEID(_Type) &typeid(_Type) +#else +namespace std +{ + class type_info; +} +# define _GLIBCXX_TYPEID(_Type) 0 +#endif + +#if __cplusplus >= 201103L +namespace __gnu_cxx +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +template + class __normal_iterator; + +_GLIBCXX_END_NAMESPACE_VERSION +} + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +template + class reverse_iterator; + +template + class move_iterator; + +_GLIBCXX_END_NAMESPACE_VERSION +} +#endif + +namespace __gnu_debug +{ + using std::type_info; + + template + bool __check_singular(const _Iterator&); + + class _Safe_sequence_base; + + template + class _Safe_iterator; + + template + class _Safe_local_iterator; + + template + class _Safe_sequence; + + enum _Debug_msg_id + { + // General checks + __msg_valid_range, + __msg_insert_singular, + __msg_insert_different, + __msg_erase_bad, + __msg_erase_different, + __msg_subscript_oob, + __msg_empty, + __msg_unpartitioned, + __msg_unpartitioned_pred, + __msg_unsorted, + __msg_unsorted_pred, + __msg_not_heap, + __msg_not_heap_pred, + // std::bitset checks + __msg_bad_bitset_write, + __msg_bad_bitset_read, + __msg_bad_bitset_flip, + // std::list checks + __msg_self_splice, + __msg_splice_alloc, + __msg_splice_bad, + __msg_splice_other, + __msg_splice_overlap, + // iterator checks + __msg_init_singular, + __msg_init_copy_singular, + __msg_init_const_singular, + __msg_copy_singular, + __msg_bad_deref, + __msg_bad_inc, + __msg_bad_dec, + __msg_iter_subscript_oob, + __msg_advance_oob, + __msg_retreat_oob, + __msg_iter_compare_bad, + __msg_compare_different, + __msg_iter_order_bad, + __msg_order_different, + __msg_distance_bad, + __msg_distance_different, + // istream_iterator + __msg_deref_istream, + __msg_inc_istream, + // ostream_iterator + __msg_output_ostream, + // istreambuf_iterator + __msg_deref_istreambuf, + __msg_inc_istreambuf, + // forward_list + __msg_insert_after_end, + __msg_erase_after_bad, + __msg_valid_range2, + // unordered container local iterators + __msg_local_iter_compare_bad, + __msg_non_empty_range, + // self move assign + __msg_self_move_assign, + // unordered container buckets + __msg_bucket_index_oob, + __msg_valid_load_factor, + // others + __msg_equal_allocs, + __msg_insert_range_from_self, + __msg_irreflexive_ordering + }; + + class _Error_formatter + { + // Tags denoting the type of parameter for construction + struct _Is_iterator { }; + struct _Is_iterator_value_type { }; + struct _Is_sequence { }; + struct _Is_instance { }; + + public: + /// Whether an iterator is constant, mutable, or unknown + enum _Constness + { + __unknown_constness, + __const_iterator, + __mutable_iterator, + __last_constness + }; + + // The state of the iterator (fine-grained), if we know it. + enum _Iterator_state + { + __unknown_state, + __singular, // singular, may still be attached to a sequence + __begin, // dereferenceable, and at the beginning + __middle, // dereferenceable, not at the beginning + __end, // past-the-end, may be at beginning if sequence empty + __before_begin, // before begin + __rbegin, // dereferenceable, and at the reverse-beginning + __rmiddle, // reverse-dereferenceable, not at the reverse-beginning + __rend, // reverse-past-the-end + __last_state + }; + + // A parameter that may be referenced by an error message + struct _Parameter + { + enum + { + __unused_param, + __iterator, + __sequence, + __integer, + __string, + __instance, + __iterator_value_type + } _M_kind; + + struct _Type + { + const char* _M_name; + const type_info* _M_type; + }; + + struct _Instance : _Type + { + const void* _M_address; + }; + + union + { + // When _M_kind == __iterator + struct : _Instance + { + _Constness _M_constness; + _Iterator_state _M_state; + const void* _M_sequence; + const type_info* _M_seq_type; + } _M_iterator; + + // When _M_kind == __sequence + _Instance _M_sequence; + + // When _M_kind == __integer + struct + { + const char* _M_name; + long _M_value; + } _M_integer; + + // When _M_kind == __string + struct + { + const char* _M_name; + const char* _M_value; + } _M_string; + + // When _M_kind == __instance + _Instance _M_instance; + + // When _M_kind == __iterator_value_type + _Type _M_iterator_value_type; + } _M_variant; + + _Parameter() : _M_kind(__unused_param), _M_variant() { } + + _Parameter(long __value, const char* __name) + : _M_kind(__integer), _M_variant() + { + _M_variant._M_integer._M_name = __name; + _M_variant._M_integer._M_value = __value; + } + + _Parameter(const char* __value, const char* __name) + : _M_kind(__string), _M_variant() + { + _M_variant._M_string._M_name = __name; + _M_variant._M_string._M_value = __value; + } + + template + _Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it, + const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); + _M_variant._M_iterator._M_constness = + __it._S_constant() ? __const_iterator : __mutable_iterator; + _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); + _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); + + if (__it._M_singular()) + _M_variant._M_iterator._M_state = __singular; + else + { + if (__it._M_is_before_begin()) + _M_variant._M_iterator._M_state = __before_begin; + else if (__it._M_is_end()) + _M_variant._M_iterator._M_state = __end; + else if (__it._M_is_begin()) + _M_variant._M_iterator._M_state = __begin; + else + _M_variant._M_iterator._M_state = __middle; + } + } + + template + _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it, + const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); + _M_variant._M_iterator._M_constness = + __it._S_constant() ? __const_iterator : __mutable_iterator; + _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); + _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); + + if (__it._M_singular()) + _M_variant._M_iterator._M_state = __singular; + else + { + if (__it._M_is_end()) + _M_variant._M_iterator._M_state = __end; + else if (__it._M_is_begin()) + _M_variant._M_iterator._M_state = __begin; + else + _M_variant._M_iterator._M_state = __middle; + } + } + + template + _Parameter(const _Type* const& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); + _M_variant._M_iterator._M_constness = __const_iterator; + _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + + template + _Parameter(_Type* const& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); + _M_variant._M_iterator._M_constness = __mutable_iterator; + _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + + template + _Parameter(_Iterator const& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); + _M_variant._M_iterator._M_constness = __unknown_constness; + _M_variant._M_iterator._M_state = + __gnu_debug::__check_singular(__it) ? __singular : __unknown_state; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + +#if __cplusplus >= 201103L + // The following constructors are only defined in C++11 to take + // advantage of the constructor delegation feature. + template + _Parameter( + __gnu_cxx::__normal_iterator<_Iterator, _Container> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } + + template + _Parameter(std::reverse_iterator<_Iterator> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); + _M_variant._M_iterator._M_state + = _S_reverse_state(_M_variant._M_iterator._M_state); + } + + template + _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence, + _Category>> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { + _M_variant._M_iterator._M_type + = _GLIBCXX_TYPEID(std::reverse_iterator<_Iterator>); + _M_variant._M_iterator._M_state + = _S_reverse_state(_M_variant._M_iterator._M_state); + } + + template + _Parameter(std::move_iterator<_Iterator> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } + + template + _Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence, + _Category>> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { + _M_variant._M_iterator._M_type + = _GLIBCXX_TYPEID(std::move_iterator<_Iterator>); + } + + private: + _Iterator_state + _S_reverse_state(_Iterator_state __state) + { + switch (__state) + { + case __begin: + return __rend; + case __middle: + return __rmiddle; + case __end: + return __rbegin; + default: + return __state; + } + } + + public: +#endif + + template + _Parameter(const _Safe_sequence<_Sequence>& __seq, + const char* __name, _Is_sequence) + : _M_kind(__sequence), _M_variant() + { + _M_variant._M_sequence._M_name = __name; + _M_variant._M_sequence._M_address = + static_cast(std::__addressof(__seq)); + _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); + } + + template + _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) + : _M_kind(__sequence), _M_variant() + { + _M_variant._M_sequence._M_name = __name; + _M_variant._M_sequence._M_address = std::__addressof(__seq); + _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); + } + + template + _Parameter(const _Iterator& __it, const char* __name, + _Is_iterator_value_type) + : _M_kind(__iterator_value_type), _M_variant() + { + _M_variant._M_iterator_value_type._M_name = __name; + _M_variant._M_iterator_value_type._M_type = + _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type); + } + + template + _Parameter(const _Type& __inst, const char* __name, _Is_instance) + : _M_kind(__instance), _M_variant() + { + _M_variant._M_instance._M_name = __name; + _M_variant._M_instance._M_address = &__inst; + _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type); + } + +#if !_GLIBCXX_INLINE_VERSION + void + _M_print_field(const _Error_formatter* __formatter, + const char* __name) const _GLIBCXX_DEPRECATED; + + void + _M_print_description(const _Error_formatter* __formatter) + const _GLIBCXX_DEPRECATED; +#endif + }; + + template + _Error_formatter& + _M_iterator(const _Iterator& __it, const char* __name = 0) + { + if (_M_num_parameters < std::size_t(__max_parameters)) + _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, + _Is_iterator()); + return *this; + } + + template + _Error_formatter& + _M_iterator_value_type(const _Iterator& __it, + const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = + _Parameter(__it, __name, _Is_iterator_value_type()); + return *this; + } + + _Error_formatter& + _M_integer(long __value, const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); + return *this; + } + + _Error_formatter& + _M_string(const char* __value, const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); + return *this; + } + + template + _Error_formatter& + _M_sequence(const _Sequence& __seq, const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, + _Is_sequence()); + return *this; + } + + template + _Error_formatter& + _M_instance(const _Type& __inst, const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name, + _Is_instance()); + return *this; + } + + _Error_formatter& + _M_message(const char* __text) + { _M_text = __text; return *this; } + + // Kept const qualifier for backward compatibility, to keep the same + // exported symbol. + _Error_formatter& + _M_message(_Debug_msg_id __id) const throw (); + + _GLIBCXX_NORETURN void + _M_error() const; + +#if !_GLIBCXX_INLINE_VERSION + template + void + _M_format_word(char*, int, const char*, _Tp) + const throw () _GLIBCXX_DEPRECATED; + + void + _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED; + + void + _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED; +#endif + + private: + _Error_formatter(const char* __file, unsigned int __line, + const char* __function) + : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) + , _M_function(__function) + { } + +#if !_GLIBCXX_INLINE_VERSION + void + _M_get_max_length() const throw () _GLIBCXX_DEPRECATED; +#endif + + enum { __max_parameters = 9 }; + + const char* _M_file; + unsigned int _M_line; + _Parameter _M_parameters[__max_parameters]; + unsigned int _M_num_parameters; + const char* _M_text; + const char* _M_function; + + public: + static _Error_formatter& + _S_at(const char* __file, unsigned int __line, const char* __function) + { + static _Error_formatter __formatter(__file, __line, __function); + return __formatter; + } + }; +} // namespace __gnu_debug + +#undef _GLIBCXX_TYPEID + +#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/functions.h b/resources/sources/avr-libstdcpp/include/debug/functions.h new file mode 100644 index 000000000..aaccc8dfe --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/functions.h @@ -0,0 +1,470 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/functions.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_FUNCTIONS_H +#define _GLIBCXX_DEBUG_FUNCTIONS_H 1 + +#include // for less + +#if __cplusplus >= 201103L +# include // for __miter_base +# include // for is_lvalue_reference and conditional. +#endif + +#include +#include + +namespace __gnu_debug +{ + template + struct _Insert_range_from_self_is_safe + { enum { __value = 0 }; }; + + template + struct _Is_contiguous_sequence : std::__false_type { }; + + /* Checks that [first, last) is a valid range, and then returns + * __first. This routine is useful when we can't use a separate + * assertion statement because, e.g., we are in a constructor. + */ + template + inline _InputIterator + __check_valid_range(const _InputIterator& __first, + const _InputIterator& __last, + const char* __file, + unsigned int __line, + const char* __function) + { + __glibcxx_check_valid_range_at(__first, __last, + __file, __line, __function); + return __first; + } + + /* Handle the case where __other is a pointer to _Sequence::value_type. */ + template + inline bool + __foreign_iterator_aux4( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + const typename _Sequence::value_type* __other) + { + typedef const typename _Sequence::value_type* _PointerType; + typedef std::less<_PointerType> _Less; +#if __cplusplus >= 201103L + constexpr _Less __l{}; +#else + const _Less __l = _Less(); +#endif + const _Sequence* __seq = __it._M_get_sequence(); + const _PointerType __begin = std::__addressof(*__seq->_M_base().begin()); + const _PointerType __end = std::__addressof(*(__seq->_M_base().end()-1)); + + // Check whether __other points within the contiguous storage. + return __l(__other, __begin) || __l(__end, __other); + } + + /* Fallback overload for when we can't tell, assume it is valid. */ + template + inline bool + __foreign_iterator_aux4( + const _Safe_iterator<_Iterator, _Sequence, _Category>&, ...) + { return true; } + + /* Handle sequences with contiguous storage */ + template + inline bool + __foreign_iterator_aux3( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + const _InputIterator& __other, const _InputIterator& __other_end, + std::__true_type) + { + if (__other == __other_end) + return true; // inserting nothing is safe even if not foreign iters + if (__it._M_get_sequence()->empty()) + return true; // can't be self-inserting if self is empty + return __foreign_iterator_aux4(__it, std::__addressof(*__other)); + } + + /* Handle non-contiguous containers, assume it is valid. */ + template + inline bool + __foreign_iterator_aux3( + const _Safe_iterator<_Iterator, _Sequence, _Category>&, + const _InputIterator&, const _InputIterator&, + std::__false_type) + { return true; } + + /** Handle debug iterators from the same type of container. */ + template + inline bool + __foreign_iterator_aux2( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + const _Safe_iterator<_OtherIterator, _Sequence, _Category>& __other, + const _Safe_iterator<_OtherIterator, _Sequence, _Category>&) + { return __it._M_get_sequence() != __other._M_get_sequence(); } + + /** Handle debug iterators from different types of container. */ + template + inline bool + __foreign_iterator_aux2( + const _Safe_iterator<_Iterator, _Sequence, _Category>&, + const _Safe_iterator<_OtherIterator, _OtherSequence, + _OtherCategory>&, + const _Safe_iterator<_OtherIterator, _OtherSequence, + _OtherCategory>&) + { return true; } + + /* Handle non-debug iterators. */ + template + inline bool + __foreign_iterator_aux2( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + const _InputIterator& __other, + const _InputIterator& __other_end) + { +#if __cplusplus < 201103L + typedef _Is_contiguous_sequence<_Sequence> __tag; +#else + using __lvalref = std::is_lvalue_reference< + typename std::iterator_traits<_InputIterator>::reference>; + using __contiguous = _Is_contiguous_sequence<_Sequence>; + using __tag = typename std::conditional<__lvalref::value, __contiguous, + std::__false_type>::type; +#endif + return __foreign_iterator_aux3(__it, __other, __other_end, __tag()); + } + + /* Handle the case where we aren't really inserting a range after all */ + template + inline bool + __foreign_iterator_aux( + const _Safe_iterator<_Iterator, _Sequence, _Category>&, + _Integral, _Integral, std::__true_type) + { return true; } + + /* Handle all iterators. */ + template + inline bool + __foreign_iterator_aux( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + _InputIterator __other, _InputIterator __other_end, + std::__false_type) + { + return _Insert_range_from_self_is_safe<_Sequence>::__value + || __foreign_iterator_aux2(__it, std::__miter_base(__other), + std::__miter_base(__other_end)); + } + + template + inline bool + __foreign_iterator( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + _InputIterator __other, _InputIterator __other_end) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + return __foreign_iterator_aux(__it, __other, __other_end, _Integral()); + } + + // Can't check if an input iterator sequence is sorted, because we + // can't step through the sequence. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_aux(const _InputIterator&, const _InputIterator&, + std::input_iterator_tag) + { return true; } + + // Can verify if a forward iterator sequence is in fact sorted using + // std::__is_sorted + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (*__next < *__first) + return false; + + return true; + } + + // Can't check if an input iterator sequence is sorted, because we can't step + // through the sequence. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_aux(const _InputIterator&, const _InputIterator&, + _Predicate, std::input_iterator_tag) + { return true; } + + // Can verify if a forward iterator sequence is in fact sorted using + // std::__is_sorted + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, std::forward_iterator_tag) + { + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (__pred(*__next, *__first)) + return false; + + return true; + } + + // Determine if a sequence is sorted. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted(const _InputIterator& __first, const _InputIterator& __last) + { + return __check_sorted_aux(__first, __last, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted(const _InputIterator& __first, const _InputIterator& __last, + _Predicate __pred) + { + return __check_sorted_aux(__first, __last, __pred, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set_aux(const _InputIterator& __first, + const _InputIterator& __last, + std::__true_type) + { return __check_sorted(__first, __last); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set_aux(const _InputIterator&, + const _InputIterator&, + std::__false_type) + { return true; } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set_aux(const _InputIterator& __first, + const _InputIterator& __last, + _Predicate __pred, std::__true_type) + { return __check_sorted(__first, __last, __pred); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set_aux(const _InputIterator&, + const _InputIterator&, _Predicate, + std::__false_type) + { return true; } + + // ... special variant used in std::merge, std::includes, std::set_*. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set(const _InputIterator1& __first, + const _InputIterator1& __last, + const _InputIterator2&) + { + typedef typename std::iterator_traits<_InputIterator1>::value_type + _ValueType1; + typedef typename std::iterator_traits<_InputIterator2>::value_type + _ValueType2; + + typedef typename std::__are_same<_ValueType1, _ValueType2>::__type + _SameType; + return __check_sorted_set_aux(__first, __last, _SameType()); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set(const _InputIterator1& __first, + const _InputIterator1& __last, + const _InputIterator2&, _Predicate __pred) + { + typedef typename std::iterator_traits<_InputIterator1>::value_type + _ValueType1; + typedef typename std::iterator_traits<_InputIterator2>::value_type + _ValueType2; + + typedef typename std::__are_same<_ValueType1, _ValueType2>::__type + _SameType; + return __check_sorted_set_aux(__first, __last, __pred, _SameType()); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 270. Binary search requirements overly strict + // Determine if a sequence is partitioned w.r.t. this element. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_partitioned_lower(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value) + { + while (__first != __last && *__first < __value) + ++__first; + if (__first != __last) + { + ++__first; + while (__first != __last && !(*__first < __value)) + ++__first; + } + return __first == __last; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_partitioned_upper(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value) + { + while (__first != __last && !(__value < *__first)) + ++__first; + if (__first != __last) + { + ++__first; + while (__first != __last && __value < *__first) + ++__first; + } + return __first == __last; + } + + // Determine if a sequence is partitioned w.r.t. this element. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_partitioned_lower(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value, + _Pred __pred) + { + while (__first != __last && bool(__pred(*__first, __value))) + ++__first; + if (__first != __last) + { + ++__first; + while (__first != __last && !bool(__pred(*__first, __value))) + ++__first; + } + return __first == __last; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_partitioned_upper(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value, + _Pred __pred) + { + while (__first != __last && !bool(__pred(__value, *__first))) + ++__first; + if (__first != __last) + { + ++__first; + while (__first != __last && bool(__pred(__value, *__first))) + ++__first; + } + return __first == __last; + } + +#if __cplusplus >= 201103L + struct _Irreflexive_checker + { + template + static typename std::iterator_traits<_It>::reference + __deref(); + + template() < __deref<_It>())> + _GLIBCXX20_CONSTEXPR + static bool + _S_is_valid(_It __it) + { return !(*__it < *__it); } + + // Fallback method if operator doesn't exist. + template + _GLIBCXX20_CONSTEXPR + static bool + _S_is_valid(_Args...) + { return true; } + + template()(__deref<_It>(), __deref<_It>()))> + _GLIBCXX20_CONSTEXPR + static bool + _S_is_valid_pred(_It __it, _Pred __pred) + { return !__pred(*__it, *__it); } + + // Fallback method if predicate can't be invoked. + template + _GLIBCXX20_CONSTEXPR + static bool + _S_is_valid_pred(_Args...) + { return true; } + }; + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_irreflexive(_Iterator __it) + { return _Irreflexive_checker::_S_is_valid(__it); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_irreflexive_pred(_Iterator __it, _Pred __pred) + { return _Irreflexive_checker::_S_is_valid_pred(__it, __pred); } +#endif + +} // namespace __gnu_debug + +#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/helper_functions.h b/resources/sources/avr-libstdcpp/include/debug/helper_functions.h new file mode 100644 index 000000000..62d530925 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/helper_functions.h @@ -0,0 +1,315 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/helper_functions.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H +#define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1 + +#include // for __addressof +#include // for iterator_traits, + // categories and _Iter_base +#include // for __is_integer + +#include // for pair + +namespace __gnu_debug +{ + template + class _Safe_iterator; + +#if __cplusplus >= 201103L + template + class _Safe_local_iterator; +#endif + + /** The precision to which we can calculate the distance between + * two iterators. + */ + enum _Distance_precision + { + __dp_none, // Not even an iterator type + __dp_equality, //< Can compare iterator equality, only + __dp_sign, //< Can determine equality and ordering + __dp_sign_max_size, //< __dp_sign and gives max range size + __dp_exact //< Can determine distance precisely + }; + + template::__type> + struct _Distance_traits + { + private: + typedef + typename std::iterator_traits<_Iterator>::difference_type _ItDiffType; + + template::__type> + struct _DiffTraits + { typedef _DiffType __type; }; + + template + struct _DiffTraits<_DiffType, std::__true_type> + { typedef std::ptrdiff_t __type; }; + + typedef typename _DiffTraits<_ItDiffType>::__type _DiffType; + + public: + typedef std::pair<_DiffType, _Distance_precision> __type; + }; + + template + struct _Distance_traits<_Integral, std::__true_type> + { typedef std::pair __type; }; + + /** Determine the distance between two iterators with some known + * precision. + */ + template + _GLIBCXX_CONSTEXPR + inline typename _Distance_traits<_Iterator>::__type + __get_distance(_Iterator __lhs, _Iterator __rhs, + std::random_access_iterator_tag) + { return std::make_pair(__rhs - __lhs, __dp_exact); } + + template + _GLIBCXX14_CONSTEXPR + inline typename _Distance_traits<_Iterator>::__type + __get_distance(_Iterator __lhs, _Iterator __rhs, + std::input_iterator_tag) + { + if (__lhs == __rhs) + return std::make_pair(0, __dp_exact); + + return std::make_pair(1, __dp_equality); + } + + template + _GLIBCXX_CONSTEXPR + inline typename _Distance_traits<_Iterator>::__type + __get_distance(_Iterator __lhs, _Iterator __rhs) + { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } + + // An arbitrary iterator pointer is not singular. + inline bool + __check_singular_aux(const void*) { return false; } + + // We may have an iterator that derives from _Safe_iterator_base but isn't + // a _Safe_iterator. + template + inline bool + __check_singular(_Iterator const& __x) + { return __check_singular_aux(std::__addressof(__x)); } + + /** Non-NULL pointers are nonsingular. */ + template + inline bool + __check_singular(_Tp* const& __ptr) + { return __ptr == 0; } + + /** We say that integral types for a valid range, and defer to other + * routines to realize what to do with integral types instead of + * iterators. + */ + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_Integral, _Integral, std::__true_type) + { return true; } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __valid_range_aux(_Integral, _Integral, + typename _Distance_traits<_Integral>::__type& __dist, + std::__true_type) + { + __dist = std::make_pair(0, __dp_none); + return true; + } + + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + return __first == __last + || (!__check_singular(__first) && !__check_singular(__last)); + } + + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::random_access_iterator_tag) + { + return + __valid_range_aux(__first, __last, std::input_iterator_tag()) + && __first <= __last; + } + + /** We have iterators, so figure out what kind of iterators they are + * to see if we can check the range ahead of time. + */ + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::__false_type) + { + return __valid_range_aux(__first, __last, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + typename _Distance_traits<_InputIterator>::__type& __dist, + std::__false_type) + { + if (!__valid_range_aux(__first, __last, std::input_iterator_tag())) + return false; + + __dist = __get_distance(__first, __last); + switch (__dist.second) + { + case __dp_none: + break; + case __dp_equality: + if (__dist.first == 0) + return true; + break; + case __dp_sign: + case __dp_sign_max_size: + case __dp_exact: + return __dist.first >= 0; + } + + // Can't tell so assume it is fine. + return true; + } + + /** Don't know what these iterators are, or if they are even + * iterators (we may get an integral type for InputIterator), so + * see if they are integral and pass them on to the next phase + * otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + __valid_range(_InputIterator __first, _InputIterator __last, + typename _Distance_traits<_InputIterator>::__type& __dist) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + // Detected by the compiler directly. + return true; +#endif + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + return __valid_range_aux(__first, __last, __dist, _Integral()); + } + + template + bool + __valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&, + const _Safe_iterator<_Iterator, _Sequence, _Category>&, + typename _Distance_traits<_Iterator>::__type&); + +#if __cplusplus >= 201103L + template + bool + __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&, + const _Safe_local_iterator<_Iterator, _Sequence>&, + typename _Distance_traits<_Iterator>::__type&); +#endif + + template + _GLIBCXX14_CONSTEXPR + inline bool + __valid_range(_InputIterator __first, _InputIterator __last) + { +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) + // Detected by the compiler directly. + return true; +#endif + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + return __valid_range_aux(__first, __last, _Integral()); + } + + template + bool + __valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&, + const _Safe_iterator<_Iterator, _Sequence, _Category>&); + +#if __cplusplus >= 201103L + template + bool + __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&, + const _Safe_local_iterator<_Iterator, _Sequence>&); +#endif + + // Fallback method, always ok. + template + _GLIBCXX_CONSTEXPR + inline bool + __can_advance(_InputIterator, _Size) + { return true; } + + template + bool + __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>&, + _Size); + + /** Helper function to extract base iterator of random access safe iterator + * in order to reduce performance impact of debug mode. Limited to random + * access iterator because it is the only category for which it is possible + * to check for correct iterators order in the __valid_range function + * thanks to the < operator. + */ + template + _GLIBCXX_CONSTEXPR + inline _Iterator + __base(_Iterator __it) + { return __it; } + +#if __cplusplus < 201103L + template + struct _Unsafe_type + { typedef _Iterator _Type; }; +#endif + + /* Remove debug mode safe iterator layer, if any. */ + template + inline _Iterator + __unsafe(_Iterator __it) + { return __it; } +} + +#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/macros.h b/resources/sources/avr-libstdcpp/include/debug/macros.h new file mode 100644 index 000000000..73fb50d0c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/macros.h @@ -0,0 +1,471 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/macros.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MACROS_H +#define _GLIBCXX_DEBUG_MACROS_H 1 + +/** + * Macros used by the implementation to verify certain + * properties. These macros may only be used directly by the debug + * wrappers. Note that these are macros (instead of the more obviously + * @a correct choice of making them functions) because we need line and + * file information at the call site, to minimize the distance between + * the user error and where the error is reported. + * + */ +#if 0 /* defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED */ +# define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ + if (__builtin_is_constant_evaluated()) \ + /* FIXME: Compilation error here when !_Cond. */ \ + break; \ + if (! (_Cond)) \ + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ + ._ErrMsg._M_error() +#else +# define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ + if (! (_Cond)) \ + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ + ._ErrMsg._M_error() +#endif + +#define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func) \ + do \ + { \ + _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func); \ + } while (false) + +#define _GLIBCXX_DEBUG_VERIFY_AT(_Cond,_ErrMsg,_File,_Line) \ + _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,__PRETTY_FUNCTION__) + +#define _GLIBCXX_DEBUG_VERIFY(_Cond,_ErrMsg) \ + _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond, _ErrMsg, __FILE__, __LINE__, \ + __PRETTY_FUNCTION__) + +// Verify that [_First, _Last) forms a valid iterator range. +#define __glibcxx_check_valid_range(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last), \ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +#define __glibcxx_check_valid_range_at(_First,_Last,_File,_Line,_Func) \ +_GLIBCXX_DEBUG_VERIFY_AT_F(__gnu_debug::__valid_range(_First, _Last), \ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last), \ + _File,_Line,_Func) + +#define __glibcxx_check_valid_range2(_First,_Last,_Dist) \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last, _Dist), \ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +#define __glibcxx_check_valid_constructor_range(_First,_Last) \ + __gnu_debug::__check_valid_range(_First, _Last, \ + __FILE__, __LINE__, __PRETTY_FUNCTION__) + +// Verify that [_First, _Last) forms a non-empty iterator range. +#define __glibcxx_check_non_empty_range(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(_First != _Last, \ + _M_message(__gnu_debug::__msg_non_empty_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +// Verify that [_First, _First + _Size) forms a valid range. +#define __glibcxx_check_can_increment(_First,_Size) \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__can_advance(_First, _Size), \ + _M_message(__gnu_debug::__msg_iter_subscript_oob) \ + ._M_iterator(_First, #_First) \ + ._M_integer(_Size, #_Size)) + +#define __glibcxx_check_can_increment_range(_First1,_Last1,_First2) \ + do \ + { \ + typename __gnu_debug::_Distance_traits<__decltype(_First1)>::__type __dist;\ + _GLIBCXX_DEBUG_VERIFY_COND_AT( \ + __gnu_debug::__valid_range(_First1, _Last1, __dist),\ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1), \ + __FILE__,__LINE__,__PRETTY_FUNCTION__); \ + _GLIBCXX_DEBUG_VERIFY_COND_AT( \ + __gnu_debug::__can_advance(_First2, __dist.first),\ + _M_message(__gnu_debug::__msg_iter_subscript_oob)\ + ._M_iterator(_First2, #_First2) \ + ._M_integer(__dist.first), \ + __FILE__,__LINE__,__PRETTY_FUNCTION__); \ + } while(false) + +#define __glibcxx_check_can_decrement_range(_First1,_Last1,_First2) \ + do \ + { \ + typename __gnu_debug::_Distance_traits<__decltype(_First1)>::__type __dist;\ + _GLIBCXX_DEBUG_VERIFY_COND_AT( \ + __gnu_debug::__valid_range(_First1, _Last1, __dist),\ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1), \ + __FILE__,__LINE__,__PRETTY_FUNCTION__); \ + _GLIBCXX_DEBUG_VERIFY_COND_AT( \ + __gnu_debug::__can_advance(_First2, -__dist.first),\ + _M_message(__gnu_debug::__msg_iter_subscript_oob)\ + ._M_iterator(_First2, #_First2) \ + ._M_integer(-__dist.first), \ + __FILE__,__LINE__,__PRETTY_FUNCTION__); \ + } while(false) + +/** Verify that we can insert into *this with the iterator _Position. + * Insertion into a container at a specific position requires that + * the iterator be nonsingular, either dereferenceable or past-the-end, + * and that it reference the sequence we are inserting into. Note that + * this macro is only valid when the container is a_Safe_sequence and + * the iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert(_Position) \ +_GLIBCXX_DEBUG_VERIFY(!_Position._M_singular(), \ + _M_message(__gnu_debug::__msg_insert_singular) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_insert_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can insert into *this after the iterator _Position. + * Insertion into a container after a specific position requires that + * the iterator be nonsingular, either dereferenceable or before-begin, + * and that it reference the sequence we are inserting into. Note that + * this macro is only valid when the container is a_Safe_sequence and + * the iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert_after(_Position) \ +__glibcxx_check_insert(_Position); \ +_GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(), \ + _M_message(__gnu_debug::__msg_insert_after_end) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can insert the values in the iterator range + * [_First, _Last) into *this with the iterator _Position. Insertion + * into a container at a specific position requires that the iterator + * be nonsingular (i.e., either dereferenceable or past-the-end), + * that it reference the sequence we are inserting into, and that the + * iterator range [_First, _Last) is a valid (possibly empty) + * range which does not reference the sequence we are inserting into. + * Note that this macro is only valid when the container is a + * _Safe_sequence and the _Position iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert_range(_Position,_First,_Last,_Dist) \ +__glibcxx_check_valid_range2(_First,_Last,_Dist); \ +__glibcxx_check_insert(_Position); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\ + _M_message(__gnu_debug::__msg_insert_range_from_self)\ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_sequence(*this, "this")) + +/** Verify that we can insert the values in the iterator range + * [_First, _Last) into *this after the iterator _Position. Insertion + * into a container after a specific position requires that the iterator + * be nonsingular (i.e., either dereferenceable or past-the-end), + * that it reference the sequence we are inserting into, and that the + * iterator range [_First, _Last) is a valid (possibly empty) + * range which does not reference the sequence we are inserting into. + * Note that this macro is only valid when the container is a + * _Safe_sequence and the _Position iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert_range_after(_Position,_First,_Last,_Dist)\ +__glibcxx_check_valid_range2(_First,_Last,_Dist); \ +__glibcxx_check_insert_after(_Position); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\ + _M_message(__gnu_debug::__msg_insert_range_from_self)\ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_sequence(*this, "this")) + +/** Verify that we can erase the element referenced by the iterator + * _Position. We can erase the element if the _Position iterator is + * dereferenceable and references this sequence. +*/ +#define __glibcxx_check_erase(_Position) \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_dereferenceable(), \ + _M_message(__gnu_debug::__msg_erase_bad) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can erase the element after the iterator + * _Position. We can erase the element if the _Position iterator is + * before a dereferenceable one and references this sequence. +*/ +#define __glibcxx_check_erase_after(_Position) \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_before_dereferenceable(), \ + _M_message(__gnu_debug::__msg_erase_after_bad) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can erase the elements in the iterator range + * [_First, _Last). We can erase the elements if [_First, _Last) is a + * valid iterator range within this sequence. +*/ +#define __glibcxx_check_erase_range(_First,_Last) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that we can erase the elements in the iterator range + * (_First, _Last). We can erase the elements if (_First, _Last) is a + * valid iterator range within this sequence. +*/ +#define __glibcxx_check_erase_range_after(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(_First._M_can_compare(_Last), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First)); \ +_GLIBCXX_DEBUG_VERIFY(_First != _Last, \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_incrementable(), \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(!_Last._M_is_before_begin(), \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) \ + +// Verify that the subscript _N is less than the container's size. +#define __glibcxx_check_subscript(_N) \ +_GLIBCXX_DEBUG_VERIFY(_N < this->size(), \ + _M_message(__gnu_debug::__msg_subscript_oob) \ + ._M_sequence(*this, "this") \ + ._M_integer(_N, #_N) \ + ._M_integer(this->size(), "size")) + +// Verify that the bucket _N is less than the container's buckets count. +#define __glibcxx_check_bucket_index(_N) \ +_GLIBCXX_DEBUG_VERIFY(_N < this->bucket_count(), \ + _M_message(__gnu_debug::__msg_bucket_index_oob) \ + ._M_sequence(*this, "this") \ + ._M_integer(_N, #_N) \ + ._M_integer(this->bucket_count(), "size")) + +// Verify that the container is nonempty +#define __glibcxx_check_nonempty() \ +_GLIBCXX_DEBUG_VERIFY(! this->empty(), \ + _M_message(__gnu_debug::__msg_empty) \ + ._M_sequence(*this, "this")) + +// Verify that a predicate is irreflexive +#define __glibcxx_check_irreflexive(_First,_Last) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last || !(*_First < *_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_iterator_value_type(_First, "< operator type")) + +#if __cplusplus >= 201103L +# define __glibcxx_check_irreflexive2(_First,_Last) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last \ + || __gnu_debug::__is_irreflexive(_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_iterator_value_type(_First, "< operator type")) +#else +# define __glibcxx_check_irreflexive2(_First,_Last) +#endif + +#define __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last || !_Pred(*_First, *_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_instance(_Pred, "functor") \ + ._M_iterator_value_type(_First, "ordered type")) + +#if __cplusplus >= 201103L +# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last \ + ||__gnu_debug::__is_irreflexive_pred(_First, _Pred), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_instance(_Pred, "functor") \ + ._M_iterator_value_type(_First, "ordered type")) +#else +# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) +#endif + +// Verify that the iterator range [_First, _Last) is sorted +#define __glibcxx_check_sorted(_First,_Last) \ +__glibcxx_check_valid_range(_First,_Last); \ +__glibcxx_check_irreflexive(_First,_Last); \ + _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last)), \ + _M_message(__gnu_debug::__msg_unsorted) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that the iterator range [_First, _Last) is sorted by the + predicate _Pred. */ +#define __glibcxx_check_sorted_pred(_First,_Last,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +__glibcxx_check_irreflexive_pred(_First,_Last,_Pred); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Pred), \ + _M_message(__gnu_debug::__msg_unsorted_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred)) + +// Special variant for std::merge, std::includes, std::set_* +#define __glibcxx_check_sorted_set(_First1,_Last1,_First2) \ +__glibcxx_check_valid_range(_First1,_Last1); \ +_GLIBCXX_DEBUG_VERIFY( \ + __gnu_debug::__check_sorted_set(__gnu_debug::__base(_First1), \ + __gnu_debug::__base(_Last1), _First2),\ + _M_message(__gnu_debug::__msg_unsorted) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1)) + +// Likewise with a _Pred. +#define __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ +__glibcxx_check_valid_range(_First1,_Last1); \ +_GLIBCXX_DEBUG_VERIFY( \ + __gnu_debug::__check_sorted_set(__gnu_debug::__base(_First1), \ + __gnu_debug::__base(_Last1), \ + _First2, _Pred), \ + _M_message(__gnu_debug::__msg_unsorted_pred) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1) \ + ._M_string(#_Pred)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value. */ +#define __glibcxx_check_partitioned_lower(_First,_Last,_Value) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_lower( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Value), \ + _M_message(__gnu_debug::__msg_unpartitioned) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Value)) + +#define __glibcxx_check_partitioned_upper(_First,_Last,_Value) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Value), \ + _M_message(__gnu_debug::__msg_unpartitioned) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Value)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value and predicate _Pred. */ +#define __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_lower( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Value, _Pred), \ + _M_message(__gnu_debug::__msg_unpartitioned_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred) \ + ._M_string(#_Value)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value and predicate _Pred. */ +#define __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Value, _Pred), \ + _M_message(__gnu_debug::__msg_unpartitioned_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred) \ + ._M_string(#_Value)) + +// Verify that the iterator range [_First, _Last) is a heap +#define __glibcxx_check_heap(_First,_Last) \ + _GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last)), \ + _M_message(__gnu_debug::__msg_not_heap) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that the iterator range [_First, _Last) is a heap + w.r.t. the predicate _Pred. */ +#define __glibcxx_check_heap_pred(_First,_Last,_Pred) \ + _GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), \ + _Pred), \ + _M_message(__gnu_debug::__msg_not_heap_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred)) + +// Verify that the container is not self move assigned +#define __glibcxx_check_self_move_assign(_Other) \ +_GLIBCXX_DEBUG_VERIFY(this != &_Other, \ + _M_message(__gnu_debug::__msg_self_move_assign) \ + ._M_sequence(*this, "this")) + +// Verify that load factor is positive +#define __glibcxx_check_max_load_factor(_F) \ +_GLIBCXX_DEBUG_VERIFY(_F > 0.0f, \ + _M_message(__gnu_debug::__msg_valid_load_factor) \ + ._M_sequence(*this, "this")) + +#define __glibcxx_check_equal_allocs(_This, _Other) \ +_GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \ + _M_message(__gnu_debug::__msg_equal_allocs) \ + ._M_sequence(_This, "this")) + +#define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_PEDASSERT(_String != 0) +#define __glibcxx_check_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0) + +#endif diff --git a/resources/sources/avr-libstdcpp/include/decimal/decimal b/resources/sources/avr-libstdcpp/include/decimal/decimal new file mode 100644 index 000000000..8863d7e2a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/decimal/decimal @@ -0,0 +1,494 @@ +// -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file decimal/decimal + * This is a Standard C++ Library header. + */ + +// ISO/IEC TR 24733 +// Written by Janis Johnson + +#ifndef _GLIBCXX_DECIMAL +#define _GLIBCXX_DECIMAL 1 + +#pragma GCC system_header + +#include + +#ifndef _GLIBCXX_USE_DECIMAL_FLOAT +#error This file requires compiler and library support for ISO/IEC TR 24733 \ +that is currently not available. +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup decimal Decimal Floating-Point Arithmetic + * @ingroup numerics + * + * Classes and functions for decimal floating-point arithmetic. + * @{ + */ + + /** @namespace std::decimal + * @brief ISO/IEC TR 24733 Decimal floating-point arithmetic. + */ +namespace decimal +{ + class decimal32; + class decimal64; + class decimal128; + + // 3.2.5 Initialization from coefficient and exponent. + static decimal32 make_decimal32(long long __coeff, int __exp); + static decimal32 make_decimal32(unsigned long long __coeff, int __exp); + static decimal64 make_decimal64(long long __coeff, int __exp); + static decimal64 make_decimal64(unsigned long long __coeff, int __exp); + static decimal128 make_decimal128(long long __coeff, int __exp); + static decimal128 make_decimal128(unsigned long long __coeff, int __exp); + + /// Non-conforming extension: Conversion to integral type. + long long decimal32_to_long_long(decimal32 __d); + long long decimal64_to_long_long(decimal64 __d); + long long decimal128_to_long_long(decimal128 __d); + long long decimal_to_long_long(decimal32 __d); + long long decimal_to_long_long(decimal64 __d); + long long decimal_to_long_long(decimal128 __d); + + // 3.2.6 Conversion to generic floating-point type. + float decimal32_to_float(decimal32 __d); + float decimal64_to_float(decimal64 __d); + float decimal128_to_float(decimal128 __d); + float decimal_to_float(decimal32 __d); + float decimal_to_float(decimal64 __d); + float decimal_to_float(decimal128 __d); + + double decimal32_to_double(decimal32 __d); + double decimal64_to_double(decimal64 __d); + double decimal128_to_double(decimal128 __d); + double decimal_to_double(decimal32 __d); + double decimal_to_double(decimal64 __d); + double decimal_to_double(decimal128 __d); + + long double decimal32_to_long_double(decimal32 __d); + long double decimal64_to_long_double(decimal64 __d); + long double decimal128_to_long_double(decimal128 __d); + long double decimal_to_long_double(decimal32 __d); + long double decimal_to_long_double(decimal64 __d); + long double decimal_to_long_double(decimal128 __d); + + // 3.2.7 Unary arithmetic operators. + decimal32 operator+(decimal32 __rhs); + decimal64 operator+(decimal64 __rhs); + decimal128 operator+(decimal128 __rhs); + decimal32 operator-(decimal32 __rhs); + decimal64 operator-(decimal64 __rhs); + decimal128 operator-(decimal128 __rhs); + + // 3.2.8 Binary arithmetic operators. +#define _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(_Op, _T1, _T2, _T3) \ + _T1 operator _Op(_T2 __lhs, _T3 __rhs); +#define _DECLARE_DECIMAL_BINARY_OP_WITH_INT(_Op, _Tp) \ + _Tp operator _Op(_Tp __lhs, int __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned int __rhs); \ + _Tp operator _Op(_Tp __lhs, long __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned long __rhs); \ + _Tp operator _Op(_Tp __lhs, long long __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned long long __rhs); \ + _Tp operator _Op(int __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned int __lhs, _Tp __rhs); \ + _Tp operator _Op(long __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned long __lhs, _Tp __rhs); \ + _Tp operator _Op(long long __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned long long __lhs, _Tp __rhs); + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal128) + +#undef _DECLARE_DECIMAL_BINARY_OP_WITH_DEC +#undef _DECLARE_DECIMAL_BINARY_OP_WITH_INT + + // 3.2.9 Comparison operators. +#define _DECLARE_DECIMAL_COMPARISON(_Op, _Tp) \ + bool operator _Op(_Tp __lhs, decimal32 __rhs); \ + bool operator _Op(_Tp __lhs, decimal64 __rhs); \ + bool operator _Op(_Tp __lhs, decimal128 __rhs); \ + bool operator _Op(_Tp __lhs, int __rhs); \ + bool operator _Op(_Tp __lhs, unsigned int __rhs); \ + bool operator _Op(_Tp __lhs, long __rhs); \ + bool operator _Op(_Tp __lhs, unsigned long __rhs); \ + bool operator _Op(_Tp __lhs, long long __rhs); \ + bool operator _Op(_Tp __lhs, unsigned long long __rhs); \ + bool operator _Op(int __lhs, _Tp __rhs); \ + bool operator _Op(unsigned int __lhs, _Tp __rhs); \ + bool operator _Op(long __lhs, _Tp __rhs); \ + bool operator _Op(unsigned long __lhs, _Tp __rhs); \ + bool operator _Op(long long __lhs, _Tp __rhs); \ + bool operator _Op(unsigned long long __lhs, _Tp __rhs); + + _DECLARE_DECIMAL_COMPARISON(==, decimal32) + _DECLARE_DECIMAL_COMPARISON(==, decimal64) + _DECLARE_DECIMAL_COMPARISON(==, decimal128) + + _DECLARE_DECIMAL_COMPARISON(!=, decimal32) + _DECLARE_DECIMAL_COMPARISON(!=, decimal64) + _DECLARE_DECIMAL_COMPARISON(!=, decimal128) + + _DECLARE_DECIMAL_COMPARISON(<, decimal32) + _DECLARE_DECIMAL_COMPARISON(<, decimal64) + _DECLARE_DECIMAL_COMPARISON(<, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>=, decimal32) + _DECLARE_DECIMAL_COMPARISON(>=, decimal64) + _DECLARE_DECIMAL_COMPARISON(>=, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>, decimal32) + _DECLARE_DECIMAL_COMPARISON(>, decimal64) + _DECLARE_DECIMAL_COMPARISON(>, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>=, decimal32) + _DECLARE_DECIMAL_COMPARISON(>=, decimal64) + _DECLARE_DECIMAL_COMPARISON(>=, decimal128) + +#undef _DECLARE_DECIMAL_COMPARISON + + /// 3.2.2 Class decimal32. + class decimal32 + { + public: + typedef float __decfloat32 __attribute__((mode(SD))); + + // 3.2.2.2 Construct/copy/destroy. + decimal32() : __val(0.e-101DF) {} + + // 3.2.2.3 Conversion from floating-point type. + explicit decimal32(decimal64 __d64); + explicit decimal32(decimal128 __d128); + explicit decimal32(float __r) : __val(__r) {} + explicit decimal32(double __r) : __val(__r) {} + explicit decimal32(long double __r) : __val(__r) {} + + // 3.2.2.4 Conversion from integral type. + decimal32(int __z) : __val(__z) {} + decimal32(unsigned int __z) : __val(__z) {} + decimal32(long __z) : __val(__z) {} + decimal32(unsigned long __z) : __val(__z) {} + decimal32(long long __z) : __val(__z) {} + decimal32(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal32(__decfloat32 __z) : __val(__z) {} + +#if __cplusplus >= 201103L + // 3.2.2.5 Conversion to integral type. + // Note: explicit per n3407. + explicit operator long long() const { return (long long)__val; } +#endif + + // 3.2.2.6 Increment and decrement operators. + decimal32& operator++() + { + __val += 1; + return *this; + } + + decimal32 operator++(int) + { + decimal32 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal32& operator--() + { + __val -= 1; + return *this; + } + + decimal32 operator--(int) + { + decimal32 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.2.7 Compound assignment. +#define _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(_Op) \ + decimal32& operator _Op(decimal32 __rhs); \ + decimal32& operator _Op(decimal64 __rhs); \ + decimal32& operator _Op(decimal128 __rhs); \ + decimal32& operator _Op(int __rhs); \ + decimal32& operator _Op(unsigned int __rhs); \ + decimal32& operator _Op(long __rhs); \ + decimal32& operator _Op(unsigned long __rhs); \ + decimal32& operator _Op(long long __rhs); \ + decimal32& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT + + private: + __decfloat32 __val; + + public: + __decfloat32 __getval(void) { return __val; } + void __setval(__decfloat32 __x) { __val = __x; } + }; + + /// 3.2.3 Class decimal64. + class decimal64 + { + public: + typedef float __decfloat64 __attribute__((mode(DD))); + + // 3.2.3.2 Construct/copy/destroy. + decimal64() : __val(0.e-398dd) {} + + // 3.2.3.3 Conversion from floating-point type. + decimal64(decimal32 d32); + explicit decimal64(decimal128 d128); + explicit decimal64(float __r) : __val(__r) {} + explicit decimal64(double __r) : __val(__r) {} + explicit decimal64(long double __r) : __val(__r) {} + + // 3.2.3.4 Conversion from integral type. + decimal64(int __z) : __val(__z) {} + decimal64(unsigned int __z) : __val(__z) {} + decimal64(long __z) : __val(__z) {} + decimal64(unsigned long __z) : __val(__z) {} + decimal64(long long __z) : __val(__z) {} + decimal64(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal64(__decfloat64 __z) : __val(__z) {} + +#if __cplusplus >= 201103L + // 3.2.3.5 Conversion to integral type. + // Note: explicit per n3407. + explicit operator long long() const { return (long long)__val; } +#endif + + // 3.2.3.6 Increment and decrement operators. + decimal64& operator++() + { + __val += 1; + return *this; + } + + decimal64 operator++(int) + { + decimal64 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal64& operator--() + { + __val -= 1; + return *this; + } + + decimal64 operator--(int) + { + decimal64 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.3.7 Compound assignment. +#define _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(_Op) \ + decimal64& operator _Op(decimal32 __rhs); \ + decimal64& operator _Op(decimal64 __rhs); \ + decimal64& operator _Op(decimal128 __rhs); \ + decimal64& operator _Op(int __rhs); \ + decimal64& operator _Op(unsigned int __rhs); \ + decimal64& operator _Op(long __rhs); \ + decimal64& operator _Op(unsigned long __rhs); \ + decimal64& operator _Op(long long __rhs); \ + decimal64& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT + + private: + __decfloat64 __val; + + public: + __decfloat64 __getval(void) { return __val; } + void __setval(__decfloat64 __x) { __val = __x; } + }; + + /// 3.2.4 Class decimal128. + class decimal128 + { + public: + typedef float __decfloat128 __attribute__((mode(TD))); + + // 3.2.4.2 Construct/copy/destroy. + decimal128() : __val(0.e-6176DL) {} + + // 3.2.4.3 Conversion from floating-point type. + decimal128(decimal32 d32); + decimal128(decimal64 d64); + explicit decimal128(float __r) : __val(__r) {} + explicit decimal128(double __r) : __val(__r) {} + explicit decimal128(long double __r) : __val(__r) {} + + + // 3.2.4.4 Conversion from integral type. + decimal128(int __z) : __val(__z) {} + decimal128(unsigned int __z) : __val(__z) {} + decimal128(long __z) : __val(__z) {} + decimal128(unsigned long __z) : __val(__z) {} + decimal128(long long __z) : __val(__z) {} + decimal128(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal128(__decfloat128 __z) : __val(__z) {} + +#if __cplusplus >= 201103L + // 3.2.4.5 Conversion to integral type. + // Note: explicit per n3407. + explicit operator long long() const { return (long long)__val; } +#endif + + // 3.2.4.6 Increment and decrement operators. + decimal128& operator++() + { + __val += 1; + return *this; + } + + decimal128 operator++(int) + { + decimal128 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal128& operator--() + { + __val -= 1; + return *this; + } + + decimal128 operator--(int) + { + decimal128 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.4.7 Compound assignment. +#define _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(_Op) \ + decimal128& operator _Op(decimal32 __rhs); \ + decimal128& operator _Op(decimal64 __rhs); \ + decimal128& operator _Op(decimal128 __rhs); \ + decimal128& operator _Op(int __rhs); \ + decimal128& operator _Op(unsigned int __rhs); \ + decimal128& operator _Op(long __rhs); \ + decimal128& operator _Op(unsigned long __rhs); \ + decimal128& operator _Op(long long __rhs); \ + decimal128& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT + + private: + __decfloat128 __val; + + public: + __decfloat128 __getval(void) { return __val; } + void __setval(__decfloat128 __x) { __val = __x; } + }; + +#define _GLIBCXX_USE_DECIMAL_ 1 +} // namespace decimal + // @} group decimal + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#include + +#endif /* _GLIBCXX_DECIMAL */ diff --git a/resources/sources/avr-libstdcpp/include/decimal/decimal.h b/resources/sources/avr-libstdcpp/include/decimal/decimal.h new file mode 100644 index 000000000..50147e7e8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/decimal/decimal.h @@ -0,0 +1,469 @@ +// decimal classes -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. + +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file decimal/decimal.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{decimal} + */ + +// ISO/IEC TR 24733 +// Written by Janis Johnson + +#ifndef _GLIBCXX_DECIMAL_IMPL +#define _GLIBCXX_DECIMAL_IMPL 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace decimal +{ + // ISO/IEC TR 24733 3.2.[234].1 Construct/copy/destroy. + + inline decimal32::decimal32(decimal64 __r) : __val(__r.__getval()) {} + inline decimal32::decimal32(decimal128 __r) : __val(__r.__getval()) {} + inline decimal64::decimal64(decimal32 __r) : __val(__r.__getval()) {} + inline decimal64::decimal64(decimal128 __r) : __val(__r.__getval()) {} + inline decimal128::decimal128(decimal32 __r) : __val(__r.__getval()) {} + inline decimal128::decimal128(decimal64 __r) : __val(__r.__getval()) {} + + // ISO/IEC TR 24733 3.2.[234].6 Compound assignment. + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, _T2) \ + inline _T1& _T1::operator _Op1(_T2 __rhs) \ + { \ + __setval(__getval() _Op2 __rhs.__getval()); \ + return *this; \ + } + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, _T2) \ + inline _T1& _T1::operator _Op1(_T2 __rhs) \ + { \ + __setval(__getval() _Op2 __rhs); \ + return *this; \ + } + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(_Op1, _Op2, _T1) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal32) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal64) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal128) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, int) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned int) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, long) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned long)\ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, long long) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned long long) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal32) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal64) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal128) + +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS + + // Extension: Conversion to integral type. + + inline long long decimal32_to_long_long(decimal32 __d) + { return (long long)__d.__getval(); } + + inline long long decimal64_to_long_long(decimal64 __d) + { return (long long)__d.__getval(); } + + inline long long decimal128_to_long_long(decimal128 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal32 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal64 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal128 __d) + { return (long long)__d.__getval(); } + + // ISO/IEC TR 24733 3.2.5 Initialization from coefficient and exponent. + + static decimal32 make_decimal32(long long __coeff, int __exponent) + { + decimal32 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DF; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DF; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal32 make_decimal32(unsigned long long __coeff, int __exponent) + { + decimal32 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DF; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DF; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal64 make_decimal64(long long __coeff, int __exponent) + { + decimal64 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DD; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DD; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal64 make_decimal64(unsigned long long __coeff, int __exponent) + { + decimal64 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DD; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DD; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal128 make_decimal128(long long __coeff, int __exponent) + { + decimal128 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DL; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DL; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal128 make_decimal128(unsigned long long __coeff, int __exponent) + { + decimal128 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DL; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DL; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + // ISO/IEC TR 24733 3.2.6 Conversion to generic floating-point type. + + inline float decimal32_to_float(decimal32 __d) + { return (float)__d.__getval(); } + + inline float decimal64_to_float(decimal64 __d) + { return (float)__d.__getval(); } + + inline float decimal128_to_float(decimal128 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal32 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal64 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal128 __d) + { return (float)__d.__getval(); } + + inline double decimal32_to_double(decimal32 __d) + { return (double)__d.__getval(); } + + inline double decimal64_to_double(decimal64 __d) + { return (double)__d.__getval(); } + + inline double decimal128_to_double(decimal128 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal32 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal64 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal128 __d) + { return (double)__d.__getval(); } + + inline long double decimal32_to_long_double(decimal32 __d) + { return (long double)__d.__getval(); } + + inline long double decimal64_to_long_double(decimal64 __d) + { return (long double)__d.__getval(); } + + inline long double decimal128_to_long_double(decimal128 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal32 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal64 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal128 __d) + { return (long double)__d.__getval(); } + + // ISO/IEC TR 24733 3.2.7 Unary arithmetic operators. + +#define _DEFINE_DECIMAL_UNARY_OP(_Op, _Tp) \ + inline _Tp operator _Op(_Tp __rhs) \ + { \ + _Tp __tmp; \ + __tmp.__setval(_Op __rhs.__getval()); \ + return __tmp; \ + } + + _DEFINE_DECIMAL_UNARY_OP(+, decimal32) + _DEFINE_DECIMAL_UNARY_OP(+, decimal64) + _DEFINE_DECIMAL_UNARY_OP(+, decimal128) + _DEFINE_DECIMAL_UNARY_OP(-, decimal32) + _DEFINE_DECIMAL_UNARY_OP(-, decimal64) + _DEFINE_DECIMAL_UNARY_OP(-, decimal128) + +#undef _DEFINE_DECIMAL_UNARY_OP + + // ISO/IEC TR 24733 3.2.8 Binary arithmetic operators. + +#define _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(_Op, _T1, _T2, _T3) \ + inline _T1 operator _Op(_T2 __lhs, _T3 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_BOTH(_Op, _T1, _T2, _T3) \ + inline _T1 operator _Op(_T2 __lhs, _T3 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, _T2) \ + inline _T1 operator _Op(_T1 __lhs, _T2 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, _T2) \ + inline _T1 operator _Op(_T2 __lhs, _T1 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_WITH_INT(_Op, _T1) \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, int); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned int); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, long long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned long long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, int); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned int); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, long long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned long long); \ + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal128) + +#undef _DEFINE_DECIMAL_BINARY_OP_WITH_DEC +#undef _DEFINE_DECIMAL_BINARY_OP_BOTH +#undef _DEFINE_DECIMAL_BINARY_OP_LHS +#undef _DEFINE_DECIMAL_BINARY_OP_RHS +#undef _DEFINE_DECIMAL_BINARY_OP_WITH_INT + + // ISO/IEC TR 24733 3.2.9 Comparison operators. + +#define _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs.__getval() _Op __rhs.__getval(); } + +#define _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs.__getval() _Op __rhs; } + +#define _DEFINE_DECIMAL_COMPARISON_RHS(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs _Op __rhs.__getval(); } + +#define _DEFINE_DECIMAL_COMPARISONS(_Op, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal32) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal64) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal128) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, int) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned int) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, long long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned long long) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, int, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned int, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, long long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned long long, _Tp) + + _DEFINE_DECIMAL_COMPARISONS(==, decimal32) + _DEFINE_DECIMAL_COMPARISONS(==, decimal64) + _DEFINE_DECIMAL_COMPARISONS(==, decimal128) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal128) + _DEFINE_DECIMAL_COMPARISONS(<, decimal32) + _DEFINE_DECIMAL_COMPARISONS(<, decimal64) + _DEFINE_DECIMAL_COMPARISONS(<, decimal128) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal128) + _DEFINE_DECIMAL_COMPARISONS(>, decimal32) + _DEFINE_DECIMAL_COMPARISONS(>, decimal64) + _DEFINE_DECIMAL_COMPARISONS(>, decimal128) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal128) + +#undef _DEFINE_DECIMAL_COMPARISON_BOTH +#undef _DEFINE_DECIMAL_COMPARISON_LHS +#undef _DEFINE_DECIMAL_COMPARISON_RHS +#undef _DEFINE_DECIMAL_COMPARISONS +} // namespace decimal + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _GLIBCXX_DECIMAL_IMPL */ diff --git a/resources/sources/avr-libstdcpp/include/deque b/resources/sources/avr-libstdcpp/include/deque new file mode 100644 index 000000000..07e2c69d0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/deque @@ -0,0 +1,119 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/deque + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_DEQUE +#define _GLIBCXX_DEQUE 1 + +#pragma GCC system_header + +#include +#if __cplusplus > 201703L +# include // For remove and remove_if +#endif // C++20 +#include +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template + using deque = std::deque<_Tp, polymorphic_allocator<_Tp>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_erase_if 202002L + + template + inline typename deque<_Tp, _Alloc>::size_type + erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred) + { + const auto __osz = __cont.size(); + __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred), + __cont.end()); + return __osz - __cont.size(); + } + + template + inline typename deque<_Tp, _Alloc>::size_type + erase(deque<_Tp, _Alloc>& __cont, const _Up& __value) + { + const auto __osz = __cont.size(); + __cont.erase(std::remove(__cont.begin(), __cont.end(), __value), + __cont.end()); + return __osz - __cont.size(); + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_DEQUE */ diff --git a/resources/sources/avr-libstdcpp/include/ext/algorithm b/resources/sources/avr-libstdcpp/include/ext/algorithm new file mode 100644 index 000000000..e7106fde4 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/algorithm @@ -0,0 +1,596 @@ +// Algorithm extensions -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/algorithm + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_ALGORITHM +#define _EXT_ALGORITHM 1 + +#pragma GCC system_header + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + //-------------------------------------------------- + // copy_n (not part of the C++ standard) + + template + std::pair<_InputIterator, _OutputIterator> + __copy_n(_InputIterator __first, _Size __count, + _OutputIterator __result, + std::input_iterator_tag) + { + for ( ; __count > 0; --__count) + { + *__result = *__first; + ++__first; + ++__result; + } + return std::pair<_InputIterator, _OutputIterator>(__first, __result); + } + + template + inline std::pair<_RAIterator, _OutputIterator> + __copy_n(_RAIterator __first, _Size __count, + _OutputIterator __result, + std::random_access_iterator_tag) + { + _RAIterator __last = __first + __count; + return std::pair<_RAIterator, _OutputIterator>(__last, std::copy(__first, + __last, + __result)); + } + + /** + * @brief Copies the range [first,first+count) into [result,result+count). + * @param __first An input iterator. + * @param __count The number of elements to copy. + * @param __result An output iterator. + * @return A std::pair composed of first+count and result+count. + * + * This is an SGI extension. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + * @ingroup SGIextensions + */ + template + inline std::pair<_InputIterator, _OutputIterator> + copy_n(_InputIterator __first, _Size __count, _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename std::iterator_traits<_InputIterator>::value_type>) + + return __gnu_cxx::__copy_n(__first, __count, __result, + std::__iterator_category(__first)); + } + + template + int + __lexicographical_compare_3way(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (*__first1 < *__first2) + return -1; + if (*__first2 < *__first1) + return 1; + ++__first1; + ++__first2; + } + if (__first2 == __last2) + return !(__first1 == __last1); + else + return -1; + } + + inline int + __lexicographical_compare_3way(const unsigned char* __first1, + const unsigned char* __last1, + const unsigned char* __first2, + const unsigned char* __last2) + { + const std::ptrdiff_t __len1 = __last1 - __first1; + const std::ptrdiff_t __len2 = __last2 - __first2; + const int __result = __builtin_memcmp(__first1, __first2, + (std::min)(__len1, __len2)); + return __result != 0 ? __result + : (__len1 == __len2 ? 0 : (__len1 < __len2 ? -1 : 1)); + } + + inline int + __lexicographical_compare_3way(const char* __first1, const char* __last1, + const char* __first2, const char* __last2) + { +#if CHAR_MAX == SCHAR_MAX + return __lexicographical_compare_3way((const signed char*) __first1, + (const signed char*) __last1, + (const signed char*) __first2, + (const signed char*) __last2); +#else + return __lexicographical_compare_3way((const unsigned char*) __first1, + (const unsigned char*) __last1, + (const unsigned char*) __first2, + (const unsigned char*) __last2); +#endif + } + + /** + * @brief @c memcmp on steroids. + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return An int, as with @c memcmp. + * + * The return value will be less than zero if the first range is + * lexigraphically less than the second, greater than zero + * if the second range is lexigraphically less than the + * first, and zero otherwise. + * This is an SGI extension. + * @ingroup SGIextensions + */ + template + int + lexicographical_compare_3way(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename std::iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename std::iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return __lexicographical_compare_3way(__first1, __last1, __first2, + __last2); + } + + // count and count_if: this version, whose return type is void, was present + // in the HP STL, and is retained as an extension for backward compatibility. + template + void + count(_InputIterator __first, _InputIterator __last, + const _Tp& __value, + _Size& __n) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename std::iterator_traits<_InputIterator>::value_type >) + __glibcxx_function_requires(_EqualityComparableConcept<_Tp>) + __glibcxx_requires_valid_range(__first, __last); + + for ( ; __first != __last; ++__first) + if (*__first == __value) + ++__n; + } + + template + void + count_if(_InputIterator __first, _InputIterator __last, + _Predicate __pred, + _Size& __n) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename std::iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for ( ; __first != __last; ++__first) + if (__pred(*__first)) + ++__n; + } + + // random_sample and random_sample_n (extensions, not part of the standard). + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + _OutputIterator + random_sample_n(_ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __out, const _Distance __n) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename std::iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + _Distance __remaining = std::distance(__first, __last); + _Distance __m = (std::min)(__n, __remaining); + + while (__m > 0) + { + if ((std::rand() % __remaining) < __m) + { + *__out = *__first; + ++__out; + --__m; + } + --__remaining; + ++__first; + } + return __out; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + _OutputIterator + random_sample_n(_ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __out, const _Distance __n, + _RandomNumberGenerator& __rand) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename std::iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_function_requires(_UnaryFunctionConcept< + _RandomNumberGenerator, _Distance, _Distance>) + __glibcxx_requires_valid_range(__first, __last); + + _Distance __remaining = std::distance(__first, __last); + _Distance __m = (std::min)(__n, __remaining); + + while (__m > 0) + { + if (__rand(__remaining) < __m) + { + *__out = *__first; + ++__out; + --__m; + } + --__remaining; + ++__first; + } + return __out; + } + + template + _RandomAccessIterator + __random_sample(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __out, + const _Distance __n) + { + _Distance __m = 0; + _Distance __t = __n; + for ( ; __first != __last && __m < __n; ++__m, ++__first) + __out[__m] = *__first; + + while (__first != __last) + { + ++__t; + _Distance __M = std::rand() % (__t); + if (__M < __n) + __out[__M] = *__first; + ++__first; + } + return __out + __m; + } + + template + _RandomAccessIterator + __random_sample(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __out, + _RandomNumberGenerator& __rand, + const _Distance __n) + { + // concept requirements + __glibcxx_function_requires(_UnaryFunctionConcept< + _RandomNumberGenerator, _Distance, _Distance>) + + _Distance __m = 0; + _Distance __t = __n; + for ( ; __first != __last && __m < __n; ++__m, ++__first) + __out[__m] = *__first; + + while (__first != __last) + { + ++__t; + _Distance __M = __rand(__t); + if (__M < __n) + __out[__M] = *__first; + ++__first; + } + return __out + __m; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline _RandomAccessIterator + random_sample(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __out_first, + _RandomAccessIterator __out_last) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_valid_range(__out_first, __out_last); + + return __random_sample(__first, __last, + __out_first, __out_last - __out_first); + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline _RandomAccessIterator + random_sample(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __out_first, + _RandomAccessIterator __out_last, + _RandomNumberGenerator& __rand) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_valid_range(__out_first, __out_last); + + return __random_sample(__first, __last, + __out_first, __rand, + __out_last - __out_first); + } + +#if __cplusplus >= 201103L + using std::is_heap; +#else + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename std::iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__is_heap(__first, __last - __first); + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _StrictWeakOrdering __comp) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering, + typename std::iterator_traits<_RandomAccessIterator>::value_type, + typename std::iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__is_heap(__first, __comp, __last - __first); + } +#endif + +#if __cplusplus >= 201103L + using std::is_sorted; +#else + // is_sorted, a predicated testing whether a range is sorted in + // nondescending order. This is an extension, not part of the C++ + // standard. + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename std::iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, ++__next) + if (*__next < *__first) + return false; + return true; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last, + _StrictWeakOrdering __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering, + typename std::iterator_traits<_ForwardIterator>::value_type, + typename std::iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, ++__next) + if (__comp(*__next, *__first)) + return false; + return true; + } +#endif // C++11 + + /** + * @brief Find the median of three values. + * @param __a A value. + * @param __b A value. + * @param __c A value. + * @return One of @p a, @p b or @p c. + * + * If @c {l,m,n} is some convolution of @p {a,b,c} such that @c l<=m<=n + * then the value returned will be @c m. + * This is an SGI extension. + * @ingroup SGIextensions + */ + template + const _Tp& + __median(const _Tp& __a, const _Tp& __b, const _Tp& __c) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + if (__a < __b) + if (__b < __c) + return __b; + else if (__a < __c) + return __c; + else + return __a; + else if (__a < __c) + return __a; + else if (__b < __c) + return __c; + else + return __b; + } + + /** + * @brief Find the median of three values using a predicate for comparison. + * @param __a A value. + * @param __b A value. + * @param __c A value. + * @param __comp A binary predicate. + * @return One of @p a, @p b or @p c. + * + * If @c {l,m,n} is some convolution of @p {a,b,c} such that @p comp(l,m) + * and @p comp(m,n) are both true then the value returned will be @c m. + * This is an SGI extension. + * @ingroup SGIextensions + */ + template + const _Tp& + __median(const _Tp& __a, const _Tp& __b, const _Tp& __c, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_BinaryFunctionConcept<_Compare, bool, + _Tp, _Tp>) + if (__comp(__a, __b)) + if (__comp(__b, __c)) + return __b; + else if (__comp(__a, __c)) + return __c; + else + return __a; + else if (__comp(__a, __c)) + return __a; + else if (__comp(__b, __c)) + return __c; + else + return __b; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _EXT_ALGORITHM */ diff --git a/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h b/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h new file mode 100644 index 000000000..667a9c084 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h @@ -0,0 +1,125 @@ +// Aligned memory buffer -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/aligned_buffer.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _ALIGNED_BUFFER_H +#define _ALIGNED_BUFFER_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L +# include +#else +# include +#endif + +namespace __gnu_cxx +{ + // A utility type containing a POD object that can hold an object of type + // _Tp initialized via placement new or allocator_traits::construct. + // Intended for use as a data member subobject, use __aligned_buffer for + // complete objects. + template + struct __aligned_membuf + { + // Target macro ADJUST_FIELD_ALIGN can produce different alignment for + // types when used as class members. __aligned_membuf is intended + // for use as a class member, so align the buffer as for a class member. + // Since GCC 8 we could just use alignof(_Tp) instead, but older + // versions of non-GNU compilers might still need this trick. + struct _Tp2 { _Tp _M_t; }; + + alignas(__alignof__(_Tp2::_M_t)) unsigned char _M_storage[sizeof(_Tp)]; + + __aligned_membuf() = default; + + // Can be used to avoid value-initialization zeroing _M_storage. + __aligned_membuf(std::nullptr_t) { } + + void* + _M_addr() noexcept + { return static_cast(&_M_storage); } + + const void* + _M_addr() const noexcept + { return static_cast(&_M_storage); } + + _Tp* + _M_ptr() noexcept + { return static_cast<_Tp*>(_M_addr()); } + + const _Tp* + _M_ptr() const noexcept + { return static_cast(_M_addr()); } + }; + +#if _GLIBCXX_INLINE_VERSION + template + using __aligned_buffer = __aligned_membuf<_Tp>; +#else + // Similar to __aligned_membuf but aligned for complete objects, not members. + // This type is used in , , + // and , but ideally they would use __aligned_membuf + // instead, as it has smaller size for some types on some targets. + // This type is still used to avoid an ABI change. + template + struct __aligned_buffer + : std::aligned_storage + { + typename + std::aligned_storage::type _M_storage; + + __aligned_buffer() = default; + + // Can be used to avoid value-initialization + __aligned_buffer(std::nullptr_t) { } + + void* + _M_addr() noexcept + { + return static_cast(&_M_storage); + } + + const void* + _M_addr() const noexcept + { + return static_cast(&_M_storage); + } + + _Tp* + _M_ptr() noexcept + { return static_cast<_Tp*>(_M_addr()); } + + const _Tp* + _M_ptr() const noexcept + { return static_cast(_M_addr()); } + }; +#endif + +} // namespace + +#endif /* _ALIGNED_BUFFER_H */ diff --git a/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h b/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h new file mode 100644 index 000000000..3bbef9ec5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h @@ -0,0 +1,171 @@ +// Allocator traits -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/alloc_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_ALLOC_TRAITS_H +#define _EXT_ALLOC_TRAITS_H 1 + +#pragma GCC system_header + +# include +#if __cplusplus < 201103L +# include // for __alloc_swap +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** + * @brief Uniform interface to C++98 and C++11 allocators. + * @ingroup allocators +*/ +template + struct __alloc_traits +#if __cplusplus >= 201103L + : std::allocator_traits<_Alloc> +#endif + { + typedef _Alloc allocator_type; +#if __cplusplus >= 201103L + typedef std::allocator_traits<_Alloc> _Base_type; + typedef typename _Base_type::value_type value_type; + typedef typename _Base_type::pointer pointer; + typedef typename _Base_type::const_pointer const_pointer; + typedef typename _Base_type::size_type size_type; + typedef typename _Base_type::difference_type difference_type; + // C++11 allocators do not define reference or const_reference + typedef value_type& reference; + typedef const value_type& const_reference; + using _Base_type::allocate; + using _Base_type::deallocate; + using _Base_type::construct; + using _Base_type::destroy; + using _Base_type::max_size; + + private: + template + using __is_custom_pointer + = std::__and_, + std::__not_>>; + + public: + // overload construct for non-standard pointer types + template + static _GLIBCXX14_CONSTEXPR + std::__enable_if_t<__is_custom_pointer<_Ptr>::value> + construct(_Alloc& __a, _Ptr __p, _Args&&... __args) + noexcept(noexcept(_Base_type::construct(__a, std::__to_address(__p), + std::forward<_Args>(__args)...))) + { + _Base_type::construct(__a, std::__to_address(__p), + std::forward<_Args>(__args)...); + } + + // overload destroy for non-standard pointer types + template + static _GLIBCXX14_CONSTEXPR + std::__enable_if_t<__is_custom_pointer<_Ptr>::value> + destroy(_Alloc& __a, _Ptr __p) + noexcept(noexcept(_Base_type::destroy(__a, std::__to_address(__p)))) + { _Base_type::destroy(__a, std::__to_address(__p)); } + + static constexpr _Alloc _S_select_on_copy(const _Alloc& __a) + { return _Base_type::select_on_container_copy_construction(__a); } + + static _GLIBCXX14_CONSTEXPR void _S_on_swap(_Alloc& __a, _Alloc& __b) + { std::__alloc_on_swap(__a, __b); } + + static constexpr bool _S_propagate_on_copy_assign() + { return _Base_type::propagate_on_container_copy_assignment::value; } + + static constexpr bool _S_propagate_on_move_assign() + { return _Base_type::propagate_on_container_move_assignment::value; } + + static constexpr bool _S_propagate_on_swap() + { return _Base_type::propagate_on_container_swap::value; } + + static constexpr bool _S_always_equal() + { return _Base_type::is_always_equal::value; } + + static constexpr bool _S_nothrow_move() + { return _S_propagate_on_move_assign() || _S_always_equal(); } + + template + struct rebind + { typedef typename _Base_type::template rebind_alloc<_Tp> other; }; +#else // ! C++11 + + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef typename _Alloc::value_type value_type; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + typedef typename _Alloc::size_type size_type; + typedef typename _Alloc::difference_type difference_type; + + _GLIBCXX_NODISCARD static pointer + allocate(_Alloc& __a, size_type __n) + { return __a.allocate(__n); } + + template + _GLIBCXX_NODISCARD static pointer + allocate(_Alloc& __a, size_type __n, _Hint __hint) + { return __a.allocate(__n, __hint); } + + static void deallocate(_Alloc& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + template + static void construct(_Alloc& __a, pointer __p, const _Tp& __arg) + { __a.construct(__p, __arg); } + + static void destroy(_Alloc& __a, pointer __p) + { __a.destroy(__p); } + + static size_type max_size(const _Alloc& __a) + { return __a.max_size(); } + + static const _Alloc& _S_select_on_copy(const _Alloc& __a) { return __a; } + + static void _S_on_swap(_Alloc& __a, _Alloc& __b) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 431. Swapping containers with unequal allocators. + std::__alloc_swap<_Alloc>::_S_do_it(__a, __b); + } + + template + struct rebind + { typedef typename _Alloc::template rebind<_Tp>::other other; }; +#endif // C++11 + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace __gnu_cxx + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/atomicity.h b/resources/sources/avr-libstdcpp/include/ext/atomicity.h new file mode 100644 index 000000000..581e0c92a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/atomicity.h @@ -0,0 +1,116 @@ +// Support for atomic operations -*- C++ -*- + +// Copyright (C) 2004-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/atomicity.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_ATOMICITY_H +#define _GLIBCXX_ATOMICITY_H 1 + +#pragma GCC system_header + +#include + +typedef int _Atomic_word; + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Functions for portable atomic access. + // To abstract locking primitives across all thread policies, use: + // __exchange_and_add_dispatch + // __atomic_add_dispatch +#ifdef _GLIBCXX_ATOMIC_BUILTINS + inline _Atomic_word + __attribute__((__always_inline__)) + __exchange_and_add(volatile _Atomic_word* __mem, int __val) + { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } + + inline void + __attribute__((__always_inline__)) + __atomic_add(volatile _Atomic_word* __mem, int __val) + { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } +#else + _Atomic_word + __exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; + + void + __atomic_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; +#endif + + inline _Atomic_word + __attribute__((__always_inline__)) + __exchange_and_add_single(_Atomic_word* __mem, int __val) + { + _Atomic_word __result = *__mem; + *__mem += __val; + return __result; + } + + inline void + __attribute__((__always_inline__)) + __atomic_add_single(_Atomic_word* __mem, int __val) + { *__mem += __val; } + + inline _Atomic_word + __attribute__ ((__always_inline__)) + __exchange_and_add_dispatch(_Atomic_word* __mem, int __val) + { +#ifdef __GTHREADS + if (__gthread_active_p()) + return __exchange_and_add(__mem, __val); +#endif + return __exchange_and_add_single(__mem, __val); + } + + inline void + __attribute__ ((__always_inline__)) + __atomic_add_dispatch(_Atomic_word* __mem, int __val) + { +#ifdef __GTHREADS + if (__gthread_active_p()) + { + __atomic_add(__mem, __val); + return; + } +#endif + __atomic_add_single(__mem, __val); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +// Even if the CPU doesn't need a memory barrier, we need to ensure +// that the compiler doesn't reorder memory accesses across the +// barriers. +#ifndef _GLIBCXX_READ_MEM_BARRIER +#define _GLIBCXX_READ_MEM_BARRIER __atomic_thread_fence (__ATOMIC_ACQUIRE) +#endif +#ifndef _GLIBCXX_WRITE_MEM_BARRIER +#define _GLIBCXX_WRITE_MEM_BARRIER __atomic_thread_fence (__ATOMIC_RELEASE) +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/cmath b/resources/sources/avr-libstdcpp/include/ext/cmath new file mode 100644 index 000000000..09c6e44b8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/cmath @@ -0,0 +1,152 @@ +// Math extensions -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/cmath + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_CMATH +#define _EXT_CMATH 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // A class for math constants. + template + struct __math_constants + { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + + // Constant @f$ \pi @f$. + static constexpr _RealType __pi = 3.1415926535897932384626433832795029L; + // Constant @f$ \pi / 2 @f$. + static constexpr _RealType __pi_half = 1.5707963267948966192313216916397514L; + // Constant @f$ \pi / 3 @f$. + static constexpr _RealType __pi_third = 1.0471975511965977461542144610931676L; + // Constant @f$ \pi / 4 @f$. + static constexpr _RealType __pi_quarter = 0.7853981633974483096156608458198757L; + // Constant @f$ \sqrt(\pi / 2) @f$. + static constexpr _RealType __root_pi_div_2 = 1.2533141373155002512078826424055226L; + // Constant @f$ 1 / \pi @f$. + static constexpr _RealType __one_div_pi = 0.3183098861837906715377675267450287L; + // Constant @f$ 2 / \pi @f$. + static constexpr _RealType __two_div_pi = 0.6366197723675813430755350534900574L; + // Constant @f$ 2 / \sqrt(\pi) @f$. + static constexpr _RealType __two_div_root_pi = 1.1283791670955125738961589031215452L; + + // Constant Euler's number @f$ e @f$. + static constexpr _RealType __e = 2.7182818284590452353602874713526625L; + // Constant @f$ 1 / e @f$. + static constexpr _RealType __one_div_e = 0.36787944117144232159552377016146087L; + // Constant @f$ \log_2(e) @f$. + static constexpr _RealType __log2_e = 1.4426950408889634073599246810018921L; + // Constant @f$ \log_10(e) @f$. + static constexpr _RealType __log10_e = 0.4342944819032518276511289189166051L; + // Constant @f$ \ln(2) @f$. + static constexpr _RealType __ln_2 = 0.6931471805599453094172321214581766L; + // Constant @f$ \ln(3) @f$. + static constexpr _RealType __ln_3 = 1.0986122886681096913952452369225257L; + // Constant @f$ \ln(10) @f$. + static constexpr _RealType __ln_10 = 2.3025850929940456840179914546843642L; + + // Constant Euler-Mascheroni @f$ \gamma_E @f$. + static constexpr _RealType __gamma_e = 0.5772156649015328606065120900824024L; + // Constant Golden Ratio @f$ \phi @f$. + static constexpr _RealType __phi = 1.6180339887498948482045868343656381L; + + // Constant @f$ \sqrt(2) @f$. + static constexpr _RealType __root_2 = 1.4142135623730950488016887242096981L; + // Constant @f$ \sqrt(3) @f$. + static constexpr _RealType __root_3 = 1.7320508075688772935274463415058724L; + // Constant @f$ \sqrt(5) @f$. + static constexpr _RealType __root_5 = 2.2360679774997896964091736687312762L; + // Constant @f$ \sqrt(7) @f$. + static constexpr _RealType __root_7 = 2.6457513110645905905016157536392604L; + // Constant @f$ 1 / \sqrt(2) @f$. + static constexpr _RealType __one_div_root_2 = 0.7071067811865475244008443621048490L; + }; + + // And the template definitions for the constants. + template + constexpr _RealType __math_constants<_RealType>::__pi; + template + constexpr _RealType __math_constants<_RealType>::__pi_half; + template + constexpr _RealType __math_constants<_RealType>::__pi_third; + template + constexpr _RealType __math_constants<_RealType>::__pi_quarter; + template + constexpr _RealType __math_constants<_RealType>::__root_pi_div_2; + template + constexpr _RealType __math_constants<_RealType>::__one_div_pi; + template + constexpr _RealType __math_constants<_RealType>::__two_div_pi; + template + constexpr _RealType __math_constants<_RealType>::__two_div_root_pi; + template + constexpr _RealType __math_constants<_RealType>::__e; + template + constexpr _RealType __math_constants<_RealType>::__one_div_e; + template + constexpr _RealType __math_constants<_RealType>::__log2_e; + template + constexpr _RealType __math_constants<_RealType>::__log10_e; + template + constexpr _RealType __math_constants<_RealType>::__ln_2; + template + constexpr _RealType __math_constants<_RealType>::__ln_3; + template + constexpr _RealType __math_constants<_RealType>::__ln_10; + template + constexpr _RealType __math_constants<_RealType>::__gamma_e; + template + constexpr _RealType __math_constants<_RealType>::__phi; + template + constexpr _RealType __math_constants<_RealType>::__root_2; + template + constexpr _RealType __math_constants<_RealType>::__root_3; + template + constexpr _RealType __math_constants<_RealType>::__root_5; + template + constexpr _RealType __math_constants<_RealType>::__root_7; + template + constexpr _RealType __math_constants<_RealType>::__one_div_root_2; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace __gnu_cxx + +#endif // C++11 + +#endif // _EXT_CMATH diff --git a/resources/sources/avr-libstdcpp/include/ext/functional b/resources/sources/avr-libstdcpp/include/ext/functional new file mode 100644 index 000000000..4f50a6003 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/functional @@ -0,0 +1,422 @@ +// Functional extensions -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/functional + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_FUNCTIONAL +#define _EXT_FUNCTIONAL 1 + +#pragma GCC system_header + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** The @c identity_element functions are not part of the C++ + * standard; SGI provided them as an extension. Its argument is an + * operation, and its return value is the identity element for that + * operation. It is overloaded for addition and multiplication, + * and you can overload it for your own nefarious operations. + * + * @addtogroup SGIextensions + * @{ + */ + /// An \link SGIextensions SGI extension \endlink. + template + inline _Tp + identity_element(std::plus<_Tp>) + { return _Tp(0); } + + /// An \link SGIextensions SGI extension \endlink. + template + inline _Tp + identity_element(std::multiplies<_Tp>) + { return _Tp(1); } + /** @} */ + + /** As an extension to the binders, SGI provided composition functors and + * wrapper functions to aid in their creation. The @c unary_compose + * functor is constructed from two functions/functors, @c f and @c g. + * Calling @c operator() with a single argument @c x returns @c f(g(x)). + * The function @c compose1 takes the two functions and constructs a + * @c unary_compose variable for you. + * + * @c binary_compose is constructed from three functors, @c f, @c g1, + * and @c g2. Its @c operator() returns @c f(g1(x),g2(x)). The function + * compose2 takes f, g1, and g2, and constructs the @c binary_compose + * instance for you. For example, if @c f returns an int, then + * \code + * int answer = (compose2(f,g1,g2))(x); + * \endcode + * is equivalent to + * \code + * int temp1 = g1(x); + * int temp2 = g2(x); + * int answer = f(temp1,temp2); + * \endcode + * But the first form is more compact, and can be passed around as a + * functor to other algorithms. + * + * @addtogroup SGIextensions + * @{ + */ + /// An \link SGIextensions SGI extension \endlink. + template + class unary_compose + : public std::unary_function + { + protected: + _Operation1 _M_fn1; + _Operation2 _M_fn2; + + public: + unary_compose(const _Operation1& __x, const _Operation2& __y) + : _M_fn1(__x), _M_fn2(__y) {} + + typename _Operation1::result_type + operator()(const typename _Operation2::argument_type& __x) const + { return _M_fn1(_M_fn2(__x)); } + }; + + /// An \link SGIextensions SGI extension \endlink. + template + inline unary_compose<_Operation1, _Operation2> + compose1(const _Operation1& __fn1, const _Operation2& __fn2) + { return unary_compose<_Operation1,_Operation2>(__fn1, __fn2); } + + /// An \link SGIextensions SGI extension \endlink. + template + class binary_compose + : public std::unary_function + { + protected: + _Operation1 _M_fn1; + _Operation2 _M_fn2; + _Operation3 _M_fn3; + + public: + binary_compose(const _Operation1& __x, const _Operation2& __y, + const _Operation3& __z) + : _M_fn1(__x), _M_fn2(__y), _M_fn3(__z) { } + + typename _Operation1::result_type + operator()(const typename _Operation2::argument_type& __x) const + { return _M_fn1(_M_fn2(__x), _M_fn3(__x)); } + }; + + /// An \link SGIextensions SGI extension \endlink. + template + inline binary_compose<_Operation1, _Operation2, _Operation3> + compose2(const _Operation1& __fn1, const _Operation2& __fn2, + const _Operation3& __fn3) + { return binary_compose<_Operation1, _Operation2, _Operation3> + (__fn1, __fn2, __fn3); } + /** @} */ + + /** As an extension, SGI provided a functor called @c identity. When a + * functor is required but no operations are desired, this can be used as a + * pass-through. Its @c operator() returns its argument unchanged. + * + * @addtogroup SGIextensions + */ + template + struct identity + : public std::_Identity<_Tp> {}; + + /** @c select1st and @c select2nd are extensions provided by SGI. Their + * @c operator()s + * take a @c std::pair as an argument, and return either the first member + * or the second member, respectively. They can be used (especially with + * the composition functors) to @a strip data from a sequence before + * performing the remainder of an algorithm. + * + * @addtogroup SGIextensions + * @{ + */ + /// An \link SGIextensions SGI extension \endlink. + template + struct select1st + : public std::_Select1st<_Pair> {}; + + /// An \link SGIextensions SGI extension \endlink. + template + struct select2nd + : public std::_Select2nd<_Pair> {}; + + /** @} */ + + // extension documented next + template + struct _Project1st : public std::binary_function<_Arg1, _Arg2, _Arg1> + { + _Arg1 + operator()(const _Arg1& __x, const _Arg2&) const + { return __x; } + }; + + template + struct _Project2nd : public std::binary_function<_Arg1, _Arg2, _Arg2> + { + _Arg2 + operator()(const _Arg1&, const _Arg2& __y) const + { return __y; } + }; + + /** The @c operator() of the @c project1st functor takes two arbitrary + * arguments and returns the first one, while @c project2nd returns the + * second one. They are extensions provided by SGI. + * + * @addtogroup SGIextensions + * @{ + */ + + /// An \link SGIextensions SGI extension \endlink. + template + struct project1st : public _Project1st<_Arg1, _Arg2> {}; + + /// An \link SGIextensions SGI extension \endlink. + template + struct project2nd : public _Project2nd<_Arg1, _Arg2> {}; + /** @} */ + + // extension documented next + template + struct _Constant_void_fun + { + typedef _Result result_type; + result_type _M_val; + + _Constant_void_fun(const result_type& __v) : _M_val(__v) {} + + const result_type& + operator()() const + { return _M_val; } + }; + + template + struct _Constant_unary_fun + { + typedef _Argument argument_type; + typedef _Result result_type; + result_type _M_val; + + _Constant_unary_fun(const result_type& __v) : _M_val(__v) {} + + const result_type& + operator()(const _Argument&) const + { return _M_val; } + }; + + template + struct _Constant_binary_fun + { + typedef _Arg1 first_argument_type; + typedef _Arg2 second_argument_type; + typedef _Result result_type; + _Result _M_val; + + _Constant_binary_fun(const _Result& __v) : _M_val(__v) {} + + const result_type& + operator()(const _Arg1&, const _Arg2&) const + { return _M_val; } + }; + + /** These three functors are each constructed from a single arbitrary + * variable/value. Later, their @c operator()s completely ignore any + * arguments passed, and return the stored value. + * - @c constant_void_fun's @c operator() takes no arguments + * - @c constant_unary_fun's @c operator() takes one argument (ignored) + * - @c constant_binary_fun's @c operator() takes two arguments (ignored) + * + * The helper creator functions @c constant0, @c constant1, and + * @c constant2 each take a @a result argument and construct variables of + * the appropriate functor type. + * + * @addtogroup SGIextensions + * @{ + */ + /// An \link SGIextensions SGI extension \endlink. + template + struct constant_void_fun + : public _Constant_void_fun<_Result> + { + constant_void_fun(const _Result& __v) + : _Constant_void_fun<_Result>(__v) {} + }; + + /// An \link SGIextensions SGI extension \endlink. + template + struct constant_unary_fun : public _Constant_unary_fun<_Result, _Argument> + { + constant_unary_fun(const _Result& __v) + : _Constant_unary_fun<_Result, _Argument>(__v) {} + }; + + /// An \link SGIextensions SGI extension \endlink. + template + struct constant_binary_fun + : public _Constant_binary_fun<_Result, _Arg1, _Arg2> + { + constant_binary_fun(const _Result& __v) + : _Constant_binary_fun<_Result, _Arg1, _Arg2>(__v) {} + }; + + /// An \link SGIextensions SGI extension \endlink. + template + inline constant_void_fun<_Result> + constant0(const _Result& __val) + { return constant_void_fun<_Result>(__val); } + + /// An \link SGIextensions SGI extension \endlink. + template + inline constant_unary_fun<_Result, _Result> + constant1(const _Result& __val) + { return constant_unary_fun<_Result, _Result>(__val); } + + /// An \link SGIextensions SGI extension \endlink. + template + inline constant_binary_fun<_Result,_Result,_Result> + constant2(const _Result& __val) + { return constant_binary_fun<_Result, _Result, _Result>(__val); } + /** @} */ + + /** The @c subtractive_rng class is documented on + * SGI's site. + * Note that this code assumes that @c int is 32 bits. + * + * @ingroup SGIextensions + */ + class subtractive_rng + : public std::unary_function + { + private: + unsigned int _M_table[55]; + std::size_t _M_index1; + std::size_t _M_index2; + + public: + /// Returns a number less than the argument. + unsigned int + operator()(unsigned int __limit) + { + _M_index1 = (_M_index1 + 1) % 55; + _M_index2 = (_M_index2 + 1) % 55; + _M_table[_M_index1] = _M_table[_M_index1] - _M_table[_M_index2]; + return _M_table[_M_index1] % __limit; + } + + void + _M_initialize(unsigned int __seed) + { + unsigned int __k = 1; + _M_table[54] = __seed; + std::size_t __i; + for (__i = 0; __i < 54; __i++) + { + std::size_t __ii = (21 * (__i + 1) % 55) - 1; + _M_table[__ii] = __k; + __k = __seed - __k; + __seed = _M_table[__ii]; + } + for (int __loop = 0; __loop < 4; __loop++) + { + for (__i = 0; __i < 55; __i++) + _M_table[__i] = _M_table[__i] - _M_table[(1 + __i + 30) % 55]; + } + _M_index1 = 0; + _M_index2 = 31; + } + + /// Ctor allowing you to initialize the seed. + subtractive_rng(unsigned int __seed) + { _M_initialize(__seed); } + + /// Default ctor; initializes its state with some number you don't see. + subtractive_rng() + { _M_initialize(161803398u); } + }; + + // Mem_fun adaptor helper functions mem_fun1 and mem_fun1_ref, + // provided for backward compatibility, they are no longer part of + // the C++ standard. + + template + inline std::mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun1(_Ret (_Tp::*__f)(_Arg)) + { return std::mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + inline std::const_mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun1(_Ret (_Tp::*__f)(_Arg) const) + { return std::const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + inline std::mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun1_ref(_Ret (_Tp::*__f)(_Arg)) + { return std::mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + + template + inline std::const_mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun1_ref(_Ret (_Tp::*__f)(_Arg) const) + { return std::const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/ext/hash_map b/resources/sources/avr-libstdcpp/include/ext/hash_map new file mode 100644 index 000000000..93db70d56 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/hash_map @@ -0,0 +1,599 @@ +// Hashing map implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_map + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_MAP +#define _BACKWARD_HASH_MAP 1 + +#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH +#include +#endif + +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::equal_to; + using std::allocator; + using std::pair; + using std::_Select1st; + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> > + class hash_map + { + private: + typedef hashtable,_Key, _HashFn, + _Select1st >, + _EqualKey, _Alloc> _Ht; + + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_map() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_map(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_map(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_map(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_map& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&, + const hash_map<_K1, _T1, _HF, _EqK, _Al>&); + + iterator + begin() + { return _M_ht.begin(); } + + iterator + end() + { return _M_ht.end(); } + + const_iterator + begin() const + { return _M_ht.begin(); } + + const_iterator + end() const + { return _M_ht.end(); } + + pair + insert(const value_type& __obj) + { return _M_ht.insert_unique(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f, __l); } + + pair + insert_noresize(const value_type& __obj) + { return _M_ht.insert_unique_noresize(__obj); } + + iterator + find(const key_type& __key) + { return _M_ht.find(__key); } + + const_iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + _Tp& + operator[](const key_type& __key) + { return _M_ht.find_or_insert(value_type(__key, _Tp())).second; } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + {return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { return __hm1._M_ht == __hm2._M_ht; } + + template + inline bool + operator!=(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { return !(__hm1 == __hm2); } + + template + inline void + swap(hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { __hm1.swap(__hm2); } + + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Key>, + class _Alloc = allocator<_Tp> > + class hash_multimap + { + // concept requirements + __glibcxx_class_requires(_Key, _SGIAssignableConcept) + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFn, size_t, _Key, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Key, _Key, _BinaryPredicateConcept) + + private: + typedef hashtable, _Key, _HashFn, + _Select1st >, _EqualKey, _Alloc> + _Ht; + + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_multimap() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_multimap(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_multimap(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_multimap(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_multimap& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator==(const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&, + const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&); + + iterator + begin() + { return _M_ht.begin(); } + + iterator + end() + { return _M_ht.end(); } + + const_iterator + begin() const + { return _M_ht.begin(); } + + const_iterator + end() const + { return _M_ht.end(); } + + iterator + insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } + + iterator + insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator + find(const key_type& __key) + { return _M_ht.find(__key); } + + const_iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + { return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, + const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) + { return __hm1._M_ht == __hm2._M_ht; } + + template + inline bool + operator!=(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, + const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) + { return !(__hm1 == __hm2); } + + template + inline void + swap(hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { __hm1.swap(__hm2); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that it will work for hash_map + // and hash_multimap. + template + class insert_iterator<__gnu_cxx::hash_map<_Key, _Tp, _HashFn, + _EqKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc> + _Container; + _Container* container; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + + template + class insert_iterator<__gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, + _EqKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc> + _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/hash_set b/resources/sources/avr-libstdcpp/include/ext/hash_set new file mode 100644 index 000000000..0b99302af --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/hash_set @@ -0,0 +1,569 @@ +// Hashing set implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_set + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_SET +#define _BACKWARD_HASH_SET 1 + +#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH +#include +#endif + +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::equal_to; + using std::allocator; + using std::pair; + using std::_Identity; + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Value>, + class _Alloc = allocator<_Value> > + class hash_set + { + // concept requirements + __glibcxx_class_requires(_Value, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) + + typedef __alloc_traits<_Alloc> _Alloc_traits; + + private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_set() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_set(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_set(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_set(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_set& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator==(const hash_set<_Val, _HF, _EqK, _Al>&, + const hash_set<_Val, _HF, _EqK, _Al>&); + + iterator + begin() const + { return _M_ht.begin(); } + + iterator + end() const + { return _M_ht.end(); } + + pair + insert(const value_type& __obj) + { + pair __p = _M_ht.insert_unique(__obj); + return pair(__p.first, __p.second); + } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f, __l); } + + pair + insert_noresize(const value_type& __obj) + { + pair __p + = _M_ht.insert_unique_noresize(__obj); + return pair(__p.first, __p.second); + } + + iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + {return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return __hs1._M_ht == __hs2._M_ht; } + + template + inline bool + operator!=(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return !(__hs1 == __hs2); } + + template + inline void + swap(hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { __hs1.swap(__hs2); } + + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Value>, + class _Alloc = allocator<_Value> > + class hash_multiset + { + // concept requirements + __glibcxx_class_requires(_Value, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) + + private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_multiset() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_multiset(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_multiset(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_multiset(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_multiset& hs) + { _M_ht.swap(hs._M_ht); } + + template + friend bool + operator==(const hash_multiset<_Val, _HF, _EqK, _Al>&, + const hash_multiset<_Val, _HF, _EqK, _Al>&); + + iterator + begin() const + { return _M_ht.begin(); } + + iterator + end() const + { return _M_ht.end(); } + + iterator + insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } + + iterator + insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + { return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return __hs1._M_ht == __hs2._M_ht; } + + template + inline bool + operator!=(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return !(__hs1 == __hs2); } + + template + inline void + swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { __hs1.swap(__hs2); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that it will work for hash_set + // and hash_multiset. + template + class insert_iterator<__gnu_cxx::hash_set<_Value, _HashFcn, + _EqualKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc> + _Container; + _Container* container; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + + template + class insert_iterator<__gnu_cxx::hash_multiset<_Value, _HashFcn, + _EqualKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_multiset<_Value, _HashFcn, _EqualKey, _Alloc> + _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/iterator b/resources/sources/avr-libstdcpp/include/ext/iterator new file mode 100644 index 000000000..acfb353a9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/iterator @@ -0,0 +1,116 @@ +// HP/SGI iterator extensions -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/iterator + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_ITERATOR +#define _EXT_ITERATOR 1 + +#pragma GCC system_header + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // There are two signatures for distance. In addition to the one + // taking two iterators and returning a result, there is another + // taking two iterators and a reference-to-result variable, and + // returning nothing. The latter seems to be an SGI extension. + // -- pedwards + template + inline void + __distance(_InputIterator __first, _InputIterator __last, + _Distance& __n, std::input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + while (__first != __last) + { + ++__first; + ++__n; + } + } + + template + inline void + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Distance& __n, std::random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __n += __last - __first; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline void + distance(_InputIterator __first, _InputIterator __last, + _Distance& __n) + { + // concept requirements -- taken care of in __distance + __distance(__first, __last, __n, std::__iterator_category(__first)); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h b/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h new file mode 100644 index 000000000..366c766f2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h @@ -0,0 +1,199 @@ +// Allocator that wraps "C" malloc -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/malloc_allocator.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _MALLOC_ALLOCATOR_H +#define _MALLOC_ALLOCATOR_H 1 + +#include +#include +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief An allocator that uses malloc. + * @ingroup allocators + * + * This is precisely the allocator defined in the C++ Standard. + * - all allocation calls malloc + * - all deallocation calls free + */ + template + class malloc_allocator + { + public: + typedef _Tp value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; +#if __cplusplus <= 201703L + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + + template + struct rebind + { typedef malloc_allocator<_Tp1> other; }; +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. propagate_on_container_move_assignment + typedef std::true_type propagate_on_container_move_assignment; +#endif + + _GLIBCXX20_CONSTEXPR + malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } + + _GLIBCXX20_CONSTEXPR + malloc_allocator(const malloc_allocator&) _GLIBCXX_USE_NOEXCEPT { } + + template + _GLIBCXX20_CONSTEXPR + malloc_allocator(const malloc_allocator<_Tp1>&) + _GLIBCXX_USE_NOEXCEPT { } + +#if __cplusplus <= 201703L + ~malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } + + pointer + address(reference __x) const _GLIBCXX_NOEXCEPT + { return std::__addressof(__x); } + + const_pointer + address(const_reference __x) const _GLIBCXX_NOEXCEPT + { return std::__addressof(__x); } +#endif + + // NB: __n is permitted to be 0. The C++ standard says nothing + // about what the return value is when __n == 0. + _Tp* + allocate(size_type __n, const void* = 0) + { + if (__n > this->_M_max_size()) + std::__throw_bad_alloc(); + + _Tp* __ret = 0; +#if __cpp_aligned_new +#if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC + if (alignof(_Tp) > alignof(std::max_align_t)) + { + __ret = static_cast<_Tp*>(::aligned_alloc(alignof(_Tp), + __n * sizeof(_Tp))); + } +#else +# define _GLIBCXX_CHECK_MALLOC_RESULT +#endif +#endif + if (!__ret) + __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp))); + if (!__ret) + std::__throw_bad_alloc(); +#ifdef _GLIBCXX_CHECK_MALLOC_RESULT +#undef _GLIBCXX_CHECK_MALLOC_RESULT + if (reinterpret_cast(__ret) % alignof(_Tp)) + { + // Memory returned by malloc is not suitably aligned for _Tp. + deallocate(__ret, __n); + std::__throw_bad_alloc(); + } +#endif + return __ret; + } + + // __p is not permitted to be a null pointer. + void + deallocate(_Tp* __p, size_type) + { std::free(static_cast(__p)); } + +#if __cplusplus <= 201703L + size_type + max_size() const _GLIBCXX_USE_NOEXCEPT + { return _M_max_size(); } + +#if __cplusplus >= 201103L + template + void + construct(_Up* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } + + template + void + destroy(_Up* __p) + noexcept(std::is_nothrow_destructible<_Up>::value) + { __p->~_Up(); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_] allocator::construct + void + construct(pointer __p, const _Tp& __val) + { ::new((void *)__p) value_type(__val); } + + void + destroy(pointer __p) { __p->~_Tp(); } +#endif +#endif // ! C++20 + + template + friend _GLIBCXX20_CONSTEXPR bool + operator==(const malloc_allocator&, const malloc_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + template + friend _GLIBCXX20_CONSTEXPR bool + operator!=(const malloc_allocator&, const malloc_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return false; } +#endif + + private: + _GLIBCXX_CONSTEXPR size_type + _M_max_size() const _GLIBCXX_USE_NOEXCEPT + { +#if __PTRDIFF_MAX__ < __SIZE_MAX__ + return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); +#else + return std::size_t(-1) / sizeof(_Tp); +#endif + } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/memory b/resources/sources/avr-libstdcpp/include/ext/memory new file mode 100644 index 000000000..f590fd98c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/memory @@ -0,0 +1,200 @@ +// Memory extensions -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/memory + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_MEMORY +#define _EXT_MEMORY 1 + +#pragma GCC system_header + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::_Temporary_buffer; + + template + std::pair<_InputIter, _ForwardIter> + __uninitialized_copy_n(_InputIter __first, _Size __count, + _ForwardIter __result, std::input_iterator_tag) + { + _ForwardIter __cur = __result; + __try + { + for (; __count > 0 ; --__count, ++__first, ++__cur) + std::_Construct(&*__cur, *__first); + return std::pair<_InputIter, _ForwardIter>(__first, __cur); + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + inline std::pair<_RandomAccessIter, _ForwardIter> + __uninitialized_copy_n(_RandomAccessIter __first, _Size __count, + _ForwardIter __result, + std::random_access_iterator_tag) + { + _RandomAccessIter __last = __first + __count; + return (std::pair<_RandomAccessIter, _ForwardIter> + (__last, std::uninitialized_copy(__first, __last, __result))); + } + + template + inline std::pair<_InputIter, _ForwardIter> + __uninitialized_copy_n(_InputIter __first, _Size __count, + _ForwardIter __result) + { + return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result, + std::__iterator_category(__first)); + } + + /** + * @brief Copies the range [first,last) into result. + * @param __first An input iterator. + * @param __count Length + * @param __result An output iterator. + * @return __result + (__first + __count) + * @ingroup SGIextensions + * + * Like copy(), but does not require an initialized output range. + */ + template + inline std::pair<_InputIter, _ForwardIter> + uninitialized_copy_n(_InputIter __first, _Size __count, + _ForwardIter __result) + { + return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result, + std::__iterator_category(__first)); + } + + + // An alternative version of uninitialized_copy_n that constructs + // and destroys objects with a user-provided allocator. + template + std::pair<_InputIter, _ForwardIter> + __uninitialized_copy_n_a(_InputIter __first, _Size __count, + _ForwardIter __result, + _Allocator __alloc) + { + _ForwardIter __cur = __result; + __try + { + for (; __count > 0 ; --__count, ++__first, ++__cur) + __alloc.construct(&*__cur, *__first); + return std::pair<_InputIter, _ForwardIter>(__first, __cur); + } + __catch(...) + { + std::_Destroy(__result, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline std::pair<_InputIter, _ForwardIter> + __uninitialized_copy_n_a(_InputIter __first, _Size __count, + _ForwardIter __result, + std::allocator<_Tp>) + { + return __gnu_cxx::uninitialized_copy_n(__first, __count, __result); + } + + /** + * This class provides similar behavior and semantics of the standard + * functions get_temporary_buffer() and return_temporary_buffer(), but + * encapsulated in a type vaguely resembling a standard container. + * + * By default, a temporary_buffer stores space for objects of + * whatever type the Iter iterator points to. It is constructed from a + * typical [first,last) range, and provides the begin(), end(), size() + * functions, as well as requested_size(). For non-trivial types, copies + * of *first will be used to initialize the storage. + * + * @c malloc is used to obtain underlying storage. + * + * Like get_temporary_buffer(), not all the requested memory may be + * available. Ideally, the created buffer will be large enough to hold a + * copy of [first,last), but if size() is less than requested_size(), + * then this didn't happen. + * + * @ingroup SGIextensions + */ + template ::value_type > + struct temporary_buffer : public _Temporary_buffer<_ForwardIterator, _Tp> + { + /// Requests storage large enough to hold a copy of [first,last). + temporary_buffer(_ForwardIterator __first, _ForwardIterator __last) + : _Temporary_buffer<_ForwardIterator, _Tp>(__first, + std::distance(__first, __last)) + { } + + /// Destroys objects and frees storage. + ~temporary_buffer() { } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/ext/new_allocator.h b/resources/sources/avr-libstdcpp/include/ext/new_allocator.h new file mode 100644 index 000000000..131718b8b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/new_allocator.h @@ -0,0 +1,198 @@ +// Allocator that wraps operator new -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/new_allocator.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _NEW_ALLOCATOR_H +#define _NEW_ALLOCATOR_H 1 + +#include +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief An allocator that uses global new, as per [20.4]. + * @ingroup allocators + * + * This is precisely the allocator defined in the C++ Standard. + * - all allocation calls operator new + * - all deallocation calls operator delete + * + * @tparam _Tp Type of allocated object. + */ + template + class new_allocator + { + public: + typedef _Tp value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; +#if __cplusplus <= 201703L + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + + template + struct rebind + { typedef new_allocator<_Tp1> other; }; +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. propagate_on_container_move_assignment + typedef std::true_type propagate_on_container_move_assignment; +#endif + + _GLIBCXX20_CONSTEXPR + new_allocator() _GLIBCXX_USE_NOEXCEPT { } + + _GLIBCXX20_CONSTEXPR + new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { } + + template + _GLIBCXX20_CONSTEXPR + new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } + +#if __cplusplus <= 201703L + ~new_allocator() _GLIBCXX_USE_NOEXCEPT { } + + pointer + address(reference __x) const _GLIBCXX_NOEXCEPT + { return std::__addressof(__x); } + + const_pointer + address(const_reference __x) const _GLIBCXX_NOEXCEPT + { return std::__addressof(__x); } +#endif + + // NB: __n is permitted to be 0. The C++ standard says nothing + // about what the return value is when __n == 0. + _GLIBCXX_NODISCARD _Tp* + allocate(size_type __n, const void* = static_cast(0)) + { + if (__n > this->_M_max_size()) + std::__throw_bad_alloc(); + +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + std::align_val_t __al = std::align_val_t(alignof(_Tp)); + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al)); + } +#endif + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); + } + + // __p is not permitted to be a null pointer. + void + deallocate(_Tp* __p, size_type __t) + { +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + ::operator delete(__p, +# if __cpp_sized_deallocation + __t * sizeof(_Tp), +# endif + std::align_val_t(alignof(_Tp))); + return; + } +#endif + ::operator delete(__p +#if __cpp_sized_deallocation + , __t * sizeof(_Tp) +#endif + ); + } + +#if __cplusplus <= 201703L + size_type + max_size() const _GLIBCXX_USE_NOEXCEPT + { return _M_max_size(); } + +#if __cplusplus >= 201103L + template + void + construct(_Up* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } + + template + void + destroy(_Up* __p) + noexcept(std::is_nothrow_destructible<_Up>::value) + { __p->~_Up(); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_] allocator::construct + void + construct(pointer __p, const _Tp& __val) + { ::new((void *)__p) _Tp(__val); } + + void + destroy(pointer __p) { __p->~_Tp(); } +#endif +#endif // ! C++20 + + template + friend _GLIBCXX20_CONSTEXPR bool + operator==(const new_allocator&, const new_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + template + friend _GLIBCXX20_CONSTEXPR bool + operator!=(const new_allocator&, const new_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return false; } +#endif + + private: + _GLIBCXX_CONSTEXPR size_type + _M_max_size() const _GLIBCXX_USE_NOEXCEPT + { +#if __PTRDIFF_MAX__ < __SIZE_MAX__ + return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); +#else + return std::size_t(-1) / sizeof(_Tp); +#endif + } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/numeric b/resources/sources/avr-libstdcpp/include/ext/numeric new file mode 100644 index 000000000..f437ecafd --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/numeric @@ -0,0 +1,152 @@ +// Numeric extensions -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/numeric + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_NUMERIC +#define _EXT_NUMERIC 1 + +#pragma GCC system_header + +#include +#include + +#include // For identity_element + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Returns __x ** __n, where __n >= 0. _Note that "multiplication" + // is required to be associative, but not necessarily commutative. + template + _Tp + __power(_Tp __x, _Integer __n, _MonoidOperation __monoid_op) + { + if (__n == 0) + return identity_element(__monoid_op); + else + { + while ((__n & 1) == 0) + { + __n >>= 1; + __x = __monoid_op(__x, __x); + } + + _Tp __result = __x; + __n >>= 1; + while (__n != 0) + { + __x = __monoid_op(__x, __x); + if ((__n & 1) != 0) + __result = __monoid_op(__result, __x); + __n >>= 1; + } + return __result; + } + } + + template + inline _Tp + __power(_Tp __x, _Integer __n) + { return __power(__x, __n, std::multiplies<_Tp>()); } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + // Alias for the internal name __power. Note that power is an extension, + // not part of the C++ standard. + template + inline _Tp + power(_Tp __x, _Integer __n, _MonoidOperation __monoid_op) + { return __power(__x, __n, __monoid_op); } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline _Tp + power(_Tp __x, _Integer __n) + { return __power(__x, __n); } + +#if __cplusplus >= 201103L + using std::iota; +#else + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + // iota is not part of the standard until C++11. It is an extension. + template + void + iota(_ForwardIter __first, _ForwardIter __last, _Tp __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename std::iterator_traits<_ForwardIter>::value_type>) + + while (__first != __last) + *__first++ = __value++; + } +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h b/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h new file mode 100644 index 000000000..69f286d7b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h @@ -0,0 +1,148 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software +// Foundation; either version 3, or (at your option) any later +// version. + +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/numeric_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_NUMERIC_TRAITS +#define _EXT_NUMERIC_TRAITS 1 + +#pragma GCC system_header + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Compile time constants for builtin types. + // In C++98 std::numeric_limits member functions cannot be used for this. +#define __glibcxx_signed(_Tp) ((_Tp)(-1) < 0) +#define __glibcxx_digits(_Tp) \ + (sizeof(_Tp) * __CHAR_BIT__ - __glibcxx_signed(_Tp)) + +#define __glibcxx_min(_Tp) \ + (__glibcxx_signed(_Tp) ? -__glibcxx_max(_Tp) - 1 : (_Tp)0) + +#define __glibcxx_max(_Tp) \ + (__glibcxx_signed(_Tp) ? \ + (((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0) + + template + struct __numeric_traits_integer + { +#if __cplusplus >= 201103L + static_assert(std::__is_integer<_Value>::__value, + "invalid specialization"); +#endif + + // Only integers for initialization of member constant. + static const _Value __min = __glibcxx_min(_Value); + static const _Value __max = __glibcxx_max(_Value); + + // NB: these two also available in std::numeric_limits as compile + // time constants, but is big and we avoid including it. + static const bool __is_signed = __glibcxx_signed(_Value); + static const int __digits = __glibcxx_digits(_Value); + }; + + template + const _Value __numeric_traits_integer<_Value>::__min; + + template + const _Value __numeric_traits_integer<_Value>::__max; + + template + const bool __numeric_traits_integer<_Value>::__is_signed; + + template + const int __numeric_traits_integer<_Value>::__digits; + +#if __cplusplus >= 201103L + template + using __int_traits = __numeric_traits_integer<_Tp>; +#endif + +#undef __glibcxx_signed +#undef __glibcxx_digits +#undef __glibcxx_min +#undef __glibcxx_max + +#define __glibcxx_floating(_Tp, _Fval, _Dval, _LDval) \ + (std::__are_same<_Tp, float>::__value ? _Fval \ + : std::__are_same<_Tp, double>::__value ? _Dval : _LDval) + +#define __glibcxx_max_digits10(_Tp) \ + (2 + __glibcxx_floating(_Tp, __FLT_MANT_DIG__, __DBL_MANT_DIG__, \ + __LDBL_MANT_DIG__) * 643L / 2136) + +#define __glibcxx_digits10(_Tp) \ + __glibcxx_floating(_Tp, __FLT_DIG__, __DBL_DIG__, __LDBL_DIG__) + +#define __glibcxx_max_exponent10(_Tp) \ + __glibcxx_floating(_Tp, __FLT_MAX_10_EXP__, __DBL_MAX_10_EXP__, \ + __LDBL_MAX_10_EXP__) + + template + struct __numeric_traits_floating + { + // Only floating point types. See N1822. + static const int __max_digits10 = __glibcxx_max_digits10(_Value); + + // See above comment... + static const bool __is_signed = true; + static const int __digits10 = __glibcxx_digits10(_Value); + static const int __max_exponent10 = __glibcxx_max_exponent10(_Value); + }; + + template + const int __numeric_traits_floating<_Value>::__max_digits10; + + template + const bool __numeric_traits_floating<_Value>::__is_signed; + + template + const int __numeric_traits_floating<_Value>::__digits10; + + template + const int __numeric_traits_floating<_Value>::__max_exponent10; + + template + struct __numeric_traits + : public __conditional_type::__value, + __numeric_traits_integer<_Value>, + __numeric_traits_floating<_Value> >::__type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#undef __glibcxx_floating +#undef __glibcxx_max_digits10 +#undef __glibcxx_digits10 +#undef __glibcxx_max_exponent10 + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h b/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h new file mode 100644 index 000000000..fc68a7290 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h @@ -0,0 +1,198 @@ +// POD character, std::char_traits specialization -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/pod_char_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +// Gabriel Dos Reis +// Benjamin Kosnik + +#ifndef _POD_CHAR_TRAITS_H +#define _POD_CHAR_TRAITS_H 1 + +#pragma GCC system_header + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // POD character abstraction. + // NB: The char_type parameter is a subset of int_type, as to allow + // int_type to properly hold the full range of char_type values as + // well as EOF. + /// @brief A POD class that serves as a character abstraction class. + template + struct character + { + typedef _Value value_type; + typedef _Int int_type; + typedef _St state_type; + typedef character<_Value, _Int, _St> char_type; + + value_type value; + + template + static char_type + from(const V2& v) + { + char_type ret = { static_cast(v) }; + return ret; + } + + template + static V2 + to(const char_type& c) + { + V2 ret = { static_cast(c.value) }; + return ret; + } + + }; + + template + inline bool + operator==(const character<_Value, _Int, _St>& lhs, + const character<_Value, _Int, _St>& rhs) + { return lhs.value == rhs.value; } + + template + inline bool + operator<(const character<_Value, _Int, _St>& lhs, + const character<_Value, _Int, _St>& rhs) + { return lhs.value < rhs.value; } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// char_traits<__gnu_cxx::character> specialization. + template + struct char_traits<__gnu_cxx::character<_Value, _Int, _St> > + { + typedef __gnu_cxx::character<_Value, _Int, _St> char_type; + typedef typename char_type::int_type int_type; + typedef typename char_type::state_type state_type; + typedef fpos pos_type; + typedef streamoff off_type; + + static void + assign(char_type& __c1, const char_type& __c2) + { __c1 = __c2; } + + static bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } + + static int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (!eq(__s1[__i], __s2[__i])) + return lt(__s1[__i], __s2[__i]) ? -1 : 1; + return 0; + } + + static size_t + length(const char_type* __s) + { + const char_type* __p = __s; + while (__p->value) + ++__p; + return (__p - __s); + } + + static const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p) + if (*__p == __a) + return __p; + return 0; + } + + static char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; + return static_cast + (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))); + } + + static char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; + std::copy(__s2, __s2 + __n, __s1); + return __s1; + } + + static char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + std::fill_n(__s, __n, __a); + return __s; + } + + static char_type + to_char_type(const int_type& __i) + { return char_type::template from(__i); } + + static int_type + to_int_type(const char_type& __c) + { return char_type::template to(__c); } + + static bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + + static int_type + eof() + { + int_type __r = { static_cast::__value, + int_type, int>::__type>(-1) }; + return __r; + } + + static int_type + not_eof(const int_type& __c) + { return eq_int_type(__c, eof()) ? int_type() : __c; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/rb_tree b/resources/sources/avr-libstdcpp/include/ext/rb_tree new file mode 100644 index 000000000..036e959b1 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/rb_tree @@ -0,0 +1,93 @@ +// rb_tree extension -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/rb_tree + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _RB_TREE +#define _RB_TREE 1 + +#pragma GCC system_header + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Class rb_tree is not part of the C++ standard. It is provided for + // compatibility with the HP STL. + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template > + struct rb_tree + : public std::_Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc> + { + typedef std::_Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc> _Base; + typedef typename _Base::allocator_type allocator_type; + + rb_tree(const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _Base(__comp, __a) { } + + ~rb_tree() { } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/slist b/resources/sources/avr-libstdcpp/include/ext/slist new file mode 100644 index 000000000..03c550127 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/slist @@ -0,0 +1,1082 @@ +// Singly-linked list implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file ext/slist + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _SLIST +#define _SLIST 1 + +#include +#include +#include +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct _Slist_node_base + { + _Slist_node_base* _M_next; + }; + + inline _Slist_node_base* + __slist_make_link(_Slist_node_base* __prev_node, + _Slist_node_base* __new_node) + { + __new_node->_M_next = __prev_node->_M_next; + __prev_node->_M_next = __new_node; + return __new_node; + } + + inline _Slist_node_base* + __slist_previous(_Slist_node_base* __head, + const _Slist_node_base* __node) + { + while (__head && __head->_M_next != __node) + __head = __head->_M_next; + return __head; + } + + inline const _Slist_node_base* + __slist_previous(const _Slist_node_base* __head, + const _Slist_node_base* __node) + { + while (__head && __head->_M_next != __node) + __head = __head->_M_next; + return __head; + } + + inline void + __slist_splice_after(_Slist_node_base* __pos, + _Slist_node_base* __before_first, + _Slist_node_base* __before_last) + { + if (__pos != __before_first && __pos != __before_last) + { + _Slist_node_base* __first = __before_first->_M_next; + _Slist_node_base* __after = __pos->_M_next; + __before_first->_M_next = __before_last->_M_next; + __pos->_M_next = __first; + __before_last->_M_next = __after; + } + } + + inline void + __slist_splice_after(_Slist_node_base* __pos, _Slist_node_base* __head) + { + _Slist_node_base* __before_last = __slist_previous(__head, 0); + if (__before_last != __head) + { + _Slist_node_base* __after = __pos->_M_next; + __pos->_M_next = __head->_M_next; + __head->_M_next = 0; + __before_last->_M_next = __after; + } + } + + inline _Slist_node_base* + __slist_reverse(_Slist_node_base* __node) + { + _Slist_node_base* __result = __node; + __node = __node->_M_next; + __result->_M_next = 0; + while(__node) + { + _Slist_node_base* __next = __node->_M_next; + __node->_M_next = __result; + __result = __node; + __node = __next; + } + return __result; + } + + inline std::size_t + __slist_size(_Slist_node_base* __node) + { + std::size_t __result = 0; + for (; __node != 0; __node = __node->_M_next) + ++__result; + return __result; + } + + template + struct _Slist_node : public _Slist_node_base + { + _Tp _M_data; + }; + + struct _Slist_iterator_base + { + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Slist_node_base* _M_node; + + _Slist_iterator_base(_Slist_node_base* __x) + : _M_node(__x) {} + + void + _M_incr() + { _M_node = _M_node->_M_next; } + + bool + operator==(const _Slist_iterator_base& __x) const + { return _M_node == __x._M_node; } + + bool + operator!=(const _Slist_iterator_base& __x) const + { return _M_node != __x._M_node; } + }; + + template + struct _Slist_iterator : public _Slist_iterator_base + { + typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; + typedef _Slist_iterator<_Tp, _Ref, _Ptr> _Self; + + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef _Slist_node<_Tp> _Node; + + explicit + _Slist_iterator(_Node* __x) + : _Slist_iterator_base(__x) {} + + _Slist_iterator() + : _Slist_iterator_base(0) {} + + _Slist_iterator(const iterator& __x) + : _Slist_iterator_base(__x._M_node) {} + + reference + operator*() const + { return ((_Node*) _M_node)->_M_data; } + + pointer + operator->() const + { return &(operator*()); } + + _Self& + operator++() + { + _M_incr(); + return *this; + } + + _Self + operator++(int) + { + _Self __tmp = *this; + _M_incr(); + return __tmp; + } + }; + + template + struct _Slist_base + : public __alloc_traits<_Alloc>::template rebind<_Slist_node<_Tp> >::other + { + typedef typename __alloc_traits<_Alloc>::template + rebind<_Slist_node<_Tp> >::other _Node_alloc; + typedef _Alloc allocator_type; + + allocator_type + get_allocator() const + { return *static_cast(this); } + + _Slist_base(const allocator_type& __a) + : _Node_alloc(__a) + { this->_M_head._M_next = 0; } + + ~_Slist_base() + { _M_erase_after(&this->_M_head, 0); } + + protected: + _Slist_node_base _M_head; + + _Slist_node<_Tp>* + _M_get_node() + { return _Node_alloc::allocate(1); } + + void + _M_put_node(_Slist_node<_Tp>* __p) + { _Node_alloc::deallocate(__p, 1); } + + protected: + _Slist_node_base* _M_erase_after(_Slist_node_base* __pos) + { + _Slist_node<_Tp>* __next = (_Slist_node<_Tp>*) (__pos->_M_next); + _Slist_node_base* __next_next = __next->_M_next; + __pos->_M_next = __next_next; + allocator_type __a = get_allocator(); + __alloc_traits::destroy(__a, &__next->_M_data); + _M_put_node(__next); + return __next_next; + } + _Slist_node_base* _M_erase_after(_Slist_node_base*, _Slist_node_base*); + }; + + template + _Slist_node_base* + _Slist_base<_Tp,_Alloc>::_M_erase_after(_Slist_node_base* __before_first, + _Slist_node_base* __last_node) + { + _Slist_node<_Tp>* __cur = (_Slist_node<_Tp>*) (__before_first->_M_next); + while (__cur != __last_node) + { + _Slist_node<_Tp>* __tmp = __cur; + __cur = (_Slist_node<_Tp>*) __cur->_M_next; + allocator_type __a = get_allocator(); + __alloc_traits::destroy(__a, &__tmp->_M_data); + _M_put_node(__tmp); + } + __before_first->_M_next = __last_node; + return __last_node; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template > + class slist : private _Slist_base<_Tp,_Alloc> + { + // concept requirements + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) + + private: + typedef _Slist_base<_Tp,_Alloc> _Base; + + public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; + + typedef typename _Base::allocator_type allocator_type; + + allocator_type + get_allocator() const + { return _Base::get_allocator(); } + + private: + typedef _Slist_node<_Tp> _Node; + typedef _Slist_node_base _Node_base; + typedef _Slist_iterator_base _Iterator_base; + + _Node* + _M_create_node(const value_type& __x) + { + _Node* __node = this->_M_get_node(); + __try + { + allocator_type __a = get_allocator(); + __alloc_traits::construct(__a, &__node->_M_data, + __x); + __node->_M_next = 0; + } + __catch(...) + { + this->_M_put_node(__node); + __throw_exception_again; + } + return __node; + } + + _Node* + _M_create_node() + { + _Node* __node = this->_M_get_node(); + __try + { + allocator_type __a = get_allocator(); + __alloc_traits::construct(__a, &__node->_M_data, + value_type()); + __node->_M_next = 0; + } + __catch(...) + { + this->_M_put_node(__node); + __throw_exception_again; + } + return __node; + } + + public: + explicit + slist(const allocator_type& __a = allocator_type()) + : _Base(__a) {} + + slist(size_type __n, const value_type& __x, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { _M_insert_after_fill(&this->_M_head, __n, __x); } + + explicit + slist(size_type __n) + : _Base(allocator_type()) + { _M_insert_after_fill(&this->_M_head, __n, value_type()); } + + // We don't need any dispatching tricks here, because + // _M_insert_after_range already does them. + template + slist(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { _M_insert_after_range(&this->_M_head, __first, __last); } + + slist(const slist& __x) + : _Base(__x.get_allocator()) + { _M_insert_after_range(&this->_M_head, __x.begin(), __x.end()); } + + slist& + operator= (const slist& __x); + + ~slist() {} + + public: + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + + void + assign(size_type __n, const _Tp& __val) + { _M_fill_assign(__n, __val); } + + void + _M_fill_assign(size_type __n, const _Tp& __val); + + template + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } + + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, std::__true_type) + { _M_fill_assign((size_type) __n, (_Tp) __val); } + + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + std::__false_type); + + public: + + iterator + begin() + { return iterator((_Node*)this->_M_head._M_next); } + + const_iterator + begin() const + { return const_iterator((_Node*)this->_M_head._M_next);} + + iterator + end() + { return iterator(0); } + + const_iterator + end() const + { return const_iterator(0); } + + // Experimental new feature: before_begin() returns a + // non-dereferenceable iterator that, when incremented, yields + // begin(). This iterator may be used as the argument to + // insert_after, erase_after, etc. Note that even for an empty + // slist, before_begin() is not the same iterator as end(). It + // is always necessary to increment before_begin() at least once to + // obtain end(). + iterator + before_begin() + { return iterator((_Node*) &this->_M_head); } + + const_iterator + before_begin() const + { return const_iterator((_Node*) &this->_M_head); } + + size_type + size() const + { return __slist_size(this->_M_head._M_next); } + + size_type + max_size() const + { return size_type(-1); } + + _GLIBCXX_NODISCARD bool + empty() const + { return this->_M_head._M_next == 0; } + + void + swap(slist& __x) + { std::swap(this->_M_head._M_next, __x._M_head._M_next); } + + public: + + reference + front() + { return ((_Node*) this->_M_head._M_next)->_M_data; } + + const_reference + front() const + { return ((_Node*) this->_M_head._M_next)->_M_data; } + + void + push_front(const value_type& __x) + { __slist_make_link(&this->_M_head, _M_create_node(__x)); } + + void + push_front() + { __slist_make_link(&this->_M_head, _M_create_node()); } + + void + pop_front() + { + _Node* __node = (_Node*) this->_M_head._M_next; + this->_M_head._M_next = __node->_M_next; + allocator_type __a = get_allocator(); + __alloc_traits::destroy(__a, &__node->_M_data); + this->_M_put_node(__node); + } + + iterator + previous(const_iterator __pos) + { return iterator((_Node*) __slist_previous(&this->_M_head, + __pos._M_node)); } + + const_iterator + previous(const_iterator __pos) const + { return const_iterator((_Node*) __slist_previous(&this->_M_head, + __pos._M_node)); } + + private: + _Node* + _M_insert_after(_Node_base* __pos, const value_type& __x) + { return (_Node*) (__slist_make_link(__pos, _M_create_node(__x))); } + + _Node* + _M_insert_after(_Node_base* __pos) + { return (_Node*) (__slist_make_link(__pos, _M_create_node())); } + + void + _M_insert_after_fill(_Node_base* __pos, + size_type __n, const value_type& __x) + { + for (size_type __i = 0; __i < __n; ++__i) + __pos = __slist_make_link(__pos, _M_create_node(__x)); + } + + // Check whether it's an integral type. If so, it's not an iterator. + template + void + _M_insert_after_range(_Node_base* __pos, + _InIterator __first, _InIterator __last) + { + typedef typename std::__is_integer<_InIterator>::__type _Integral; + _M_insert_after_range(__pos, __first, __last, _Integral()); + } + + template + void + _M_insert_after_range(_Node_base* __pos, _Integer __n, _Integer __x, + std::__true_type) + { _M_insert_after_fill(__pos, __n, __x); } + + template + void + _M_insert_after_range(_Node_base* __pos, + _InIterator __first, _InIterator __last, + std::__false_type) + { + while (__first != __last) + { + __pos = __slist_make_link(__pos, _M_create_node(*__first)); + ++__first; + } + } + + public: + iterator + insert_after(iterator __pos, const value_type& __x) + { return iterator(_M_insert_after(__pos._M_node, __x)); } + + iterator + insert_after(iterator __pos) + { return insert_after(__pos, value_type()); } + + void + insert_after(iterator __pos, size_type __n, const value_type& __x) + { _M_insert_after_fill(__pos._M_node, __n, __x); } + + // We don't need any dispatching tricks here, because + // _M_insert_after_range already does them. + template + void + insert_after(iterator __pos, _InIterator __first, _InIterator __last) + { _M_insert_after_range(__pos._M_node, __first, __last); } + + iterator + insert(iterator __pos, const value_type& __x) + { return iterator(_M_insert_after(__slist_previous(&this->_M_head, + __pos._M_node), + __x)); } + + iterator + insert(iterator __pos) + { return iterator(_M_insert_after(__slist_previous(&this->_M_head, + __pos._M_node), + value_type())); } + + void + insert(iterator __pos, size_type __n, const value_type& __x) + { _M_insert_after_fill(__slist_previous(&this->_M_head, __pos._M_node), + __n, __x); } + + // We don't need any dispatching tricks here, because + // _M_insert_after_range already does them. + template + void + insert(iterator __pos, _InIterator __first, _InIterator __last) + { _M_insert_after_range(__slist_previous(&this->_M_head, __pos._M_node), + __first, __last); } + + public: + iterator + erase_after(iterator __pos) + { return iterator((_Node*) this->_M_erase_after(__pos._M_node)); } + + iterator + erase_after(iterator __before_first, iterator __last) + { + return iterator((_Node*) this->_M_erase_after(__before_first._M_node, + __last._M_node)); + } + + iterator + erase(iterator __pos) + { + return iterator((_Node*) this->_M_erase_after + (__slist_previous(&this->_M_head, __pos._M_node))); + } + + iterator + erase(iterator __first, iterator __last) + { + return iterator((_Node*) this->_M_erase_after + (__slist_previous(&this->_M_head, __first._M_node), + __last._M_node)); + } + + void + resize(size_type new_size, const _Tp& __x); + + void + resize(size_type new_size) + { resize(new_size, _Tp()); } + + void + clear() + { this->_M_erase_after(&this->_M_head, 0); } + + public: + // Moves the range [__before_first + 1, __before_last + 1) to *this, + // inserting it immediately after __pos. This is constant time. + void + splice_after(iterator __pos, + iterator __before_first, iterator __before_last) + { + if (__before_first != __before_last) + __slist_splice_after(__pos._M_node, __before_first._M_node, + __before_last._M_node); + } + + // Moves the element that follows __prev to *this, inserting it + // immediately after __pos. This is constant time. + void + splice_after(iterator __pos, iterator __prev) + { __slist_splice_after(__pos._M_node, + __prev._M_node, __prev._M_node->_M_next); } + + // Removes all of the elements from the list __x to *this, inserting + // them immediately after __pos. __x must not be *this. Complexity: + // linear in __x.size(). + void + splice_after(iterator __pos, slist& __x) + { __slist_splice_after(__pos._M_node, &__x._M_head); } + + // Linear in distance(begin(), __pos), and linear in __x.size(). + void + splice(iterator __pos, slist& __x) + { + if (__x._M_head._M_next) + __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), + &__x._M_head, + __slist_previous(&__x._M_head, 0)); } + + // Linear in distance(begin(), __pos), and in distance(__x.begin(), __i). + void + splice(iterator __pos, slist& __x, iterator __i) + { __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), + __slist_previous(&__x._M_head, __i._M_node), + __i._M_node); } + + // Linear in distance(begin(), __pos), in distance(__x.begin(), __first), + // and in distance(__first, __last). + void + splice(iterator __pos, slist& __x, iterator __first, iterator __last) + { + if (__first != __last) + __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), + __slist_previous(&__x._M_head, __first._M_node), + __slist_previous(__first._M_node, + __last._M_node)); + } + + public: + void + reverse() + { + if (this->_M_head._M_next) + this->_M_head._M_next = __slist_reverse(this->_M_head._M_next); + } + + void + remove(const _Tp& __val); + + void + unique(); + + void + merge(slist& __x); + + void + sort(); + + template + void + remove_if(_Predicate __pred); + + template + void + unique(_BinaryPredicate __pred); + + template + void + merge(slist&, _StrictWeakOrdering); + + template + void + sort(_StrictWeakOrdering __comp); + }; + + template + slist<_Tp, _Alloc>& + slist<_Tp, _Alloc>::operator=(const slist<_Tp, _Alloc>& __x) + { + if (&__x != this) + { + _Node_base* __p1 = &this->_M_head; + _Node* __n1 = (_Node*) this->_M_head._M_next; + const _Node* __n2 = (const _Node*) __x._M_head._M_next; + while (__n1 && __n2) + { + __n1->_M_data = __n2->_M_data; + __p1 = __n1; + __n1 = (_Node*) __n1->_M_next; + __n2 = (const _Node*) __n2->_M_next; + } + if (__n2 == 0) + this->_M_erase_after(__p1, 0); + else + _M_insert_after_range(__p1, const_iterator((_Node*)__n2), + const_iterator(0)); + } + return *this; + } + + template + void + slist<_Tp, _Alloc>::_M_fill_assign(size_type __n, const _Tp& __val) + { + _Node_base* __prev = &this->_M_head; + _Node* __node = (_Node*) this->_M_head._M_next; + for (; __node != 0 && __n > 0; --__n) + { + __node->_M_data = __val; + __prev = __node; + __node = (_Node*) __node->_M_next; + } + if (__n > 0) + _M_insert_after_fill(__prev, __n, __val); + else + this->_M_erase_after(__prev, 0); + } + + template + template + void + slist<_Tp, _Alloc>::_M_assign_dispatch(_InputIterator __first, + _InputIterator __last, + std::__false_type) + { + _Node_base* __prev = &this->_M_head; + _Node* __node = (_Node*) this->_M_head._M_next; + while (__node != 0 && __first != __last) + { + __node->_M_data = *__first; + __prev = __node; + __node = (_Node*) __node->_M_next; + ++__first; + } + if (__first != __last) + _M_insert_after_range(__prev, __first, __last); + else + this->_M_erase_after(__prev, 0); + } + + template + inline bool + operator==(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { + typedef typename slist<_Tp,_Alloc>::const_iterator const_iterator; + const_iterator __end1 = _SL1.end(); + const_iterator __end2 = _SL2.end(); + + const_iterator __i1 = _SL1.begin(); + const_iterator __i2 = _SL2.begin(); + while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) + { + ++__i1; + ++__i2; + } + return __i1 == __end1 && __i2 == __end2; + } + + + template + inline bool + operator<(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return std::lexicographical_compare(_SL1.begin(), _SL1.end(), + _SL2.begin(), _SL2.end()); } + + template + inline bool + operator!=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return !(_SL1 == _SL2); } + + template + inline bool + operator>(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return _SL2 < _SL1; } + + template + inline bool + operator<=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return !(_SL2 < _SL1); } + + template + inline bool + operator>=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return !(_SL1 < _SL2); } + + template + inline void + swap(slist<_Tp, _Alloc>& __x, slist<_Tp, _Alloc>& __y) + { __x.swap(__y); } + + template + void + slist<_Tp, _Alloc>::resize(size_type __len, const _Tp& __x) + { + _Node_base* __cur = &this->_M_head; + while (__cur->_M_next != 0 && __len > 0) + { + --__len; + __cur = __cur->_M_next; + } + if (__cur->_M_next) + this->_M_erase_after(__cur, 0); + else + _M_insert_after_fill(__cur, __len, __x); + } + + template + void + slist<_Tp, _Alloc>::remove(const _Tp& __val) + { + _Node_base* __cur = &this->_M_head; + while (__cur && __cur->_M_next) + { + if (((_Node*) __cur->_M_next)->_M_data == __val) + this->_M_erase_after(__cur); + else + __cur = __cur->_M_next; + } + } + + template + void + slist<_Tp, _Alloc>::unique() + { + _Node_base* __cur = this->_M_head._M_next; + if (__cur) + { + while (__cur->_M_next) + { + if (((_Node*)__cur)->_M_data + == ((_Node*)(__cur->_M_next))->_M_data) + this->_M_erase_after(__cur); + else + __cur = __cur->_M_next; + } + } + } + + template + void + slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x) + { + _Node_base* __n1 = &this->_M_head; + while (__n1->_M_next && __x._M_head._M_next) + { + if (((_Node*) __x._M_head._M_next)->_M_data + < ((_Node*) __n1->_M_next)->_M_data) + __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); + __n1 = __n1->_M_next; + } + if (__x._M_head._M_next) + { + __n1->_M_next = __x._M_head._M_next; + __x._M_head._M_next = 0; + } + } + + template + void + slist<_Tp, _Alloc>::sort() + { + if (this->_M_head._M_next && this->_M_head._M_next->_M_next) + { + slist __carry; + slist __counter[64]; + int __fill = 0; + while (!empty()) + { + __slist_splice_after(&__carry._M_head, + &this->_M_head, this->_M_head._M_next); + int __i = 0; + while (__i < __fill && !__counter[__i].empty()) + { + __counter[__i].merge(__carry); + __carry.swap(__counter[__i]); + ++__i; + } + __carry.swap(__counter[__i]); + if (__i == __fill) + ++__fill; + } + + for (int __i = 1; __i < __fill; ++__i) + __counter[__i].merge(__counter[__i-1]); + this->swap(__counter[__fill-1]); + } + } + + template + template + void slist<_Tp, _Alloc>::remove_if(_Predicate __pred) + { + _Node_base* __cur = &this->_M_head; + while (__cur->_M_next) + { + if (__pred(((_Node*) __cur->_M_next)->_M_data)) + this->_M_erase_after(__cur); + else + __cur = __cur->_M_next; + } + } + + template + template + void + slist<_Tp, _Alloc>::unique(_BinaryPredicate __pred) + { + _Node* __cur = (_Node*) this->_M_head._M_next; + if (__cur) + { + while (__cur->_M_next) + { + if (__pred(((_Node*)__cur)->_M_data, + ((_Node*)(__cur->_M_next))->_M_data)) + this->_M_erase_after(__cur); + else + __cur = (_Node*) __cur->_M_next; + } + } + } + + template + template + void + slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x, + _StrictWeakOrdering __comp) + { + _Node_base* __n1 = &this->_M_head; + while (__n1->_M_next && __x._M_head._M_next) + { + if (__comp(((_Node*) __x._M_head._M_next)->_M_data, + ((_Node*) __n1->_M_next)->_M_data)) + __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); + __n1 = __n1->_M_next; + } + if (__x._M_head._M_next) + { + __n1->_M_next = __x._M_head._M_next; + __x._M_head._M_next = 0; + } + } + + template + template + void + slist<_Tp, _Alloc>::sort(_StrictWeakOrdering __comp) + { + if (this->_M_head._M_next && this->_M_head._M_next->_M_next) + { + slist __carry; + slist __counter[64]; + int __fill = 0; + while (!empty()) + { + __slist_splice_after(&__carry._M_head, + &this->_M_head, this->_M_head._M_next); + int __i = 0; + while (__i < __fill && !__counter[__i].empty()) + { + __counter[__i].merge(__carry, __comp); + __carry.swap(__counter[__i]); + ++__i; + } + __carry.swap(__counter[__i]); + if (__i == __fill) + ++__fill; + } + + for (int __i = 1; __i < __fill; ++__i) + __counter[__i].merge(__counter[__i-1], __comp); + this->swap(__counter[__fill-1]); + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that insertions will be constant + // time rather than linear time. + template + class insert_iterator<__gnu_cxx::slist<_Tp, _Alloc> > + { + protected: + typedef __gnu_cxx::slist<_Tp, _Alloc> _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x, typename _Container::iterator __i) + : container(&__x) + { + if (__i == __x.begin()) + iter = __x.before_begin(); + else + iter = __x.previous(__i); + } + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + iter = container->insert_after(iter, __value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/type_traits.h b/resources/sources/avr-libstdcpp/include/ext/type_traits.h new file mode 100644 index 000000000..cf773cf2d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/type_traits.h @@ -0,0 +1,221 @@ +// -*- C++ -*- + +// Copyright (C) 2005-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software +// Foundation; either version 3, or (at your option) any later +// version. + +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/type_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_TYPE_TRAITS +#define _EXT_TYPE_TRAITS 1 + +#pragma GCC system_header + +#include +#include + +extern "C++" { + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Define a nested type if some predicate holds. + template + struct __enable_if + { }; + + template + struct __enable_if + { typedef _Tp __type; }; + + + // Conditional expression for types. If true, first, if false, second. + template + struct __conditional_type + { typedef _Iftrue __type; }; + + template + struct __conditional_type + { typedef _Iffalse __type; }; + + + // Given an integral builtin type, return the corresponding unsigned type. + template + struct __add_unsigned + { + private: + typedef __enable_if::__value, _Tp> __if_type; + + public: + typedef typename __if_type::__type __type; + }; + + template<> + struct __add_unsigned + { typedef unsigned char __type; }; + + template<> + struct __add_unsigned + { typedef unsigned char __type; }; + + template<> + struct __add_unsigned + { typedef unsigned short __type; }; + + template<> + struct __add_unsigned + { typedef unsigned int __type; }; + + template<> + struct __add_unsigned + { typedef unsigned long __type; }; + + template<> + struct __add_unsigned + { typedef unsigned long long __type; }; + + // Declare but don't define. + template<> + struct __add_unsigned; + + template<> + struct __add_unsigned; + + + // Given an integral builtin type, return the corresponding signed type. + template + struct __remove_unsigned + { + private: + typedef __enable_if::__value, _Tp> __if_type; + + public: + typedef typename __if_type::__type __type; + }; + + template<> + struct __remove_unsigned + { typedef signed char __type; }; + + template<> + struct __remove_unsigned + { typedef signed char __type; }; + + template<> + struct __remove_unsigned + { typedef short __type; }; + + template<> + struct __remove_unsigned + { typedef int __type; }; + + template<> + struct __remove_unsigned + { typedef long __type; }; + + template<> + struct __remove_unsigned + { typedef long long __type; }; + + // Declare but don't define. + template<> + struct __remove_unsigned; + + template<> + struct __remove_unsigned; + + + // For use in string and vstring. + template + inline bool + __is_null_pointer(_Type* __ptr) + { return __ptr == 0; } + + template + inline bool + __is_null_pointer(_Type) + { return false; } + +#if __cplusplus >= 201103L + inline bool + __is_null_pointer(std::nullptr_t) + { return true; } +#endif + + // For complex and cmath + template::__value> + struct __promote + { typedef double __type; }; + + // No nested __type member for non-integer non-floating point types, + // allows this type to be used for SFINAE to constrain overloads in + // and to only the intended types. + template + struct __promote<_Tp, false> + { }; + + template<> + struct __promote + { typedef long double __type; }; + + template<> + struct __promote + { typedef double __type; }; + + template<> + struct __promote + { typedef float __type; }; + + template::__type, + typename _Up2 = typename __promote<_Up>::__type> + struct __promote_2 + { + typedef __typeof__(_Tp2() + _Up2()) __type; + }; + + template::__type, + typename _Up2 = typename __promote<_Up>::__type, + typename _Vp2 = typename __promote<_Vp>::__type> + struct __promote_3 + { + typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type; + }; + + template::__type, + typename _Up2 = typename __promote<_Up>::__type, + typename _Vp2 = typename __promote<_Vp>::__type, + typename _Wp2 = typename __promote<_Wp>::__type> + struct __promote_4 + { + typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/typelist.h b/resources/sources/avr-libstdcpp/include/ext/typelist.h new file mode 100644 index 000000000..1835c141f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/typelist.h @@ -0,0 +1,538 @@ +// -*- C++ -*- + +// Copyright (C) 2005-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. + +// Permission to use, copy, modify, sell, and distribute this software +// is hereby granted without fee, provided that the above copyright +// notice appears in all copies, and that both that copyright notice and +// this permission notice appear in supporting documentation. None of +// the above authors, nor IBM Haifa Research Laboratories, make any +// representation about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. + +/** + * @file ext/typelist.h + * This file is a GNU extension to the Standard C++ Library. + * + * Contains typelist_chain definitions. + * Typelists are an idea by Andrei Alexandrescu. + */ + +#ifndef _TYPELIST_H +#define _TYPELIST_H 1 + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** @namespace __gnu_cxx::typelist + * @brief GNU typelist extensions for public compile-time use. +*/ +namespace typelist +{ + struct null_type { }; + + template + struct node + { + typedef Root root; + }; + + // Forward declarations of functors. + template + struct chain + { + typedef Hd head; + typedef Typelist tail; + }; + + // Apply all typelist types to unary functor. + template + void + apply(Fn&, Typelist); + + /// Apply all typelist types to generator functor. + template + void + apply_generator(Gn&, Typelist); + + // Apply all typelist types and values to generator functor. + template + void + apply_generator(Gn&, TypelistT, TypelistV); + + template + struct append; + + template + struct append_typelist; + + template + struct contains; + + template class Pred> + struct filter; + + template + struct at_index; + + template class Transform> + struct transform; + + template + struct flatten; + + template + struct from_first; + + template + struct create1; + + template + struct create2; + + template + struct create3; + + template + struct create4; + + template + struct create5; + + template + struct create6; + +namespace detail +{ + template + struct apply_; + + template + struct apply_ > + { + void + operator()(Fn& f) + { + f.operator()(Hd()); + apply_ next; + next(f); + } + }; + + template + struct apply_ + { + void + operator()(Fn&) { } + }; + + template + struct apply_generator1_; + + template + struct apply_generator1_ > + { + void + operator()(Gn& g) + { + g.template operator()(); + apply_generator1_ next; + next(g); + } + }; + + template + struct apply_generator1_ + { + void + operator()(Gn&) { } + }; + + template + struct apply_generator2_; + + template + struct apply_generator2_, chain > + { + void + operator()(Gn& g) + { + g.template operator()(); + apply_generator2_ next; + next(g); + } + }; + + template + struct apply_generator2_ + { + void + operator()(Gn&) { } + }; + + template + struct append_; + + template + struct append_, Typelist_Chain> + { + private: + typedef append_ append_type; + + public: + typedef chain type; + }; + + template + struct append_ + { + typedef Typelist_Chain type; + }; + + template + struct append_, null_type> + { + typedef chain type; + }; + + template<> + struct append_ + { + typedef null_type type; + }; + + template + struct append_typelist_; + + template + struct append_typelist_ > + { + typedef chain type; + }; + + template + struct append_typelist_ > + { + private: + typedef typename append_typelist_::type rest_type; + + public: + typedef typename append >::type::root type; + }; + + template + struct contains_; + + template + struct contains_ + { + enum + { + value = false + }; + }; + + template + struct contains_, T> + { + enum + { + value = contains_::value + }; + }; + + template + struct contains_, T> + { + enum + { + value = true + }; + }; + + template class Pred> + struct chain_filter_; + + template class Pred> + struct chain_filter_ + { + typedef null_type type; + }; + + template class Pred> + struct chain_filter_, Pred> + { + private: + enum + { + include_hd = Pred::value + }; + + typedef typename chain_filter_::type rest_type; + typedef chain chain_type; + + public: + typedef typename __conditional_type::__type type; + }; + + template + struct chain_at_index_; + + template + struct chain_at_index_, 0> + { + typedef Hd type; + }; + + template + struct chain_at_index_, i> + { + typedef typename chain_at_index_::type type; + }; + + template class Transform> + struct chain_transform_; + + template class Transform> + struct chain_transform_ + { + typedef null_type type; + }; + + template class Transform> + struct chain_transform_, Transform> + { + private: + typedef typename chain_transform_::type rest_type; + typedef typename Transform::type transform_type; + + public: + typedef chain type; + }; + + template + struct chain_flatten_; + + template + struct chain_flatten_ > + { + typedef typename Hd_Tl::root type; + }; + + template + struct chain_flatten_ > + { + private: + typedef typename chain_flatten_::type rest_type; + typedef append > append_type; + public: + typedef typename append_type::type::root type; + }; +} // namespace detail + +#define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN7(X0, X1, X2, X3, X4, X5, X6) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN8(X0, X1, X2, X3, X4, X5, X6, X7) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN9(X0, X1, X2, X3, X4, X5, X6, X7, X8) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN10(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN11(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN12(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN13(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN14(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN15(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN16(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN17(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN18(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN19(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN20(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) __gnu_cxx::typelist::chain + + template + void + apply(Fn& fn, Typelist) + { + detail::apply_ a; + a(fn); + } + + template + void + apply_generator(Fn& fn, Typelist) + { + detail::apply_generator1_ a; + a(fn); + } + + template + void + apply_generator(Fn& fn, TypelistT, TypelistV) + { + typedef typename TypelistT::root rootT; + typedef typename TypelistV::root rootV; + detail::apply_generator2_ a; + a(fn); + } + + template + struct append + { + private: + typedef typename Typelist0::root root0_type; + typedef typename Typelist1::root root1_type; + typedef detail::append_ append_type; + + public: + typedef node type; + }; + + template + struct append_typelist + { + private: + typedef typename Typelist_Typelist::root root_type; + typedef detail::append_typelist_ append_type; + + public: + typedef node type; + }; + + template + struct contains + { + private: + typedef typename Typelist::root root_type; + + public: + enum + { + value = detail::contains_::value + }; + }; + + template class Pred> + struct filter + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_filter_ filter_type; + + public: + typedef node type; + }; + + template + struct at_index + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_at_index_ index_type; + + public: + typedef typename index_type::type type; + }; + + template class Transform> + struct transform + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_transform_ transform_type; + + public: + typedef node type; + }; + + template + struct flatten + { + private: + typedef typename Typelist_Typelist::root root_type; + typedef typename detail::chain_flatten_::type flatten_type; + + public: + typedef node type; + }; + + template + struct from_first + { + private: + typedef typename at_index::type first_type; + + public: + typedef node > type; + }; + + template + struct create1 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> type; + }; + + template + struct create2 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> type; + }; + + template + struct create3 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)> type; + }; + + template + struct create4 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)> type; + }; + + template + struct create5 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)> type; + }; + + template + struct create6 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type; + }; +} // namespace typelist +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + + +#endif diff --git a/resources/sources/avr-libstdcpp/include/forward_list b/resources/sources/avr-libstdcpp/include/forward_list new file mode 100644 index 000000000..439ef6b38 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/forward_list @@ -0,0 +1,87 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/forward_list + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_FORWARD_LIST +#define _GLIBCXX_FORWARD_LIST 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template + using forward_list = std::forward_list<_Tp, polymorphic_allocator<_Tp>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_erase_if 202002L + + template + inline typename forward_list<_Tp, _Alloc>::size_type + erase_if(forward_list<_Tp, _Alloc>& __cont, _Predicate __pred) + { return __cont.remove_if(__pred); } + + template + inline typename forward_list<_Tp, _Alloc>::size_type + erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value) + { + using __elem_type = typename forward_list<_Tp, _Alloc>::value_type; + return std::erase_if(__cont, [&](__elem_type& __elem) { + return __elem == __value; + }); + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif // C++11 + +#endif // _GLIBCXX_FORWARD_LIST diff --git a/resources/sources/avr-libstdcpp/include/functional b/resources/sources/avr-libstdcpp/include/functional new file mode 100644 index 000000000..dc21c10b7 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/functional @@ -0,0 +1,1280 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file include/functional + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_FUNCTIONAL +#define _GLIBCXX_FUNCTIONAL 1 + +#pragma GCC system_header + +#include +#include + +#if __cplusplus >= 201103L + +#include +#include +#include +#include +#include +#include // std::reference_wrapper and _Mem_fn_traits +#include // std::function +#if __cplusplus > 201402L +# include +# include +# include +# include +# include +#endif +#if __cplusplus > 201703L +# include +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201703L +# define __cpp_lib_invoke 201411L +# if __cplusplus > 201703L +# define __cpp_lib_constexpr_functional 201907L +# endif + + /// Invoke a callable object. + template + inline _GLIBCXX20_CONSTEXPR invoke_result_t<_Callable, _Args...> + invoke(_Callable&& __fn, _Args&&... __args) + noexcept(is_nothrow_invocable_v<_Callable, _Args...>) + { + return std::__invoke(std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#endif // C++17 + + template::value> + class _Mem_fn_base + : public _Mem_fn_traits<_MemFunPtr>::__maybe_type + { + using _Traits = _Mem_fn_traits<_MemFunPtr>; + + using _Arity = typename _Traits::__arity; + using _Varargs = typename _Traits::__vararg; + + template + friend struct _Bind_check_arity; + + _MemFunPtr _M_pmf; + + public: + + using result_type = typename _Traits::__result_type; + + explicit constexpr + _Mem_fn_base(_MemFunPtr __pmf) noexcept : _M_pmf(__pmf) { } + + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_Args&&... __args) const + noexcept(noexcept( + std::__invoke(_M_pmf, std::forward<_Args>(__args)...))) + -> decltype(std::__invoke(_M_pmf, std::forward<_Args>(__args)...)) + { return std::__invoke(_M_pmf, std::forward<_Args>(__args)...); } + }; + + // Partial specialization for member object pointers. + template + class _Mem_fn_base<_MemObjPtr, false> + { + using _Arity = integral_constant; + using _Varargs = false_type; + + template + friend struct _Bind_check_arity; + + _MemObjPtr _M_pm; + + public: + explicit constexpr + _Mem_fn_base(_MemObjPtr __pm) noexcept : _M_pm(__pm) { } + + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_Tp&& __obj) const + noexcept(noexcept(std::__invoke(_M_pm, std::forward<_Tp>(__obj)))) + -> decltype(std::__invoke(_M_pm, std::forward<_Tp>(__obj))) + { return std::__invoke(_M_pm, std::forward<_Tp>(__obj)); } + }; + + template + struct _Mem_fn; // undefined + + template + struct _Mem_fn<_Res _Class::*> + : _Mem_fn_base<_Res _Class::*> + { + using _Mem_fn_base<_Res _Class::*>::_Mem_fn_base; + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2048. Unnecessary mem_fn overloads + /** + * @brief Returns a function object that forwards to the member + * pointer @a pm. + * @ingroup functors + */ + template + _GLIBCXX20_CONSTEXPR + inline _Mem_fn<_Tp _Class::*> + mem_fn(_Tp _Class::* __pm) noexcept + { + return _Mem_fn<_Tp _Class::*>(__pm); + } + + /** + * @brief Determines if the given type _Tp is a function object that + * should be treated as a subexpression when evaluating calls to + * function objects returned by bind(). + * + * C++11 [func.bind.isbind]. + * @ingroup binders + */ + template + struct is_bind_expression + : public false_type { }; + + /** + * @brief Determines if the given type _Tp is a placeholder in a + * bind() expression and, if so, which placeholder it is. + * + * C++11 [func.bind.isplace]. + * @ingroup binders + */ + template + struct is_placeholder + : public integral_constant + { }; + +#if __cplusplus > 201402L + template inline constexpr bool is_bind_expression_v + = is_bind_expression<_Tp>::value; + template inline constexpr int is_placeholder_v + = is_placeholder<_Tp>::value; +#endif // C++17 + + /** @brief The type of placeholder objects defined by libstdc++. + * @ingroup binders + */ + template struct _Placeholder { }; + + /** @namespace std::placeholders + * @brief ISO C++ 2011 namespace for std::bind placeholders. + * @ingroup binders + */ + namespace placeholders + { + /* Define a large number of placeholders. There is no way to + * simplify this with variadic templates, because we're introducing + * unique names for each. + */ + extern const _Placeholder<1> _1; + extern const _Placeholder<2> _2; + extern const _Placeholder<3> _3; + extern const _Placeholder<4> _4; + extern const _Placeholder<5> _5; + extern const _Placeholder<6> _6; + extern const _Placeholder<7> _7; + extern const _Placeholder<8> _8; + extern const _Placeholder<9> _9; + extern const _Placeholder<10> _10; + extern const _Placeholder<11> _11; + extern const _Placeholder<12> _12; + extern const _Placeholder<13> _13; + extern const _Placeholder<14> _14; + extern const _Placeholder<15> _15; + extern const _Placeholder<16> _16; + extern const _Placeholder<17> _17; + extern const _Placeholder<18> _18; + extern const _Placeholder<19> _19; + extern const _Placeholder<20> _20; + extern const _Placeholder<21> _21; + extern const _Placeholder<22> _22; + extern const _Placeholder<23> _23; + extern const _Placeholder<24> _24; + extern const _Placeholder<25> _25; + extern const _Placeholder<26> _26; + extern const _Placeholder<27> _27; + extern const _Placeholder<28> _28; + extern const _Placeholder<29> _29; + } + + /** + * Partial specialization of is_placeholder that provides the placeholder + * number for the placeholder objects defined by libstdc++. + * @ingroup binders + */ + template + struct is_placeholder<_Placeholder<_Num> > + : public integral_constant + { }; + + template + struct is_placeholder > + : public integral_constant + { }; + + + // Like tuple_element_t but SFINAE-friendly. + template + using _Safe_tuple_element_t + = typename enable_if<(__i < tuple_size<_Tuple>::value), + tuple_element<__i, _Tuple>>::type::type; + + /** + * Maps an argument to bind() into an actual argument to the bound + * function object [func.bind.bind]/10. Only the first parameter should + * be specified: the rest are used to determine among the various + * implementations. Note that, although this class is a function + * object, it isn't entirely normal because it takes only two + * parameters regardless of the number of parameters passed to the + * bind expression. The first parameter is the bound argument and + * the second parameter is a tuple containing references to the + * rest of the arguments. + */ + template::value, + bool _IsPlaceholder = (is_placeholder<_Arg>::value > 0)> + class _Mu; + + /** + * If the argument is reference_wrapper<_Tp>, returns the + * underlying reference. + * C++11 [func.bind.bind] p10 bullet 1. + */ + template + class _Mu, false, false> + { + public: + /* Note: This won't actually work for const volatile + * reference_wrappers, because reference_wrapper::get() is const + * but not volatile-qualified. This might be a defect in the TR. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp& + operator()(_CVRef& __arg, _Tuple&) const volatile + { return __arg.get(); } + }; + + /** + * If the argument is a bind expression, we invoke the underlying + * function object with the same cv-qualifiers as we are given and + * pass along all of our arguments (unwrapped). + * C++11 [func.bind.bind] p10 bullet 2. + */ + template + class _Mu<_Arg, true, false> + { + public: + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_CVArg& __arg, + tuple<_Args...>& __tuple) const volatile + -> decltype(__arg(declval<_Args>()...)) + { + // Construct an index tuple and forward to __call + typedef typename _Build_index_tuple::__type + _Indexes; + return this->__call(__arg, __tuple, _Indexes()); + } + + private: + // Invokes the underlying function object __arg by unpacking all + // of the arguments in the tuple. + template + _GLIBCXX20_CONSTEXPR + auto + __call(_CVArg& __arg, tuple<_Args...>& __tuple, + const _Index_tuple<_Indexes...>&) const volatile + -> decltype(__arg(declval<_Args>()...)) + { + return __arg(std::get<_Indexes>(std::move(__tuple))...); + } + }; + + /** + * If the argument is a placeholder for the Nth argument, returns + * a reference to the Nth argument to the bind function object. + * C++11 [func.bind.bind] p10 bullet 3. + */ + template + class _Mu<_Arg, false, true> + { + public: + template + _GLIBCXX20_CONSTEXPR + _Safe_tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>&& + operator()(const volatile _Arg&, _Tuple& __tuple) const volatile + { + return + ::std::get<(is_placeholder<_Arg>::value - 1)>(std::move(__tuple)); + } + }; + + /** + * If the argument is just a value, returns a reference to that + * value. The cv-qualifiers on the reference are determined by the caller. + * C++11 [func.bind.bind] p10 bullet 4. + */ + template + class _Mu<_Arg, false, false> + { + public: + template + _GLIBCXX20_CONSTEXPR + _CVArg&& + operator()(_CVArg&& __arg, _Tuple&) const volatile + { return std::forward<_CVArg>(__arg); } + }; + + // std::get for volatile-qualified tuples + template + inline auto + __volget(volatile tuple<_Tp...>& __tuple) + -> __tuple_element_t<_Ind, tuple<_Tp...>> volatile& + { return std::get<_Ind>(const_cast&>(__tuple)); } + + // std::get for const-volatile-qualified tuples + template + inline auto + __volget(const volatile tuple<_Tp...>& __tuple) + -> __tuple_element_t<_Ind, tuple<_Tp...>> const volatile& + { return std::get<_Ind>(const_cast&>(__tuple)); } + + /// Type of the function object returned from bind(). + template + struct _Bind; + + template + class _Bind<_Functor(_Bound_args...)> + : public _Weak_result_type<_Functor> + { + typedef typename _Build_index_tuple::__type + _Bound_indexes; + + _Functor _M_f; + tuple<_Bound_args...> _M_bound_args; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + _Result + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... + ); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + _Result + __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... + ); + } + + // Call as volatile + template + _Result + __call_v(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) volatile + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... + ); + } + + // Call as const volatile + template + _Result + __call_c_v(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) const volatile + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... + ); + } + + template + using _Mu_type = decltype( + _Mu::type>()( + std::declval<_BoundArg&>(), std::declval<_CallArgs&>()) ); + + template + using _Res_type_impl + = typename result_of< _Fn&(_Mu_type<_BArgs, _CallArgs>&&...) >::type; + + template + using _Res_type = _Res_type_impl<_Functor, _CallArgs, _Bound_args...>; + + template + using __dependent = typename + enable_if::value+1), _Functor>::type; + + template class __cv_quals> + using _Res_type_cv = _Res_type_impl< + typename __cv_quals<__dependent<_CallArgs>>::type, + _CallArgs, + typename __cv_quals<_Bound_args>::type...>; + + public: + template + explicit _GLIBCXX20_CONSTEXPR + _Bind(const _Functor& __f, _Args&&... __args) + : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) + { } + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind(_Functor&& __f, _Args&&... __args) + : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) + { } + + _Bind(const _Bind&) = default; + _Bind(_Bind&&) = default; + + // Call unqualified + template>> + _GLIBCXX20_CONSTEXPR + _Result + operator()(_Args&&... __args) + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const + template, add_const>> + _GLIBCXX20_CONSTEXPR + _Result + operator()(_Args&&... __args) const + { + return this->__call_c<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + +#if __cplusplus > 201402L +# define _GLIBCXX_DEPR_BIND \ + [[deprecated("std::bind does not support volatile in C++17")]] +#else +# define _GLIBCXX_DEPR_BIND +#endif + // Call as volatile + template, add_volatile>> + _GLIBCXX_DEPR_BIND + _Result + operator()(_Args&&... __args) volatile + { + return this->__call_v<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const volatile + template, add_cv>> + _GLIBCXX_DEPR_BIND + _Result + operator()(_Args&&... __args) const volatile + { + return this->__call_c_v<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + }; + + /// Type of the function object returned from bind(). + template + struct _Bind_result; + + template + class _Bind_result<_Result, _Functor(_Bound_args...)> + { + typedef typename _Build_index_tuple::__type + _Bound_indexes; + + _Functor _M_f; + tuple<_Bound_args...> _M_bound_args; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (std::get<_Indexes>(_M_bound_args), __args)...); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (std::get<_Indexes>(_M_bound_args), __args)...); + } + + // Call as volatile + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (__volget<_Indexes>(_M_bound_args), __args)...); + } + + // Call as const volatile + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) const volatile + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (__volget<_Indexes>(_M_bound_args), __args)...); + } + + public: + typedef _Result result_type; + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind_result(const _Functor& __f, _Args&&... __args) + : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) + { } + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind_result(_Functor&& __f, _Args&&... __args) + : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) + { } + + _Bind_result(const _Bind_result&) = default; + _Bind_result(_Bind_result&&) = default; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + result_type + operator()(_Args&&... __args) + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + result_type + operator()(_Args&&... __args) const + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as volatile + template + _GLIBCXX_DEPR_BIND + result_type + operator()(_Args&&... __args) volatile + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const volatile + template + _GLIBCXX_DEPR_BIND + result_type + operator()(_Args&&... __args) const volatile + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + }; +#undef _GLIBCXX_DEPR_BIND + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression<_Bind<_Signature> > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression<_Bind_result<_Result, _Signature>> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + template + struct _Bind_check_arity { }; + + template + struct _Bind_check_arity<_Ret (*)(_Args...), _BoundArgs...> + { + static_assert(sizeof...(_BoundArgs) == sizeof...(_Args), + "Wrong number of arguments for function"); + }; + + template + struct _Bind_check_arity<_Ret (*)(_Args......), _BoundArgs...> + { + static_assert(sizeof...(_BoundArgs) >= sizeof...(_Args), + "Wrong number of arguments for function"); + }; + + template + struct _Bind_check_arity<_Tp _Class::*, _BoundArgs...> + { + using _Arity = typename _Mem_fn<_Tp _Class::*>::_Arity; + using _Varargs = typename _Mem_fn<_Tp _Class::*>::_Varargs; + static_assert(_Varargs::value + ? sizeof...(_BoundArgs) >= _Arity::value + 1 + : sizeof...(_BoundArgs) == _Arity::value + 1, + "Wrong number of arguments for pointer-to-member"); + }; + + // Trait type used to remove std::bind() from overload set via SFINAE + // when first argument has integer type, so that std::bind() will + // not be a better match than ::bind() from the BSD Sockets API. + template::type> + using __is_socketlike = __or_, is_enum<_Tp2>>; + + template + struct _Bind_helper + : _Bind_check_arity::type, _BoundArgs...> + { + typedef typename decay<_Func>::type __func_type; + typedef _Bind<__func_type(typename decay<_BoundArgs>::type...)> type; + }; + + // Partial specialization for is_socketlike == true, does not define + // nested type so std::bind() will not participate in overload resolution + // when the first argument might be a socket file descriptor. + template + struct _Bind_helper + { }; + + /** + * @brief Function template for std::bind. + * @ingroup binders + */ + template + inline _GLIBCXX20_CONSTEXPR typename + _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type + bind(_Func&& __f, _BoundArgs&&... __args) + { + typedef _Bind_helper __helper_type; + return typename __helper_type::type(std::forward<_Func>(__f), + std::forward<_BoundArgs>(__args)...); + } + + template + struct _Bindres_helper + : _Bind_check_arity::type, _BoundArgs...> + { + typedef typename decay<_Func>::type __functor_type; + typedef _Bind_result<_Result, + __functor_type(typename decay<_BoundArgs>::type...)> + type; + }; + + /** + * @brief Function template for std::bind. + * @ingroup binders + */ + template + inline _GLIBCXX20_CONSTEXPR + typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type + bind(_Func&& __f, _BoundArgs&&... __args) + { + typedef _Bindres_helper<_Result, _Func, _BoundArgs...> __helper_type; + return typename __helper_type::type(std::forward<_Func>(__f), + std::forward<_BoundArgs>(__args)...); + } + +#if __cplusplus > 201703L +#define __cpp_lib_bind_front 201907L + + template + struct _Bind_front + { + static_assert(is_move_constructible_v<_Fd>); + static_assert((is_move_constructible_v<_BoundArgs> && ...)); + + // First parameter is to ensure this constructor is never used + // instead of the copy/move constructor. + template + explicit constexpr + _Bind_front(int, _Fn&& __fn, _Args&&... __args) + noexcept(__and_, + is_nothrow_constructible<_BoundArgs, _Args>...>::value) + : _M_fd(std::forward<_Fn>(__fn)), + _M_bound_args(std::forward<_Args>(__args)...) + { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); } + + _Bind_front(const _Bind_front&) = default; + _Bind_front(_Bind_front&&) = default; + _Bind_front& operator=(const _Bind_front&) = default; + _Bind_front& operator=(_Bind_front&&) = default; + ~_Bind_front() = default; + + template + constexpr + invoke_result_t<_Fd&, _BoundArgs&..., _CallArgs...> + operator()(_CallArgs&&... __call_args) & + noexcept(is_nothrow_invocable_v<_Fd&, _BoundArgs&..., _CallArgs...>) + { + return _S_call(*this, _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + constexpr + invoke_result_t + operator()(_CallArgs&&... __call_args) const & + noexcept(is_nothrow_invocable_v) + { + return _S_call(*this, _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + constexpr + invoke_result_t<_Fd, _BoundArgs..., _CallArgs...> + operator()(_CallArgs&&... __call_args) && + noexcept(is_nothrow_invocable_v<_Fd, _BoundArgs..., _CallArgs...>) + { + return _S_call(std::move(*this), _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + constexpr + invoke_result_t + operator()(_CallArgs&&... __call_args) const && + noexcept(is_nothrow_invocable_v) + { + return _S_call(std::move(*this), _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + private: + using _BoundIndices = index_sequence_for<_BoundArgs...>; + + template + static constexpr + decltype(auto) + _S_call(_Tp&& __g, index_sequence<_Ind...>, _CallArgs&&... __call_args) + { + return std::invoke(std::forward<_Tp>(__g)._M_fd, + std::get<_Ind>(std::forward<_Tp>(__g)._M_bound_args)..., + std::forward<_CallArgs>(__call_args)...); + } + + _Fd _M_fd; + std::tuple<_BoundArgs...> _M_bound_args; + }; + + template + using _Bind_front_t + = _Bind_front, decay_t<_Args>...>; + + template + constexpr _Bind_front_t<_Fn, _Args...> + bind_front(_Fn&& __fn, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Bind_front_t<_Fn, _Args...>, + int, _Fn, _Args...>) + { + return _Bind_front_t<_Fn, _Args...>(0, std::forward<_Fn>(__fn), + std::forward<_Args>(__args)...); + } +#endif + +#if __cplusplus >= 201402L + /// Generalized negator. + template + class _Not_fn + { + template + using __inv_res_t = typename __invoke_result<_Fn2, _Args...>::type; + + template + static decltype(!std::declval<_Tp>()) + _S_not() noexcept(noexcept(!std::declval<_Tp>())); + + public: + template + constexpr + _Not_fn(_Fn2&& __fn, int) + : _M_fn(std::forward<_Fn2>(__fn)) { } + + _Not_fn(const _Not_fn& __fn) = default; + _Not_fn(_Not_fn&& __fn) = default; + ~_Not_fn() = default; + + // Macro to define operator() with given cv-qualifiers ref-qualifiers, + // forwarding _M_fn and the function arguments with the same qualifiers, + // and deducing the return type and exception-specification. +#define _GLIBCXX_NOT_FN_CALL_OP( _QUALS ) \ + template \ + _GLIBCXX20_CONSTEXPR \ + decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()) \ + operator()(_Args&&... __args) _QUALS \ + noexcept(__is_nothrow_invocable<_Fn _QUALS, _Args...>::value \ + && noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())) \ + { \ + return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn), \ + std::forward<_Args>(__args)...); \ + } + _GLIBCXX_NOT_FN_CALL_OP( & ) + _GLIBCXX_NOT_FN_CALL_OP( const & ) + _GLIBCXX_NOT_FN_CALL_OP( && ) + _GLIBCXX_NOT_FN_CALL_OP( const && ) +#undef _GLIBCXX_NOT_FN_CALL_OP + + private: + _Fn _M_fn; + }; + + template + struct __is_byte_like : false_type { }; + + template + struct __is_byte_like<_Tp, equal_to<_Tp>> + : __bool_constant::value> { }; + + template + struct __is_byte_like<_Tp, equal_to> + : __bool_constant::value> { }; + +#if __cplusplus >= 201703L + // Declare std::byte (full definition is in ). + enum class byte : unsigned char; + + template<> + struct __is_byte_like> + : true_type { }; + + template<> + struct __is_byte_like> + : true_type { }; + +#define __cpp_lib_not_fn 201603 + /// [func.not_fn] Function template not_fn + template + _GLIBCXX20_CONSTEXPR + inline auto + not_fn(_Fn&& __fn) + noexcept(std::is_nothrow_constructible, _Fn&&>::value) + { + return _Not_fn>{std::forward<_Fn>(__fn), 0}; + } + + // Searchers +#define __cpp_lib_boyer_moore_searcher 201603 + + template> + class default_searcher + { + public: + _GLIBCXX20_CONSTEXPR + default_searcher(_ForwardIterator1 __pat_first, + _ForwardIterator1 __pat_last, + _BinaryPredicate __pred = _BinaryPredicate()) + : _M_m(__pat_first, __pat_last, std::move(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + pair<_ForwardIterator2, _ForwardIterator2> + operator()(_ForwardIterator2 __first, _ForwardIterator2 __last) const + { + _ForwardIterator2 __first_ret = + std::search(__first, __last, std::get<0>(_M_m), std::get<1>(_M_m), + std::get<2>(_M_m)); + auto __ret = std::make_pair(__first_ret, __first_ret); + if (__ret.first != __last) + std::advance(__ret.second, std::distance(std::get<0>(_M_m), + std::get<1>(_M_m))); + return __ret; + } + + private: + tuple<_ForwardIterator1, _ForwardIterator1, _BinaryPredicate> _M_m; + }; + + template + struct __boyer_moore_map_base + { + template + __boyer_moore_map_base(_RAIter __pat, size_t __patlen, + _Hash&& __hf, _Pred&& __pred) + : _M_bad_char{ __patlen, std::move(__hf), std::move(__pred) } + { + if (__patlen > 0) + for (__diff_type __i = 0; __i < __patlen - 1; ++__i) + _M_bad_char[__pat[__i]] = __patlen - 1 - __i; + } + + using __diff_type = _Tp; + + __diff_type + _M_lookup(_Key __key, __diff_type __not_found) const + { + auto __iter = _M_bad_char.find(__key); + if (__iter == _M_bad_char.end()) + return __not_found; + return __iter->second; + } + + _Pred + _M_pred() const { return _M_bad_char.key_eq(); } + + _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred> _M_bad_char; + }; + + template + struct __boyer_moore_array_base + { + template + __boyer_moore_array_base(_RAIter __pat, size_t __patlen, + _Unused&&, _Pred&& __pred) + : _M_bad_char{ _GLIBCXX_STD_C::array<_Tp, _Len>{}, std::move(__pred) } + { + std::get<0>(_M_bad_char).fill(__patlen); + if (__patlen > 0) + for (__diff_type __i = 0; __i < __patlen - 1; ++__i) + { + auto __ch = __pat[__i]; + using _UCh = make_unsigned_t; + auto __uch = static_cast<_UCh>(__ch); + std::get<0>(_M_bad_char)[__uch] = __patlen - 1 - __i; + } + } + + using __diff_type = _Tp; + + template + __diff_type + _M_lookup(_Key __key, __diff_type __not_found) const + { + auto __ukey = static_cast>(__key); + if (__ukey >= _Len) + return __not_found; + return std::get<0>(_M_bad_char)[__ukey]; + } + + const _Pred& + _M_pred() const { return std::get<1>(_M_bad_char); } + + tuple<_GLIBCXX_STD_C::array<_Tp, _Len>, _Pred> _M_bad_char; + }; + + // Use __boyer_moore_array_base when pattern consists of narrow characters + // (or std::byte) and uses std::equal_to as the predicate. + template::value_type, + typename _Diff = typename iterator_traits<_RAIter>::difference_type> + using __boyer_moore_base_t + = conditional_t<__is_byte_like<_Val, _Pred>::value, + __boyer_moore_array_base<_Diff, 256, _Pred>, + __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>; + + template::value_type>, + typename _BinaryPredicate = equal_to<>> + class boyer_moore_searcher + : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate> + { + using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>; + using typename _Base::__diff_type; + + public: + boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last, + _Hash __hf = _Hash(), + _BinaryPredicate __pred = _BinaryPredicate()); + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const; + + private: + bool + _M_is_prefix(_RAIter __word, __diff_type __len, + __diff_type __pos) + { + const auto& __pred = this->_M_pred(); + __diff_type __suffixlen = __len - __pos; + for (__diff_type __i = 0; __i < __suffixlen; ++__i) + if (!__pred(__word[__i], __word[__pos + __i])) + return false; + return true; + } + + __diff_type + _M_suffix_length(_RAIter __word, __diff_type __len, + __diff_type __pos) + { + const auto& __pred = this->_M_pred(); + __diff_type __i = 0; + while (__pred(__word[__pos - __i], __word[__len - 1 - __i]) + && __i < __pos) + { + ++__i; + } + return __i; + } + + template + __diff_type + _M_bad_char_shift(_Tp __c) const + { return this->_M_lookup(__c, _M_pat_end - _M_pat); } + + _RAIter _M_pat; + _RAIter _M_pat_end; + _GLIBCXX_STD_C::vector<__diff_type> _M_good_suffix; + }; + + template::value_type>, + typename _BinaryPredicate = equal_to<>> + class boyer_moore_horspool_searcher + : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate> + { + using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>; + using typename _Base::__diff_type; + + public: + boyer_moore_horspool_searcher(_RAIter __pat, + _RAIter __pat_end, + _Hash __hf = _Hash(), + _BinaryPredicate __pred + = _BinaryPredicate()) + : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)), + _M_pat(__pat), _M_pat_end(__pat_end) + { } + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const + { + const auto& __pred = this->_M_pred(); + auto __patlen = _M_pat_end - _M_pat; + if (__patlen == 0) + return std::make_pair(__first, __first); + auto __len = __last - __first; + while (__len >= __patlen) + { + for (auto __scan = __patlen - 1; + __pred(__first[__scan], _M_pat[__scan]); --__scan) + if (__scan == 0) + return std::make_pair(__first, __first + __patlen); + auto __shift = _M_bad_char_shift(__first[__patlen - 1]); + __len -= __shift; + __first += __shift; + } + return std::make_pair(__last, __last); + } + + private: + template + __diff_type + _M_bad_char_shift(_Tp __c) const + { return this->_M_lookup(__c, _M_pat_end - _M_pat); } + + _RAIter _M_pat; + _RAIter _M_pat_end; + }; + + template + boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>:: + boyer_moore_searcher(_RAIter __pat, _RAIter __pat_end, + _Hash __hf, _BinaryPredicate __pred) + : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)), + _M_pat(__pat), _M_pat_end(__pat_end), _M_good_suffix(__pat_end - __pat) + { + auto __patlen = __pat_end - __pat; + if (__patlen == 0) + return; + __diff_type __last_prefix = __patlen - 1; + for (__diff_type __p = __patlen - 1; __p >= 0; --__p) + { + if (_M_is_prefix(__pat, __patlen, __p + 1)) + __last_prefix = __p + 1; + _M_good_suffix[__p] = __last_prefix + (__patlen - 1 - __p); + } + for (__diff_type __p = 0; __p < __patlen - 1; ++__p) + { + auto __slen = _M_suffix_length(__pat, __patlen, __p); + auto __pos = __patlen - 1 - __slen; + if (!__pred(__pat[__p - __slen], __pat[__pos])) + _M_good_suffix[__pos] = __patlen - 1 - __p + __slen; + } + } + + template + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>:: + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const + { + auto __patlen = _M_pat_end - _M_pat; + if (__patlen == 0) + return std::make_pair(__first, __first); + const auto& __pred = this->_M_pred(); + __diff_type __i = __patlen - 1; + auto __stringlen = __last - __first; + while (__i < __stringlen) + { + __diff_type __j = __patlen - 1; + while (__j >= 0 && __pred(__first[__i], _M_pat[__j])) + { + --__i; + --__j; + } + if (__j < 0) + { + const auto __match = __first + __i + 1; + return std::make_pair(__match, __match + __patlen); + } + __i += std::max(_M_bad_char_shift(__first[__i]), + _M_good_suffix[__j]); + } + return std::make_pair(__last, __last); + } + +#endif // C++17 +#endif // C++14 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_FUNCTIONAL diff --git a/resources/sources/avr-libstdcpp/include/initializer_list b/resources/sources/avr-libstdcpp/include/initializer_list new file mode 100644 index 000000000..9f4859514 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/initializer_list @@ -0,0 +1,109 @@ +// std::initializer_list support -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file initializer_list + * This is a Standard C++ Library header. + */ + +#ifndef _INITIALIZER_LIST +#define _INITIALIZER_LIST + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else // C++0x + +#pragma GCC visibility push(default) + +#include + +namespace std +{ + /// initializer_list + template + class initializer_list + { + public: + typedef _E value_type; + typedef const _E& reference; + typedef const _E& const_reference; + typedef size_t size_type; + typedef const _E* iterator; + typedef const _E* const_iterator; + + private: + iterator _M_array; + size_type _M_len; + + // The compiler can call a private constructor. + constexpr initializer_list(const_iterator __a, size_type __l) + : _M_array(__a), _M_len(__l) { } + + public: + constexpr initializer_list() noexcept + : _M_array(0), _M_len(0) { } + + // Number of elements. + constexpr size_type + size() const noexcept { return _M_len; } + + // First element. + constexpr const_iterator + begin() const noexcept { return _M_array; } + + // One past the last element. + constexpr const_iterator + end() const noexcept { return begin() + size(); } + }; + + /** + * @brief Return an iterator pointing to the first element of + * the initializer_list. + * @param __ils Initializer list. + * @relates initializer_list + */ + template + constexpr const _Tp* + begin(initializer_list<_Tp> __ils) noexcept + { return __ils.begin(); } + + /** + * @brief Return an iterator pointing to one past the last element + * of the initializer_list. + * @param __ils Initializer list. + * @relates initializer_list + */ + template + constexpr const _Tp* + end(initializer_list<_Tp> __ils) noexcept + { return __ils.end(); } +} + +#pragma GCC visibility pop + +#endif // C++11 + +#endif // _INITIALIZER_LIST diff --git a/resources/sources/avr-libstdcpp/include/iterator b/resources/sources/avr-libstdcpp/include/iterator new file mode 100644 index 000000000..fbc47e01e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/iterator @@ -0,0 +1,70 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/iterator + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ITERATOR +#define _GLIBCXX_ITERATOR 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201402L && ! defined _GLIBCXX_DEBUG // PR libstdc++/70303 +# define __cpp_lib_null_iterators 201304L +#endif + +#endif /* _GLIBCXX_ITERATOR */ diff --git a/resources/sources/avr-libstdcpp/include/limits b/resources/sources/avr-libstdcpp/include/limits new file mode 100644 index 000000000..898406f91 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/limits @@ -0,0 +1,1893 @@ +// The template and inlines for the numeric_limits classes. -*- C++ -*- + +// Copyright (C) 1999-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/limits + * This is a Standard C++ Library header. + */ + +// Note: this is not a conforming implementation. +// Written by Gabriel Dos Reis + +// +// ISO 14882:1998 +// 18.2.1 +// + +#ifndef _GLIBCXX_NUMERIC_LIMITS +#define _GLIBCXX_NUMERIC_LIMITS 1 + +#pragma GCC system_header + +#include + +// +// The numeric_limits<> traits document implementation-defined aspects +// of fundamental arithmetic data types (integers and floating points). +// From Standard C++ point of view, there are 14 such types: +// * integers +// bool (1) +// char, signed char, unsigned char, wchar_t (4) +// short, unsigned short (2) +// int, unsigned (2) +// long, unsigned long (2) +// +// * floating points +// float (1) +// double (1) +// long double (1) +// +// GNU C++ understands (where supported by the host C-library) +// * integer +// long long, unsigned long long (2) +// +// which brings us to 16 fundamental arithmetic data types in GNU C++. +// +// +// Since a numeric_limits<> is a bit tricky to get right, we rely on +// an interface composed of macros which should be defined in config/os +// or config/cpu when they differ from the generic (read arbitrary) +// definitions given here. +// + +// These values can be overridden in the target configuration file. +// The default values are appropriate for many 32-bit targets. + +// GCC only intrinsically supports modulo integral types. The only remaining +// integral exceptional values is division by zero. Only targets that do not +// signal division by zero in some "hard to ignore" way should use false. +#ifndef __glibcxx_integral_traps +# define __glibcxx_integral_traps true +#endif + +// float +// + +// Default values. Should be overridden in configuration files if necessary. + +#ifndef __glibcxx_float_has_denorm_loss +# define __glibcxx_float_has_denorm_loss false +#endif +#ifndef __glibcxx_float_traps +# define __glibcxx_float_traps false +#endif +#ifndef __glibcxx_float_tinyness_before +# define __glibcxx_float_tinyness_before false +#endif + +// double + +// Default values. Should be overridden in configuration files if necessary. + +#ifndef __glibcxx_double_has_denorm_loss +# define __glibcxx_double_has_denorm_loss false +#endif +#ifndef __glibcxx_double_traps +# define __glibcxx_double_traps false +#endif +#ifndef __glibcxx_double_tinyness_before +# define __glibcxx_double_tinyness_before false +#endif + +// long double + +// Default values. Should be overridden in configuration files if necessary. + +#ifndef __glibcxx_long_double_has_denorm_loss +# define __glibcxx_long_double_has_denorm_loss false +#endif +#ifndef __glibcxx_long_double_traps +# define __glibcxx_long_double_traps false +#endif +#ifndef __glibcxx_long_double_tinyness_before +# define __glibcxx_long_double_tinyness_before false +#endif + +// You should not need to define any macros below this point. + +#define __glibcxx_signed_b(T,B) ((T)(-1) < 0) + +#define __glibcxx_min_b(T,B) \ + (__glibcxx_signed_b (T,B) ? -__glibcxx_max_b (T,B) - 1 : (T)0) + +#define __glibcxx_max_b(T,B) \ + (__glibcxx_signed_b (T,B) ? \ + (((((T)1 << (__glibcxx_digits_b (T,B) - 1)) - 1) << 1) + 1) : ~(T)0) + +#define __glibcxx_digits_b(T,B) \ + (B - __glibcxx_signed_b (T,B)) + +// The fraction 643/2136 approximates log10(2) to 7 significant digits. +#define __glibcxx_digits10_b(T,B) \ + (__glibcxx_digits_b (T,B) * 643L / 2136) + +#define __glibcxx_signed(T) \ + __glibcxx_signed_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_min(T) \ + __glibcxx_min_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_max(T) \ + __glibcxx_max_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_digits(T) \ + __glibcxx_digits_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_digits10(T) \ + __glibcxx_digits10_b (T, sizeof(T) * __CHAR_BIT__) + +#define __glibcxx_max_digits10(T) \ + (2 + (T) * 643L / 2136) + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Describes the rounding style for floating-point types. + * + * This is used in the std::numeric_limits class. + */ + enum float_round_style + { + round_indeterminate = -1, /// Intermediate. + round_toward_zero = 0, /// To zero. + round_to_nearest = 1, /// To the nearest representable value. + round_toward_infinity = 2, /// To infinity. + round_toward_neg_infinity = 3 /// To negative infinity. + }; + + /** + * @brief Describes the denormalization for floating-point types. + * + * These values represent the presence or absence of a variable number + * of exponent bits. This type is used in the std::numeric_limits class. + */ + enum float_denorm_style + { + /// Indeterminate at compile time whether denormalized values are allowed. + denorm_indeterminate = -1, + /// The type does not allow denormalized values. + denorm_absent = 0, + /// The type allows denormalized values. + denorm_present = 1 + }; + + /** + * @brief Part of std::numeric_limits. + * + * The @c static @c const members are usable as integral constant + * expressions. + * + * @note This is a separate class for purposes of efficiency; you + * should only access these members as part of an instantiation + * of the std::numeric_limits class. + */ + struct __numeric_limits_base + { + /** This will be true for all fundamental types (which have + specializations), and false for everything else. */ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = false; + + /** The number of @c radix digits that be represented without change: for + integer types, the number of non-sign bits in the mantissa; for + floating types, the number of @c radix digits in the mantissa. */ + static _GLIBCXX_USE_CONSTEXPR int digits = 0; + + /** The number of base 10 digits that can be represented without change. */ + static _GLIBCXX_USE_CONSTEXPR int digits10 = 0; + +#if __cplusplus >= 201103L + /** The number of base 10 digits required to ensure that values which + differ are always differentiated. */ + static constexpr int max_digits10 = 0; +#endif + + /** True if the type is signed. */ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + + /** True if the type is integer. */ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + + /** True if the type uses an exact representation. All integer types are + exact, but not all exact types are integer. For example, rational and + fixed-exponent representations are exact but not integer. */ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + + /** For integer types, specifies the base of the representation. For + floating types, specifies the base of the exponent representation. */ + static _GLIBCXX_USE_CONSTEXPR int radix = 0; + + /** The minimum negative integer such that @c radix raised to the power of + (one less than that integer) is a normalized floating point number. */ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + + /** The minimum negative integer such that 10 raised to that power is in + the range of normalized floating point numbers. */ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + + /** The maximum positive integer such that @c radix raised to the power of + (one less than that integer) is a representable finite floating point + number. */ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + + /** The maximum positive integer such that 10 raised to that power is in + the range of representable finite floating point numbers. */ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + /** True if the type has a representation for positive infinity. */ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + + /** True if the type has a representation for a quiet (non-signaling) + Not a Number. */ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + + /** True if the type has a representation for a signaling + Not a Number. */ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + + /** See std::float_denorm_style for more information. */ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + + /** True if loss of accuracy is detected as a denormalization loss, + rather than as an inexact result. */ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + /** True if-and-only-if the type adheres to the IEC 559 standard, also + known as IEEE 754. (Only makes sense for floating point types.) */ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + + /** True if the set of values representable by the type is + finite. All built-in types are bounded, this member would be + false for arbitrary precision types. */ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = false; + + /** True if the type is @e modulo. A type is modulo if, for any + operation involving +, -, or * on values of that type whose + result would fall outside the range [min(),max()], the value + returned differs from the true value by an integer multiple of + max() - min() + 1. On most machines, this is false for floating + types, true for unsigned integers, and true for signed integers. + See PR22200 about signed integers. */ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + /** True if trapping is implemented for this type. */ + static _GLIBCXX_USE_CONSTEXPR bool traps = false; + + /** True if tininess is detected before rounding. (see IEC 559) */ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + + /** See std::float_round_style for more information. This is only + meaningful for floating types; integer types will all be + round_toward_zero. */ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = + round_toward_zero; + }; + + /** + * @brief Properties of fundamental types. + * + * This class allows a program to obtain information about the + * representation of a fundamental type on a given platform. For + * non-fundamental types, the functions will return 0 and the data + * members will all be @c false. + */ + template + struct numeric_limits : public __numeric_limits_base + { + /** The minimum finite value, or for floating types with + denormalization, the minimum positive normalized value. */ + static _GLIBCXX_CONSTEXPR _Tp + min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The maximum finite value. */ + static _GLIBCXX_CONSTEXPR _Tp + max() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + +#if __cplusplus >= 201103L + /** A finite value x such that there is no other finite value y + * where y < x. */ + static constexpr _Tp + lowest() noexcept { return _Tp(); } +#endif + + /** The @e machine @e epsilon: the difference between 1 and the least + value greater than 1 that is representable. */ + static _GLIBCXX_CONSTEXPR _Tp + epsilon() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The maximum rounding error measurement (see LIA-1). */ + static _GLIBCXX_CONSTEXPR _Tp + round_error() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of positive infinity, if @c has_infinity. */ + static _GLIBCXX_CONSTEXPR _Tp + infinity() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of a quiet Not a Number, + if @c has_quiet_NaN. */ + static _GLIBCXX_CONSTEXPR _Tp + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of a signaling Not a Number, if + @c has_signaling_NaN. */ + static _GLIBCXX_CONSTEXPR _Tp + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The minimum positive denormalized value. For types where + @c has_denorm is false, this is the minimum positive normalized + value. */ + static _GLIBCXX_CONSTEXPR _Tp + denorm_min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 559. numeric_limits + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + // Now there follow 16 explicit specializations. Yes, 16. Make sure + // you get the count right. (18 in C++11 mode, with char16_t and char32_t.) + // (+1 if char8_t is enabled.) + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 184. numeric_limits wording problems + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR bool + min() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + max() _GLIBCXX_USE_NOEXCEPT { return true; } + +#if __cplusplus >= 201103L + static constexpr bool + lowest() noexcept { return min(); } +#endif + static _GLIBCXX_USE_CONSTEXPR int digits = 1; + static _GLIBCXX_USE_CONSTEXPR int digits10 = 0; +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR bool + epsilon() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + round_error() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR bool + infinity() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + denorm_min() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + // It is not clear what it means for a boolean type to trap. + // This is a DR on the LWG issue list. Here, I use integer + // promotion semantics. + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR char + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min(char); } + + static _GLIBCXX_CONSTEXPR char + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max(char); } + +#if __cplusplus >= 201103L + static constexpr char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR + char infinity() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR signed char + min() _GLIBCXX_USE_NOEXCEPT { return -__SCHAR_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR signed char + max() _GLIBCXX_USE_NOEXCEPT { return __SCHAR_MAX__; } + +#if __cplusplus >= 201103L + static constexpr signed char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (signed char); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (signed char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR signed char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR signed char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR signed char + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned char + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned char + max() _GLIBCXX_USE_NOEXCEPT { return __SCHAR_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned char); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned char + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR wchar_t + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (wchar_t); } + + static _GLIBCXX_CONSTEXPR wchar_t + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (wchar_t); } + +#if __cplusplus >= 201103L + static constexpr wchar_t + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (wchar_t); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (wchar_t); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (wchar_t); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR wchar_t + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR wchar_t + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR wchar_t + infinity() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + denorm_min() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + +#if _GLIBCXX_USE_CHAR8_T + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR char8_t + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (char8_t); } + + static _GLIBCXX_CONSTEXPR char8_t + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (char8_t); } + + static _GLIBCXX_CONSTEXPR char8_t + lowest() _GLIBCXX_USE_NOEXCEPT { return min(); } + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char8_t); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char8_t); + static _GLIBCXX_USE_CONSTEXPR int max_digits10 = 0; + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char8_t); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR char8_t + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR char8_t + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR char8_t + infinity() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + denorm_min() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; +#endif + +#if __cplusplus >= 201103L + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static constexpr bool is_specialized = true; + + static constexpr char16_t + min() noexcept { return __glibcxx_min (char16_t); } + + static constexpr char16_t + max() noexcept { return __glibcxx_max (char16_t); } + + static constexpr char16_t + lowest() noexcept { return min(); } + + static constexpr int digits = __glibcxx_digits (char16_t); + static constexpr int digits10 = __glibcxx_digits10 (char16_t); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = __glibcxx_signed (char16_t); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr char16_t + epsilon() noexcept { return 0; } + + static constexpr char16_t + round_error() noexcept { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr char16_t + infinity() noexcept { return char16_t(); } + + static constexpr char16_t + quiet_NaN() noexcept { return char16_t(); } + + static constexpr char16_t + signaling_NaN() noexcept { return char16_t(); } + + static constexpr char16_t + denorm_min() noexcept { return char16_t(); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = !is_signed; + + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static constexpr bool is_specialized = true; + + static constexpr char32_t + min() noexcept { return __glibcxx_min (char32_t); } + + static constexpr char32_t + max() noexcept { return __glibcxx_max (char32_t); } + + static constexpr char32_t + lowest() noexcept { return min(); } + + static constexpr int digits = __glibcxx_digits (char32_t); + static constexpr int digits10 = __glibcxx_digits10 (char32_t); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = __glibcxx_signed (char32_t); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr char32_t + epsilon() noexcept { return 0; } + + static constexpr char32_t + round_error() noexcept { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr char32_t + infinity() noexcept { return char32_t(); } + + static constexpr char32_t + quiet_NaN() noexcept { return char32_t(); } + + static constexpr char32_t + signaling_NaN() noexcept { return char32_t(); } + + static constexpr char32_t + denorm_min() noexcept { return char32_t(); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = !is_signed; + + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + }; +#endif + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR short + min() _GLIBCXX_USE_NOEXCEPT { return -__SHRT_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR short + max() _GLIBCXX_USE_NOEXCEPT { return __SHRT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr short + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (short); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (short); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR short + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR short + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR short + infinity() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + denorm_min() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned short + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned short + max() _GLIBCXX_USE_NOEXCEPT { return __SHRT_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned short + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned short); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned short); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned short + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned short + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned short + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR int + min() _GLIBCXX_USE_NOEXCEPT { return -__INT_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR int + max() _GLIBCXX_USE_NOEXCEPT { return __INT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr int + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (int); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (int); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR int + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR int + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR int + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned int + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned int + max() _GLIBCXX_USE_NOEXCEPT { return __INT_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned int + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned int); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned int); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned int + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned int + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned int + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long + min() _GLIBCXX_USE_NOEXCEPT { return -__LONG_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (long); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR long + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned long + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__ * 2UL + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned long + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long long + min() _GLIBCXX_USE_NOEXCEPT { return -__LONG_LONG_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR long long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_LONG_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (long long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (long long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR long long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR long long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR long long + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned long long + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_LONG_MAX__ * 2ULL + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned long long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned long long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned long long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned long long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned long long + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + +#if !defined(__STRICT_ANSI__) + +#define __INT_N(TYPE, BITSIZE, EXT, UEXT) \ + template<> \ + struct numeric_limits \ + { \ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min_b (TYPE, BITSIZE); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max_b (TYPE, BITSIZE); } \ + \ + static _GLIBCXX_USE_CONSTEXPR int digits \ + = BITSIZE - 1; \ + static _GLIBCXX_USE_CONSTEXPR int digits10 \ + = (BITSIZE - 1) * 643L / 2136; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; \ + static _GLIBCXX_USE_CONSTEXPR int radix = 2; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + EXT \ + \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ + = denorm_absent; \ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + infinity() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + denorm_min() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool traps \ + = __glibcxx_integral_traps; \ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ + = round_toward_zero; \ + }; \ + \ + template<> \ + struct numeric_limits \ + { \ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + min() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + max() _GLIBCXX_USE_NOEXCEPT \ + { return __glibcxx_max_b (unsigned TYPE, BITSIZE); } \ + \ + UEXT \ + \ + static _GLIBCXX_USE_CONSTEXPR int digits \ + = BITSIZE; \ + static _GLIBCXX_USE_CONSTEXPR int digits10 \ + = BITSIZE * 643L / 2136; \ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; \ + static _GLIBCXX_USE_CONSTEXPR int radix = 2; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ + = denorm_absent; \ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + infinity() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + denorm_min() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; \ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ + = round_toward_zero; \ + }; + +#if __cplusplus >= 201103L + +#define __INT_N_201103(TYPE) \ + static constexpr TYPE \ + lowest() noexcept { return min(); } \ + static constexpr int max_digits10 = 0; + +#define __INT_N_U201103(TYPE) \ + static constexpr unsigned TYPE \ + lowest() noexcept { return min(); } \ + static constexpr int max_digits10 = 0; + +#else +#define __INT_N_201103(TYPE) +#define __INT_N_U201103(TYPE) +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_0 + __INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_0), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_0)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 + __INT_N (__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_1), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_1)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 + __INT_N (__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_2), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_2)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 + __INT_N (__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_3), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3)) +#endif + +#undef __INT_N +#undef __INT_N_201103 +#undef __INT_N_U201103 + +#endif + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR float + min() _GLIBCXX_USE_NOEXCEPT { return __FLT_MIN__; } + + static _GLIBCXX_CONSTEXPR float + max() _GLIBCXX_USE_NOEXCEPT { return __FLT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr float + lowest() noexcept { return -__FLT_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __FLT_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __FLT_DIG__; +#if __cplusplus >= 201103L + static constexpr int max_digits10 + = __glibcxx_max_digits10 (__FLT_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR float + epsilon() _GLIBCXX_USE_NOEXCEPT { return __FLT_EPSILON__; } + + static _GLIBCXX_CONSTEXPR float + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5F; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __FLT_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __FLT_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __FLT_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __FLT_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __FLT_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __FLT_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__FLT_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_float_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR float + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_valf(); } + + static _GLIBCXX_CONSTEXPR float + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nanf(""); } + + static _GLIBCXX_CONSTEXPR float + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nansf(""); } + + static _GLIBCXX_CONSTEXPR float + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __FLT_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_float_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before + = __glibcxx_float_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_to_nearest; + }; + +#undef __glibcxx_float_has_denorm_loss +#undef __glibcxx_float_traps +#undef __glibcxx_float_tinyness_before + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR double + min() _GLIBCXX_USE_NOEXCEPT { return __DBL_MIN__; } + + static _GLIBCXX_CONSTEXPR double + max() _GLIBCXX_USE_NOEXCEPT { return __DBL_MAX__; } + +#if __cplusplus >= 201103L + static constexpr double + lowest() noexcept { return -__DBL_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __DBL_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __DBL_DIG__; +#if __cplusplus >= 201103L + static constexpr int max_digits10 + = __glibcxx_max_digits10 (__DBL_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR double + epsilon() _GLIBCXX_USE_NOEXCEPT { return __DBL_EPSILON__; } + + static _GLIBCXX_CONSTEXPR double + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __DBL_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __DBL_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __DBL_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __DBL_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __DBL_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__DBL_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_double_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR double + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_val(); } + + static _GLIBCXX_CONSTEXPR double + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nan(""); } + + static _GLIBCXX_CONSTEXPR double + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nans(""); } + + static _GLIBCXX_CONSTEXPR double + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __DBL_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_double_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before + = __glibcxx_double_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_to_nearest; + }; + +#undef __glibcxx_double_has_denorm_loss +#undef __glibcxx_double_traps +#undef __glibcxx_double_tinyness_before + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long double + min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_MIN__; } + + static _GLIBCXX_CONSTEXPR long double + max() _GLIBCXX_USE_NOEXCEPT { return __LDBL_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long double + lowest() noexcept { return -__LDBL_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __LDBL_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __LDBL_DIG__; +#if __cplusplus >= 201103L + static _GLIBCXX_USE_CONSTEXPR int max_digits10 + = __glibcxx_max_digits10 (__LDBL_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR long double + epsilon() _GLIBCXX_USE_NOEXCEPT { return __LDBL_EPSILON__; } + + static _GLIBCXX_CONSTEXPR long double + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5L; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __LDBL_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __LDBL_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __LDBL_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __LDBL_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __LDBL_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __LDBL_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__LDBL_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_long_double_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR long double + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_vall(); } + + static _GLIBCXX_CONSTEXPR long double + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nanl(""); } + + static _GLIBCXX_CONSTEXPR long double + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nansl(""); } + + static _GLIBCXX_CONSTEXPR long double + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_long_double_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = + __glibcxx_long_double_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = + round_to_nearest; + }; + +#undef __glibcxx_long_double_has_denorm_loss +#undef __glibcxx_long_double_traps +#undef __glibcxx_long_double_tinyness_before + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#undef __glibcxx_signed +#undef __glibcxx_min +#undef __glibcxx_max +#undef __glibcxx_digits +#undef __glibcxx_digits10 +#undef __glibcxx_max_digits10 + +#endif // _GLIBCXX_NUMERIC_LIMITS diff --git a/resources/sources/avr-libstdcpp/include/list b/resources/sources/avr-libstdcpp/include/list new file mode 100644 index 000000000..7b3d3c2e8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/list @@ -0,0 +1,109 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/list + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_LIST +#define _GLIBCXX_LIST 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template + using list = std::list<_Tp, polymorphic_allocator<_Tp>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_erase_if 202002L + + template + inline typename list<_Tp, _Alloc>::size_type + erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred) + { return __cont.remove_if(__pred); } + + template + inline typename list<_Tp, _Alloc>::size_type + erase(list<_Tp, _Alloc>& __cont, const _Up& __value) + { + using __elem_type = typename list<_Tp, _Alloc>::value_type; + return std::erase_if(__cont, [&](__elem_type& __elem) { + return __elem == __value; + }); + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_LIST */ diff --git a/resources/sources/avr-libstdcpp/include/map b/resources/sources/avr-libstdcpp/include/map new file mode 100644 index 000000000..9e8f76b48 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/map @@ -0,0 +1,109 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/map + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_MAP +#define _GLIBCXX_MAP 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template> + using map + = std::map<_Key, _Tp, _Cmp, + polymorphic_allocator>>; + template> + using multimap + = std::multimap<_Key, _Tp, _Cmp, + polymorphic_allocator>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template + inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type + erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } + + template + inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type + erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_MAP */ diff --git a/resources/sources/avr-libstdcpp/include/memory b/resources/sources/avr-libstdcpp/include/memory new file mode 100644 index 000000000..0ed1a86b5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/memory @@ -0,0 +1,404 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1997-1999 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file include/memory + * This is a Standard C++ Library header. + * @ingroup memory + */ + +#ifndef _GLIBCXX_MEMORY +#define _GLIBCXX_MEMORY 1 + +#pragma GCC system_header + +/** + * @defgroup memory Memory + * @ingroup utilities + * + * Components for memory allocation, deallocation, and management. + */ + +/** + * @defgroup pointer_abstractions Pointer Abstractions + * @ingroup memory + * + * Smart pointers, etc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +# include +# include +# include // std::less +# include +# include +# include +# include +# include +#endif + +#if __cplusplus >= 201103L +#include +#if __cplusplus > 201703L +# include // for has_single_bit +# include // for placement operator new +# include // for tuple, make_tuple, make_from_tuple +#endif +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** + * @brief Fit aligned storage in buffer. + * @ingroup memory + * + * This function tries to fit @a __size bytes of storage with alignment + * @a __align into the buffer @a __ptr of size @a __space bytes. If such + * a buffer fits then @a __ptr is changed to point to the first byte of the + * aligned storage and @a __space is reduced by the bytes used for alignment. + * + * C++11 20.6.5 [ptr.align] + * + * @param __align A fundamental or extended alignment value. + * @param __size Size of the aligned storage required. + * @param __ptr Pointer to a buffer of @a __space bytes. + * @param __space Size of the buffer pointed to by @a __ptr. + * @return the updated pointer if the aligned storage fits, otherwise nullptr. + * + */ +inline void* +align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept +{ +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + const auto __intptr = reinterpret_cast(__ptr); +#else + // Cannot use std::uintptr_t so assume that std::size_t can be used instead. + static_assert(sizeof(size_t) >= sizeof(void*), + "std::size_t must be a suitable substitute for std::uintptr_t"); + const auto __intptr = reinterpret_cast(__ptr); +#endif + const auto __aligned = (__intptr - 1u + __align) & -__align; + const auto __diff = __aligned - __intptr; + if ((__size + __diff) > __space) + return nullptr; + else + { + __space -= __diff; + return __ptr = reinterpret_cast(__aligned); + } +} + +/** @defgroup ptr_safety Pointer Safety and Garbage Collection + * @ingroup memory + * + * Utilities to assist with garbage collection in an implementation + * that supports strict pointer safety. + * This implementation only supports relaxed pointer safety + * and so these functions have no effect. + * + * C++11 20.6.4 [util.dynamic.safety], Pointer safety + * + * @{ + */ + +/// Constants representing the different types of pointer safety. +enum class pointer_safety { relaxed, preferred, strict }; + +/// Inform a garbage collector that an object is still in use. +inline void +declare_reachable(void*) { } + +/// Unregister an object previously registered with declare_reachable. +template + inline _Tp* + undeclare_reachable(_Tp* __p) { return __p; } + +/// Inform a garbage collector that a region of memory need not be traced. +inline void +declare_no_pointers(char*, size_t) { } + +/// Unregister a range previously registered with declare_no_pointers. +inline void +undeclare_no_pointers(char*, size_t) { } + +/// The type of pointer safety supported by the implementation. +inline pointer_safety +get_pointer_safety() noexcept { return pointer_safety::relaxed; } +// @} + +#if __cplusplus > 201703L +#define __cpp_lib_assume_aligned 201811L + /** @brief Inform the compiler that a pointer is aligned. + * + * @tparam _Align An alignment value (i.e. a power of two) + * @tparam _Tp An object type + * @param __ptr A pointer that is aligned to _Align + * + * C++20 20.10.6 [ptr.align] + * + * @ingroup memory + */ + template + [[nodiscard,__gnu__::__always_inline__]] + constexpr _Tp* + assume_aligned(_Tp* __ptr) noexcept + { + static_assert(std::has_single_bit(_Align)); + if (std::is_constant_evaluated()) + return __ptr; + else + { + // This function is expected to be used in hot code, where + // __glibcxx_assert would add unwanted overhead. + _GLIBCXX_DEBUG_ASSERT((std::uintptr_t)__ptr % _Align == 0); + return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align)); + } + } +#endif // C++2a + +#if __cplusplus > 201703L + template + struct __is_pair : false_type { }; + template + struct __is_pair> : true_type { }; + template + struct __is_pair> : true_type { }; + +/** @addtogroup allocators + * @{ + */ + template>>, + typename _Alloc, typename... _Args> + constexpr auto + __uses_alloc_args(const _Alloc& __a, _Args&&... __args) noexcept + { + if constexpr (uses_allocator_v, _Alloc>) + { + if constexpr (is_constructible_v<_Tp, allocator_arg_t, + const _Alloc&, _Args...>) + { + return tuple( + allocator_arg, __a, std::forward<_Args>(__args)...); + } + else + { + static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>, + "construction with an allocator must be possible" + " if uses_allocator is true"); + + return tuple<_Args&&..., const _Alloc&>( + std::forward<_Args>(__args)..., __a); + } + } + else + { + static_assert(is_constructible_v<_Tp, _Args...>); + + return tuple<_Args&&...>(std::forward<_Args>(__args)...); + } + } + +#if __cpp_concepts + template + concept _Std_pair = __is_pair<_Tp>::value; +#endif + +// This is a temporary workaround until -fconcepts is implied by -std=gnu++2a +#if __cpp_concepts +# define _GLIBCXX_STD_PAIR_CONSTRAINT(T) _Std_pair T +# define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) _Std_pair T +#else +# define _GLIBCXX_STD_PAIR_CONSTRAINT(T) \ + typename T, typename __ = _Require<__is_pair> +# define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) typename T, typename +#endif + + template>>, +#endif + typename _Alloc, typename... _Args> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + _Args&&... __args) noexcept +#if __cpp_concepts + requires (! _Std_pair<_Tp>) +#endif + { + return std::__uses_alloc_args<_Tp>(__a, std::forward<_Args>(__args)...); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, + typename _Tuple1, typename _Tuple2> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, + _Tuple1&& __x, _Tuple2&& __y) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc> + constexpr auto + uses_allocator_construction_args(const _Alloc&) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, _Up&&, _Vp&&) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, + const pair<_Up, _Vp>&) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, pair<_Up, _Vp>&&) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, + typename _Tuple1, typename _Tuple2> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, + _Tuple1&& __x, _Tuple2&& __y) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::apply([&__a](auto&&... __args1) { + return std::uses_allocator_construction_args<_Tp1>( + __a, std::forward(__args1)...); + }, std::forward<_Tuple1>(__x)), + std::apply([&__a](auto&&... __args2) { + return std::uses_allocator_construction_args<_Tp2>( + __a, std::forward(__args2)...); + }, std::forward<_Tuple2>(__y))); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a), + std::uses_allocator_construction_args<_Tp2>(__a)); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, _Up&& __u, _Vp&& __v) + noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, + std::forward<_Up>(__u)), + std::uses_allocator_construction_args<_Tp2>(__a, + std::forward<_Vp>(__v))); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + const pair<_Up, _Vp>& __pr) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, __pr.first), + std::uses_allocator_construction_args<_Tp2>(__a, __pr.second)); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + pair<_Up, _Vp>&& __pr) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, + std::move(__pr).first), + std::uses_allocator_construction_args<_Tp2>(__a, + std::move(__pr).second)); + } + + template + inline _Tp + make_obj_using_allocator(const _Alloc& __a, _Args&&... __args) + { + return std::make_from_tuple<_Tp>( + std::uses_allocator_construction_args<_Tp>(__a, + std::forward<_Args>(__args)...)); + } + + template + inline _Tp* + uninitialized_construct_using_allocator(_Tp* __p, const _Alloc& __a, + _Args&&... __args) + { + return std::apply([&](auto&&... __xs) { + return std::construct_at(__p, std::forward(__xs)...); + }, std::uses_allocator_construction_args<_Tp>(__a, + std::forward<_Args>(__args)...)); + } +// @} + +#endif // C++2a + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // C++11 + +#endif /* _GLIBCXX_MEMORY */ diff --git a/resources/sources/avr-libstdcpp/include/mutex b/resources/sources/avr-libstdcpp/include/mutex new file mode 100644 index 000000000..389504d7d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/mutex @@ -0,0 +1,746 @@ +// -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/mutex + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_MUTEX +#define _GLIBCXX_MUTEX 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#ifndef _GLIBCXX_HAVE_TLS +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup mutexes + * @{ + */ + +#ifdef _GLIBCXX_HAS_GTHREADS + + // Common base class for std::recursive_mutex and std::recursive_timed_mutex + class __recursive_mutex_base + { + protected: + typedef __gthread_recursive_mutex_t __native_type; + + __recursive_mutex_base(const __recursive_mutex_base&) = delete; + __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; + +#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT + __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; + + __recursive_mutex_base() = default; +#else + __native_type _M_mutex; + + __recursive_mutex_base() + { + // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) + __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); + } + + ~__recursive_mutex_base() + { __gthread_recursive_mutex_destroy(&_M_mutex); } +#endif + }; + + /// The standard recursive mutex type. + class recursive_mutex : private __recursive_mutex_base + { + public: + typedef __native_type* native_handle_type; + + recursive_mutex() = default; + ~recursive_mutex() = default; + + recursive_mutex(const recursive_mutex&) = delete; + recursive_mutex& operator=(const recursive_mutex&) = delete; + + void + lock() + { + int __e = __gthread_recursive_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() noexcept + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_recursive_mutex_trylock(&_M_mutex); + } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EBUSY + __gthread_recursive_mutex_unlock(&_M_mutex); + } + + native_handle_type + native_handle() noexcept + { return &_M_mutex; } + }; + +#if _GTHREAD_USE_MUTEX_TIMEDLOCK + template + class __timed_mutex_impl + { + protected: + template + bool + _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { +#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK + using __clock = chrono::steady_clock; +#else + using __clock = chrono::system_clock; +#endif + + auto __rt = chrono::duration_cast<__clock::duration>(__rtime); + if (ratio_greater<__clock::period, _Period>()) + ++__rt; + return _M_try_lock_until(__clock::now() + __rt); + } + + template + bool + _M_try_lock_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + return static_cast<_Derived*>(this)->_M_timedlock(__ts); + } + +#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK + template + bool + _M_try_lock_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + return static_cast<_Derived*>(this)->_M_clocklock(CLOCK_MONOTONIC, + __ts); + } +#endif + + template + bool + _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { +#if __cplusplus > 201703L + static_assert(chrono::is_clock_v<_Clock>); +#endif + // The user-supplied clock may not tick at the same rate as + // steady_clock, so we must loop in order to guarantee that + // the timeout has expired before returning false. + auto __now = _Clock::now(); + do { + auto __rtime = __atime - __now; + if (_M_try_lock_for(__rtime)) + return true; + __now = _Clock::now(); + } while (__atime > __now); + return false; + } + }; + + /// The standard timed mutex type. + class timed_mutex + : private __mutex_base, public __timed_mutex_impl + { + public: + typedef __native_type* native_handle_type; + + timed_mutex() = default; + ~timed_mutex() = default; + + timed_mutex(const timed_mutex&) = delete; + timed_mutex& operator=(const timed_mutex&) = delete; + + void + lock() + { + int __e = __gthread_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() noexcept + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_mutex_trylock(&_M_mutex); + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { return _M_try_lock_for(__rtime); } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { return _M_try_lock_until(__atime); } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EBUSY + __gthread_mutex_unlock(&_M_mutex); + } + + native_handle_type + native_handle() noexcept + { return &_M_mutex; } + + private: + friend class __timed_mutex_impl; + + bool + _M_timedlock(const __gthread_time_t& __ts) + { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); } + +#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK + bool + _M_clocklock(clockid_t clockid, const __gthread_time_t& __ts) + { return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); } +#endif + }; + + /// recursive_timed_mutex + class recursive_timed_mutex + : private __recursive_mutex_base, + public __timed_mutex_impl + { + public: + typedef __native_type* native_handle_type; + + recursive_timed_mutex() = default; + ~recursive_timed_mutex() = default; + + recursive_timed_mutex(const recursive_timed_mutex&) = delete; + recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; + + void + lock() + { + int __e = __gthread_recursive_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() noexcept + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_recursive_mutex_trylock(&_M_mutex); + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { return _M_try_lock_for(__rtime); } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { return _M_try_lock_until(__atime); } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EBUSY + __gthread_recursive_mutex_unlock(&_M_mutex); + } + + native_handle_type + native_handle() noexcept + { return &_M_mutex; } + + private: + friend class __timed_mutex_impl; + + bool + _M_timedlock(const __gthread_time_t& __ts) + { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); } + +#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK + bool + _M_clocklock(clockid_t clockid, const __gthread_time_t& __ts) + { return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); } +#endif + }; + +#else // !_GTHREAD_USE_MUTEX_TIMEDLOCK + + /// timed_mutex + class timed_mutex + { + mutex _M_mut; + condition_variable _M_cv; + bool _M_locked = false; + + public: + + timed_mutex() = default; + ~timed_mutex() { __glibcxx_assert( !_M_locked ); } + + timed_mutex(const timed_mutex&) = delete; + timed_mutex& operator=(const timed_mutex&) = delete; + + void + lock() + { + unique_lock __lk(_M_mut); + _M_cv.wait(__lk, [&]{ return !_M_locked; }); + _M_locked = true; + } + + bool + try_lock() + { + lock_guard __lk(_M_mut); + if (_M_locked) + return false; + _M_locked = true; + return true; + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + unique_lock __lk(_M_mut); + if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; })) + return false; + _M_locked = true; + return true; + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + unique_lock __lk(_M_mut); + if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; })) + return false; + _M_locked = true; + return true; + } + + void + unlock() + { + lock_guard __lk(_M_mut); + __glibcxx_assert( _M_locked ); + _M_locked = false; + _M_cv.notify_one(); + } + }; + + /// recursive_timed_mutex + class recursive_timed_mutex + { + mutex _M_mut; + condition_variable _M_cv; + thread::id _M_owner; + unsigned _M_count = 0; + + // Predicate type that tests whether the current thread can lock a mutex. + struct _Can_lock + { + // Returns true if the mutex is unlocked or is locked by _M_caller. + bool + operator()() const noexcept + { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; } + + const recursive_timed_mutex* _M_mx; + thread::id _M_caller; + }; + + public: + + recursive_timed_mutex() = default; + ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); } + + recursive_timed_mutex(const recursive_timed_mutex&) = delete; + recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; + + void + lock() + { + auto __id = this_thread::get_id(); + _Can_lock __can_lock{this, __id}; + unique_lock __lk(_M_mut); + _M_cv.wait(__lk, __can_lock); + if (_M_count == -1u) + __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3 + _M_owner = __id; + ++_M_count; + } + + bool + try_lock() + { + auto __id = this_thread::get_id(); + _Can_lock __can_lock{this, __id}; + lock_guard __lk(_M_mut); + if (!__can_lock()) + return false; + if (_M_count == -1u) + return false; + _M_owner = __id; + ++_M_count; + return true; + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + auto __id = this_thread::get_id(); + _Can_lock __can_lock{this, __id}; + unique_lock __lk(_M_mut); + if (!_M_cv.wait_for(__lk, __rtime, __can_lock)) + return false; + if (_M_count == -1u) + return false; + _M_owner = __id; + ++_M_count; + return true; + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + auto __id = this_thread::get_id(); + _Can_lock __can_lock{this, __id}; + unique_lock __lk(_M_mut); + if (!_M_cv.wait_until(__lk, __atime, __can_lock)) + return false; + if (_M_count == -1u) + return false; + _M_owner = __id; + ++_M_count; + return true; + } + + void + unlock() + { + lock_guard __lk(_M_mut); + __glibcxx_assert( _M_owner == this_thread::get_id() ); + __glibcxx_assert( _M_count > 0 ); + if (--_M_count == 0) + { + _M_owner = {}; + _M_cv.notify_one(); + } + } + }; + +#endif +#endif // _GLIBCXX_HAS_GTHREADS + + /// @cond undocumented + template + inline unique_lock<_Lock> + __try_to_lock(_Lock& __l) + { return unique_lock<_Lock>{__l, try_to_lock}; } + + template + struct __try_lock_impl + { + template + static void + __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) + { + __idx = _Idx; + auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); + if (__lock.owns_lock()) + { + constexpr bool __cont = _Idx + 2 < sizeof...(_Lock); + using __try_locker = __try_lock_impl<_Idx + 1, __cont>; + __try_locker::__do_try_lock(__locks, __idx); + if (__idx == -1) + __lock.release(); + } + } + }; + + template + struct __try_lock_impl<_Idx, false> + { + template + static void + __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) + { + __idx = _Idx; + auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); + if (__lock.owns_lock()) + { + __idx = -1; + __lock.release(); + } + } + }; + /// @endcond + + /** @brief Generic try_lock. + * @param __l1 Meets Lockable requirements (try_lock() may throw). + * @param __l2 Meets Lockable requirements (try_lock() may throw). + * @param __l3 Meets Lockable requirements (try_lock() may throw). + * @return Returns -1 if all try_lock() calls return true. Otherwise returns + * a 0-based index corresponding to the argument that returned false. + * @post Either all arguments are locked, or none will be. + * + * Sequentially calls try_lock() on each argument. + */ + template + int + try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3) + { + int __idx; + auto __locks = std::tie(__l1, __l2, __l3...); + __try_lock_impl<0>::__do_try_lock(__locks, __idx); + return __idx; + } + + /** @brief Generic lock. + * @param __l1 Meets Lockable requirements (try_lock() may throw). + * @param __l2 Meets Lockable requirements (try_lock() may throw). + * @param __l3 Meets Lockable requirements (try_lock() may throw). + * @throw An exception thrown by an argument's lock() or try_lock() member. + * @post All arguments are locked. + * + * All arguments are locked via a sequence of calls to lock(), try_lock() + * and unlock(). If the call exits via an exception any locks that were + * obtained will be released. + */ + template + void + lock(_L1& __l1, _L2& __l2, _L3&... __l3) + { + while (true) + { + using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>; + unique_lock<_L1> __first(__l1); + int __idx; + auto __locks = std::tie(__l2, __l3...); + __try_locker::__do_try_lock(__locks, __idx); + if (__idx == -1) + { + __first.release(); + return; + } + } + } + +#if __cplusplus >= 201703L +#define __cpp_lib_scoped_lock 201703 + /** @brief A scoped lock type for multiple lockable objects. + * + * A scoped_lock controls mutex ownership within a scope, releasing + * ownership in the destructor. + */ + template + class scoped_lock + { + public: + explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...)) + { std::lock(__m...); } + + explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept + : _M_devices(std::tie(__m...)) + { } // calling thread owns mutex + + ~scoped_lock() + { std::apply([](auto&... __m) { (__m.unlock(), ...); }, _M_devices); } + + scoped_lock(const scoped_lock&) = delete; + scoped_lock& operator=(const scoped_lock&) = delete; + + private: + tuple<_MutexTypes&...> _M_devices; + }; + + template<> + class scoped_lock<> + { + public: + explicit scoped_lock() = default; + explicit scoped_lock(adopt_lock_t) noexcept { } + ~scoped_lock() = default; + + scoped_lock(const scoped_lock&) = delete; + scoped_lock& operator=(const scoped_lock&) = delete; + }; + + template + class scoped_lock<_Mutex> + { + public: + using mutex_type = _Mutex; + + explicit scoped_lock(mutex_type& __m) : _M_device(__m) + { _M_device.lock(); } + + explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept + : _M_device(__m) + { } // calling thread owns mutex + + ~scoped_lock() + { _M_device.unlock(); } + + scoped_lock(const scoped_lock&) = delete; + scoped_lock& operator=(const scoped_lock&) = delete; + + private: + mutex_type& _M_device; + }; +#endif // C++17 + +#ifdef _GLIBCXX_HAS_GTHREADS + /// Flag type used by std::call_once + struct once_flag + { + private: + typedef __gthread_once_t __native_type; + __native_type _M_once = __GTHREAD_ONCE_INIT; + + public: + /// Constructor + constexpr once_flag() noexcept = default; + + /// Deleted copy constructor + once_flag(const once_flag&) = delete; + /// Deleted assignment operator + once_flag& operator=(const once_flag&) = delete; + + template + friend void + call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); + }; + + /// @cond undocumented +#ifdef _GLIBCXX_HAVE_TLS + extern __thread void* __once_callable; + extern __thread void (*__once_call)(); +#else + extern function __once_functor; + + extern void + __set_once_functor_lock_ptr(unique_lock*); + + extern mutex& + __get_once_mutex(); +#endif + + extern "C" void __once_proxy(void); + /// @endcond + + /// Invoke a callable and synchronize with other calls using the same flag + template + void + call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2442. call_once() shouldn't DECAY_COPY() + auto __callable = [&] { + std::__invoke(std::forward<_Callable>(__f), + std::forward<_Args>(__args)...); + }; +#ifdef _GLIBCXX_HAVE_TLS + __once_callable = std::__addressof(__callable); + __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; +#else + unique_lock __functor_lock(__get_once_mutex()); + __once_functor = __callable; + __set_once_functor_lock_ptr(&__functor_lock); +#endif + + int __e = __gthread_once(&__once._M_once, &__once_proxy); + +#ifndef _GLIBCXX_HAVE_TLS + if (__functor_lock) + __set_once_functor_lock_ptr(0); +#endif + +#ifdef __clang_analyzer__ + // PR libstdc++/82481 + __once_callable = nullptr; + __once_call = nullptr; +#endif + + if (__e) + __throw_system_error(__e); + } +#endif // _GLIBCXX_HAS_GTHREADS + + // @} group mutexes +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _GLIBCXX_MUTEX diff --git a/resources/sources/avr-libstdcpp/include/new b/resources/sources/avr-libstdcpp/include/new new file mode 100644 index 000000000..06e43dc6f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/new @@ -0,0 +1,193 @@ +// The -*- C++ -*- dynamic memory management header. + +// Copyright (C) 1994-2020 Free Software Foundation, Inc. + +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file new + * This is a Standard C++ Library header. + * + * The header @c new defines several functions to manage dynamic memory and + * handling memory allocation errors; see + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html + * for more. + */ + +#ifndef _NEW +#define _NEW + +#pragma GCC system_header + +#include +#include + +#pragma GCC visibility push(default) + +extern "C++" { + +namespace std +{ +#if __cpp_aligned_new + enum class align_val_t: size_t {}; +#endif + + struct nothrow_t + { +#if __cplusplus >= 201103L + explicit nothrow_t() = default; +#endif + }; + + extern const nothrow_t nothrow; + + /** If you write your own error handler to be called by @c new, it must + * be of this type. */ + typedef void (*new_handler)(); + + /// Takes a replacement handler as the argument, returns the + /// previous handler. + new_handler set_new_handler(new_handler) throw(); + +#if __cplusplus >= 201103L + /// Return the current new handler. + new_handler get_new_handler() noexcept; +#endif +} // namespace std + +//@{ +/** These are replaceable signatures: + * - normal single new and delete (no arguments, throw @c bad_alloc on error) + * - normal array new and delete (same) + * - @c nothrow single new and delete (take a @c nothrow argument, return + * @c NULL on error) + * - @c nothrow array new and delete (same) + * + * Placement new and delete signatures (take a memory address argument, + * does nothing) may not be replaced by a user's program. +*/ +_GLIBCXX_NODISCARD void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc) + __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc) + __attribute__((__externally_visible__)); +void operator delete(void*) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#if __cpp_sized_deallocation +void operator delete(void*, std::size_t) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*, std::size_t) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#endif +_GLIBCXX_NODISCARD void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__, __malloc__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__, __malloc__)); +void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#if 0 // __cpp_aligned_new +_GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t) + __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __malloc__)); +void operator delete(void*, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete(void*, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t) + __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __malloc__)); +void operator delete[](void*, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete[](void*, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +#if __cpp_sized_deallocation +void operator delete(void*, std::size_t, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete[](void*, std::size_t, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +#endif // __cpp_sized_deallocation +#endif // __cpp_aligned_new + +// Default placement versions of operator new. +_GLIBCXX_NODISCARD inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT +{ return __p; } +_GLIBCXX_NODISCARD inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT +{ return __p; } + +// Default placement versions of operator delete. +inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { } +inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { } +//@} +} // extern "C++" + +#if __cplusplus >= 201703L +#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER +namespace std +{ +#define __cpp_lib_launder 201606 + /// Pointer optimization barrier [ptr.launder] + template + [[nodiscard]] constexpr _Tp* + launder(_Tp* __p) noexcept + { return __builtin_launder(__p); } + + // The program is ill-formed if T is a function type or + // (possibly cv-qualified) void. + + template + void launder(_Ret (*)(_Args...) _GLIBCXX_NOEXCEPT_QUAL) = delete; + template + void launder(_Ret (*)(_Args......) _GLIBCXX_NOEXCEPT_QUAL) = delete; + + void launder(void*) = delete; + void launder(const void*) = delete; + void launder(volatile void*) = delete; + void launder(const volatile void*) = delete; +} +#endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER +#endif // C++17 + +#if __cplusplus > 201703L +namespace std +{ + /// Tag type used to declare a class-specific operator delete that can + /// invoke the destructor before deallocating the memory. + struct destroying_delete_t + { + explicit destroying_delete_t() = default; + }; + /// Tag variable of type destroying_delete_t. + inline constexpr destroying_delete_t destroying_delete{}; +} +// Only define the feature test macro if the compiler supports the feature: +#if __cpp_impl_destroying_delete +# define __cpp_lib_destroying_delete 201806L +#endif +#endif // C++20 + +#pragma GCC visibility pop + +#endif diff --git a/resources/sources/avr-libstdcpp/include/numbers b/resources/sources/avr-libstdcpp/include/numbers new file mode 100644 index 000000000..7e51851bd --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/numbers @@ -0,0 +1,208 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/numbers + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_NUMBERS +#define _GLIBCXX_NUMBERS 1 + +#pragma GCC system_header + +#if __cplusplus > 201703L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** @defgroup math_constants Mathematical constants + * @ingroup numerics + * @{ + */ + +/// Namespace for mathematical constants +namespace numbers +{ +#define __cpp_lib_math_constants 201907L + + /// @cond undoc + template + using _Enable_if_floating = enable_if_t, _Tp>; + /// @endcond + + /// e + template + inline constexpr _Tp e_v + = _Enable_if_floating<_Tp>(2.718281828459045235360287471352662498L); + + /// log_2 e + template + inline constexpr _Tp log2e_v + = _Enable_if_floating<_Tp>(1.442695040888963407359924681001892137L); + + /// log_10 e + template + inline constexpr _Tp log10e_v + = _Enable_if_floating<_Tp>(0.434294481903251827651128918916605082L); + + /// pi + template + inline constexpr _Tp pi_v + = _Enable_if_floating<_Tp>(3.141592653589793238462643383279502884L); + + /// 1/pi + template + inline constexpr _Tp inv_pi_v + = _Enable_if_floating<_Tp>(0.318309886183790671537767526745028724L); + + /// 1/sqrt(pi) + template + inline constexpr _Tp inv_sqrtpi_v + = _Enable_if_floating<_Tp>(0.564189583547756286948079451560772586L); + + /// log_e 2 + template + inline constexpr _Tp ln2_v + = _Enable_if_floating<_Tp>(0.693147180559945309417232121458176568L); + + /// log_e 10 + template + inline constexpr _Tp ln10_v + = _Enable_if_floating<_Tp>(2.302585092994045684017991454684364208L); + + /// sqrt(2) + template + inline constexpr _Tp sqrt2_v + = _Enable_if_floating<_Tp>(1.414213562373095048801688724209698079L); + + /// sqrt(3) + template + inline constexpr _Tp sqrt3_v + = _Enable_if_floating<_Tp>(1.732050807568877293527446341505872367L); + + /// 1/sqrt(3) + template + inline constexpr _Tp inv_sqrt3_v + = _Enable_if_floating<_Tp>(0.577350269189625764509148780501957456L); + + /// The Euler-Mascheroni constant + template + inline constexpr _Tp egamma_v + = _Enable_if_floating<_Tp>(0.577215664901532860606512090082402431L); + + /// The golden ratio, (1+sqrt(5))/2 + template + inline constexpr _Tp phi_v + = _Enable_if_floating<_Tp>(1.618033988749894848204586834365638118L); + + inline constexpr double e = e_v; + inline constexpr double log2e = log2e_v; + inline constexpr double log10e = log10e_v; + inline constexpr double pi = pi_v; + inline constexpr double inv_pi = inv_pi_v; + inline constexpr double inv_sqrtpi = inv_sqrtpi_v; + inline constexpr double ln2 = ln2_v; + inline constexpr double ln10 = ln10_v; + inline constexpr double sqrt2 = sqrt2_v; + inline constexpr double sqrt3 = sqrt3_v; + inline constexpr double inv_sqrt3 = inv_sqrt3_v; + inline constexpr double egamma = egamma_v; + inline constexpr double phi = phi_v; + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + template<> + inline constexpr __float128 e_v<__float128> + = 2.718281828459045235360287471352662498Q; + + /// log_2 e + template<> + inline constexpr __float128 log2e_v<__float128> + = 1.442695040888963407359924681001892137Q; + + /// log_10 e + template<> + inline constexpr __float128 log10e_v<__float128> + = 0.434294481903251827651128918916605082Q; + + /// pi + template<> + inline constexpr __float128 pi_v<__float128> + = 3.141592653589793238462643383279502884Q; + + /// 1/pi + template<> + inline constexpr __float128 inv_pi_v<__float128> + = 0.318309886183790671537767526745028724Q; + + /// 1/sqrt(pi) + template<> + inline constexpr __float128 inv_sqrtpi_v<__float128> + = 0.564189583547756286948079451560772586Q; + + /// log_e 2 + template<> + inline constexpr __float128 ln2_v<__float128> + = 0.693147180559945309417232121458176568Q; + + /// log_e 10 + template<> + inline constexpr __float128 ln10_v<__float128> + = 2.302585092994045684017991454684364208Q; + + /// sqrt(2) + template<> + inline constexpr __float128 sqrt2_v<__float128> + = 1.414213562373095048801688724209698079Q; + + /// sqrt(3) + template<> + inline constexpr __float128 sqrt3_v<__float128> + = 1.732050807568877293527446341505872367Q; + + /// 1/sqrt(3) + template<> + inline constexpr __float128 inv_sqrt3_v<__float128> + = 0.577350269189625764509148780501957456Q; + + /// The Euler-Mascheroni constant + template<> + inline constexpr __float128 egamma_v<__float128> + = 0.577215664901532860606512090082402431Q; + + /// The golden ratio, (1+sqrt(5))/2 + template<> + inline constexpr __float128 phi_v<__float128> + = 1.618033988749894848204586834365638118Q; +#endif // USE_FLOAT128 + +} // namespace numbers +/// @} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++20 +#endif // _GLIBCXX_NUMBERS diff --git a/resources/sources/avr-libstdcpp/include/numeric b/resources/sources/avr-libstdcpp/include/numeric new file mode 100644 index 000000000..7793c9db3 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/numeric @@ -0,0 +1,699 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/numeric + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_NUMERIC +#define _GLIBCXX_NUMERIC 1 + +#pragma GCC system_header + +#include +#include +#include +#include + +/** + * @defgroup numerics Numerics + * + * Components for performing numeric operations. Includes support for + * complex number types, random number generation, numeric (n-at-a-time) + * arrays, generalized numeric algorithms, and mathematical special functions. + */ + +#if __cplusplus >= 201402L +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __detail +{ + // std::abs is not constexpr, doesn't support unsigned integers, + // and std::abs(std::numeric_limits::min()) is undefined. + template + constexpr _Up + __absu(_Tp __val) + { + static_assert(is_unsigned<_Up>::value, "result type must be unsigned"); + static_assert(sizeof(_Up) >= sizeof(_Tp), + "result type must be at least as wide as the input type"); + return __val < 0 ? -(_Up)__val : (_Up)__val; + } + + template void __absu(bool) = delete; + + // GCD implementation + template + constexpr _Tp + __gcd(_Tp __m, _Tp __n) + { + static_assert(is_unsigned<_Tp>::value, "type must be unsigned"); + return __m == 0 ? __n + : __n == 0 ? __m + : __detail::__gcd(__n, _Tp(__m % __n)); + } + + // LCM implementation + template + constexpr _Tp + __lcm(_Tp __m, _Tp __n) + { + return (__m != 0 && __n != 0) + ? (__m / __detail::__gcd(__m, __n)) * __n + : 0; + } +} // namespace __detail + +#if __cplusplus >= 201703L + +#define __cpp_lib_gcd_lcm 201606 +// These were used in drafts of SD-6: +#define __cpp_lib_gcd 201606 +#define __cpp_lib_lcm 201606 + + /// Greatest common divisor + template + constexpr common_type_t<_Mn, _Nn> + gcd(_Mn __m, _Nn __n) noexcept + { + static_assert(is_integral_v<_Mn>, "std::gcd arguments must be integers"); + static_assert(is_integral_v<_Nn>, "std::gcd arguments must be integers"); + static_assert(_Mn(2) != _Mn(1), "std::gcd arguments must not be bool"); + static_assert(_Nn(2) != _Nn(1), "std::gcd arguments must not be bool"); + using _Up = make_unsigned_t>; + return __detail::__gcd(__detail::__absu<_Up>(__m), + __detail::__absu<_Up>(__n)); + } + + /// Least common multiple + template + constexpr common_type_t<_Mn, _Nn> + lcm(_Mn __m, _Nn __n) noexcept + { + static_assert(is_integral_v<_Mn>, "std::lcm arguments must be integers"); + static_assert(is_integral_v<_Nn>, "std::lcm arguments must be integers"); + static_assert(_Mn(2) == 2, "std::lcm arguments must not be bool"); + static_assert(_Nn(2) == 2, "std::lcm arguments must not be bool"); + using _Up = make_unsigned_t>; + return __detail::__lcm(__detail::__absu<_Up>(__m), + __detail::__absu<_Up>(__n)); + } + +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + +#if __cplusplus > 201703L +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // midpoint +# define __cpp_lib_interpolate 201902L + + template + constexpr + enable_if_t<__and_v, is_same, _Tp>, + __not_>>, + _Tp> + midpoint(_Tp __a, _Tp __b) noexcept + { + if constexpr (is_integral_v<_Tp>) + { + using _Up = make_unsigned_t<_Tp>; + + int __k = 1; + _Up __m = __a; + _Up __M = __b; + if (__a > __b) + { + __k = -1; + __m = __b; + __M = __a; + } + return __a + __k * _Tp(_Up(__M - __m) / 2); + } + else // is_floating + { + constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2; + constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2; + const _Tp __abs_a = __a < 0 ? -__a : __a; + const _Tp __abs_b = __b < 0 ? -__b : __b; + if (__abs_a <= __hi && __abs_b <= __hi) [[likely]] + return (__a + __b) / 2; // always correctly rounded + if (__abs_a < __lo) // not safe to halve __a + return __a + __b/2; + if (__abs_b < __lo) // not safe to halve __b + return __a/2 + __b; + return __a/2 + __b/2; // otherwise correctly rounded + } + } + + template + constexpr enable_if_t, _Tp*> + midpoint(_Tp* __a, _Tp* __b) noexcept + { + static_assert( sizeof(_Tp) != 0, "type must be complete" ); + return __a + (__b - __a) / 2; + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++20 + +#if __cplusplus > 201402L +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus > 201703L +#define __cpp_lib_constexpr_numeric 201911L +#endif + + /// @addtogroup numeric_ops + /// @{ + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op A binary function object. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using a binary operation. + * The initial value is `init`. The values are not necessarily processed + * in order. + * + * This algorithm is similar to `std::accumulate` but is not required to + * perform the operations in order from first to last. For operations + * that are commutative and associative the result will be the same as + * for `std::accumulate`, but for other operations (such as floating point + * arithmetic) the result can be different. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + reduce(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op) + { + using value_type = typename iterator_traits<_InputIterator>::value_type; + static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>); + static_assert(is_convertible_v); + if constexpr (__is_random_access_iter<_InputIterator>::value) + { + while ((__last - __first) >= 4) + { + _Tp __v1 = __binary_op(__first[0], __first[1]); + _Tp __v2 = __binary_op(__first[2], __first[3]); + _Tp __v3 = __binary_op(__v1, __v2); + __init = __binary_op(__init, __v3); + __first += 4; + } + } + for (; __first != __last; ++__first) + __init = __binary_op(__init, *__first); + return __init; + } + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using addition. + * Equivalent to calling `std::reduce(first, last, init, std::plus<>())`. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + reduce(_InputIterator __first, _InputIterator __last, _Tp __init) + { return std::reduce(__first, __last, std::move(__init), plus<>()); } + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using addition, with + * an initial value of `T{}`, where `T` is the iterator's value type. + * Equivalent to calling `std::reduce(first, last, T{}, std::plus<>())`. + */ + template + _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::value_type + reduce(_InputIterator __first, _InputIterator __last) + { + using value_type = typename iterator_traits<_InputIterator>::value_type; + return std::reduce(__first, __last, value_type{}, plus<>()); + } + + /** + * @brief Combine elements from two ranges and reduce + * + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __init Starting value to add other values to. + * @param __binary_op1 The function used to perform reduction. + * @param __binary_op2 The function used to combine values from the ranges. + * @return The final sum. + * + * Call `binary_op2(first1[n],first2[n])` for each `n` in `[0,last1-first1)` + * and then use `binary_op1` to reduce the values returned by `binary_op2` + * to a single value of type `T`. + * + * The range beginning at `first2` must contain at least `last1-first1` + * elements. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init, + _BinaryOperation1 __binary_op1, + _BinaryOperation2 __binary_op2) + { + if constexpr (__and_v<__is_random_access_iter<_InputIterator1>, + __is_random_access_iter<_InputIterator2>>) + { + while ((__last1 - __first1) >= 4) + { + _Tp __v1 = __binary_op1(__binary_op2(__first1[0], __first2[0]), + __binary_op2(__first1[1], __first2[1])); + _Tp __v2 = __binary_op1(__binary_op2(__first1[2], __first2[2]), + __binary_op2(__first1[3], __first2[3])); + _Tp __v3 = __binary_op1(__v1, __v2); + __init = __binary_op1(__init, __v3); + __first1 += 4; + __first2 += 4; + } + } + for (; __first1 != __last1; ++__first1, (void) ++__first2) + __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); + return __init; + } + + /** + * @brief Combine elements from two ranges and reduce + * + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __init Starting value to add other values to. + * @return The final sum. + * + * Call `first1[n]*first2[n]` for each `n` in `[0,last1-first1)` and then + * use addition to sum those products to a single value of type `T`. + * + * The range beginning at `first2` must contain at least `last1-first1` + * elements. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init) + { + return std::transform_reduce(__first1, __last1, __first2, + std::move(__init), + plus<>(), multiplies<>()); + } + + /** + * @brief Transform the elements of a range and reduce + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op The function used to perform reduction. + * @param __unary_op The function used to transform values from the range. + * @return The final sum. + * + * Call `unary_op(first[n])` for each `n` in `[0,last-first)` and then + * use `binary_op` to reduce the values returned by `unary_op` + * to a single value of type `T`. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op, _UnaryOperation __unary_op) + { + if constexpr (__is_random_access_iter<_InputIterator>::value) + { + while ((__last - __first) >= 4) + { + _Tp __v1 = __binary_op(__unary_op(__first[0]), + __unary_op(__first[1])); + _Tp __v2 = __binary_op(__unary_op(__first[2]), + __unary_op(__first[3])); + _Tp __v3 = __binary_op(__v1, __v2); + __init = __binary_op(__init, __v3); + __first += 4; + } + } + for (; __first != __last; ++__first) + __init = __binary_op(__init, __unary_op(*__first)); + return __init; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @param __binary_op Function to perform summation. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `binary_op` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init, + _BinaryOperation __binary_op) + { + while (__first != __last) + { + auto __v = __init; + __init = __binary_op(__init, *__first); + ++__first; + *__result++ = std::move(__v); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `std::plus<>` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init) + { + return std::exclusive_scan(__first, __last, __result, std::move(__init), + plus<>()); + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op, + _Tp __init) + { + for (; __first != __last; ++__first) + *__result++ = __init = __binary_op(__init, *__first); + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, using `binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + if (__first != __last) + { + auto __init = *__first; + *__result++ = __init; + ++__first; + if (__first != __last) + __result = std::inclusive_scan(__first, __last, __result, + __binary_op, std::move(__init)); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, using `std::plus<>` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { return std::inclusive_scan(__first, __last, __result, plus<>()); } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) + { + while (__first != __last) + { + auto __v = __init; + __init = __binary_op(__init, __unary_op(*__first)); + ++__first; + *__result++ = std::move(__v); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op, + _Tp __init) + { + for (; __first != __last; ++__first) + *__result++ = __init = __binary_op(__init, __unary_op(*__first)); + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) + { + if (__first != __last) + { + auto __init = __unary_op(*__first); + *__result++ = __init; + ++__first; + if (__first != __last) + __result = std::transform_inclusive_scan(__first, __last, __result, + __binary_op, __unary_op, + std::move(__init)); + } + return __result; + } + + // @} group numeric_ops + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif /* _GLIBCXX_NUMERIC */ diff --git a/resources/sources/avr-libstdcpp/include/optional b/resources/sources/avr-libstdcpp/include/optional new file mode 100644 index 000000000..6c7701e21 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/optional @@ -0,0 +1,1238 @@ +// -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/optional + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_OPTIONAL +#define _GLIBCXX_OPTIONAL 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#include +#include +#include +#include +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + +#define __cpp_lib_optional 201606L + + template + class optional; + + /// Tag type to disengage optional objects. + struct nullopt_t + { + // Do not user-declare default constructor at all for + // optional_value = {} syntax to work. + // nullopt_t() = delete; + + // Used for constructing nullopt. + enum class _Construct { _Token }; + + // Must be constexpr for nullopt_t to be literal. + explicit constexpr nullopt_t(_Construct) { } + }; + + /// Tag to disengage optional objects. + inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; + + // This class template manages construction/destruction of + // the contained value for a std::optional. + template + struct _Optional_payload_base + { + using _Stored_type = remove_const_t<_Tp>; + + _Optional_payload_base() = default; + ~_Optional_payload_base() = default; + + template + constexpr + _Optional_payload_base(in_place_t __tag, _Args&&... __args) + : _M_payload(__tag, std::forward<_Args>(__args)...), + _M_engaged(true) + { } + + template + constexpr + _Optional_payload_base(std::initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(__il, std::forward<_Args>(__args)...), + _M_engaged(true) + { } + + // Constructor used by _Optional_base copy constructor when the + // contained value is not trivially copy constructible. + constexpr + _Optional_payload_base(bool __engaged, + const _Optional_payload_base& __other) + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + } + + // Constructor used by _Optional_base move constructor when the + // contained value is not trivially move constructible. + constexpr + _Optional_payload_base(bool __engaged, + _Optional_payload_base&& __other) + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + } + + // Copy constructor is only used to when the contained value is + // trivially copy constructible. + _Optional_payload_base(const _Optional_payload_base&) = default; + + // Move constructor is only used to when the contained value is + // trivially copy constructible. + _Optional_payload_base(_Optional_payload_base&&) = default; + + _Optional_payload_base& + operator=(const _Optional_payload_base&) = default; + + _Optional_payload_base& + operator=(_Optional_payload_base&&) = default; + + // used to perform non-trivial copy assignment. + constexpr void + _M_copy_assign(const _Optional_payload_base& __other) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = __other._M_get(); + else + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + else + this->_M_reset(); + } + } + + // used to perform non-trivial move assignment. + constexpr void + _M_move_assign(_Optional_payload_base&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = std::move(__other._M_get()); + else + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + else + this->_M_reset(); + } + } + + struct _Empty_byte { }; + + template> + union _Storage + { + constexpr _Storage() noexcept : _M_empty() { } + + template + constexpr + _Storage(in_place_t, _Args&&... __args) + : _M_value(std::forward<_Args>(__args)...) + { } + + template + constexpr + _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) + : _M_value(__il, std::forward<_Args>(__args)...) + { } + + _Empty_byte _M_empty; + _Up _M_value; + }; + + template + union _Storage<_Up, false> + { + constexpr _Storage() noexcept : _M_empty() { } + + template + constexpr + _Storage(in_place_t, _Args&&... __args) + : _M_value(std::forward<_Args>(__args)...) + { } + + template + constexpr + _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) + : _M_value(__il, std::forward<_Args>(__args)...) + { } + + // User-provided destructor is needed when _Up has non-trivial dtor. + ~_Storage() { } + + _Empty_byte _M_empty; + _Up _M_value; + }; + + _Storage<_Stored_type> _M_payload; + + bool _M_engaged = false; + + template + void + _M_construct(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) + { + ::new ((void *) std::__addressof(this->_M_payload)) + _Stored_type(std::forward<_Args>(__args)...); + this->_M_engaged = true; + } + + constexpr void + _M_destroy() noexcept + { + _M_engaged = false; + _M_payload._M_value.~_Stored_type(); + } + + // The _M_get() operations have _M_engaged as a precondition. + // They exist to access the contained value with the appropriate + // const-qualification, because _M_payload has had the const removed. + + constexpr _Tp& + _M_get() noexcept + { return this->_M_payload._M_value; } + + constexpr const _Tp& + _M_get() const noexcept + { return this->_M_payload._M_value; } + + // _M_reset is a 'safe' operation with no precondition. + constexpr void + _M_reset() noexcept + { + if (this->_M_engaged) + _M_destroy(); + } + }; + + // Class template that manages the payload for optionals. + template , + bool /*_HasTrivialCopy */ = + is_trivially_copy_assignable_v<_Tp> + && is_trivially_copy_constructible_v<_Tp>, + bool /*_HasTrivialMove */ = + is_trivially_move_assignable_v<_Tp> + && is_trivially_move_constructible_v<_Tp>> + struct _Optional_payload; + + // Payload for potentially-constexpr optionals (trivial copy/move/destroy). + template + struct _Optional_payload<_Tp, true, true, true> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + }; + + // Payload for optionals with non-trivial copy construction/assignment. + template + struct _Optional_payload<_Tp, true, false, true> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(_Optional_payload&&) = default; + + // Non-trivial copy assignment. + constexpr + _Optional_payload& + operator=(const _Optional_payload& __other) + { + this->_M_copy_assign(__other); + return *this; + } + }; + + // Payload for optionals with non-trivial move construction/assignment. + template + struct _Optional_payload<_Tp, true, true, false> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(const _Optional_payload&) = default; + + // Non-trivial move assignment. + constexpr + _Optional_payload& + operator=(_Optional_payload&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + this->_M_move_assign(std::move(__other)); + return *this; + } + }; + + // Payload for optionals with non-trivial copy and move assignment. + template + struct _Optional_payload<_Tp, true, false, false> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + + // Non-trivial copy assignment. + constexpr + _Optional_payload& + operator=(const _Optional_payload& __other) + { + this->_M_copy_assign(__other); + return *this; + } + + // Non-trivial move assignment. + constexpr + _Optional_payload& + operator=(_Optional_payload&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + this->_M_move_assign(std::move(__other)); + return *this; + } + }; + + // Payload for optionals with non-trivial destructors. + template + struct _Optional_payload<_Tp, false, _Copy, _Move> + : _Optional_payload<_Tp, true, false, false> + { + // Base class implements all the constructors and assignment operators: + using _Optional_payload<_Tp, true, false, false>::_Optional_payload; + _Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(const _Optional_payload&) = default; + _Optional_payload& operator=(_Optional_payload&&) = default; + + // Destructor needs to destroy the contained value: + ~_Optional_payload() { this->_M_reset(); } + }; + + // Common base class for _Optional_base to avoid repeating these + // member functions in each specialization. + template + class _Optional_base_impl + { + protected: + using _Stored_type = remove_const_t<_Tp>; + + // The _M_construct operation has !_M_engaged as a precondition + // while _M_destruct has _M_engaged as a precondition. + template + void + _M_construct(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) + { + ::new + (std::__addressof(static_cast<_Dp*>(this)->_M_payload._M_payload)) + _Stored_type(std::forward<_Args>(__args)...); + static_cast<_Dp*>(this)->_M_payload._M_engaged = true; + } + + void + _M_destruct() noexcept + { static_cast<_Dp*>(this)->_M_payload._M_destroy(); } + + // _M_reset is a 'safe' operation with no precondition. + constexpr void + _M_reset() noexcept + { static_cast<_Dp*>(this)->_M_payload._M_reset(); } + + constexpr bool _M_is_engaged() const noexcept + { return static_cast(this)->_M_payload._M_engaged; } + + // The _M_get operations have _M_engaged as a precondition. + constexpr _Tp& + _M_get() noexcept + { + __glibcxx_assert(this->_M_is_engaged()); + return static_cast<_Dp*>(this)->_M_payload._M_get(); + } + + constexpr const _Tp& + _M_get() const noexcept + { + __glibcxx_assert(this->_M_is_engaged()); + return static_cast(this)->_M_payload._M_get(); + } + }; + + /** + * @brief Class template that provides copy/move constructors of optional. + * + * Such a separate base class template is necessary in order to + * conditionally make copy/move constructors trivial. + * + * When the contained value is trivially copy/move constructible, + * the copy/move constructors of _Optional_base will invoke the + * trivial copy/move constructor of _Optional_payload. Otherwise, + * they will invoke _Optional_payload(bool, const _Optional_payload&) + * or _Optional_payload(bool, _Optional_payload&&) to initialize + * the contained value, if copying/moving an engaged optional. + * + * Whether the other special members are trivial is determined by the + * _Optional_payload<_Tp> specialization used for the _M_payload member. + * + * @see optional, _Enable_special_members + */ + template, + bool = is_trivially_move_constructible_v<_Tp>> + struct _Optional_base + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, + std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>, bool> = false> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, + __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) + : _M_payload(__other._M_payload._M_engaged, + __other._M_payload) + { } + + constexpr _Optional_base(_Optional_base&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp>) + : _M_payload(__other._M_payload._M_engaged, + std::move(__other._M_payload)) + { } + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, false, true> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, + std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>, bool> = false> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, + __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) + : _M_payload(__other._M_payload._M_engaged, + __other._M_payload) + { } + + constexpr _Optional_base(_Optional_base&& __other) = default; + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, true, false> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, + std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>, bool> = false> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, + __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) = default; + + constexpr _Optional_base(_Optional_base&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp>) + : _M_payload(__other._M_payload._M_engaged, + std::move(__other._M_payload)) + { } + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, true, true> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, + std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>, bool> = false> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, + __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) = default; + constexpr _Optional_base(_Optional_base&& __other) = default; + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + class optional; + + template + using __converts_from_optional = + __or_&>, + is_constructible<_Tp, optional<_Up>&>, + is_constructible<_Tp, const optional<_Up>&&>, + is_constructible<_Tp, optional<_Up>&&>, + is_convertible&, _Tp>, + is_convertible&, _Tp>, + is_convertible&&, _Tp>, + is_convertible&&, _Tp>>; + + template + using __assigns_from_optional = + __or_&>, + is_assignable<_Tp&, optional<_Up>&>, + is_assignable<_Tp&, const optional<_Up>&&>, + is_assignable<_Tp&, optional<_Up>&&>>; + + /** + * @brief Class template for optional values. + */ + template + class optional + : private _Optional_base<_Tp>, + private _Enable_copy_move< + // Copy constructor. + is_copy_constructible_v<_Tp>, + // Copy assignment. + __and_v, is_copy_assignable<_Tp>>, + // Move constructor. + is_move_constructible_v<_Tp>, + // Move assignment. + __and_v, is_move_assignable<_Tp>>, + // Unique tag type. + optional<_Tp>> + { + static_assert(!is_same_v, nullopt_t>); + static_assert(!is_same_v, in_place_t>); + static_assert(!is_reference_v<_Tp>); + + private: + using _Base = _Optional_base<_Tp>; + + // SFINAE helpers + template + using __not_self = __not_>>; + template + using __not_tag = __not_>>; + template + using _Requires = enable_if_t<__and_v<_Cond...>, bool>; + + public: + using value_type = _Tp; + + constexpr optional() = default; + + constexpr optional(nullopt_t) noexcept { } + + // Converting constructors for engaged optionals. + template, __not_tag<_Up>, + is_constructible<_Tp, _Up&&>, + is_convertible<_Up&&, _Tp>> = true> + constexpr + optional(_Up&& __t) + : _Base(std::in_place, std::forward<_Up>(__t)) { } + + template, __not_tag<_Up>, + is_constructible<_Tp, _Up&&>, + __not_>> = false> + explicit constexpr + optional(_Up&& __t) + : _Base(std::in_place, std::forward<_Up>(__t)) { } + + template>, + is_constructible<_Tp, const _Up&>, + is_convertible, + __not_<__converts_from_optional<_Tp, _Up>>> = true> + constexpr + optional(const optional<_Up>& __t) + { + if (__t) + emplace(*__t); + } + + template>, + is_constructible<_Tp, const _Up&>, + __not_>, + __not_<__converts_from_optional<_Tp, _Up>>> = false> + explicit constexpr + optional(const optional<_Up>& __t) + { + if (__t) + emplace(*__t); + } + + template >, + is_constructible<_Tp, _Up&&>, + is_convertible<_Up&&, _Tp>, + __not_<__converts_from_optional<_Tp, _Up>>> = true> + constexpr + optional(optional<_Up>&& __t) + { + if (__t) + emplace(std::move(*__t)); + } + + template >, + is_constructible<_Tp, _Up&&>, + __not_>, + __not_<__converts_from_optional<_Tp, _Up>>> = false> + explicit constexpr + optional(optional<_Up>&& __t) + { + if (__t) + emplace(std::move(*__t)); + } + + template> = false> + explicit constexpr + optional(in_place_t, _Args&&... __args) + : _Base(std::in_place, std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>> = false> + explicit constexpr + optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) + : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } + + // Assignment operators. + optional& + operator=(nullopt_t) noexcept + { + this->_M_reset(); + return *this; + } + + template + enable_if_t<__and_v<__not_self<_Up>, + __not_<__and_, + is_same<_Tp, decay_t<_Up>>>>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>>, + optional&> + operator=(_Up&& __u) + { + if (this->_M_is_engaged()) + this->_M_get() = std::forward<_Up>(__u); + else + this->_M_construct(std::forward<_Up>(__u)); + + return *this; + } + + template + enable_if_t<__and_v<__not_>, + is_constructible<_Tp, const _Up&>, + is_assignable<_Tp&, _Up>, + __not_<__converts_from_optional<_Tp, _Up>>, + __not_<__assigns_from_optional<_Tp, _Up>>>, + optional&> + operator=(const optional<_Up>& __u) + { + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = *__u; + else + this->_M_construct(*__u); + } + else + { + this->_M_reset(); + } + return *this; + } + + template + enable_if_t<__and_v<__not_>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>, + __not_<__converts_from_optional<_Tp, _Up>>, + __not_<__assigns_from_optional<_Tp, _Up>>>, + optional&> + operator=(optional<_Up>&& __u) + { + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = std::move(*__u); + else + this->_M_construct(std::move(*__u)); + } + else + { + this->_M_reset(); + } + + return *this; + } + + template + enable_if_t, _Tp&> + emplace(_Args&&... __args) + { + this->_M_reset(); + this->_M_construct(std::forward<_Args>(__args)...); + return this->_M_get(); + } + + template + enable_if_t&, + _Args&&...>, _Tp&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + this->_M_reset(); + this->_M_construct(__il, std::forward<_Args>(__args)...); + return this->_M_get(); + } + + // Destructor is implicit, implemented in _Optional_base. + + // Swap. + void + swap(optional& __other) + noexcept(is_nothrow_move_constructible_v<_Tp> + && is_nothrow_swappable_v<_Tp>) + { + using std::swap; + + if (this->_M_is_engaged() && __other._M_is_engaged()) + swap(this->_M_get(), __other._M_get()); + else if (this->_M_is_engaged()) + { + __other._M_construct(std::move(this->_M_get())); + this->_M_destruct(); + } + else if (__other._M_is_engaged()) + { + this->_M_construct(std::move(__other._M_get())); + __other._M_destruct(); + } + } + + // Observers. + constexpr const _Tp* + operator->() const + { return std::__addressof(this->_M_get()); } + + constexpr _Tp* + operator->() + { return std::__addressof(this->_M_get()); } + + constexpr const _Tp& + operator*() const& + { return this->_M_get(); } + + constexpr _Tp& + operator*()& + { return this->_M_get(); } + + constexpr _Tp&& + operator*()&& + { return std::move(this->_M_get()); } + + constexpr const _Tp&& + operator*() const&& + { return std::move(this->_M_get()); } + + constexpr explicit operator bool() const noexcept + { return this->_M_is_engaged(); } + + constexpr bool has_value() const noexcept + { return this->_M_is_engaged(); } + + constexpr const _Tp& + value() const& + { + return this->_M_is_engaged() + ? this->_M_get() + : (__throw_bad_optional_access(), this->_M_get()); + } + + constexpr _Tp& + value()& + { + return this->_M_is_engaged() + ? this->_M_get() + : (__throw_bad_optional_access(), this->_M_get()); + } + + constexpr _Tp&& + value()&& + { + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : (__throw_bad_optional_access(), std::move(this->_M_get())); + } + + constexpr const _Tp&& + value() const&& + { + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : (__throw_bad_optional_access(), std::move(this->_M_get())); + } + + template + constexpr _Tp + value_or(_Up&& __u) const& + { + static_assert(is_copy_constructible_v<_Tp>); + static_assert(is_convertible_v<_Up&&, _Tp>); + + return this->_M_is_engaged() + ? this->_M_get() : static_cast<_Tp>(std::forward<_Up>(__u)); + } + + template + constexpr _Tp + value_or(_Up&& __u) && + { + static_assert(is_move_constructible_v<_Tp>); + static_assert(is_convertible_v<_Up&&, _Tp>); + + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : static_cast<_Tp>(std::forward<_Up>(__u)); + } + + void reset() noexcept { this->_M_reset(); } + }; + + template + using __optional_relop_t = + enable_if_t::value, bool>; + + // Comparisons between optional values. + template + constexpr auto + operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() == declval<_Up>())> + { + return static_cast(__lhs) == static_cast(__rhs) + && (!__lhs || *__lhs == *__rhs); + } + + template + constexpr auto + operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() != declval<_Up>())> + { + return static_cast(__lhs) != static_cast(__rhs) + || (static_cast(__lhs) && *__lhs != *__rhs); + } + + template + constexpr auto + operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() < declval<_Up>())> + { + return static_cast(__rhs) && (!__lhs || *__lhs < *__rhs); + } + + template + constexpr auto + operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() > declval<_Up>())> + { + return static_cast(__lhs) && (!__rhs || *__lhs > *__rhs); + } + + template + constexpr auto + operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() <= declval<_Up>())> + { + return !__lhs || (static_cast(__rhs) && *__lhs <= *__rhs); + } + + template + constexpr auto + operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() >= declval<_Up>())> + { + return !__rhs || (static_cast(__lhs) && *__lhs >= *__rhs); + } + +#ifdef __cpp_lib_three_way_comparison + template _Up> + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) + { + return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y); + } +#endif + + // Comparisons with nullopt. + template + constexpr bool + operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + +#ifdef __cpp_lib_three_way_comparison + template + constexpr strong_ordering + operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept + { return bool(__x) <=> false; } +#else + template + constexpr bool + operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } + + template + constexpr bool + operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast(__lhs); } + + template + constexpr bool + operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast(__rhs); } + + template + constexpr bool + operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return false; } + + template + constexpr bool + operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast(__rhs); } + + template + constexpr bool + operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast(__lhs); } + + template + constexpr bool + operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return false; } + + template + constexpr bool + operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + + template + constexpr bool + operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return true; } + + template + constexpr bool + operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return true; } + + template + constexpr bool + operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } +#endif // three-way-comparison + + // Comparisons with value type. + template + constexpr auto + operator==(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() == declval<_Up>())> + { return __lhs && *__lhs == __rhs; } + + template + constexpr auto + operator==(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() == declval<_Tp>())> + { return __rhs && __lhs == *__rhs; } + + template + constexpr auto + operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() != declval<_Up>())> + { return !__lhs || *__lhs != __rhs; } + + template + constexpr auto + operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() != declval<_Tp>())> + { return !__rhs || __lhs != *__rhs; } + + template + constexpr auto + operator<(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() < declval<_Up>())> + { return !__lhs || *__lhs < __rhs; } + + template + constexpr auto + operator<(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() < declval<_Tp>())> + { return __rhs && __lhs < *__rhs; } + + template + constexpr auto + operator>(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() > declval<_Up>())> + { return __lhs && *__lhs > __rhs; } + + template + constexpr auto + operator>(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() > declval<_Tp>())> + { return !__rhs || __lhs > *__rhs; } + + template + constexpr auto + operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() <= declval<_Up>())> + { return !__lhs || *__lhs <= __rhs; } + + template + constexpr auto + operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() <= declval<_Tp>())> + { return __rhs && __lhs <= *__rhs; } + + template + constexpr auto + operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() >= declval<_Up>())> + { return __lhs && *__lhs >= __rhs; } + + template + constexpr auto + operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() >= declval<_Tp>())> + { return !__rhs || __lhs >= *__rhs; } + +#ifdef __cpp_lib_three_way_comparison + template + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(const optional<_Tp>& __x, const _Up& __v) + { return bool(__x) ? *__x <=> __v : strong_ordering::less; } +#endif + + // Swap and creation functions. + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2748. swappable traits for optionals + template + inline enable_if_t && is_swappable_v<_Tp>> + swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template + enable_if_t && is_swappable_v<_Tp>)> + swap(optional<_Tp>&, optional<_Tp>&) = delete; + + template + constexpr optional> + make_optional(_Tp&& __t) + { return optional> { std::forward<_Tp>(__t) }; } + + template + constexpr optional<_Tp> + make_optional(_Args&&... __args) + { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; } + + template + constexpr optional<_Tp> + make_optional(initializer_list<_Up> __il, _Args&&... __args) + { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; } + + // Hash. + + template, + bool = __poison_hash<_Up>::__enable_hash_call> + struct __optional_hash_call_base + { + size_t + operator()(const optional<_Tp>& __t) const + noexcept(noexcept(hash<_Up>{}(*__t))) + { + // We pick an arbitrary hash for disengaged optionals which hopefully + // usual values of _Tp won't typically hash to. + constexpr size_t __magic_disengaged_hash = static_cast(-3333); + return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; + } + }; + + template + struct __optional_hash_call_base<_Tp, _Up, false> {}; + + template + struct hash> + : private __poison_hash>, + public __optional_hash_call_base<_Tp> + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = optional<_Tp>; + }; + + template + struct __is_fast_hash>> : __is_fast_hash> + { }; + + /// @} + +#if __cpp_deduction_guides >= 201606 + template optional(_Tp) -> optional<_Tp>; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_OPTIONAL diff --git a/resources/sources/avr-libstdcpp/include/queue b/resources/sources/avr-libstdcpp/include/queue new file mode 100644 index 000000000..ef6b6fd60 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/queue @@ -0,0 +1,66 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/queue + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_QUEUE +#define _GLIBCXX_QUEUE 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#endif /* _GLIBCXX_QUEUE */ diff --git a/resources/sources/avr-libstdcpp/include/random b/resources/sources/avr-libstdcpp/include/random new file mode 100644 index 000000000..7a68ba37f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/random @@ -0,0 +1,54 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/random + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_RANDOM +#define _GLIBCXX_RANDOM 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + +#include // For uint_fast32_t, uint_fast64_t, uint_least32_t +#include +#include + +#endif // _GLIBCXX_USE_C99_STDINT_TR1 + +#endif // C++11 + +#endif // _GLIBCXX_RANDOM diff --git a/resources/sources/avr-libstdcpp/include/ranges b/resources/sources/avr-libstdcpp/include/ranges new file mode 100644 index 000000000..56800095b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ranges @@ -0,0 +1,3561 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ranges + * This is a Standard C++ Library header. + * @ingroup concepts + */ + +#ifndef _GLIBCXX_RANGES +#define _GLIBCXX_RANGES 1 + +#if __cplusplus > 201703L + +#pragma GCC system_header + +#include + +#if __cpp_lib_concepts + +#include +#include +#include +#include +#include +#include + +/** + * @defgroup ranges Ranges + * + * Components for dealing with ranges of elements. + */ + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + // [range.range] The range concept. + // [range.sized] The sized_range concept. + // Defined in + + // [range.refinements] + // Defined in + + struct view_base { }; + + template + inline constexpr bool enable_view = derived_from<_Tp, view_base>; + + template + concept view + = range<_Tp> && movable<_Tp> && default_initializable<_Tp> + && enable_view<_Tp>; + + /// A range which can be safely converted to a view. + template + concept viewable_range = range<_Tp> + && (borrowed_range<_Tp> || view>); + + namespace __detail + { + template + concept __simple_view = view<_Range> && range + && same_as, iterator_t> + && same_as, sentinel_t>; + + template + concept __has_arrow = input_iterator<_It> + && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); }); + + template + concept __not_same_as + = !same_as, remove_cvref_t<_Up>>; + } // namespace __detail + + template + requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> + class view_interface : public view_base + { + private: + constexpr _Derived& _M_derived() noexcept + { + static_assert(derived_from<_Derived, view_interface<_Derived>>); + static_assert(view<_Derived>); + return static_cast<_Derived&>(*this); + } + + constexpr const _Derived& _M_derived() const noexcept + { + static_assert(derived_from<_Derived, view_interface<_Derived>>); + static_assert(view<_Derived>); + return static_cast(*this); + } + + public: + constexpr bool + empty() requires forward_range<_Derived> + { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); } + + constexpr bool + empty() const requires forward_range + { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); } + + constexpr explicit + operator bool() requires requires { ranges::empty(_M_derived()); } + { return !ranges::empty(_M_derived()); } + + constexpr explicit + operator bool() const requires requires { ranges::empty(_M_derived()); } + { return !ranges::empty(_M_derived()); } + + constexpr auto + data() requires contiguous_iterator> + { return to_address(ranges::begin(_M_derived())); } + + constexpr auto + data() const + requires range + && contiguous_iterator> + { return to_address(ranges::begin(_M_derived())); } + + constexpr auto + size() + requires forward_range<_Derived> + && sized_sentinel_for, iterator_t<_Derived>> + { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); } + + constexpr auto + size() const + requires forward_range + && sized_sentinel_for, + iterator_t> + { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); } + + constexpr decltype(auto) + front() requires forward_range<_Derived> + { + __glibcxx_assert(!empty()); + return *ranges::begin(_M_derived()); + } + + constexpr decltype(auto) + front() const requires forward_range + { + __glibcxx_assert(!empty()); + return *ranges::begin(_M_derived()); + } + + constexpr decltype(auto) + back() + requires bidirectional_range<_Derived> && common_range<_Derived> + { + __glibcxx_assert(!empty()); + return *ranges::prev(ranges::end(_M_derived())); + } + + constexpr decltype(auto) + back() const + requires bidirectional_range + && common_range + { + __glibcxx_assert(!empty()); + return *ranges::prev(ranges::end(_M_derived())); + } + + template + constexpr decltype(auto) + operator[](range_difference_t<_Range> __n) + { return ranges::begin(_M_derived())[__n]; } + + template + constexpr decltype(auto) + operator[](range_difference_t<_Range> __n) const + { return ranges::begin(_M_derived())[__n]; } + }; + + namespace __detail + { + template + concept __convertible_to_non_slicing = convertible_to<_From, _To> + && !(is_pointer_v> && is_pointer_v> + && __not_same_as>, + remove_pointer_t>>); + + template + concept __pair_like + = !is_reference_v<_Tp> && requires(_Tp __t) + { + typename tuple_size<_Tp>::type; + requires derived_from, integral_constant>; + typename tuple_element_t<0, remove_const_t<_Tp>>; + typename tuple_element_t<1, remove_const_t<_Tp>>; + { get<0>(__t) } -> convertible_to&>; + { get<1>(__t) } -> convertible_to&>; + }; + + template + concept __pair_like_convertible_from + = !range<_Tp> && __pair_like<_Tp> + && constructible_from<_Tp, _Up, _Vp> + && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>> + && convertible_to<_Vp, tuple_element_t<1, _Tp>>; + + template + concept __iterator_sentinel_pair + = !range<_Tp> && __pair_like<_Tp> + && sentinel_for, tuple_element_t<0, _Tp>>; + + } // namespace __detail + + enum class subrange_kind : bool { unsized, sized }; + + template _Sent = _It, + subrange_kind _Kind = sized_sentinel_for<_Sent, _It> + ? subrange_kind::sized : subrange_kind::unsized> + requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>) + class subrange : public view_interface> + { + private: + // XXX: gcc complains when using constexpr here + static const bool _S_store_size + = _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>; + + _It _M_begin = _It(); + _Sent _M_end = _Sent(); + + template + struct _Size + { }; + + template + struct _Size<_Tp, true> + { __detail::__make_unsigned_like_t<_Tp> _M_size; }; + + [[no_unique_address]] _Size> _M_size = {}; + + public: + subrange() = default; + + constexpr + subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s) + requires (!_S_store_size) + : _M_begin(std::move(__i)), _M_end(__s) + { } + + constexpr + subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s, + __detail::__make_unsigned_like_t> __n) + requires (_Kind == subrange_kind::sized) + : _M_begin(std::move(__i)), _M_end(__s) + { + using __detail::__to_unsigned_like; + __glibcxx_assert(__n == __to_unsigned_like(ranges::distance(__i, __s))); + if constexpr (_S_store_size) + _M_size._M_size = __n; + } + + template<__detail::__not_same_as _Rng> + requires borrowed_range<_Rng> + && __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r) requires _S_store_size && sized_range<_Rng> + : subrange{__r, ranges::size(__r)} + { } + + template<__detail::__not_same_as _Rng> + requires borrowed_range<_Rng> + && __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r) requires (!_S_store_size) + : subrange{ranges::begin(__r), ranges::end(__r)} + { } + + template + requires __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r, + __detail::__make_unsigned_like_t> __n) + requires (_Kind == subrange_kind::sized) + : subrange{ranges::begin(__r), ranges::end(__r), __n} + { } + + template<__detail::__not_same_as _PairLike> + requires __detail::__pair_like_convertible_from<_PairLike, const _It&, + const _Sent&> + constexpr + operator _PairLike() const + { return _PairLike(_M_begin, _M_end); } + + constexpr _It + begin() const requires copyable<_It> + { return _M_begin; } + + [[nodiscard]] constexpr _It + begin() requires (!copyable<_It>) + { return std::move(_M_begin); } + + constexpr _Sent end() const { return _M_end; } + + constexpr bool empty() const { return _M_begin == _M_end; } + + constexpr __detail::__make_unsigned_like_t> + size() const requires (_Kind == subrange_kind::sized) + { + if constexpr (_S_store_size) + return _M_size._M_size; + else + return __detail::__to_unsigned_like(_M_end - _M_begin); + } + + [[nodiscard]] constexpr subrange + next(iter_difference_t<_It> __n = 1) const & + requires forward_iterator<_It> + { + auto __tmp = *this; + __tmp.advance(__n); + return __tmp; + } + + [[nodiscard]] constexpr subrange + next(iter_difference_t<_It> __n = 1) && + { + advance(__n); + return std::move(*this); + } + + [[nodiscard]] constexpr subrange + prev(iter_difference_t<_It> __n = 1) const + requires bidirectional_iterator<_It> + { + auto __tmp = *this; + __tmp.advance(-__n); + return __tmp; + } + + constexpr subrange& + advance(iter_difference_t<_It> __n) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3433. subrange::advance(n) has UB when n < 0 + if constexpr (bidirectional_iterator<_It>) + if (__n < 0) + { + ranges::advance(_M_begin, __n); + if constexpr (_S_store_size) + _M_size._M_size += __detail::__to_unsigned_like(-__n); + return *this; + } + + __glibcxx_assert(__n >= 0); + auto __d = __n - ranges::advance(_M_begin, __n, _M_end); + if constexpr (_S_store_size) + _M_size._M_size -= __detail::__to_unsigned_like(__d); + return *this; + } + }; + + template _Sent> + subrange(_It, _Sent) -> subrange<_It, _Sent>; + + template _Sent> + subrange(_It, _Sent, + __detail::__make_unsigned_like_t>) + -> subrange<_It, _Sent, subrange_kind::sized>; + + template<__detail::__iterator_sentinel_pair _Pr> + subrange(_Pr) + -> subrange, tuple_element_t<1, _Pr>>; + + template<__detail::__iterator_sentinel_pair _Pr> + subrange(_Pr, __detail::__make_unsigned_like_t>>) + -> subrange, tuple_element_t<1, _Pr>, + subrange_kind::sized>; + + template + subrange(_Rng&&) + -> subrange, sentinel_t<_Rng>, + (sized_range<_Rng> + || sized_sentinel_for, iterator_t<_Rng>>) + ? subrange_kind::sized : subrange_kind::unsized>; + + template + subrange(_Rng&&, + __detail::__make_unsigned_like_t>) + -> subrange, sentinel_t<_Rng>, subrange_kind::sized>; + + template + requires (_Num < 2) + constexpr auto + get(const subrange<_It, _Sent, _Kind>& __r) + { + if constexpr (_Num == 0) + return __r.begin(); + else + return __r.end(); + } + + template + requires (_Num < 2) + constexpr auto + get(subrange<_It, _Sent, _Kind>&& __r) + { + if constexpr (_Num == 0) + return __r.begin(); + else + return __r.end(); + } + + template _Sent, + subrange_kind _Kind> + inline constexpr bool + enable_borrowed_range> = true; + +} // namespace ranges + + using ranges::get; + +namespace ranges +{ + /// Type returned by algorithms instead of a dangling iterator or subrange. + struct dangling + { + constexpr dangling() noexcept = default; + template + constexpr dangling(_Args&&...) noexcept { } + }; + + template + using borrowed_iterator_t = conditional_t, + iterator_t<_Range>, + dangling>; + + template + using borrowed_subrange_t = conditional_t, + subrange>, + dangling>; + + template requires is_object_v<_Tp> + class empty_view + : public view_interface> + { + public: + static constexpr _Tp* begin() noexcept { return nullptr; } + static constexpr _Tp* end() noexcept { return nullptr; } + static constexpr _Tp* data() noexcept { return nullptr; } + static constexpr size_t size() noexcept { return 0; } + static constexpr bool empty() noexcept { return true; } + }; + + template + inline constexpr bool enable_borrowed_range> = true; + + namespace __detail + { + template requires is_object_v<_Tp> + struct __box : std::optional<_Tp> + { + using std::optional<_Tp>::optional; + + constexpr + __box() + noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : std::optional<_Tp>{std::in_place} + { } + + __box(const __box&) = default; + __box(__box&&) = default; + + using std::optional<_Tp>::operator=; + + __box& + operator=(const __box& __that) + noexcept(is_nothrow_copy_constructible_v<_Tp>) + requires (!assignable_from<_Tp&, const _Tp&>) + { + if ((bool)__that) + this->emplace(*__that); + else + this->reset(); + return *this; + } + + __box& + operator=(__box&& __that) + noexcept(is_nothrow_move_constructible_v<_Tp>) + requires (!assignable_from<_Tp&, _Tp>) + { + if ((bool)__that) + this->emplace(std::move(*__that)); + else + this->reset(); + return *this; + } + }; + + } // namespace __detail + + /// A view that contains exactly one element. + template requires is_object_v<_Tp> + class single_view : public view_interface> + { + public: + single_view() = default; + + constexpr explicit + single_view(const _Tp& __t) + : _M_value(__t) + { } + + constexpr explicit + single_view(_Tp&& __t) + : _M_value(std::move(__t)) + { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3428. single_view's in place constructor should be explicit + template + requires constructible_from<_Tp, _Args...> + constexpr explicit + single_view(in_place_t, _Args&&... __args) + : _M_value{in_place, std::forward<_Args>(__args)...} + { } + + constexpr _Tp* + begin() noexcept + { return data(); } + + constexpr const _Tp* + begin() const noexcept + { return data(); } + + constexpr _Tp* + end() noexcept + { return data() + 1; } + + constexpr const _Tp* + end() const noexcept + { return data() + 1; } + + static constexpr size_t + size() noexcept + { return 1; } + + constexpr _Tp* + data() noexcept + { return _M_value.operator->(); } + + constexpr const _Tp* + data() const noexcept + { return _M_value.operator->(); } + + private: + __detail::__box<_Tp> _M_value; + }; + + namespace __detail + { + template + constexpr auto __to_signed_like(_Wp __w) noexcept + { + if constexpr (!integral<_Wp>) + return iter_difference_t<_Wp>(); + else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp)) + return iter_difference_t<_Wp>(__w); + else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp)) + return ptrdiff_t(__w); + else if constexpr (sizeof(long long) > sizeof(_Wp)) + return (long long)(__w); +#ifdef __SIZEOF_INT128__ + else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp)) + return __int128(__w); +#endif + else + return __max_diff_type(__w); + } + + template + using __iota_diff_t = decltype(__to_signed_like(std::declval<_Wp>())); + + template + concept __decrementable = incrementable<_It> + && requires(_It __i) + { + { --__i } -> same_as<_It&>; + { __i-- } -> same_as<_It>; + }; + + template + concept __advanceable = __decrementable<_It> && totally_ordered<_It> + && requires( _It __i, const _It __j, const __iota_diff_t<_It> __n) + { + { __i += __n } -> same_as<_It&>; + { __i -= __n } -> same_as<_It&>; + _It(__j + __n); + _It(__n + __j); + _It(__j - __n); + { __j - __j } -> convertible_to<__iota_diff_t<_It>>; + }; + + } // namespace __detail + + template + requires std::__detail::__weakly_eq_cmp_with<_Winc, _Bound> + && semiregular<_Winc> + class iota_view : public view_interface> + { + private: + struct _Sentinel; + + struct _Iterator + { + private: + static auto + _S_iter_cat() + { + using namespace __detail; + if constexpr (__advanceable<_Winc>) + return random_access_iterator_tag{}; + else if constexpr (__decrementable<_Winc>) + return bidirectional_iterator_tag{}; + else if constexpr (incrementable<_Winc>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + public: + using iterator_category = decltype(_S_iter_cat()); + using value_type = _Winc; + using difference_type = __detail::__iota_diff_t<_Winc>; + + _Iterator() = default; + + constexpr explicit + _Iterator(_Winc __value) + : _M_value(__value) { } + + constexpr _Winc + operator*() const noexcept(is_nothrow_copy_constructible_v<_Winc>) + { return _M_value; } + + constexpr _Iterator& + operator++() + { + ++_M_value; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires incrementable<_Winc> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires __detail::__decrementable<_Winc> + { + --_M_value; + return *this; + } + + constexpr _Iterator + operator--(int) requires __detail::__decrementable<_Winc> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + if constexpr (__is_integer_like<_Winc> + && !__is_signed_integer_like<_Winc>) + { + if (__n >= difference_type(0)) + _M_value += static_cast<_Winc>(__n); + else + _M_value -= static_cast<_Winc>(-__n); + } + else + _M_value += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + if constexpr (__is_integer_like<_Winc> + && !__is_signed_integer_like<_Winc>) + { + if (__n >= difference_type(0)) + _M_value -= static_cast<_Winc>(__n); + else + _M_value += static_cast<_Winc>(-__n); + } + else + _M_value -= __n; + return *this; + } + + constexpr _Winc + operator[](difference_type __n) const + requires __detail::__advanceable<_Winc> + { return _Winc(_M_value + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Winc> + { return __x._M_value == __y._M_value; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return __x._M_value < __y._M_value; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return !(__x < __y); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> && three_way_comparable<_Winc> + { return __x._M_value <=> __y._M_value; } +#endif + + friend constexpr _Iterator + operator+(_Iterator __i, difference_type __n) + requires __detail::__advanceable<_Winc> + { return __i += __n; } + + friend constexpr _Iterator + operator+(difference_type __n, _Iterator __i) + requires __detail::__advanceable<_Winc> + { return __i += __n; } + + friend constexpr _Iterator + operator-(_Iterator __i, difference_type __n) + requires __detail::__advanceable<_Winc> + { return __i -= __n; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + using _Dt = difference_type; + if constexpr (__is_integer_like<_Winc>) + { + if constexpr (__is_signed_integer_like<_Winc>) + return _Dt(_Dt(__x._M_value) - _Dt(__y._M_value)); + else + return (__y._M_value > __x._M_value) + ? _Dt(-_Dt(__y._M_value - __x._M_value)) + : _Dt(__x._M_value - __y._M_value); + } + else + return __x._M_value - __y._M_value; + } + + private: + _Winc _M_value = _Winc(); + + friend _Sentinel; + }; + + struct _Sentinel + { + private: + constexpr bool + _M_equal(const _Iterator& __x) const + { return __x._M_value == _M_bound; } + + _Bound _M_bound = _Bound(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(_Bound __bound) + : _M_bound(__bound) { } + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __y._M_equal(__x); } + + friend constexpr iter_difference_t<_Winc> + operator-(const _Iterator& __x, const _Sentinel& __y) + requires sized_sentinel_for<_Bound, _Winc> + { return __x._M_value - __y._M_bound; } + + friend constexpr iter_difference_t<_Winc> + operator-(const _Sentinel& __x, const _Iterator& __y) + requires sized_sentinel_for<_Bound, _Winc> + { return -(__y - __x); } + }; + + _Winc _M_value = _Winc(); + _Bound _M_bound = _Bound(); + + public: + iota_view() = default; + + constexpr explicit + iota_view(_Winc __value) + : _M_value(__value) + { } + + constexpr + iota_view(type_identity_t<_Winc> __value, + type_identity_t<_Bound> __bound) + : _M_value(__value), _M_bound(__bound) + { + if constexpr (totally_ordered_with<_Winc, _Bound>) + { + __glibcxx_assert( bool(__value <= __bound) ); + } + } + + constexpr _Iterator + begin() const { return _Iterator{_M_value}; } + + constexpr auto + end() const + { + if constexpr (same_as<_Bound, unreachable_sentinel_t>) + return unreachable_sentinel; + else + return _Sentinel{_M_bound}; + } + + constexpr _Iterator + end() const requires same_as<_Winc, _Bound> + { return _Iterator{_M_bound}; } + + constexpr auto + size() const + requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>) + || (integral<_Winc> && integral<_Bound>) + || sized_sentinel_for<_Bound, _Winc> + { + using __detail::__is_integer_like; + using __detail::__to_unsigned_like; + if constexpr (__is_integer_like<_Winc> && __is_integer_like<_Bound>) + return (_M_value < 0) + ? ((_M_bound < 0) + ? __to_unsigned_like(-_M_value) - __to_unsigned_like(-_M_bound) + : __to_unsigned_like(_M_bound) + __to_unsigned_like(-_M_value)) + : __to_unsigned_like(_M_bound) - __to_unsigned_like(_M_value); + else + return __to_unsigned_like(_M_bound - _M_value); + } + }; + + template + requires (!__detail::__is_integer_like<_Winc> + || !__detail::__is_integer_like<_Bound> + || (__detail::__is_signed_integer_like<_Winc> + == __detail::__is_signed_integer_like<_Bound>)) + iota_view(_Winc, _Bound) -> iota_view<_Winc, _Bound>; + + template + inline constexpr bool + enable_borrowed_range> = true; + +namespace views +{ + template + inline constexpr empty_view<_Tp> empty{}; + + struct _Single + { + template + constexpr auto + operator()(_Tp&& __e) const + { return single_view{std::forward<_Tp>(__e)}; } + }; + + inline constexpr _Single single{}; + + struct _Iota + { + template + constexpr auto + operator()(_Tp&& __e) const + { return iota_view{std::forward<_Tp>(__e)}; } + + template + constexpr auto + operator()(_Tp&& __e, _Up&& __f) const + { return iota_view{std::forward<_Tp>(__e), std::forward<_Up>(__f)}; } + }; + + inline constexpr _Iota iota{}; +} // namespace views + +namespace __detail +{ + struct _Empty { }; + + // Alias for a type that is conditionally present + // (and is an empty type otherwise). + // Data members using this alias should use [[no_unique_address]] so that + // they take no space when not needed. + template + using __maybe_present_t = conditional_t<_Present, _Tp, _Empty>; + + // Alias for a type that is conditionally const. + template + using __maybe_const_t = conditional_t<_Const, const _Tp, _Tp>; + +} // namespace __detail + +namespace views +{ + namespace __adaptor + { + template + inline constexpr auto + __maybe_refwrap(_Tp& __arg) + { return reference_wrapper<_Tp>{__arg}; } + + template + inline constexpr auto + __maybe_refwrap(const _Tp& __arg) + { return reference_wrapper{__arg}; } + + template + inline constexpr decltype(auto) + __maybe_refwrap(_Tp&& __arg) + { return std::forward<_Tp>(__arg); } + + template + struct _RangeAdaptorClosure; + + template + struct _RangeAdaptor + { + protected: + [[no_unique_address]] + __detail::__maybe_present_t, + _Callable> _M_callable; + + public: + constexpr + _RangeAdaptor(const _Callable& = {}) + requires is_default_constructible_v<_Callable> + { } + + constexpr + _RangeAdaptor(_Callable __callable) + requires (!is_default_constructible_v<_Callable>) + : _M_callable(std::move(__callable)) + { } + + template + requires (sizeof...(_Args) >= 1) + constexpr auto + operator()(_Args&&... __args) const + { + // [range.adaptor.object]: If a range adaptor object accepts more + // than one argument, then the following expressions are equivalent: + // + // (1) adaptor(range, args...) + // (2) adaptor(args...)(range) + // (3) range | adaptor(args...) + // + // In this case, adaptor(args...) is a range adaptor closure object. + // + // We handle (1) and (2) here, and (3) is just a special case of a + // more general case already handled by _RangeAdaptorClosure. + if constexpr (is_invocable_v<_Callable, _Args...>) + { + static_assert(sizeof...(_Args) != 1, + "a _RangeAdaptor that accepts only one argument " + "should be defined as a _RangeAdaptorClosure"); + // Here we handle adaptor(range, args...) -- just forward all + // arguments to the underlying adaptor routine. + return _Callable{}(std::forward<_Args>(__args)...); + } + else + { + // Here we handle adaptor(args...)(range). + // Given args..., we return a _RangeAdaptorClosure that takes a + // range argument, such that (2) is equivalent to (1). + // + // We need to be careful about how we capture args... in this + // closure. By using __maybe_refwrap, we capture lvalue + // references by reference (through a reference_wrapper) and + // otherwise capture by value. + auto __closure + = [...__args(__maybe_refwrap(std::forward<_Args>(__args)))] + (_Range&& __r) { + // This static_cast has two purposes: it forwards a + // reference_wrapper capture as a T&, and otherwise + // forwards the captured argument as an rvalue. + return _Callable{}(std::forward<_Range>(__r), + (static_cast>> + (__args))...); + }; + using _ClosureType = decltype(__closure); + return _RangeAdaptorClosure<_ClosureType>(std::move(__closure)); + } + } + }; + + template + _RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>; + + template + struct _RangeAdaptorClosure : public _RangeAdaptor<_Callable> + { + using _RangeAdaptor<_Callable>::_RangeAdaptor; + + template + requires requires { declval<_Callable>()(declval<_Range>()); } + constexpr auto + operator()(_Range&& __r) const + { + if constexpr (is_default_constructible_v<_Callable>) + return _Callable{}(std::forward<_Range>(__r)); + else + return this->_M_callable(std::forward<_Range>(__r)); + } + + template + requires requires { declval<_Callable>()(declval<_Range>()); } + friend constexpr auto + operator|(_Range&& __r, const _RangeAdaptorClosure& __o) + { return __o(std::forward<_Range>(__r)); } + + template + friend constexpr auto + operator|(const _RangeAdaptorClosure<_Tp>& __x, + const _RangeAdaptorClosure& __y) + { + if constexpr (is_default_constructible_v<_Tp> + && is_default_constructible_v<_Callable>) + { + auto __closure = [] (_Up&& __e) { + return std::forward<_Up>(__e) | decltype(__x){} | decltype(__y){}; + }; + return _RangeAdaptorClosure(__closure); + } + else if constexpr (is_default_constructible_v<_Tp> + && !is_default_constructible_v<_Callable>) + { + auto __closure = [__y] (_Up&& __e) { + return std::forward<_Up>(__e) | decltype(__x){} | __y; + }; + return _RangeAdaptorClosure(__closure); + } + else if constexpr (!is_default_constructible_v<_Tp> + && is_default_constructible_v<_Callable>) + { + auto __closure = [__x] (_Up&& __e) { + return std::forward<_Up>(__e) | __x | decltype(__y){}; + }; + return _RangeAdaptorClosure(__closure); + } + else + { + auto __closure = [__x, __y] (_Up&& __e) { + return std::forward<_Up>(__e) | __x | __y; + }; + return _RangeAdaptorClosure(__closure); + } + } + }; + + template + _RangeAdaptorClosure(_Callable) -> _RangeAdaptorClosure<_Callable>; + } // namespace __adaptor +} // namespace views + + template requires is_object_v<_Range> + class ref_view : public view_interface> + { + private: + _Range* _M_r = nullptr; + + static void _S_fun(_Range&); // not defined + static void _S_fun(_Range&&) = delete; + + public: + constexpr + ref_view() noexcept = default; + + template<__detail::__not_same_as _Tp> + requires convertible_to<_Tp, _Range&> + && requires { _S_fun(declval<_Tp>()); } + constexpr + ref_view(_Tp&& __t) + : _M_r(std::__addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) + { } + + constexpr _Range& + base() const + { return *_M_r; } + + constexpr iterator_t<_Range> + begin() const + { return ranges::begin(*_M_r); } + + constexpr sentinel_t<_Range> + end() const + { return ranges::end(*_M_r); } + + constexpr bool + empty() const requires requires { ranges::empty(*_M_r); } + { return ranges::empty(*_M_r); } + + constexpr auto + size() const requires sized_range<_Range> + { return ranges::size(*_M_r); } + + constexpr auto + data() const requires contiguous_range<_Range> + { return ranges::data(*_M_r); } + }; + + template + ref_view(_Range&) -> ref_view<_Range>; + + template + inline constexpr bool enable_borrowed_range> = true; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptorClosure all + = [] (_Range&& __r) + { + if constexpr (view>) + return std::forward<_Range>(__r); + else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; }) + return ref_view{std::forward<_Range>(__r)}; + else + return subrange{std::forward<_Range>(__r)}; + }; + + template + using all_t = decltype(all(std::declval<_Range>())); + + } // namespace views + + // XXX: the following algos are copied from ranges_algo.h to avoid a circular + // dependency with that header. + namespace __detail + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + find_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + while (__first != __last + && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + find_if_not(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + while (__first != __last + && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template> + _Comp = ranges::less> + constexpr const _Tp& + min(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; + else + return __a; + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr pair<_Iter1, _Iter2> + mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2 + && (bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + ++__first1; + ++__first2; + } + return { std::move(__first1), std::move(__first2) }; + } + } // namespace __detail + + namespace __detail + { + template + struct _CachedPosition + { + constexpr bool + _M_has_value() const + { return false; } + + constexpr iterator_t<_Range> + _M_get(const _Range&) const + { + __glibcxx_assert(false); + return {}; + } + + constexpr void + _M_set(const _Range&, const iterator_t<_Range>&) const + { } + }; + + template + struct _CachedPosition<_Range> + { + private: + iterator_t<_Range> _M_iter{}; + + public: + constexpr bool + _M_has_value() const + { return _M_iter != iterator_t<_Range>{}; } + + constexpr iterator_t<_Range> + _M_get(const _Range&) const + { + __glibcxx_assert(_M_has_value()); + return _M_iter; + } + + constexpr void + _M_set(const _Range&, const iterator_t<_Range>& __it) + { + __glibcxx_assert(!_M_has_value()); + _M_iter = __it; + } + }; + + template + requires (sizeof(range_difference_t<_Range>) + <= sizeof(iterator_t<_Range>)) + struct _CachedPosition<_Range> + { + private: + range_difference_t<_Range> _M_offset = -1; + + public: + constexpr bool + _M_has_value() const + { return _M_offset >= 0; } + + constexpr iterator_t<_Range> + _M_get(_Range& __r) const + { + __glibcxx_assert(_M_has_value()); + return ranges::begin(__r) + _M_offset; + } + + constexpr void + _M_set(_Range& __r, const iterator_t<_Range>& __it) + { + __glibcxx_assert(!_M_has_value()); + _M_offset = __it - ranges::begin(__r); + } + }; + + } // namespace __detail + + template> _Pred> + requires view<_Vp> && is_object_v<_Pred> + class filter_view : public view_interface> + { + private: + struct _Sentinel; + + struct _Iterator + { + private: + static constexpr auto + _S_iter_concept() + { + if constexpr (bidirectional_range<_Vp>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Vp>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + static constexpr auto + _S_iter_cat() + { + using _Cat = typename iterator_traits<_Vp_iter>::iterator_category; + if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return _Cat{}; + } + + friend filter_view; + + using _Vp_iter = iterator_t<_Vp>; + + _Vp_iter _M_current = _Vp_iter(); + filter_view* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + using iterator_category = decltype(_S_iter_cat()); + using value_type = range_value_t<_Vp>; + using difference_type = range_difference_t<_Vp>; + + _Iterator() = default; + + constexpr + _Iterator(filter_view& __parent, _Vp_iter __current) + : _M_current(std::move(__current)), + _M_parent(std::__addressof(__parent)) + { } + + constexpr _Vp_iter + base() const & + requires copyable<_Vp_iter> + { return _M_current; } + + constexpr _Vp_iter + base() && + { return std::move(_M_current); } + + constexpr range_reference_t<_Vp> + operator*() const + { return *_M_current; } + + constexpr _Vp_iter + operator->() const + requires __detail::__has_arrow<_Vp_iter> + && copyable<_Vp_iter> + { return _M_current; } + + constexpr _Iterator& + operator++() + { + _M_current = __detail::find_if(std::move(++_M_current), + ranges::end(_M_parent->_M_base), + std::ref(*_M_parent->_M_pred)); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Vp> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Vp> + { + do + --_M_current; + while (!std::__invoke(*_M_parent->_M_pred, *_M_current)); + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Vp> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Vp_iter> + { return __x._M_current == __y._M_current; } + + friend constexpr range_rvalue_reference_t<_Vp> + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + requires indirectly_swappable<_Vp_iter> + { ranges::iter_swap(__x._M_current, __y._M_current); } + }; + + struct _Sentinel + { + private: + sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); + + constexpr bool + __equal(const _Iterator& __i) const + { return __i._M_current == _M_end; } + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(filter_view& __parent) + : _M_end(ranges::end(__parent._M_base)) + { } + + constexpr sentinel_t<_Vp> + base() const + { return _M_end; } + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + }; + + _Vp _M_base = _Vp(); + __detail::__box<_Pred> _M_pred; + [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; + + public: + filter_view() = default; + + constexpr + filter_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr _Iterator + begin() + { + if (_M_cached_begin._M_has_value()) + return {*this, _M_cached_begin._M_get(_M_base)}; + + __glibcxx_assert(_M_pred.has_value()); + auto __it = __detail::find_if(ranges::begin(_M_base), + ranges::end(_M_base), + std::ref(*_M_pred)); + _M_cached_begin._M_set(_M_base, __it); + return {*this, std::move(__it)}; + } + + constexpr auto + end() + { + if constexpr (common_range<_Vp>) + return _Iterator{*this, ranges::end(_M_base)}; + else + return _Sentinel{*this}; + } + }; + + template + filter_view(_Range&&, _Pred) -> filter_view, _Pred>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor filter + = [] (_Range&& __r, _Pred&& __p) + { + return filter_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)}; + }; + } // namespace views + + template + requires view<_Vp> && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vp>> + && std::__detail::__can_reference>> + class transform_view : public view_interface> + { + private: + template + struct _Sentinel; + + template + struct _Iterator + { + private: + using _Parent = __detail::__maybe_const_t<_Const, transform_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + static constexpr auto + _S_iter_concept() + { + if constexpr (random_access_range<_Vp>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Vp>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Vp>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + static constexpr auto + _S_iter_cat() + { + using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>; + if constexpr (is_lvalue_reference_v<_Res>) + { + using _Cat + = typename iterator_traits<_Base_iter>::iterator_category; + if constexpr (derived_from<_Cat, contiguous_iterator_tag>) + return random_access_iterator_tag{}; + else + return _Cat{}; + } + else + return input_iterator_tag{}; + } + + using _Base_iter = iterator_t<_Base>; + + _Base_iter _M_current = _Base_iter(); + _Parent* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + using iterator_category = decltype(_S_iter_cat()); + using value_type + = remove_cvref_t>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Parent& __parent, _Base_iter __current) + : _M_current(std::move(__current)), + _M_parent(std::__addressof(__parent)) + { } + + constexpr + _Iterator(_Iterator __i) + requires _Const + && convertible_to, _Base_iter> + : _M_current(std::move(__i._M_current)), _M_parent(__i._M_parent) + { } + + constexpr _Base_iter + base() const & + requires copyable<_Base_iter> + { return _M_current; } + + constexpr _Base_iter + base() && + { return std::move(_M_current); } + + constexpr decltype(auto) + operator*() const + noexcept(noexcept(std::__invoke(*_M_parent->_M_fun, *_M_current))) + { return std::__invoke(*_M_parent->_M_fun, *_M_current); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + return *this; + } + + constexpr void + operator++(int) + { ++_M_current; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires random_access_range<_Base> + { + _M_current += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires random_access_range<_Base> + { + _M_current -= __n; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const + requires random_access_range<_Base> + { return std::__invoke(*_M_parent->_M_fun, _M_current[__n]); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Base_iter> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable<_Base_iter> + { return __x._M_current <=> __y._M_current; } +#endif + + friend constexpr _Iterator + operator+(_Iterator __i, difference_type __n) + requires random_access_range<_Base> + { return {*__i._M_parent, __i._M_current + __n}; } + + friend constexpr _Iterator + operator+(difference_type __n, _Iterator __i) + requires random_access_range<_Base> + { return {*__i._M_parent, __i._M_current + __n}; } + + friend constexpr _Iterator + operator-(_Iterator __i, difference_type __n) + requires random_access_range<_Base> + { return {*__i._M_parent, __i._M_current - __n}; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current - __y._M_current; } + + friend constexpr decltype(auto) + iter_move(const _Iterator& __i) noexcept(noexcept(*__i)) + { + if constexpr (is_lvalue_reference_v) + return std::move(*__i); + else + return *__i; + } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + requires indirectly_swappable<_Base_iter> + { return ranges::iter_swap(__x._M_current, __y._M_current); } + + friend _Iterator; + template friend struct _Sentinel; + }; + + template + struct _Sentinel + { + private: + using _Parent = __detail::__maybe_const_t<_Const, transform_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + constexpr auto + __distance_from(const _Iterator<_Const2>& __i) const + { return _M_end - __i._M_current; } + + template + constexpr bool + __equal(const _Iterator<_Const2>& __i) const + { return __i._M_current == _M_end; } + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + constexpr + _Sentinel(_Sentinel __i) + requires _Const + && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__i._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return -__y.__distance_from(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Sentinel& __y, const _Iterator<_Const2>& __x) + { return __y.__distance_from(__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + __detail::__box<_Fp> _M_fun; + + public: + transform_view() = default; + + constexpr + transform_view(_Vp __base, _Fp __fun) + : _M_base(std::move(__base)), _M_fun(std::move(__fun)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base ; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr _Iterator + begin() + { return _Iterator{*this, ranges::begin(_M_base)}; } + + constexpr _Iterator + begin() const + requires range + && regular_invocable> + { return _Iterator{*this, ranges::begin(_M_base)}; } + + constexpr _Sentinel + end() + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr _Iterator + end() requires common_range<_Vp> + { return _Iterator{*this, ranges::end(_M_base)}; } + + constexpr _Sentinel + end() const + requires range + && regular_invocable> + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr _Iterator + end() const + requires common_range + && regular_invocable> + { return _Iterator{*this, ranges::end(_M_base)}; } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + transform_view(_Range&&, _Fp) -> transform_view, _Fp>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor transform + = [] (_Range&& __r, _Fp&& __f) + { + return transform_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)}; + }; + } // namespace views + + template + class take_view : public view_interface> + { + private: + template + struct _Sentinel + { + private: + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + using _CI = counted_iterator>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__s._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + friend constexpr bool operator==(const _CI& __y, const _Sentinel& __x) + { return __y.count() == 0 || __y.base() == __x._M_end; } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; + + public: + take_view() = default; + + constexpr + take_view(_Vp base, range_difference_t<_Vp> __count) + : _M_base(std::move(base)), _M_count(std::move(__count)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (sized_range<_Vp>) + { + if constexpr (random_access_range<_Vp>) + return ranges::begin(_M_base); + else + { + auto __sz = size(); + return counted_iterator{ranges::begin(_M_base), __sz}; + } + } + else + return counted_iterator{ranges::begin(_M_base), _M_count}; + } + + constexpr auto + begin() const requires range + { + if constexpr (sized_range) + { + if constexpr (random_access_range) + return ranges::begin(_M_base); + else + { + auto __sz = size(); + return counted_iterator{ranges::begin(_M_base), __sz}; + } + } + else + return counted_iterator{ranges::begin(_M_base), _M_count}; + } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (sized_range<_Vp>) + { + if constexpr (random_access_range<_Vp>) + return ranges::begin(_M_base) + size(); + else + return default_sentinel; + } + else + return _Sentinel{ranges::end(_M_base)}; + } + + constexpr auto + end() const requires range + { + if constexpr (sized_range) + { + if constexpr (random_access_range) + return ranges::begin(_M_base) + size(); + else + return default_sentinel; + } + else + return _Sentinel{ranges::end(_M_base)}; + } + + constexpr auto + size() requires sized_range<_Vp> + { + auto __n = ranges::size(_M_base); + return __detail::min(__n, static_cast(_M_count)); + } + + constexpr auto + size() const requires sized_range + { + auto __n = ranges::size(_M_base); + return __detail::min(__n, static_cast(_M_count)); + } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3447. Deduction guides for take_view and drop_view have different + // constraints + template + take_view(_Range&&, range_difference_t<_Range>) + -> take_view>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor take + = [] (_Range&& __r, _Tp&& __n) + { + return take_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)}; + }; + } // namespace views + + template + requires input_range<_Vp> && is_object_v<_Pred> + && indirect_unary_predicate> + class take_while_view : public view_interface> + { + template + struct _Sentinel + { + private: + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + const _Pred* _M_pred = nullptr; + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end, const _Pred* __pred) + : _M_end(__end), _M_pred(__pred) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(__s._M_end), _M_pred(__s._M_pred) + { } + + constexpr sentinel_t<_Base> + base() const { return _M_end; } + + friend constexpr bool + operator==(const iterator_t<_Base>& __x, const _Sentinel& __y) + { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + __detail::__box<_Pred> _M_pred; + + public: + take_while_view() = default; + + constexpr + take_while_view(_Vp base, _Pred __pred) + : _M_base(std::move(base)), _M_pred(std::move(__pred)) + { + } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return ranges::begin(_M_base); } + + constexpr auto + begin() const requires range + && indirect_unary_predicate> + { return ranges::begin(_M_base); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return _Sentinel(ranges::end(_M_base), + std::__addressof(*_M_pred)); } + + constexpr auto + end() const requires range + && indirect_unary_predicate> + { return _Sentinel(ranges::end(_M_base), + std::__addressof(*_M_pred)); } + }; + + template + take_while_view(_Range&&, _Pred) + -> take_while_view, _Pred>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor take_while + = [] (_Range&& __r, _Pred&& __p) + { + return take_while_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)}; + }; + } // namespace views + + template + class drop_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; + + static constexpr bool _S_needs_cached_begin = !random_access_range<_Vp>; + [[no_unique_address]] + __detail::__maybe_present_t<_S_needs_cached_begin, + __detail::_CachedPosition<_Vp>> + _M_cached_begin; + + public: + drop_view() = default; + + constexpr + drop_view(_Vp __base, range_difference_t<_Vp> __count) + : _M_base(std::move(__base)), _M_count(__count) + { __glibcxx_assert(__count >= 0); } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!(__detail::__simple_view<_Vp> + && random_access_range<_Vp>)) + { + if constexpr (_S_needs_cached_begin) + if (_M_cached_begin._M_has_value()) + return _M_cached_begin._M_get(_M_base); + + auto __it = ranges::next(ranges::begin(_M_base), + _M_count, ranges::end(_M_base)); + if constexpr (_S_needs_cached_begin) + _M_cached_begin._M_set(_M_base, __it); + return __it; + } + + constexpr auto + begin() const requires random_access_range + { + return ranges::next(ranges::begin(_M_base), _M_count, + ranges::end(_M_base)); + } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return ranges::end(_M_base); } + + constexpr auto + end() const requires range + { return ranges::end(_M_base); } + + constexpr auto + size() requires sized_range<_Vp> + { + const auto __s = ranges::size(_M_base); + const auto __c = static_cast(_M_count); + return __s < __c ? 0 : __s - __c; + } + + constexpr auto + size() const requires sized_range + { + const auto __s = ranges::size(_M_base); + const auto __c = static_cast(_M_count); + return __s < __c ? 0 : __s - __c; + } + }; + + template + drop_view(_Range&&, range_difference_t<_Range>) + -> drop_view>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor drop + = [] (_Range&& __r, _Tp&& __n) + { + return drop_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)}; + }; + } // namespace views + + template + requires input_range<_Vp> && is_object_v<_Pred> + && indirect_unary_predicate> + class drop_while_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + __detail::__box<_Pred> _M_pred; + [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; + + public: + drop_while_view() = default; + + constexpr + drop_while_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr auto + begin() + { + if (_M_cached_begin._M_has_value()) + return _M_cached_begin._M_get(_M_base); + + auto __it = __detail::find_if_not(ranges::begin(_M_base), + ranges::end(_M_base), + std::cref(*_M_pred)); + _M_cached_begin._M_set(_M_base, __it); + return __it; + } + + constexpr auto + end() + { return ranges::end(_M_base); } + }; + + template + drop_while_view(_Range&&, _Pred) + -> drop_while_view, _Pred>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor drop_while + = [] (_Range&& __r, _Pred&& __p) + { + return drop_while_view{std::forward<_Range>(__r), + std::forward<_Pred>(__p)}; + }; + } // namespace views + + template + requires view<_Vp> && input_range> + && (is_reference_v> + || view>) + class join_view : public view_interface> + { + private: + using _InnerRange = range_reference_t<_Vp>; + + template + struct _Sentinel; + + template + struct _Iterator + { + private: + using _Parent = __detail::__maybe_const_t<_Const, join_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + static constexpr bool _S_ref_is_glvalue + = is_reference_v>; + + constexpr void + _M_satisfy() + { + auto __update_inner = [this] (range_reference_t<_Base> __x) -> auto& + { + if constexpr (_S_ref_is_glvalue) + return __x; + else + return (_M_parent->_M_inner = views::all(std::move(__x))); + }; + + for (; _M_outer != ranges::end(_M_parent->_M_base); ++_M_outer) + { + auto& inner = __update_inner(*_M_outer); + _M_inner = ranges::begin(inner); + if (_M_inner != ranges::end(inner)) + return; + } + + if constexpr (_S_ref_is_glvalue) + _M_inner = _Inner_iter(); + } + + static constexpr auto + _S_iter_concept() + { + if constexpr (_S_ref_is_glvalue + && bidirectional_range<_Base> + && bidirectional_range>) + return bidirectional_iterator_tag{}; + else if constexpr (_S_ref_is_glvalue + && forward_range<_Base> + && forward_range>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + static constexpr auto + _S_iter_cat() + { + using _OuterCat + = typename iterator_traits<_Outer_iter>::iterator_category; + using _InnerCat + = typename iterator_traits<_Inner_iter>::iterator_category; + if constexpr (_S_ref_is_glvalue + && derived_from<_OuterCat, bidirectional_iterator_tag> + && derived_from<_InnerCat, bidirectional_iterator_tag>) + return bidirectional_iterator_tag{}; + else if constexpr (_S_ref_is_glvalue + && derived_from<_OuterCat, forward_iterator_tag> + && derived_from<_InnerCat, forward_iterator_tag>) + return forward_iterator_tag{}; + else if constexpr (derived_from<_OuterCat, input_iterator_tag> + && derived_from<_InnerCat, input_iterator_tag>) + return input_iterator_tag{}; + else + return output_iterator_tag{}; + } + + using _Outer_iter = iterator_t<_Base>; + using _Inner_iter = iterator_t>; + + _Outer_iter _M_outer = _Outer_iter(); + _Inner_iter _M_inner = _Inner_iter(); + _Parent* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + using iterator_category = decltype(_S_iter_cat()); + using value_type = range_value_t>; + using difference_type + = common_type_t, + range_difference_t>>; + + _Iterator() = default; + + constexpr + _Iterator(_Parent& __parent, _Outer_iter __outer) + : _M_outer(std::move(__outer)), + _M_parent(std::__addressof(__parent)) + { _M_satisfy(); } + + constexpr + _Iterator(_Iterator __i) + requires _Const + && convertible_to, _Outer_iter> + && convertible_to, _Inner_iter> + : _M_outer(std::move(__i._M_outer)), _M_inner(__i._M_inner), + _M_parent(__i._M_parent) + { } + + constexpr decltype(auto) + operator*() const + { return *_M_inner; } + + constexpr _Outer_iter + operator->() const + requires __detail::__has_arrow<_Outer_iter> + && copyable<_Outer_iter> + { return _M_inner; } + + constexpr _Iterator& + operator++() + { + auto&& __inner_range = [this] () -> decltype(auto) { + if constexpr (_S_ref_is_glvalue) + return *_M_outer; + else + return _M_parent->_M_inner; + }(); + if (++_M_inner == ranges::end(__inner_range)) + { + ++_M_outer; + _M_satisfy(); + } + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) + requires _S_ref_is_glvalue && forward_range<_Base> + && forward_range> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires _S_ref_is_glvalue && bidirectional_range<_Base> + && bidirectional_range> + && common_range> + { + if (_M_outer == ranges::end(_M_parent->_M_base)) + _M_inner = ranges::end(*--_M_outer); + while (_M_inner == ranges::begin(*_M_outer)) + _M_inner = ranges::end(*--_M_outer); + --_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) + requires _S_ref_is_glvalue && bidirectional_range<_Base> + && bidirectional_range> + && common_range> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires _S_ref_is_glvalue + && equality_comparable<_Outer_iter> + && equality_comparable<_Inner_iter> + { + return (__x._M_outer == __y._M_outer + && __x._M_inner == __y._M_inner); + } + + friend constexpr decltype(auto) + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_inner))) + { return ranges::iter_move(__i._M_inner); } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_inner, __y._M_inner))) + { return ranges::iter_swap(__x._M_inner, __y._M_inner); } + + friend _Iterator; + template friend struct _Sentinel; + }; + + template + struct _Sentinel + { + private: + using _Parent = __detail::__maybe_const_t<_Const, join_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + constexpr bool + __equal(const _Iterator<_Const2>& __i) const + { return __i._M_outer == _M_end; } + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(_Parent& __parent) + : _M_end(ranges::end(__parent._M_base)) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__s._M_end)) + { } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + + // XXX: _M_inner is "present only when !is_reference_v<_InnerRange>" + [[no_unique_address]] + __detail::__maybe_present_t, + views::all_t<_InnerRange>> _M_inner; + + public: + join_view() = default; + + constexpr explicit + join_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + constexpr bool __use_const + = (__detail::__simple_view<_Vp> + && is_reference_v>); + return _Iterator<__use_const>{*this, ranges::begin(_M_base)}; + } + + constexpr auto + begin() const + requires input_range + && is_reference_v> + { + return _Iterator{*this, ranges::begin(_M_base)}; + } + + constexpr auto + end() + { + if constexpr (forward_range<_Vp> && is_reference_v<_InnerRange> + && forward_range<_InnerRange> + && common_range<_Vp> && common_range<_InnerRange>) + return _Iterator<__detail::__simple_view<_Vp>>{*this, + ranges::end(_M_base)}; + else + return _Sentinel<__detail::__simple_view<_Vp>>{*this}; + } + + constexpr auto + end() const + requires input_range + && is_reference_v> + { + if constexpr (forward_range + && is_reference_v> + && forward_range> + && common_range + && common_range>) + return _Iterator{*this, ranges::end(_M_base)}; + else + return _Sentinel{*this}; + } + }; + + template + explicit join_view(_Range&&) -> join_view>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptorClosure join + = [] (_Range&& __r) + { + return join_view{std::forward<_Range>(__r)}; + }; + } // namespace views + + namespace __detail + { + template + struct __require_constant; + + template + concept __tiny_range = sized_range<_Range> + && requires + { typename __require_constant::size()>; } + && (remove_reference_t<_Range>::size() <= 1); + } + + template + requires view<_Vp> && view<_Pattern> + && indirectly_comparable, iterator_t<_Pattern>, + ranges::equal_to> + && (forward_range<_Vp> || __detail::__tiny_range<_Pattern>) + class split_view : public view_interface> + { + private: + template + struct _InnerIter; + + template + struct _OuterIter + { + private: + using _Parent = __detail::__maybe_const_t<_Const, split_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + constexpr bool + __at_end() const + { return __current() == ranges::end(_M_parent->_M_base); } + + // [range.split.outer] p1 + // Many of the following specifications refer to the notional member + // current of outer-iterator. current is equivalent to current_ if + // V models forward_range, and parent_->current_ otherwise. + constexpr auto& + __current() noexcept + { + if constexpr (forward_range<_Vp>) + return _M_current; + else + return _M_parent->_M_current; + } + + constexpr auto& + __current() const noexcept + { + if constexpr (forward_range<_Vp>) + return _M_current; + else + return _M_parent->_M_current; + } + + _Parent* _M_parent = nullptr; + + // XXX: _M_current is present only if "V models forward_range" + [[no_unique_address]] + __detail::__maybe_present_t, + iterator_t<_Base>> _M_current; + + public: + using iterator_concept = conditional_t, + forward_iterator_tag, + input_iterator_tag>; + using iterator_category = input_iterator_tag; + using difference_type = range_difference_t<_Base>; + + struct value_type : view_interface + { + private: + _OuterIter _M_i = _OuterIter(); + + public: + value_type() = default; + + constexpr explicit + value_type(_OuterIter __i) + : _M_i(std::move(__i)) + { } + + constexpr _InnerIter<_Const> + begin() const + requires copyable<_OuterIter> + { return _InnerIter<_Const>{_M_i}; } + + constexpr _InnerIter<_Const> + begin() + requires (!copyable<_OuterIter>) + { return _InnerIter<_Const>{std::move(_M_i)}; } + + constexpr default_sentinel_t + end() const + { return default_sentinel; } + }; + + _OuterIter() = default; + + constexpr explicit + _OuterIter(_Parent& __parent) requires (!forward_range<_Base>) + : _M_parent(std::__addressof(__parent)) + { } + + constexpr + _OuterIter(_Parent& __parent, iterator_t<_Base> __current) + requires forward_range<_Base> + : _M_parent(std::__addressof(__parent)), + _M_current(std::move(__current)) + { } + + constexpr + _OuterIter(_OuterIter __i) + requires _Const + && convertible_to, iterator_t<_Base>> + : _M_parent(__i._M_parent), _M_current(std::move(__i._M_current)) + { } + + constexpr value_type + operator*() const + { return value_type{*this}; } + + constexpr _OuterIter& + operator++() + { + const auto __end = ranges::end(_M_parent->_M_base); + if (__current() == __end) + return *this; + const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern}; + if (__pbegin == __pend) + ++__current(); + else + do + { + auto [__b, __p] + = __detail::mismatch(std::move(__current()), __end, + __pbegin, __pend); + __current() = std::move(__b); + if (__p == __pend) + break; + } while (++__current() != __end); + return *this; + } + + constexpr decltype(auto) + operator++(int) + { + if constexpr (forward_range<_Base>) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + else + ++*this; + } + + friend constexpr bool + operator==(const _OuterIter& __x, const _OuterIter& __y) + requires forward_range<_Base> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator==(const _OuterIter& __x, default_sentinel_t) + { return __x.__at_end(); }; + + friend _OuterIter; + friend _InnerIter<_Const>; + }; + + template + struct _InnerIter + { + private: + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + constexpr bool + __at_end() const + { + auto [__pcur, __pend] = subrange{_M_i._M_parent->_M_pattern}; + auto __end = ranges::end(_M_i._M_parent->_M_base); + if constexpr (__detail::__tiny_range<_Pattern>) + { + const auto& __cur = _M_i_current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return _M_incremented; + return *__cur == *__pcur; + } + else + { + auto __cur = _M_i_current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return _M_incremented; + do + { + if (*__cur != *__pcur) + return false; + if (++__pcur == __pend) + return true; + } while (++__cur != __end); + return false; + } + } + + static constexpr auto + _S_iter_cat() + { + using _Cat + = typename iterator_traits>::iterator_category; + if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return _Cat{}; + } + + constexpr auto& + _M_i_current() noexcept + { return _M_i.__current(); } + + constexpr auto& + _M_i_current() const noexcept + { return _M_i.__current(); } + + _OuterIter<_Const> _M_i = _OuterIter<_Const>(); + bool _M_incremented = false; + + public: + using iterator_concept + = typename _OuterIter<_Const>::iterator_concept; + using iterator_category = decltype(_S_iter_cat()); + using value_type = range_value_t<_Base>; + using difference_type = range_difference_t<_Base>; + + _InnerIter() = default; + + constexpr explicit + _InnerIter(_OuterIter<_Const> __i) + : _M_i(std::move(__i)) + { } + + constexpr decltype(auto) + operator*() const + { return *_M_i_current(); } + + constexpr _InnerIter& + operator++() + { + _M_incremented = true; + if constexpr (!forward_range<_Base>) + if constexpr (_Pattern::size() == 0) + return *this; + ++_M_i_current(); + return *this; + } + + constexpr decltype(auto) + operator++(int) + { + if constexpr (forward_range<_Vp>) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + else + ++*this; + } + + friend constexpr bool + operator==(const _InnerIter& __x, const _InnerIter& __y) + requires forward_range<_Base> + { return __x._M_i == __y._M_i; } + + friend constexpr bool + operator==(const _InnerIter& __x, default_sentinel_t) + { return __x.__at_end(); } + + friend constexpr decltype(auto) + iter_move(const _InnerIter& __i) + noexcept(noexcept(ranges::iter_move(__i._M_i_current()))) + { return ranges::iter_move(__i._M_i_current()); } + + friend constexpr void + iter_swap(const _InnerIter& __x, const _InnerIter& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_i_current(), + __y._M_i_current()))) + requires indirectly_swappable> + { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); } + }; + + _Vp _M_base = _Vp(); + _Pattern _M_pattern = _Pattern(); + + // XXX: _M_current is "present only if !forward_range" + [[no_unique_address]] + __detail::__maybe_present_t, iterator_t<_Vp>> + _M_current; + + + public: + split_view() = default; + + constexpr + split_view(_Vp __base, _Pattern __pattern) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) + { } + + template + requires constructible_from<_Vp, views::all_t<_Range>> + && constructible_from<_Pattern, single_view>> + constexpr + split_view(_Range&& __r, range_value_t<_Range> __e) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(std::move(__e)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + if constexpr (forward_range<_Vp>) + return _OuterIter<__detail::__simple_view<_Vp>>{ + *this, ranges::begin(_M_base)}; + else + { + _M_current = ranges::begin(_M_base); + return _OuterIter{*this}; + } + } + + constexpr auto + begin() const requires forward_range<_Vp> && forward_range + { + return _OuterIter{*this, ranges::begin(_M_base)}; + } + + constexpr auto + end() requires forward_range<_Vp> && common_range<_Vp> + { + return _OuterIter<__detail::__simple_view<_Vp>>{ + *this, ranges::end(_M_base)}; + } + + constexpr auto + end() const + { + if constexpr (forward_range<_Vp> + && forward_range + && common_range) + return _OuterIter{*this, ranges::end(_M_base)}; + else + return default_sentinel; + } + }; + + template + split_view(_Range&&, _Pred&&) + -> split_view, views::all_t<_Pred>>; + + template + split_view(_Range&&, range_value_t<_Range>) + -> split_view, single_view>>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor split + = [] (_Range&& __r, _Fp&& __f) + { + return split_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)}; + }; + } // namespace views + + namespace views + { + struct _Counted + { + template + constexpr auto + operator()(_Iter __i, iter_difference_t<_Iter> __n) const + { + if constexpr (random_access_iterator<_Iter>) + return subrange{__i, __i + __n}; + else + return subrange{counted_iterator{std::move(__i), __n}, + default_sentinel}; + } + }; + + inline constexpr _Counted counted{}; + } // namespace views + + template + requires (!common_range<_Vp>) && copyable> + class common_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + + public: + common_view() = default; + + constexpr explicit + common_view(_Vp __r) + : _M_base(std::move(__r)) + { } + + /* XXX: LWG 3280 didn't remove this constructor, but I think it should? + template + requires (!common_range<_Range>) + && constructible_from<_Vp, views::all_t<_Range>> + constexpr explicit + common_view(_Range&& __r) + : _M_base(views::all(std::forward<_Range>(__r))) + { } + */ + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + if constexpr (random_access_range<_Vp> && sized_range<_Vp>) + return ranges::begin(_M_base); + else + return common_iterator, sentinel_t<_Vp>> + (ranges::begin(_M_base)); + } + + constexpr auto + begin() const requires range + { + if constexpr (random_access_range && sized_range) + return ranges::begin(_M_base); + else + return common_iterator, sentinel_t> + (ranges::begin(_M_base)); + } + + constexpr auto + end() + { + if constexpr (random_access_range<_Vp> && sized_range<_Vp>) + return ranges::begin(_M_base) + ranges::size(_M_base); + else + return common_iterator, sentinel_t<_Vp>> + (ranges::end(_M_base)); + } + + constexpr auto + end() const requires range + { + if constexpr (random_access_range && sized_range) + return ranges::begin(_M_base) + ranges::size(_M_base); + else + return common_iterator, sentinel_t> + (ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + common_view(_Range&&) -> common_view>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptorClosure common + = [] (_Range&& __r) + { + if constexpr (common_range<_Range> + && requires { views::all(std::forward<_Range>(__r)); }) + return views::all(std::forward<_Range>(__r)); + else + return common_view{std::forward<_Range>(__r)}; + }; + + } // namespace views + + template + requires bidirectional_range<_Vp> + class reverse_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + + static constexpr bool _S_needs_cached_begin + = !common_range<_Vp> && !random_access_range<_Vp>; + [[no_unique_address]] + __detail::__maybe_present_t<_S_needs_cached_begin, + __detail::_CachedPosition<_Vp>> + _M_cached_begin; + + public: + reverse_view() = default; + + constexpr explicit + reverse_view(_Vp __r) + : _M_base(std::move(__r)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr reverse_iterator> + begin() + { + if constexpr (_S_needs_cached_begin) + if (_M_cached_begin._M_has_value()) + return make_reverse_iterator(_M_cached_begin._M_get(_M_base)); + + auto __it = ranges::next(ranges::begin(_M_base), ranges::end(_M_base)); + if constexpr (_S_needs_cached_begin) + _M_cached_begin._M_set(_M_base, __it); + return make_reverse_iterator(std::move(__it)); + } + + constexpr auto + begin() requires common_range<_Vp> + { return make_reverse_iterator(ranges::end(_M_base)); } + + constexpr auto + begin() const requires common_range + { return make_reverse_iterator(ranges::end(_M_base)); } + + constexpr reverse_iterator> + end() + { return make_reverse_iterator(ranges::begin(_M_base)); } + + constexpr auto + end() const requires common_range + { return make_reverse_iterator(ranges::begin(_M_base)); } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + reverse_view(_Range&&) -> reverse_view>; + + namespace views + { + namespace __detail + { + template + inline constexpr bool __is_reversible_subrange = false; + + template + inline constexpr bool + __is_reversible_subrange, + reverse_iterator<_Iter>, + _Kind>> = true; + + template + inline constexpr bool __is_reverse_view = false; + + template + inline constexpr bool __is_reverse_view> = true; + } + + inline constexpr __adaptor::_RangeAdaptorClosure reverse + = [] (_Range&& __r) + { + using _Tp = remove_cvref_t<_Range>; + if constexpr (__detail::__is_reverse_view<_Tp>) + return std::forward<_Range>(__r).base(); + else if constexpr (__detail::__is_reversible_subrange<_Tp>) + { + using _Iter = decltype(ranges::begin(__r).base()); + if constexpr (sized_range<_Tp>) + return subrange<_Iter, _Iter, subrange_kind::sized> + (__r.end().base(), __r.begin().base(), __r.size()); + else + return subrange<_Iter, _Iter, subrange_kind::unsized> + (__r.end().base(), __r.begin().base()); + } + else + return reverse_view{std::forward<_Range>(__r)}; + }; + } // namespace views + + namespace __detail + { + template + concept __has_tuple_element = requires(_Tp __t) + { + typename tuple_size<_Tp>::type; + requires _Nm < tuple_size_v<_Tp>; + typename tuple_element_t<_Nm, _Tp>; + { std::get<_Nm>(__t) } + -> convertible_to&>; + }; + } + + template + requires view<_Vp> + && __detail::__has_tuple_element, _Nm> + && __detail::__has_tuple_element>, + _Nm> + class elements_view : public view_interface> + { + public: + elements_view() = default; + + constexpr explicit + elements_view(_Vp base) + : _M_base(std::move(base)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(ranges::begin(_M_base)); } + + constexpr auto + begin() const requires range + { return _Iterator(ranges::begin(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp> && !common_range<_Vp>) + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp> && common_range<_Vp>) + { return _Iterator{ranges::end(_M_base)}; } + + constexpr auto + end() const requires range + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr auto + end() const requires common_range + { return _Iterator{ranges::end(_M_base)}; } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + + private: + template + struct _Sentinel; + + template + struct _Iterator + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + + friend _Iterator; + + public: + using iterator_category + = typename iterator_traits>::iterator_category; + using value_type + = remove_cvref_t>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr explicit + _Iterator(iterator_t<_Base> current) + : _M_current(std::move(current)) + { } + + constexpr + _Iterator(_Iterator i) + requires _Const && convertible_to, iterator_t<_Base>> + : _M_current(std::move(i._M_current)) + { } + + constexpr iterator_t<_Base> + base() const& + requires copyable> + { return _M_current; } + + constexpr iterator_t<_Base> + base() && + { return std::move(_M_current); } + + constexpr decltype(auto) + operator*() const + { return std::get<_Nm>(*_M_current); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + return *this; + } + + constexpr void + operator++(int) requires (!forward_range<_Base>) + { ++_M_current; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++_M_current; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --_M_current; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) + requires random_access_range<_Base> + { + _M_current += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) + requires random_access_range<_Base> + { + _M_current -= __n; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const + requires random_access_range<_Base> + { return std::get<_Nm>(*(_M_current + __n)); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y._M_current < __x._M_current; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y._M_current > __x._M_current); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x._M_current > __y._M_current); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current <=> __y._M_current; } +#endif + + friend constexpr _Iterator + operator+(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return _Iterator{__x} += __y; } + + friend constexpr _Iterator + operator+(difference_type __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y + __x; } + + friend constexpr _Iterator + operator-(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return _Iterator{__x} -= __y; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current - __y._M_current; } + + friend _Sentinel<_Const>; + }; + + template + struct _Sentinel + { + private: + constexpr bool + _M_equal(const _Iterator<_Const>& __x) const + { return __x._M_current == _M_end; } + + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(std::move(__end)) + { } + + constexpr + _Sentinel(_Sentinel __other) + requires _Const + && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__other._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y._M_equal(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __x._M_current - __y._M_end; } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base> + operator-(const _Sentinel& __x, const _Iterator<_Const2>& __y) + { return __x._M_end - __y._M_current; } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + }; + + template + using keys_view = elements_view, 0>; + + template + using values_view = elements_view, 1>; + + namespace views + { + template + inline constexpr __adaptor::_RangeAdaptorClosure elements + = [] (_Range&& __r) + { + using _El = elements_view, _Nm>; + return _El{std::forward<_Range>(__r)}; + }; + + inline constexpr __adaptor::_RangeAdaptorClosure keys = elements<0>; + inline constexpr __adaptor::_RangeAdaptorClosure values = elements<1>; + } // namespace views + +} // namespace ranges + + namespace views = ranges::views; + + template + struct tuple_size> + : integral_constant + { }; + + template + struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Iter; }; + + template + struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Sent; }; + + template + struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Iter; }; + + template + struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Sent; }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // library concepts +#endif // C++2a +#endif /* _GLIBCXX_RANGES */ diff --git a/resources/sources/avr-libstdcpp/include/ratio b/resources/sources/avr-libstdcpp/include/ratio new file mode 100644 index 000000000..83c8c7927 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ratio @@ -0,0 +1,576 @@ +// ratio -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ratio + * This is a Standard C++ Library header. + * @ingroup ratio + */ + +#ifndef _GLIBCXX_RATIO +#define _GLIBCXX_RATIO 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include // intmax_t, uintmax_t + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup ratio Rational Arithmetic + * @ingroup utilities + * + * Compile time representation of finite rational numbers. + * @{ + */ + + /// @cond undocumented + + template + struct __static_sign + : integral_constant + { }; + + template + struct __static_abs + : integral_constant::value> + { }; + + template + struct __static_gcd + : __static_gcd<_Qn, (_Pn % _Qn)> + { }; + + template + struct __static_gcd<_Pn, 0> + : integral_constant::value> + { }; + + template + struct __static_gcd<0, _Qn> + : integral_constant::value> + { }; + + // Let c = 2^(half # of bits in an intmax_t) + // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0 + // The multiplication of N and M becomes, + // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0 + // Multiplication is safe if each term and the sum of the terms + // is representable by intmax_t. + template + struct __safe_multiply + { + private: + static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + + static const uintmax_t __a0 = __static_abs<_Pn>::value % __c; + static const uintmax_t __a1 = __static_abs<_Pn>::value / __c; + static const uintmax_t __b0 = __static_abs<_Qn>::value % __c; + static const uintmax_t __b1 = __static_abs<_Qn>::value / __c; + + static_assert(__a1 == 0 || __b1 == 0, + "overflow in multiplication"); + static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), + "overflow in multiplication"); + static_assert(__b0 * __a0 <= __INTMAX_MAX__, + "overflow in multiplication"); + static_assert((__a0 * __b1 + __b0 * __a1) * __c + <= __INTMAX_MAX__ - __b0 * __a0, + "overflow in multiplication"); + + public: + static const intmax_t value = _Pn * _Qn; + }; + + // Some double-precision utilities, where numbers are represented as + // __hi*2^(8*sizeof(uintmax_t)) + __lo. + template + struct __big_less + : integral_constant + { }; + + template + struct __big_add + { + static constexpr uintmax_t __lo = __lo1 + __lo2; + static constexpr uintmax_t __hi = (__hi1 + __hi2 + + (__lo1 + __lo2 < __lo1)); // carry + }; + + // Subtract a number from a bigger one. + template + struct __big_sub + { + static_assert(!__big_less<__hi1, __lo1, __hi2, __lo2>::value, + "Internal library error"); + static constexpr uintmax_t __lo = __lo1 - __lo2; + static constexpr uintmax_t __hi = (__hi1 - __hi2 - + (__lo1 < __lo2)); // carry + }; + + // Same principle as __safe_multiply. + template + struct __big_mul + { + private: + static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + static constexpr uintmax_t __x0 = __x % __c; + static constexpr uintmax_t __x1 = __x / __c; + static constexpr uintmax_t __y0 = __y % __c; + static constexpr uintmax_t __y1 = __y / __c; + static constexpr uintmax_t __x0y0 = __x0 * __y0; + static constexpr uintmax_t __x0y1 = __x0 * __y1; + static constexpr uintmax_t __x1y0 = __x1 * __y0; + static constexpr uintmax_t __x1y1 = __x1 * __y1; + static constexpr uintmax_t __mix = __x0y1 + __x1y0; // possible carry... + static constexpr uintmax_t __mix_lo = __mix * __c; + static constexpr uintmax_t __mix_hi + = __mix / __c + ((__mix < __x0y1) ? __c : 0); // ... added here + typedef __big_add<__mix_hi, __mix_lo, __x1y1, __x0y0> _Res; + public: + static constexpr uintmax_t __hi = _Res::__hi; + static constexpr uintmax_t __lo = _Res::__lo; + }; + + // Adapted from __udiv_qrnnd_c in longlong.h + // This version assumes that the high bit of __d is 1. + template + struct __big_div_impl + { + private: + static_assert(__d >= (uintmax_t(1) << (sizeof(intmax_t) * 8 - 1)), + "Internal library error"); + static_assert(__n1 < __d, "Internal library error"); + static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + static constexpr uintmax_t __d1 = __d / __c; + static constexpr uintmax_t __d0 = __d % __c; + + static constexpr uintmax_t __q1x = __n1 / __d1; + static constexpr uintmax_t __r1x = __n1 % __d1; + static constexpr uintmax_t __m = __q1x * __d0; + static constexpr uintmax_t __r1y = __r1x * __c + __n0 / __c; + static constexpr uintmax_t __r1z = __r1y + __d; + static constexpr uintmax_t __r1 + = ((__r1y < __m) ? ((__r1z >= __d) && (__r1z < __m)) + ? (__r1z + __d) : __r1z : __r1y) - __m; + static constexpr uintmax_t __q1 + = __q1x - ((__r1y < __m) + ? ((__r1z >= __d) && (__r1z < __m)) ? 2 : 1 : 0); + static constexpr uintmax_t __q0x = __r1 / __d1; + static constexpr uintmax_t __r0x = __r1 % __d1; + static constexpr uintmax_t __n = __q0x * __d0; + static constexpr uintmax_t __r0y = __r0x * __c + __n0 % __c; + static constexpr uintmax_t __r0z = __r0y + __d; + static constexpr uintmax_t __r0 + = ((__r0y < __n) ? ((__r0z >= __d) && (__r0z < __n)) + ? (__r0z + __d) : __r0z : __r0y) - __n; + static constexpr uintmax_t __q0 + = __q0x - ((__r0y < __n) ? ((__r0z >= __d) + && (__r0z < __n)) ? 2 : 1 : 0); + + public: + static constexpr uintmax_t __quot = __q1 * __c + __q0; + static constexpr uintmax_t __rem = __r0; + + private: + typedef __big_mul<__quot, __d> _Prod; + typedef __big_add<_Prod::__hi, _Prod::__lo, 0, __rem> _Sum; + static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, + "Internal library error"); + }; + + template + struct __big_div + { + private: + static_assert(__d != 0, "Internal library error"); + static_assert(sizeof (uintmax_t) == sizeof (unsigned long long), + "This library calls __builtin_clzll on uintmax_t, which " + "is unsafe on your platform. Please complain to " + "http://gcc.gnu.org/bugzilla/"); + static constexpr int __shift = __builtin_clzll(__d); + static constexpr int __coshift_ = sizeof(uintmax_t) * 8 - __shift; + static constexpr int __coshift = (__shift != 0) ? __coshift_ : 0; + static constexpr uintmax_t __c1 = uintmax_t(1) << __shift; + static constexpr uintmax_t __c2 = uintmax_t(1) << __coshift; + static constexpr uintmax_t __new_d = __d * __c1; + static constexpr uintmax_t __new_n0 = __n0 * __c1; + static constexpr uintmax_t __n1_shifted = (__n1 % __d) * __c1; + static constexpr uintmax_t __n0_top = (__shift != 0) ? (__n0 / __c2) : 0; + static constexpr uintmax_t __new_n1 = __n1_shifted + __n0_top; + typedef __big_div_impl<__new_n1, __new_n0, __new_d> _Res; + + public: + static constexpr uintmax_t __quot_hi = __n1 / __d; + static constexpr uintmax_t __quot_lo = _Res::__quot; + static constexpr uintmax_t __rem = _Res::__rem / __c1; + + private: + typedef __big_mul<__quot_lo, __d> _P0; + typedef __big_mul<__quot_hi, __d> _P1; + typedef __big_add<_P0::__hi, _P0::__lo, _P1::__lo, __rem> _Sum; + // No overflow. + static_assert(_P1::__hi == 0, "Internal library error"); + static_assert(_Sum::__hi >= _P0::__hi, "Internal library error"); + // Matches the input data. + static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, + "Internal library error"); + static_assert(__rem < __d, "Internal library error"); + }; + + /// @endcond + + /** + * @brief Provides compile-time rational arithmetic. + * + * This class template represents any finite rational number with a + * numerator and denominator representable by compile-time constants of + * type intmax_t. The ratio is simplified when instantiated. + * + * For example: + * @code + * std::ratio<7,-21>::num == -1; + * std::ratio<7,-21>::den == 3; + * @endcode + * + */ + template + struct ratio + { + static_assert(_Den != 0, "denominator cannot be zero"); + static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__, + "out of range"); + + // Note: sign(N) * abs(N) == N + static constexpr intmax_t num = + _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value; + + static constexpr intmax_t den = + __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value; + + typedef ratio type; + }; + + template + constexpr intmax_t ratio<_Num, _Den>::num; + + template + constexpr intmax_t ratio<_Num, _Den>::den; + + /// @cond undocumented + + template + struct __ratio_multiply + { + private: + static const intmax_t __gcd1 = + __static_gcd<_R1::num, _R2::den>::value; + static const intmax_t __gcd2 = + __static_gcd<_R2::num, _R1::den>::value; + + public: + typedef ratio< + __safe_multiply<(_R1::num / __gcd1), + (_R2::num / __gcd2)>::value, + __safe_multiply<(_R1::den / __gcd2), + (_R2::den / __gcd1)>::value> type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + + template + constexpr intmax_t __ratio_multiply<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_multiply<_R1, _R2>::den; + + /// @endcond + + /// ratio_multiply + template + using ratio_multiply = typename __ratio_multiply<_R1, _R2>::type; + + /// @cond undocumented + + template + struct __ratio_divide + { + static_assert(_R2::num != 0, "division by 0"); + + typedef typename __ratio_multiply< + _R1, + ratio<_R2::den, _R2::num>>::type type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + + template + constexpr intmax_t __ratio_divide<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_divide<_R1, _R2>::den; + + /// @endcond + + /// ratio_divide + template + using ratio_divide = typename __ratio_divide<_R1, _R2>::type; + + /// ratio_equal + template + struct ratio_equal + : integral_constant + { }; + + /// ratio_not_equal + template + struct ratio_not_equal + : integral_constant::value> + { }; + + /// @cond undocumented + + // Both numbers are positive. + template, + typename _Right = __big_mul<_R2::num,_R1::den> > + struct __ratio_less_impl_1 + : integral_constant::value> + { }; + + template::value + != __static_sign<_R2::num>::value)), + bool = (__static_sign<_R1::num>::value == -1 + && __static_sign<_R2::num>::value == -1)> + struct __ratio_less_impl + : __ratio_less_impl_1<_R1, _R2>::type + { }; + + template + struct __ratio_less_impl<_R1, _R2, true, false> + : integral_constant + { }; + + template + struct __ratio_less_impl<_R1, _R2, false, true> + : __ratio_less_impl_1, + ratio<-_R1::num, _R1::den> >::type + { }; + + /// @endcond + + /// ratio_less + template + struct ratio_less + : __ratio_less_impl<_R1, _R2>::type + { }; + + /// ratio_less_equal + template + struct ratio_less_equal + : integral_constant::value> + { }; + + /// ratio_greater + template + struct ratio_greater + : integral_constant::value> + { }; + + /// ratio_greater_equal + template + struct ratio_greater_equal + : integral_constant::value> + { }; + +#if __cplusplus > 201402L + template + inline constexpr bool ratio_equal_v = ratio_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_not_equal_v = ratio_not_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_less_v = ratio_less<_R1, _R2>::value; + template + inline constexpr bool ratio_less_equal_v = + ratio_less_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_greater_v = ratio_greater<_R1, _R2>::value; + template + inline constexpr bool ratio_greater_equal_v + = ratio_greater_equal<_R1, _R2>::value; +#endif // C++17 + + /// @cond undocumented + + template= 0), + bool = (_R2::num >= 0), + bool = ratio_less::value, _R1::den>, + ratio<__static_abs<_R2::num>::value, _R2::den> >::value> + struct __ratio_add_impl + { + private: + typedef typename __ratio_add_impl< + ratio<-_R1::num, _R1::den>, + ratio<-_R2::num, _R2::den> >::type __t; + public: + typedef ratio<-__t::num, __t::den> type; + }; + + // True addition of nonnegative numbers. + template + struct __ratio_add_impl<_R1, _R2, true, true, __b> + { + private: + static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; + static constexpr uintmax_t __d2 = _R2::den / __g; + typedef __big_mul<_R1::den, __d2> __d; + typedef __big_mul<_R1::num, _R2::den / __g> __x; + typedef __big_mul<_R2::num, _R1::den / __g> __y; + typedef __big_add<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; + static_assert(__n::__hi >= __x::__hi, "Internal library error"); + typedef __big_div<__n::__hi, __n::__lo, __g> __ng; + static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; + typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; + static_assert(__n_final::__rem == 0, "Internal library error"); + static_assert(__n_final::__quot_hi == 0 && + __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); + typedef __big_mul<_R1::den / __g2, __d2> __d_final; + static_assert(__d_final::__hi == 0 && + __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); + public: + typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; + }; + + template + struct __ratio_add_impl<_R1, _R2, false, true, true> + : __ratio_add_impl<_R2, _R1> + { }; + + // True subtraction of nonnegative numbers yielding a nonnegative result. + template + struct __ratio_add_impl<_R1, _R2, true, false, false> + { + private: + static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; + static constexpr uintmax_t __d2 = _R2::den / __g; + typedef __big_mul<_R1::den, __d2> __d; + typedef __big_mul<_R1::num, _R2::den / __g> __x; + typedef __big_mul<-_R2::num, _R1::den / __g> __y; + typedef __big_sub<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; + typedef __big_div<__n::__hi, __n::__lo, __g> __ng; + static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; + typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; + static_assert(__n_final::__rem == 0, "Internal library error"); + static_assert(__n_final::__quot_hi == 0 && + __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); + typedef __big_mul<_R1::den / __g2, __d2> __d_final; + static_assert(__d_final::__hi == 0 && + __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); + public: + typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; + }; + + template + struct __ratio_add + { + typedef typename __ratio_add_impl<_R1, _R2>::type type; + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + + template + constexpr intmax_t __ratio_add<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_add<_R1, _R2>::den; + + /// @endcond + + /// ratio_add + template + using ratio_add = typename __ratio_add<_R1, _R2>::type; + + /// @cond undocumented + + template + struct __ratio_subtract + { + typedef typename __ratio_add< + _R1, + ratio<-_R2::num, _R2::den>>::type type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + + template + constexpr intmax_t __ratio_subtract<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_subtract<_R1, _R2>::den; + + /// @endcond + + /// ratio_subtract + template + using ratio_subtract = typename __ratio_subtract<_R1, _R2>::type; + + + typedef ratio<1, 1000000000000000000> atto; + typedef ratio<1, 1000000000000000> femto; + typedef ratio<1, 1000000000000> pico; + typedef ratio<1, 1000000000> nano; + typedef ratio<1, 1000000> micro; + typedef ratio<1, 1000> milli; + typedef ratio<1, 100> centi; + typedef ratio<1, 10> deci; + typedef ratio< 10, 1> deca; + typedef ratio< 100, 1> hecto; + typedef ratio< 1000, 1> kilo; + typedef ratio< 1000000, 1> mega; + typedef ratio< 1000000000, 1> giga; + typedef ratio< 1000000000000, 1> tera; + typedef ratio< 1000000000000000, 1> peta; + typedef ratio< 1000000000000000000, 1> exa; + + // @} group ratio +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif //_GLIBCXX_RATIO diff --git a/resources/sources/avr-libstdcpp/include/scoped_allocator b/resources/sources/avr-libstdcpp/include/scoped_allocator new file mode 100644 index 000000000..969b6d8e8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/scoped_allocator @@ -0,0 +1,519 @@ +// -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/scoped_allocator + * This is a Standard C++ Library header. + * @ingroup allocators + */ + +#ifndef _SCOPED_ALLOCATOR +#define _SCOPED_ALLOCATOR 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup allocators + * @{ + */ + + /// @cond undocumented + + template + using __outer_allocator_t + = decltype(std::declval<_Alloc>().outer_allocator()); + + template + struct __outermost_type + { + using type = _Alloc; + static type& _S_outermost(_Alloc& __a) { return __a; } + }; + + template + struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>> + : __outermost_type< + typename remove_reference<__outer_allocator_t<_Alloc>>::type + > + { + using __base = __outermost_type< + typename remove_reference<__outer_allocator_t<_Alloc>>::type + >; + + static typename __base::type& + _S_outermost(_Alloc& __a) + { return __base::_S_outermost(__a.outer_allocator()); } + }; + + /// Implementation of the OUTERMOST pseudofunction + template + inline typename __outermost_type<_Alloc>::type& + __outermost(_Alloc& __a) + { return __outermost_type<_Alloc>::_S_outermost(__a); } + + template + class scoped_allocator_adaptor; + + template + struct __inner_type_impl; + + template + struct __inner_type_impl<_Outer> + { + typedef scoped_allocator_adaptor<_Outer> __type; + + __inner_type_impl() = default; + __inner_type_impl(const __inner_type_impl&) = default; + __inner_type_impl(__inner_type_impl&&) = default; + __inner_type_impl& operator=(const __inner_type_impl&) = default; + __inner_type_impl& operator=(__inner_type_impl&&) = default; + + template + __inner_type_impl(const __inner_type_impl<_Alloc>& __other) + { } + + template + __inner_type_impl(__inner_type_impl<_Alloc>&& __other) + { } + + __type& + _M_get(__type* __p) noexcept { return *__p; } + + const __type& + _M_get(const __type* __p) const noexcept { return *__p; } + + tuple<> + _M_tie() const noexcept { return tuple<>(); } + + bool + operator==(const __inner_type_impl&) const noexcept + { return true; } + }; + + template + struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> + { + typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; + + __inner_type_impl() = default; + __inner_type_impl(const __inner_type_impl&) = default; + __inner_type_impl(__inner_type_impl&&) = default; + __inner_type_impl& operator=(const __inner_type_impl&) = default; + __inner_type_impl& operator=(__inner_type_impl&&) = default; + + template + __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) + : _M_inner(__other._M_inner) { } + + template + __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) + : _M_inner(std::move(__other._M_inner)) { } + + template + explicit + __inner_type_impl(_Args&&... __args) + : _M_inner(std::forward<_Args>(__args)...) { } + + __type& + _M_get(void*) noexcept { return _M_inner; } + + const __type& + _M_get(const void*) const noexcept { return _M_inner; } + + tuple + _M_tie() const noexcept + { return _M_inner._M_tie(); } + + bool + operator==(const __inner_type_impl& __other) const noexcept + { return _M_inner == __other._M_inner; } + + private: + template friend class __inner_type_impl; + template friend class scoped_allocator_adaptor; + + __type _M_inner; + }; + + /// @endcond + + /// An adaptor to recursively pass an allocator to the objects it constructs + template + class scoped_allocator_adaptor + : public _OuterAlloc + { + typedef allocator_traits<_OuterAlloc> __traits; + + typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; + __inner_type _M_inner; + + template + friend class scoped_allocator_adaptor; + + template + friend class __inner_type_impl; + + tuple + _M_tie() const noexcept + { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } + + template + using __outermost_alloc_traits + = allocator_traits::type>; + +#if __cplusplus <= 201703 + template + void + _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + std::forward<_Args>(__args)...); + } + + typedef __uses_alloc1 __uses_alloc1_; + typedef __uses_alloc2 __uses_alloc2_; + + template + void + _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + allocator_arg, inner_allocator(), + std::forward<_Args>(__args)...); + } + + template + void + _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + std::forward<_Args>(__args)..., + inner_allocator()); + } +#endif // C++17 + + template + static _Alloc + _S_select_on_copy(const _Alloc& __a) + { + typedef allocator_traits<_Alloc> __a_traits; + return __a_traits::select_on_container_copy_construction(__a); + } + + template + scoped_allocator_adaptor(tuple __refs, + _Index_tuple<_Indices...>) + : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), + _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) + { } + + // Used to constrain constructors to disallow invalid conversions. + template + using _Constructible = typename enable_if< + is_constructible<_OuterAlloc, _Alloc>::value + >::type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2975. Missing case for pair construction in scoped [...] allocators + template + struct __not_pair { using type = void; }; + + template + struct __not_pair> { }; + + public: + typedef _OuterAlloc outer_allocator_type; + typedef typename __inner_type::__type inner_allocator_type; + + typedef typename __traits::value_type value_type; + typedef typename __traits::size_type size_type; + typedef typename __traits::difference_type difference_type; + typedef typename __traits::pointer pointer; + typedef typename __traits::const_pointer const_pointer; + typedef typename __traits::void_pointer void_pointer; + typedef typename __traits::const_void_pointer const_void_pointer; + + typedef typename __or_< + typename __traits::propagate_on_container_copy_assignment, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_copy_assignment...>::type + propagate_on_container_copy_assignment; + + typedef typename __or_< + typename __traits::propagate_on_container_move_assignment, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_move_assignment...>::type + propagate_on_container_move_assignment; + + typedef typename __or_< + typename __traits::propagate_on_container_swap, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_swap...>::type + propagate_on_container_swap; + + typedef typename __and_< + typename __traits::is_always_equal, + typename allocator_traits<_InnerAllocs>::is_always_equal...>::type + is_always_equal; + + template + struct rebind + { + typedef scoped_allocator_adaptor< + typename __traits::template rebind_alloc<_Tp>, + _InnerAllocs...> other; + }; + + scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } + + template> + scoped_allocator_adaptor(_Outer2&& __outer, + const _InnerAllocs&... __inner) + : _OuterAlloc(std::forward<_Outer2>(__outer)), + _M_inner(__inner...) + { } + + scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) + : _OuterAlloc(__other.outer_allocator()), + _M_inner(__other._M_inner) + { } + + scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) + : _OuterAlloc(std::move(__other.outer_allocator())), + _M_inner(std::move(__other._M_inner)) + { } + + template> + scoped_allocator_adaptor( + const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) + : _OuterAlloc(__other.outer_allocator()), + _M_inner(__other._M_inner) + { } + + template> + scoped_allocator_adaptor( + scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) + : _OuterAlloc(std::move(__other.outer_allocator())), + _M_inner(std::move(__other._M_inner)) + { } + + scoped_allocator_adaptor& + operator=(const scoped_allocator_adaptor&) = default; + + scoped_allocator_adaptor& + operator=(scoped_allocator_adaptor&&) = default; + + inner_allocator_type& inner_allocator() noexcept + { return _M_inner._M_get(this); } + + const inner_allocator_type& inner_allocator() const noexcept + { return _M_inner._M_get(this); } + + outer_allocator_type& outer_allocator() noexcept + { return static_cast<_OuterAlloc&>(*this); } + + const outer_allocator_type& outer_allocator() const noexcept + { return static_cast(*this); } + + _GLIBCXX_NODISCARD pointer allocate(size_type __n) + { return __traits::allocate(outer_allocator(), __n); } + + _GLIBCXX_NODISCARD pointer allocate(size_type __n, const_void_pointer __hint) + { return __traits::allocate(outer_allocator(), __n, __hint); } + + void deallocate(pointer __p, size_type __n) + { return __traits::deallocate(outer_allocator(), __p, __n); } + + size_type max_size() const + { return __traits::max_size(outer_allocator()); } + +#if __cplusplus <= 201703 + template + typename __not_pair<_Tp>::type + construct(_Tp* __p, _Args&&... __args) + { + auto& __inner = inner_allocator(); + auto __use_tag + = std::__use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); + _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); + } + + template + void + construct(pair<_T1, _T2>* __p, piecewise_construct_t, + tuple<_Args1...> __x, tuple<_Args2...> __y) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2203. wrong argument types for piecewise construction + auto& __inner = inner_allocator(); + auto __x_use_tag + = std::__use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); + auto __y_use_tag + = std::__use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); + typename _Build_index_tuple::__type __x_indices; + typename _Build_index_tuple::__type __y_indices; + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, piecewise_construct, + _M_construct_p(__x_use_tag, __x_indices, __x), + _M_construct_p(__y_use_tag, __y_indices, __y)); + } + + template + void + construct(pair<_T1, _T2>* __p) + { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } + + template + void + construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(std::forward<_Up>(__u)), + std::forward_as_tuple(std::forward<_Vp>(__v))); + } + + template + void + construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(__x.first), + std::forward_as_tuple(__x.second)); + } + + template + void + construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(std::forward<_Up>(__x.first)), + std::forward_as_tuple(std::forward<_Vp>(__x.second))); + } +#else // C++2a + template + __attribute__((__nonnull__)) + void + construct(_Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + std::apply([__p, this](auto&&... __newargs) { + _O_traits::construct(__outermost(*this), __p, + std::forward(__newargs)...); + }, + uses_allocator_construction_args<_Tp>(inner_allocator(), + std::forward<_Args>(__args)...)); + } +#endif // C++2a + + template + void destroy(_Tp* __p) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::destroy(__outermost(*this), __p); + } + + scoped_allocator_adaptor + select_on_container_copy_construction() const + { + typedef typename _Build_index_tuple::__type + _Indices; + return scoped_allocator_adaptor(_M_tie(), _Indices()); + } + + template + friend bool + operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; + + private: +#if __cplusplus <= 201703L + template + tuple<_Args&&...> + _M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) + { return std::move(__t); } + + template + tuple + _M_construct_p(__uses_alloc1_, _Index_tuple<_Ind...>, + tuple<_Args...>& __t) + { + return { allocator_arg, inner_allocator(), + std::get<_Ind>(std::move(__t))... + }; + } + + template + tuple<_Args&&..., inner_allocator_type&> + _M_construct_p(__uses_alloc2_, _Index_tuple<_Ind...>, + tuple<_Args...>& __t) + { + return { std::get<_Ind>(std::move(__t))..., inner_allocator() }; + } +#endif // C++17 + }; + + /// @related std::scoped_allocator_adaptor + template + inline bool + operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept + { + return __a.outer_allocator() == __b.outer_allocator() + && __a._M_inner == __b._M_inner; + } + +#if __cpp_impl_three_way_comparison < 201907L + /// @related std::scoped_allocator_adaptor + template + inline bool + operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept + { return !(__a == __b); } +#endif + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _SCOPED_ALLOCATOR diff --git a/resources/sources/avr-libstdcpp/include/set b/resources/sources/avr-libstdcpp/include/set new file mode 100644 index 000000000..168918346 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/set @@ -0,0 +1,105 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/set + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_SET +#define _GLIBCXX_SET 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template> + using set = std::set<_Key, _Cmp, polymorphic_allocator<_Key>>; + template> + using multiset = std::multiset<_Key, _Cmp, polymorphic_allocator<_Key>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template + inline typename set<_Key, _Compare, _Alloc>::size_type + erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } + + template + inline typename multiset<_Key, _Compare, _Alloc>::size_type + erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_SET */ diff --git a/resources/sources/avr-libstdcpp/include/shared_mutex b/resources/sources/avr-libstdcpp/include/shared_mutex new file mode 100644 index 000000000..343886107 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/shared_mutex @@ -0,0 +1,855 @@ +// -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/shared_mutex + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_SHARED_MUTEX +#define _GLIBCXX_SHARED_MUTEX 1 + +#pragma GCC system_header + +#if __cplusplus >= 201402L + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup mutexes + * @{ + */ + +#ifdef _GLIBCXX_HAS_GTHREADS + +#if __cplusplus >= 201703L +#define __cpp_lib_shared_mutex 201505 + class shared_mutex; +#endif + +#define __cpp_lib_shared_timed_mutex 201402 + class shared_timed_mutex; + + /// @cond undocumented + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T +#ifdef __gthrw +#define _GLIBCXX_GTHRW(name) \ + __gthrw(pthread_ ## name); \ + static inline int \ + __glibcxx_ ## name (pthread_rwlock_t *__rwlock) \ + { \ + if (__gthread_active_p ()) \ + return __gthrw_(pthread_ ## name) (__rwlock); \ + else \ + return 0; \ + } + _GLIBCXX_GTHRW(rwlock_rdlock) + _GLIBCXX_GTHRW(rwlock_tryrdlock) + _GLIBCXX_GTHRW(rwlock_wrlock) + _GLIBCXX_GTHRW(rwlock_trywrlock) + _GLIBCXX_GTHRW(rwlock_unlock) +# ifndef PTHREAD_RWLOCK_INITIALIZER + _GLIBCXX_GTHRW(rwlock_destroy) + __gthrw(pthread_rwlock_init); + static inline int + __glibcxx_rwlock_init (pthread_rwlock_t *__rwlock) + { + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_init) (__rwlock, NULL); + else + return 0; + } +# endif +# if _GTHREAD_USE_MUTEX_TIMEDLOCK + __gthrw(pthread_rwlock_timedrdlock); + static inline int + __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock, + const timespec *__ts) + { + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_timedrdlock) (__rwlock, __ts); + else + return 0; + } + __gthrw(pthread_rwlock_timedwrlock); + static inline int + __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock, + const timespec *__ts) + { + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_timedwrlock) (__rwlock, __ts); + else + return 0; + } +# endif +#else + static inline int + __glibcxx_rwlock_rdlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_rdlock (__rwlock); } + static inline int + __glibcxx_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_tryrdlock (__rwlock); } + static inline int + __glibcxx_rwlock_wrlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_wrlock (__rwlock); } + static inline int + __glibcxx_rwlock_trywrlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_trywrlock (__rwlock); } + static inline int + __glibcxx_rwlock_unlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_unlock (__rwlock); } + static inline int + __glibcxx_rwlock_destroy(pthread_rwlock_t *__rwlock) + { return pthread_rwlock_destroy (__rwlock); } + static inline int + __glibcxx_rwlock_init(pthread_rwlock_t *__rwlock) + { return pthread_rwlock_init (__rwlock, NULL); } +# if _GTHREAD_USE_MUTEX_TIMEDLOCK + static inline int + __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock, + const timespec *__ts) + { return pthread_rwlock_timedrdlock (__rwlock, __ts); } + static inline int + __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock, + const timespec *__ts) + { return pthread_rwlock_timedwrlock (__rwlock, __ts); } +# endif +#endif + + /// A shared mutex type implemented using pthread_rwlock_t. + class __shared_mutex_pthread + { + friend class shared_timed_mutex; + +#ifdef PTHREAD_RWLOCK_INITIALIZER + pthread_rwlock_t _M_rwlock = PTHREAD_RWLOCK_INITIALIZER; + + public: + __shared_mutex_pthread() = default; + ~__shared_mutex_pthread() = default; +#else + pthread_rwlock_t _M_rwlock; + + public: + __shared_mutex_pthread() + { + int __ret = __glibcxx_rwlock_init(&_M_rwlock); + if (__ret == ENOMEM) + __throw_bad_alloc(); + else if (__ret == EAGAIN) + __throw_system_error(int(errc::resource_unavailable_try_again)); + else if (__ret == EPERM) + __throw_system_error(int(errc::operation_not_permitted)); + // Errors not handled: EBUSY, EINVAL + __glibcxx_assert(__ret == 0); + } + + ~__shared_mutex_pthread() + { + int __ret __attribute((__unused__)) = __glibcxx_rwlock_destroy(&_M_rwlock); + // Errors not handled: EBUSY, EINVAL + __glibcxx_assert(__ret == 0); + } +#endif + + __shared_mutex_pthread(const __shared_mutex_pthread&) = delete; + __shared_mutex_pthread& operator=(const __shared_mutex_pthread&) = delete; + + void + lock() + { + int __ret = __glibcxx_rwlock_wrlock(&_M_rwlock); + if (__ret == EDEADLK) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + } + + bool + try_lock() + { + int __ret = __glibcxx_rwlock_trywrlock(&_M_rwlock); + if (__ret == EBUSY) return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } + + void + unlock() + { + int __ret __attribute((__unused__)) = __glibcxx_rwlock_unlock(&_M_rwlock); + // Errors not handled: EPERM, EBUSY, EINVAL + __glibcxx_assert(__ret == 0); + } + + // Shared ownership + + void + lock_shared() + { + int __ret; + // We retry if we exceeded the maximum number of read locks supported by + // the POSIX implementation; this can result in busy-waiting, but this + // is okay based on the current specification of forward progress + // guarantees by the standard. + do + __ret = __glibcxx_rwlock_rdlock(&_M_rwlock); + while (__ret == EAGAIN); + if (__ret == EDEADLK) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + } + + bool + try_lock_shared() + { + int __ret = __glibcxx_rwlock_tryrdlock(&_M_rwlock); + // If the maximum number of read locks has been exceeded, we just fail + // to acquire the lock. Unlike for lock(), we are not allowed to throw + // an exception. + if (__ret == EBUSY || __ret == EAGAIN) return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } + + void + unlock_shared() + { + unlock(); + } + + void* native_handle() { return &_M_rwlock; } + }; +#endif + +#if ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) + /// A shared mutex type implemented using std::condition_variable. + class __shared_mutex_cv + { + friend class shared_timed_mutex; + + // Based on Howard Hinnant's reference implementation from N2406. + + // The high bit of _M_state is the write-entered flag which is set to + // indicate a writer has taken the lock or is queuing to take the lock. + // The remaining bits are the count of reader locks. + // + // To take a reader lock, block on gate1 while the write-entered flag is + // set or the maximum number of reader locks is held, then increment the + // reader lock count. + // To release, decrement the count, then if the write-entered flag is set + // and the count is zero then signal gate2 to wake a queued writer, + // otherwise if the maximum number of reader locks was held signal gate1 + // to wake a reader. + // + // To take a writer lock, block on gate1 while the write-entered flag is + // set, then set the write-entered flag to start queueing, then block on + // gate2 while the number of reader locks is non-zero. + // To release, unset the write-entered flag and signal gate1 to wake all + // blocked readers and writers. + // + // This means that when no reader locks are held readers and writers get + // equal priority. When one or more reader locks is held a writer gets + // priority and no more reader locks can be taken while the writer is + // queued. + + // Only locked when accessing _M_state or waiting on condition variables. + mutex _M_mut; + // Used to block while write-entered is set or reader count at maximum. + condition_variable _M_gate1; + // Used to block queued writers while reader count is non-zero. + condition_variable _M_gate2; + // The write-entered flag and reader count. + unsigned _M_state; + + static constexpr unsigned _S_write_entered + = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1); + static constexpr unsigned _S_max_readers = ~_S_write_entered; + + // Test whether the write-entered flag is set. _M_mut must be locked. + bool _M_write_entered() const { return _M_state & _S_write_entered; } + + // The number of reader locks currently held. _M_mut must be locked. + unsigned _M_readers() const { return _M_state & _S_max_readers; } + + public: + __shared_mutex_cv() : _M_state(0) {} + + ~__shared_mutex_cv() + { + __glibcxx_assert( _M_state == 0 ); + } + + __shared_mutex_cv(const __shared_mutex_cv&) = delete; + __shared_mutex_cv& operator=(const __shared_mutex_cv&) = delete; + + // Exclusive ownership + + void + lock() + { + unique_lock __lk(_M_mut); + // Wait until we can set the write-entered flag. + _M_gate1.wait(__lk, [=]{ return !_M_write_entered(); }); + _M_state |= _S_write_entered; + // Then wait until there are no more readers. + _M_gate2.wait(__lk, [=]{ return _M_readers() == 0; }); + } + + bool + try_lock() + { + unique_lock __lk(_M_mut, try_to_lock); + if (__lk.owns_lock() && _M_state == 0) + { + _M_state = _S_write_entered; + return true; + } + return false; + } + + void + unlock() + { + lock_guard __lk(_M_mut); + __glibcxx_assert( _M_write_entered() ); + _M_state = 0; + // call notify_all() while mutex is held so that another thread can't + // lock and unlock the mutex then destroy *this before we make the call. + _M_gate1.notify_all(); + } + + // Shared ownership + + void + lock_shared() + { + unique_lock __lk(_M_mut); + _M_gate1.wait(__lk, [=]{ return _M_state < _S_max_readers; }); + ++_M_state; + } + + bool + try_lock_shared() + { + unique_lock __lk(_M_mut, try_to_lock); + if (!__lk.owns_lock()) + return false; + if (_M_state < _S_max_readers) + { + ++_M_state; + return true; + } + return false; + } + + void + unlock_shared() + { + lock_guard __lk(_M_mut); + __glibcxx_assert( _M_readers() > 0 ); + auto __prev = _M_state--; + if (_M_write_entered()) + { + // Wake the queued writer if there are no more readers. + if (_M_readers() == 0) + _M_gate2.notify_one(); + // No need to notify gate1 because we give priority to the queued + // writer, and that writer will eventually notify gate1 after it + // clears the write-entered flag. + } + else + { + // Wake any thread that was blocked on reader overflow. + if (__prev == _S_max_readers) + _M_gate1.notify_one(); + } + } + }; +#endif + /// @endcond + +#if __cplusplus > 201402L + /// The standard shared mutex type. + class shared_mutex + { + public: + shared_mutex() = default; + ~shared_mutex() = default; + + shared_mutex(const shared_mutex&) = delete; + shared_mutex& operator=(const shared_mutex&) = delete; + + // Exclusive ownership + + void lock() { _M_impl.lock(); } + bool try_lock() { return _M_impl.try_lock(); } + void unlock() { _M_impl.unlock(); } + + // Shared ownership + + void lock_shared() { _M_impl.lock_shared(); } + bool try_lock_shared() { return _M_impl.try_lock_shared(); } + void unlock_shared() { _M_impl.unlock_shared(); } + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T + typedef void* native_handle_type; + native_handle_type native_handle() { return _M_impl.native_handle(); } + + private: + __shared_mutex_pthread _M_impl; +#else + private: + __shared_mutex_cv _M_impl; +#endif + }; +#endif // C++17 + + /// @cond undocumented +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK + using __shared_timed_mutex_base = __shared_mutex_pthread; +#else + using __shared_timed_mutex_base = __shared_mutex_cv; +#endif + /// @endcond + + /// The standard shared timed mutex type. + class shared_timed_mutex + : private __shared_timed_mutex_base + { + using _Base = __shared_timed_mutex_base; + + // Must use the same clock as condition_variable for __shared_mutex_cv. +#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK + using __clock_t = chrono::steady_clock; +#else + using __clock_t = chrono::system_clock; +#endif + + public: + shared_timed_mutex() = default; + ~shared_timed_mutex() = default; + + shared_timed_mutex(const shared_timed_mutex&) = delete; + shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; + + // Exclusive ownership + + void lock() { _Base::lock(); } + bool try_lock() { return _Base::try_lock(); } + void unlock() { _Base::unlock(); } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime); + if (ratio_greater<__clock_t::period, _Period>()) + ++__rt; + return try_lock_until(__clock_t::now() + __rt); + } + + // Shared ownership + + void lock_shared() { _Base::lock_shared(); } + bool try_lock_shared() { return _Base::try_lock_shared(); } + void unlock_shared() { _Base::unlock_shared(); } + + template + bool + try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rtime) + { + auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime); + if (ratio_greater<__clock_t::period, _Period>()) + ++__rt; + return try_lock_shared_until(__clock_t::now() + __rt); + } + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK + + // Exclusive ownership + + template + bool + try_lock_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret = __glibcxx_rwlock_timedwrlock(&_M_rwlock, &__ts); + // On self-deadlock, we just fail to acquire the lock. Technically, + // the program violated the precondition. + if (__ret == ETIMEDOUT || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } + +#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK + template + bool + try_lock_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret = pthread_rwlock_clockwrlock(&_M_rwlock, CLOCK_MONOTONIC, + &__ts); + // On self-deadlock, we just fail to acquire the lock. Technically, + // the program violated the precondition. + if (__ret == ETIMEDOUT || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } +#endif + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { +#if __cplusplus > 201703L + static_assert(chrono::is_clock_v<_Clock>); +#endif + // The user-supplied clock may not tick at the same rate as + // steady_clock, so we must loop in order to guarantee that + // the timeout has expired before returning false. + typename _Clock::time_point __now = _Clock::now(); + do { + auto __rtime = __atime - __now; + if (try_lock_for(__rtime)) + return true; + __now = _Clock::now(); + } while (__atime > __now); + return false; + } + + // Shared ownership + + template + bool + try_lock_shared_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret; + // Unlike for lock(), we are not allowed to throw an exception so if + // the maximum number of read locks has been exceeded, or we would + // deadlock, we just try to acquire the lock again (and will time out + // eventually). + // In cases where we would exceed the maximum number of read locks + // throughout the whole time until the timeout, we will fail to + // acquire the lock even if it would be logically free; however, this + // is allowed by the standard, and we made a "strong effort" + // (see C++14 30.4.1.4p26). + // For cases where the implementation detects a deadlock we + // intentionally block and timeout so that an early return isn't + // mistaken for a spurious failure, which might help users realise + // there is a deadlock. + do + __ret = __glibcxx_rwlock_timedrdlock(&_M_rwlock, &__ts); + while (__ret == EAGAIN || __ret == EDEADLK); + if (__ret == ETIMEDOUT) + return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } + +#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK + template + bool + try_lock_shared_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret = pthread_rwlock_clockrdlock(&_M_rwlock, CLOCK_MONOTONIC, + &__ts); + // On self-deadlock, we just fail to acquire the lock. Technically, + // the program violated the precondition. + if (__ret == ETIMEDOUT || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } +#endif + + template + bool + try_lock_shared_until(const chrono::time_point<_Clock, + _Duration>& __atime) + { +#if __cplusplus > 201703L + static_assert(chrono::is_clock_v<_Clock>); +#endif + // The user-supplied clock may not tick at the same rate as + // steady_clock, so we must loop in order to guarantee that + // the timeout has expired before returning false. + typename _Clock::time_point __now = _Clock::now(); + do { + auto __rtime = __atime - __now; + if (try_lock_shared_for(__rtime)) + return true; + __now = _Clock::now(); + } while (__atime > __now); + return false; + } + +#else // ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) + + // Exclusive ownership + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + { + unique_lock __lk(_M_mut); + if (!_M_gate1.wait_until(__lk, __abs_time, + [=]{ return !_M_write_entered(); })) + { + return false; + } + _M_state |= _S_write_entered; + if (!_M_gate2.wait_until(__lk, __abs_time, + [=]{ return _M_readers() == 0; })) + { + _M_state ^= _S_write_entered; + // Wake all threads blocked while the write-entered flag was set. + _M_gate1.notify_all(); + return false; + } + return true; + } + + // Shared ownership + + template + bool + try_lock_shared_until(const chrono::time_point<_Clock, + _Duration>& __abs_time) + { + unique_lock __lk(_M_mut); + if (!_M_gate1.wait_until(__lk, __abs_time, + [=]{ return _M_state < _S_max_readers; })) + { + return false; + } + ++_M_state; + return true; + } + +#endif // _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK + }; +#endif // _GLIBCXX_HAS_GTHREADS + + /// shared_lock + template + class shared_lock + { + public: + typedef _Mutex mutex_type; + + // Shared locking + + shared_lock() noexcept : _M_pm(nullptr), _M_owns(false) { } + + explicit + shared_lock(mutex_type& __m) + : _M_pm(std::__addressof(__m)), _M_owns(true) + { __m.lock_shared(); } + + shared_lock(mutex_type& __m, defer_lock_t) noexcept + : _M_pm(std::__addressof(__m)), _M_owns(false) { } + + shared_lock(mutex_type& __m, try_to_lock_t) + : _M_pm(std::__addressof(__m)), _M_owns(__m.try_lock_shared()) { } + + shared_lock(mutex_type& __m, adopt_lock_t) + : _M_pm(std::__addressof(__m)), _M_owns(true) { } + + template + shared_lock(mutex_type& __m, + const chrono::time_point<_Clock, _Duration>& __abs_time) + : _M_pm(std::__addressof(__m)), + _M_owns(__m.try_lock_shared_until(__abs_time)) { } + + template + shared_lock(mutex_type& __m, + const chrono::duration<_Rep, _Period>& __rel_time) + : _M_pm(std::__addressof(__m)), + _M_owns(__m.try_lock_shared_for(__rel_time)) { } + + ~shared_lock() + { + if (_M_owns) + _M_pm->unlock_shared(); + } + + shared_lock(shared_lock const&) = delete; + shared_lock& operator=(shared_lock const&) = delete; + + shared_lock(shared_lock&& __sl) noexcept : shared_lock() + { swap(__sl); } + + shared_lock& + operator=(shared_lock&& __sl) noexcept + { + shared_lock(std::move(__sl)).swap(*this); + return *this; + } + + void + lock() + { + _M_lockable(); + _M_pm->lock_shared(); + _M_owns = true; + } + + bool + try_lock() + { + _M_lockable(); + return _M_owns = _M_pm->try_lock_shared(); + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) + { + _M_lockable(); + return _M_owns = _M_pm->try_lock_shared_for(__rel_time); + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + { + _M_lockable(); + return _M_owns = _M_pm->try_lock_shared_until(__abs_time); + } + + void + unlock() + { + if (!_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + _M_pm->unlock_shared(); + _M_owns = false; + } + + // Setters + + void + swap(shared_lock& __u) noexcept + { + std::swap(_M_pm, __u._M_pm); + std::swap(_M_owns, __u._M_owns); + } + + mutex_type* + release() noexcept + { + _M_owns = false; + return std::exchange(_M_pm, nullptr); + } + + // Getters + + bool owns_lock() const noexcept { return _M_owns; } + + explicit operator bool() const noexcept { return _M_owns; } + + mutex_type* mutex() const noexcept { return _M_pm; } + + private: + void + _M_lockable() const + { + if (_M_pm == nullptr) + __throw_system_error(int(errc::operation_not_permitted)); + if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + + } + + mutex_type* _M_pm; + bool _M_owns; + }; + + /// Swap specialization for shared_lock + /// @relates shared_mutex + template + void + swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) noexcept + { __x.swap(__y); } + + // @} group mutexes +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++14 + +#endif // _GLIBCXX_SHARED_MUTEX diff --git a/resources/sources/avr-libstdcpp/include/span b/resources/sources/avr-libstdcpp/include/span new file mode 100644 index 000000000..1cdc0589d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/span @@ -0,0 +1,462 @@ +// Components for manipulating non-owning sequences of objects -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file span + * This is a Standard C++ Library header. + */ + +// +// P0122 span library +// Contributed by ThePhD +// + +#ifndef _GLIBCXX_SPAN +#define _GLIBCXX_SPAN 1 + +#pragma GCC system_header + +#if __cplusplus > 201703L + +#include +#include +#include +#include + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_span 202002L + + inline constexpr size_t dynamic_extent = static_cast(-1); + + template + class span; + + namespace __detail + { + template + struct __is_std_span : false_type { }; + + template + struct __is_std_span> : true_type { }; + + template + struct __is_std_array : false_type { }; + + template + struct __is_std_array<_GLIBCXX_STD_C::array<_Tp, _Num>> : true_type { }; + +#ifdef _GLIBCXX_DEBUG + template + struct __is_std_array<__debug::array<_Tp, _Num>> : true_type { }; +#endif + + template + class __extent_storage + { + public: + constexpr + __extent_storage(size_t) noexcept + { } + + static constexpr size_t + _M_extent() noexcept + { return _Extent; } + }; + + template<> + class __extent_storage + { + public: + constexpr + __extent_storage(size_t __extent) noexcept + : _M_extent_value(__extent) + { } + + constexpr size_t + _M_extent() const noexcept + { return this->_M_extent_value; } + + private: + size_t _M_extent_value; + }; + } // namespace __detail + + template + class span + { + template + static constexpr size_t + _S_subspan_extent() + { + if constexpr (_Count != dynamic_extent) + return _Count; + else if constexpr (extent != dynamic_extent) + return _Extent - _Offset; + else + return dynamic_extent; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3255. span's array constructor is too strict + template + requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) + using __is_compatible_array = __is_array_convertible<_Type, _Tp>; + + template + using __is_compatible_ref + = __is_array_convertible<_Type, remove_reference_t<_Ref>>; + + public: + // member types + using element_type = _Type; + using value_type = remove_cv_t<_Type>; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = _Type*; + using const_pointer = const _Type*; + using reference = element_type&; + using const_reference = const element_type&; + using iterator = __gnu_cxx::__normal_iterator; + using reverse_iterator = std::reverse_iterator; + + // member constants + static constexpr size_t extent = _Extent; + + // constructors, copy and assignment + + constexpr + span() noexcept + requires ((_Extent + 1u) <= 1u) + : _M_extent(0), _M_ptr(nullptr) + { } + + template + requires __is_compatible_ref>::value + constexpr explicit(extent != dynamic_extent) + span(_It __first, size_type __count) + noexcept + : _M_extent(__count), _M_ptr(std::to_address(__first)) + { + if constexpr (_Extent != dynamic_extent) + { + __glibcxx_assert(__count == _Extent); + } + } + + template _End> + requires __is_compatible_ref>::value + && (!is_convertible_v<_End, size_type>) + constexpr explicit(extent != dynamic_extent) + span(_It __first, _End __last) + noexcept(noexcept(__last - __first)) + : _M_extent(static_cast(__last - __first)), + _M_ptr(std::to_address(__first)) + { + if constexpr (_Extent != dynamic_extent) + { + __glibcxx_assert((__last - __first) == _Extent); + } + } + + template + requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) + constexpr + span(type_identity_t (&__arr)[_ArrayExtent]) noexcept + : span(static_cast(__arr), _ArrayExtent) + { } + + template + requires __is_compatible_array<_Tp, _ArrayExtent>::value + constexpr + span(array<_Tp, _ArrayExtent>& __arr) noexcept + : span(static_cast(__arr.data()), _ArrayExtent) + { } + + template + requires __is_compatible_array::value + constexpr + span(const array<_Tp, _ArrayExtent>& __arr) noexcept + : span(static_cast(__arr.data()), _ArrayExtent) + { } + + template + requires ranges::contiguous_range<_Range> && ranges::sized_range<_Range> + && (ranges::borrowed_range<_Range> || is_const_v) + && (!__detail::__is_std_span>::value) + && (!__detail::__is_std_array>::value) + && (!is_array_v>) + && __is_compatible_ref>::value + constexpr explicit(extent != dynamic_extent) + span(_Range&& __range) + noexcept(noexcept(ranges::data(__range)) + && noexcept(ranges::size(__range))) + : span(ranges::data(__range), ranges::size(__range)) + { + if constexpr (extent != dynamic_extent) + { + __glibcxx_assert(ranges::size(__range) == extent); + } + } + + constexpr + span(const span&) noexcept = default; + + template + requires (_Extent == dynamic_extent || _OExtent == dynamic_extent + || _Extent == _OExtent) + && (__is_array_convertible<_Type, _OType>::value) + constexpr + explicit(extent != dynamic_extent && _OExtent == dynamic_extent) + span(const span<_OType, _OExtent>& __s) noexcept + : _M_extent(__s.size()), _M_ptr(__s.data()) + { + if constexpr (extent != dynamic_extent) + { + __glibcxx_assert(__s.size() == extent); + } + } + + ~span() noexcept = default; + + constexpr span& + operator=(const span&) noexcept = default; + + // observers + + constexpr size_type + size() const noexcept + { return this->_M_extent._M_extent(); } + + constexpr size_type + size_bytes() const noexcept + { return this->_M_extent._M_extent() * sizeof(element_type); } + + [[nodiscard]] constexpr bool + empty() const noexcept + { return size() == 0; } + + // element access + + constexpr reference + front() const noexcept + { + __glibcxx_assert(!empty()); + return *this->_M_ptr; + } + + constexpr reference + back() const noexcept + { + __glibcxx_assert(!empty()); + return *(this->_M_ptr + (size() - 1)); + } + + constexpr reference + operator[](size_type __idx) const noexcept + { + __glibcxx_assert(__idx < size()); + return *(this->_M_ptr + __idx); + } + + constexpr pointer + data() const noexcept + { return this->_M_ptr; } + + // iterator support + + constexpr iterator + begin() const noexcept + { return iterator(this->_M_ptr); } + + constexpr iterator + end() const noexcept + { return iterator(this->_M_ptr + this->size()); } + + constexpr reverse_iterator + rbegin() const noexcept + { return reverse_iterator(this->end()); } + + constexpr reverse_iterator + rend() const noexcept + { return reverse_iterator(this->begin()); } + + // subviews + + template + constexpr span + first() const noexcept + { + if constexpr (_Extent == dynamic_extent) + __glibcxx_assert(_Count <= size()); + else + static_assert(_Count <= extent); + using _Sp = span; + return _Sp{ this->data(), _Count }; + } + + constexpr span + first(size_type __count) const noexcept + { + __glibcxx_assert(__count <= size()); + return { this->data(), __count }; + } + + template + constexpr span + last() const noexcept + { + if constexpr (_Extent == dynamic_extent) + __glibcxx_assert(_Count <= size()); + else + static_assert(_Count <= extent); + using _Sp = span; + return _Sp{ this->data() + (this->size() - _Count), _Count }; + } + + constexpr span + last(size_type __count) const noexcept + { + __glibcxx_assert(__count <= size()); + return { this->data() + (this->size() - __count), __count }; + } + + template + constexpr auto + subspan() const noexcept + -> span()> + { + if constexpr (_Extent == dynamic_extent) + { + __glibcxx_assert(_Offset <= size()); + } + else + static_assert(_Offset <= extent); + + using _Sp = span()>; + + if constexpr (_Count == dynamic_extent) + return _Sp{ this->data() + _Offset, this->size() - _Offset }; + else + { + if constexpr (_Extent == dynamic_extent) + { + __glibcxx_assert(_Count <= size()); + __glibcxx_assert(_Count <= (size() - _Offset)); + } + else + { + static_assert(_Count <= extent); + static_assert(_Count <= (extent - _Offset)); + } + return _Sp{ this->data() + _Offset, _Count }; + } + } + + constexpr span + subspan(size_type __offset, size_type __count = dynamic_extent) const + noexcept + { + __glibcxx_assert(__offset <= size()); + if (__count == dynamic_extent) + __count = this->size() - __offset; + else + { + __glibcxx_assert(__count <= size()); + __glibcxx_assert(__offset + __count <= size()); + } + return {this->data() + __offset, __count}; + } + + private: + [[no_unique_address]] __detail::__extent_storage _M_extent; + pointer _M_ptr; + }; + + // deduction guides + + template + span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; + + template + span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>; + + template + span(const array<_Type, _ArrayExtent>&) + -> span; + + template + span(_Iter, _End) + -> span>>; + + template + span(_Range &&) + -> span>>; + + template + inline + span + as_bytes(span<_Type, _Extent> __sp) noexcept + { + auto data = reinterpret_cast(__sp.data()); + auto size = __sp.size_bytes(); + constexpr auto extent = _Extent == dynamic_extent + ? dynamic_extent : _Extent * sizeof(_Type); + return span{data, size}; + } + + template + inline + span + as_writable_bytes(span<_Type, _Extent> __sp) noexcept + { + auto data = reinterpret_cast(__sp.data()); + auto size = __sp.size_bytes(); + constexpr auto extent = _Extent == dynamic_extent + ? dynamic_extent : _Extent * sizeof(_Type); + return span{data, size}; + } + + namespace ranges + { + // Opt-in to borrowed_range concept + template + inline constexpr bool + enable_borrowed_range> = true; + + // Opt-in to view concept + template + inline constexpr bool + enable_view> + = _Extent == 0 || _Extent == dynamic_extent; + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _GLIBCXX_SPAN diff --git a/resources/sources/avr-libstdcpp/include/stack b/resources/sources/avr-libstdcpp/include/stack new file mode 100644 index 000000000..064b3583a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/stack @@ -0,0 +1,63 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/stack + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_STACK +#define _GLIBCXX_STACK 1 + +#pragma GCC system_header + +#include +#include + +#endif /* _GLIBCXX_STACK */ diff --git a/resources/sources/avr-libstdcpp/include/string_view b/resources/sources/avr-libstdcpp/include/string_view new file mode 100644 index 000000000..487088c7e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/string_view @@ -0,0 +1,758 @@ +// Components for manipulating non-owning sequences of characters -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file string_view + * This is a Standard C++ Library header. + */ + +// +// N3762 basic_string_view library +// + +#ifndef _GLIBCXX_STRING_VIEW +#define _GLIBCXX_STRING_VIEW 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +# define __cpp_lib_string_view 201803L +#if __cplusplus > 201703L +# define __cpp_lib_constexpr_string_view 201811L +#endif + + // Helper for basic_string and basic_string_view members. + constexpr size_t + __sv_check(size_t __size, size_t __pos, const char* __s) + { + if (__pos > __size) + __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size " + "(which is %zu)"), __s, __pos, __size); + return __pos; + } + + // Helper for basic_string members. + // NB: __sv_limit doesn't check for a bad __pos value. + constexpr size_t + __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept + { + const bool __testoff = __off < __size - __pos; + return __testoff ? __off : __size - __pos; + } + + /** + * @class basic_string_view + * @brief A non-owning reference to a string. + * + * @ingroup strings + * @ingroup sequences + * + * @tparam _CharT Type of character + * @tparam _Traits Traits for character type, defaults to + * char_traits<_CharT>. + * + * A basic_string_view looks like this: + * + * @code + * _CharT* _M_str + * size_t _M_len + * @endcode + */ + template> + class basic_string_view + { + static_assert(!is_array_v<_CharT>); + static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>); + static_assert(is_same_v<_CharT, typename _Traits::char_type>); + + public: + + // types + using traits_type = _Traits; + using value_type = _CharT; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using const_iterator = const value_type*; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = const_reverse_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + static constexpr size_type npos = size_type(-1); + + // [string.view.cons], construction and assignment + + constexpr + basic_string_view() noexcept + : _M_len{0}, _M_str{nullptr} + { } + + constexpr basic_string_view(const basic_string_view&) noexcept = default; + + __attribute__((__nonnull__)) constexpr + basic_string_view(const _CharT* __str) noexcept + : _M_len{traits_type::length(__str)}, + _M_str{__str} + { } + + constexpr + basic_string_view(const _CharT* __str, size_type __len) noexcept + : _M_len{__len}, _M_str{__str} + { } + +#if __cplusplus > 201703L && __cpp_lib_concepts + template _End> + requires same_as, _CharT> + && (!convertible_to<_End, size_type>) + constexpr + basic_string_view(_It __first, _End __last) + : _M_len(__last - __first), _M_str(std::to_address(__first)) + { } +#endif + + constexpr basic_string_view& + operator=(const basic_string_view&) noexcept = default; + + // [string.view.iterators], iterator support + + constexpr const_iterator + begin() const noexcept + { return this->_M_str; } + + constexpr const_iterator + end() const noexcept + { return this->_M_str + this->_M_len; } + + constexpr const_iterator + cbegin() const noexcept + { return this->_M_str; } + + constexpr const_iterator + cend() const noexcept + { return this->_M_str + this->_M_len; } + + constexpr const_reverse_iterator + rbegin() const noexcept + { return const_reverse_iterator(this->end()); } + + constexpr const_reverse_iterator + rend() const noexcept + { return const_reverse_iterator(this->begin()); } + + constexpr const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(this->end()); } + + constexpr const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(this->begin()); } + + // [string.view.capacity], capacity + + constexpr size_type + size() const noexcept + { return this->_M_len; } + + constexpr size_type + length() const noexcept + { return _M_len; } + + constexpr size_type + max_size() const noexcept + { + return (npos - sizeof(size_type) - sizeof(void*)) + / sizeof(value_type) / 4; + } + + [[nodiscard]] constexpr bool + empty() const noexcept + { return this->_M_len == 0; } + + // [string.view.access], element access + + constexpr const_reference + operator[](size_type __pos) const noexcept + { + __glibcxx_assert(__pos < this->_M_len); + return *(this->_M_str + __pos); + } + + constexpr const_reference + at(size_type __pos) const + { + if (__pos >= _M_len) + __throw_out_of_range_fmt(__N("basic_string_view::at: __pos " + "(which is %zu) >= this->size() " + "(which is %zu)"), __pos, this->size()); + return *(this->_M_str + __pos); + } + + constexpr const_reference + front() const noexcept + { + __glibcxx_assert(this->_M_len > 0); + return *this->_M_str; + } + + constexpr const_reference + back() const noexcept + { + __glibcxx_assert(this->_M_len > 0); + return *(this->_M_str + this->_M_len - 1); + } + + constexpr const_pointer + data() const noexcept + { return this->_M_str; } + + // [string.view.modifiers], modifiers: + + constexpr void + remove_prefix(size_type __n) noexcept + { + __glibcxx_assert(this->_M_len >= __n); + this->_M_str += __n; + this->_M_len -= __n; + } + + constexpr void + remove_suffix(size_type __n) noexcept + { this->_M_len -= __n; } + + constexpr void + swap(basic_string_view& __sv) noexcept + { + auto __tmp = *this; + *this = __sv; + __sv = __tmp; + } + + // [string.view.ops], string operations: + + _GLIBCXX20_CONSTEXPR + size_type + copy(_CharT* __str, size_type __n, size_type __pos = 0) const + { + __glibcxx_requires_string_len(__str, __n); + __pos = std::__sv_check(size(), __pos, "basic_string_view::copy"); + const size_type __rlen = std::min(__n, _M_len - __pos); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2777. basic_string_view::copy should use char_traits::copy + traits_type::copy(__str, data() + __pos, __rlen); + return __rlen; + } + + constexpr basic_string_view + substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) + { + __pos = std::__sv_check(size(), __pos, "basic_string_view::substr"); + const size_type __rlen = std::min(__n, _M_len - __pos); + return basic_string_view{_M_str + __pos, __rlen}; + } + + constexpr int + compare(basic_string_view __str) const noexcept + { + const size_type __rlen = std::min(this->_M_len, __str._M_len); + int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen); + if (__ret == 0) + __ret = _S_compare(this->_M_len, __str._M_len); + return __ret; + } + + constexpr int + compare(size_type __pos1, size_type __n1, basic_string_view __str) const + { return this->substr(__pos1, __n1).compare(__str); } + + constexpr int + compare(size_type __pos1, size_type __n1, + basic_string_view __str, size_type __pos2, size_type __n2) const + { + return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); + } + + __attribute__((__nonnull__)) constexpr int + compare(const _CharT* __str) const noexcept + { return this->compare(basic_string_view{__str}); } + + __attribute__((__nonnull__)) constexpr int + compare(size_type __pos1, size_type __n1, const _CharT* __str) const + { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } + + constexpr int + compare(size_type __pos1, size_type __n1, + const _CharT* __str, size_type __n2) const noexcept(false) + { + return this->substr(__pos1, __n1) + .compare(basic_string_view(__str, __n2)); + } + +#if __cplusplus > 201703L +#define __cpp_lib_starts_ends_with 201711L + constexpr bool + starts_with(basic_string_view __x) const noexcept + { return this->substr(0, __x.size()) == __x; } + + constexpr bool + starts_with(_CharT __x) const noexcept + { return !this->empty() && traits_type::eq(this->front(), __x); } + + constexpr bool + starts_with(const _CharT* __x) const noexcept + { return this->starts_with(basic_string_view(__x)); } + + constexpr bool + ends_with(basic_string_view __x) const noexcept + { + return this->size() >= __x.size() + && this->compare(this->size() - __x.size(), npos, __x) == 0; + } + + constexpr bool + ends_with(_CharT __x) const noexcept + { return !this->empty() && traits_type::eq(this->back(), __x); } + + constexpr bool + ends_with(const _CharT* __x) const noexcept + { return this->ends_with(basic_string_view(__x)); } +#endif // C++20 + + // [string.view.find], searching + + constexpr size_type + find(basic_string_view __str, size_type __pos = 0) const noexcept + { return this->find(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find(_CharT __c, size_type __pos = 0) const noexcept; + + constexpr size_type + find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find(const _CharT* __str, size_type __pos = 0) const noexcept + { return this->find(__str, __pos, traits_type::length(__str)); } + + constexpr size_type + rfind(basic_string_view __str, size_type __pos = npos) const noexcept + { return this->rfind(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + rfind(_CharT __c, size_type __pos = npos) const noexcept; + + constexpr size_type + rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + rfind(const _CharT* __str, size_type __pos = npos) const noexcept + { return this->rfind(__str, __pos, traits_type::length(__str)); } + + constexpr size_type + find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept + { return this->find_first_of(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find_first_of(_CharT __c, size_type __pos = 0) const noexcept + { return this->find(__c, __pos); } + + constexpr size_type + find_first_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept + { return this->find_first_of(__str, __pos, traits_type::length(__str)); } + + constexpr size_type + find_last_of(basic_string_view __str, + size_type __pos = npos) const noexcept + { return this->find_last_of(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find_last_of(_CharT __c, size_type __pos=npos) const noexcept + { return this->rfind(__c, __pos); } + + constexpr size_type + find_last_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept + { return this->find_last_of(__str, __pos, traits_type::length(__str)); } + + constexpr size_type + find_first_not_of(basic_string_view __str, + size_type __pos = 0) const noexcept + { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; + + constexpr size_type + find_first_not_of(const _CharT* __str, + size_type __pos, size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept + { + return this->find_first_not_of(__str, __pos, + traits_type::length(__str)); + } + + constexpr size_type + find_last_not_of(basic_string_view __str, + size_type __pos = npos) const noexcept + { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; + + constexpr size_type + find_last_not_of(const _CharT* __str, + size_type __pos, size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find_last_not_of(const _CharT* __str, + size_type __pos = npos) const noexcept + { + return this->find_last_not_of(__str, __pos, + traits_type::length(__str)); + } + + private: + + static constexpr int + _S_compare(size_type __n1, size_type __n2) noexcept + { + const difference_type __diff = __n1 - __n2; + if (__diff > __gnu_cxx::__int_traits::__max) + return __gnu_cxx::__int_traits::__max; + if (__diff < __gnu_cxx::__int_traits::__min) + return __gnu_cxx::__int_traits::__min; + return static_cast(__diff); + } + + size_t _M_len; + const _CharT* _M_str; + }; + +#if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides + template _End> + basic_string_view(_It, _End) -> basic_string_view>; +#endif + + // [string.view.comparison], non-member basic_string_view comparison function + + // Several of these functions use type_identity_t to create a non-deduced + // context, so that only one argument participates in template argument + // deduction and the other argument gets implicitly converted to the deduced + // type (see N3766). + + template + constexpr bool + operator==(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + + template + constexpr bool + operator==(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + +#if __cpp_lib_three_way_comparison + template + constexpr auto + operator<=>(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) + { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } + + template + constexpr auto + operator<=>(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) + { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } +#else + template + constexpr bool + operator==(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + + template + constexpr bool + operator!=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return !(__x == __y); } + + template + constexpr bool + operator!=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return !(__x == __y); } + + template + constexpr bool + operator!=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return !(__x == __y); } + + template + constexpr bool + operator< (basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) < 0; } + + template + constexpr bool + operator< (basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) < 0; } + + template + constexpr bool + operator< (__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) < 0; } + + template + constexpr bool + operator> (basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) > 0; } + + template + constexpr bool + operator> (basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) > 0; } + + template + constexpr bool + operator> (__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) > 0; } + + template + constexpr bool + operator<=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) <= 0; } + + template + constexpr bool + operator<=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) <= 0; } + + template + constexpr bool + operator<=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) <= 0; } + + template + constexpr bool + operator>=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) >= 0; } + + template + constexpr bool + operator>=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) >= 0; } + + template + constexpr bool + operator>=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) >= 0; } +#endif // three-way comparison + + // basic_string_view typedef names + + using string_view = basic_string_view; +#ifdef _GLIBCXX_USE_WCHAR_T + using wstring_view = basic_string_view; +#endif +#ifdef _GLIBCXX_USE_CHAR8_T + using u8string_view = basic_string_view; +#endif + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + + // [string.view.hash], hash support: + + template + struct hash; + + template<> + struct hash + : public __hash_base + { + size_t + operator()(const string_view& __str) const noexcept + { return std::_Hash_impl::hash(__str.data(), __str.length()); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct hash + : public __hash_base + { + size_t + operator()(const wstring_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(wchar_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; +#endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct hash + : public __hash_base + { + size_t + operator()(const u8string_view& __str) const noexcept + { return std::_Hash_impl::hash(__str.data(), __str.length()); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; +#endif + + template<> + struct hash + : public __hash_base + { + size_t + operator()(const u16string_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(char16_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + + template<> + struct hash + : public __hash_base + { + size_t + operator()(const u32string_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(char32_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + + inline namespace literals + { + inline namespace string_view_literals + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" + inline constexpr basic_string_view + operator""sv(const char* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + +#ifdef _GLIBCXX_USE_WCHAR_T + inline constexpr basic_string_view + operator""sv(const wchar_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } +#endif + +#ifdef _GLIBCXX_USE_CHAR8_T + inline constexpr basic_string_view + operator""sv(const char8_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } +#endif + + inline constexpr basic_string_view + operator""sv(const char16_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + + inline constexpr basic_string_view + operator""sv(const char32_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + +#pragma GCC diagnostic pop + } // namespace string_literals + } // namespace literals + +#if __cpp_lib_concepts + namespace ranges + { + // Opt-in to borrowed_range concept + template + inline constexpr bool + enable_borrowed_range> = true; + + // Opt-in to view concept + template + inline constexpr bool + enable_view> = true; + } +#endif +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#include + +#endif // __cplusplus <= 201402L + +#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW diff --git a/resources/sources/avr-libstdcpp/include/tuple b/resources/sources/avr-libstdcpp/include/tuple new file mode 100644 index 000000000..94b9e0335 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/tuple @@ -0,0 +1,1764 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/tuple + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TUPLE +#define _GLIBCXX_TUPLE 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +# define __cpp_lib_constexpr_tuple 201811L +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + template + class tuple; + + template + struct __is_empty_non_tuple : is_empty<_Tp> { }; + + // Using EBO for elements that are tuples causes ambiguous base errors. + template + struct __is_empty_non_tuple> : false_type { }; + + // Use the Empty Base-class Optimization for empty, non-final types. + template + using __empty_not_final + = typename conditional<__is_final(_Tp), false_type, + __is_empty_non_tuple<_Tp>>::type; + + template::value> + struct _Head_base; + + template + struct _Head_base<_Idx, _Head, true> + : public _Head + { + constexpr _Head_base() + : _Head() { } + + constexpr _Head_base(const _Head& __h) + : _Head(__h) { } + + constexpr _Head_base(const _Head_base&) = default; + constexpr _Head_base(_Head_base&&) = default; + + template + constexpr _Head_base(_UHead&& __h) + : _Head(std::forward<_UHead>(__h)) { } + + _Head_base(allocator_arg_t, __uses_alloc0) + : _Head() { } + + template + _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) + : _Head(allocator_arg, *__a._M_a) { } + + template + _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) + : _Head(*__a._M_a) { } + + template + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _Head(std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } + + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b; } + }; + + template + struct _Head_base<_Idx, _Head, false> + { + constexpr _Head_base() + : _M_head_impl() { } + + constexpr _Head_base(const _Head& __h) + : _M_head_impl(__h) { } + + constexpr _Head_base(const _Head_base&) = default; + constexpr _Head_base(_Head_base&&) = default; + + template + constexpr _Head_base(_UHead&& __h) + : _M_head_impl(std::forward<_UHead>(__h)) { } + + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc0) + : _M_head_impl() { } + + template + _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) + : _M_head_impl(allocator_arg, *__a._M_a) { } + + template + _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) + : _M_head_impl(*__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) + { } + + template + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } + + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } + + _Head _M_head_impl; + }; + + /** + * Contains the actual implementation of the @c tuple template, stored + * as a recursive inheritance hierarchy from the first element (most + * derived class) to the last (least derived class). The @c Idx + * parameter gives the 0-based index of the element stored at this + * point in the hierarchy; we use it to implement a constant-time + * get() operation. + */ + template + struct _Tuple_impl; + + /** + * Recursive tuple implementation. Here we store the @c Head element + * and derive from a @c Tuple_impl containing the remaining elements + * (which contains the @c Tail). + */ + template + struct _Tuple_impl<_Idx, _Head, _Tail...> + : public _Tuple_impl<_Idx + 1, _Tail...>, + private _Head_base<_Idx, _Head> + { + template friend class _Tuple_impl; + + typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; + typedef _Head_base<_Idx, _Head> _Base; + + static constexpr _Head& + _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr const _Head& + _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr _Inherited& + _M_tail(_Tuple_impl& __t) noexcept { return __t; } + + static constexpr const _Inherited& + _M_tail(const _Tuple_impl& __t) noexcept { return __t; } + + constexpr _Tuple_impl() + : _Inherited(), _Base() { } + + explicit + constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) + : _Inherited(__tail...), _Base(__head) { } + + template::type> + explicit + constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail) + : _Inherited(std::forward<_UTail>(__tail)...), + _Base(std::forward<_UHead>(__head)) { } + + constexpr _Tuple_impl(const _Tuple_impl&) = default; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2729. Missing SFINAE on std::pair::operator= + _Tuple_impl& operator=(const _Tuple_impl&) = delete; + + constexpr + _Tuple_impl(_Tuple_impl&& __in) + noexcept(__and_, + is_nothrow_move_constructible<_Inherited>>::value) + : _Inherited(std::move(_M_tail(__in))), + _Base(std::forward<_Head>(_M_head(__in))) { } + + template + constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } + + template + constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a), + _Base(__tag, __use_alloc<_Head>(__a)) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Head& __head, const _Tail&... __tail) + : _Inherited(__tag, __a, __tail...), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } + + template::type> + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _UHead&& __head, _UTail&&... __tail) + : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), + _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(__head)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl& __in) + : _Inherited(__tag, __a, _M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl&& __in) + : _Inherited(__tag, __a, std::move(_M_tail(__in))), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + std::forward<_Head>(_M_head(__in))) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead, _UTails...>& __in) + : _Inherited(__tag, __a, + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(__tag, __a, std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) + { + _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); + _M_tail(*this)._M_assign( + _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)); + } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + { + _M_head(*this) = std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); + _M_tail(*this)._M_assign( + std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); + } + + protected: + _GLIBCXX20_CONSTEXPR + void + _M_swap(_Tuple_impl& __in) + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + _Inherited::_M_swap(_M_tail(__in)); + } + }; + + // Basis case of inheritance recursion. + template + struct _Tuple_impl<_Idx, _Head> + : private _Head_base<_Idx, _Head> + { + template friend class _Tuple_impl; + + typedef _Head_base<_Idx, _Head> _Base; + + static constexpr _Head& + _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr const _Head& + _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + constexpr _Tuple_impl() + : _Base() { } + + explicit + constexpr _Tuple_impl(const _Head& __head) + : _Base(__head) { } + + template + explicit + constexpr _Tuple_impl(_UHead&& __head) + : _Base(std::forward<_UHead>(__head)) { } + + constexpr _Tuple_impl(const _Tuple_impl&) = default; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2729. Missing SFINAE on std::pair::operator= + _Tuple_impl& operator=(const _Tuple_impl&) = delete; + + constexpr + _Tuple_impl(_Tuple_impl&& __in) + noexcept(is_nothrow_move_constructible<_Head>::value) + : _Base(std::forward<_Head>(_M_head(__in))) { } + + template + constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in) + : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } + + template + constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in) + : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) + : _Base(__tag, __use_alloc<_Head>(__a)) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Head& __head) + : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _UHead&& __head) + : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(__head)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl& __in) + : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl&& __in) + : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + std::forward<_Head>(_M_head(__in))) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead>& __in) + : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), + _Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead>&& __in) + : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) + { + _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); + } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) + { + _M_head(*this) + = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); + } + + protected: + _GLIBCXX20_CONSTEXPR + void + _M_swap(_Tuple_impl& __in) + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + } + }; + + // Concept utility functions, reused in conditionally-explicit + // constructors. + template + struct _TupleConstraints + { + // Constraint for a non-explicit constructor. + // True iff each Ti in _Types... can be constructed from Ui in _UTypes... + // and every Ui is implicitly convertible to Ti. + template + static constexpr bool __is_implicitly_constructible() + { + return __and_..., + is_convertible<_UTypes, _Types>... + >::value; + } + + // Constraint for a non-explicit constructor. + // True iff each Ti in _Types... can be constructed from Ui in _UTypes... + // but not every Ui is implicitly convertible to Ti. + template + static constexpr bool __is_explicitly_constructible() + { + return __and_..., + __not_<__and_...>> + >::value; + } + + static constexpr bool __is_implicitly_default_constructible() + { + return __and_... + >::value; + } + + static constexpr bool __is_explicitly_default_constructible() + { + return __and_..., + __not_<__and_< + std::__is_implicitly_default_constructible<_Types>...> + >>::value; + } + }; + + // Partial specialization used when a required precondition isn't met, + // e.g. when sizeof...(_Types) != sizeof...(_UTypes). + template + struct _TupleConstraints + { + template + static constexpr bool __is_implicitly_constructible() + { return false; } + + template + static constexpr bool __is_explicitly_constructible() + { return false; } + }; + + /// Primary class template, tuple + template + class tuple : public _Tuple_impl<0, _Elements...> + { + typedef _Tuple_impl<0, _Elements...> _Inherited; + + template + using _TCC = _TupleConstraints<_Cond, _Elements...>; + + // Constraint for non-explicit default constructor + template + using _ImplicitDefaultCtor = __enable_if_t< + _TCC<_Dummy>::__is_implicitly_default_constructible(), + bool>; + + // Constraint for explicit default constructor + template + using _ExplicitDefaultCtor = __enable_if_t< + _TCC<_Dummy>::__is_explicitly_default_constructible(), + bool>; + + // Constraint for non-explicit constructors + template + using _ImplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(), + bool>; + + // Constraint for non-explicit constructors + template + using _ExplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(), + bool>; + + template + static constexpr + __enable_if_t + __assignable() + { return __and_...>::value; } + + // Condition for noexcept-specifier of an assignment operator. + template + static constexpr bool __nothrow_assignable() + { + return + __and_...>::value; + } + + // Condition for noexcept-specifier of a constructor. + template + static constexpr bool __nothrow_constructible() + { + return + __and_...>::value; + } + + // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1. + template + static constexpr bool __valid_args() + { + return sizeof...(_Elements) == 1 + && !is_same>::value; + } + + // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1. + template + static constexpr bool __valid_args() + { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); } + + /* Constraint for constructors with a tuple parameter ensures + * that the constructor is only viable when it would not interfere with + * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&). + * Such constructors are only viable if: + * either sizeof...(Types) != 1, + * or (when Types... expands to T and UTypes... expands to U) + * is_convertible_v, is_constructible_v, + * and is_same_v are all false. + */ + template> + struct _UseOtherCtor + : false_type + { }; + // If TUPLE is convertible to the single element in *this, + // then TUPLE should match tuple(UTypes&&...) instead. + template + struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>> + : __or_, is_constructible<_Tp, _Tuple>> + { }; + // If TUPLE and *this each have a single element of the same type, + // then TUPLE should match a copy/move constructor instead. + template + struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>> + : true_type + { }; + + // Return true iff sizeof...(Types) == 1 && tuple_size_v == 1 + // and the single element in Types can be initialized from TUPLE, + // or is the same type as tuple_element_t<0, TUPLE>. + template + static constexpr bool __use_other_ctor() + { return _UseOtherCtor<_Tuple>::value; } + + public: + template::value> = true> + constexpr + tuple() + noexcept(__and_...>::value) + : _Inherited() { } + + template::value> = false> + explicit constexpr + tuple() + noexcept(__and_...>::value) + : _Inherited() { } + + template= 1), + _ImplicitCtor<_NotEmpty, const _Elements&...> = true> + constexpr + tuple(const _Elements&... __elements) + noexcept(__nothrow_constructible()) + : _Inherited(__elements...) { } + + template= 1), + _ExplicitCtor<_NotEmpty, const _Elements&...> = false> + explicit constexpr + tuple(const _Elements&... __elements) + noexcept(__nothrow_constructible()) + : _Inherited(__elements...) { } + + template(), + _ImplicitCtor<_Valid, _UElements...> = true> + constexpr + tuple(_UElements&&... __elements) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(std::forward<_UElements>(__elements)...) { } + + template(), + _ExplicitCtor<_Valid, _UElements...> = false> + explicit constexpr + tuple(_UElements&&... __elements) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(std::forward<_UElements>(__elements)...) { } + + constexpr tuple(const tuple&) = default; + + constexpr tuple(tuple&&) = default; + + template&>(), + _ImplicitCtor<_Valid, const _UElements&...> = true> + constexpr + tuple(const tuple<_UElements...>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) + { } + + template&>(), + _ExplicitCtor<_Valid, const _UElements&...> = false> + explicit constexpr + tuple(const tuple<_UElements...>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) + { } + + template&&>(), + _ImplicitCtor<_Valid, _UElements...> = true> + constexpr + tuple(tuple<_UElements...>&& __in) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } + + template&&>(), + _ExplicitCtor<_Valid, _UElements...> = false> + explicit constexpr + tuple(tuple<_UElements...>&& __in) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } + + // Allocator-extended constructors. + + template::value> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template= 1), + _ImplicitCtor<_NotEmpty, const _Elements&...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _Elements&... __elements) + : _Inherited(__tag, __a, __elements...) { } + + template= 1), + _ExplicitCtor<_NotEmpty, const _Elements&...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _Elements&... __elements) + : _Inherited(__tag, __a, __elements...) { } + + template(), + _ImplicitCtor<_Valid, _UElements...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + _UElements&&... __elements) + : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) + { } + + template(), + _ExplicitCtor<_Valid, _UElements...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + _UElements&&... __elements) + : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) + { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template&>(), + _ImplicitCtor<_Valid, const _UElements&...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UElements...>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template&>(), + _ExplicitCtor<_Valid, const _UElements&...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UElements...>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template&&>(), + _ImplicitCtor<_Valid, _UElements...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_UElements...>&& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { } + + template&&>(), + _ExplicitCtor<_Valid, _UElements...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_UElements...>&& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { } + + // tuple assignment + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(typename conditional<__assignable(), + const tuple&, + const __nonesuch&>::type __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(typename conditional<__assignable<_Elements...>(), + tuple&&, + __nonesuch&&>::type __in) + noexcept(__nothrow_assignable<_Elements...>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const tuple<_UElements...>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_UElements...>(), tuple&> + operator=(tuple<_UElements...>&& __in) + noexcept(__nothrow_assignable<_UElements...>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + // tuple swap + _GLIBCXX20_CONSTEXPR + void + swap(tuple& __in) + noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value) + { _Inherited::_M_swap(__in); } + }; + +#if __cpp_deduction_guides >= 201606 + template + tuple(_UTypes...) -> tuple<_UTypes...>; + template + tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>; + template + tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>; + template + tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>; + template + tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>; +#endif + + // Explicit specialization, zero-element tuple. + template<> + class tuple<> + { + public: + void swap(tuple&) noexcept { /* no-op */ } + // We need the default since we're going to define no-op + // allocator constructors. + tuple() = default; + // No-op allocator constructors. + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t, const _Alloc&) noexcept { } + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { } + }; + + /// Partial specialization, 2-element tuple. + /// Includes construction and assignment from a pair. + template + class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> + { + typedef _Tuple_impl<0, _T1, _T2> _Inherited; + + // Constraint for non-explicit default constructor + template + using _ImplicitDefaultCtor = __enable_if_t< + _TupleConstraints<_Dummy, _U1, _U2>:: + __is_implicitly_default_constructible(), + bool>; + + // Constraint for explicit default constructor + template + using _ExplicitDefaultCtor = __enable_if_t< + _TupleConstraints<_Dummy, _U1, _U2>:: + __is_explicitly_default_constructible(), + bool>; + + template + using _TCC = _TupleConstraints<_Dummy, _T1, _T2>; + + // Constraint for non-explicit constructors + template + using _ImplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(), + bool>; + + // Constraint for non-explicit constructors + template + using _ExplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(), + bool>; + + template + static constexpr bool __assignable() + { + return __and_, + is_assignable<_T2&, _U2>>::value; + } + + template + static constexpr bool __nothrow_assignable() + { + return __and_, + is_nothrow_assignable<_T2&, _U2>>::value; + } + + template + static constexpr bool __nothrow_constructible() + { + return __and_, + is_nothrow_constructible<_T2, _U2>>::value; + } + + static constexpr bool __nothrow_default_constructible() + { + return __and_, + is_nothrow_default_constructible<_T2>>::value; + } + + template + static constexpr bool __is_alloc_arg() + { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; } + + public: + template = true> + constexpr + tuple() + noexcept(__nothrow_default_constructible()) + : _Inherited() { } + + template = false> + explicit constexpr + tuple() + noexcept(__nothrow_default_constructible()) + : _Inherited() { } + + template = true> + constexpr + tuple(const _T1& __a1, const _T2& __a2) + noexcept(__nothrow_constructible()) + : _Inherited(__a1, __a2) { } + + template = false> + explicit constexpr + tuple(const _T1& __a1, const _T2& __a2) + noexcept(__nothrow_constructible()) + : _Inherited(__a1, __a2) { } + + template(), _U1, _U2> = true> + constexpr + tuple(_U1&& __a1, _U2&& __a2) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } + + template(), _U1, _U2> = false> + explicit constexpr + tuple(_U1&& __a1, _U2&& __a2) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } + + constexpr tuple(const tuple&) = default; + + constexpr tuple(tuple&&) = default; + + template = true> + constexpr + tuple(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) { } + + template = false> + explicit constexpr + tuple(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) { } + + template = true> + constexpr + tuple(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } + + template = false> + explicit constexpr + tuple(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } + + template = true> + constexpr + tuple(const pair<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(__in.first, __in.second) { } + + template = false> + explicit constexpr + tuple(const pair<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(__in.first, __in.second) { } + + template = true> + constexpr + tuple(pair<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + + template = false> + explicit constexpr + tuple(pair<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + + // Allocator-extended constructors. + + template::value, _T1, _T2> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _T1& __a1, const _T2& __a2) + : _Inherited(__tag, __a, __a1, __a2) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _T1& __a1, const _T2& __a2) + : _Inherited(__tag, __a, __a1, __a2) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2) + : _Inherited(__tag, __a, std::forward<_U1>(__a1), + std::forward<_U2>(__a2)) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + _U1&& __a1, _U2&& __a2) + : _Inherited(__tag, __a, std::forward<_U1>(__a1), + std::forward<_U2>(__a2)) { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_U1, _U2>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_U1, _U2>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>& __in) + : _Inherited(__tag, __a, __in.first, __in.second) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>& __in) + : _Inherited(__tag, __a, __in.first, __in.second) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) + : _Inherited(__tag, __a, std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) + : _Inherited(__tag, __a, std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + + // Tuple assignment. + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(typename conditional<__assignable(), + const tuple&, + const __nonesuch&>::type __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(typename conditional<__assignable<_T1, _T2>(), + tuple&&, + __nonesuch&&>::type __in) + noexcept(__nothrow_assignable<_T1, _T2>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_U1, _U2>(), tuple&> + operator=(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_assignable<_U1, _U2>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const pair<_U1, _U2>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_head(*this) = __in.first; + this->_M_tail(*this)._M_head(*this) = __in.second; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_U1, _U2>(), tuple&> + operator=(pair<_U1, _U2>&& __in) + noexcept(__nothrow_assignable<_U1, _U2>()) + { + this->_M_head(*this) = std::forward<_U1>(__in.first); + this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); + return *this; + } + + _GLIBCXX20_CONSTEXPR + void + swap(tuple& __in) + noexcept(__and_<__is_nothrow_swappable<_T1>, + __is_nothrow_swappable<_T2>>::value) + { _Inherited::_M_swap(__in); } + }; + + + /// class tuple_size + template + struct tuple_size> + : public integral_constant { }; + +#if __cplusplus > 201402L + template + inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; +#endif + + /** + * Recursive case for tuple_element: strip off the first element in + * the tuple and retrieve the (i-1)th element of the remaining tuple. + */ + template + struct tuple_element<__i, tuple<_Head, _Tail...> > + : tuple_element<__i - 1, tuple<_Tail...> > { }; + + /** + * Basis case for tuple_element: The first element is the one we're seeking. + */ + template + struct tuple_element<0, tuple<_Head, _Tail...> > + { + typedef _Head type; + }; + + /** + * Error case for tuple_element: invalid index. + */ + template + struct tuple_element<__i, tuple<>> + { + static_assert(__i < tuple_size>::value, + "tuple index is in range"); + }; + + template + constexpr _Head& + __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + template + constexpr const _Head& + __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + /// Return a reference to the ith element of a tuple. + template + constexpr __tuple_element_t<__i, tuple<_Elements...>>& + get(tuple<_Elements...>& __t) noexcept + { return std::__get_helper<__i>(__t); } + + /// Return a const reference to the ith element of a const tuple. + template + constexpr const __tuple_element_t<__i, tuple<_Elements...>>& + get(const tuple<_Elements...>& __t) noexcept + { return std::__get_helper<__i>(__t); } + + /// Return an rvalue reference to the ith element of a tuple rvalue. + template + constexpr __tuple_element_t<__i, tuple<_Elements...>>&& + get(tuple<_Elements...>&& __t) noexcept + { + typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; + return std::forward<__element_type&&>(std::get<__i>(__t)); + } + + /// Return a const rvalue reference to the ith element of a const tuple rvalue. + template + constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& + get(const tuple<_Elements...>&& __t) noexcept + { + typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; + return std::forward(std::get<__i>(__t)); + } + +#if __cplusplus >= 201402L + +#define __cpp_lib_tuples_by_type 201304 + + template + constexpr _Head& + __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + template + constexpr const _Head& + __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + /// Return a reference to the unique element of type _Tp of a tuple. + template + constexpr _Tp& + get(tuple<_Types...>& __t) noexcept + { return std::__get_helper2<_Tp>(__t); } + + /// Return a reference to the unique element of type _Tp of a tuple rvalue. + template + constexpr _Tp&& + get(tuple<_Types...>&& __t) noexcept + { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } + + /// Return a const reference to the unique element of type _Tp of a tuple. + template + constexpr const _Tp& + get(const tuple<_Types...>& __t) noexcept + { return std::__get_helper2<_Tp>(__t); } + + /// Return a const reference to the unique element of type _Tp of + /// a const tuple rvalue. + template + constexpr const _Tp&& + get(const tuple<_Types...>&& __t) noexcept + { return std::forward(std::__get_helper2<_Tp>(__t)); } +#endif + + // This class performs the comparison operations on tuples + template + struct __tuple_compare + { + static constexpr bool + __eq(const _Tp& __t, const _Up& __u) + { + return bool(std::get<__i>(__t) == std::get<__i>(__u)) + && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u); + } + + static constexpr bool + __less(const _Tp& __t, const _Up& __u) + { + return bool(std::get<__i>(__t) < std::get<__i>(__u)) + || (!bool(std::get<__i>(__u) < std::get<__i>(__t)) + && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u)); + } + }; + + template + struct __tuple_compare<_Tp, _Up, __size, __size> + { + static constexpr bool + __eq(const _Tp&, const _Up&) { return true; } + + static constexpr bool + __less(const _Tp&, const _Up&) { return false; } + }; + + template + constexpr bool + operator==(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { + static_assert(sizeof...(_TElements) == sizeof...(_UElements), + "tuple objects can only be compared if they have equal sizes."); + using __compare = __tuple_compare, + tuple<_UElements...>, + 0, sizeof...(_TElements)>; + return __compare::__eq(__t, __u); + } + +#if __cpp_lib_three_way_comparison + template + constexpr _Cat + __tuple_cmp(const _Tp&, const _Up&, index_sequence<>) + { return _Cat::equivalent; } + + template + constexpr _Cat + __tuple_cmp(const _Tp& __t, const _Up& __u, + index_sequence<_Idx0, _Idxs...>) + { + auto __c + = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u)); + if (__c != 0) + return __c; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>()); + } + + template + constexpr + common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...> + operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u) + { + using _Cat + = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>()); + } +#else + template + constexpr bool + operator<(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { + static_assert(sizeof...(_TElements) == sizeof...(_UElements), + "tuple objects can only be compared if they have equal sizes."); + using __compare = __tuple_compare, + tuple<_UElements...>, + 0, sizeof...(_TElements)>; + return __compare::__less(__t, __u); + } + + template + constexpr bool + operator!=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__t == __u); } + + template + constexpr bool + operator>(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return __u < __t; } + + template + constexpr bool + operator<=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__u < __t); } + + template + constexpr bool + operator>=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__t < __u); } +#endif // three_way_comparison + + // NB: DR 705. + template + constexpr tuple::__type...> + make_tuple(_Elements&&... __args) + { + typedef tuple::__type...> + __result_type; + return __result_type(std::forward<_Elements>(__args)...); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2275. Why is forward_as_tuple not constexpr? + /// std::forward_as_tuple + template + constexpr tuple<_Elements&&...> + forward_as_tuple(_Elements&&... __args) noexcept + { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } + + template + struct __make_tuple_impl; + + template + struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> + : __make_tuple_impl<_Idx + 1, + tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>, + _Tuple, _Nm> + { }; + + template + struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> + { + typedef tuple<_Tp...> __type; + }; + + template + struct __do_make_tuple + : __make_tuple_impl<0, tuple<>, _Tuple, std::tuple_size<_Tuple>::value> + { }; + + // Returns the std::tuple equivalent of a tuple-like type. + template + struct __make_tuple + : public __do_make_tuple<__remove_cvref_t<_Tuple>> + { }; + + // Combines several std::tuple's into a single one. + template + struct __combine_tuples; + + template<> + struct __combine_tuples<> + { + typedef tuple<> __type; + }; + + template + struct __combine_tuples> + { + typedef tuple<_Ts...> __type; + }; + + template + struct __combine_tuples, tuple<_T2s...>, _Rem...> + { + typedef typename __combine_tuples, + _Rem...>::__type __type; + }; + + // Computes the result type of tuple_cat given a set of tuple-like types. + template + struct __tuple_cat_result + { + typedef typename __combine_tuples + ::__type...>::__type __type; + }; + + // Helper to determine the index set for the first tuple-like + // type of a given set. + template + struct __make_1st_indices; + + template<> + struct __make_1st_indices<> + { + typedef std::_Index_tuple<> __type; + }; + + template + struct __make_1st_indices<_Tp, _Tpls...> + { + typedef typename std::_Build_index_tuple::type>::value>::__type __type; + }; + + // Performs the actual concatenation by step-wise expanding tuple-like + // objects into the elements, which are finally forwarded into the + // result tuple. + template + struct __tuple_concater; + + template + struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> + { + template + static constexpr _Ret + _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) + { + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; + return __next::_S_do(std::forward<_Tpls>(__tps)..., + std::forward<_Us>(__us)..., + std::get<_Is>(std::forward<_Tp>(__tp))...); + } + }; + + template + struct __tuple_concater<_Ret, std::_Index_tuple<>> + { + template + static constexpr _Ret + _S_do(_Us&&... __us) + { + return _Ret(std::forward<_Us>(__us)...); + } + }; + + /// tuple_cat + template...>::value>::type> + constexpr auto + tuple_cat(_Tpls&&... __tpls) + -> typename __tuple_cat_result<_Tpls...>::__type + { + typedef typename __tuple_cat_result<_Tpls...>::__type __ret; + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; + return __concater::_S_do(std::forward<_Tpls>(__tpls)...); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2301. Why is tie not constexpr? + /// tie + template + constexpr tuple<_Elements&...> + tie(_Elements&... __args) noexcept + { return tuple<_Elements&...>(__args...); } + + /// swap + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_Elements>...>::value + >::type +#else + void +#endif + swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + _GLIBCXX20_CONSTEXPR + typename enable_if...>::value>::type + swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete; +#endif + + // A class (and instance) which can be used in 'tie' when an element + // of a tuple is not required. + // _GLIBCXX14_CONSTEXPR + // 2933. PR for LWG 2773 could be clearer + struct _Swallow_assign + { + template + _GLIBCXX14_CONSTEXPR const _Swallow_assign& + operator=(const _Tp&) const + { return *this; } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2773. Making std::ignore constexpr + _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{}; + + /// Partial specialization for tuples + template + struct uses_allocator, _Alloc> : true_type { }; + + // See stl_pair.h... + /** "piecewise construction" using a tuple of arguments for each member. + * + * @param __first Arguments for the first member of the pair. + * @param __second Arguments for the second member of the pair. + * + * The elements of each tuple will be used as the constructor arguments + * for the data members of the pair. + */ + template + template + _GLIBCXX20_CONSTEXPR + inline + pair<_T1, _T2>:: + pair(piecewise_construct_t, + tuple<_Args1...> __first, tuple<_Args2...> __second) + : pair(__first, __second, + typename _Build_index_tuple::__type(), + typename _Build_index_tuple::__type()) + { } + + template + template + _GLIBCXX20_CONSTEXPR inline + pair<_T1, _T2>:: + pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2, + _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>) + : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...), + second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) + { } + +#if __cplusplus >= 201703L + + // Unpack a std::tuple into a type trait and use its value. + // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value. + // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value. + // Otherwise the result is false (because we don't know if std::get throws). + template class _Trait, typename _Tp, typename _Tuple> + inline constexpr bool __unpack_std_tuple = false; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>> + = _Trait<_Tp, _Up...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&> + = _Trait<_Tp, _Up&...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>> + = _Trait<_Tp, const _Up...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&> + = _Trait<_Tp, const _Up&...>::value; + +# define __cpp_lib_apply 201603 + + template + constexpr decltype(auto) + __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>) + { + return std::__invoke(std::forward<_Fn>(__f), + std::get<_Idx>(std::forward<_Tuple>(__t))...); + } + + template + constexpr decltype(auto) + apply(_Fn&& __f, _Tuple&& __t) + noexcept(__unpack_std_tuple) + { + using _Indices + = make_index_sequence>>; + return std::__apply_impl(std::forward<_Fn>(__f), + std::forward<_Tuple>(__t), + _Indices{}); + } + +#define __cpp_lib_make_from_tuple 201606 + + template + constexpr _Tp + __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) + { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } + + template + constexpr _Tp + make_from_tuple(_Tuple&& __t) + noexcept(__unpack_std_tuple) + { + return __make_from_tuple_impl<_Tp>( + std::forward<_Tuple>(__t), + make_index_sequence>>{}); + } +#endif // C++17 + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_TUPLE diff --git a/resources/sources/avr-libstdcpp/include/type_traits b/resources/sources/avr-libstdcpp/include/type_traits new file mode 100644 index 000000000..37ef4238d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/type_traits @@ -0,0 +1,3774 @@ +// C++11 -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/type_traits + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TYPE_TRAITS +#define _GLIBCXX_TYPE_TRAITS 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup metaprogramming Metaprogramming + * @ingroup utilities + * + * Template utilities for compile-time introspection and modification, + * including type classification traits, type property inspection traits + * and type transformation traits. + * + * @{ + */ + + /// integral_constant + template + struct integral_constant + { + static constexpr _Tp value = __v; + typedef _Tp value_type; + typedef integral_constant<_Tp, __v> type; + constexpr operator value_type() const noexcept { return value; } +#if __cplusplus > 201103L + +#define __cpp_lib_integral_constant_callable 201304 + + constexpr value_type operator()() const noexcept { return value; } +#endif + }; + + template + constexpr _Tp integral_constant<_Tp, __v>::value; + + /// The type used as a compile-time boolean with true value. + typedef integral_constant true_type; + + /// The type used as a compile-time boolean with false value. + typedef integral_constant false_type; + + template + using __bool_constant = integral_constant; + +#if __cplusplus > 201402L +# define __cpp_lib_bool_constant 201505 + template + using bool_constant = integral_constant; +#endif + + // Meta programming helper types. + + template + struct conditional; + + template + struct __type_identity + { using type = _Type; }; + + template + using __type_identity_t = typename __type_identity<_Tp>::type; + + template + struct __or_; + + template<> + struct __or_<> + : public false_type + { }; + + template + struct __or_<_B1> + : public _B1 + { }; + + template + struct __or_<_B1, _B2> + : public conditional<_B1::value, _B1, _B2>::type + { }; + + template + struct __or_<_B1, _B2, _B3, _Bn...> + : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type + { }; + + template + struct __and_; + + template<> + struct __and_<> + : public true_type + { }; + + template + struct __and_<_B1> + : public _B1 + { }; + + template + struct __and_<_B1, _B2> + : public conditional<_B1::value, _B2, _B1>::type + { }; + + template + struct __and_<_B1, _B2, _B3, _Bn...> + : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type + { }; + + template + struct __not_ + : public __bool_constant + { }; + +#if __cplusplus >= 201703L + + template + inline constexpr bool __or_v = __or_<_Bn...>::value; + template + inline constexpr bool __and_v = __and_<_Bn...>::value; + +#define __cpp_lib_logical_traits 201510 + + template + struct conjunction + : __and_<_Bn...> + { }; + + template + struct disjunction + : __or_<_Bn...> + { }; + + template + struct negation + : __not_<_Pp> + { }; + + template + inline constexpr bool conjunction_v = conjunction<_Bn...>::value; + + template + inline constexpr bool disjunction_v = disjunction<_Bn...>::value; + + template + inline constexpr bool negation_v = negation<_Pp>::value; + +#endif // C++17 + + // Forward declarations + template + struct is_reference; + template + struct is_function; + template + struct is_void; + template + struct __is_array_unknown_bounds; + + // Helper functions that return false_type for incomplete classes, + // incomplete unions and arrays of known bound from those. + + template + constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>) + { return {}; } + + template + constexpr typename __or_< + is_reference<_NestedType>, + is_function<_NestedType>, + is_void<_NestedType>, + __is_array_unknown_bounds<_NestedType> + >::type __is_complete_or_unbounded(_TypeIdentity) + { return {}; } + + // For several sfinae-friendly trait implementations we transport both the + // result information (as the member type) and the failure information (no + // member type). This is very similar to std::enable_if, but we cannot use + // them, because we need to derive from them as an implementation detail. + + template + struct __success_type + { typedef _Tp type; }; + + struct __failure_type + { }; + + template + struct remove_cv; + + // __remove_cv_t (std::remove_cv_t for C++11). + template + using __remove_cv_t = typename remove_cv<_Tp>::type; + + template + struct is_const; + + // Primary type categories. + + template + struct __is_void_helper + : public false_type { }; + + template<> + struct __is_void_helper + : public true_type { }; + + /// is_void + template + struct is_void + : public __is_void_helper<__remove_cv_t<_Tp>>::type + { }; + + template + struct __is_integral_helper + : public false_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct __is_integral_helper + : public true_type { }; +#endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_integral_helper + : public true_type { }; +#endif + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + // Conditionalizing on __STRICT_ANSI__ here will break any port that + // uses one of these types for size_t. +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0> + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1> + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2> + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3> + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; +#endif + + /// is_integral + template + struct is_integral + : public __is_integral_helper<__remove_cv_t<_Tp>>::type + { }; + + template + struct __is_floating_point_helper + : public false_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + template<> + struct __is_floating_point_helper<__float128> + : public true_type { }; +#endif + + /// is_floating_point + template + struct is_floating_point + : public __is_floating_point_helper<__remove_cv_t<_Tp>>::type + { }; + + /// is_array + template + struct is_array + : public false_type { }; + + template + struct is_array<_Tp[_Size]> + : public true_type { }; + + template + struct is_array<_Tp[]> + : public true_type { }; + + template + struct __is_pointer_helper + : public false_type { }; + + template + struct __is_pointer_helper<_Tp*> + : public true_type { }; + + /// is_pointer + template + struct is_pointer + : public __is_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + /// is_lvalue_reference + template + struct is_lvalue_reference + : public false_type { }; + + template + struct is_lvalue_reference<_Tp&> + : public true_type { }; + + /// is_rvalue_reference + template + struct is_rvalue_reference + : public false_type { }; + + template + struct is_rvalue_reference<_Tp&&> + : public true_type { }; + + template + struct __is_member_object_pointer_helper + : public false_type { }; + + template + struct __is_member_object_pointer_helper<_Tp _Cp::*> + : public __not_>::type { }; + + /// is_member_object_pointer + template + struct is_member_object_pointer + : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + template + struct __is_member_function_pointer_helper + : public false_type { }; + + template + struct __is_member_function_pointer_helper<_Tp _Cp::*> + : public is_function<_Tp>::type { }; + + /// is_member_function_pointer + template + struct is_member_function_pointer + : public __is_member_function_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + /// is_enum + template + struct is_enum + : public integral_constant + { }; + + /// is_union + template + struct is_union + : public integral_constant + { }; + + /// is_class + template + struct is_class + : public integral_constant + { }; + + /// is_function + template + struct is_function + : public __bool_constant::value> { }; + + template + struct is_function<_Tp&> + : public false_type { }; + + template + struct is_function<_Tp&&> + : public false_type { }; + +#define __cpp_lib_is_null_pointer 201309 + + template + struct __is_null_pointer_helper + : public false_type { }; + + template<> + struct __is_null_pointer_helper + : public true_type { }; + + /// is_null_pointer (LWG 2247). + template + struct is_null_pointer + : public __is_null_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + /// __is_nullptr_t (deprecated extension). + template + struct __is_nullptr_t + : public is_null_pointer<_Tp> + { } _GLIBCXX_DEPRECATED_SUGGEST("std::is_null_pointer"); + + // Composite type categories. + + /// is_reference + template + struct is_reference + : public __or_, + is_rvalue_reference<_Tp>>::type + { }; + + /// is_arithmetic + template + struct is_arithmetic + : public __or_, is_floating_point<_Tp>>::type + { }; + + /// is_fundamental + template + struct is_fundamental + : public __or_, is_void<_Tp>, + is_null_pointer<_Tp>>::type + { }; + + /// is_object + template + struct is_object + : public __not_<__or_, is_reference<_Tp>, + is_void<_Tp>>>::type + { }; + + template + struct is_member_pointer; + + /// is_scalar + template + struct is_scalar + : public __or_, is_enum<_Tp>, is_pointer<_Tp>, + is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type + { }; + + /// is_compound + template + struct is_compound + : public __not_>::type { }; + + template + struct __is_member_pointer_helper + : public false_type { }; + + template + struct __is_member_pointer_helper<_Tp _Cp::*> + : public true_type { }; + + /// is_member_pointer + template + struct is_member_pointer + : public __is_member_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + template + struct is_same; + + template + using __is_one_of = __or_...>; + + // Check if a type is one of the signed integer types. + template + using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>, + signed char, signed short, signed int, signed long, + signed long long +#if defined(__GLIBCXX_TYPE_INT_N_0) + , signed __GLIBCXX_TYPE_INT_N_0 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + , signed __GLIBCXX_TYPE_INT_N_1 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + , signed __GLIBCXX_TYPE_INT_N_2 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + , signed __GLIBCXX_TYPE_INT_N_3 +#endif + >; + + // Check if a type is one of the unsigned integer types. + template + using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>, + unsigned char, unsigned short, unsigned int, unsigned long, + unsigned long long +#if defined(__GLIBCXX_TYPE_INT_N_0) + , unsigned __GLIBCXX_TYPE_INT_N_0 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + , unsigned __GLIBCXX_TYPE_INT_N_1 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + , unsigned __GLIBCXX_TYPE_INT_N_2 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + , unsigned __GLIBCXX_TYPE_INT_N_3 +#endif + >; + + // Check if a type is one of the signed or unsigned integer types. + template + using __is_standard_integer + = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>; + + // __void_t (std::void_t for C++11) + template using __void_t = void; + + // Utility to detect referenceable types ([defns.referenceable]). + + template + struct __is_referenceable + : public false_type + { }; + + template + struct __is_referenceable<_Tp, __void_t<_Tp&>> + : public true_type + { }; + + // Type properties. + + /// is_const + template + struct is_const + : public false_type { }; + + template + struct is_const<_Tp const> + : public true_type { }; + + /// is_volatile + template + struct is_volatile + : public false_type { }; + + template + struct is_volatile<_Tp volatile> + : public true_type { }; + + /// is_trivial + template + struct is_trivial + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + // is_trivially_copyable + template + struct is_trivially_copyable + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_standard_layout + template + struct is_standard_layout + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_pod (deprecated in C++20) + // Could use is_standard_layout && is_trivial instead of the builtin. + template + struct + _GLIBCXX20_DEPRECATED("use is_standard_layout && is_trivial instead") + is_pod + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_literal_type + template + struct is_literal_type + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_empty + template + struct is_empty + : public integral_constant + { }; + + /// is_polymorphic + template + struct is_polymorphic + : public integral_constant + { }; + +#if __cplusplus >= 201402L +#define __cpp_lib_is_final 201402L + /// is_final + template + struct is_final + : public integral_constant + { }; +#endif + + /// is_abstract + template + struct is_abstract + : public integral_constant + { }; + + template::value> + struct __is_signed_helper + : public false_type { }; + + template + struct __is_signed_helper<_Tp, true> + : public integral_constant + { }; + + /// is_signed + template + struct is_signed + : public __is_signed_helper<_Tp>::type + { }; + + /// is_unsigned + template + struct is_unsigned + : public __and_, __not_>> + { }; + + + // Destructible and constructible type properties. + + /** + * @brief Utility to simplify expressions used in unevaluated operands + * @ingroup utilities + */ + + template + _Up + __declval(int); + + template + _Tp + __declval(long); + + template + auto declval() noexcept -> decltype(__declval<_Tp>(0)); + + template + struct extent; + + template + struct remove_all_extents; + + template + struct __is_array_known_bounds + : public integral_constant::value > 0)> + { }; + + template + struct __is_array_unknown_bounds + : public __and_, __not_>> + { }; + + // In N3290 is_destructible does not say anything about function + // types and abstract types, see LWG 2049. This implementation + // describes function types as non-destructible and all complete + // object types as destructible, iff the explicit destructor + // call expression is wellformed. + struct __do_is_destructible_impl + { + template().~_Tp())> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_destructible_impl + : public __do_is_destructible_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template, + __is_array_unknown_bounds<_Tp>, + is_function<_Tp>>::value, + bool = __or_, is_scalar<_Tp>>::value> + struct __is_destructible_safe; + + template + struct __is_destructible_safe<_Tp, false, false> + : public __is_destructible_impl::type>::type + { }; + + template + struct __is_destructible_safe<_Tp, true, false> + : public false_type { }; + + template + struct __is_destructible_safe<_Tp, false, true> + : public true_type { }; + + /// is_destructible + template + struct is_destructible + : public __is_destructible_safe<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + // is_nothrow_destructible requires that is_destructible is + // satisfied as well. We realize that by mimicing the + // implementation of is_destructible but refer to noexcept(expr) + // instead of decltype(expr). + struct __do_is_nt_destructible_impl + { + template + static __bool_constant().~_Tp())> + __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_nt_destructible_impl + : public __do_is_nt_destructible_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template, + __is_array_unknown_bounds<_Tp>, + is_function<_Tp>>::value, + bool = __or_, is_scalar<_Tp>>::value> + struct __is_nt_destructible_safe; + + template + struct __is_nt_destructible_safe<_Tp, false, false> + : public __is_nt_destructible_impl::type>::type + { }; + + template + struct __is_nt_destructible_safe<_Tp, true, false> + : public false_type { }; + + template + struct __is_nt_destructible_safe<_Tp, false, true> + : public true_type { }; + + /// is_nothrow_destructible + template + struct is_nothrow_destructible + : public __is_nt_destructible_safe<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +#if __GNUC__ >= 8 + template + struct __is_constructible_impl + : public __bool_constant<__is_constructible(_Tp, _Args...)> + { }; +#else + // Implementation of __is_constructible_impl. + + struct __do_is_default_constructible_impl + { + template + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_default_constructible_impl + : public __do_is_default_constructible_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template + struct __is_default_constructible_atom + : public __and_<__not_>, + __is_default_constructible_impl<_Tp>>::type + { }; + + template::value> + struct __is_default_constructible_safe; + + // The following technique is a workaround for a current core language + // restriction, which does not allow for array types to occur in + // functional casts of the form T(). Complete arrays can be default- + // constructed, if the element type is default-constructible, but + // arrays with unknown bounds are not. + template + struct __is_default_constructible_safe<_Tp, true> + : public __and_<__is_array_known_bounds<_Tp>, + __is_default_constructible_atom::type>>::type + { }; + + template + struct __is_default_constructible_safe<_Tp, false> + : public __is_default_constructible_atom<_Tp>::type + { }; + + // The hardest part of this trait is the binary direct-initialization + // case, because we hit into a functional cast of the form T(arg). + // This implementation uses different strategies depending on the + // target type to reduce the test overhead as much as possible: + // + // a) For a reference target type, we use a static_cast expression + // modulo its extra cases. + // + // b) For a non-reference target type we use a ::new expression. + struct __do_is_static_castable_impl + { + template(declval<_From>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_static_castable_impl + : public __do_is_static_castable_impl + { + typedef decltype(__test<_From, _To>(0)) type; + }; + + template + struct __is_static_castable_safe + : public __is_static_castable_impl<_From, _To>::type + { }; + + // __is_static_castable + template + struct __is_static_castable + : public integral_constant::value)> + { }; + + // Implementation for non-reference types. To meet the proper + // variable definition semantics, we also need to test for + // is_destructible in this case. + // This form should be simplified by a single expression: + // ::delete ::new _Tp(declval<_Arg>()), see c++/51222. + struct __do_is_direct_constructible_impl + { + template()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_direct_constructible_impl + : public __do_is_direct_constructible_impl + { + typedef decltype(__test<_Tp, _Arg>(0)) type; + }; + + template + struct __is_direct_constructible_new_safe + : public __and_, + __is_direct_constructible_impl<_Tp, _Arg>> + { }; + + template + struct is_same; + + template + struct is_base_of; + + template + struct remove_reference; + + template, + is_function<_From>>>::value> + struct __is_base_to_derived_ref; + + template + struct is_constructible; + + // Detect whether we have a downcast situation during + // reference binding. + template + struct __is_base_to_derived_ref<_From, _To, true> + { + typedef typename remove_cv::type>::type __src_t; + typedef typename remove_cv::type>::type __dst_t; + typedef __and_<__not_>, + is_base_of<__src_t, __dst_t>, + __not_>> type; + static constexpr bool value = type::value; + }; + + template + struct __is_base_to_derived_ref<_From, _To, false> + : public false_type + { }; + + template, + is_rvalue_reference<_To>>::value> + struct __is_lvalue_to_rvalue_ref; + + // Detect whether we have an lvalue of non-function type + // bound to a reference-compatible rvalue-reference. + template + struct __is_lvalue_to_rvalue_ref<_From, _To, true> + { + typedef typename remove_cv::type>::type __src_t; + typedef typename remove_cv::type>::type __dst_t; + typedef __and_<__not_>, + __or_, + is_base_of<__dst_t, __src_t>>> type; + static constexpr bool value = type::value; + }; + + template + struct __is_lvalue_to_rvalue_ref<_From, _To, false> + : public false_type + { }; + + // Here we handle direct-initialization to a reference type as + // equivalent to a static_cast modulo overshooting conversions. + // These are restricted to the following conversions: + // a) A base class value to a derived class reference + // b) An lvalue to an rvalue-reference of reference-compatible + // types that are not functions + template + struct __is_direct_constructible_ref_cast + : public __and_<__is_static_castable<_Arg, _Tp>, + __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>, + __is_lvalue_to_rvalue_ref<_Arg, _Tp> + >>> + { }; + + template + struct __is_direct_constructible_new + : public conditional::value, + __is_direct_constructible_ref_cast<_Tp, _Arg>, + __is_direct_constructible_new_safe<_Tp, _Arg> + >::type + { }; + + template + struct __is_direct_constructible + : public __is_direct_constructible_new<_Tp, _Arg>::type + { }; + + // Since default-construction and binary direct-initialization have + // been handled separately, the implementation of the remaining + // n-ary construction cases is rather straightforward. We can use + // here a functional cast, because array types are excluded anyway + // and this form is never interpreted as a C cast. + struct __do_is_nary_constructible_impl + { + template()...))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_nary_constructible_impl + : public __do_is_nary_constructible_impl + { + typedef decltype(__test<_Tp, _Args...>(0)) type; + }; + + template + struct __is_nary_constructible + : public __is_nary_constructible_impl<_Tp, _Args...>::type + { + static_assert(sizeof...(_Args) > 1, + "Only useful for > 1 arguments"); + }; + + template + struct __is_constructible_impl + : public __is_nary_constructible<_Tp, _Args...> + { }; + + template + struct __is_constructible_impl<_Tp, _Arg> + : public __is_direct_constructible<_Tp, _Arg> + { }; + + template + struct __is_constructible_impl<_Tp> + : public __is_default_constructible_safe<_Tp>::type + { }; +#endif + + /// is_constructible + template + struct is_constructible + : public __is_constructible_impl<_Tp, _Args...> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_default_constructible + template + struct is_default_constructible + : public __is_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_copy_constructible_impl; + + template + struct __is_copy_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_copy_constructible_impl<_Tp, true> + : public __is_constructible_impl<_Tp, const _Tp&> + { }; + + /// is_copy_constructible + template + struct is_copy_constructible + : public __is_copy_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_move_constructible_impl; + + template + struct __is_move_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_move_constructible_impl<_Tp, true> + : public __is_constructible_impl<_Tp, _Tp&&> + { }; + + /// is_move_constructible + template + struct is_move_constructible + : public __is_move_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template + struct __is_nt_constructible_impl + : public false_type + { }; + + template + struct __is_nt_constructible_impl + : public __bool_constant()...))> + { }; + + template + struct __is_nt_constructible_impl + : public __bool_constant(std::declval<_Arg>()))> + { }; + + template + struct __is_nt_constructible_impl + : public __bool_constant + { }; + + template + struct __is_nt_constructible_impl + : public __bool_constant::type())> + { }; + +#if __cpp_aggregate_paren_init + template + struct __is_nt_constructible_impl + : public __is_nt_constructible_impl + { }; + + template + struct __is_nt_constructible_impl + : public __and_<__is_nt_constructible_impl...> + { }; +#endif + +#if __GNUC__ >= 8 + template + using __is_nothrow_constructible_impl + = __is_nt_constructible_impl<__is_constructible(_Tp, _Args...), + _Tp, _Args...>; +#else + template + using __is_nothrow_constructible_impl + = __is_nt_constructible_impl<__is_constructible_impl<_Tp, _Args...>::value, + _Tp, _Args...>; +#endif + + /// is_nothrow_constructible + template + struct is_nothrow_constructible + : public __is_nothrow_constructible_impl<_Tp, _Args...>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_default_constructible + template + struct is_nothrow_default_constructible + : public __is_nothrow_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + + template::value> + struct __is_nothrow_copy_constructible_impl; + + template + struct __is_nothrow_copy_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_nothrow_copy_constructible_impl<_Tp, true> + : public __is_nothrow_constructible_impl<_Tp, const _Tp&> + { }; + + /// is_nothrow_copy_constructible + template + struct is_nothrow_copy_constructible + : public __is_nothrow_copy_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_nothrow_move_constructible_impl; + + template + struct __is_nothrow_move_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_nothrow_move_constructible_impl<_Tp, true> + : public __is_nothrow_constructible_impl<_Tp, _Tp&&> + { }; + + /// is_nothrow_move_constructible + template + struct is_nothrow_move_constructible + : public __is_nothrow_move_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +#if __GNUC__ >= 8 + /// is_assignable + template + struct is_assignable + : public __bool_constant<__is_assignable(_Tp, _Up)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; +#else + template + class __is_assignable_helper + { + template() = declval<_Up1>())> + static true_type + __test(int); + + template + static false_type + __test(...); + + public: + typedef decltype(__test<_Tp, _Up>(0)) type; + }; + + /// is_assignable + template + struct is_assignable + : public __is_assignable_helper<_Tp, _Up>::type + { }; +#endif + + template::value> + struct __is_copy_assignable_impl; + + template + struct __is_copy_assignable_impl<_Tp, false> + : public false_type { }; + +#if __GNUC__ >= 8 + template + struct __is_copy_assignable_impl<_Tp, true> + : public __bool_constant<__is_assignable(_Tp&, const _Tp&)> + { }; +#else + template + struct __is_copy_assignable_impl<_Tp, true> + : public is_assignable<_Tp&, const _Tp&> + { }; +#endif + + /// is_copy_assignable + template + struct is_copy_assignable + : public __is_copy_assignable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_move_assignable_impl; + + template + struct __is_move_assignable_impl<_Tp, false> + : public false_type { }; + +#if __GNUC__ >= 8 + template + struct __is_move_assignable_impl<_Tp, true> + : public __bool_constant<__is_assignable(_Tp&, _Tp&&)> + { }; +#else + template + struct __is_move_assignable_impl<_Tp, true> + : public is_assignable<_Tp&, _Tp&&> + { }; +#endif + + /// is_move_assignable + template + struct is_move_assignable + : public __is_move_assignable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template + struct __is_nt_assignable_impl + : public integral_constant() = declval<_Up>())> + { }; + +#if __GNUC__ >= 8 + template + struct __is_nothrow_assignable_impl + : public __and_<__bool_constant<__is_assignable(_Tp, _Up)>, + __is_nt_assignable_impl<_Tp, _Up>> + { }; +#else + template + struct __is_nothrow_assignable_impl + : public __and_, + __is_nt_assignable_impl<_Tp, _Up>> + { }; +#endif + + /// is_nothrow_assignable + template + struct is_nothrow_assignable + : public __is_nothrow_assignable_impl<_Tp, _Up> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_nt_copy_assignable_impl; + + template + struct __is_nt_copy_assignable_impl<_Tp, false> + : public false_type { }; + + template + struct __is_nt_copy_assignable_impl<_Tp, true> + : public __is_nothrow_assignable_impl<_Tp&, const _Tp&> + { }; + + /// is_nothrow_copy_assignable + template + struct is_nothrow_copy_assignable + : public __is_nt_copy_assignable_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_nt_move_assignable_impl; + + template + struct __is_nt_move_assignable_impl<_Tp, false> + : public false_type { }; + + template + struct __is_nt_move_assignable_impl<_Tp, true> + : public __is_nothrow_assignable_impl<_Tp&, _Tp&&> + { }; + + /// is_nothrow_move_assignable + template + struct is_nothrow_move_assignable + : public __is_nt_move_assignable_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_constructible + template + struct is_trivially_constructible + : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_default_constructible + template + struct is_trivially_default_constructible + : public __bool_constant<__is_trivially_constructible(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + struct __do_is_implicitly_default_constructible_impl + { + template + static void __helper(const _Tp&); + + template + static true_type __test(const _Tp&, + decltype(__helper({}))* = 0); + + static false_type __test(...); + }; + + template + struct __is_implicitly_default_constructible_impl + : public __do_is_implicitly_default_constructible_impl + { + typedef decltype(__test(declval<_Tp>())) type; + }; + + template + struct __is_implicitly_default_constructible_safe + : public __is_implicitly_default_constructible_impl<_Tp>::type + { }; + + template + struct __is_implicitly_default_constructible + : public __and_<__is_constructible_impl<_Tp>, + __is_implicitly_default_constructible_safe<_Tp>> + { }; + + template::value> + struct __is_trivially_copy_constructible_impl; + + template + struct __is_trivially_copy_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_trivially_copy_constructible_impl<_Tp, true> + : public __and_<__is_copy_constructible_impl<_Tp>, + integral_constant> + { }; + + /// is_trivially_copy_constructible + template + struct is_trivially_copy_constructible + : public __is_trivially_copy_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_trivially_move_constructible_impl; + + template + struct __is_trivially_move_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_trivially_move_constructible_impl<_Tp, true> + : public __and_<__is_move_constructible_impl<_Tp>, + integral_constant> + { }; + + /// is_trivially_move_constructible + template + struct is_trivially_move_constructible + : public __is_trivially_move_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_assignable + template + struct is_trivially_assignable + : public __bool_constant<__is_trivially_assignable(_Tp, _Up)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_trivially_copy_assignable_impl; + + template + struct __is_trivially_copy_assignable_impl<_Tp, false> + : public false_type { }; + + template + struct __is_trivially_copy_assignable_impl<_Tp, true> + : public __bool_constant<__is_trivially_assignable(_Tp&, const _Tp&)> + { }; + + /// is_trivially_copy_assignable + template + struct is_trivially_copy_assignable + : public __is_trivially_copy_assignable_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_trivially_move_assignable_impl; + + template + struct __is_trivially_move_assignable_impl<_Tp, false> + : public false_type { }; + + template + struct __is_trivially_move_assignable_impl<_Tp, true> + : public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)> + { }; + + /// is_trivially_move_assignable + template + struct is_trivially_move_assignable + : public __is_trivially_move_assignable_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_destructible + template + struct is_trivially_destructible + : public __and_<__is_destructible_safe<_Tp>, + __bool_constant<__has_trivial_destructor(_Tp)>> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + + /// has_virtual_destructor + template + struct has_virtual_destructor + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + + // type property queries. + + /// alignment_of + template + struct alignment_of + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// rank + template + struct rank + : public integral_constant { }; + + template + struct rank<_Tp[_Size]> + : public integral_constant::value> { }; + + template + struct rank<_Tp[]> + : public integral_constant::value> { }; + + /// extent + template + struct extent + : public integral_constant { }; + + template + struct extent<_Tp[_Size], _Uint> + : public integral_constant::value> + { }; + + template + struct extent<_Tp[], _Uint> + : public integral_constant::value> + { }; + + + // Type relations. + + /// is_same + template + struct is_same +#ifdef _GLIBCXX_BUILTIN_IS_SAME_AS + : public integral_constant +#else + : public false_type +#endif + { }; + +#ifndef _GLIBCXX_BUILTIN_IS_SAME_AS + template + struct is_same<_Tp, _Tp> + : public true_type + { }; +#endif + + /// is_base_of + template + struct is_base_of + : public integral_constant + { }; + + template, is_function<_To>, + is_array<_To>>::value> + struct __is_convertible_helper + { + typedef typename is_void<_To>::type type; + }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + template + class __is_convertible_helper<_From, _To, false> + { + template + static void __test_aux(_To1) noexcept; + + template(std::declval<_From1>()))> + static true_type + __test(int); + + template + static false_type + __test(...); + + public: + typedef decltype(__test<_From, _To>(0)) type; + }; +#pragma GCC diagnostic pop + + /// is_convertible + template + struct is_convertible + : public __is_convertible_helper<_From, _To>::type + { }; + + // helper trait for unique_ptr, shared_ptr, and span + template + using __is_array_convertible + = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>; + +#if __cplusplus >= 202002L +#define __cpp_lib_is_nothrow_convertible 201806L + +#if __has_builtin(__is_nothrow_convertible) + /// is_nothrow_convertible_v + template + inline constexpr bool is_nothrow_convertible_v + = __is_nothrow_convertible(_From, _To); + + /// is_nothrow_convertible + template + struct is_nothrow_convertible + : public bool_constant> + { }; +#else + template, is_function<_To>, + is_array<_To>>::value> + struct __is_nt_convertible_helper + : is_void<_To> + { }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + template + class __is_nt_convertible_helper<_From, _To, false> + { + template + static void __test_aux(_To1) noexcept; + + template + static + __bool_constant(std::declval<_From1>()))> + __test(int); + + template + static false_type + __test(...); + + public: + using type = decltype(__test<_From, _To>(0)); + }; +#pragma GCC diagnostic pop + + /// is_nothrow_convertible + template + struct is_nothrow_convertible + : public __is_nt_convertible_helper<_From, _To>::type + { }; + + /// is_nothrow_convertible_v + template + inline constexpr bool is_nothrow_convertible_v + = is_nothrow_convertible<_From, _To>::value; +#endif +#endif // C++2a + + // Const-volatile modifications. + + /// remove_const + template + struct remove_const + { typedef _Tp type; }; + + template + struct remove_const<_Tp const> + { typedef _Tp type; }; + + /// remove_volatile + template + struct remove_volatile + { typedef _Tp type; }; + + template + struct remove_volatile<_Tp volatile> + { typedef _Tp type; }; + + /// remove_cv + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; + + /// add_const + template + struct add_const + { typedef _Tp const type; }; + + /// add_volatile + template + struct add_volatile + { typedef _Tp volatile type; }; + + /// add_cv + template + struct add_cv + { + typedef typename + add_const::type>::type type; + }; + +#if __cplusplus > 201103L + +#define __cpp_lib_transformation_trait_aliases 201304 + + /// Alias template for remove_const + template + using remove_const_t = typename remove_const<_Tp>::type; + + /// Alias template for remove_volatile + template + using remove_volatile_t = typename remove_volatile<_Tp>::type; + + /// Alias template for remove_cv + template + using remove_cv_t = typename remove_cv<_Tp>::type; + + /// Alias template for add_const + template + using add_const_t = typename add_const<_Tp>::type; + + /// Alias template for add_volatile + template + using add_volatile_t = typename add_volatile<_Tp>::type; + + /// Alias template for add_cv + template + using add_cv_t = typename add_cv<_Tp>::type; +#endif + + // Reference transformations. + + /// remove_reference + template + struct remove_reference + { typedef _Tp type; }; + + template + struct remove_reference<_Tp&> + { typedef _Tp type; }; + + template + struct remove_reference<_Tp&&> + { typedef _Tp type; }; + + template::value> + struct __add_lvalue_reference_helper + { typedef _Tp type; }; + + template + struct __add_lvalue_reference_helper<_Tp, true> + { typedef _Tp& type; }; + + /// add_lvalue_reference + template + struct add_lvalue_reference + : public __add_lvalue_reference_helper<_Tp> + { }; + + template::value> + struct __add_rvalue_reference_helper + { typedef _Tp type; }; + + template + struct __add_rvalue_reference_helper<_Tp, true> + { typedef _Tp&& type; }; + + /// add_rvalue_reference + template + struct add_rvalue_reference + : public __add_rvalue_reference_helper<_Tp> + { }; + +#if __cplusplus > 201103L + /// Alias template for remove_reference + template + using remove_reference_t = typename remove_reference<_Tp>::type; + + /// Alias template for add_lvalue_reference + template + using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type; + + /// Alias template for add_rvalue_reference + template + using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type; +#endif + + // Sign modifications. + + // Utility for constructing identically cv-qualified types. + template + struct __cv_selector; + + template + struct __cv_selector<_Unqualified, false, false> + { typedef _Unqualified __type; }; + + template + struct __cv_selector<_Unqualified, false, true> + { typedef volatile _Unqualified __type; }; + + template + struct __cv_selector<_Unqualified, true, false> + { typedef const _Unqualified __type; }; + + template + struct __cv_selector<_Unqualified, true, true> + { typedef const volatile _Unqualified __type; }; + + template::value, + bool _IsVol = is_volatile<_Qualified>::value> + class __match_cv_qualifiers + { + typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match; + + public: + typedef typename __match::__type __type; + }; + + // Utility for finding the unsigned versions of signed integral types. + template + struct __make_unsigned + { typedef _Tp __type; }; + + template<> + struct __make_unsigned + { typedef unsigned char __type; }; + + template<> + struct __make_unsigned + { typedef unsigned char __type; }; + + template<> + struct __make_unsigned + { typedef unsigned short __type; }; + + template<> + struct __make_unsigned + { typedef unsigned int __type; }; + + template<> + struct __make_unsigned + { typedef unsigned long __type; }; + + template<> + struct __make_unsigned + { typedef unsigned long long __type; }; + +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0> + { typedef unsigned __GLIBCXX_TYPE_INT_N_0 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1> + { typedef unsigned __GLIBCXX_TYPE_INT_N_1 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2> + { typedef unsigned __GLIBCXX_TYPE_INT_N_2 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3> + { typedef unsigned __GLIBCXX_TYPE_INT_N_3 __type; }; +#endif + + // Select between integral and enum: not possible to be both. + template::value, + bool _IsEnum = is_enum<_Tp>::value> + class __make_unsigned_selector; + + template + class __make_unsigned_selector<_Tp, true, false> + { + using __unsigned_type + = typename __make_unsigned<__remove_cv_t<_Tp>>::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; + }; + + class __make_unsigned_selector_base + { + protected: + template struct _List { }; + + template + struct _List<_Tp, _Up...> : _List<_Up...> + { static constexpr size_t __size = sizeof(_Tp); }; + + template + struct __select; + + template + struct __select<_Sz, _List<_Uint, _UInts...>, true> + { using __type = _Uint; }; + + template + struct __select<_Sz, _List<_Uint, _UInts...>, false> + : __select<_Sz, _List<_UInts...>> + { }; + }; + + // Choose unsigned integer type with the smallest rank and same size as _Tp + template + class __make_unsigned_selector<_Tp, false, true> + : __make_unsigned_selector_base + { + // With -fshort-enums, an enum may be as small as a char. + using _UInts = _List; + + using __unsigned_type = typename __select::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; + }; + + // wchar_t, char8_t, char16_t and char32_t are integral types but are + // neither signed integer types nor unsigned integer types, so must be + // transformed to the unsigned integer type with the smallest rank. + // Use the partial specialization for enumeration types to do that. +#if defined(_GLIBCXX_USE_WCHAR_T) + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; +#endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; +#endif + + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; + + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; + + // Given an integral/enum type, return the corresponding unsigned + // integer type. + // Primary template. + /// make_unsigned + template + struct make_unsigned + { typedef typename __make_unsigned_selector<_Tp>::__type type; }; + + // Integral, but don't define. + template<> + struct make_unsigned; + + + // Utility for finding the signed versions of unsigned integral types. + template + struct __make_signed + { typedef _Tp __type; }; + + template<> + struct __make_signed + { typedef signed char __type; }; + + template<> + struct __make_signed + { typedef signed char __type; }; + + template<> + struct __make_signed + { typedef signed short __type; }; + + template<> + struct __make_signed + { typedef signed int __type; }; + + template<> + struct __make_signed + { typedef signed long __type; }; + + template<> + struct __make_signed + { typedef signed long long __type; }; + +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> + struct __make_signed + { typedef __GLIBCXX_TYPE_INT_N_0 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> + struct __make_signed + { typedef __GLIBCXX_TYPE_INT_N_1 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> + struct __make_signed + { typedef __GLIBCXX_TYPE_INT_N_2 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + template<> + struct __make_signed + { typedef __GLIBCXX_TYPE_INT_N_3 __type; }; +#endif + + // Select between integral and enum: not possible to be both. + template::value, + bool _IsEnum = is_enum<_Tp>::value> + class __make_signed_selector; + + template + class __make_signed_selector<_Tp, true, false> + { + using __signed_type + = typename __make_signed<__remove_cv_t<_Tp>>::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __signed_type>::__type; + }; + + // Choose signed integer type with the smallest rank and same size as _Tp + template + class __make_signed_selector<_Tp, false, true> + { + typedef typename __make_unsigned_selector<_Tp>::__type __unsigned_type; + + public: + typedef typename __make_signed_selector<__unsigned_type>::__type __type; + }; + + // wchar_t, char16_t and char32_t are integral types but are neither + // signed integer types nor unsigned integer types, so must be + // transformed to the signed integer type with the smallest rank. + // Use the partial specialization for enumeration types to do that. +#if defined(_GLIBCXX_USE_WCHAR_T) + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; +#endif + +#if defined(_GLIBCXX_USE_CHAR8_T) + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; +#endif + + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + + // Given an integral/enum type, return the corresponding signed + // integer type. + // Primary template. + /// make_signed + template + struct make_signed + { typedef typename __make_signed_selector<_Tp>::__type type; }; + + // Integral, but don't define. + template<> + struct make_signed; + +#if __cplusplus > 201103L + /// Alias template for make_signed + template + using make_signed_t = typename make_signed<_Tp>::type; + + /// Alias template for make_unsigned + template + using make_unsigned_t = typename make_unsigned<_Tp>::type; +#endif + + // Array modifications. + + /// remove_extent + template + struct remove_extent + { typedef _Tp type; }; + + template + struct remove_extent<_Tp[_Size]> + { typedef _Tp type; }; + + template + struct remove_extent<_Tp[]> + { typedef _Tp type; }; + + /// remove_all_extents + template + struct remove_all_extents + { typedef _Tp type; }; + + template + struct remove_all_extents<_Tp[_Size]> + { typedef typename remove_all_extents<_Tp>::type type; }; + + template + struct remove_all_extents<_Tp[]> + { typedef typename remove_all_extents<_Tp>::type type; }; + +#if __cplusplus > 201103L + /// Alias template for remove_extent + template + using remove_extent_t = typename remove_extent<_Tp>::type; + + /// Alias template for remove_all_extents + template + using remove_all_extents_t = typename remove_all_extents<_Tp>::type; +#endif + + // Pointer modifications. + + template + struct __remove_pointer_helper + { typedef _Tp type; }; + + template + struct __remove_pointer_helper<_Tp, _Up*> + { typedef _Up type; }; + + /// remove_pointer + template + struct remove_pointer + : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>> + { }; + + /// add_pointer + template, + is_void<_Tp>>::value> + struct __add_pointer_helper + { typedef _Tp type; }; + + template + struct __add_pointer_helper<_Tp, true> + { typedef typename remove_reference<_Tp>::type* type; }; + + template + struct add_pointer + : public __add_pointer_helper<_Tp> + { }; + +#if __cplusplus > 201103L + /// Alias template for remove_pointer + template + using remove_pointer_t = typename remove_pointer<_Tp>::type; + + /// Alias template for add_pointer + template + using add_pointer_t = typename add_pointer<_Tp>::type; +#endif + + template + struct __aligned_storage_msa + { + union __type + { + unsigned char __data[_Len]; + struct __attribute__((__aligned__)) { } __align; + }; + }; + + /** + * @brief Alignment type. + * + * The value of _Align is a default-alignment which shall be the + * most stringent alignment requirement for any C++ object type + * whose size is no greater than _Len (3.9). The member typedef + * type shall be a POD type suitable for use as uninitialized + * storage for any object whose size is at most _Len and whose + * alignment is a divisor of _Align. + */ + template::__type)> + struct aligned_storage + { + union type + { + unsigned char __data[_Len]; + struct __attribute__((__aligned__((_Align)))) { } __align; + }; + }; + + template + struct __strictest_alignment + { + static const size_t _S_alignment = 0; + static const size_t _S_size = 0; + }; + + template + struct __strictest_alignment<_Tp, _Types...> + { + static const size_t _S_alignment = + alignof(_Tp) > __strictest_alignment<_Types...>::_S_alignment + ? alignof(_Tp) : __strictest_alignment<_Types...>::_S_alignment; + static const size_t _S_size = + sizeof(_Tp) > __strictest_alignment<_Types...>::_S_size + ? sizeof(_Tp) : __strictest_alignment<_Types...>::_S_size; + }; + + /** + * @brief Provide aligned storage for types. + * + * [meta.trans.other] + * + * Provides aligned storage for any of the provided types of at + * least size _Len. + * + * @see aligned_storage + */ + template + struct aligned_union + { + private: + static_assert(sizeof...(_Types) != 0, "At least one type is required"); + + using __strictest = __strictest_alignment<_Types...>; + static const size_t _S_len = _Len > __strictest::_S_size + ? _Len : __strictest::_S_size; + public: + /// The value of the strictest alignment of _Types. + static const size_t alignment_value = __strictest::_S_alignment; + /// The storage. + typedef typename aligned_storage<_S_len, alignment_value>::type type; + }; + + template + const size_t aligned_union<_Len, _Types...>::alignment_value; + + // Decay trait for arrays and functions, used for perfect forwarding + // in make_pair, make_tuple, etc. + template::value, + bool _IsFunction = is_function<_Up>::value> + struct __decay_selector; + + // NB: DR 705. + template + struct __decay_selector<_Up, false, false> + { typedef __remove_cv_t<_Up> __type; }; + + template + struct __decay_selector<_Up, true, false> + { typedef typename remove_extent<_Up>::type* __type; }; + + template + struct __decay_selector<_Up, false, true> + { typedef typename add_pointer<_Up>::type __type; }; + + /// decay + template + class decay + { + typedef typename remove_reference<_Tp>::type __remove_type; + + public: + typedef typename __decay_selector<__remove_type>::__type type; + }; + + // __decay_t (std::decay_t for C++11). + template + using __decay_t = typename decay<_Tp>::type; + + template + class reference_wrapper; + + // Helper which adds a reference to a type when given a reference_wrapper + template + struct __strip_reference_wrapper + { + typedef _Tp __type; + }; + + template + struct __strip_reference_wrapper > + { + typedef _Tp& __type; + }; + + template + using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>; + + + // Primary template. + /// Define a member typedef @c type only if a boolean constant is true. + template + struct enable_if + { }; + + // Partial specialization for true. + template + struct enable_if + { typedef _Tp type; }; + + // __enable_if_t (std::enable_if_t for C++11) + template + using __enable_if_t = typename enable_if<_Cond, _Tp>::type; + + template + using _Require = __enable_if_t<__and_<_Cond...>::value>; + + // Primary template. + /// Define a member typedef @c type to one of two argument types. + template + struct conditional + { typedef _Iftrue type; }; + + // Partial specialization for false. + template + struct conditional + { typedef _Iffalse type; }; + + // __remove_cvref_t (std::remove_cvref_t for C++11). + template + using __remove_cvref_t + = typename remove_cv::type>::type; + + /// common_type + template + struct common_type; + + // Sfinae-friendly common_type implementation: + + struct __do_common_type_impl + { + template + using __cond_t + = decltype(true ? std::declval<_Tp>() : std::declval<_Up>()); + + // if decay_t() : declval())> + // denotes a valid type, let C denote that type. + template + static __success_type<__decay_t<__cond_t<_Tp, _Up>>> + _S_test(int); + +#if __cplusplus > 201703L + // Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type, + // let C denote the type decay_t. + template + static __success_type<__remove_cvref_t<__cond_t>> + _S_test_2(int); +#endif + + template + static __failure_type + _S_test_2(...); + + template + static decltype(_S_test_2<_Tp, _Up>(0)) + _S_test(...); + }; + + // If sizeof...(T) is zero, there shall be no member type. + template<> + struct common_type<> + { }; + + // If sizeof...(T) is one, the same type, if any, as common_type_t. + template + struct common_type<_Tp0> + : public common_type<_Tp0, _Tp0> + { }; + + // If sizeof...(T) is two, ... + template, typename _Dp2 = __decay_t<_Tp2>> + struct __common_type_impl + { + // If is_same_v is false or is_same_v is false, + // let C denote the same type, if any, as common_type_t. + using type = common_type<_Dp1, _Dp2>; + }; + + template + struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2> + : private __do_common_type_impl + { + // Otherwise, if decay_t() : declval())> + // denotes a valid type, let C denote that type. + using type = decltype(_S_test<_Tp1, _Tp2>(0)); + }; + + // If sizeof...(T) is two, ... + template + struct common_type<_Tp1, _Tp2> + : public __common_type_impl<_Tp1, _Tp2>::type + { }; + + template + struct __common_type_pack + { }; + + template + struct __common_type_fold; + + // If sizeof...(T) is greater than two, ... + template + struct common_type<_Tp1, _Tp2, _Rp...> + : public __common_type_fold, + __common_type_pack<_Rp...>> + { }; + + // Let C denote the same type, if any, as common_type_t. + // If there is such a type C, type shall denote the same type, if any, + // as common_type_t. + template + struct __common_type_fold<_CTp, __common_type_pack<_Rp...>, + __void_t> + : public common_type + { }; + + // Otherwise, there shall be no member type. + template + struct __common_type_fold<_CTp, _Rp, void> + { }; + + template::value> + struct __underlying_type_impl + { + using type = __underlying_type(_Tp); + }; + + template + struct __underlying_type_impl<_Tp, false> + { }; + + /// The underlying type of an enum. + template + struct underlying_type + : public __underlying_type_impl<_Tp> + { }; + + template + struct __declval_protector + { + static const bool __stop = false; + }; + + template + auto declval() noexcept -> decltype(__declval<_Tp>(0)) + { + static_assert(__declval_protector<_Tp>::__stop, + "declval() must not be used!"); + return __declval<_Tp>(0); + } + + /// result_of + template + class result_of; + + // Sfinae-friendly result_of implementation: + +#define __cpp_lib_result_of_sfinae 201210 + + struct __invoke_memfun_ref { }; + struct __invoke_memfun_deref { }; + struct __invoke_memobj_ref { }; + struct __invoke_memobj_deref { }; + struct __invoke_other { }; + + // Associate a tag type with a specialization of __success_type. + template + struct __result_of_success : __success_type<_Tp> + { using __invoke_type = _Tag; }; + + // [func.require] paragraph 1 bullet 1: + struct __result_of_memfun_ref_impl + { + template + static __result_of_success().*std::declval<_Fp>())(std::declval<_Args>()...) + ), __invoke_memfun_ref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memfun_ref + : private __result_of_memfun_ref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg, _Args...>(0)) type; + }; + + // [func.require] paragraph 1 bullet 2: + struct __result_of_memfun_deref_impl + { + template + static __result_of_success()).*std::declval<_Fp>())(std::declval<_Args>()...) + ), __invoke_memfun_deref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memfun_deref + : private __result_of_memfun_deref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg, _Args...>(0)) type; + }; + + // [func.require] paragraph 1 bullet 3: + struct __result_of_memobj_ref_impl + { + template + static __result_of_success().*std::declval<_Fp>() + ), __invoke_memobj_ref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memobj_ref + : private __result_of_memobj_ref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg>(0)) type; + }; + + // [func.require] paragraph 1 bullet 4: + struct __result_of_memobj_deref_impl + { + template + static __result_of_success()).*std::declval<_Fp>() + ), __invoke_memobj_deref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memobj_deref + : private __result_of_memobj_deref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg>(0)) type; + }; + + template + struct __result_of_memobj; + + template + struct __result_of_memobj<_Res _Class::*, _Arg> + { + typedef __remove_cvref_t<_Arg> _Argval; + typedef _Res _Class::* _MemPtr; + typedef typename conditional<__or_, + is_base_of<_Class, _Argval>>::value, + __result_of_memobj_ref<_MemPtr, _Arg>, + __result_of_memobj_deref<_MemPtr, _Arg> + >::type::type type; + }; + + template + struct __result_of_memfun; + + template + struct __result_of_memfun<_Res _Class::*, _Arg, _Args...> + { + typedef typename remove_reference<_Arg>::type _Argval; + typedef _Res _Class::* _MemPtr; + typedef typename conditional::value, + __result_of_memfun_ref<_MemPtr, _Arg, _Args...>, + __result_of_memfun_deref<_MemPtr, _Arg, _Args...> + >::type::type type; + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2219. INVOKE-ing a pointer to member with a reference_wrapper + // as the object expression + + // Used by result_of, invoke etc. to unwrap a reference_wrapper. + template> + struct __inv_unwrap + { + using type = _Tp; + }; + + template + struct __inv_unwrap<_Tp, reference_wrapper<_Up>> + { + using type = _Up&; + }; + + template + struct __result_of_impl + { + typedef __failure_type type; + }; + + template + struct __result_of_impl + : public __result_of_memobj<__decay_t<_MemPtr>, + typename __inv_unwrap<_Arg>::type> + { }; + + template + struct __result_of_impl + : public __result_of_memfun<__decay_t<_MemPtr>, + typename __inv_unwrap<_Arg>::type, _Args...> + { }; + + // [func.require] paragraph 1 bullet 5: + struct __result_of_other_impl + { + template + static __result_of_success()(std::declval<_Args>()...) + ), __invoke_other> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_impl + : private __result_of_other_impl + { + typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type; + }; + + // __invoke_result (std::invoke_result for C++11) + template + struct __invoke_result + : public __result_of_impl< + is_member_object_pointer< + typename remove_reference<_Functor>::type + >::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type + >::value, + _Functor, _ArgTypes... + >::type + { }; + + template + struct result_of<_Functor(_ArgTypes...)> + : public __invoke_result<_Functor, _ArgTypes...> + { }; + +#if __cplusplus >= 201402L + /// Alias template for aligned_storage + template::__type)> + using aligned_storage_t = typename aligned_storage<_Len, _Align>::type; + + template + using aligned_union_t = typename aligned_union<_Len, _Types...>::type; + + /// Alias template for decay + template + using decay_t = typename decay<_Tp>::type; + + /// Alias template for enable_if + template + using enable_if_t = typename enable_if<_Cond, _Tp>::type; + + /// Alias template for conditional + template + using conditional_t = typename conditional<_Cond, _Iftrue, _Iffalse>::type; + + /// Alias template for common_type + template + using common_type_t = typename common_type<_Tp...>::type; + + /// Alias template for underlying_type + template + using underlying_type_t = typename underlying_type<_Tp>::type; + + /// Alias template for result_of + template + using result_of_t = typename result_of<_Tp>::type; +#endif // C++14 + +#if __cplusplus >= 201703L || !defined(__STRICT_ANSI__) // c++17 or gnu++11 +#define __cpp_lib_void_t 201411 + /// A metafunction that always yields void, used for detecting valid types. + template using void_t = void; +#endif + + /// Implementation of the detection idiom (negative case). + template class _Op, typename... _Args> + struct __detector + { + using value_t = false_type; + using type = _Default; + }; + + /// Implementation of the detection idiom (positive case). + template class _Op, + typename... _Args> + struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...> + { + using value_t = true_type; + using type = _Op<_Args...>; + }; + + // Detect whether _Op<_Args...> is a valid type, use _Default if not. + template class _Op, + typename... _Args> + using __detected_or = __detector<_Default, void, _Op, _Args...>; + + // _Op<_Args...> if that is a valid type, otherwise _Default. + template class _Op, + typename... _Args> + using __detected_or_t + = typename __detected_or<_Default, _Op, _Args...>::type; + + /// @} group metaprogramming + + /** + * Use SFINAE to determine if the type _Tp has a publicly-accessible + * member type _NTYPE. + */ +#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE) \ + template> \ + struct __has_##_NTYPE \ + : false_type \ + { }; \ + template \ + struct __has_##_NTYPE<_Tp, __void_t> \ + : true_type \ + { }; + + template + struct __is_swappable; + + template + struct __is_nothrow_swappable; + + template + class tuple; + + template + struct __is_tuple_like_impl : false_type + { }; + + template + struct __is_tuple_like_impl> : true_type + { }; + + // Internal type trait that allows us to sfinae-protect tuple_cat. + template + struct __is_tuple_like + : public __is_tuple_like_impl<__remove_cvref_t<_Tp>>::type + { }; + + template + _GLIBCXX20_CONSTEXPR + inline + _Require<__not_<__is_tuple_like<_Tp>>, + is_move_constructible<_Tp>, + is_move_assignable<_Tp>> + swap(_Tp&, _Tp&) + noexcept(__and_, + is_nothrow_move_assignable<_Tp>>::value); + + template + _GLIBCXX20_CONSTEXPR + inline + __enable_if_t<__is_swappable<_Tp>::value> + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + noexcept(__is_nothrow_swappable<_Tp>::value); + + namespace __swappable_details { + using std::swap; + + struct __do_is_swappable_impl + { + template(), std::declval<_Tp&>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + struct __do_is_nothrow_swappable_impl + { + template + static __bool_constant< + noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())) + > __test(int); + + template + static false_type __test(...); + }; + + } // namespace __swappable_details + + template + struct __is_swappable_impl + : public __swappable_details::__do_is_swappable_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template + struct __is_nothrow_swappable_impl + : public __swappable_details::__do_is_nothrow_swappable_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template + struct __is_swappable + : public __is_swappable_impl<_Tp>::type + { }; + + template + struct __is_nothrow_swappable + : public __is_nothrow_swappable_impl<_Tp>::type + { }; + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 +#define __cpp_lib_is_swappable 201603 + /// Metafunctions used for detecting swappable types: p0185r1 + + /// is_swappable + template + struct is_swappable + : public __is_swappable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_swappable + template + struct is_nothrow_swappable + : public __is_nothrow_swappable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +#if __cplusplus >= 201402L + /// is_swappable_v + template + _GLIBCXX17_INLINE constexpr bool is_swappable_v = + is_swappable<_Tp>::value; + + /// is_nothrow_swappable_v + template + _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_v = + is_nothrow_swappable<_Tp>::value; +#endif // __cplusplus >= 201402L + + namespace __swappable_with_details { + using std::swap; + + struct __do_is_swappable_with_impl + { + template(), std::declval<_Up>())), + typename + = decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + struct __do_is_nothrow_swappable_with_impl + { + template + static __bool_constant< + noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) + && + noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())) + > __test(int); + + template + static false_type __test(...); + }; + + } // namespace __swappable_with_details + + template + struct __is_swappable_with_impl + : public __swappable_with_details::__do_is_swappable_with_impl + { + typedef decltype(__test<_Tp, _Up>(0)) type; + }; + + // Optimization for the homogenous lvalue case, not required: + template + struct __is_swappable_with_impl<_Tp&, _Tp&> + : public __swappable_details::__do_is_swappable_impl + { + typedef decltype(__test<_Tp&>(0)) type; + }; + + template + struct __is_nothrow_swappable_with_impl + : public __swappable_with_details::__do_is_nothrow_swappable_with_impl + { + typedef decltype(__test<_Tp, _Up>(0)) type; + }; + + // Optimization for the homogenous lvalue case, not required: + template + struct __is_nothrow_swappable_with_impl<_Tp&, _Tp&> + : public __swappable_details::__do_is_nothrow_swappable_impl + { + typedef decltype(__test<_Tp&>(0)) type; + }; + + /// is_swappable_with + template + struct is_swappable_with + : public __is_swappable_with_impl<_Tp, _Up>::type + { }; + + /// is_nothrow_swappable_with + template + struct is_nothrow_swappable_with + : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type + { }; + +#if __cplusplus >= 201402L + /// is_swappable_with_v + template + _GLIBCXX17_INLINE constexpr bool is_swappable_with_v = + is_swappable_with<_Tp, _Up>::value; + + /// is_nothrow_swappable_with_v + template + _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_with_v = + is_nothrow_swappable_with<_Tp, _Up>::value; +#endif // __cplusplus >= 201402L + +#endif// c++1z or gnu++11 + + // __is_invocable (std::is_invocable for C++11) + + // The primary template is used for invalid INVOKE expressions. + template::value, typename = void> + struct __is_invocable_impl : false_type { }; + + // Used for valid INVOKE and INVOKE expressions. + template + struct __is_invocable_impl<_Result, _Ret, + /* is_void<_Ret> = */ true, + __void_t> + : true_type + { }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + // Used for INVOKE expressions to check the implicit conversion to R. + template + struct __is_invocable_impl<_Result, _Ret, + /* is_void<_Ret> = */ false, + __void_t> + { + private: + // The type of the INVOKE expression. + // Unlike declval, this doesn't add_rvalue_reference. + static typename _Result::type _S_get(); + + template + static void _S_conv(_Tp); + + // This overload is viable if INVOKE(f, args...) can convert to _Tp. + template(_S_get()))> + static true_type + _S_test(int); + + template + static false_type + _S_test(...); + + public: + using type = decltype(_S_test<_Ret>(1)); + }; +#pragma GCC diagnostic pop + + template + struct __is_invocable + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type + { }; + + template + constexpr bool __call_is_nt(__invoke_memfun_ref) + { + using _Up = typename __inv_unwrap<_Tp>::type; + return noexcept((std::declval<_Up>().*std::declval<_Fn>())( + std::declval<_Args>()...)); + } + + template + constexpr bool __call_is_nt(__invoke_memfun_deref) + { + return noexcept(((*std::declval<_Tp>()).*std::declval<_Fn>())( + std::declval<_Args>()...)); + } + + template + constexpr bool __call_is_nt(__invoke_memobj_ref) + { + using _Up = typename __inv_unwrap<_Tp>::type; + return noexcept(std::declval<_Up>().*std::declval<_Fn>()); + } + + template + constexpr bool __call_is_nt(__invoke_memobj_deref) + { + return noexcept((*std::declval<_Tp>()).*std::declval<_Fn>()); + } + + template + constexpr bool __call_is_nt(__invoke_other) + { + return noexcept(std::declval<_Fn>()(std::declval<_Args>()...)); + } + + template + struct __call_is_nothrow + : __bool_constant< + std::__call_is_nt<_Fn, _Args...>(typename _Result::__invoke_type{}) + > + { }; + + template + using __call_is_nothrow_ + = __call_is_nothrow<__invoke_result<_Fn, _Args...>, _Fn, _Args...>; + + // __is_nothrow_invocable (std::is_nothrow_invocable for C++11) + template + struct __is_nothrow_invocable + : __and_<__is_invocable<_Fn, _Args...>, + __call_is_nothrow_<_Fn, _Args...>>::type + { }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + struct __nonesuchbase {}; + struct __nonesuch : private __nonesuchbase { + ~__nonesuch() = delete; + __nonesuch(__nonesuch const&) = delete; + void operator=(__nonesuch const&) = delete; + }; +#pragma GCC diagnostic pop + +#if __cplusplus >= 201703L +# define __cpp_lib_is_invocable 201703 + + /// std::invoke_result + template + struct invoke_result + : public __invoke_result<_Functor, _ArgTypes...> + { }; + + /// std::invoke_result_t + template + using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; + + /// std::is_invocable + template + struct is_invocable + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; + + /// std::is_invocable_r + template + struct is_invocable_r + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; + + /// std::is_nothrow_invocable + template + struct is_nothrow_invocable + : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>, + __call_is_nothrow_<_Fn, _ArgTypes...>>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + // This checks that the INVOKE expression is well-formed and that the + // conversion to R does not throw. It does *not* check whether the INVOKE + // expression itself can throw. That is done by __call_is_nothrow_ instead. + template + using __is_nt_invocable_impl + = typename __is_invocable_impl<_Result, _Ret>::__nothrow_conv; + /// @endcond + + /// std::is_nothrow_invocable_r + template + struct is_nothrow_invocable_r + : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>, + __call_is_nothrow_<_Fn, _ArgTypes...>>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + static_assert((std::__is_complete_or_unbounded( + __type_identity<_ArgTypes>{}) && ...), + "each argument type must be a complete class or an unbounded array"); + static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}), + "_Ret must be a complete class or an unbounded array"); + }; + + /// std::is_invocable_v + template + inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; + + /// std::is_nothrow_invocable_v + template + inline constexpr bool is_nothrow_invocable_v + = is_nothrow_invocable<_Fn, _Args...>::value; + + /// std::is_invocable_r_v + template + inline constexpr bool is_invocable_r_v + = is_invocable_r<_Ret, _Fn, _Args...>::value; + + /// std::is_nothrow_invocable_r_v + template + inline constexpr bool is_nothrow_invocable_r_v + = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; +#endif // C++17 + +#if __cplusplus >= 201703L +# define __cpp_lib_type_trait_variable_templates 201510L +template + inline constexpr bool is_void_v = is_void<_Tp>::value; +template + inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value; +template + inline constexpr bool is_integral_v = is_integral<_Tp>::value; +template + inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; +template + inline constexpr bool is_array_v = is_array<_Tp>::value; +template + inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; +template + inline constexpr bool is_lvalue_reference_v = + is_lvalue_reference<_Tp>::value; +template + inline constexpr bool is_rvalue_reference_v = + is_rvalue_reference<_Tp>::value; +template + inline constexpr bool is_member_object_pointer_v = + is_member_object_pointer<_Tp>::value; +template + inline constexpr bool is_member_function_pointer_v = + is_member_function_pointer<_Tp>::value; +template + inline constexpr bool is_enum_v = is_enum<_Tp>::value; +template + inline constexpr bool is_union_v = is_union<_Tp>::value; +template + inline constexpr bool is_class_v = is_class<_Tp>::value; +template + inline constexpr bool is_function_v = is_function<_Tp>::value; +template + inline constexpr bool is_reference_v = is_reference<_Tp>::value; +template + inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; +template + inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value; +template + inline constexpr bool is_object_v = is_object<_Tp>::value; +template + inline constexpr bool is_scalar_v = is_scalar<_Tp>::value; +template + inline constexpr bool is_compound_v = is_compound<_Tp>::value; +template + inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; +template + inline constexpr bool is_const_v = is_const<_Tp>::value; +template + inline constexpr bool is_volatile_v = is_volatile<_Tp>::value; +template + inline constexpr bool is_trivial_v = is_trivial<_Tp>::value; +template + inline constexpr bool is_trivially_copyable_v = + is_trivially_copyable<_Tp>::value; +template + inline constexpr bool is_standard_layout_v = is_standard_layout<_Tp>::value; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +template + _GLIBCXX20_DEPRECATED("use is_standard_layout_v && is_trivial_v instead") + inline constexpr bool is_pod_v = is_pod<_Tp>::value; +#pragma GCC diagnostic pop +template + inline constexpr bool is_literal_type_v = is_literal_type<_Tp>::value; +template + inline constexpr bool is_empty_v = is_empty<_Tp>::value; +template + inline constexpr bool is_polymorphic_v = is_polymorphic<_Tp>::value; +template + inline constexpr bool is_abstract_v = is_abstract<_Tp>::value; +template + inline constexpr bool is_final_v = is_final<_Tp>::value; +template + inline constexpr bool is_signed_v = is_signed<_Tp>::value; +template + inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; +template + inline constexpr bool is_constructible_v = + is_constructible<_Tp, _Args...>::value; +template + inline constexpr bool is_default_constructible_v = + is_default_constructible<_Tp>::value; +template + inline constexpr bool is_copy_constructible_v = + is_copy_constructible<_Tp>::value; +template + inline constexpr bool is_move_constructible_v = + is_move_constructible<_Tp>::value; +template + inline constexpr bool is_assignable_v = is_assignable<_Tp, _Up>::value; +template + inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; +template + inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value; +template + inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; +template + inline constexpr bool is_trivially_constructible_v = + is_trivially_constructible<_Tp, _Args...>::value; +template + inline constexpr bool is_trivially_default_constructible_v = + is_trivially_default_constructible<_Tp>::value; +template + inline constexpr bool is_trivially_copy_constructible_v = + is_trivially_copy_constructible<_Tp>::value; +template + inline constexpr bool is_trivially_move_constructible_v = + is_trivially_move_constructible<_Tp>::value; +template + inline constexpr bool is_trivially_assignable_v = + is_trivially_assignable<_Tp, _Up>::value; +template + inline constexpr bool is_trivially_copy_assignable_v = + is_trivially_copy_assignable<_Tp>::value; +template + inline constexpr bool is_trivially_move_assignable_v = + is_trivially_move_assignable<_Tp>::value; +template + inline constexpr bool is_trivially_destructible_v = + is_trivially_destructible<_Tp>::value; +template + inline constexpr bool is_nothrow_constructible_v = + is_nothrow_constructible<_Tp, _Args...>::value; +template + inline constexpr bool is_nothrow_default_constructible_v = + is_nothrow_default_constructible<_Tp>::value; +template + inline constexpr bool is_nothrow_copy_constructible_v = + is_nothrow_copy_constructible<_Tp>::value; +template + inline constexpr bool is_nothrow_move_constructible_v = + is_nothrow_move_constructible<_Tp>::value; +template + inline constexpr bool is_nothrow_assignable_v = + is_nothrow_assignable<_Tp, _Up>::value; +template + inline constexpr bool is_nothrow_copy_assignable_v = + is_nothrow_copy_assignable<_Tp>::value; +template + inline constexpr bool is_nothrow_move_assignable_v = + is_nothrow_move_assignable<_Tp>::value; +template + inline constexpr bool is_nothrow_destructible_v = + is_nothrow_destructible<_Tp>::value; +template + inline constexpr bool has_virtual_destructor_v = + has_virtual_destructor<_Tp>::value; +template + inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; +template + inline constexpr size_t rank_v = rank<_Tp>::value; +template + inline constexpr size_t extent_v = extent<_Tp, _Idx>::value; +#ifdef _GLIBCXX_BUILTIN_IS_SAME_AS +template + inline constexpr bool is_same_v = _GLIBCXX_BUILTIN_IS_SAME_AS(_Tp, _Up); +#else +template + inline constexpr bool is_same_v = std::is_same<_Tp, _Up>::value; +#endif +template + inline constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value; +template + inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; + +#ifdef _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP +# define __cpp_lib_has_unique_object_representations 201606 + /// has_unique_object_representations + template + struct has_unique_object_representations + : bool_constant<__has_unique_object_representations( + remove_cv_t> + )> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template + inline constexpr bool has_unique_object_representations_v + = has_unique_object_representations<_Tp>::value; +#endif + +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE +# define __cpp_lib_is_aggregate 201703 + /// is_aggregate + template + struct is_aggregate + : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> + { }; + + /// is_aggregate_v + template + inline constexpr bool is_aggregate_v = is_aggregate<_Tp>::value; +#endif +#endif // C++17 + +#if __cplusplus > 201703L +#define __cpp_lib_remove_cvref 201711L + + /// Remove references and cv-qualifiers. + template + struct remove_cvref + { + using type = __remove_cvref_t<_Tp>; + }; + + template + using remove_cvref_t = __remove_cvref_t<_Tp>; + +#define __cpp_lib_type_identity 201806L + /// Identity metafunction. + template + struct type_identity { using type = _Tp; }; + + template + using type_identity_t = typename type_identity<_Tp>::type; + +#define __cpp_lib_unwrap_ref 201811L + + /// Unwrap a reference_wrapper + template + struct unwrap_reference { using type = _Tp; }; + + template + struct unwrap_reference> { using type = _Tp&; }; + + template + using unwrap_reference_t = typename unwrap_reference<_Tp>::type; + + /// Decay type and if it's a reference_wrapper, unwrap it + template + struct unwrap_ref_decay { using type = unwrap_reference_t>; }; + + template + using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; + +#define __cpp_lib_bounded_array_traits 201902L + + /// True for a type that is an array of known bound. + template + struct is_bounded_array + : public __is_array_known_bounds<_Tp> + { }; + + /// True for a type that is an array of unknown bound. + template + struct is_unbounded_array + : public __is_array_unknown_bounds<_Tp> + { }; + + template + inline constexpr bool is_bounded_array_v + = is_bounded_array<_Tp>::value; + + template + inline constexpr bool is_unbounded_array_v + = is_unbounded_array<_Tp>::value; + +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + +#define __cpp_lib_is_constant_evaluated 201811L + + constexpr inline bool + is_constant_evaluated() noexcept + { return __builtin_is_constant_evaluated(); } +#endif + + template + using __copy_cv = typename __match_cv_qualifiers<_From, _To>::__type; + + template + using __cond_res + = decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()()); + + template + struct __common_ref_impl + { }; + + // [meta.trans.other], COMMON-REF(A, B) + template + using __common_ref = typename __common_ref_impl<_Ap, _Bp>::type; + + // If A and B are both lvalue reference types, ... + template + struct __common_ref_impl<_Xp&, _Yp&, + __void_t<__cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>>> + { using type = __cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>; }; + + // let C be remove_reference_t&& + template + using __common_ref_C = remove_reference_t<__common_ref<_Xp&, _Yp&>>&&; + + // If A and B are both rvalue reference types, ... + template + struct __common_ref_impl<_Xp&&, _Yp&&, + _Require>, + is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp>>>> + { using type = __common_ref_C<_Xp, _Yp>; }; + + // let D be COMMON-REF(const X&, Y&) + template + using __common_ref_D = __common_ref; + + // If A is an rvalue reference and B is an lvalue reference, ... + template + struct __common_ref_impl<_Xp&&, _Yp&, + _Require>>> + { using type = __common_ref_D<_Xp, _Yp>; }; + + // If A is an lvalue reference and B is an rvalue reference, ... + template + struct __common_ref_impl<_Xp&, _Yp&&> + : __common_ref_impl<_Yp&&, _Xp&> + { }; + + template class _TQual, template class _UQual> + struct basic_common_reference + { }; + + template + struct __xref + { template using __type = __copy_cv<_Tp, _Up>; }; + + template + struct __xref<_Tp&> + { template using __type = __copy_cv<_Tp, _Up>&; }; + + template + struct __xref<_Tp&&> + { template using __type = __copy_cv<_Tp, _Up>&&; }; + + template + using __basic_common_ref + = typename basic_common_reference, + remove_cvref_t<_Tp2>, + __xref<_Tp1>::template __type, + __xref<_Tp2>::template __type>::type; + + template + struct common_reference; + + template + using common_reference_t = typename common_reference<_Tp...>::type; + + // If sizeof...(T) is zero, there shall be no member type. + template<> + struct common_reference<> + { }; + + // If sizeof...(T) is one ... + template + struct common_reference<_Tp0> + { using type = _Tp0; }; + + template + struct __common_reference_impl + : __common_reference_impl<_Tp1, _Tp2, _Bullet + 1> + { }; + + // If sizeof...(T) is two ... + template + struct common_reference<_Tp1, _Tp2> + : __common_reference_impl<_Tp1, _Tp2> + { }; + + // If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ... + template + struct __common_reference_impl<_Tp1&, _Tp2&, 1, + void_t<__common_ref<_Tp1&, _Tp2&>>> + { using type = __common_ref<_Tp1&, _Tp2&>; }; + + template + struct __common_reference_impl<_Tp1&&, _Tp2&&, 1, + void_t<__common_ref<_Tp1&&, _Tp2&&>>> + { using type = __common_ref<_Tp1&&, _Tp2&&>; }; + + template + struct __common_reference_impl<_Tp1&, _Tp2&&, 1, + void_t<__common_ref<_Tp1&, _Tp2&&>>> + { using type = __common_ref<_Tp1&, _Tp2&&>; }; + + template + struct __common_reference_impl<_Tp1&&, _Tp2&, 1, + void_t<__common_ref<_Tp1&&, _Tp2&>>> + { using type = __common_ref<_Tp1&&, _Tp2&>; }; + + // Otherwise, if basic_common_reference<...>::type is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 2, + void_t<__basic_common_ref<_Tp1, _Tp2>>> + { using type = __basic_common_ref<_Tp1, _Tp2>; }; + + // Otherwise, if COND-RES(T1, T2) is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 3, + void_t<__cond_res<_Tp1, _Tp2>>> + { using type = __cond_res<_Tp1, _Tp2>; }; + + // Otherwise, if common_type_t is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 4, + void_t>> + { using type = common_type_t<_Tp1, _Tp2>; }; + + // Otherwise, there shall be no member type. + template + struct __common_reference_impl<_Tp1, _Tp2, 5, void> + { }; + + // Otherwise, if sizeof...(T) is greater than two, ... + template + struct common_reference<_Tp1, _Tp2, _Rest...> + : __common_type_fold, + __common_type_pack<_Rest...>> + { }; + + // Reuse __common_type_fold for common_reference + template + struct __common_type_fold, + __common_type_pack<_Rest...>, + void_t>> + : public common_reference, _Rest...> + { }; + +#endif // C++2a + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_TYPE_TRAITS diff --git a/resources/sources/avr-libstdcpp/include/unordered_map b/resources/sources/avr-libstdcpp/include/unordered_map new file mode 100644 index 000000000..e05238fe9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/unordered_map @@ -0,0 +1,101 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/unordered_map + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_UNORDERED_MAP +#define _GLIBCXX_UNORDERED_MAP 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include +#include +#include // equal_to, _Identity, _Select1st +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template, + typename _Pred = std::equal_to<_Key>> + using unordered_map + = std::unordered_map<_Key, _Tp, _Hash, _Pred, + polymorphic_allocator>>; + template, + typename _Pred = std::equal_to<_Key>> + using unordered_multimap + = std::unordered_multimap<_Key, _Tp, _Hash, _Pred, + polymorphic_allocator>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template + inline typename unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>::size_type + erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, + _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } + + template + inline typename unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>:: + size_type + erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, + _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif // C++11 + +#endif // _GLIBCXX_UNORDERED_MAP diff --git a/resources/sources/avr-libstdcpp/include/unordered_set b/resources/sources/avr-libstdcpp/include/unordered_set new file mode 100644 index 000000000..6cbd242ff --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/unordered_set @@ -0,0 +1,100 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/unordered_set + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_UNORDERED_SET +#define _GLIBCXX_UNORDERED_SET 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include +#include +#include // equal_to, _Identity, _Select1st +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template, + typename _Pred = std::equal_to<_Key>> + using unordered_set + = std::unordered_set<_Key, _Hash, _Pred, + polymorphic_allocator<_Key>>; + template, + typename _Pred = std::equal_to<_Key>> + using unordered_multiset + = std::unordered_multiset<_Key, _Hash, _Pred, + polymorphic_allocator<_Key>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template + inline typename unordered_set<_Key, _Hash, _CPred, _Alloc>::size_type + erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont, + _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } + + template + inline typename unordered_multiset<_Key, _Hash, _CPred, _Alloc>::size_type + erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont, + _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif // C++11 + +#endif // _GLIBCXX_UNORDERED_SET diff --git a/resources/sources/avr-libstdcpp/include/utility b/resources/sources/avr-libstdcpp/include/utility new file mode 100644 index 000000000..f7533d5a5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/utility @@ -0,0 +1,538 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/utility + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_UTILITY +#define _GLIBCXX_UTILITY 1 + +#pragma GCC system_header + +/** + * @defgroup utilities Utilities + * + * Components deemed generally useful. Includes pair, tuple, + * forward/move helpers, ratio, function object, metaprogramming and + * type traits, time, date, and memory functions. + */ + +#include +#include +#include + +#if __cplusplus >= 201103L + +#include +#include +#include + +#if __cplusplus > 201703L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Finds the size of a given tuple type. + template + struct tuple_size; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2313. tuple_size should always derive from integral_constant + // 2770. tuple_size specialization is not SFINAE compatible + + template::type, + typename = typename enable_if::value>::type, + size_t = tuple_size<_Tp>::value> + using __enable_if_has_tuple_size = _Tp; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + + /// Gives the type of the ith element of a given tuple type. + template + struct tuple_element; + + // Duplicate of C++14's tuple_element_t for internal use in C++11 mode + template + using __tuple_element_t = typename tuple_element<__i, _Tp>::type; + + template + struct tuple_element<__i, const _Tp> + { + typedef typename add_const<__tuple_element_t<__i, _Tp>>::type type; + }; + + template + struct tuple_element<__i, volatile _Tp> + { + typedef typename add_volatile<__tuple_element_t<__i, _Tp>>::type type; + }; + + template + struct tuple_element<__i, const volatile _Tp> + { + typedef typename add_cv<__tuple_element_t<__i, _Tp>>::type type; + }; + +#if __cplusplus >= 201402L +// The standard says this macro and alias template should be in +// but we define them here, to be available when the partial specializations +// of tuple_element> and tuple_element> are defined. +#define __cpp_lib_tuple_element_t 201402L + + template + using tuple_element_t = typename tuple_element<__i, _Tp>::type; +#endif + + // Various functions which give std::pair a tuple-like interface. + + /// Partial specialization for std::pair + template + struct __is_tuple_like_impl> : true_type + { }; + + /// Partial specialization for std::pair + template + struct tuple_size> + : public integral_constant { }; + + /// Partial specialization for std::pair + template + struct tuple_element<0, std::pair<_Tp1, _Tp2>> + { typedef _Tp1 type; }; + + /// Partial specialization for std::pair + template + struct tuple_element<1, std::pair<_Tp1, _Tp2>> + { typedef _Tp2 type; }; + + template + struct __pair_get; + + template<> + struct __pair_get<0> + { + template + static constexpr _Tp1& + __get(std::pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.first; } + + template + static constexpr _Tp1&& + __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<_Tp1>(__pair.first); } + + template + static constexpr const _Tp1& + __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.first; } + + template + static constexpr const _Tp1&& + __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward(__pair.first); } + }; + + template<> + struct __pair_get<1> + { + template + static constexpr _Tp2& + __get(std::pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.second; } + + template + static constexpr _Tp2&& + __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<_Tp2>(__pair.second); } + + template + static constexpr const _Tp2& + __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.second; } + + template + static constexpr const _Tp2&& + __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward(__pair.second); } + }; + + template + constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& + get(std::pair<_Tp1, _Tp2>& __in) noexcept + { return __pair_get<_Int>::__get(__in); } + + template + constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& + get(std::pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__move_get(std::move(__in)); } + + template + constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& + get(const std::pair<_Tp1, _Tp2>& __in) noexcept + { return __pair_get<_Int>::__const_get(__in); } + + template + constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& + get(const std::pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__const_move_get(std::move(__in)); } + +#if __cplusplus >= 201402L + +#define __cpp_lib_tuples_by_type 201304 + + template + constexpr _Tp& + get(pair<_Tp, _Up>& __p) noexcept + { return __p.first; } + + template + constexpr const _Tp& + get(const pair<_Tp, _Up>& __p) noexcept + { return __p.first; } + + template + constexpr _Tp&& + get(pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template + constexpr const _Tp&& + get(const pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template + constexpr _Tp& + get(pair<_Up, _Tp>& __p) noexcept + { return __p.second; } + + template + constexpr const _Tp& + get(const pair<_Up, _Tp>& __p) noexcept + { return __p.second; } + + template + constexpr _Tp&& + get(pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } + + template + constexpr const _Tp&& + get(const pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } + +#define __cpp_lib_exchange_function 201304 + + /// Assign @p __new_val to @p __obj and return its previous value. + template + _GLIBCXX20_CONSTEXPR + inline _Tp + exchange(_Tp& __obj, _Up&& __new_val) + { return std::__exchange(__obj, std::forward<_Up>(__new_val)); } + +#endif // C++14 + + // Stores a tuple of indices. Used by tuple and pair, and by bind() to + // extract the elements in a tuple. + template struct _Index_tuple { }; + +#if __GNUC__ >= 8 + +#ifdef __has_builtin +# if __has_builtin(__make_integer_seq) +# define _GLIBCXX_USE_MAKE_INTEGER_SEQ 1 +# endif +#endif + + // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. + template + struct _Build_index_tuple + { +#if _GLIBCXX_USE_MAKE_INTEGER_SEQ + template + using _IdxTuple = _Index_tuple<_Indices...>; + + using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; +#else + using __type = _Index_tuple<__integer_pack(_Num)...>; +#endif + }; +#else // __GNUC__ < 8 + // Concatenates two _Index_tuples. + template struct _Itup_cat; + + template + struct _Itup_cat<_Index_tuple<_Ind1...>, _Index_tuple<_Ind2...>> + { + using __type = _Index_tuple<_Ind1..., (_Ind2 + sizeof...(_Ind1))...>; + }; + + // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. + template + struct _Build_index_tuple + : _Itup_cat::__type, + typename _Build_index_tuple<_Num - _Num / 2>::__type> + { }; + + template<> + struct _Build_index_tuple<1> + { + typedef _Index_tuple<0> __type; + }; + + template<> + struct _Build_index_tuple<0> + { + typedef _Index_tuple<> __type; + }; +#endif // __GNUC__ < 8 + +#if __cplusplus > 201103L + +#define __cpp_lib_integer_sequence 201304 + +#if __GNUC__ >= 8 + /// Class template integer_sequence + template + struct integer_sequence + { + typedef _Tp value_type; + static constexpr size_t size() noexcept { return sizeof...(_Idx); } + }; + + /// Alias template make_integer_sequence + template + using make_integer_sequence +#if _GLIBCXX_USE_MAKE_INTEGER_SEQ + = __make_integer_seq; +#else + = integer_sequence<_Tp, __integer_pack(_Num)...>; +#endif + +#undef _GLIBCXX_USE_MAKE_INTEGER_SEQ + +#else // __GNUC__ < 8 + /// Class template integer_sequence + template + struct integer_sequence + { + typedef _Tp value_type; + static constexpr size_t size() { return sizeof...(_Idx); } + }; + + template::__type> + struct _Make_integer_sequence; + + template + struct _Make_integer_sequence<_Tp, _Num, _Index_tuple<_Idx...>> + { + static_assert( _Num >= 0, + "Cannot make integer sequence of negative length" ); + + typedef integer_sequence<_Tp, static_cast<_Tp>(_Idx)...> __type; + }; + + /// Alias template make_integer_sequence + template + using make_integer_sequence + = typename _Make_integer_sequence<_Tp, _Num>::__type; +#endif // __GNUC__ < 8 + + /// Alias template index_sequence + template + using index_sequence = integer_sequence; + + /// Alias template make_index_sequence + template + using make_index_sequence = make_integer_sequence; + + /// Alias template index_sequence_for + template + using index_sequence_for = make_index_sequence; +#endif + +#if __cplusplus > 201402L + + struct in_place_t { + explicit in_place_t() = default; + }; + + inline constexpr in_place_t in_place{}; + + template struct in_place_type_t + { + explicit in_place_type_t() = default; + }; + + template + inline constexpr in_place_type_t<_Tp> in_place_type{}; + + template struct in_place_index_t + { + explicit in_place_index_t() = default; + }; + + template + inline constexpr in_place_index_t<_Idx> in_place_index{}; + + template + struct __is_in_place_type_impl : false_type + { }; + + template + struct __is_in_place_type_impl> : true_type + { }; + + template + struct __is_in_place_type + : public __is_in_place_type_impl<_Tp> + { }; + +#define __cpp_lib_as_const 201510 + template + constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; } + + template + void as_const(const _Tp&&) = delete; + +#if __cplusplus > 201703L +#define __cpp_lib_integer_comparison_functions 202002L + + template + constexpr bool + cmp_equal(_Tp __t, _Up __u) noexcept + { + static_assert(__is_standard_integer<_Tp>::value); + static_assert(__is_standard_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t == __u; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; + else + return __u >= 0 && __t == make_unsigned_t<_Up>(__u); + } + + template + constexpr bool + cmp_not_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_equal(__t, __u); } + + template + constexpr bool + cmp_less(_Tp __t, _Up __u) noexcept + { + static_assert(__is_standard_integer<_Tp>::value); + static_assert(__is_standard_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t < __u; + else if constexpr (is_signed_v<_Tp>) + return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; + else + return __u >= 0 && __t < make_unsigned_t<_Up>(__u); + } + + template + constexpr bool + cmp_greater(_Tp __t, _Up __u) noexcept + { return std::cmp_less(__u, __t); } + + template + constexpr bool + cmp_less_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__u, __t); } + + template + constexpr bool + cmp_greater_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__t, __u); } + + template + constexpr bool + in_range(_Tp __t) noexcept + { + static_assert(__is_standard_integer<_Up>::value); + static_assert(__is_standard_integer<_Tp>::value); + using __gnu_cxx::__int_traits; + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __int_traits<_Up>::__min <= __t + && __t <= __int_traits<_Up>::__max; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 + && make_unsigned_t<_Tp>(__t) <= __int_traits<_Up>::__max; + else + return __t <= make_unsigned_t<_Up>(__int_traits<_Up>::__max); + } +#endif // C++20 +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + +#endif /* _GLIBCXX_UTILITY */ diff --git a/resources/sources/avr-libstdcpp/include/valarray b/resources/sources/avr-libstdcpp/include/valarray new file mode 100644 index 000000000..be2e70dc0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/valarray @@ -0,0 +1,1253 @@ +// The template and inlines for the -*- C++ -*- valarray class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/valarray + * This is a Standard C++ Library header. + */ + +// Written by Gabriel Dos Reis + +#ifndef _GLIBCXX_VALARRAY +#define _GLIBCXX_VALARRAY 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + class _Expr; + + template + class _ValArray; + +namespace __detail +{ + template class _Meta, class _Dom> + struct _UnClos; + + template class _Meta1, + template class _Meta2, + class _Dom1, class _Dom2> + class _BinClos; + + template class _Meta, class _Dom> + class _SClos; + + template class _Meta, class _Dom> + class _GClos; + + template class _Meta, class _Dom> + class _IClos; + + template class _Meta, class _Dom> + class _ValFunClos; + + template class _Meta, class _Dom> + class _RefFunClos; +} // namespace __detail + + using __detail::_UnClos; + using __detail::_BinClos; + using __detail::_SClos; + using __detail::_GClos; + using __detail::_IClos; + using __detail::_ValFunClos; + using __detail::_RefFunClos; + + template class valarray; // An array of type _Tp + class slice; // BLAS-like slice out of an array + template class slice_array; + class gslice; // generalized slice out of an array + template class gslice_array; + template class mask_array; // masked array + template class indirect_array; // indirected array + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup numeric_arrays Numeric Arrays + * @ingroup numerics + * + * Classes and functions for representing and manipulating arrays of elements. + * @{ + */ + + /** + * @brief Smart array designed to support numeric processing. + * + * A valarray is an array that provides constraints intended to allow for + * effective optimization of numeric array processing by reducing the + * aliasing that can result from pointer representations. It represents a + * one-dimensional array from which different multidimensional subsets can + * be accessed and modified. + * + * @tparam _Tp Type of object in the array. + */ + template + class valarray + { + template + struct _UnaryOp + { + typedef typename __fun<_Op, _Tp>::result_type __rt; + typedef _Expr<_UnClos<_Op, _ValArray, _Tp>, __rt> _Rt; + }; + public: + typedef _Tp value_type; + + // _lib.valarray.cons_ construct/destroy: + /// Construct an empty array. + valarray(); + + /// Construct an array with @a n elements. + explicit valarray(size_t); + + /// Construct an array with @a n elements initialized to @a t. + valarray(const _Tp&, size_t); + + /// Construct an array initialized to the first @a n elements of @a t. + valarray(const _Tp* __restrict__, size_t); + + /// Copy constructor. + valarray(const valarray&); + +#if __cplusplus >= 201103L + /// Move constructor. + valarray(valarray&&) noexcept; +#endif + + /// Construct an array with the same size and values in @a sa. + valarray(const slice_array<_Tp>&); + + /// Construct an array with the same size and values in @a ga. + valarray(const gslice_array<_Tp>&); + + /// Construct an array with the same size and values in @a ma. + valarray(const mask_array<_Tp>&); + + /// Construct an array with the same size and values in @a ia. + valarray(const indirect_array<_Tp>&); + +#if __cplusplus >= 201103L + /// Construct an array with an initializer_list of values. + valarray(initializer_list<_Tp>); +#endif + + template + valarray(const _Expr<_Dom, _Tp>& __e); + + ~valarray() _GLIBCXX_NOEXCEPT; + + // _lib.valarray.assign_ assignment: + /** + * @brief Assign elements to an array. + * + * Assign elements of array to values in @a v. + * + * @param __v Valarray to get values from. + */ + valarray<_Tp>& operator=(const valarray<_Tp>& __v); + +#if __cplusplus >= 201103L + /** + * @brief Move assign elements to an array. + * + * Move assign elements of array to values in @a v. + * + * @param __v Valarray to get values from. + */ + valarray<_Tp>& operator=(valarray<_Tp>&& __v) noexcept; +#endif + + /** + * @brief Assign elements to a value. + * + * Assign all elements of array to @a t. + * + * @param __t Value for elements. + */ + valarray<_Tp>& operator=(const _Tp& __t); + + /** + * @brief Assign elements to an array subset. + * + * Assign elements of array to values in @a sa. Results are undefined + * if @a sa does not have the same size as this array. + * + * @param __sa Array slice to get values from. + */ + valarray<_Tp>& operator=(const slice_array<_Tp>& __sa); + + /** + * @brief Assign elements to an array subset. + * + * Assign elements of array to values in @a ga. Results are undefined + * if @a ga does not have the same size as this array. + * + * @param __ga Array slice to get values from. + */ + valarray<_Tp>& operator=(const gslice_array<_Tp>& __ga); + + /** + * @brief Assign elements to an array subset. + * + * Assign elements of array to values in @a ma. Results are undefined + * if @a ma does not have the same size as this array. + * + * @param __ma Array slice to get values from. + */ + valarray<_Tp>& operator=(const mask_array<_Tp>& __ma); + + /** + * @brief Assign elements to an array subset. + * + * Assign elements of array to values in @a ia. Results are undefined + * if @a ia does not have the same size as this array. + * + * @param __ia Array slice to get values from. + */ + valarray<_Tp>& operator=(const indirect_array<_Tp>& __ia); + +#if __cplusplus >= 201103L + /** + * @brief Assign elements to an initializer_list. + * + * Assign elements of array to values in @a __l. Results are undefined + * if @a __l does not have the same size as this array. + * + * @param __l initializer_list to get values from. + */ + valarray& operator=(initializer_list<_Tp> __l); +#endif + + template valarray<_Tp>& + operator= (const _Expr<_Dom, _Tp>&); + + // _lib.valarray.access_ element access: + /** + * Return a reference to the i'th array element. + * + * @param __i Index of element to return. + * @return Reference to the i'th element. + */ + _Tp& operator[](size_t __i); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 389. Const overload of valarray::operator[] returns by value. + const _Tp& operator[](size_t) const; + + // _lib.valarray.sub_ subset operations: + /** + * @brief Return an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the slice argument. The new valarray has the same size + * as the input slice. @see slice. + * + * @param __s The source slice. + * @return New valarray containing elements in @a __s. + */ + _Expr<_SClos<_ValArray, _Tp>, _Tp> operator[](slice __s) const; + + /** + * @brief Return a reference to an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the slice argument. The new valarray has the same size + * as the input slice. @see slice. + * + * @param __s The source slice. + * @return New valarray containing elements in @a __s. + */ + slice_array<_Tp> operator[](slice __s); + + /** + * @brief Return an array subset. + * + * Returns a slice_array referencing the elements of the array + * indicated by the slice argument. @see gslice. + * + * @param __s The source slice. + * @return Slice_array referencing elements indicated by @a __s. + */ + _Expr<_GClos<_ValArray, _Tp>, _Tp> operator[](const gslice& __s) const; + + /** + * @brief Return a reference to an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the gslice argument. The new valarray has + * the same size as the input gslice. @see gslice. + * + * @param __s The source gslice. + * @return New valarray containing elements in @a __s. + */ + gslice_array<_Tp> operator[](const gslice& __s); + + /** + * @brief Return an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the argument. The input is a valarray of bool which + * represents a bitmask indicating which elements should be copied into + * the new valarray. Each element of the array is added to the return + * valarray if the corresponding element of the argument is true. + * + * @param __m The valarray bitmask. + * @return New valarray containing elements indicated by @a __m. + */ + valarray<_Tp> operator[](const valarray& __m) const; + + /** + * @brief Return a reference to an array subset. + * + * Returns a new mask_array referencing the elements of the array + * indicated by the argument. The input is a valarray of bool which + * represents a bitmask indicating which elements are part of the + * subset. Elements of the array are part of the subset if the + * corresponding element of the argument is true. + * + * @param __m The valarray bitmask. + * @return New valarray containing elements indicated by @a __m. + */ + mask_array<_Tp> operator[](const valarray& __m); + + /** + * @brief Return an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the argument. The elements in the argument are + * interpreted as the indices of elements of this valarray to copy to + * the return valarray. + * + * @param __i The valarray element index list. + * @return New valarray containing elements in @a __s. + */ + _Expr<_IClos<_ValArray, _Tp>, _Tp> + operator[](const valarray& __i) const; + + /** + * @brief Return a reference to an array subset. + * + * Returns an indirect_array referencing the elements of the array + * indicated by the argument. The elements in the argument are + * interpreted as the indices of elements of this valarray to include + * in the subset. The returned indirect_array refers to these + * elements. + * + * @param __i The valarray element index list. + * @return Indirect_array referencing elements in @a __i. + */ + indirect_array<_Tp> operator[](const valarray& __i); + + // _lib.valarray.unary_ unary operators: + /// Return a new valarray by applying unary + to each element. + typename _UnaryOp<__unary_plus>::_Rt operator+() const; + + /// Return a new valarray by applying unary - to each element. + typename _UnaryOp<__negate>::_Rt operator-() const; + + /// Return a new valarray by applying unary ~ to each element. + typename _UnaryOp<__bitwise_not>::_Rt operator~() const; + + /// Return a new valarray by applying unary ! to each element. + typename _UnaryOp<__logical_not>::_Rt operator!() const; + + // _lib.valarray.cassign_ computed assignment: + /// Multiply each element of array by @a t. + valarray<_Tp>& operator*=(const _Tp&); + + /// Divide each element of array by @a t. + valarray<_Tp>& operator/=(const _Tp&); + + /// Set each element e of array to e % @a t. + valarray<_Tp>& operator%=(const _Tp&); + + /// Add @a t to each element of array. + valarray<_Tp>& operator+=(const _Tp&); + + /// Subtract @a t to each element of array. + valarray<_Tp>& operator-=(const _Tp&); + + /// Set each element e of array to e ^ @a t. + valarray<_Tp>& operator^=(const _Tp&); + + /// Set each element e of array to e & @a t. + valarray<_Tp>& operator&=(const _Tp&); + + /// Set each element e of array to e | @a t. + valarray<_Tp>& operator|=(const _Tp&); + + /// Left shift each element e of array by @a t bits. + valarray<_Tp>& operator<<=(const _Tp&); + + /// Right shift each element e of array by @a t bits. + valarray<_Tp>& operator>>=(const _Tp&); + + /// Multiply elements of array by corresponding elements of @a v. + valarray<_Tp>& operator*=(const valarray<_Tp>&); + + /// Divide elements of array by corresponding elements of @a v. + valarray<_Tp>& operator/=(const valarray<_Tp>&); + + /// Modulo elements of array by corresponding elements of @a v. + valarray<_Tp>& operator%=(const valarray<_Tp>&); + + /// Add corresponding elements of @a v to elements of array. + valarray<_Tp>& operator+=(const valarray<_Tp>&); + + /// Subtract corresponding elements of @a v from elements of array. + valarray<_Tp>& operator-=(const valarray<_Tp>&); + + /// Logical xor corresponding elements of @a v with elements of array. + valarray<_Tp>& operator^=(const valarray<_Tp>&); + + /// Logical or corresponding elements of @a v with elements of array. + valarray<_Tp>& operator|=(const valarray<_Tp>&); + + /// Logical and corresponding elements of @a v with elements of array. + valarray<_Tp>& operator&=(const valarray<_Tp>&); + + /// Left shift elements of array by corresponding elements of @a v. + valarray<_Tp>& operator<<=(const valarray<_Tp>&); + + /// Right shift elements of array by corresponding elements of @a v. + valarray<_Tp>& operator>>=(const valarray<_Tp>&); + + template + valarray<_Tp>& operator*=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator/=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator%=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator+=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator-=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator^=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator|=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator&=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator<<=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator>>=(const _Expr<_Dom, _Tp>&); + + // _lib.valarray.members_ member functions: +#if __cplusplus >= 201103L + /// Swap. + void swap(valarray<_Tp>& __v) noexcept; +#endif + + /// Return the number of elements in array. + size_t size() const; + + /** + * @brief Return the sum of all elements in the array. + * + * Accumulates the sum of all elements into a Tp using +=. The order + * of adding the elements is unspecified. + */ + _Tp sum() const; + + /// Return the minimum element using operator<(). + _Tp min() const; + + /// Return the maximum element using operator<(). + _Tp max() const; + + /** + * @brief Return a shifted array. + * + * A new valarray is constructed as a copy of this array with elements + * in shifted positions. For an element with index i, the new position + * is i - n. The new valarray has the same size as the current one. + * New elements without a value are set to 0. Elements whose new + * position is outside the bounds of the array are discarded. + * + * Positive arguments shift toward index 0, discarding elements [0, n). + * Negative arguments discard elements from the top of the array. + * + * @param __n Number of element positions to shift. + * @return New valarray with elements in shifted positions. + */ + valarray<_Tp> shift (int __n) const; + + /** + * @brief Return a rotated array. + * + * A new valarray is constructed as a copy of this array with elements + * in shifted positions. For an element with index i, the new position + * is (i - n) % size(). The new valarray has the same size as the + * current one. Elements that are shifted beyond the array bounds are + * shifted into the other end of the array. No elements are lost. + * + * Positive arguments shift toward index 0, wrapping around the top. + * Negative arguments shift towards the top, wrapping around to 0. + * + * @param __n Number of element positions to rotate. + * @return New valarray with elements in shifted positions. + */ + valarray<_Tp> cshift(int __n) const; + + /** + * @brief Apply a function to the array. + * + * Returns a new valarray with elements assigned to the result of + * applying func to the corresponding element of this array. The new + * array has the same size as this one. + * + * @param func Function of Tp returning Tp to apply. + * @return New valarray with transformed elements. + */ + _Expr<_ValFunClos<_ValArray, _Tp>, _Tp> apply(_Tp func(_Tp)) const; + + /** + * @brief Apply a function to the array. + * + * Returns a new valarray with elements assigned to the result of + * applying func to the corresponding element of this array. The new + * array has the same size as this one. + * + * @param func Function of const Tp& returning Tp to apply. + * @return New valarray with transformed elements. + */ + _Expr<_RefFunClos<_ValArray, _Tp>, _Tp> apply(_Tp func(const _Tp&)) const; + + /** + * @brief Resize array. + * + * Resize this array to @a size and set all elements to @a c. All + * references and iterators are invalidated. + * + * @param __size New array size. + * @param __c New value for all elements. + */ + void resize(size_t __size, _Tp __c = _Tp()); + + private: + size_t _M_size; + _Tp* __restrict__ _M_data; + + friend class _Array<_Tp>; + }; + +#if __cpp_deduction_guides >= 201606 + template + valarray(const _Tp(&)[_Nm], size_t) -> valarray<_Tp>; +#endif + + template + inline const _Tp& + valarray<_Tp>::operator[](size_t __i) const + { + __glibcxx_requires_subscript(__i); + return _M_data[__i]; + } + + template + inline _Tp& + valarray<_Tp>::operator[](size_t __i) + { + __glibcxx_requires_subscript(__i); + return _M_data[__i]; + } + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#include +#include +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + template + inline + valarray<_Tp>::valarray() : _M_size(0), _M_data(0) {} + + template + inline + valarray<_Tp>::valarray(size_t __n) + : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) + { std::__valarray_default_construct(_M_data, _M_data + __n); } + + template + inline + valarray<_Tp>::valarray(const _Tp& __t, size_t __n) + : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) + { std::__valarray_fill_construct(_M_data, _M_data + __n, __t); } + + template + inline + valarray<_Tp>::valarray(const _Tp* __restrict__ __p, size_t __n) + : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) + { + __glibcxx_assert(__p != 0 || __n == 0); + std::__valarray_copy_construct(__p, __p + __n, _M_data); + } + + template + inline + valarray<_Tp>::valarray(const valarray<_Tp>& __v) + : _M_size(__v._M_size), _M_data(__valarray_get_storage<_Tp>(__v._M_size)) + { std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size, + _M_data); } + +#if __cplusplus >= 201103L + template + inline + valarray<_Tp>::valarray(valarray<_Tp>&& __v) noexcept + : _M_size(__v._M_size), _M_data(__v._M_data) + { + __v._M_size = 0; + __v._M_data = 0; + } +#endif + + template + inline + valarray<_Tp>::valarray(const slice_array<_Tp>& __sa) + : _M_size(__sa._M_sz), _M_data(__valarray_get_storage<_Tp>(__sa._M_sz)) + { + std::__valarray_copy_construct + (__sa._M_array, __sa._M_sz, __sa._M_stride, _Array<_Tp>(_M_data)); + } + + template + inline + valarray<_Tp>::valarray(const gslice_array<_Tp>& __ga) + : _M_size(__ga._M_index.size()), + _M_data(__valarray_get_storage<_Tp>(_M_size)) + { + std::__valarray_copy_construct + (__ga._M_array, _Array(__ga._M_index), + _Array<_Tp>(_M_data), _M_size); + } + + template + inline + valarray<_Tp>::valarray(const mask_array<_Tp>& __ma) + : _M_size(__ma._M_sz), _M_data(__valarray_get_storage<_Tp>(__ma._M_sz)) + { + std::__valarray_copy_construct + (__ma._M_array, __ma._M_mask, _Array<_Tp>(_M_data), _M_size); + } + + template + inline + valarray<_Tp>::valarray(const indirect_array<_Tp>& __ia) + : _M_size(__ia._M_sz), _M_data(__valarray_get_storage<_Tp>(__ia._M_sz)) + { + std::__valarray_copy_construct + (__ia._M_array, __ia._M_index, _Array<_Tp>(_M_data), _M_size); + } + +#if __cplusplus >= 201103L + template + inline + valarray<_Tp>::valarray(initializer_list<_Tp> __l) + : _M_size(__l.size()), _M_data(__valarray_get_storage<_Tp>(__l.size())) + { std::__valarray_copy_construct(__l.begin(), __l.end(), _M_data); } +#endif + + template template + inline + valarray<_Tp>::valarray(const _Expr<_Dom, _Tp>& __e) + : _M_size(__e.size()), _M_data(__valarray_get_storage<_Tp>(_M_size)) + { std::__valarray_copy_construct(__e, _M_size, _Array<_Tp>(_M_data)); } + + template + inline + valarray<_Tp>::~valarray() _GLIBCXX_NOEXCEPT + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const valarray<_Tp>& __v) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 630. arrays of valarray. + if (_M_size == __v._M_size) + std::__valarray_copy(__v._M_data, _M_size, _M_data); + else + { + if (_M_data) + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + _M_size = __v._M_size; + _M_data = __valarray_get_storage<_Tp>(_M_size); + std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size, + _M_data); + } + return *this; + } + +#if __cplusplus >= 201103L + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(valarray<_Tp>&& __v) noexcept + { + if (_M_data) + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + _M_size = __v._M_size; + _M_data = __v._M_data; + __v._M_size = 0; + __v._M_data = 0; + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(initializer_list<_Tp> __l) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 630. arrays of valarray. + if (_M_size == __l.size()) + std::__valarray_copy(__l.begin(), __l.size(), _M_data); + else + { + if (_M_data) + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + _M_size = __l.size(); + _M_data = __valarray_get_storage<_Tp>(_M_size); + std::__valarray_copy_construct(__l.begin(), __l.begin() + _M_size, + _M_data); + } + return *this; + } +#endif + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const _Tp& __t) + { + std::__valarray_fill(_M_data, _M_size, __t); + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const slice_array<_Tp>& __sa) + { + __glibcxx_assert(_M_size == __sa._M_sz); + std::__valarray_copy(__sa._M_array, __sa._M_sz, + __sa._M_stride, _Array<_Tp>(_M_data)); + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const gslice_array<_Tp>& __ga) + { + __glibcxx_assert(_M_size == __ga._M_index.size()); + std::__valarray_copy(__ga._M_array, _Array(__ga._M_index), + _Array<_Tp>(_M_data), _M_size); + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const mask_array<_Tp>& __ma) + { + __glibcxx_assert(_M_size == __ma._M_sz); + std::__valarray_copy(__ma._M_array, __ma._M_mask, + _Array<_Tp>(_M_data), _M_size); + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const indirect_array<_Tp>& __ia) + { + __glibcxx_assert(_M_size == __ia._M_sz); + std::__valarray_copy(__ia._M_array, __ia._M_index, + _Array<_Tp>(_M_data), _M_size); + return *this; + } + + template template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 630. arrays of valarray. + if (_M_size == __e.size()) + std::__valarray_copy(__e, _M_size, _Array<_Tp>(_M_data)); + else + { + if (_M_data) + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + _M_size = __e.size(); + _M_data = __valarray_get_storage<_Tp>(_M_size); + std::__valarray_copy_construct(__e, _M_size, _Array<_Tp>(_M_data)); + } + return *this; + } + + template + inline _Expr<_SClos<_ValArray,_Tp>, _Tp> + valarray<_Tp>::operator[](slice __s) const + { + typedef _SClos<_ValArray,_Tp> _Closure; + return _Expr<_Closure, _Tp>(_Closure (_Array<_Tp>(_M_data), __s)); + } + + template + inline slice_array<_Tp> + valarray<_Tp>::operator[](slice __s) + { return slice_array<_Tp>(_Array<_Tp>(_M_data), __s); } + + template + inline _Expr<_GClos<_ValArray,_Tp>, _Tp> + valarray<_Tp>::operator[](const gslice& __gs) const + { + typedef _GClos<_ValArray,_Tp> _Closure; + return _Expr<_Closure, _Tp> + (_Closure(_Array<_Tp>(_M_data), __gs._M_index->_M_index)); + } + + template + inline gslice_array<_Tp> + valarray<_Tp>::operator[](const gslice& __gs) + { + return gslice_array<_Tp> + (_Array<_Tp>(_M_data), __gs._M_index->_M_index); + } + + template + inline valarray<_Tp> + valarray<_Tp>::operator[](const valarray& __m) const + { + size_t __s = 0; + size_t __e = __m.size(); + for (size_t __i=0; __i<__e; ++__i) + if (__m[__i]) ++__s; + return valarray<_Tp>(mask_array<_Tp>(_Array<_Tp>(_M_data), __s, + _Array (__m))); + } + + template + inline mask_array<_Tp> + valarray<_Tp>::operator[](const valarray& __m) + { + size_t __s = 0; + size_t __e = __m.size(); + for (size_t __i=0; __i<__e; ++__i) + if (__m[__i]) ++__s; + return mask_array<_Tp>(_Array<_Tp>(_M_data), __s, _Array(__m)); + } + + template + inline _Expr<_IClos<_ValArray,_Tp>, _Tp> + valarray<_Tp>::operator[](const valarray& __i) const + { + typedef _IClos<_ValArray,_Tp> _Closure; + return _Expr<_Closure, _Tp>(_Closure(*this, __i)); + } + + template + inline indirect_array<_Tp> + valarray<_Tp>::operator[](const valarray& __i) + { + return indirect_array<_Tp>(_Array<_Tp>(_M_data), __i.size(), + _Array(__i)); + } + +#if __cplusplus >= 201103L + template + inline void + valarray<_Tp>::swap(valarray<_Tp>& __v) noexcept + { + std::swap(_M_size, __v._M_size); + std::swap(_M_data, __v._M_data); + } +#endif + + template + inline size_t + valarray<_Tp>::size() const + { return _M_size; } + + template + inline _Tp + valarray<_Tp>::sum() const + { + __glibcxx_assert(_M_size > 0); + return std::__valarray_sum(_M_data, _M_data + _M_size); + } + + template + inline valarray<_Tp> + valarray<_Tp>::shift(int __n) const + { + valarray<_Tp> __ret; + + if (_M_size == 0) + return __ret; + + _Tp* __restrict__ __tmp_M_data = + std::__valarray_get_storage<_Tp>(_M_size); + + if (__n == 0) + std::__valarray_copy_construct(_M_data, + _M_data + _M_size, __tmp_M_data); + else if (__n > 0) // shift left + { + if (size_t(__n) > _M_size) + __n = int(_M_size); + + std::__valarray_copy_construct(_M_data + __n, + _M_data + _M_size, __tmp_M_data); + std::__valarray_default_construct(__tmp_M_data + _M_size - __n, + __tmp_M_data + _M_size); + } + else // shift right + { + if (-size_t(__n) > _M_size) + __n = -int(_M_size); + + std::__valarray_copy_construct(_M_data, _M_data + _M_size + __n, + __tmp_M_data - __n); + std::__valarray_default_construct(__tmp_M_data, + __tmp_M_data - __n); + } + + __ret._M_size = _M_size; + __ret._M_data = __tmp_M_data; + return __ret; + } + + template + inline valarray<_Tp> + valarray<_Tp>::cshift(int __n) const + { + valarray<_Tp> __ret; + + if (_M_size == 0) + return __ret; + + _Tp* __restrict__ __tmp_M_data = + std::__valarray_get_storage<_Tp>(_M_size); + + if (__n == 0) + std::__valarray_copy_construct(_M_data, + _M_data + _M_size, __tmp_M_data); + else if (__n > 0) // cshift left + { + if (size_t(__n) > _M_size) + __n = int(__n % _M_size); + + std::__valarray_copy_construct(_M_data, _M_data + __n, + __tmp_M_data + _M_size - __n); + std::__valarray_copy_construct(_M_data + __n, _M_data + _M_size, + __tmp_M_data); + } + else // cshift right + { + if (-size_t(__n) > _M_size) + __n = -int(-size_t(__n) % _M_size); + + std::__valarray_copy_construct(_M_data + _M_size + __n, + _M_data + _M_size, __tmp_M_data); + std::__valarray_copy_construct(_M_data, _M_data + _M_size + __n, + __tmp_M_data - __n); + } + + __ret._M_size = _M_size; + __ret._M_data = __tmp_M_data; + return __ret; + } + + template + inline void + valarray<_Tp>::resize(size_t __n, _Tp __c) + { + // This complication is so to make valarray > work + // even though it is not required by the standard. Nobody should + // be saying valarray > anyway. See the specs. + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + if (_M_size != __n) + { + std::__valarray_release_memory(_M_data); + _M_size = __n; + _M_data = __valarray_get_storage<_Tp>(__n); + } + std::__valarray_fill_construct(_M_data, _M_data + __n, __c); + } + + template + inline _Tp + valarray<_Tp>::min() const + { + __glibcxx_assert(_M_size > 0); + return *std::min_element(_M_data, _M_data + _M_size); + } + + template + inline _Tp + valarray<_Tp>::max() const + { + __glibcxx_assert(_M_size > 0); + return *std::max_element(_M_data, _M_data + _M_size); + } + + template + inline _Expr<_ValFunClos<_ValArray, _Tp>, _Tp> + valarray<_Tp>::apply(_Tp func(_Tp)) const + { + typedef _ValFunClos<_ValArray, _Tp> _Closure; + return _Expr<_Closure, _Tp>(_Closure(*this, func)); + } + + template + inline _Expr<_RefFunClos<_ValArray, _Tp>, _Tp> + valarray<_Tp>::apply(_Tp func(const _Tp &)) const + { + typedef _RefFunClos<_ValArray, _Tp> _Closure; + return _Expr<_Closure, _Tp>(_Closure(*this, func)); + } + +#define _DEFINE_VALARRAY_UNARY_OPERATOR(_Op, _Name) \ + template \ + inline typename valarray<_Tp>::template _UnaryOp<_Name>::_Rt \ + valarray<_Tp>::operator _Op() const \ + { \ + typedef _UnClos<_Name, _ValArray, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(*this)); \ + } + + _DEFINE_VALARRAY_UNARY_OPERATOR(+, __unary_plus) + _DEFINE_VALARRAY_UNARY_OPERATOR(-, __negate) + _DEFINE_VALARRAY_UNARY_OPERATOR(~, __bitwise_not) + _DEFINE_VALARRAY_UNARY_OPERATOR (!, __logical_not) + +#undef _DEFINE_VALARRAY_UNARY_OPERATOR + +#define _DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(_Op, _Name) \ + template \ + inline valarray<_Tp>& \ + valarray<_Tp>::operator _Op##=(const _Tp &__t) \ + { \ + _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, __t); \ + return *this; \ + } \ + \ + template \ + inline valarray<_Tp>& \ + valarray<_Tp>::operator _Op##=(const valarray<_Tp> &__v) \ + { \ + __glibcxx_assert(_M_size == __v._M_size); \ + _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, \ + _Array<_Tp>(__v._M_data)); \ + return *this; \ + } + +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(+, __plus) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(-, __minus) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(*, __multiplies) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(/, __divides) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(%, __modulus) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(^, __bitwise_xor) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(&, __bitwise_and) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(|, __bitwise_or) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(<<, __shift_left) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(>>, __shift_right) + +#undef _DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT + +#define _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(_Op, _Name) \ + template template \ + inline valarray<_Tp>& \ + valarray<_Tp>::operator _Op##=(const _Expr<_Dom, _Tp>& __e) \ + { \ + _Array_augmented_##_Name(_Array<_Tp>(_M_data), __e, _M_size); \ + return *this; \ + } + +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(+, __plus) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(-, __minus) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(*, __multiplies) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(/, __divides) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(%, __modulus) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(^, __bitwise_xor) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(&, __bitwise_and) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(|, __bitwise_or) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(<<, __shift_left) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(>>, __shift_right) + +#undef _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT + + +#define _DEFINE_BINARY_OPERATOR(_Op, _Name) \ + template \ + inline _Expr<_BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ + operator _Op(const valarray<_Tp>& __v, const valarray<_Tp>& __w) \ + { \ + __glibcxx_assert(__v.size() == __w.size()); \ + typedef _BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__v, __w)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _ValArray,_Constant, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ + operator _Op(const valarray<_Tp>& __v, \ + const typename valarray<_Tp>::value_type& __t) \ + { \ + typedef _BinClos<_Name, _ValArray, _Constant, _Tp, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__v, __t)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _Constant, _ValArray, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ + operator _Op(const typename valarray<_Tp>::value_type& __t, \ + const valarray<_Tp>& __v) \ + { \ + typedef _BinClos<_Name, _Constant, _ValArray, _Tp, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__t, __v)); \ + } + +_DEFINE_BINARY_OPERATOR(+, __plus) +_DEFINE_BINARY_OPERATOR(-, __minus) +_DEFINE_BINARY_OPERATOR(*, __multiplies) +_DEFINE_BINARY_OPERATOR(/, __divides) +_DEFINE_BINARY_OPERATOR(%, __modulus) +_DEFINE_BINARY_OPERATOR(^, __bitwise_xor) +_DEFINE_BINARY_OPERATOR(&, __bitwise_and) +_DEFINE_BINARY_OPERATOR(|, __bitwise_or) +_DEFINE_BINARY_OPERATOR(<<, __shift_left) +_DEFINE_BINARY_OPERATOR(>>, __shift_right) +_DEFINE_BINARY_OPERATOR(&&, __logical_and) +_DEFINE_BINARY_OPERATOR(||, __logical_or) +_DEFINE_BINARY_OPERATOR(==, __equal_to) +_DEFINE_BINARY_OPERATOR(!=, __not_equal_to) +_DEFINE_BINARY_OPERATOR(<, __less) +_DEFINE_BINARY_OPERATOR(>, __greater) +_DEFINE_BINARY_OPERATOR(<=, __less_equal) +_DEFINE_BINARY_OPERATOR(>=, __greater_equal) + +#undef _DEFINE_BINARY_OPERATOR + +#if __cplusplus >= 201103L + /** + * @brief Return an iterator pointing to the first element of + * the valarray. + * @param __va valarray. + */ + template + inline _Tp* + begin(valarray<_Tp>& __va) + { return std::__addressof(__va[0]); } + + /** + * @brief Return an iterator pointing to the first element of + * the const valarray. + * @param __va valarray. + */ + template + inline const _Tp* + begin(const valarray<_Tp>& __va) + { return std::__addressof(__va[0]); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the valarray. + * @param __va valarray. + */ + template + inline _Tp* + end(valarray<_Tp>& __va) + { return std::__addressof(__va[0]) + __va.size(); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the const valarray. + * @param __va valarray. + */ + template + inline const _Tp* + end(const valarray<_Tp>& __va) + { return std::__addressof(__va[0]) + __va.size(); } +#endif // C++11 + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _GLIBCXX_VALARRAY */ diff --git a/resources/sources/avr-libstdcpp/include/variant b/resources/sources/avr-libstdcpp/include/variant new file mode 100644 index 000000000..3a0d1c1ce --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/variant @@ -0,0 +1,1775 @@ +// -*- C++ -*- + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file variant + * This is the C++ Library header. + */ + +#ifndef _GLIBCXX_VARIANT +#define _GLIBCXX_VARIANT 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __detail +{ +namespace __variant +{ + template + struct _Nth_type; + + template + struct _Nth_type<_Np, _First, _Rest...> + : _Nth_type<_Np-1, _Rest...> { }; + + template + struct _Nth_type<0, _First, _Rest...> + { using type = _First; }; + +} // namespace __variant +} // namespace __detail + +#define __cpp_lib_variant 201606L + + template class tuple; + template class variant; + template struct hash; + + template + struct variant_size; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size> + : std::integral_constant {}; + + template + inline constexpr size_t variant_size_v = variant_size<_Variant>::value; + + template + struct variant_alternative; + + template + struct variant_alternative<_Np, variant<_First, _Rest...>> + : variant_alternative<_Np-1, variant<_Rest...>> {}; + + template + struct variant_alternative<0, variant<_First, _Rest...>> + { using type = _First; }; + + template + using variant_alternative_t = + typename variant_alternative<_Np, _Variant>::type; + + template + struct variant_alternative<_Np, const _Variant> + { using type = add_const_t>; }; + + template + struct variant_alternative<_Np, volatile _Variant> + { using type = add_volatile_t>; }; + + template + struct variant_alternative<_Np, const volatile _Variant> + { using type = add_cv_t>; }; + + inline constexpr size_t variant_npos = -1; + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>& + get(variant<_Types...>&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>&& + get(variant<_Types...>&&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>> const& + get(const variant<_Types...>&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>> const&& + get(const variant<_Types...>&&); + + template + constexpr decltype(auto) + __do_visit(_Visitor&& __visitor, _Variants&&... __variants); + + template + decltype(auto) + __variant_cast(_Tp&& __rhs) + { + if constexpr (is_lvalue_reference_v<_Tp>) + { + if constexpr (is_const_v>) + return static_cast&>(__rhs); + else + return static_cast&>(__rhs); + } + else + return static_cast&&>(__rhs); + } + +namespace __detail +{ +namespace __variant +{ + // Returns the first appearence of _Tp in _Types. + // Returns sizeof...(_Types) if _Tp is not in _Types. + template + struct __index_of : std::integral_constant {}; + + template + inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value; + + template + struct __index_of<_Tp, _First, _Rest...> : + std::integral_constant + ? 0 : __index_of_v<_Tp, _Rest...> + 1> {}; + + // used for raw visitation + struct __variant_cookie {}; + // used for raw visitation with indices passed in + struct __variant_idx_cookie { using type = __variant_idx_cookie; }; + // Used to enable deduction (and same-type checking) for std::visit: + template struct __deduce_visit_result { }; + + // Visit variants that might be valueless. + template + constexpr void + __raw_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + std::__do_visit<__variant_cookie>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + + // Visit variants that might be valueless, passing indices to the visitor. + template + constexpr void + __raw_idx_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + std::__do_visit<__variant_idx_cookie>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + + // _Uninitialized is guaranteed to be a trivially destructible type, + // even if T is not. + template> + struct _Uninitialized; + + template + struct _Uninitialized<_Type, true> + { + template + constexpr + _Uninitialized(in_place_index_t<0>, _Args&&... __args) + : _M_storage(std::forward<_Args>(__args)...) + { } + + constexpr const _Type& _M_get() const & noexcept + { return _M_storage; } + + constexpr _Type& _M_get() & noexcept + { return _M_storage; } + + constexpr const _Type&& _M_get() const && noexcept + { return std::move(_M_storage); } + + constexpr _Type&& _M_get() && noexcept + { return std::move(_M_storage); } + + _Type _M_storage; + }; + + template + struct _Uninitialized<_Type, false> + { + template + constexpr + _Uninitialized(in_place_index_t<0>, _Args&&... __args) + { + ::new ((void*)std::addressof(_M_storage)) + _Type(std::forward<_Args>(__args)...); + } + + const _Type& _M_get() const & noexcept + { return *_M_storage._M_ptr(); } + + _Type& _M_get() & noexcept + { return *_M_storage._M_ptr(); } + + const _Type&& _M_get() const && noexcept + { return std::move(*_M_storage._M_ptr()); } + + _Type&& _M_get() && noexcept + { return std::move(*_M_storage._M_ptr()); } + + __gnu_cxx::__aligned_membuf<_Type> _M_storage; + }; + + template + constexpr decltype(auto) + __get(in_place_index_t<0>, _Union&& __u) noexcept + { return std::forward<_Union>(__u)._M_first._M_get(); } + + template + constexpr decltype(auto) + __get(in_place_index_t<_Np>, _Union&& __u) noexcept + { + return __variant::__get(in_place_index<_Np-1>, + std::forward<_Union>(__u)._M_rest); + } + + // Returns the typed storage for __v. + template + constexpr decltype(auto) + __get(_Variant&& __v) noexcept + { + return __variant::__get(std::in_place_index<_Np>, + std::forward<_Variant>(__v)._M_u); + } + + template + struct _Traits + { + static constexpr bool _S_default_ctor = + is_default_constructible_v::type>; + static constexpr bool _S_copy_ctor = + (is_copy_constructible_v<_Types> && ...); + static constexpr bool _S_move_ctor = + (is_move_constructible_v<_Types> && ...); + static constexpr bool _S_copy_assign = + _S_copy_ctor + && (is_copy_assignable_v<_Types> && ...); + static constexpr bool _S_move_assign = + _S_move_ctor + && (is_move_assignable_v<_Types> && ...); + + static constexpr bool _S_trivial_dtor = + (is_trivially_destructible_v<_Types> && ...); + static constexpr bool _S_trivial_copy_ctor = + (is_trivially_copy_constructible_v<_Types> && ...); + static constexpr bool _S_trivial_move_ctor = + (is_trivially_move_constructible_v<_Types> && ...); + static constexpr bool _S_trivial_copy_assign = + _S_trivial_dtor && _S_trivial_copy_ctor + && (is_trivially_copy_assignable_v<_Types> && ...); + static constexpr bool _S_trivial_move_assign = + _S_trivial_dtor && _S_trivial_move_ctor + && (is_trivially_move_assignable_v<_Types> && ...); + + // The following nothrow traits are for non-trivial SMFs. Trivial SMFs + // are always nothrow. + static constexpr bool _S_nothrow_default_ctor = + is_nothrow_default_constructible_v< + typename _Nth_type<0, _Types...>::type>; + static constexpr bool _S_nothrow_copy_ctor = false; + static constexpr bool _S_nothrow_move_ctor = + (is_nothrow_move_constructible_v<_Types> && ...); + static constexpr bool _S_nothrow_copy_assign = false; + static constexpr bool _S_nothrow_move_assign = + _S_nothrow_move_ctor + && (is_nothrow_move_assignable_v<_Types> && ...); + }; + + // Defines members and ctors. + template + union _Variadic_union { }; + + template + union _Variadic_union<_First, _Rest...> + { + constexpr _Variadic_union() : _M_rest() { } + + template + constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args) + : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) + { } + + template + constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) + : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) + { } + + _Uninitialized<_First> _M_first; + _Variadic_union<_Rest...> _M_rest; + }; + + // _Never_valueless_alt is true for variant alternatives that can + // always be placed in a variant without it becoming valueless. + + // For suitably-small, trivially copyable types we can create temporaries + // on the stack and then memcpy them into place. + template + struct _Never_valueless_alt + : __and_, is_trivially_copyable<_Tp>> + { }; + + // Specialize _Never_valueless_alt for other types which have a + // non-throwing and cheap move construction and move assignment operator, + // so that emplacing the type will provide the strong exception-safety + // guarantee, by creating and moving a temporary. + // Whether _Never_valueless_alt is true or not affects the ABI of a + // variant using that alternative, so we can't change the value later! + + // True if every alternative in _Types... can be emplaced in a variant + // without it becoming valueless. If this is true, variant<_Types...> + // can never be valueless, which enables some minor optimizations. + template + constexpr bool __never_valueless() + { + return _Traits<_Types...>::_S_move_assign + && (_Never_valueless_alt<_Types>::value && ...); + } + + // Defines index and the dtor, possibly trivial. + template + struct _Variant_storage; + + template + using __select_index = + typename __select_int::_Select_int_base::type::value_type; + + template + struct _Variant_storage + { + constexpr + _Variant_storage() + : _M_index(static_cast<__index_type>(variant_npos)) + { } + + template + constexpr + _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) + : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), + _M_index{_Np} + { } + + void _M_reset() + { + if (!_M_valid()) [[unlikely]] + return; + + std::__do_visit([](auto&& __this_mem) mutable + { + std::_Destroy(std::__addressof(__this_mem)); + }, __variant_cast<_Types...>(*this)); + + _M_index = static_cast<__index_type>(variant_npos); + } + + ~_Variant_storage() + { _M_reset(); } + + void* + _M_storage() const noexcept + { + return const_cast(static_cast( + std::addressof(_M_u))); + } + + constexpr bool + _M_valid() const noexcept + { + if constexpr (__variant::__never_valueless<_Types...>()) + return true; + return this->_M_index != __index_type(variant_npos); + } + + _Variadic_union<_Types...> _M_u; + using __index_type = __select_index<_Types...>; + __index_type _M_index; + }; + + template + struct _Variant_storage + { + constexpr + _Variant_storage() + : _M_index(static_cast<__index_type>(variant_npos)) + { } + + template + constexpr + _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) + : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), + _M_index{_Np} + { } + + void _M_reset() noexcept + { _M_index = static_cast<__index_type>(variant_npos); } + + void* + _M_storage() const noexcept + { + return const_cast(static_cast( + std::addressof(_M_u))); + } + + constexpr bool + _M_valid() const noexcept + { + if constexpr (__variant::__never_valueless<_Types...>()) + return true; + return this->_M_index != static_cast<__index_type>(variant_npos); + } + + _Variadic_union<_Types...> _M_u; + using __index_type = __select_index<_Types...>; + __index_type _M_index; + }; + + template + using _Variant_storage_alias = + _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>; + + template + void __variant_construct_single(_Tp&& __lhs, _Up&& __rhs_mem) + { + void* __storage = std::addressof(__lhs._M_u); + using _Type = remove_reference_t; + if constexpr (!is_same_v<_Type, __variant_cookie>) + ::new (__storage) + _Type(std::forward(__rhs_mem)); + } + + template + void __variant_construct(_Tp&& __lhs, _Up&& __rhs) + { + __lhs._M_index = __rhs._M_index; + __variant::__raw_visit([&__lhs](auto&& __rhs_mem) mutable + { + __variant_construct_single(std::forward<_Tp>(__lhs), + std::forward(__rhs_mem)); + }, __variant_cast<_Types...>(std::forward<_Up>(__rhs))); + } + + // The following are (Copy|Move) (ctor|assign) layers for forwarding + // triviality and handling non-trivial SMF behaviors. + + template + struct _Copy_ctor_base : _Variant_storage_alias<_Types...> + { + using _Base = _Variant_storage_alias<_Types...>; + using _Base::_Base; + + _Copy_ctor_base(const _Copy_ctor_base& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor) + { + __variant_construct<_Types...>(*this, __rhs); + } + + _Copy_ctor_base(_Copy_ctor_base&&) = default; + _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default; + _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default; + }; + + template + struct _Copy_ctor_base : _Variant_storage_alias<_Types...> + { + using _Base = _Variant_storage_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Copy_ctor_alias = + _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>; + + template + struct _Move_ctor_base : _Copy_ctor_alias<_Types...> + { + using _Base = _Copy_ctor_alias<_Types...>; + using _Base::_Base; + + _Move_ctor_base(_Move_ctor_base&& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_move_ctor) + { + __variant_construct<_Types...>(*this, std::move(__rhs)); + } + + template + void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs) + { + this->_M_reset(); + __variant_construct_single(*this, std::forward<_Up>(__rhs)); + this->_M_index = __rhs_index; + } + + template + void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs) + { + this->_M_reset(); + __variant_construct_single(*this, __rhs); + this->_M_index = __rhs_index; + } + + _Move_ctor_base(const _Move_ctor_base&) = default; + _Move_ctor_base& operator=(const _Move_ctor_base&) = default; + _Move_ctor_base& operator=(_Move_ctor_base&&) = default; + }; + + template + struct _Move_ctor_base : _Copy_ctor_alias<_Types...> + { + using _Base = _Copy_ctor_alias<_Types...>; + using _Base::_Base; + + template + void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs) + { + this->_M_reset(); + __variant_construct_single(*this, std::forward<_Up>(__rhs)); + this->_M_index = __rhs_index; + } + + template + void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs) + { + this->_M_reset(); + __variant_construct_single(*this, __rhs); + this->_M_index = __rhs_index; + } + }; + + template + using _Move_ctor_alias = + _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>; + + template + struct _Copy_assign_base : _Move_ctor_alias<_Types...> + { + using _Base = _Move_ctor_alias<_Types...>; + using _Base::_Base; + + _Copy_assign_base& + operator=(const _Copy_assign_base& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_copy_assign) + { + __variant::__raw_idx_visit( + [this](auto&& __rhs_mem, auto __rhs_index) mutable + { + if constexpr (__rhs_index != variant_npos) + { + if (this->_M_index == __rhs_index) + __variant::__get<__rhs_index>(*this) = __rhs_mem; + else + { + using __rhs_type = __remove_cvref_t; + if constexpr (is_nothrow_copy_constructible_v<__rhs_type> + || !is_nothrow_move_constructible_v<__rhs_type>) + // The standard says this->emplace<__rhs_type>(__rhs_mem) + // should be used here, but _M_destructive_copy is + // equivalent in this case. Either copy construction + // doesn't throw, so _M_destructive_copy gives strong + // exception safety guarantee, or both copy construction + // and move construction can throw, so emplace only gives + // basic exception safety anyway. + this->_M_destructive_copy(__rhs_index, __rhs_mem); + else + __variant_cast<_Types...>(*this) + = variant<_Types...>(std::in_place_index<__rhs_index>, + __rhs_mem); + } + } + else + this->_M_reset(); + }, __variant_cast<_Types...>(__rhs)); + return *this; + } + + _Copy_assign_base(const _Copy_assign_base&) = default; + _Copy_assign_base(_Copy_assign_base&&) = default; + _Copy_assign_base& operator=(_Copy_assign_base&&) = default; + }; + + template + struct _Copy_assign_base : _Move_ctor_alias<_Types...> + { + using _Base = _Move_ctor_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Copy_assign_alias = + _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, _Types...>; + + template + struct _Move_assign_base : _Copy_assign_alias<_Types...> + { + using _Base = _Copy_assign_alias<_Types...>; + using _Base::_Base; + + _Move_assign_base& + operator=(_Move_assign_base&& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_move_assign) + { + __variant::__raw_idx_visit( + [this](auto&& __rhs_mem, auto __rhs_index) mutable + { + if constexpr (__rhs_index != variant_npos) + { + if (this->_M_index == __rhs_index) + __variant::__get<__rhs_index>(*this) = std::move(__rhs_mem); + else + __variant_cast<_Types...>(*this) + .template emplace<__rhs_index>(std::move(__rhs_mem)); + } + else + this->_M_reset(); + }, __variant_cast<_Types...>(__rhs)); + return *this; + } + + _Move_assign_base(const _Move_assign_base&) = default; + _Move_assign_base(_Move_assign_base&&) = default; + _Move_assign_base& operator=(const _Move_assign_base&) = default; + }; + + template + struct _Move_assign_base : _Copy_assign_alias<_Types...> + { + using _Base = _Copy_assign_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Move_assign_alias = + _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>; + + template + struct _Variant_base : _Move_assign_alias<_Types...> + { + using _Base = _Move_assign_alias<_Types...>; + + constexpr + _Variant_base() + noexcept(_Traits<_Types...>::_S_nothrow_default_ctor) + : _Variant_base(in_place_index<0>) { } + + template + constexpr explicit + _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args) + : _Base(__i, std::forward<_Args>(__args)...) + { } + + _Variant_base(const _Variant_base&) = default; + _Variant_base(_Variant_base&&) = default; + _Variant_base& operator=(const _Variant_base&) = default; + _Variant_base& operator=(_Variant_base&&) = default; + }; + + // For how many times does _Tp appear in _Tuple? + template + struct __tuple_count; + + template + inline constexpr size_t __tuple_count_v = + __tuple_count<_Tp, _Tuple>::value; + + template + struct __tuple_count<_Tp, tuple<_Types...>> + : integral_constant { }; + + template + struct __tuple_count<_Tp, tuple<_First, _Rest...>> + : integral_constant< + size_t, + __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { }; + + // TODO: Reuse this in ? + template + inline constexpr bool __exactly_once = + __tuple_count_v<_Tp, tuple<_Types...>> == 1; + + // Helper used to check for valid conversions that don't involve narrowing. + template struct _Arr { _Ti _M_x[1]; }; + + // Build an imaginary function FUN(Ti) for each alternative type Ti + template, bool>, + typename = void> + struct _Build_FUN + { + // This function means 'using _Build_FUN::_S_fun;' is valid, + // but only static functions will be considered in the call below. + void _S_fun(); + }; + + // ... for which Ti x[] = {std::forward(t)}; is well-formed, + template + struct _Build_FUN<_Ind, _Tp, _Ti, false, + void_t{{std::declval<_Tp>()}})>> + { + // This is the FUN function for type _Ti, with index _Ind + static integral_constant _S_fun(_Ti); + }; + + // ... and if Ti is cv bool, remove_cvref_t is bool. + template + struct _Build_FUN<_Ind, _Tp, _Ti, true, + enable_if_t, bool>>> + { + // This is the FUN function for when _Ti is cv bool, with index _Ind + static integral_constant _S_fun(_Ti); + }; + + template>> + struct _Build_FUNs; + + template + struct _Build_FUNs<_Tp, variant<_Ti...>, index_sequence<_Ind...>> + : _Build_FUN<_Ind, _Tp, _Ti>... + { + using _Build_FUN<_Ind, _Tp, _Ti>::_S_fun...; + }; + + // The index j of the overload FUN(Tj) selected by overload resolution + // for FUN(std::forward<_Tp>(t)) + template + using _FUN_type + = decltype(_Build_FUNs<_Tp, _Variant>::_S_fun(std::declval<_Tp>())); + + // The index selected for FUN(std::forward(t)), or variant_npos if none. + template + struct __accepted_index + : integral_constant + { }; + + template + struct __accepted_index<_Tp, _Variant, void_t<_FUN_type<_Tp, _Variant>>> + : _FUN_type<_Tp, _Variant> + { }; + + // Returns the raw storage for __v. + template + void* __get_storage(_Variant&& __v) noexcept + { return __v._M_storage(); } + + template + struct _Extra_visit_slot_needed + { + template struct _Variant_never_valueless; + + template + struct _Variant_never_valueless> + : bool_constant<__variant::__never_valueless<_Types...>()> {}; + + static constexpr bool value = + (is_same_v<_Maybe_variant_cookie, __variant_cookie> + || is_same_v<_Maybe_variant_cookie, __variant_idx_cookie>) + && !_Variant_never_valueless<__remove_cvref_t<_Variant>>::value; + }; + + // Used for storing a multi-dimensional vtable. + template + struct _Multi_array; + + // Partial specialization with rank zero, stores a single _Tp element. + template + struct _Multi_array<_Tp> + { + template + struct __untag_result + : false_type + { using element_type = _Tp; }; + + template + struct __untag_result + : false_type + { using element_type = void(*)(_Args...); }; + + template + struct __untag_result<__variant_cookie(*)(_Args...)> + : false_type + { using element_type = void(*)(_Args...); }; + + template + struct __untag_result<__variant_idx_cookie(*)(_Args...)> + : false_type + { using element_type = void(*)(_Args...); }; + + template + struct __untag_result<__deduce_visit_result<_Res>(*)(_Args...)> + : true_type + { using element_type = _Res(*)(_Args...); }; + + using __result_is_deduced = __untag_result<_Tp>; + + constexpr const typename __untag_result<_Tp>::element_type& + _M_access() const + { return _M_data; } + + typename __untag_result<_Tp>::element_type _M_data; + }; + + // Partial specialization with rank >= 1. + template + struct _Multi_array<_Ret(*)(_Visitor, _Variants...), __first, __rest...> + { + static constexpr size_t __index = + sizeof...(_Variants) - sizeof...(__rest) - 1; + + using _Variant = typename _Nth_type<__index, _Variants...>::type; + + static constexpr int __do_cookie = + _Extra_visit_slot_needed<_Ret, _Variant>::value ? 1 : 0; + + using _Tp = _Ret(*)(_Visitor, _Variants...); + + template + constexpr decltype(auto) + _M_access(size_t __first_index, _Args... __rest_indices) const + { + return _M_arr[__first_index + __do_cookie] + ._M_access(__rest_indices...); + } + + _Multi_array<_Tp, __rest...> _M_arr[__first + __do_cookie]; + }; + + // Creates a multi-dimensional vtable recursively. + // + // For example, + // visit([](auto, auto){}, + // variant(), // typedef'ed as V1 + // variant()) // typedef'ed as V2 + // will trigger instantiations of: + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 2>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 2>> + // The returned multi-dimensional vtable can be fast accessed by the visitor + // using index calculation. + template + struct __gen_vtable_impl; + + // Defines the _S_apply() member that returns a _Multi_array populated + // with function pointers that perform the visitation expressions e(m) + // for each valid pack of indexes into the variant types _Variants. + // + // This partial specialization builds up the index sequences by recursively + // calling _S_apply() on the next specialization of __gen_vtable_impl. + // The base case of the recursion defines the actual function pointers. + template + struct __gen_vtable_impl< + _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>, + std::index_sequence<__indices...>> + { + using _Next = + remove_reference_t::type>; + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...), + __dimensions...>; + + static constexpr _Array_type + _S_apply() + { + _Array_type __vtable{}; + _S_apply_all_alts( + __vtable, make_index_sequence>()); + return __vtable; + } + + template + static constexpr void + _S_apply_all_alts(_Array_type& __vtable, + std::index_sequence<__var_indices...>) + { + if constexpr (_Extra_visit_slot_needed<_Result_type, _Next>::value) + (_S_apply_single_alt( + __vtable._M_arr[__var_indices + 1], + &(__vtable._M_arr[0])), ...); + else + (_S_apply_single_alt( + __vtable._M_arr[__var_indices]), ...); + } + + template + static constexpr void + _S_apply_single_alt(_Tp& __element, _Tp* __cookie_element = nullptr) + { + if constexpr (__do_cookie) + { + __element = __gen_vtable_impl< + _Tp, + std::index_sequence<__indices..., __index>>::_S_apply(); + *__cookie_element = __gen_vtable_impl< + _Tp, + std::index_sequence<__indices..., variant_npos>>::_S_apply(); + } + else + { + __element = __gen_vtable_impl< + remove_reference_t, + std::index_sequence<__indices..., __index>>::_S_apply(); + } + } + }; + + // This partial specialization is the base case for the recursion. + // It populates a _Multi_array element with the address of a function + // that invokes the visitor with the alternatives specified by __indices. + template + struct __gen_vtable_impl< + _Multi_array<_Result_type (*)(_Visitor, _Variants...)>, + std::index_sequence<__indices...>> + { + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...)>; + + template + static constexpr decltype(auto) + __element_by_index_or_cookie(_Variant&& __var) noexcept + { + if constexpr (__index != variant_npos) + return __variant::__get<__index>(std::forward<_Variant>(__var)); + else + return __variant_cookie{}; + } + + static constexpr decltype(auto) + __visit_invoke(_Visitor&& __visitor, _Variants... __vars) + { + if constexpr (is_same_v<_Result_type, __variant_idx_cookie>) + // For raw visitation using indices, pass the indices to the visitor + // and discard the return value: + std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))..., + integral_constant()...); + else if constexpr (is_same_v<_Result_type, __variant_cookie>) + // For raw visitation without indices, and discard the return value: + std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))...); + else if constexpr (_Array_type::__result_is_deduced::value) + // For the usual std::visit case deduce the return value: + return std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))...); + else // for std::visit use INVOKE + return std::__invoke_r<_Result_type>( + std::forward<_Visitor>(__visitor), + __variant::__get<__indices>(std::forward<_Variants>(__vars))...); + } + + static constexpr auto + _S_apply() + { return _Array_type{&__visit_invoke}; } + }; + + template + struct __gen_vtable + { + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...), + variant_size_v>...>; + + static constexpr _Array_type _S_vtable + = __gen_vtable_impl<_Array_type, std::index_sequence<>>::_S_apply(); + }; + + template + struct _Base_dedup : public _Tp { }; + + template + struct _Variant_hash_base; + + template + struct _Variant_hash_base, + std::index_sequence<__indices...>> + : _Base_dedup<__indices, __poison_hash>>... { }; + +} // namespace __variant +} // namespace __detail + + template + void __variant_construct_by_index(_Variant& __v, _Args&&... __args) + { + __v._M_index = _Np; + auto&& __storage = __detail::__variant::__get<_Np>(__v); + ::new ((void*)std::addressof(__storage)) + remove_reference_t + (std::forward<_Args>(__args)...); + } + + template + constexpr bool + holds_alternative(const variant<_Types...>& __v) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>; + } + + template + constexpr _Tp& get(variant<_Types...>& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); + } + + template + constexpr _Tp&& get(variant<_Types...>&& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( + std::move(__v)); + } + + template + constexpr const _Tp& get(const variant<_Types...>& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); + } + + template + constexpr const _Tp&& get(const variant<_Types...>&& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( + std::move(__v)); + } + + template + constexpr add_pointer_t>> + get_if(variant<_Types...>* __ptr) noexcept + { + using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void"); + if (__ptr && __ptr->index() == _Np) + return std::addressof(__detail::__variant::__get<_Np>(*__ptr)); + return nullptr; + } + + template + constexpr + add_pointer_t>> + get_if(const variant<_Types...>* __ptr) noexcept + { + using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void"); + if (__ptr && __ptr->index() == _Np) + return std::addressof(__detail::__variant::__get<_Np>(*__ptr)); + return nullptr; + } + + template + constexpr add_pointer_t<_Tp> + get_if(variant<_Types...>* __ptr) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( + __ptr); + } + + template + constexpr add_pointer_t + get_if(const variant<_Types...>* __ptr) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( + __ptr); + } + + struct monostate { }; + +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ + template \ + constexpr bool operator __OP(const variant<_Types...>& __lhs, \ + const variant<_Types...>& __rhs) \ + { \ + bool __ret = true; \ + __detail::__variant::__raw_idx_visit( \ + [&__ret, &__lhs] (auto&& __rhs_mem, auto __rhs_index) mutable \ + { \ + if constexpr (__rhs_index != variant_npos) \ + { \ + if (__lhs.index() == __rhs_index) \ + { \ + auto& __this_mem = std::get<__rhs_index>(__lhs); \ + __ret = __this_mem __OP __rhs_mem; \ + } \ + else \ + __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ + } \ + else \ + __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ + }, __rhs); \ + return __ret; \ + } + + _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE + + constexpr bool operator==(monostate, monostate) noexcept { return true; } + +#ifdef __cpp_lib_three_way_comparison + template + requires (three_way_comparable<_Types> && ...) + constexpr + common_comparison_category_t...> + operator<=>(const variant<_Types...>& __v, const variant<_Types...>& __w) + { + common_comparison_category_t...> __ret + = strong_ordering::equal; + + __detail::__variant::__raw_idx_visit( + [&__ret, &__v] (auto&& __w_mem, auto __w_index) mutable + { + if constexpr (__w_index != variant_npos) + { + if (__v.index() == __w_index) + { + auto& __this_mem = std::get<__w_index>(__v); + __ret = __this_mem <=> __w_mem; + return; + } + } + __ret = (__v.index() + 1) <=> (__w_index + 1); + }, __w); + return __ret; + } + + constexpr strong_ordering + operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; } +#else + constexpr bool operator!=(monostate, monostate) noexcept { return false; } + constexpr bool operator<(monostate, monostate) noexcept { return false; } + constexpr bool operator>(monostate, monostate) noexcept { return false; } + constexpr bool operator<=(monostate, monostate) noexcept { return true; } + constexpr bool operator>=(monostate, monostate) noexcept { return true; } +#endif + + template + constexpr decltype(auto) visit(_Visitor&&, _Variants&&...); + + template + inline enable_if_t<(is_move_constructible_v<_Types> && ...) + && (is_swappable_v<_Types> && ...)> + swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template + enable_if_t && ...) + && (is_swappable_v<_Types> && ...))> + swap(variant<_Types...>&, variant<_Types...>&) = delete; + + inline void + __throw_bad_variant_access(bool __valueless __attribute__((unused))) + { + __throw_bad_variant_access(""); + } + + template + class variant + : private __detail::__variant::_Variant_base<_Types...>, + private _Enable_default_constructor< + __detail::__variant::_Traits<_Types...>::_S_default_ctor, + variant<_Types...>>, + private _Enable_copy_move< + __detail::__variant::_Traits<_Types...>::_S_copy_ctor, + __detail::__variant::_Traits<_Types...>::_S_copy_assign, + __detail::__variant::_Traits<_Types...>::_S_move_ctor, + __detail::__variant::_Traits<_Types...>::_S_move_assign, + variant<_Types...>> + { + private: + template + friend decltype(auto) __variant_cast(_Tp&&); + template + friend void __variant_construct_by_index(_Variant& __v, + _Args&&... __args); + + static_assert(sizeof...(_Types) > 0, + "variant must have at least one alternative"); + static_assert(!(std::is_reference_v<_Types> || ...), + "variant must have no reference alternative"); + static_assert(!(std::is_void_v<_Types> || ...), + "variant must have no void alternative"); + + using _Base = __detail::__variant::_Variant_base<_Types...>; + using _Default_ctor_enabler = + _Enable_default_constructor< + __detail::__variant::_Traits<_Types...>::_S_default_ctor, + variant<_Types...>>; + + template + static constexpr bool __not_self + = !is_same_v<__remove_cvref_t<_Tp>, variant>; + + template + static constexpr bool + __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>; + + template + static constexpr size_t __accepted_index + = __detail::__variant::__accepted_index<_Tp, variant>::value; + + template> + using __to_type = variant_alternative_t<_Np, variant>; + + template>> + using __accepted_type = __to_type<__accepted_index<_Tp>>; + + template + static constexpr size_t __index_of = + __detail::__variant::__index_of_v<_Tp, _Types...>; + + using _Traits = __detail::__variant::_Traits<_Types...>; + + template + struct __is_in_place_tag : false_type { }; + template + struct __is_in_place_tag> : true_type { }; + template + struct __is_in_place_tag> : true_type { }; + + template + static constexpr bool __not_in_place_tag + = !__is_in_place_tag<__remove_cvref_t<_Tp>>::value; + + public: + variant() = default; + variant(const variant& __rhs) = default; + variant(variant&&) = default; + variant& operator=(const variant&) = default; + variant& operator=(variant&&) = default; + ~variant() = default; + + template, + typename = enable_if_t<__not_in_place_tag<_Tp>>, + typename _Tj = __accepted_type<_Tp&&>, + typename = enable_if_t<__exactly_once<_Tj> + && is_constructible_v<_Tj, _Tp>>> + constexpr + variant(_Tp&& __t) + noexcept(is_nothrow_constructible_v<_Tj, _Tp>) + : variant(in_place_index<__accepted_index<_Tp>>, + std::forward<_Tp>(__t)) + { } + + template + && is_constructible_v<_Tp, _Args...>>> + constexpr explicit + variant(in_place_type_t<_Tp>, _Args&&... __args) + : variant(in_place_index<__index_of<_Tp>>, + std::forward<_Args>(__args)...) + { } + + template + && is_constructible_v<_Tp, + initializer_list<_Up>&, _Args...>>> + constexpr explicit + variant(in_place_type_t<_Tp>, initializer_list<_Up> __il, + _Args&&... __args) + : variant(in_place_index<__index_of<_Tp>>, __il, + std::forward<_Args>(__args)...) + { } + + template, + typename = enable_if_t>> + constexpr explicit + variant(in_place_index_t<_Np>, _Args&&... __args) + : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...), + _Default_ctor_enabler(_Enable_default_constructor_tag{}) + { } + + template, + typename = enable_if_t&, + _Args...>>> + constexpr explicit + variant(in_place_index_t<_Np>, initializer_list<_Up> __il, + _Args&&... __args) + : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...), + _Default_ctor_enabler(_Enable_default_constructor_tag{}) + { } + + template + enable_if_t<__exactly_once<__accepted_type<_Tp&&>> + && is_constructible_v<__accepted_type<_Tp&&>, _Tp> + && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>, + variant&> + operator=(_Tp&& __rhs) + noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp> + && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>) + { + constexpr auto __index = __accepted_index<_Tp>; + if (index() == __index) + std::get<__index>(*this) = std::forward<_Tp>(__rhs); + else + { + using _Tj = __accepted_type<_Tp&&>; + if constexpr (is_nothrow_constructible_v<_Tj, _Tp> + || !is_nothrow_move_constructible_v<_Tj>) + this->emplace<__index>(std::forward<_Tp>(__rhs)); + else + operator=(variant(std::forward<_Tp>(__rhs))); + } + return *this; + } + + template + enable_if_t && __exactly_once<_Tp>, + _Tp&> + emplace(_Args&&... __args) + { + constexpr size_t __index = __index_of<_Tp>; + return this->emplace<__index>(std::forward<_Args>(__args)...); + } + + template + enable_if_t&, _Args...> + && __exactly_once<_Tp>, + _Tp&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + constexpr size_t __index = __index_of<_Tp>; + return this->emplace<__index>(__il, std::forward<_Args>(__args)...); + } + + template + enable_if_t, + _Args...>, + variant_alternative_t<_Np, variant>&> + emplace(_Args&&... __args) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + using type = variant_alternative_t<_Np, variant>; + // Provide the strong exception-safety guarantee when possible, + // to avoid becoming valueless. + if constexpr (is_nothrow_constructible_v) + { + this->_M_reset(); + __variant_construct_by_index<_Np>(*this, + std::forward<_Args>(__args)...); + } + else if constexpr (is_scalar_v) + { + // This might invoke a potentially-throwing conversion operator: + const type __tmp(std::forward<_Args>(__args)...); + // But these steps won't throw: + this->_M_reset(); + __variant_construct_by_index<_Np>(*this, __tmp); + } + else if constexpr (__detail::__variant::_Never_valueless_alt() + && _Traits::_S_move_assign) + { + // This construction might throw: + variant __tmp(in_place_index<_Np>, + std::forward<_Args>(__args)...); + // But _Never_valueless_alt means this won't: + *this = std::move(__tmp); + } + else + { + // This case only provides the basic exception-safety guarantee, + // i.e. the variant can become valueless. + this->_M_reset(); + __try + { + __variant_construct_by_index<_Np>(*this, + std::forward<_Args>(__args)...); + } + __catch (...) + { + this->_M_index = variant_npos; + __throw_exception_again; + } + } + return std::get<_Np>(*this); + } + + template + enable_if_t, + initializer_list<_Up>&, _Args...>, + variant_alternative_t<_Np, variant>&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + using type = variant_alternative_t<_Np, variant>; + // Provide the strong exception-safety guarantee when possible, + // to avoid becoming valueless. + if constexpr (is_nothrow_constructible_v&, + _Args...>) + { + this->_M_reset(); + __variant_construct_by_index<_Np>(*this, __il, + std::forward<_Args>(__args)...); + } + else if constexpr (__detail::__variant::_Never_valueless_alt() + && _Traits::_S_move_assign) + { + // This construction might throw: + variant __tmp(in_place_index<_Np>, __il, + std::forward<_Args>(__args)...); + // But _Never_valueless_alt means this won't: + *this = std::move(__tmp); + } + else + { + // This case only provides the basic exception-safety guarantee, + // i.e. the variant can become valueless. + this->_M_reset(); + __try + { + __variant_construct_by_index<_Np>(*this, __il, + std::forward<_Args>(__args)...); + } + __catch (...) + { + this->_M_index = variant_npos; + __throw_exception_again; + } + } + return std::get<_Np>(*this); + } + + constexpr bool valueless_by_exception() const noexcept + { return !this->_M_valid(); } + + constexpr size_t index() const noexcept + { + using __index_type = typename _Base::__index_type; + if constexpr (__detail::__variant::__never_valueless<_Types...>()) + return this->_M_index; + else if constexpr (sizeof...(_Types) <= __index_type(-1) / 2) + return make_signed_t<__index_type>(this->_M_index); + else + return size_t(__index_type(this->_M_index + 1)) - 1; + } + + void + swap(variant& __rhs) + noexcept((__is_nothrow_swappable<_Types>::value && ...) + && is_nothrow_move_constructible_v) + { + __detail::__variant::__raw_idx_visit( + [this, &__rhs](auto&& __rhs_mem, auto __rhs_index) mutable + { + if constexpr (__rhs_index != variant_npos) + { + if (this->index() == __rhs_index) + { + auto& __this_mem = + std::get<__rhs_index>(*this); + using std::swap; + swap(__this_mem, __rhs_mem); + } + else + { + if (!this->valueless_by_exception()) [[__likely__]] + { + auto __tmp(std::move(__rhs_mem)); + __rhs = std::move(*this); + this->_M_destructive_move(__rhs_index, + std::move(__tmp)); + } + else + { + this->_M_destructive_move(__rhs_index, + std::move(__rhs_mem)); + __rhs._M_reset(); + } + } + } + else + { + if (!this->valueless_by_exception()) [[__likely__]] + { + __rhs = std::move(*this); + this->_M_reset(); + } + } + }, __rhs); + } + + private: + +#if defined(__clang__) && __clang_major__ <= 7 + public: + using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852 + private: +#endif + + template + friend constexpr decltype(auto) + __detail::__variant::__get(_Vp&& __v) noexcept; + + template + friend void* + __detail::__variant::__get_storage(_Vp&& __v) noexcept; + +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \ + template \ + friend constexpr bool \ + operator __OP(const variant<_Tp...>& __lhs, \ + const variant<_Tp...>& __rhs); + + _VARIANT_RELATION_FUNCTION_TEMPLATE(<) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE + }; + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>& + get(variant<_Types...>& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(__v); + } + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>&& + get(variant<_Types...>&& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(std::move(__v)); + } + + template + constexpr const variant_alternative_t<_Np, variant<_Types...>>& + get(const variant<_Types...>& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(__v); + } + + template + constexpr const variant_alternative_t<_Np, variant<_Types...>>&& + get(const variant<_Types...>&& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(std::move(__v)); + } + + template + constexpr decltype(auto) + __do_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + constexpr auto& __vtable = __detail::__variant::__gen_vtable< + _Result_type, _Visitor&&, _Variants&&...>::_S_vtable; + + auto __func_ptr = __vtable._M_access(__variants.index()...); + return (*__func_ptr)(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + + template + constexpr decltype(auto) + visit(_Visitor&& __visitor, _Variants&&... __variants) + { + if ((__variants.valueless_by_exception() || ...)) + __throw_bad_variant_access("std::visit: variant is valueless"); + + using _Result_type = std::invoke_result_t<_Visitor, + decltype(std::get<0>(std::declval<_Variants>()))...>; + + using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>; + + return std::__do_visit<_Tag>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + +#if __cplusplus > 201703L + template + constexpr _Res + visit(_Visitor&& __visitor, _Variants&&... __variants) + { + if ((__variants.valueless_by_exception() || ...)) + __throw_bad_variant_access("std::visit: variant is valueless"); + + return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } +#endif + + template + struct __variant_hash_call_base_impl + { + size_t + operator()(const variant<_Types...>& __t) const + noexcept((is_nothrow_invocable_v>, _Types> && ...)) + { + size_t __ret; + __detail::__variant::__raw_visit( + [&__t, &__ret](auto&& __t_mem) mutable + { + using _Type = __remove_cvref_t; + if constexpr (!is_same_v<_Type, + __detail::__variant::__variant_cookie>) + __ret = std::hash{}(__t.index()) + + std::hash<_Type>{}(__t_mem); + else + __ret = std::hash{}(__t.index()); + }, __t); + return __ret; + } + }; + + template + struct __variant_hash_call_base_impl {}; + + template + using __variant_hash_call_base = + __variant_hash_call_base_impl<(__poison_hash>:: + __enable_hash_call &&...), _Types...>; + + template + struct hash> + : private __detail::__variant::_Variant_hash_base< + variant<_Types...>, std::index_sequence_for<_Types...>>, + public __variant_hash_call_base<_Types...> + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = variant<_Types...>; + }; + + template<> + struct hash + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = monostate; + + size_t + operator()(const monostate&) const noexcept + { + constexpr size_t __magic_monostate_hash = -7777; + return __magic_monostate_hash; + } + }; + + template + struct __is_fast_hash>> + : bool_constant<(__is_fast_hash<_Types>::value && ...)> + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_VARIANT diff --git a/resources/sources/avr-libstdcpp/include/vector b/resources/sources/avr-libstdcpp/include/vector new file mode 100644 index 000000000..6f587a82a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/vector @@ -0,0 +1,129 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/vector + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_VECTOR +#define _GLIBCXX_VECTOR 1 + +#pragma GCC system_header + +#include +#if __cplusplus > 201703L +# include // For remove and remove_if +#endif // C++20 +#include +#include +#include +#include +#include +#include + +#ifndef _GLIBCXX_EXPORT_TEMPLATE +# include +#endif + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr { + template class polymorphic_allocator; + template + using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>; + } // namespace pmr +# ifdef _GLIBCXX_DEBUG + namespace _GLIBCXX_STD_C::pmr { + template + using vector + = _GLIBCXX_STD_C::vector<_Tp, std::pmr::polymorphic_allocator<_Tp>>; + } // namespace _GLIBCXX_STD_C::pmr +# endif +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_erase_if 202002L + + template + inline typename vector<_Tp, _Alloc>::size_type + erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred) + { + const auto __osz = __cont.size(); + __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred), + __cont.end()); + return __osz - __cont.size(); + } + + template + inline typename vector<_Tp, _Alloc>::size_type + erase(vector<_Tp, _Alloc>& __cont, const _Up& __value) + { + const auto __osz = __cont.size(); + __cont.erase(std::remove(__cont.begin(), __cont.end(), __value), + __cont.end()); + return __osz - __cont.size(); + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_VECTOR */ diff --git a/resources/sources/avr-libstdcpp/include/version b/resources/sources/avr-libstdcpp/include/version new file mode 100644 index 000000000..1e98be3ce --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/version @@ -0,0 +1,231 @@ +// -*- C++ -*- Libstdc++ version details header. + +// Copyright (C) 2018-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file version + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + */ + +#ifndef _GLIBCXX_VERSION_INCLUDED +#define _GLIBCXX_VERSION_INCLUDED + +#pragma GCC system_header + +#include + +// c++03 +#if _GLIBCXX_HOSTED +# define __cpp_lib_incomplete_container_elements 201505 +#endif + +#if !defined(__STRICT_ANSI__) +// gnu++03 +# define __cpp_lib_uncaught_exceptions 201411L +#endif + +#if __cplusplus >= 201103L +// c++11 +#define __cpp_lib_is_null_pointer 201309 +#define __cpp_lib_result_of_sfinae 201210 + +#if _GLIBCXX_HOSTED +# define __cpp_lib_allocator_traits_is_always_equal 201411 +# define __cpp_lib_shared_ptr_arrays 201611L +#endif + +#if !defined(__STRICT_ANSI__) +// gnu++11 +# define __cpp_lib_is_swappable 201603 +# define __cpp_lib_void_t 201411 +# if _GLIBCXX_HOSTED +# define __cpp_lib_enable_shared_from_this 201603 +# endif +#endif + +// For C++11 and later we support ISO/IEC 29124 Mathematical Special Functions +#define __STDCPP_MATH_SPEC_FUNCS__ 201003L + +#if __cplusplus >= 201402L +// c++14 +#if __cpp_impl_coroutine +# define __cpp_lib_coroutine 201902L +#endif +#define __cpp_lib_integral_constant_callable 201304 +#define __cpp_lib_is_final 201402L +#define __cpp_lib_transformation_trait_aliases 201304 + +#if _GLIBCXX_HOSTED +# define __cpp_lib_chrono_udls 201304 +# define __cpp_lib_complex_udls 201309 +# define __cpp_lib_exchange_function 201304 +# define __cpp_lib_generic_associative_lookup 201304 +# define __cpp_lib_integer_sequence 201304 +# define __cpp_lib_make_reverse_iterator 201402 +# define __cpp_lib_make_unique 201304 +# ifndef _GLIBCXX_DEBUG // PR libstdc++/70303 +# define __cpp_lib_null_iterators 201304L +# endif +# define __cpp_lib_quoted_string_io 201304 +# define __cpp_lib_robust_nonmodifying_seq_ops 201304 +# ifdef _GLIBCXX_HAS_GTHREADS +# define __cpp_lib_shared_timed_mutex 201402 +# endif +# define __cpp_lib_string_udls 201304 +# define __cpp_lib_transparent_operators 201510 +# define __cpp_lib_tuple_element_t 201402L +# define __cpp_lib_tuples_by_type 201304 +#endif + +#if __cplusplus >= 201703L +// c++17 +#define __cpp_lib_addressof_constexpr 201603 +#define __cpp_lib_atomic_is_always_lock_free 201603 +#define __cpp_lib_bool_constant 201505 +#define __cpp_lib_byte 201603 +#ifdef _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP +# define __cpp_lib_has_unique_object_representations 201606 +#endif +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE +# define __cpp_lib_is_aggregate 201703 +#endif +#define __cpp_lib_is_invocable 201703 +#define __cpp_lib_is_swappable 201603 +#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER +# define __cpp_lib_launder 201606 +#endif +#define __cpp_lib_logical_traits 201510 +#define __cpp_lib_type_trait_variable_templates 201510L +#define __cpp_lib_uncaught_exceptions 201411L +#define __cpp_lib_void_t 201411 + +#if _GLIBCXX_HOSTED +#define __cpp_lib_any 201606L +#define __cpp_lib_apply 201603 +#define __cpp_lib_array_constexpr 201803L +#define __cpp_lib_as_const 201510 +#define __cpp_lib_boyer_moore_searcher 201603 +#define __cpp_lib_chrono 201611 +#define __cpp_lib_clamp 201603 +#define __cpp_lib_constexpr_char_traits 201611 +#define __cpp_lib_enable_shared_from_this 201603 +#define __cpp_lib_execution 201902L // FIXME: should be 201603L +#define __cpp_lib_filesystem 201703 +#define __cpp_lib_gcd 201606 +#define __cpp_lib_gcd_lcm 201606 +#define __cpp_lib_hypot 201603 +#define __cpp_lib_invoke 201411L +#define __cpp_lib_lcm 201606 +#define __cpp_lib_make_from_tuple 201606 +#define __cpp_lib_map_try_emplace 201411 +#define __cpp_lib_math_special_functions 201603L +#ifdef _GLIBCXX_HAS_GTHREADS +# define __cpp_lib_memory_resource 201603 +#else +# define __cpp_lib_memory_resource 1 +#endif +#define __cpp_lib_node_extract 201606 +#define __cpp_lib_nonmember_container_access 201411 +#define __cpp_lib_not_fn 201603 +#define __cpp_lib_optional 201606L +#define __cpp_lib_raw_memory_algorithms 201606L +#define __cpp_lib_sample 201603 +#ifdef _GLIBCXX_HAS_GTHREADS +# define __cpp_lib_scoped_lock 201703 +# define __cpp_lib_shared_mutex 201505 +#endif +#define __cpp_lib_shared_ptr_weak_type 201606 +#define __cpp_lib_string_view 201803L +// #define __cpp_lib_to_chars 201611L +#define __cpp_lib_unordered_map_try_emplace 201411 +#define __cpp_lib_variant 201606L +#endif + +#if __cplusplus > 201703L +// c++2a +#define __cpp_lib_atomic_float 201711L +#define __cpp_lib_atomic_ref 201806L +#define __cpp_lib_atomic_value_initialization 201911L +#define __cpp_lib_bitops 201907L +#define __cpp_lib_bounded_array_traits 201902L +// __cpp_lib_char8_t is defined in +#if __cpp_concepts >= 201907L +# define __cpp_lib_concepts 202002L +#endif +#if __cpp_impl_destroying_delete +# define __cpp_lib_destroying_delete 201806L +#endif +#define __cpp_lib_endian 201907L +#define __cpp_lib_int_pow2 202002L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +# define __cpp_lib_is_constant_evaluated 201811L +#endif +#define __cpp_lib_is_nothrow_convertible 201806L +#define __cpp_lib_remove_cvref 201711L +#if __cpp_impl_three_way_comparison >= 201907L && __cpp_lib_concepts +# define __cpp_lib_three_way_comparison 201907L +#endif +#define __cpp_lib_type_identity 201806L +#define __cpp_lib_unwrap_ref 201811L + +#if _GLIBCXX_HOSTED +#undef __cpp_lib_array_constexpr +#define __cpp_lib_array_constexpr 201811L +#define __cpp_lib_assume_aligned 201811L +#define __cpp_lib_bind_front 201907L +// FIXME: #define __cpp_lib_execution 201902L +#define __cpp_lib_integer_comparison_functions 202002L +#define __cpp_lib_constexpr_algorithms 201806L +#define __cpp_lib_constexpr_complex 201711L +#define __cpp_lib_constexpr_dynamic_alloc 201907L +#define __cpp_lib_constexpr_functional 201907L +# define __cpp_lib_constexpr_iterator 201811L +#define __cpp_lib_constexpr_memory 201811L +#define __cpp_lib_constexpr_numeric 201911L +#define __cpp_lib_constexpr_string_view 201811L +#define __cpp_lib_constexpr_tuple 201811L +#define __cpp_lib_constexpr_utility 201811L +#define __cpp_lib_erase_if 202002L +#define __cpp_lib_interpolate 201902L +#ifdef _GLIBCXX_HAS_GTHREADS +# define __cpp_lib_jthread 201911L +#endif +#define __cpp_lib_list_remove_return_type 201806L +#define __cpp_lib_math_constants 201907L +#define __cpp_lib_polymorphic_allocator 201902L +#if __cpp_lib_concepts +# define __cpp_lib_ranges 201911L +#endif +#define __cpp_lib_shift 201806L +#define __cpp_lib_span 202002L +#define __cpp_lib_ssize 201902L +#define __cpp_lib_starts_ends_with 201711L +#define __cpp_lib_to_address 201711L +#define __cpp_lib_to_array 201907L +#endif +#endif // C++2a +#endif // C++17 +#endif // C++14 +#endif // C++11 + +#endif // _GLIBCXX_VERSION_INCLUDED diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index c5d9cb6ae..be269a3f2 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -967,10 +967,17 @@ class CompilerModule { } if (boardHalsContent['cxx_flags']) { + const cxxFlags = [...boardHalsContent['cxx_flags']] + // AVR toolchains don't ship the C++ standard library (no , , etc.). + // Add avr-libstdcpp headers so STruC++ runtime compiles on AVR targets. + const avrLibStdCppPath = join(this.sourceDirectoryPath, 'avr-libstdcpp', 'include') + if (boardHalsContent['core']?.startsWith('arduino:avr')) { + cxxFlags.push(`-isystem "${avrLibStdCppPath}"`) + } buildProjectFlags = [ ...buildProjectFlags, '--build-property', - `compiler.cpp.extra_flags=${boardHalsContent['cxx_flags'].map((f) => f).join(' ')}`, + `compiler.cpp.extra_flags=${cxxFlags.join(' ')}`, ] } From c9623dcdc0d19373f8148cf60f2a93bfa780b75f Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 14 Apr 2026 23:50:46 -0400 Subject: [PATCH 025/296] chore: bump strucpp to v0.2.7 (AVR exception guards) v0.2.7 guards includes and throw statements with #ifndef __AVR__ so runtime headers compile on AVR targets where exceptions are not available. Co-Authored-By: Claude Opus 4.6 (1M context) --- binary-versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binary-versions.json b/binary-versions.json index 0e1292f63..5ad810810 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -4,7 +4,7 @@ "repository": "Autonomy-Logic/xml2st" }, "strucpp": { - "version": "v0.2.6", + "version": "v0.2.7", "repository": "Autonomy-Logic/STruCpp" } } From 605b54b35c5d5f75f38f32299da13ba04ff80d9d Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Wed, 15 Apr 2026 00:13:13 -0400 Subject: [PATCH 026/296] fix: replace avr-libstdcpp with minimal C++ stdlib headers for AVR The full avr-libstdcpp (GCC 10) is incompatible with Arduino's AVR GCC 7.3 due to c++config.h version mismatches. Replace with minimal custom headers that provide only what STruC++ runtime needs: - type_traits: integral_constant, enable_if, is_same, is_integral, is_floating_point, is_arithmetic, is_signed, is_unsigned, is_enum, is_class, is_base_of, is_convertible, underlying_type, etc. - utility: move, forward, swap - algorithm: min, max, find, copy, fill - array: std::array - C wrappers: cstdint, cstddef, cstring, cstdlib, cmath, cstdio - Stubs: string, stdexcept, ostream, new (for headers that include them but guard usage with #ifndef __AVR__) Also fix: use -I (not -isystem) for AVR C++ headers -- GCC 7.3 treats -isystem headers as C linkage on AVR, causing "template with C linkage" errors. Also fix: rename StrucppBaremetal.ino to Baremetal.ino (Arduino requires .ino filename to match directory name). Also fix: #undef min/max in sketch to prevent Arduino macro conflicts with std::min/std::max and numeric_limits. Remaining issues to fix: - iec_located.hpp static_assert for 16-byte LocatedVar fails on AVR (pointers are 2 bytes, not 8) - Arduino binary.h defines B0-B7 macros conflicting with template params in iec_traits.hpp - iec_array.hpp uses C++17 deduction guides not supported by GCC 7.3 Co-Authored-By: Claude Opus 4.6 (1M context) --- .../{StrucppBaremetal.ino => Baremetal.ino} | 5 + .../.github/workflows/compile_examples.yml | 34 - resources/sources/avr-libstdcpp/.gitignore | 2 - resources/sources/avr-libstdcpp/COPYING.MPLv2 | 373 -- resources/sources/avr-libstdcpp/COPYING3 | 674 -- resources/sources/avr-libstdcpp/README.md | 359 - .../sources/avr-libstdcpp/include/algorithm | 104 +- resources/sources/avr-libstdcpp/include/any | 626 -- resources/sources/avr-libstdcpp/include/array | 486 +- .../sources/avr-libstdcpp/include/atomic | 1552 ----- .../include/backward/backward_warning.h | 56 - .../avr-libstdcpp/include/backward/binders.h | 182 - .../avr-libstdcpp/include/backward/hash_fun.h | 170 - .../avr-libstdcpp/include/backward/hash_map | 599 -- .../avr-libstdcpp/include/backward/hash_set | 569 -- .../include/backward/hashtable.h | 1166 ---- resources/sources/avr-libstdcpp/include/bit | 371 -- .../avr-libstdcpp/include/bits/algorithmfwd.h | 963 --- .../avr-libstdcpp/include/bits/alloc_traits.h | 743 --- .../include/bits/allocated_ptr.h | 104 - .../avr-libstdcpp/include/bits/allocator.h | 323 - .../avr-libstdcpp/include/bits/atomic_base.h | 1724 ----- .../include/bits/atomic_lockfree_defines.h | 66 - .../include/bits/boost_concept_check.h | 794 --- .../include/bits/c++0x_warning.h | 37 - .../avr-libstdcpp/include/bits/c++allocator.h | 59 - .../avr-libstdcpp/include/bits/c++config.h | 2074 ------ .../avr-libstdcpp/include/bits/char_traits.h | 943 --- .../avr-libstdcpp/include/bits/charconv.h | 106 - .../include/bits/concept_check.h | 81 - .../include/bits/cpp_type_traits.h | 551 -- .../include/bits/cxxabi_forced.h | 60 - .../include/bits/cxxabi_init_exception.h | 80 - .../avr-libstdcpp/include/bits/deque.tcc | 1216 ---- .../include/bits/enable_special_members.h | 312 - .../avr-libstdcpp/include/bits/erase_if.h | 72 - .../include/bits/error_constants.h | 180 - .../include/bits/exception_defines.h | 47 - .../avr-libstdcpp/include/bits/forward_list.h | 1514 ----- .../include/bits/forward_list.tcc | 517 -- .../avr-libstdcpp/include/bits/functexcept.h | 114 - .../include/bits/functional_hash.h | 280 - .../avr-libstdcpp/include/bits/gslice.h | 185 - .../avr-libstdcpp/include/bits/gslice_array.h | 223 - .../avr-libstdcpp/include/bits/hash_bytes.h | 59 - .../avr-libstdcpp/include/bits/hashtable.h | 2228 ------- .../include/bits/hashtable_policy.h | 2107 ------ .../include/bits/indirect_array.h | 212 - .../avr-libstdcpp/include/bits/invoke.h | 163 - .../include/bits/iterator_concepts.h | 911 --- .../avr-libstdcpp/include/bits/list.tcc | 633 -- .../avr-libstdcpp/include/bits/mask_array.h | 213 - .../avr-libstdcpp/include/bits/memoryfwd.h | 82 - .../sources/avr-libstdcpp/include/bits/move.h | 224 - .../avr-libstdcpp/include/bits/node_handle.h | 299 - .../include/bits/parse_numbers.h | 294 - .../avr-libstdcpp/include/bits/postypes.h | 253 - .../include/bits/predefined_ops.h | 405 -- .../avr-libstdcpp/include/bits/ptr_traits.h | 211 - .../avr-libstdcpp/include/bits/random.h | 5183 --------------- .../avr-libstdcpp/include/bits/random.tcc | 2193 ------ .../avr-libstdcpp/include/bits/range_access.h | 1148 ---- .../avr-libstdcpp/include/bits/range_cmp.h | 195 - .../avr-libstdcpp/include/bits/ranges_algo.h | 3792 ----------- .../include/bits/ranges_algobase.h | 597 -- .../include/bits/ranges_uninitialized.h | 574 -- .../avr-libstdcpp/include/bits/refwrap.h | 401 -- .../avr-libstdcpp/include/bits/slice_array.h | 284 - .../avr-libstdcpp/include/bits/std_abs.h | 111 - .../avr-libstdcpp/include/bits/std_function.h | 728 -- .../avr-libstdcpp/include/bits/std_mutex.h | 176 - .../avr-libstdcpp/include/bits/stl_algo.h | 5884 ----------------- .../avr-libstdcpp/include/bits/stl_algobase.h | 1959 ------ .../avr-libstdcpp/include/bits/stl_bvector.h | 1363 ---- .../include/bits/stl_construct.h | 256 - .../avr-libstdcpp/include/bits/stl_deque.h | 2330 ------- .../avr-libstdcpp/include/bits/stl_function.h | 1395 ---- .../avr-libstdcpp/include/bits/stl_heap.h | 583 -- .../avr-libstdcpp/include/bits/stl_iterator.h | 2238 ------- .../include/bits/stl_iterator_base_funcs.h | 239 - .../include/bits/stl_iterator_base_types.h | 271 - .../avr-libstdcpp/include/bits/stl_list.h | 2127 ------ .../avr-libstdcpp/include/bits/stl_map.h | 1568 ----- .../avr-libstdcpp/include/bits/stl_multimap.h | 1233 ---- .../avr-libstdcpp/include/bits/stl_multiset.h | 1075 --- .../avr-libstdcpp/include/bits/stl_numeric.h | 413 -- .../avr-libstdcpp/include/bits/stl_pair.h | 586 -- .../avr-libstdcpp/include/bits/stl_queue.h | 753 --- .../include/bits/stl_raw_storage_iter.h | 123 - .../avr-libstdcpp/include/bits/stl_relops.h | 133 - .../avr-libstdcpp/include/bits/stl_set.h | 1086 --- .../avr-libstdcpp/include/bits/stl_stack.h | 392 -- .../avr-libstdcpp/include/bits/stl_tempbuf.h | 284 - .../avr-libstdcpp/include/bits/stl_tree.h | 2644 -------- .../include/bits/stl_uninitialized.h | 1041 --- .../avr-libstdcpp/include/bits/stl_vector.h | 1985 ------ .../include/bits/string_view.tcc | 229 - .../include/bits/uniform_int_dist.h | 395 -- .../avr-libstdcpp/include/bits/unique_lock.h | 243 - .../avr-libstdcpp/include/bits/unique_ptr.h | 995 --- .../include/bits/unordered_map.h | 2171 ------ .../include/bits/unordered_set.h | 1783 ----- .../include/bits/uses_allocator.h | 195 - .../include/bits/valarray_after.h | 556 -- .../include/bits/valarray_array.h | 677 -- .../include/bits/valarray_array.tcc | 244 - .../include/bits/valarray_before.h | 758 --- .../avr-libstdcpp/include/bits/vector.tcc | 1008 --- .../sources/avr-libstdcpp/include/bitset | 1245 ---- .../sources/avr-libstdcpp/include/cassert | 44 - .../sources/avr-libstdcpp/include/ccomplex | 42 - .../sources/avr-libstdcpp/include/cctype | 94 - .../sources/avr-libstdcpp/include/cerrno | 52 - resources/sources/avr-libstdcpp/include/cfenv | 84 - .../sources/avr-libstdcpp/include/cfloat | 56 - .../sources/avr-libstdcpp/include/chrono | 1131 ---- .../sources/avr-libstdcpp/include/cinttypes | 55 - .../sources/avr-libstdcpp/include/ciso646 | 38 - .../sources/avr-libstdcpp/include/climits | 59 - resources/sources/avr-libstdcpp/include/cmath | 1935 +----- .../sources/avr-libstdcpp/include/compare | 919 --- .../sources/avr-libstdcpp/include/complex | 1931 ------ .../sources/avr-libstdcpp/include/concepts | 367 - .../sources/avr-libstdcpp/include/coroutine | 303 - .../sources/avr-libstdcpp/include/csetjmp | 61 - .../sources/avr-libstdcpp/include/csignal | 57 - .../sources/avr-libstdcpp/include/cstdalign | 44 - .../sources/avr-libstdcpp/include/cstdarg | 58 - .../sources/avr-libstdcpp/include/cstdbool | 44 - .../sources/avr-libstdcpp/include/cstddef | 184 +- .../sources/avr-libstdcpp/include/cstdint | 103 +- .../sources/avr-libstdcpp/include/cstdio | 194 +- .../sources/avr-libstdcpp/include/cstdlib | 205 +- .../sources/avr-libstdcpp/include/cstring | 131 +- .../sources/avr-libstdcpp/include/ctgmath | 44 - resources/sources/avr-libstdcpp/include/ctime | 84 - .../sources/avr-libstdcpp/include/cuchar | 77 - .../sources/avr-libstdcpp/include/cwchar | 306 - .../sources/avr-libstdcpp/include/cwctype | 110 - .../avr-libstdcpp/include/debug/assertions.h | 68 - .../avr-libstdcpp/include/debug/debug.h | 137 - .../avr-libstdcpp/include/debug/formatter.h | 593 -- .../avr-libstdcpp/include/debug/functions.h | 470 -- .../include/debug/helper_functions.h | 315 - .../avr-libstdcpp/include/debug/macros.h | 471 -- .../avr-libstdcpp/include/decimal/decimal | 494 -- .../avr-libstdcpp/include/decimal/decimal.h | 469 -- resources/sources/avr-libstdcpp/include/deque | 119 - .../avr-libstdcpp/include/ext/algorithm | 596 -- .../include/ext/aligned_buffer.h | 125 - .../avr-libstdcpp/include/ext/alloc_traits.h | 171 - .../avr-libstdcpp/include/ext/atomicity.h | 116 - .../sources/avr-libstdcpp/include/ext/cmath | 152 - .../avr-libstdcpp/include/ext/functional | 422 -- .../avr-libstdcpp/include/ext/hash_map | 599 -- .../avr-libstdcpp/include/ext/hash_set | 569 -- .../avr-libstdcpp/include/ext/iterator | 116 - .../include/ext/malloc_allocator.h | 199 - .../sources/avr-libstdcpp/include/ext/memory | 200 - .../avr-libstdcpp/include/ext/new_allocator.h | 198 - .../sources/avr-libstdcpp/include/ext/numeric | 152 - .../include/ext/numeric_traits.h | 148 - .../include/ext/pod_char_traits.h | 198 - .../sources/avr-libstdcpp/include/ext/rb_tree | 93 - .../sources/avr-libstdcpp/include/ext/slist | 1082 --- .../avr-libstdcpp/include/ext/type_traits.h | 221 - .../avr-libstdcpp/include/ext/typelist.h | 538 -- .../avr-libstdcpp/include/forward_list | 87 - .../sources/avr-libstdcpp/include/functional | 1280 ---- .../avr-libstdcpp/include/initializer_list | 132 +- .../sources/avr-libstdcpp/include/iterator | 70 - .../sources/avr-libstdcpp/include/limits | 1893 ------ resources/sources/avr-libstdcpp/include/list | 109 - resources/sources/avr-libstdcpp/include/map | 109 - .../sources/avr-libstdcpp/include/memory | 404 -- resources/sources/avr-libstdcpp/include/mutex | 746 --- resources/sources/avr-libstdcpp/include/new | 196 +- .../sources/avr-libstdcpp/include/numbers | 208 - .../sources/avr-libstdcpp/include/numeric | 699 -- .../sources/avr-libstdcpp/include/optional | 1238 ---- .../sources/avr-libstdcpp/include/ostream | 4 + resources/sources/avr-libstdcpp/include/queue | 66 - .../sources/avr-libstdcpp/include/random | 54 - .../sources/avr-libstdcpp/include/ranges | 3561 ---------- resources/sources/avr-libstdcpp/include/ratio | 576 -- .../avr-libstdcpp/include/scoped_allocator | 519 -- resources/sources/avr-libstdcpp/include/set | 105 - .../avr-libstdcpp/include/shared_mutex | 855 --- resources/sources/avr-libstdcpp/include/span | 462 -- resources/sources/avr-libstdcpp/include/stack | 63 - .../sources/avr-libstdcpp/include/stdexcept | 4 + .../sources/avr-libstdcpp/include/string | 4 + .../sources/avr-libstdcpp/include/string_view | 758 --- resources/sources/avr-libstdcpp/include/tuple | 1764 ----- .../sources/avr-libstdcpp/include/type_traits | 3910 +---------- .../avr-libstdcpp/include/unordered_map | 101 - .../avr-libstdcpp/include/unordered_set | 100 - .../sources/avr-libstdcpp/include/utility | 552 +- .../sources/avr-libstdcpp/include/valarray | 1253 ---- .../sources/avr-libstdcpp/include/variant | 1775 ----- .../sources/avr-libstdcpp/include/vector | 129 - .../sources/avr-libstdcpp/include/version | 231 - .../editor/compiler/compiler-module.ts | 2 +- 203 files changed, 323 insertions(+), 128371 deletions(-) rename resources/sources/StrucppBaremetal/{StrucppBaremetal.ino => Baremetal.ino} (98%) delete mode 100644 resources/sources/avr-libstdcpp/.github/workflows/compile_examples.yml delete mode 100644 resources/sources/avr-libstdcpp/.gitignore delete mode 100644 resources/sources/avr-libstdcpp/COPYING.MPLv2 delete mode 100644 resources/sources/avr-libstdcpp/COPYING3 delete mode 100644 resources/sources/avr-libstdcpp/README.md delete mode 100644 resources/sources/avr-libstdcpp/include/any delete mode 100644 resources/sources/avr-libstdcpp/include/atomic delete mode 100644 resources/sources/avr-libstdcpp/include/backward/backward_warning.h delete mode 100644 resources/sources/avr-libstdcpp/include/backward/binders.h delete mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_fun.h delete mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_map delete mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_set delete mode 100644 resources/sources/avr-libstdcpp/include/backward/hashtable.h delete mode 100644 resources/sources/avr-libstdcpp/include/bit delete mode 100644 resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/alloc_traits.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/allocator.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/atomic_base.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/c++allocator.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/c++config.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/char_traits.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/charconv.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/concept_check.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/deque.tcc delete mode 100644 resources/sources/avr-libstdcpp/include/bits/enable_special_members.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/erase_if.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/error_constants.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/exception_defines.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/forward_list.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/forward_list.tcc delete mode 100644 resources/sources/avr-libstdcpp/include/bits/functexcept.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/functional_hash.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/gslice.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/gslice_array.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/hash_bytes.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/hashtable.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/indirect_array.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/invoke.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/list.tcc delete mode 100644 resources/sources/avr-libstdcpp/include/bits/mask_array.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/memoryfwd.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/move.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/node_handle.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/parse_numbers.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/postypes.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/predefined_ops.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/ptr_traits.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/random.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/random.tcc delete mode 100644 resources/sources/avr-libstdcpp/include/bits/range_access.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/range_cmp.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_algo.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/refwrap.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/slice_array.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/std_abs.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/std_function.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/std_mutex.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_algo.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_algobase.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_bvector.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_construct.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_deque.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_function.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_heap.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_list.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_map.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_multimap.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_multiset.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_numeric.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_pair.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_queue.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_relops.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_set.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_stack.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_tree.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_vector.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/string_view.tcc delete mode 100644 resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/unique_lock.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/unique_ptr.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/unordered_map.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/unordered_set.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/uses_allocator.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_after.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_array.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc delete mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_before.h delete mode 100644 resources/sources/avr-libstdcpp/include/bits/vector.tcc delete mode 100644 resources/sources/avr-libstdcpp/include/bitset delete mode 100644 resources/sources/avr-libstdcpp/include/cassert delete mode 100644 resources/sources/avr-libstdcpp/include/ccomplex delete mode 100644 resources/sources/avr-libstdcpp/include/cctype delete mode 100644 resources/sources/avr-libstdcpp/include/cerrno delete mode 100644 resources/sources/avr-libstdcpp/include/cfenv delete mode 100644 resources/sources/avr-libstdcpp/include/cfloat delete mode 100644 resources/sources/avr-libstdcpp/include/chrono delete mode 100644 resources/sources/avr-libstdcpp/include/cinttypes delete mode 100644 resources/sources/avr-libstdcpp/include/ciso646 delete mode 100644 resources/sources/avr-libstdcpp/include/climits delete mode 100644 resources/sources/avr-libstdcpp/include/compare delete mode 100644 resources/sources/avr-libstdcpp/include/complex delete mode 100644 resources/sources/avr-libstdcpp/include/concepts delete mode 100644 resources/sources/avr-libstdcpp/include/coroutine delete mode 100644 resources/sources/avr-libstdcpp/include/csetjmp delete mode 100644 resources/sources/avr-libstdcpp/include/csignal delete mode 100644 resources/sources/avr-libstdcpp/include/cstdalign delete mode 100644 resources/sources/avr-libstdcpp/include/cstdarg delete mode 100644 resources/sources/avr-libstdcpp/include/cstdbool delete mode 100644 resources/sources/avr-libstdcpp/include/ctgmath delete mode 100644 resources/sources/avr-libstdcpp/include/ctime delete mode 100644 resources/sources/avr-libstdcpp/include/cuchar delete mode 100644 resources/sources/avr-libstdcpp/include/cwchar delete mode 100644 resources/sources/avr-libstdcpp/include/cwctype delete mode 100644 resources/sources/avr-libstdcpp/include/debug/assertions.h delete mode 100644 resources/sources/avr-libstdcpp/include/debug/debug.h delete mode 100644 resources/sources/avr-libstdcpp/include/debug/formatter.h delete mode 100644 resources/sources/avr-libstdcpp/include/debug/functions.h delete mode 100644 resources/sources/avr-libstdcpp/include/debug/helper_functions.h delete mode 100644 resources/sources/avr-libstdcpp/include/debug/macros.h delete mode 100644 resources/sources/avr-libstdcpp/include/decimal/decimal delete mode 100644 resources/sources/avr-libstdcpp/include/decimal/decimal.h delete mode 100644 resources/sources/avr-libstdcpp/include/deque delete mode 100644 resources/sources/avr-libstdcpp/include/ext/algorithm delete mode 100644 resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h delete mode 100644 resources/sources/avr-libstdcpp/include/ext/alloc_traits.h delete mode 100644 resources/sources/avr-libstdcpp/include/ext/atomicity.h delete mode 100644 resources/sources/avr-libstdcpp/include/ext/cmath delete mode 100644 resources/sources/avr-libstdcpp/include/ext/functional delete mode 100644 resources/sources/avr-libstdcpp/include/ext/hash_map delete mode 100644 resources/sources/avr-libstdcpp/include/ext/hash_set delete mode 100644 resources/sources/avr-libstdcpp/include/ext/iterator delete mode 100644 resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h delete mode 100644 resources/sources/avr-libstdcpp/include/ext/memory delete mode 100644 resources/sources/avr-libstdcpp/include/ext/new_allocator.h delete mode 100644 resources/sources/avr-libstdcpp/include/ext/numeric delete mode 100644 resources/sources/avr-libstdcpp/include/ext/numeric_traits.h delete mode 100644 resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h delete mode 100644 resources/sources/avr-libstdcpp/include/ext/rb_tree delete mode 100644 resources/sources/avr-libstdcpp/include/ext/slist delete mode 100644 resources/sources/avr-libstdcpp/include/ext/type_traits.h delete mode 100644 resources/sources/avr-libstdcpp/include/ext/typelist.h delete mode 100644 resources/sources/avr-libstdcpp/include/forward_list delete mode 100644 resources/sources/avr-libstdcpp/include/functional delete mode 100644 resources/sources/avr-libstdcpp/include/iterator delete mode 100644 resources/sources/avr-libstdcpp/include/limits delete mode 100644 resources/sources/avr-libstdcpp/include/list delete mode 100644 resources/sources/avr-libstdcpp/include/map delete mode 100644 resources/sources/avr-libstdcpp/include/memory delete mode 100644 resources/sources/avr-libstdcpp/include/mutex delete mode 100644 resources/sources/avr-libstdcpp/include/numbers delete mode 100644 resources/sources/avr-libstdcpp/include/numeric delete mode 100644 resources/sources/avr-libstdcpp/include/optional create mode 100644 resources/sources/avr-libstdcpp/include/ostream delete mode 100644 resources/sources/avr-libstdcpp/include/queue delete mode 100644 resources/sources/avr-libstdcpp/include/random delete mode 100644 resources/sources/avr-libstdcpp/include/ranges delete mode 100644 resources/sources/avr-libstdcpp/include/ratio delete mode 100644 resources/sources/avr-libstdcpp/include/scoped_allocator delete mode 100644 resources/sources/avr-libstdcpp/include/set delete mode 100644 resources/sources/avr-libstdcpp/include/shared_mutex delete mode 100644 resources/sources/avr-libstdcpp/include/span delete mode 100644 resources/sources/avr-libstdcpp/include/stack create mode 100644 resources/sources/avr-libstdcpp/include/stdexcept create mode 100644 resources/sources/avr-libstdcpp/include/string delete mode 100644 resources/sources/avr-libstdcpp/include/string_view delete mode 100644 resources/sources/avr-libstdcpp/include/tuple delete mode 100644 resources/sources/avr-libstdcpp/include/unordered_map delete mode 100644 resources/sources/avr-libstdcpp/include/unordered_set delete mode 100644 resources/sources/avr-libstdcpp/include/valarray delete mode 100644 resources/sources/avr-libstdcpp/include/variant delete mode 100644 resources/sources/avr-libstdcpp/include/vector delete mode 100644 resources/sources/avr-libstdcpp/include/version diff --git a/resources/sources/StrucppBaremetal/StrucppBaremetal.ino b/resources/sources/StrucppBaremetal/Baremetal.ino similarity index 98% rename from resources/sources/StrucppBaremetal/StrucppBaremetal.ino rename to resources/sources/StrucppBaremetal/Baremetal.ino index 482749334..27f4edf60 100644 --- a/resources/sources/StrucppBaremetal/StrucppBaremetal.ino +++ b/resources/sources/StrucppBaremetal/Baremetal.ino @@ -7,6 +7,11 @@ // - Computes GCD of task intervals for the scan cycle base tick // - Schedules programs round-robin with per-task divisors +// Arduino.h defines min/max as macros which conflict with std::min/std::max +// and numeric_limits::min()/max(). Undefine them before including STruC++ headers. +#undef min +#undef max + #include "generated.hpp" #include "openplc.h" #include "defines.h" diff --git a/resources/sources/avr-libstdcpp/.github/workflows/compile_examples.yml b/resources/sources/avr-libstdcpp/.github/workflows/compile_examples.yml deleted file mode 100644 index 0dc094c14..000000000 --- a/resources/sources/avr-libstdcpp/.github/workflows/compile_examples.yml +++ /dev/null @@ -1,34 +0,0 @@ -name: Compile Examples - -on: - push: - branches: - - '**' - pull_request: - -jobs: - unittests-linux-generic: - runs-on: ubuntu-latest - container: - image: ghcr.io/modm-ext/modm-build-avr:latest - - strategy: - fail-fast: false - matrix: - standard: [ c++17, c++20 ] - - steps: - - name: Check out repository - uses: actions/checkout@v4 - - - name: Check environment - run: | - env - which avr-g++ - avr-g++ --version - - - name: Compile Examples - run: | - for example in $(find examples/ | grep Makefile); do - (cd $(dirname $example) && make -j4 STD=${{ matrix.standard }}) - done diff --git a/resources/sources/avr-libstdcpp/.gitignore b/resources/sources/avr-libstdcpp/.gitignore deleted file mode 100644 index 886e04000..000000000 --- a/resources/sources/avr-libstdcpp/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -examples/**/build - diff --git a/resources/sources/avr-libstdcpp/COPYING.MPLv2 b/resources/sources/avr-libstdcpp/COPYING.MPLv2 deleted file mode 100644 index d0a1fa148..000000000 --- a/resources/sources/avr-libstdcpp/COPYING.MPLv2 +++ /dev/null @@ -1,373 +0,0 @@ -Mozilla Public License Version 2.0 -================================== - -1. Definitions --------------- - -1.1. "Contributor" - means each individual or legal entity that creates, contributes to - the creation of, or owns Covered Software. - -1.2. "Contributor Version" - means the combination of the Contributions of others (if any) used - by a Contributor and that particular Contributor's Contribution. - -1.3. "Contribution" - means Covered Software of a particular Contributor. - -1.4. "Covered Software" - means Source Code Form to which the initial Contributor has attached - the notice in Exhibit A, the Executable Form of such Source Code - Form, and Modifications of such Source Code Form, in each case - including portions thereof. - -1.5. "Incompatible With Secondary Licenses" - means - - (a) that the initial Contributor has attached the notice described - in Exhibit B to the Covered Software; or - - (b) that the Covered Software was made available under the terms of - version 1.1 or earlier of the License, but not also under the - terms of a Secondary License. - -1.6. "Executable Form" - means any form of the work other than Source Code Form. - -1.7. "Larger Work" - means a work that combines Covered Software with other material, in - a separate file or files, that is not Covered Software. - -1.8. "License" - means this document. - -1.9. "Licensable" - means having the right to grant, to the maximum extent possible, - whether at the time of the initial grant or subsequently, any and - all of the rights conveyed by this License. - -1.10. "Modifications" - means any of the following: - - (a) any file in Source Code Form that results from an addition to, - deletion from, or modification of the contents of Covered - Software; or - - (b) any new file in Source Code Form that contains any Covered - Software. - -1.11. "Patent Claims" of a Contributor - means any patent claim(s), including without limitation, method, - process, and apparatus claims, in any patent Licensable by such - Contributor that would be infringed, but for the grant of the - License, by the making, using, selling, offering for sale, having - made, import, or transfer of either its Contributions or its - Contributor Version. - -1.12. "Secondary License" - means either the GNU General Public License, Version 2.0, the GNU - Lesser General Public License, Version 2.1, the GNU Affero General - Public License, Version 3.0, or any later versions of those - licenses. - -1.13. "Source Code Form" - means the form of the work preferred for making modifications. - -1.14. "You" (or "Your") - means an individual or a legal entity exercising rights under this - License. For legal entities, "You" includes any entity that - controls, is controlled by, or is under common control with You. For - purposes of this definition, "control" means (a) the power, direct - or indirect, to cause the direction or management of such entity, - whether by contract or otherwise, or (b) ownership of more than - fifty percent (50%) of the outstanding shares or beneficial - ownership of such entity. - -2. License Grants and Conditions --------------------------------- - -2.1. Grants - -Each Contributor hereby grants You a world-wide, royalty-free, -non-exclusive license: - -(a) under intellectual property rights (other than patent or trademark) - Licensable by such Contributor to use, reproduce, make available, - modify, display, perform, distribute, and otherwise exploit its - Contributions, either on an unmodified basis, with Modifications, or - as part of a Larger Work; and - -(b) under Patent Claims of such Contributor to make, use, sell, offer - for sale, have made, import, and otherwise transfer either its - Contributions or its Contributor Version. - -2.2. Effective Date - -The licenses granted in Section 2.1 with respect to any Contribution -become effective for each Contribution on the date the Contributor first -distributes such Contribution. - -2.3. Limitations on Grant Scope - -The licenses granted in this Section 2 are the only rights granted under -this License. No additional rights or licenses will be implied from the -distribution or licensing of Covered Software under this License. -Notwithstanding Section 2.1(b) above, no patent license is granted by a -Contributor: - -(a) for any code that a Contributor has removed from Covered Software; - or - -(b) for infringements caused by: (i) Your and any other third party's - modifications of Covered Software, or (ii) the combination of its - Contributions with other software (except as part of its Contributor - Version); or - -(c) under Patent Claims infringed by Covered Software in the absence of - its Contributions. - -This License does not grant any rights in the trademarks, service marks, -or logos of any Contributor (except as may be necessary to comply with -the notice requirements in Section 3.4). - -2.4. Subsequent Licenses - -No Contributor makes additional grants as a result of Your choice to -distribute the Covered Software under a subsequent version of this -License (see Section 10.2) or under the terms of a Secondary License (if -permitted under the terms of Section 3.3). - -2.5. Representation - -Each Contributor represents that the Contributor believes its -Contributions are its original creation(s) or it has sufficient rights -to grant the rights to its Contributions conveyed by this License. - -2.6. Fair Use - -This License is not intended to limit any rights You have under -applicable copyright doctrines of fair use, fair dealing, or other -equivalents. - -2.7. Conditions - -Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted -in Section 2.1. - -3. Responsibilities -------------------- - -3.1. Distribution of Source Form - -All distribution of Covered Software in Source Code Form, including any -Modifications that You create or to which You contribute, must be under -the terms of this License. You must inform recipients that the Source -Code Form of the Covered Software is governed by the terms of this -License, and how they can obtain a copy of this License. You may not -attempt to alter or restrict the recipients' rights in the Source Code -Form. - -3.2. Distribution of Executable Form - -If You distribute Covered Software in Executable Form then: - -(a) such Covered Software must also be made available in Source Code - Form, as described in Section 3.1, and You must inform recipients of - the Executable Form how they can obtain a copy of such Source Code - Form by reasonable means in a timely manner, at a charge no more - than the cost of distribution to the recipient; and - -(b) You may distribute such Executable Form under the terms of this - License, or sublicense it under different terms, provided that the - license for the Executable Form does not attempt to limit or alter - the recipients' rights in the Source Code Form under this License. - -3.3. Distribution of a Larger Work - -You may create and distribute a Larger Work under terms of Your choice, -provided that You also comply with the requirements of this License for -the Covered Software. If the Larger Work is a combination of Covered -Software with a work governed by one or more Secondary Licenses, and the -Covered Software is not Incompatible With Secondary Licenses, this -License permits You to additionally distribute such Covered Software -under the terms of such Secondary License(s), so that the recipient of -the Larger Work may, at their option, further distribute the Covered -Software under the terms of either this License or such Secondary -License(s). - -3.4. Notices - -You may not remove or alter the substance of any license notices -(including copyright notices, patent notices, disclaimers of warranty, -or limitations of liability) contained within the Source Code Form of -the Covered Software, except that You may alter any license notices to -the extent required to remedy known factual inaccuracies. - -3.5. Application of Additional Terms - -You may choose to offer, and to charge a fee for, warranty, support, -indemnity or liability obligations to one or more recipients of Covered -Software. However, You may do so only on Your own behalf, and not on -behalf of any Contributor. You must make it absolutely clear that any -such warranty, support, indemnity, or liability obligation is offered by -You alone, and You hereby agree to indemnify every Contributor for any -liability incurred by such Contributor as a result of warranty, support, -indemnity or liability terms You offer. You may include additional -disclaimers of warranty and limitations of liability specific to any -jurisdiction. - -4. Inability to Comply Due to Statute or Regulation ---------------------------------------------------- - -If it is impossible for You to comply with any of the terms of this -License with respect to some or all of the Covered Software due to -statute, judicial order, or regulation then You must: (a) comply with -the terms of this License to the maximum extent possible; and (b) -describe the limitations and the code they affect. Such description must -be placed in a text file included with all distributions of the Covered -Software under this License. Except to the extent prohibited by statute -or regulation, such description must be sufficiently detailed for a -recipient of ordinary skill to be able to understand it. - -5. Termination --------------- - -5.1. The rights granted under this License will terminate automatically -if You fail to comply with any of its terms. However, if You become -compliant, then the rights granted under this License from a particular -Contributor are reinstated (a) provisionally, unless and until such -Contributor explicitly and finally terminates Your grants, and (b) on an -ongoing basis, if such Contributor fails to notify You of the -non-compliance by some reasonable means prior to 60 days after You have -come back into compliance. Moreover, Your grants from a particular -Contributor are reinstated on an ongoing basis if such Contributor -notifies You of the non-compliance by some reasonable means, this is the -first time You have received notice of non-compliance with this License -from such Contributor, and You become compliant prior to 30 days after -Your receipt of the notice. - -5.2. If You initiate litigation against any entity by asserting a patent -infringement claim (excluding declaratory judgment actions, -counter-claims, and cross-claims) alleging that a Contributor Version -directly or indirectly infringes any patent, then the rights granted to -You by any and all Contributors for the Covered Software under Section -2.1 of this License shall terminate. - -5.3. In the event of termination under Sections 5.1 or 5.2 above, all -end user license agreements (excluding distributors and resellers) which -have been validly granted by You or Your distributors under this License -prior to termination shall survive termination. - -************************************************************************ -* * -* 6. Disclaimer of Warranty * -* ------------------------- * -* * -* Covered Software is provided under this License on an "as is" * -* basis, without warranty of any kind, either expressed, implied, or * -* statutory, including, without limitation, warranties that the * -* Covered Software is free of defects, merchantable, fit for a * -* particular purpose or non-infringing. The entire risk as to the * -* quality and performance of the Covered Software is with You. * -* Should any Covered Software prove defective in any respect, You * -* (not any Contributor) assume the cost of any necessary servicing, * -* repair, or correction. This disclaimer of warranty constitutes an * -* essential part of this License. No use of any Covered Software is * -* authorized under this License except under this disclaimer. * -* * -************************************************************************ - -************************************************************************ -* * -* 7. Limitation of Liability * -* -------------------------- * -* * -* Under no circumstances and under no legal theory, whether tort * -* (including negligence), contract, or otherwise, shall any * -* Contributor, or anyone who distributes Covered Software as * -* permitted above, be liable to You for any direct, indirect, * -* special, incidental, or consequential damages of any character * -* including, without limitation, damages for lost profits, loss of * -* goodwill, work stoppage, computer failure or malfunction, or any * -* and all other commercial damages or losses, even if such party * -* shall have been informed of the possibility of such damages. This * -* limitation of liability shall not apply to liability for death or * -* personal injury resulting from such party's negligence to the * -* extent applicable law prohibits such limitation. Some * -* jurisdictions do not allow the exclusion or limitation of * -* incidental or consequential damages, so this exclusion and * -* limitation may not apply to You. * -* * -************************************************************************ - -8. Litigation -------------- - -Any litigation relating to this License may be brought only in the -courts of a jurisdiction where the defendant maintains its principal -place of business and such litigation shall be governed by laws of that -jurisdiction, without reference to its conflict-of-law provisions. -Nothing in this Section shall prevent a party's ability to bring -cross-claims or counter-claims. - -9. Miscellaneous ----------------- - -This License represents the complete agreement concerning the subject -matter hereof. If any provision of this License is held to be -unenforceable, such provision shall be reformed only to the extent -necessary to make it enforceable. Any law or regulation which provides -that the language of a contract shall be construed against the drafter -shall not be used to construe this License against a Contributor. - -10. Versions of the License ---------------------------- - -10.1. New Versions - -Mozilla Foundation is the license steward. Except as provided in Section -10.3, no one other than the license steward has the right to modify or -publish new versions of this License. Each version will be given a -distinguishing version number. - -10.2. Effect of New Versions - -You may distribute the Covered Software under the terms of the version -of the License under which You originally received the Covered Software, -or under the terms of any subsequent version published by the license -steward. - -10.3. Modified Versions - -If you create software not governed by this License, and you want to -create a new license for such software, you may create and use a -modified version of this License if you rename the license and remove -any references to the name of the license steward (except to note that -such modified license differs from this License). - -10.4. Distributing Source Code Form that is Incompatible With Secondary -Licenses - -If You choose to distribute Source Code Form that is Incompatible With -Secondary Licenses under the terms of this version of the License, the -notice described in Exhibit B of this License must be attached. - -Exhibit A - Source Code Form License Notice -------------------------------------------- - - This Source Code Form is subject to the terms of the Mozilla Public - License, v. 2.0. If a copy of the MPL was not distributed with this - file, You can obtain one at https://mozilla.org/MPL/2.0/. - -If it is not possible or desirable to put the notice in a particular -file, then You may include the notice in a location (such as a LICENSE -file in a relevant directory) where a recipient would be likely to look -for such a notice. - -You may add additional accurate notices of copyright ownership. - -Exhibit B - "Incompatible With Secondary Licenses" Notice ---------------------------------------------------------- - - This Source Code Form is "Incompatible With Secondary Licenses", as - defined by the Mozilla Public License, v. 2.0. diff --git a/resources/sources/avr-libstdcpp/COPYING3 b/resources/sources/avr-libstdcpp/COPYING3 deleted file mode 100644 index f288702d2..000000000 --- a/resources/sources/avr-libstdcpp/COPYING3 +++ /dev/null @@ -1,674 +0,0 @@ - GNU GENERAL PUBLIC LICENSE - Version 3, 29 June 2007 - - Copyright (C) 2007 Free Software Foundation, Inc. - Everyone is permitted to copy and distribute verbatim copies - of this license document, but changing it is not allowed. - - Preamble - - The GNU General Public License is a free, copyleft license for -software and other kinds of works. - - The licenses for most software and other practical works are designed -to take away your freedom to share and change the works. By contrast, -the GNU General Public License is intended to guarantee your freedom to -share and change all versions of a program--to make sure it remains free -software for all its users. We, the Free Software Foundation, use the -GNU General Public License for most of our software; it applies also to -any other work released this way by its authors. You can apply it to -your programs, too. - - When we speak of free software, we are referring to freedom, not -price. Our General Public Licenses are designed to make sure that you -have the freedom to distribute copies of free software (and charge for -them if you wish), that you receive source code or can get it if you -want it, that you can change the software or use pieces of it in new -free programs, and that you know you can do these things. - - To protect your rights, we need to prevent others from denying you -these rights or asking you to surrender the rights. Therefore, you have -certain responsibilities if you distribute copies of the software, or if -you modify it: responsibilities to respect the freedom of others. - - For example, if you distribute copies of such a program, whether -gratis or for a fee, you must pass on to the recipients the same -freedoms that you received. You must make sure that they, too, receive -or can get the source code. And you must show them these terms so they -know their rights. - - Developers that use the GNU GPL protect your rights with two steps: -(1) assert copyright on the software, and (2) offer you this License -giving you legal permission to copy, distribute and/or modify it. - - For the developers' and authors' protection, the GPL clearly explains -that there is no warranty for this free software. For both users' and -authors' sake, the GPL requires that modified versions be marked as -changed, so that their problems will not be attributed erroneously to -authors of previous versions. - - Some devices are designed to deny users access to install or run -modified versions of the software inside them, although the manufacturer -can do so. This is fundamentally incompatible with the aim of -protecting users' freedom to change the software. The systematic -pattern of such abuse occurs in the area of products for individuals to -use, which is precisely where it is most unacceptable. Therefore, we -have designed this version of the GPL to prohibit the practice for those -products. If such problems arise substantially in other domains, we -stand ready to extend this provision to those domains in future versions -of the GPL, as needed to protect the freedom of users. - - Finally, every program is threatened constantly by software patents. -States should not allow patents to restrict development and use of -software on general-purpose computers, but in those that do, we wish to -avoid the special danger that patents applied to a free program could -make it effectively proprietary. To prevent this, the GPL assures that -patents cannot be used to render the program non-free. - - The precise terms and conditions for copying, distribution and -modification follow. - - TERMS AND CONDITIONS - - 0. Definitions. - - "This License" refers to version 3 of the GNU General Public License. - - "Copyright" also means copyright-like laws that apply to other kinds of -works, such as semiconductor masks. - - "The Program" refers to any copyrightable work licensed under this -License. Each licensee is addressed as "you". "Licensees" and -"recipients" may be individuals or organizations. - - To "modify" a work means to copy from or adapt all or part of the work -in a fashion requiring copyright permission, other than the making of an -exact copy. The resulting work is called a "modified version" of the -earlier work or a work "based on" the earlier work. - - A "covered work" means either the unmodified Program or a work based -on the Program. - - To "propagate" a work means to do anything with it that, without -permission, would make you directly or secondarily liable for -infringement under applicable copyright law, except executing it on a -computer or modifying a private copy. Propagation includes copying, -distribution (with or without modification), making available to the -public, and in some countries other activities as well. - - To "convey" a work means any kind of propagation that enables other -parties to make or receive copies. Mere interaction with a user through -a computer network, with no transfer of a copy, is not conveying. - - An interactive user interface displays "Appropriate Legal Notices" -to the extent that it includes a convenient and prominently visible -feature that (1) displays an appropriate copyright notice, and (2) -tells the user that there is no warranty for the work (except to the -extent that warranties are provided), that licensees may convey the -work under this License, and how to view a copy of this License. If -the interface presents a list of user commands or options, such as a -menu, a prominent item in the list meets this criterion. - - 1. Source Code. - - The "source code" for a work means the preferred form of the work -for making modifications to it. "Object code" means any non-source -form of a work. - - A "Standard Interface" means an interface that either is an official -standard defined by a recognized standards body, or, in the case of -interfaces specified for a particular programming language, one that -is widely used among developers working in that language. - - The "System Libraries" of an executable work include anything, other -than the work as a whole, that (a) is included in the normal form of -packaging a Major Component, but which is not part of that Major -Component, and (b) serves only to enable use of the work with that -Major Component, or to implement a Standard Interface for which an -implementation is available to the public in source code form. A -"Major Component", in this context, means a major essential component -(kernel, window system, and so on) of the specific operating system -(if any) on which the executable work runs, or a compiler used to -produce the work, or an object code interpreter used to run it. - - The "Corresponding Source" for a work in object code form means all -the source code needed to generate, install, and (for an executable -work) run the object code and to modify the work, including scripts to -control those activities. However, it does not include the work's -System Libraries, or general-purpose tools or generally available free -programs which are used unmodified in performing those activities but -which are not part of the work. For example, Corresponding Source -includes interface definition files associated with source files for -the work, and the source code for shared libraries and dynamically -linked subprograms that the work is specifically designed to require, -such as by intimate data communication or control flow between those -subprograms and other parts of the work. - - The Corresponding Source need not include anything that users -can regenerate automatically from other parts of the Corresponding -Source. - - The Corresponding Source for a work in source code form is that -same work. - - 2. Basic Permissions. - - All rights granted under this License are granted for the term of -copyright on the Program, and are irrevocable provided the stated -conditions are met. This License explicitly affirms your unlimited -permission to run the unmodified Program. The output from running a -covered work is covered by this License only if the output, given its -content, constitutes a covered work. This License acknowledges your -rights of fair use or other equivalent, as provided by copyright law. - - You may make, run and propagate covered works that you do not -convey, without conditions so long as your license otherwise remains -in force. You may convey covered works to others for the sole purpose -of having them make modifications exclusively for you, or provide you -with facilities for running those works, provided that you comply with -the terms of this License in conveying all material for which you do -not control copyright. Those thus making or running the covered works -for you must do so exclusively on your behalf, under your direction -and control, on terms that prohibit them from making any copies of -your copyrighted material outside their relationship with you. - - Conveying under any other circumstances is permitted solely under -the conditions stated below. Sublicensing is not allowed; section 10 -makes it unnecessary. - - 3. Protecting Users' Legal Rights From Anti-Circumvention Law. - - No covered work shall be deemed part of an effective technological -measure under any applicable law fulfilling obligations under article -11 of the WIPO copyright treaty adopted on 20 December 1996, or -similar laws prohibiting or restricting circumvention of such -measures. - - When you convey a covered work, you waive any legal power to forbid -circumvention of technological measures to the extent such circumvention -is effected by exercising rights under this License with respect to -the covered work, and you disclaim any intention to limit operation or -modification of the work as a means of enforcing, against the work's -users, your or third parties' legal rights to forbid circumvention of -technological measures. - - 4. Conveying Verbatim Copies. - - You may convey verbatim copies of the Program's source code as you -receive it, in any medium, provided that you conspicuously and -appropriately publish on each copy an appropriate copyright notice; -keep intact all notices stating that this License and any -non-permissive terms added in accord with section 7 apply to the code; -keep intact all notices of the absence of any warranty; and give all -recipients a copy of this License along with the Program. - - You may charge any price or no price for each copy that you convey, -and you may offer support or warranty protection for a fee. - - 5. Conveying Modified Source Versions. - - You may convey a work based on the Program, or the modifications to -produce it from the Program, in the form of source code under the -terms of section 4, provided that you also meet all of these conditions: - - a) The work must carry prominent notices stating that you modified - it, and giving a relevant date. - - b) The work must carry prominent notices stating that it is - released under this License and any conditions added under section - 7. This requirement modifies the requirement in section 4 to - "keep intact all notices". - - c) You must license the entire work, as a whole, under this - License to anyone who comes into possession of a copy. This - License will therefore apply, along with any applicable section 7 - additional terms, to the whole of the work, and all its parts, - regardless of how they are packaged. This License gives no - permission to license the work in any other way, but it does not - invalidate such permission if you have separately received it. - - d) If the work has interactive user interfaces, each must display - Appropriate Legal Notices; however, if the Program has interactive - interfaces that do not display Appropriate Legal Notices, your - work need not make them do so. - - A compilation of a covered work with other separate and independent -works, which are not by their nature extensions of the covered work, -and which are not combined with it such as to form a larger program, -in or on a volume of a storage or distribution medium, is called an -"aggregate" if the compilation and its resulting copyright are not -used to limit the access or legal rights of the compilation's users -beyond what the individual works permit. Inclusion of a covered work -in an aggregate does not cause this License to apply to the other -parts of the aggregate. - - 6. Conveying Non-Source Forms. - - You may convey a covered work in object code form under the terms -of sections 4 and 5, provided that you also convey the -machine-readable Corresponding Source under the terms of this License, -in one of these ways: - - a) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by the - Corresponding Source fixed on a durable physical medium - customarily used for software interchange. - - b) Convey the object code in, or embodied in, a physical product - (including a physical distribution medium), accompanied by a - written offer, valid for at least three years and valid for as - long as you offer spare parts or customer support for that product - model, to give anyone who possesses the object code either (1) a - copy of the Corresponding Source for all the software in the - product that is covered by this License, on a durable physical - medium customarily used for software interchange, for a price no - more than your reasonable cost of physically performing this - conveying of source, or (2) access to copy the - Corresponding Source from a network server at no charge. - - c) Convey individual copies of the object code with a copy of the - written offer to provide the Corresponding Source. This - alternative is allowed only occasionally and noncommercially, and - only if you received the object code with such an offer, in accord - with subsection 6b. - - d) Convey the object code by offering access from a designated - place (gratis or for a charge), and offer equivalent access to the - Corresponding Source in the same way through the same place at no - further charge. You need not require recipients to copy the - Corresponding Source along with the object code. If the place to - copy the object code is a network server, the Corresponding Source - may be on a different server (operated by you or a third party) - that supports equivalent copying facilities, provided you maintain - clear directions next to the object code saying where to find the - Corresponding Source. Regardless of what server hosts the - Corresponding Source, you remain obligated to ensure that it is - available for as long as needed to satisfy these requirements. - - e) Convey the object code using peer-to-peer transmission, provided - you inform other peers where the object code and Corresponding - Source of the work are being offered to the general public at no - charge under subsection 6d. - - A separable portion of the object code, whose source code is excluded -from the Corresponding Source as a System Library, need not be -included in conveying the object code work. - - A "User Product" is either (1) a "consumer product", which means any -tangible personal property which is normally used for personal, family, -or household purposes, or (2) anything designed or sold for incorporation -into a dwelling. In determining whether a product is a consumer product, -doubtful cases shall be resolved in favor of coverage. For a particular -product received by a particular user, "normally used" refers to a -typical or common use of that class of product, regardless of the status -of the particular user or of the way in which the particular user -actually uses, or expects or is expected to use, the product. A product -is a consumer product regardless of whether the product has substantial -commercial, industrial or non-consumer uses, unless such uses represent -the only significant mode of use of the product. - - "Installation Information" for a User Product means any methods, -procedures, authorization keys, or other information required to install -and execute modified versions of a covered work in that User Product from -a modified version of its Corresponding Source. The information must -suffice to ensure that the continued functioning of the modified object -code is in no case prevented or interfered with solely because -modification has been made. - - If you convey an object code work under this section in, or with, or -specifically for use in, a User Product, and the conveying occurs as -part of a transaction in which the right of possession and use of the -User Product is transferred to the recipient in perpetuity or for a -fixed term (regardless of how the transaction is characterized), the -Corresponding Source conveyed under this section must be accompanied -by the Installation Information. But this requirement does not apply -if neither you nor any third party retains the ability to install -modified object code on the User Product (for example, the work has -been installed in ROM). - - The requirement to provide Installation Information does not include a -requirement to continue to provide support service, warranty, or updates -for a work that has been modified or installed by the recipient, or for -the User Product in which it has been modified or installed. Access to a -network may be denied when the modification itself materially and -adversely affects the operation of the network or violates the rules and -protocols for communication across the network. - - Corresponding Source conveyed, and Installation Information provided, -in accord with this section must be in a format that is publicly -documented (and with an implementation available to the public in -source code form), and must require no special password or key for -unpacking, reading or copying. - - 7. Additional Terms. - - "Additional permissions" are terms that supplement the terms of this -License by making exceptions from one or more of its conditions. -Additional permissions that are applicable to the entire Program shall -be treated as though they were included in this License, to the extent -that they are valid under applicable law. If additional permissions -apply only to part of the Program, that part may be used separately -under those permissions, but the entire Program remains governed by -this License without regard to the additional permissions. - - When you convey a copy of a covered work, you may at your option -remove any additional permissions from that copy, or from any part of -it. (Additional permissions may be written to require their own -removal in certain cases when you modify the work.) You may place -additional permissions on material, added by you to a covered work, -for which you have or can give appropriate copyright permission. - - Notwithstanding any other provision of this License, for material you -add to a covered work, you may (if authorized by the copyright holders of -that material) supplement the terms of this License with terms: - - a) Disclaiming warranty or limiting liability differently from the - terms of sections 15 and 16 of this License; or - - b) Requiring preservation of specified reasonable legal notices or - author attributions in that material or in the Appropriate Legal - Notices displayed by works containing it; or - - c) Prohibiting misrepresentation of the origin of that material, or - requiring that modified versions of such material be marked in - reasonable ways as different from the original version; or - - d) Limiting the use for publicity purposes of names of licensors or - authors of the material; or - - e) Declining to grant rights under trademark law for use of some - trade names, trademarks, or service marks; or - - f) Requiring indemnification of licensors and authors of that - material by anyone who conveys the material (or modified versions of - it) with contractual assumptions of liability to the recipient, for - any liability that these contractual assumptions directly impose on - those licensors and authors. - - All other non-permissive additional terms are considered "further -restrictions" within the meaning of section 10. If the Program as you -received it, or any part of it, contains a notice stating that it is -governed by this License along with a term that is a further -restriction, you may remove that term. If a license document contains -a further restriction but permits relicensing or conveying under this -License, you may add to a covered work material governed by the terms -of that license document, provided that the further restriction does -not survive such relicensing or conveying. - - If you add terms to a covered work in accord with this section, you -must place, in the relevant source files, a statement of the -additional terms that apply to those files, or a notice indicating -where to find the applicable terms. - - Additional terms, permissive or non-permissive, may be stated in the -form of a separately written license, or stated as exceptions; -the above requirements apply either way. - - 8. Termination. - - You may not propagate or modify a covered work except as expressly -provided under this License. Any attempt otherwise to propagate or -modify it is void, and will automatically terminate your rights under -this License (including any patent licenses granted under the third -paragraph of section 11). - - However, if you cease all violation of this License, then your -license from a particular copyright holder is reinstated (a) -provisionally, unless and until the copyright holder explicitly and -finally terminates your license, and (b) permanently, if the copyright -holder fails to notify you of the violation by some reasonable means -prior to 60 days after the cessation. - - Moreover, your license from a particular copyright holder is -reinstated permanently if the copyright holder notifies you of the -violation by some reasonable means, this is the first time you have -received notice of violation of this License (for any work) from that -copyright holder, and you cure the violation prior to 30 days after -your receipt of the notice. - - Termination of your rights under this section does not terminate the -licenses of parties who have received copies or rights from you under -this License. If your rights have been terminated and not permanently -reinstated, you do not qualify to receive new licenses for the same -material under section 10. - - 9. Acceptance Not Required for Having Copies. - - You are not required to accept this License in order to receive or -run a copy of the Program. Ancillary propagation of a covered work -occurring solely as a consequence of using peer-to-peer transmission -to receive a copy likewise does not require acceptance. However, -nothing other than this License grants you permission to propagate or -modify any covered work. These actions infringe copyright if you do -not accept this License. Therefore, by modifying or propagating a -covered work, you indicate your acceptance of this License to do so. - - 10. Automatic Licensing of Downstream Recipients. - - Each time you convey a covered work, the recipient automatically -receives a license from the original licensors, to run, modify and -propagate that work, subject to this License. You are not responsible -for enforcing compliance by third parties with this License. - - An "entity transaction" is a transaction transferring control of an -organization, or substantially all assets of one, or subdividing an -organization, or merging organizations. If propagation of a covered -work results from an entity transaction, each party to that -transaction who receives a copy of the work also receives whatever -licenses to the work the party's predecessor in interest had or could -give under the previous paragraph, plus a right to possession of the -Corresponding Source of the work from the predecessor in interest, if -the predecessor has it or can get it with reasonable efforts. - - You may not impose any further restrictions on the exercise of the -rights granted or affirmed under this License. For example, you may -not impose a license fee, royalty, or other charge for exercise of -rights granted under this License, and you may not initiate litigation -(including a cross-claim or counterclaim in a lawsuit) alleging that -any patent claim is infringed by making, using, selling, offering for -sale, or importing the Program or any portion of it. - - 11. Patents. - - A "contributor" is a copyright holder who authorizes use under this -License of the Program or a work on which the Program is based. The -work thus licensed is called the contributor's "contributor version". - - A contributor's "essential patent claims" are all patent claims -owned or controlled by the contributor, whether already acquired or -hereafter acquired, that would be infringed by some manner, permitted -by this License, of making, using, or selling its contributor version, -but do not include claims that would be infringed only as a -consequence of further modification of the contributor version. For -purposes of this definition, "control" includes the right to grant -patent sublicenses in a manner consistent with the requirements of -this License. - - Each contributor grants you a non-exclusive, worldwide, royalty-free -patent license under the contributor's essential patent claims, to -make, use, sell, offer for sale, import and otherwise run, modify and -propagate the contents of its contributor version. - - In the following three paragraphs, a "patent license" is any express -agreement or commitment, however denominated, not to enforce a patent -(such as an express permission to practice a patent or covenant not to -sue for patent infringement). To "grant" such a patent license to a -party means to make such an agreement or commitment not to enforce a -patent against the party. - - If you convey a covered work, knowingly relying on a patent license, -and the Corresponding Source of the work is not available for anyone -to copy, free of charge and under the terms of this License, through a -publicly available network server or other readily accessible means, -then you must either (1) cause the Corresponding Source to be so -available, or (2) arrange to deprive yourself of the benefit of the -patent license for this particular work, or (3) arrange, in a manner -consistent with the requirements of this License, to extend the patent -license to downstream recipients. "Knowingly relying" means you have -actual knowledge that, but for the patent license, your conveying the -covered work in a country, or your recipient's use of the covered work -in a country, would infringe one or more identifiable patents in that -country that you have reason to believe are valid. - - If, pursuant to or in connection with a single transaction or -arrangement, you convey, or propagate by procuring conveyance of, a -covered work, and grant a patent license to some of the parties -receiving the covered work authorizing them to use, propagate, modify -or convey a specific copy of the covered work, then the patent license -you grant is automatically extended to all recipients of the covered -work and works based on it. - - A patent license is "discriminatory" if it does not include within -the scope of its coverage, prohibits the exercise of, or is -conditioned on the non-exercise of one or more of the rights that are -specifically granted under this License. You may not convey a covered -work if you are a party to an arrangement with a third party that is -in the business of distributing software, under which you make payment -to the third party based on the extent of your activity of conveying -the work, and under which the third party grants, to any of the -parties who would receive the covered work from you, a discriminatory -patent license (a) in connection with copies of the covered work -conveyed by you (or copies made from those copies), or (b) primarily -for and in connection with specific products or compilations that -contain the covered work, unless you entered into that arrangement, -or that patent license was granted, prior to 28 March 2007. - - Nothing in this License shall be construed as excluding or limiting -any implied license or other defenses to infringement that may -otherwise be available to you under applicable patent law. - - 12. No Surrender of Others' Freedom. - - If conditions are imposed on you (whether by court order, agreement or -otherwise) that contradict the conditions of this License, they do not -excuse you from the conditions of this License. If you cannot convey a -covered work so as to satisfy simultaneously your obligations under this -License and any other pertinent obligations, then as a consequence you may -not convey it at all. For example, if you agree to terms that obligate you -to collect a royalty for further conveying from those to whom you convey -the Program, the only way you could satisfy both those terms and this -License would be to refrain entirely from conveying the Program. - - 13. Use with the GNU Affero General Public License. - - Notwithstanding any other provision of this License, you have -permission to link or combine any covered work with a work licensed -under version 3 of the GNU Affero General Public License into a single -combined work, and to convey the resulting work. The terms of this -License will continue to apply to the part which is the covered work, -but the special requirements of the GNU Affero General Public License, -section 13, concerning interaction through a network will apply to the -combination as such. - - 14. Revised Versions of this License. - - The Free Software Foundation may publish revised and/or new versions of -the GNU General Public License from time to time. Such new versions will -be similar in spirit to the present version, but may differ in detail to -address new problems or concerns. - - Each version is given a distinguishing version number. If the -Program specifies that a certain numbered version of the GNU General -Public License "or any later version" applies to it, you have the -option of following the terms and conditions either of that numbered -version or of any later version published by the Free Software -Foundation. If the Program does not specify a version number of the -GNU General Public License, you may choose any version ever published -by the Free Software Foundation. - - If the Program specifies that a proxy can decide which future -versions of the GNU General Public License can be used, that proxy's -public statement of acceptance of a version permanently authorizes you -to choose that version for the Program. - - Later license versions may give you additional or different -permissions. However, no additional obligations are imposed on any -author or copyright holder as a result of your choosing to follow a -later version. - - 15. Disclaimer of Warranty. - - THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY -APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT -HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY -OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, -THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR -PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM -IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF -ALL NECESSARY SERVICING, REPAIR OR CORRECTION. - - 16. Limitation of Liability. - - IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING -WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS -THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY -GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE -USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF -DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD -PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), -EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF -SUCH DAMAGES. - - 17. Interpretation of Sections 15 and 16. - - If the disclaimer of warranty and limitation of liability provided -above cannot be given local legal effect according to their terms, -reviewing courts shall apply local law that most closely approximates -an absolute waiver of all civil liability in connection with the -Program, unless a warranty or assumption of liability accompanies a -copy of the Program in return for a fee. - - END OF TERMS AND CONDITIONS - - How to Apply These Terms to Your New Programs - - If you develop a new program, and you want it to be of the greatest -possible use to the public, the best way to achieve this is to make it -free software which everyone can redistribute and change under these terms. - - To do so, attach the following notices to the program. It is safest -to attach them to the start of each source file to most effectively -state the exclusion of warranty; and each file should have at least -the "copyright" line and a pointer to where the full notice is found. - - - Copyright (C) - - This program is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . - -Also add information on how to contact you by electronic and paper mail. - - If the program does terminal interaction, make it output a short -notice like this when it starts in an interactive mode: - - Copyright (C) - This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. - This is free software, and you are welcome to redistribute it - under certain conditions; type `show c' for details. - -The hypothetical commands `show w' and `show c' should show the appropriate -parts of the General Public License. Of course, your program's commands -might be different; for a GUI interface, you would use an "about box". - - You should also get your employer (if you work as a programmer) or school, -if any, to sign a "copyright disclaimer" for the program, if necessary. -For more information on this, and how to apply and follow the GNU GPL, see -. - - The GNU General Public License does not permit incorporating your program -into proprietary programs. If your program is a subroutine library, you -may consider it more useful to permit linking proprietary applications with -the library. If this is what you want to do, use the GNU Lesser General -Public License instead of this License. But first, please read -. diff --git a/resources/sources/avr-libstdcpp/README.md b/resources/sources/avr-libstdcpp/README.md deleted file mode 100644 index 0fff5319b..000000000 --- a/resources/sources/avr-libstdcpp/README.md +++ /dev/null @@ -1,359 +0,0 @@ -# avr-libstdcpp: libstdc++ port for avr-gcc -[![Build Status](https://github.com/modm-io/avr-libstdcpp/actions/workflows/compile_examples.yml/badge.svg)](https://github.com/modm-io/avr-libstdcpp/actions) -================== - -`avr-libstdcpp` is a partial, non-fully-tested -implementation of the C++ standard library and its STL. -It is intended to be used with `avr-gcc`. - -Many features of modern C++11,14,17 and 20 are supported. - -`avr-gcc` does not have a complete C++ standard library nor does it include an STL implementation. -The `avr-libstdcpp` port (even though not-fully-tested -and only partially full/complete) will, nonetheless, -be useful for those interested in making more comprehensive utilization -of C++, including its standard library, with a modern `avr-gcc` compiler. - -## Historical origins - -The `avr-libstdcpp` library traces its own origins to existing -GNU/GCC C++ standard library implementation(s), themselves targeting -embedded systems. This work is essentially an even-more -_embedded_-_friendly_ adaptation of the aforementioned work. - -The `avr-libstdcpp` port began in 2018 with an initial import -of a GNU/GCC-based C++ standard library from GCC 8. -A second import of a GNU/GCC-based C++ standard library from GCC 10 -in 2020 modernized the port to include many contemporary C++20 features. - -## Using the library - -- Add the `avr-libstdcpp/include` path to the standard `-isystem` (or `-I`) include path(s) of the compiler on the command line. -- Upon doing this, include standard library headers in the usual way (i.e., `#include `, `#include `, `#include `, etc.). -- There are also several source files located in the [src directory](./src). Some of these may potentially be needed. -- For instance, when doing floating-point mathematical calculations with the `` library, the file [`math.cc`](./src/math.cc) located [here](./src) needs to be added as a normal source file to your project. - - -For straightforward header-only use, for example, -simply add the `-isystem` (or alternatively the `-I`) include path -to your particular location of `avr-libstdcpp/include` on the command line... - -```sh -avr-g++ -O2 -x c++ -isystem /my_path/avr-libstdcpp/include -mmcu=atmega328p test.cpp -o test.elf -``` - -... and seamlessly use standard library headers in your code. - -```cpp -#include -#include - -std::array a { 1, 2, 3 }; - -int main() -{ - // 6 - auto sum = std::accumulate(a.cbegin(), a.cend(), 0); - - static_cast(sum); -} -``` - -Additional straightforward code samples exercising standard library usage -can be found in the [examples](./examples) folder. - -## Using the library with MICROCHIP's ATMEL Studio - -`avr-libstdcpp` can be successfully used with MICROCHIP's ATMEL Studio. -The include path of the headers needs to be added to the project settings in the normal way. -Add also any of the necessary source files, as described in the section above. - -This is an advanced use of `avr-libstdcpp` in combination with MICROCHIP's ATMEL Studio -because the underlying GCC compiler used with ATMEL Studio also needs to be -upgraded to a much more modern one than the `avr-gcc` 5 -delivered in the standard installation of this studio. - -An [informative thread](https://github.com/modm-io/avr-libstdcpp/issues/17#issuecomment-1098241768) -provides a few more details on how to use `avr-libstdcpp` with MICROCHIP's ATMEL Studio. - -## Guidance for tiny bare-metal systems - -### Very helpful go-to libraries - -In general the C++ standard library is intended -to be written and implemented in a resource-sensitive -fashion. This includes efforts to save on both -memory as well as run-time. -In fact, C++ standard library functions and algorithms -have, in general, been specifically written and tuned by -the library authors with efficiency aspects in mind. -In particular, library components compile reliably and quickly -and also lend themselves well to compiler optimization. - -Some library components, however, are particularly well-suited -for bare-metal microcontroller programming. -These can be exceptionally helpful when used properly and sensibly -in tiny bare-metal microcontroller environments. - -A subjective list of these the libraries/headers -and their main uses includes, but is not limited to,: - -- `` for containers having known, fixed size. -- `` for standard algorithms such as sorting, minimax, sequential operations, etc. -- `` for projects requiring floating-point mathematical functions such as `std::sin()`, `std::exp()`, `std::frexp()` and many more. For some mathematical uses, it might be necessary to include [`math.cc`](./src/math.cc) in your project. This source file is located [here](./src). -- `` which defines integral types having specified widths residing within `namespace std` like `std::uint8_t`. -- `` offering compile-time query of numeric limits of built-in types. -- `` featuring a collection of useful numeric algorithms such as `std::accumulate()`, etc. -- `` for compile-time decisions based on types. - -With these libraries alone, the entire project can benefit -from a great deal of the standard library's power without compromising -in any way on performance or sleek memory footprint. -This is because these libaries are typically lean, fast and require no additional storage. - -The following non-trivial, real-world example, for instance, -wraps instances of an overly-simplified LED class abstraction -as object-references in an `std::array`. -Once stored, the application exercises the LED's toggle -function in an algorithmic loop with `toggle()`-method call -expressed via lambda function. - -```cpp -#include -#include -#include - -class led -{ -public: - led() = default; - - auto toggle() -> void { } -}; - -led led0; -led led1; -led led2; - -using led_ref_type = std::reference_wrapper; - -std::array led_refs = -{ - led0, - led1, - led2 -}; - -int main() -{ - for(;;) - { - std::for_each(led_refs.begin(), - led_refs.end(), - [](led& lr) { lr.toggle(); }); - } -} -``` - -This nifty little example is terse, expressive and powerful. -It makes use of parts of ``, `` and `` -to greatly simplify the programming within a non-trivial -microcontroller situation. - -This example is key because it combines the domains -of object-oriented programming with the templated -algorithms and wrappers of the STL to assist -in our microcontroller world. - -### Libraries requiring more design considerations - -Some C++ library and STL artifacts, however, -require more careful design considerations -regarding memory allocation and management. - -Consider, for instance, `std::vector` from the `` library. -Vector creates a flexibly-sized array-like collection -of items of any kind, depending on the template parameter. - -For instance: - -```cpp -#include - -// A vector of 3 integers. -std::vector v { 1, 2, 3 }; -``` - -See also the [main.cpp](./examples/vector/main.cpp) file -in the [./examples/vector](./examples/vector) directory. - -This vector requires storage for three integers which, -on the `avr-gcc` platform is 6 bytes. The storage is managed -through vector's _second_, less well-known template parameter. -In other words, - -```cpp -namespace std { - -// Forward declaration of the vector template class. -template> -class vector; - -} -``` - -Using containers requires memory allocation with a so-called allocator. -If none is specified, as in our code snippet, the default allocator -from namespace `std` for the templated type `T` of the vector is -automatically selected. - -Good embeddable self-written custom allocators are essential for -using such containers so that memory could be managed with -a self-written memory pool, an off-chip memory device, etc. -A common selection is a pool of static memory creating a so-called -_ring_ _allocator_. This is an intermetiate/advanced topic -which will refine STL use _on_ _the_ _metal_ and -also allow for flexible template use in these resource-sensitive -realms. - -## Notable adaptions and limitations - -Some parts of the C++ standard library are not well suited for -tiny bare-metal systems. These include some memory-intensive -and/or hardware-intensive library artifacts. - -`avr-libstdcpp` has the following known adaptions and limitations. - -- **I/O streaming and RTTI:** I/O streaming and run-time type information (RTTI) are known -to be resource-intensive and could be disruptive on tiny -embedded platforms. An effort has been made to essentially -remove both these library dependencies and their -associated codes. - -- **exceptions:** Exceptions are also difficult to efficiently -implement on tiny embedded platforms and this library port avoids using exceptions. -The headers `` and ``, their dependencies, -and their directly relevant code sequences have been removed. -Simple mechanisms such as those found in `` -and ``, however, remain mostly available. - -- **``:** The `` library is being handled -specifically in the draft of -[avr-libstdcpp/pull/36](https://github.com/modm-io/avr-libstdcpp/pull/36). - -- **``:** There is no source of entropy whatsoever on these platforms -in their standard configuration. So `std::random_device` -has been removed. - -- **Hashing:** Hashing has been optimized for tiny architectures and uses a rudimentary 16-bit CRC algorithm. - -- **``:** Only certain judiciously selected clock functions from the `` library are implemented. -These include `std::chrono::high_resolution_clock` and `std::chrono::steady_clock`. When using -these clocks, it is required to implement the clock's static method -`now()` in a project-specific fashion. This is because -the library's authors can not in a generic way implement any -microcontroller-specific clock(s) since this requires detailed knowledge -of the underlying microcontroller peripherie. - -- **`int`, `size_t`, `ptrdiff_t` and the like:** Data types such as -`int`, and `size_t` and `ptrdiff_t` (which are aliased to -`unsigned`/`signed` versions of `int`) -are generally limited to 16-bits in width -on tiny `avr-gcc` platforms. Although this is a compiler attribute, -it has strong influence on the library (particularly the STL) -implementation because these data types are used copiously therein. -This compiler attribute limits ranges, indexes, etc. to 16-bits. -With the compiler switch `-mint8`, the built-in type `int` -is only 8 bits wide and extreme range limitations -are expected to make STL use tricky. - -- **``:** In `avr-gcc` 10 and higher, the built-in data types -`double` and `long double` can be either 32 or 64 bits in width. -The widths depend on the compiler command line options `-mdouble=32` -(alternatively `-mdouble=64`) and/or `-mlong-double=32` -(alternatively `-mlong-double=64`). Standard floating-point -`` functions such as `std::sin()`, `std::cos()`, -`std::exp()` and the like will, therefore, have input and output -widths according to these command line options. - -## C++20 `constexpr` support - -The following is a rather advanced, highly useful topic. -When using C++20, `constexpr` construction, assignment and evaluation -of various algorithms can and often will be generally -compile-time constant (i.e, via consistent use of C++20 `constexpr`-ness). - -As a result of this, STL algorithms that use compile-time constant inputs are, in fact, -evaluated at compile time in C++20. This lets us perform a strong, -purposeful shift of algorithmic complexity _to_-_the_-_left_. -In other words, we shift algorithmic complexity _into_ the compile-time -stage of code development and _away from_ the precious RAM-ROM-space/cycles -of the compiled running code. - -In the following code, for instance, we revisit the `std::array`/`` -example from above. The variation below exhibits complete compile-time -evaluation of the algorithmic result. - -To take the deep dive in this topic, follow all the useful compile-time -preprocessor symbols such as -`__cpp_lib_constexpr_algorithms`, `__cpp_lib_constexpr_numeric`, and many more -in [feature testing](https://en.cppreference.com/w/cpp/feature_test). - -```cpp -#include -#include - -#if (defined(__cpp_lib_constexpr_numeric) && (__cpp_lib_constexpr_numeric>=201911L)) -#define MODM_CONSTEXPR constexpr -#define MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR 1 -#else -#define MODM_CONSTEXPR -#define MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR 0 -#endif - -MODM_CONSTEXPR std::array a { 1, 2, 3 }; - -int main() -{ - // 6 - auto MODM_CONSTEXPR sum = std::accumulate(a.cbegin(), a.cend(), 0); - - #if (MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR == 1) - static_assert(sum == 6, "Error: Unexpected std::accumulate result!"); - #endif - - return (sum == 6 ? 0 : -1); -} -``` - -See also the [numeric.cpp](./examples/numeric/numeric.cpp) file -in the [/examples/numeric](./examples/numeric) directory. - -## Additional details - -`avr-libstdcpp` is intended for a modern `avr-gcc` -such as the port available in the [modm-io project](https://github.com/modm-io/avr-gcc) -repository. Tests show usability for `avr-gcc` 7 through 15. - -This library has been checked for compatibility on `avr-gcc` -with language standards C++11,14,17,20,23 and 2c. - -Using the port way back to `avr-gcc` 5 does not work -at the moment with today's form of the checked-in library, -and `avr-gcc` 7 or higher is required. -This is because the very old compiler lexical parsers are not capable -of properly handling some of the library's template code. -See also [avr-libstdcpp/issues/15](https://github.com/modm-io/avr-libstdcpp/issues/15) -which is closed and includes justification for its closure. - -## Licensing - -The library source files in [`src/`](./src/) -and the library include files in [`include/` and its subfolders](./include/) -(with two exceptions for the sources, as mentioned below) -are licensed under [GNU General Public License Version 3](./COPYING3) or higher. - -All of the [example codes](./examples/) and also two library source files -(namely `functexcept.cc` and `math.cc` in [`src/`](./src/)) -are subject to the terms of the [Mozilla Public License Version 2.0](./COPYING.MPLv2). diff --git a/resources/sources/avr-libstdcpp/include/algorithm b/resources/sources/avr-libstdcpp/include/algorithm index 8000e3218..d0e7e3974 100644 --- a/resources/sources/avr-libstdcpp/include/algorithm +++ b/resources/sources/avr-libstdcpp/include/algorithm @@ -1,67 +1,39 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/algorithm - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_ALGORITHM -#define _GLIBCXX_ALGORITHM 1 - -#pragma GCC system_header - -#include // UK-300. -#include -#include -#if __cplusplus > 201703L -# include +// Minimal for AVR +#ifndef _AVR_ALGORITHM +#define _AVR_ALGORITHM + +namespace std { + template constexpr const T& min(const T& a, const T& b) { return (b < a) ? b : a; } + template constexpr const T& max(const T& a, const T& b) { return (a < b) ? b : a; } + + template constexpr T min(std::initializer_list ilist) { + const T* p = ilist.begin(); + T m = *p; + for (++p; p != ilist.end(); ++p) if (*p < m) m = *p; + return m; + } + template constexpr T max(std::initializer_list ilist) { + const T* p = ilist.begin(); + T m = *p; + for (++p; p != ilist.end(); ++p) if (*p > m) m = *p; + return m; + } + + template + InputIt find(InputIt first, InputIt last, const T& value) { + for (; first != last; ++first) if (*first == value) return first; + return last; + } + + template + OutputIt copy(InputIt first, InputIt last, OutputIt d_first) { + for (; first != last; ++first, ++d_first) *d_first = *first; + return d_first; + } + + template + void fill(ForwardIt first, ForwardIt last, const T& value) { + for (; first != last; ++first) *first = value; + } +} #endif - -#endif /* _GLIBCXX_ALGORITHM */ diff --git a/resources/sources/avr-libstdcpp/include/any b/resources/sources/avr-libstdcpp/include/any deleted file mode 100644 index 39fc77082..000000000 --- a/resources/sources/avr-libstdcpp/include/any +++ /dev/null @@ -1,626 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2014-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/any - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_ANY -#define _GLIBCXX_ANY 1 - -#pragma GCC system_header - -#if __cplusplus >= 201703L - -#if __cpp_rtti -#include -#else -namespace std -{ - class type_info; -} -#endif // __cpp_rtti - -#include -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup utilities - * @{ - */ - -#define __cpp_lib_any 201606L - - /** - * @brief A type-safe container of any type. - * - * An @c any object's state is either empty or it stores a contained object - * of CopyConstructible type. - */ - class any - { - // Holds either pointer to a heap object or the contained object itself. - union _Storage - { - constexpr _Storage() : _M_ptr{nullptr} {} - - // Prevent trivial copies of this type, buffer might hold a non-POD. - _Storage(const _Storage&) = delete; - _Storage& operator=(const _Storage&) = delete; - - void* _M_ptr; - aligned_storage::type _M_buffer; - }; - - template, - bool _Fits = (sizeof(_Tp) <= sizeof(_Storage)) - && (alignof(_Tp) <= alignof(_Storage))> - using _Internal = std::integral_constant; - - template - struct _Manager_internal; // uses small-object optimization - - template - struct _Manager_external; // creates contained object on the heap - - template - using _Manager = conditional_t<_Internal<_Tp>::value, - _Manager_internal<_Tp>, - _Manager_external<_Tp>>; - - template> - using _Decay_if_not_any = enable_if_t, _VTp>; - - /// Emplace with an object created from @p __args as the contained object. - template > - void __do_emplace(_Args&&... __args) - { - reset(); - _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); - _M_manager = &_Mgr::_S_manage; - } - - /// Emplace with an object created from @p __il and @p __args as - /// the contained object. - template > - void __do_emplace(initializer_list<_Up> __il, _Args&&... __args) - { - reset(); - _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); - _M_manager = &_Mgr::_S_manage; - } - - template - using __any_constructible - = enable_if<__and_, - is_constructible<_Tp, _Args...>>::value, - _Res>; - - template - using __any_constructible_t - = typename __any_constructible::type; - - template - using __emplace_t - = typename __any_constructible<_VTp&, _VTp, _Args...>::type; - - public: - // construct/destruct - - /// Default constructor, creates an empty object. - constexpr any() noexcept : _M_manager(nullptr) { } - - /// Copy constructor, copies the state of @p __other - any(const any& __other) - { - if (!__other.has_value()) - _M_manager = nullptr; - else - { - _Arg __arg; - __arg._M_any = this; - __other._M_manager(_Op_clone, &__other, &__arg); - } - } - - /** - * @brief Move constructor, transfer the state from @p __other - * - * @post @c !__other.has_value() (this postcondition is a GNU extension) - */ - any(any&& __other) noexcept - { - if (!__other.has_value()) - _M_manager = nullptr; - else - { - _Arg __arg; - __arg._M_any = this; - __other._M_manager(_Op_xfer, &__other, &__arg); - } - } - - /// Construct with a copy of @p __value as the contained object. - template , - typename _Mgr = _Manager<_VTp>, - enable_if_t::value - && !__is_in_place_type<_VTp>::value, bool> = true> - any(_Tp&& __value) - : _M_manager(&_Mgr::_S_manage) - { - _Mgr::_S_create(_M_storage, std::forward<_Tp>(__value)); - } - - /// Construct with an object created from @p __args as the contained object. - template , - typename _Mgr = _Manager<_VTp>, - __any_constructible_t<_VTp, _Args&&...> = false> - explicit - any(in_place_type_t<_Tp>, _Args&&... __args) - : _M_manager(&_Mgr::_S_manage) - { - _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); - } - - /// Construct with an object created from @p __il and @p __args as - /// the contained object. - template , typename _Mgr = _Manager<_VTp>, - __any_constructible_t<_VTp, initializer_list<_Up>, - _Args&&...> = false> - explicit - any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) - : _M_manager(&_Mgr::_S_manage) - { - _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); - } - - /// Destructor, calls @c reset() - ~any() { reset(); } - - // assignments - - /// Copy the state of another object. - any& - operator=(const any& __rhs) - { - *this = any(__rhs); - return *this; - } - - /** - * @brief Move assignment operator - * - * @post @c !__rhs.has_value() (not guaranteed for other implementations) - */ - any& - operator=(any&& __rhs) noexcept - { - if (!__rhs.has_value()) - reset(); - else if (this != &__rhs) - { - reset(); - _Arg __arg; - __arg._M_any = this; - __rhs._M_manager(_Op_xfer, &__rhs, &__arg); - } - return *this; - } - - /// Store a copy of @p __rhs as the contained object. - template - enable_if_t>::value, any&> - operator=(_Tp&& __rhs) - { - *this = any(std::forward<_Tp>(__rhs)); - return *this; - } - - /// Emplace with an object created from @p __args as the contained object. - template - __emplace_t, _Args...> - emplace(_Args&&... __args) - { - using _VTp = decay_t<_Tp>; - __do_emplace<_VTp>(std::forward<_Args>(__args)...); - any::_Arg __arg; - this->_M_manager(any::_Op_access, this, &__arg); - return *static_cast<_VTp*>(__arg._M_obj); - } - - /// Emplace with an object created from @p __il and @p __args as - /// the contained object. - template - __emplace_t, initializer_list<_Up>, _Args&&...> - emplace(initializer_list<_Up> __il, _Args&&... __args) - { - using _VTp = decay_t<_Tp>; - __do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...); - any::_Arg __arg; - this->_M_manager(any::_Op_access, this, &__arg); - return *static_cast<_VTp*>(__arg._M_obj); - } - - // modifiers - - /// If not empty, destroy the contained object. - void reset() noexcept - { - if (has_value()) - { - _M_manager(_Op_destroy, this, nullptr); - _M_manager = nullptr; - } - } - - /// Exchange state with another object. - void swap(any& __rhs) noexcept - { - if (!has_value() && !__rhs.has_value()) - return; - - if (has_value() && __rhs.has_value()) - { - if (this == &__rhs) - return; - - any __tmp; - _Arg __arg; - __arg._M_any = &__tmp; - __rhs._M_manager(_Op_xfer, &__rhs, &__arg); - __arg._M_any = &__rhs; - _M_manager(_Op_xfer, this, &__arg); - __arg._M_any = this; - __tmp._M_manager(_Op_xfer, &__tmp, &__arg); - } - else - { - any* __empty = !has_value() ? this : &__rhs; - any* __full = !has_value() ? &__rhs : this; - _Arg __arg; - __arg._M_any = __empty; - __full->_M_manager(_Op_xfer, __full, &__arg); - } - } - - // observers - - /// Reports whether there is a contained object or not. - bool has_value() const noexcept { return _M_manager != nullptr; } - -#if __cpp_rtti - /// The @c typeid of the contained object, or @c typeid(void) if empty. - const type_info& type() const noexcept - { - if (!has_value()) - return typeid(void); - _Arg __arg; - _M_manager(_Op_get_type_info, this, &__arg); - return *__arg._M_typeinfo; - } -#endif - - template - static constexpr bool __is_valid_cast() - { return __or_, is_copy_constructible<_Tp>>::value; } - - private: - enum _Op { - _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer - }; - - union _Arg - { - void* _M_obj; - const std::type_info* _M_typeinfo; - any* _M_any; - }; - - void (*_M_manager)(_Op, const any*, _Arg*); - _Storage _M_storage; - - template - friend void* __any_caster(const any* __any); - - // Manage in-place contained object. - template - struct _Manager_internal - { - static void - _S_manage(_Op __which, const any* __anyp, _Arg* __arg); - - template - static void - _S_create(_Storage& __storage, _Up&& __value) - { - void* __addr = &__storage._M_buffer; - ::new (__addr) _Tp(std::forward<_Up>(__value)); - } - - template - static void - _S_create(_Storage& __storage, _Args&&... __args) - { - void* __addr = &__storage._M_buffer; - ::new (__addr) _Tp(std::forward<_Args>(__args)...); - } - }; - - // Manage external contained object. - template - struct _Manager_external - { - static void - _S_manage(_Op __which, const any* __anyp, _Arg* __arg); - - template - static void - _S_create(_Storage& __storage, _Up&& __value) - { - __storage._M_ptr = new _Tp(std::forward<_Up>(__value)); - } - template - static void - _S_create(_Storage& __storage, _Args&&... __args) - { - __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...); - } - }; - }; - - /// Exchange the states of two @c any objects. - inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); } - - /// Create an any holding a @c _Tp constructed from @c __args. - template - any make_any(_Args&&... __args) - { - return any(in_place_type<_Tp>, std::forward<_Args>(__args)...); - } - - /// Create an any holding a @c _Tp constructed from @c __il and @c __args. - template - any make_any(initializer_list<_Up> __il, _Args&&... __args) - { - return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...); - } - - /** - * @brief Access the contained object. - * - * @tparam _ValueType A const-reference or CopyConstructible type. - * @param __any The object to access. - * @return The contained object. - * @throw bad_any_cast If - * __any.type() != typeid(remove_reference_t<_ValueType>) - * - */ - template - inline _ValueType any_cast(const any& __any) - { - using _Up = __remove_cvref_t<_ValueType>; - static_assert(any::__is_valid_cast<_ValueType>(), - "Template argument must be a reference or CopyConstructible type"); - static_assert(is_constructible_v<_ValueType, const _Up&>, - "Template argument must be constructible from a const value."); - auto __p = any_cast<_Up>(&__any); - if (__p) - return static_cast<_ValueType>(*__p); - __throw_bad_any_cast(); - } - - /** - * @brief Access the contained object. - * - * @tparam _ValueType A reference or CopyConstructible type. - * @param __any The object to access. - * @return The contained object. - * @throw bad_any_cast If - * __any.type() != typeid(remove_reference_t<_ValueType>) - * - * - * @{ - */ - template - inline _ValueType any_cast(any& __any) - { - using _Up = __remove_cvref_t<_ValueType>; - static_assert(any::__is_valid_cast<_ValueType>(), - "Template argument must be a reference or CopyConstructible type"); - static_assert(is_constructible_v<_ValueType, _Up&>, - "Template argument must be constructible from an lvalue."); - auto __p = any_cast<_Up>(&__any); - if (__p) - return static_cast<_ValueType>(*__p); - __throw_bad_any_cast(); - } - - template - inline _ValueType any_cast(any&& __any) - { - using _Up = __remove_cvref_t<_ValueType>; - static_assert(any::__is_valid_cast<_ValueType>(), - "Template argument must be a reference or CopyConstructible type"); - static_assert(is_constructible_v<_ValueType, _Up>, - "Template argument must be constructible from an rvalue."); - auto __p = any_cast<_Up>(&__any); - if (__p) - return static_cast<_ValueType>(std::move(*__p)); - __throw_bad_any_cast(); - } - // @} - - /// @cond undocumented - template - void* __any_caster(const any* __any) - { - // any_cast returns non-null if __any->type() == typeid(T) and - // typeid(T) ignores cv-qualifiers so remove them: - using _Up = remove_cv_t<_Tp>; - // The contained value has a decayed type, so if decay_t is not U, - // then it's not possible to have a contained value of type U: - if constexpr (!is_same_v, _Up>) - return nullptr; - // Only copy constructible types can be used for contained values: - else if constexpr (!is_copy_constructible_v<_Up>) - return nullptr; - // First try comparing function addresses, which works without RTTI - else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage -#if __cpp_rtti - || __any->type() == typeid(_Tp) -#endif - ) - { - any::_Arg __arg; - __any->_M_manager(any::_Op_access, __any, &__arg); - return __arg._M_obj; - } - return nullptr; - } - /// @endcond - - /** - * @brief Access the contained object. - * - * @tparam _ValueType The type of the contained object. - * @param __any A pointer to the object to access. - * @return The address of the contained object if - * __any != nullptr && __any.type() == typeid(_ValueType) - * , otherwise a null pointer. - * - * @{ - */ - template - inline const _ValueType* any_cast(const any* __any) noexcept - { - if constexpr (is_object_v<_ValueType>) - if (__any) - return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); - return nullptr; - } - - template - inline _ValueType* any_cast(any* __any) noexcept - { - if constexpr (is_object_v<_ValueType>) - if (__any) - return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); - return nullptr; - } - // @} - - template - void - any::_Manager_internal<_Tp>:: - _S_manage(_Op __which, const any* __any, _Arg* __arg) - { - // The contained object is in _M_storage._M_buffer - auto __ptr = reinterpret_cast(&__any->_M_storage._M_buffer); - switch (__which) - { - case _Op_access: - __arg->_M_obj = const_cast<_Tp*>(__ptr); - break; - case _Op_get_type_info: -#if __cpp_rtti - __arg->_M_typeinfo = &typeid(_Tp); -#endif - break; - case _Op_clone: - ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); - __arg->_M_any->_M_manager = __any->_M_manager; - break; - case _Op_destroy: - __ptr->~_Tp(); - break; - case _Op_xfer: - ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp - (std::move(*const_cast<_Tp*>(__ptr))); - __ptr->~_Tp(); - __arg->_M_any->_M_manager = __any->_M_manager; - const_cast(__any)->_M_manager = nullptr; - break; - } - } - - template - void - any::_Manager_external<_Tp>:: - _S_manage(_Op __which, const any* __any, _Arg* __arg) - { - // The contained object is *_M_storage._M_ptr - auto __ptr = static_cast(__any->_M_storage._M_ptr); - switch (__which) - { - case _Op_access: - __arg->_M_obj = const_cast<_Tp*>(__ptr); - break; - case _Op_get_type_info: -#if __cpp_rtti - __arg->_M_typeinfo = &typeid(_Tp); -#endif - break; - case _Op_clone: - __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr); - __arg->_M_any->_M_manager = __any->_M_manager; - break; - case _Op_destroy: - delete __ptr; - break; - case _Op_xfer: - __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr; - __arg->_M_any->_M_manager = __any->_M_manager; - const_cast(__any)->_M_manager = nullptr; - break; - } - } - - /// @} - - namespace __detail::__variant - { - template struct _Never_valueless_alt; // see - - // Provide the strong exception-safety guarantee when emplacing an - // any into a variant. - template<> - struct _Never_valueless_alt - : std::true_type - { }; - } // namespace __detail::__variant - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++17 -#endif // _GLIBCXX_ANY diff --git a/resources/sources/avr-libstdcpp/include/array b/resources/sources/avr-libstdcpp/include/array index 3bb6f48c4..c96fc5c01 100644 --- a/resources/sources/avr-libstdcpp/include/array +++ b/resources/sources/avr-libstdcpp/include/array @@ -1,451 +1,37 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/array - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_ARRAY -#define _GLIBCXX_ARRAY 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - struct __array_traits - { - typedef _Tp _Type[_Nm]; - typedef __is_swappable<_Tp> _Is_swappable; - typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable; - - static constexpr _Tp& - _S_ref(const _Type& __t, std::size_t __n) noexcept - { return const_cast<_Tp&>(__t[__n]); } - - static constexpr _Tp* - _S_ptr(const _Type& __t) noexcept - { return const_cast<_Tp*>(__t); } - }; - - template - struct __array_traits<_Tp, 0> - { - struct _Type { }; - typedef true_type _Is_swappable; - typedef true_type _Is_nothrow_swappable; - - static constexpr _Tp& - _S_ref(const _Type&, std::size_t) noexcept - { return *static_cast<_Tp*>(nullptr); } - - static constexpr _Tp* - _S_ptr(const _Type&) noexcept - { return nullptr; } - }; - - /** - * @brief A standard container for storing a fixed size sequence of elements. - * - * @ingroup sequences - * - * Meets the requirements of a container, a - * reversible container, and a - * sequence. - * - * Sets support random access iterators. - * - * @tparam Tp Type of element. Required to be a complete type. - * @tparam Nm Number of elements. - */ - template - struct array - { - typedef _Tp value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef value_type* iterator; - typedef const value_type* const_iterator; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - - // Support for zero-sized arrays mandatory. - typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type; - typename _AT_Type::_Type _M_elems; - - // No explicit construct/copy/destroy for aggregate type. - - // DR 776. - _GLIBCXX20_CONSTEXPR void - fill(const value_type& __u) - { std::fill_n(begin(), size(), __u); } - - _GLIBCXX20_CONSTEXPR void - swap(array& __other) - noexcept(_AT_Type::_Is_nothrow_swappable::value) - { std::swap_ranges(begin(), end(), __other.begin()); } - - // Iterators. - _GLIBCXX17_CONSTEXPR iterator - begin() noexcept - { return iterator(data()); } - - _GLIBCXX17_CONSTEXPR const_iterator - begin() const noexcept - { return const_iterator(data()); } - - _GLIBCXX17_CONSTEXPR iterator - end() noexcept - { return iterator(data() + _Nm); } - - _GLIBCXX17_CONSTEXPR const_iterator - end() const noexcept - { return const_iterator(data() + _Nm); } - - _GLIBCXX17_CONSTEXPR reverse_iterator - rbegin() noexcept - { return reverse_iterator(end()); } - - _GLIBCXX17_CONSTEXPR const_reverse_iterator - rbegin() const noexcept - { return const_reverse_iterator(end()); } - - _GLIBCXX17_CONSTEXPR reverse_iterator - rend() noexcept - { return reverse_iterator(begin()); } - - _GLIBCXX17_CONSTEXPR const_reverse_iterator - rend() const noexcept - { return const_reverse_iterator(begin()); } - - _GLIBCXX17_CONSTEXPR const_iterator - cbegin() const noexcept - { return const_iterator(data()); } - - _GLIBCXX17_CONSTEXPR const_iterator - cend() const noexcept - { return const_iterator(data() + _Nm); } - - _GLIBCXX17_CONSTEXPR const_reverse_iterator - crbegin() const noexcept - { return const_reverse_iterator(end()); } - - _GLIBCXX17_CONSTEXPR const_reverse_iterator - crend() const noexcept - { return const_reverse_iterator(begin()); } - - // Capacity. - constexpr size_type - size() const noexcept { return _Nm; } - - constexpr size_type - max_size() const noexcept { return _Nm; } - - _GLIBCXX_NODISCARD constexpr bool - empty() const noexcept { return size() == 0; } - - // Element access. - _GLIBCXX17_CONSTEXPR reference - operator[](size_type __n) noexcept - { return _AT_Type::_S_ref(_M_elems, __n); } - - constexpr const_reference - operator[](size_type __n) const noexcept - { return _AT_Type::_S_ref(_M_elems, __n); } - - _GLIBCXX17_CONSTEXPR reference - at(size_type __n) - { - if (__n >= _Nm) - std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " - ">= _Nm (which is %zu)"), - __n, _Nm); - return _AT_Type::_S_ref(_M_elems, __n); - } - - constexpr const_reference - at(size_type __n) const - { - // Result of conditional expression must be an lvalue so use - // boolean ? lvalue : (throw-expr, lvalue) - return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n) - : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " - ">= _Nm (which is %zu)"), - __n, _Nm), - _AT_Type::_S_ref(_M_elems, 0)); - } - - _GLIBCXX17_CONSTEXPR reference - front() noexcept - { return *begin(); } - - constexpr const_reference - front() const noexcept - { return _AT_Type::_S_ref(_M_elems, 0); } - - _GLIBCXX17_CONSTEXPR reference - back() noexcept - { return _Nm ? *(end() - 1) : *end(); } - - constexpr const_reference - back() const noexcept - { - return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) - : _AT_Type::_S_ref(_M_elems, 0); - } - - _GLIBCXX17_CONSTEXPR pointer - data() noexcept - { return _AT_Type::_S_ptr(_M_elems); } - - _GLIBCXX17_CONSTEXPR const_pointer - data() const noexcept - { return _AT_Type::_S_ptr(_M_elems); } - }; - -#if __cpp_deduction_guides >= 201606 - template - array(_Tp, _Up...) - -> array && ...), _Tp>, - 1 + sizeof...(_Up)>; -#endif - - // Array comparisons. - template - _GLIBCXX20_CONSTEXPR - inline bool - operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) - { return std::equal(__one.begin(), __one.end(), __two.begin()); } - -#if __cpp_lib_three_way_comparison && __cpp_lib_concepts - template - constexpr __detail::__synth3way_t<_Tp> - operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) - { -#ifdef __cpp_lib_is_constant_evaluated - if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value) - if (!std::is_constant_evaluated()) - { - constexpr size_t __n = _Nm * sizeof(_Tp); - return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0; - } -#endif - - for (size_t __i = 0; __i < _Nm; ++__i) - { - auto __c = __detail::__synth3way(__a[__i], __b[__i]); - if (__c != 0) - return __c; - } - return strong_ordering::equal; - } -#else - template - _GLIBCXX20_CONSTEXPR - inline bool - operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) - { return !(__one == __two); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) - { - return std::lexicographical_compare(__a.begin(), __a.end(), - __b.begin(), __b.end()); - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) - { return __two < __one; } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) - { return !(__one > __two); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) - { return !(__one < __two); } -#endif // three_way_comparison && concepts - - // Specialized algorithms. - template - _GLIBCXX20_CONSTEXPR - inline -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - // Constrained free swap overload, see p0185r1 - typename enable_if< - _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value - >::type -#else - void -#endif - swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) - noexcept(noexcept(__one.swap(__two))) - { __one.swap(__two); } - -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - template - typename enable_if< - !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type - swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete; -#endif - - template - constexpr _Tp& - get(array<_Tp, _Nm>& __arr) noexcept - { - static_assert(_Int < _Nm, "array index is within bounds"); - return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: - _S_ref(__arr._M_elems, _Int); - } - - template - constexpr _Tp&& - get(array<_Tp, _Nm>&& __arr) noexcept - { - static_assert(_Int < _Nm, "array index is within bounds"); - return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); - } - - template - constexpr const _Tp& - get(const array<_Tp, _Nm>& __arr) noexcept - { - static_assert(_Int < _Nm, "array index is within bounds"); - return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: - _S_ref(__arr._M_elems, _Int); - } - - template - constexpr const _Tp&& - get(const array<_Tp, _Nm>&& __arr) noexcept - { - static_assert(_Int < _Nm, "array index is within bounds"); - return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); - } - -#if __cplusplus > 201703L -#define __cpp_lib_to_array 201907L - - template - constexpr array, sizeof...(_Idx)> - __to_array(_Tp (&__a)[sizeof...(_Idx)], index_sequence<_Idx...>) - { - if constexpr (_Move) - return {{std::move(__a[_Idx])...}}; - else - return {{__a[_Idx]...}}; - } - - template - constexpr array, _Nm> - to_array(_Tp (&__a)[_Nm]) - noexcept(is_nothrow_constructible_v<_Tp, _Tp&>) - { - static_assert(!is_array_v<_Tp>); - static_assert(is_constructible_v<_Tp, _Tp&>); - if constexpr (is_constructible_v<_Tp, _Tp&>) - return _GLIBCXX_STD_C::__to_array(__a, make_index_sequence<_Nm>{}); - __builtin_unreachable(); // FIXME: see PR c++/91388 - } - - template - constexpr array, _Nm> - to_array(_Tp (&&__a)[_Nm]) - noexcept(is_nothrow_move_constructible_v<_Tp>) - { - static_assert(!is_array_v<_Tp>); - static_assert(is_move_constructible_v<_Tp>); - if constexpr (is_move_constructible_v<_Tp>) - return _GLIBCXX_STD_C::__to_array<1>(__a, make_index_sequence<_Nm>{}); - __builtin_unreachable(); // FIXME: see PR c++/91388 - } -#endif // C++20 - -_GLIBCXX_END_NAMESPACE_CONTAINER -} // namespace std - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Tuple interface to class template array. - - /// tuple_size - template - struct tuple_size; - - /// Partial specialization for std::array - template - struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>> - : public integral_constant { }; - - /// tuple_element - template - struct tuple_element; - - /// Partial specialization for std::array - template - struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>> - { - static_assert(_Int < _Nm, "index is out of bounds"); - typedef _Tp type; - }; - - template - struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type - { }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#ifdef _GLIBCXX_DEBUG -# include +// Minimal for AVR +#ifndef _AVR_ARRAY +#define _AVR_ARRAY +#include + +namespace std { + template + struct array { + T _data[N]; + + using value_type = T; + using size_type = size_t; + using reference = T&; + using const_reference = const T&; + using iterator = T*; + using const_iterator = const T*; + + constexpr reference operator[](size_type i) noexcept { return _data[i]; } + constexpr const_reference operator[](size_type i) const noexcept { return _data[i]; } + constexpr reference at(size_type i) { return _data[i]; } + constexpr const_reference at(size_type i) const { return _data[i]; } + constexpr reference front() noexcept { return _data[0]; } + constexpr const_reference front() const noexcept { return _data[0]; } + constexpr reference back() noexcept { return _data[N - 1]; } + constexpr const_reference back() const noexcept { return _data[N - 1]; } + constexpr T* data() noexcept { return _data; } + constexpr const T* data() const noexcept { return _data; } + constexpr iterator begin() noexcept { return _data; } + constexpr const_iterator begin() const noexcept { return _data; } + constexpr iterator end() noexcept { return _data + N; } + constexpr const_iterator end() const noexcept { return _data + N; } + constexpr size_type size() const noexcept { return N; } + constexpr bool empty() const noexcept { return N == 0; } + void fill(const T& value) { for (size_type i = 0; i < N; ++i) _data[i] = value; } + }; +} #endif - -#endif // C++11 - -#endif // _GLIBCXX_ARRAY diff --git a/resources/sources/avr-libstdcpp/include/atomic b/resources/sources/avr-libstdcpp/include/atomic deleted file mode 100644 index a455286a7..000000000 --- a/resources/sources/avr-libstdcpp/include/atomic +++ /dev/null @@ -1,1552 +0,0 @@ -// -*- C++ -*- header. - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/atomic - * This is a Standard C++ Library header. - */ - -// Based on "C++ Atomic Types and Operations" by Hans Boehm and Lawrence Crowl. -// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html - -#ifndef _GLIBCXX_ATOMIC -#define _GLIBCXX_ATOMIC 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup atomics - * @{ - */ - -#if __cplusplus >= 201703L -# define __cpp_lib_atomic_is_always_lock_free 201603 -#endif - - template - struct atomic; - - /// atomic - // NB: No operators or fetch-operations for this type. - template<> - struct atomic - { - using value_type = bool; - - private: - __atomic_base _M_base; - - public: - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(bool __i) noexcept : _M_base(__i) { } - - bool - operator=(bool __i) noexcept - { return _M_base.operator=(__i); } - - bool - operator=(bool __i) volatile noexcept - { return _M_base.operator=(__i); } - - operator bool() const noexcept - { return _M_base.load(); } - - operator bool() const volatile noexcept - { return _M_base.load(); } - - bool - is_lock_free() const noexcept { return _M_base.is_lock_free(); } - - bool - is_lock_free() const volatile noexcept { return _M_base.is_lock_free(); } - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2; -#endif - - void - store(bool __i, memory_order __m = memory_order_seq_cst) noexcept - { _M_base.store(__i, __m); } - - void - store(bool __i, memory_order __m = memory_order_seq_cst) volatile noexcept - { _M_base.store(__i, __m); } - - bool - load(memory_order __m = memory_order_seq_cst) const noexcept - { return _M_base.load(__m); } - - bool - load(memory_order __m = memory_order_seq_cst) const volatile noexcept - { return _M_base.load(__m); } - - bool - exchange(bool __i, memory_order __m = memory_order_seq_cst) noexcept - { return _M_base.exchange(__i, __m); } - - bool - exchange(bool __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return _M_base.exchange(__i, __m); } - - bool - compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, - memory_order __m2) noexcept - { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } - - bool - compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, - memory_order __m2) volatile noexcept - { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } - - bool - compare_exchange_weak(bool& __i1, bool __i2, - memory_order __m = memory_order_seq_cst) noexcept - { return _M_base.compare_exchange_weak(__i1, __i2, __m); } - - bool - compare_exchange_weak(bool& __i1, bool __i2, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return _M_base.compare_exchange_weak(__i1, __i2, __m); } - - bool - compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, - memory_order __m2) noexcept - { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } - - bool - compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, - memory_order __m2) volatile noexcept - { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } - - bool - compare_exchange_strong(bool& __i1, bool __i2, - memory_order __m = memory_order_seq_cst) noexcept - { return _M_base.compare_exchange_strong(__i1, __i2, __m); } - - bool - compare_exchange_strong(bool& __i1, bool __i2, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return _M_base.compare_exchange_strong(__i1, __i2, __m); } - }; - -#if __cplusplus <= 201703L -# define _GLIBCXX20_INIT(I) -#else -# define _GLIBCXX20_INIT(I) = I -#endif - - /** - * @brief Generic atomic type, primary class template. - * - * @tparam _Tp Type to be made atomic, must be trivially copyable. - */ - template - struct atomic - { - using value_type = _Tp; - - private: - // Align 1/2/4/8/16-byte types to at least their size. - static constexpr int _S_min_alignment - = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 - ? 0 : sizeof(_Tp); - - static constexpr int _S_alignment - = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); - - alignas(_S_alignment) _Tp _M_i _GLIBCXX20_INIT(_Tp()); - - static_assert(__is_trivially_copyable(_Tp), - "std::atomic requires a trivially copyable type"); - - static_assert(sizeof(_Tp) > 0, - "Incomplete or zero-sized types are not supported"); - - public: - atomic() = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(_Tp __i) noexcept : _M_i(__i) { } - - operator _Tp() const noexcept - { return load(); } - - operator _Tp() const volatile noexcept - { return load(); } - - _Tp - operator=(_Tp __i) noexcept - { store(__i); return __i; } - - _Tp - operator=(_Tp __i) volatile noexcept - { store(__i); return __i; } - - bool - is_lock_free() const noexcept - { - // Produce a fake, minimally aligned pointer. - return __atomic_is_lock_free(sizeof(_M_i), - reinterpret_cast(-_S_alignment)); - } - - bool - is_lock_free() const volatile noexcept - { - // Produce a fake, minimally aligned pointer. - return __atomic_is_lock_free(sizeof(_M_i), - reinterpret_cast(-_S_alignment)); - } - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free - = __atomic_always_lock_free(sizeof(_M_i), 0); -#endif - - void - store(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept - { __atomic_store(std::__addressof(_M_i), std::__addressof(__i), int(__m)); } - - void - store(_Tp __i, memory_order __m = memory_order_seq_cst) volatile noexcept - { __atomic_store(std::__addressof(_M_i), std::__addressof(__i), int(__m)); } - - _Tp - load(memory_order __m = memory_order_seq_cst) const noexcept - { - alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; - _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); - __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); - return *__ptr; - } - - _Tp - load(memory_order __m = memory_order_seq_cst) const volatile noexcept - { - alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; - _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); - __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); - return *__ptr; - } - - _Tp - exchange(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept - { - alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; - _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); - __atomic_exchange(std::__addressof(_M_i), std::__addressof(__i), - __ptr, int(__m)); - return *__ptr; - } - - _Tp - exchange(_Tp __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; - _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); - __atomic_exchange(std::__addressof(_M_i), std::__addressof(__i), - __ptr, int(__m)); - return *__ptr; - } - - bool - compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, - memory_order __f) noexcept - { - return __atomic_compare_exchange(std::__addressof(_M_i), - std::__addressof(__e), - std::__addressof(__i), - true, int(__s), int(__f)); - } - - bool - compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, - memory_order __f) volatile noexcept - { - return __atomic_compare_exchange(std::__addressof(_M_i), - std::__addressof(__e), - std::__addressof(__i), - true, int(__s), int(__f)); - } - - bool - compare_exchange_weak(_Tp& __e, _Tp __i, - memory_order __m = memory_order_seq_cst) noexcept - { return compare_exchange_weak(__e, __i, __m, - __cmpexch_failure_order(__m)); } - - bool - compare_exchange_weak(_Tp& __e, _Tp __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return compare_exchange_weak(__e, __i, __m, - __cmpexch_failure_order(__m)); } - - bool - compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, - memory_order __f) noexcept - { - return __atomic_compare_exchange(std::__addressof(_M_i), - std::__addressof(__e), - std::__addressof(__i), - false, int(__s), int(__f)); - } - - bool - compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, - memory_order __f) volatile noexcept - { - return __atomic_compare_exchange(std::__addressof(_M_i), - std::__addressof(__e), - std::__addressof(__i), - false, int(__s), int(__f)); - } - - bool - compare_exchange_strong(_Tp& __e, _Tp __i, - memory_order __m = memory_order_seq_cst) noexcept - { return compare_exchange_strong(__e, __i, __m, - __cmpexch_failure_order(__m)); } - - bool - compare_exchange_strong(_Tp& __e, _Tp __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return compare_exchange_strong(__e, __i, __m, - __cmpexch_failure_order(__m)); } - }; -#undef _GLIBCXX20_INIT - - /// Partial specialization for pointer types. - template - struct atomic<_Tp*> - { - using value_type = _Tp*; - using difference_type = ptrdiff_t; - - typedef _Tp* __pointer_type; - typedef __atomic_base<_Tp*> __base_type; - __base_type _M_b; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__pointer_type __p) noexcept : _M_b(__p) { } - - operator __pointer_type() const noexcept - { return __pointer_type(_M_b); } - - operator __pointer_type() const volatile noexcept - { return __pointer_type(_M_b); } - - __pointer_type - operator=(__pointer_type __p) noexcept - { return _M_b.operator=(__p); } - - __pointer_type - operator=(__pointer_type __p) volatile noexcept - { return _M_b.operator=(__p); } - - __pointer_type - operator++(int) noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b++; - } - - __pointer_type - operator++(int) volatile noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b++; - } - - __pointer_type - operator--(int) noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b--; - } - - __pointer_type - operator--(int) volatile noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b--; - } - - __pointer_type - operator++() noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return ++_M_b; - } - - __pointer_type - operator++() volatile noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return ++_M_b; - } - - __pointer_type - operator--() noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return --_M_b; - } - - __pointer_type - operator--() volatile noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return --_M_b; - } - - __pointer_type - operator+=(ptrdiff_t __d) noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b.operator+=(__d); - } - - __pointer_type - operator+=(ptrdiff_t __d) volatile noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b.operator+=(__d); - } - - __pointer_type - operator-=(ptrdiff_t __d) noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b.operator-=(__d); - } - - __pointer_type - operator-=(ptrdiff_t __d) volatile noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b.operator-=(__d); - } - - bool - is_lock_free() const noexcept - { return _M_b.is_lock_free(); } - - bool - is_lock_free() const volatile noexcept - { return _M_b.is_lock_free(); } - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; -#endif - - void - store(__pointer_type __p, - memory_order __m = memory_order_seq_cst) noexcept - { return _M_b.store(__p, __m); } - - void - store(__pointer_type __p, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return _M_b.store(__p, __m); } - - __pointer_type - load(memory_order __m = memory_order_seq_cst) const noexcept - { return _M_b.load(__m); } - - __pointer_type - load(memory_order __m = memory_order_seq_cst) const volatile noexcept - { return _M_b.load(__m); } - - __pointer_type - exchange(__pointer_type __p, - memory_order __m = memory_order_seq_cst) noexcept - { return _M_b.exchange(__p, __m); } - - __pointer_type - exchange(__pointer_type __p, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return _M_b.exchange(__p, __m); } - - bool - compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, - memory_order __m1, memory_order __m2) noexcept - { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } - - bool - compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, - memory_order __m1, - memory_order __m2) volatile noexcept - { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } - - bool - compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, - memory_order __m = memory_order_seq_cst) noexcept - { - return compare_exchange_weak(__p1, __p2, __m, - __cmpexch_failure_order(__m)); - } - - bool - compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - return compare_exchange_weak(__p1, __p2, __m, - __cmpexch_failure_order(__m)); - } - - bool - compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, - memory_order __m1, memory_order __m2) noexcept - { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } - - bool - compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, - memory_order __m1, - memory_order __m2) volatile noexcept - { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } - - bool - compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, - memory_order __m = memory_order_seq_cst) noexcept - { - return _M_b.compare_exchange_strong(__p1, __p2, __m, - __cmpexch_failure_order(__m)); - } - - bool - compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - return _M_b.compare_exchange_strong(__p1, __p2, __m, - __cmpexch_failure_order(__m)); - } - - __pointer_type - fetch_add(ptrdiff_t __d, - memory_order __m = memory_order_seq_cst) noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b.fetch_add(__d, __m); - } - - __pointer_type - fetch_add(ptrdiff_t __d, - memory_order __m = memory_order_seq_cst) volatile noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b.fetch_add(__d, __m); - } - - __pointer_type - fetch_sub(ptrdiff_t __d, - memory_order __m = memory_order_seq_cst) noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b.fetch_sub(__d, __m); - } - - __pointer_type - fetch_sub(ptrdiff_t __d, - memory_order __m = memory_order_seq_cst) volatile noexcept - { -#if __cplusplus >= 201703L - static_assert( is_object<_Tp>::value, "pointer to object type" ); -#endif - return _M_b.fetch_sub(__d, __m); - } - }; - - - /// Explicit specialization for char. - template<> - struct atomic : __atomic_base - { - typedef char __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for signed char. - template<> - struct atomic : __atomic_base - { - typedef signed char __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept= default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for unsigned char. - template<> - struct atomic : __atomic_base - { - typedef unsigned char __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept= default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for short. - template<> - struct atomic : __atomic_base - { - typedef short __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for unsigned short. - template<> - struct atomic : __atomic_base - { - typedef unsigned short __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for int. - template<> - struct atomic : __atomic_base - { - typedef int __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for unsigned int. - template<> - struct atomic : __atomic_base - { - typedef unsigned int __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for long. - template<> - struct atomic : __atomic_base - { - typedef long __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for unsigned long. - template<> - struct atomic : __atomic_base - { - typedef unsigned long __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for long long. - template<> - struct atomic : __atomic_base - { - typedef long long __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for unsigned long long. - template<> - struct atomic : __atomic_base - { - typedef unsigned long long __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for wchar_t. - template<> - struct atomic : __atomic_base - { - typedef wchar_t __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_WCHAR_T_LOCK_FREE == 2; -#endif - }; - -#ifdef _GLIBCXX_USE_CHAR8_T - /// Explicit specialization for char8_t. - template<> - struct atomic : __atomic_base - { - typedef char8_t __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus > 201402L - static constexpr bool is_always_lock_free = ATOMIC_CHAR8_T_LOCK_FREE == 2; -#endif - }; -#endif - - /// Explicit specialization for char16_t. - template<> - struct atomic : __atomic_base - { - typedef char16_t __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_CHAR16_T_LOCK_FREE == 2; -#endif - }; - - /// Explicit specialization for char32_t. - template<> - struct atomic : __atomic_base - { - typedef char32_t __integral_type; - typedef __atomic_base __base_type; - - atomic() noexcept = default; - ~atomic() noexcept = default; - atomic(const atomic&) = delete; - atomic& operator=(const atomic&) = delete; - atomic& operator=(const atomic&) volatile = delete; - - constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } - - using __base_type::operator __integral_type; - using __base_type::operator=; - -#if __cplusplus >= 201703L - static constexpr bool is_always_lock_free = ATOMIC_CHAR32_T_LOCK_FREE == 2; -#endif - }; - - - /// atomic_bool - typedef atomic atomic_bool; - - /// atomic_char - typedef atomic atomic_char; - - /// atomic_schar - typedef atomic atomic_schar; - - /// atomic_uchar - typedef atomic atomic_uchar; - - /// atomic_short - typedef atomic atomic_short; - - /// atomic_ushort - typedef atomic atomic_ushort; - - /// atomic_int - typedef atomic atomic_int; - - /// atomic_uint - typedef atomic atomic_uint; - - /// atomic_long - typedef atomic atomic_long; - - /// atomic_ulong - typedef atomic atomic_ulong; - - /// atomic_llong - typedef atomic atomic_llong; - - /// atomic_ullong - typedef atomic atomic_ullong; - - /// atomic_wchar_t - typedef atomic atomic_wchar_t; - -#ifdef _GLIBCXX_USE_CHAR8_T - /// atomic_char8_t - typedef atomic atomic_char8_t; -#endif - - /// atomic_char16_t - typedef atomic atomic_char16_t; - - /// atomic_char32_t - typedef atomic atomic_char32_t; - -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2441. Exact-width atomic typedefs should be provided - - /// atomic_int8_t - typedef atomic atomic_int8_t; - - /// atomic_uint8_t - typedef atomic atomic_uint8_t; - - /// atomic_int16_t - typedef atomic atomic_int16_t; - - /// atomic_uint16_t - typedef atomic atomic_uint16_t; - - /// atomic_int32_t - typedef atomic atomic_int32_t; - - /// atomic_uint32_t - typedef atomic atomic_uint32_t; - - /// atomic_int64_t - typedef atomic atomic_int64_t; - - /// atomic_uint64_t - typedef atomic atomic_uint64_t; - - - /// atomic_int_least8_t - typedef atomic atomic_int_least8_t; - - /// atomic_uint_least8_t - typedef atomic atomic_uint_least8_t; - - /// atomic_int_least16_t - typedef atomic atomic_int_least16_t; - - /// atomic_uint_least16_t - typedef atomic atomic_uint_least16_t; - - /// atomic_int_least32_t - typedef atomic atomic_int_least32_t; - - /// atomic_uint_least32_t - typedef atomic atomic_uint_least32_t; - - /// atomic_int_least64_t - typedef atomic atomic_int_least64_t; - - /// atomic_uint_least64_t - typedef atomic atomic_uint_least64_t; - - - /// atomic_int_fast8_t - typedef atomic atomic_int_fast8_t; - - /// atomic_uint_fast8_t - typedef atomic atomic_uint_fast8_t; - - /// atomic_int_fast16_t - typedef atomic atomic_int_fast16_t; - - /// atomic_uint_fast16_t - typedef atomic atomic_uint_fast16_t; - - /// atomic_int_fast32_t - typedef atomic atomic_int_fast32_t; - - /// atomic_uint_fast32_t - typedef atomic atomic_uint_fast32_t; - - /// atomic_int_fast64_t - typedef atomic atomic_int_fast64_t; - - /// atomic_uint_fast64_t - typedef atomic atomic_uint_fast64_t; -#endif - - - /// atomic_intptr_t - typedef atomic atomic_intptr_t; - - /// atomic_uintptr_t - typedef atomic atomic_uintptr_t; - - /// atomic_size_t - typedef atomic atomic_size_t; - - /// atomic_ptrdiff_t - typedef atomic atomic_ptrdiff_t; - -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - /// atomic_intmax_t - typedef atomic atomic_intmax_t; - - /// atomic_uintmax_t - typedef atomic atomic_uintmax_t; -#endif - - // Function definitions, atomic_flag operations. - inline bool - atomic_flag_test_and_set_explicit(atomic_flag* __a, - memory_order __m) noexcept - { return __a->test_and_set(__m); } - - inline bool - atomic_flag_test_and_set_explicit(volatile atomic_flag* __a, - memory_order __m) noexcept - { return __a->test_and_set(__m); } - - inline void - atomic_flag_clear_explicit(atomic_flag* __a, memory_order __m) noexcept - { __a->clear(__m); } - - inline void - atomic_flag_clear_explicit(volatile atomic_flag* __a, - memory_order __m) noexcept - { __a->clear(__m); } - - inline bool - atomic_flag_test_and_set(atomic_flag* __a) noexcept - { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } - - inline bool - atomic_flag_test_and_set(volatile atomic_flag* __a) noexcept - { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } - - inline void - atomic_flag_clear(atomic_flag* __a) noexcept - { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } - - inline void - atomic_flag_clear(volatile atomic_flag* __a) noexcept - { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } - - - template - using __atomic_val_t = typename atomic<_Tp>::value_type; - template - using __atomic_diff_t = typename atomic<_Tp>::difference_type; - - // [atomics.nonmembers] Non-member functions. - // Function templates generally applicable to atomic types. - template - inline bool - atomic_is_lock_free(const atomic<_ITp>* __a) noexcept - { return __a->is_lock_free(); } - - template - inline bool - atomic_is_lock_free(const volatile atomic<_ITp>* __a) noexcept - { return __a->is_lock_free(); } - - template - inline void - atomic_init(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept - { __a->store(__i, memory_order_relaxed); } - - template - inline void - atomic_init(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept - { __a->store(__i, memory_order_relaxed); } - - template - inline void - atomic_store_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { __a->store(__i, __m); } - - template - inline void - atomic_store_explicit(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { __a->store(__i, __m); } - - template - inline _ITp - atomic_load_explicit(const atomic<_ITp>* __a, memory_order __m) noexcept - { return __a->load(__m); } - - template - inline _ITp - atomic_load_explicit(const volatile atomic<_ITp>* __a, - memory_order __m) noexcept - { return __a->load(__m); } - - template - inline _ITp - atomic_exchange_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { return __a->exchange(__i, __m); } - - template - inline _ITp - atomic_exchange_explicit(volatile atomic<_ITp>* __a, - __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { return __a->exchange(__i, __m); } - - template - inline bool - atomic_compare_exchange_weak_explicit(atomic<_ITp>* __a, - __atomic_val_t<_ITp>* __i1, - __atomic_val_t<_ITp> __i2, - memory_order __m1, - memory_order __m2) noexcept - { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } - - template - inline bool - atomic_compare_exchange_weak_explicit(volatile atomic<_ITp>* __a, - __atomic_val_t<_ITp>* __i1, - __atomic_val_t<_ITp> __i2, - memory_order __m1, - memory_order __m2) noexcept - { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } - - template - inline bool - atomic_compare_exchange_strong_explicit(atomic<_ITp>* __a, - __atomic_val_t<_ITp>* __i1, - __atomic_val_t<_ITp> __i2, - memory_order __m1, - memory_order __m2) noexcept - { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } - - template - inline bool - atomic_compare_exchange_strong_explicit(volatile atomic<_ITp>* __a, - __atomic_val_t<_ITp>* __i1, - __atomic_val_t<_ITp> __i2, - memory_order __m1, - memory_order __m2) noexcept - { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } - - - template - inline void - atomic_store(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept - { atomic_store_explicit(__a, __i, memory_order_seq_cst); } - - template - inline void - atomic_store(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept - { atomic_store_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_load(const atomic<_ITp>* __a) noexcept - { return atomic_load_explicit(__a, memory_order_seq_cst); } - - template - inline _ITp - atomic_load(const volatile atomic<_ITp>* __a) noexcept - { return atomic_load_explicit(__a, memory_order_seq_cst); } - - template - inline _ITp - atomic_exchange(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept - { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_exchange(volatile atomic<_ITp>* __a, - __atomic_val_t<_ITp> __i) noexcept - { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } - - template - inline bool - atomic_compare_exchange_weak(atomic<_ITp>* __a, - __atomic_val_t<_ITp>* __i1, - __atomic_val_t<_ITp> __i2) noexcept - { - return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, - memory_order_seq_cst, - memory_order_seq_cst); - } - - template - inline bool - atomic_compare_exchange_weak(volatile atomic<_ITp>* __a, - __atomic_val_t<_ITp>* __i1, - __atomic_val_t<_ITp> __i2) noexcept - { - return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, - memory_order_seq_cst, - memory_order_seq_cst); - } - - template - inline bool - atomic_compare_exchange_strong(atomic<_ITp>* __a, - __atomic_val_t<_ITp>* __i1, - __atomic_val_t<_ITp> __i2) noexcept - { - return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, - memory_order_seq_cst, - memory_order_seq_cst); - } - - template - inline bool - atomic_compare_exchange_strong(volatile atomic<_ITp>* __a, - __atomic_val_t<_ITp>* __i1, - __atomic_val_t<_ITp> __i2) noexcept - { - return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, - memory_order_seq_cst, - memory_order_seq_cst); - } - - // Function templates for atomic_integral and atomic_pointer operations only. - // Some operations (and, or, xor) are only available for atomic integrals, - // which is implemented by taking a parameter of type __atomic_base<_ITp>*. - - template - inline _ITp - atomic_fetch_add_explicit(atomic<_ITp>* __a, - __atomic_diff_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_add(__i, __m); } - - template - inline _ITp - atomic_fetch_add_explicit(volatile atomic<_ITp>* __a, - __atomic_diff_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_add(__i, __m); } - - template - inline _ITp - atomic_fetch_sub_explicit(atomic<_ITp>* __a, - __atomic_diff_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_sub(__i, __m); } - - template - inline _ITp - atomic_fetch_sub_explicit(volatile atomic<_ITp>* __a, - __atomic_diff_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_sub(__i, __m); } - - template - inline _ITp - atomic_fetch_and_explicit(__atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_and(__i, __m); } - - template - inline _ITp - atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_and(__i, __m); } - - template - inline _ITp - atomic_fetch_or_explicit(__atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_or(__i, __m); } - - template - inline _ITp - atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_or(__i, __m); } - - template - inline _ITp - atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_xor(__i, __m); } - - template - inline _ITp - atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i, - memory_order __m) noexcept - { return __a->fetch_xor(__i, __m); } - - template - inline _ITp - atomic_fetch_add(atomic<_ITp>* __a, - __atomic_diff_t<_ITp> __i) noexcept - { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_add(volatile atomic<_ITp>* __a, - __atomic_diff_t<_ITp> __i) noexcept - { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_sub(atomic<_ITp>* __a, - __atomic_diff_t<_ITp> __i) noexcept - { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_sub(volatile atomic<_ITp>* __a, - __atomic_diff_t<_ITp> __i) noexcept - { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_and(__atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i) noexcept - { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_and(volatile __atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i) noexcept - { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_or(__atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i) noexcept - { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_or(volatile __atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i) noexcept - { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_xor(__atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i) noexcept - { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } - - template - inline _ITp - atomic_fetch_xor(volatile __atomic_base<_ITp>* __a, - __atomic_val_t<_ITp> __i) noexcept - { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } - -#if __cplusplus > 201703L -#define __cpp_lib_atomic_float 201711L - template<> - struct atomic : __atomic_float - { - atomic() noexcept = default; - - constexpr - atomic(float __fp) noexcept : __atomic_float(__fp) - { } - - atomic& operator=(const atomic&) volatile = delete; - atomic& operator=(const atomic&) = delete; - - using __atomic_float::operator=; - }; - - template<> - struct atomic : __atomic_float - { - atomic() noexcept = default; - - constexpr - atomic(double __fp) noexcept : __atomic_float(__fp) - { } - - atomic& operator=(const atomic&) volatile = delete; - atomic& operator=(const atomic&) = delete; - - using __atomic_float::operator=; - }; - - template<> - struct atomic : __atomic_float - { - atomic() noexcept = default; - - constexpr - atomic(long double __fp) noexcept : __atomic_float(__fp) - { } - - atomic& operator=(const atomic&) volatile = delete; - atomic& operator=(const atomic&) = delete; - - using __atomic_float::operator=; - }; - -#define __cpp_lib_atomic_ref 201806L - - /// Class template to provide atomic operations on a non-atomic variable. - template - struct atomic_ref : __atomic_ref<_Tp> - { - explicit - atomic_ref(_Tp& __t) noexcept : __atomic_ref<_Tp>(__t) - { } - - atomic_ref& operator=(const atomic_ref&) = delete; - - atomic_ref(const atomic_ref&) = default; - - using __atomic_ref<_Tp>::operator=; - }; - -#endif // C++2a - - // @} group atomics - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 - -#endif // _GLIBCXX_ATOMIC diff --git a/resources/sources/avr-libstdcpp/include/backward/backward_warning.h b/resources/sources/avr-libstdcpp/include/backward/backward_warning.h deleted file mode 100644 index 94347de40..000000000 --- a/resources/sources/avr-libstdcpp/include/backward/backward_warning.h +++ /dev/null @@ -1,56 +0,0 @@ -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file backward/backward_warning.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iosfwd} - */ - -#ifndef _BACKWARD_BACKWARD_WARNING_H -#define _BACKWARD_BACKWARD_WARNING_H 1 - -#ifdef __DEPRECATED -#warning \ - This file includes at least one deprecated or antiquated header which \ - may be removed without further notice at a future date. Please use a \ - non-deprecated interface with equivalent functionality instead. For a \ - listing of replacement headers and interfaces, consult the file \ - backward_warning.h. To disable this warning use -Wno-deprecated. - -/* - A list of valid replacements is as follows: - - Use: Instead of: - , unordered_set , hash_set - , unordered_multiset , hash_multiset - , unordered_map , hash_map - , unordered_multimap , hash_multimap - , bind , binder1st - , bind , binder2nd - , bind , bind1st - , bind , bind2nd - , unique_ptr , auto_ptr -*/ - -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/binders.h b/resources/sources/avr-libstdcpp/include/backward/binders.h deleted file mode 100644 index 8c2c00d78..000000000 --- a/resources/sources/avr-libstdcpp/include/backward/binders.h +++ /dev/null @@ -1,182 +0,0 @@ -// Functor implementations -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996-1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file backward/binders.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _BACKWARD_BINDERS_H -#define _BACKWARD_BINDERS_H 1 - -// Suppress deprecated warning for this file. -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // 20.3.6 binders - /** @defgroup binders Binder Classes - * @ingroup functors - * - * Binders turn functions/functors with two arguments into functors - * with a single argument, storing an argument to be applied later. - * For example, a variable @c B of type @c binder1st is constructed - * from a functor @c f and an argument @c x. Later, B's @c - * operator() is called with a single argument @c y. The return - * value is the value of @c f(x,y). @c B can be @a called with - * various arguments (y1, y2, ...) and will in turn call @c - * f(x,y1), @c f(x,y2), ... - * - * The function @c bind1st is provided to save some typing. It takes the - * function and an argument as parameters, and returns an instance of - * @c binder1st. - * - * The type @c binder2nd and its creator function @c bind2nd do the same - * thing, but the stored argument is passed as the second parameter instead - * of the first, e.g., @c bind2nd(std::minus(),1.3) will create a - * functor whose @c operator() accepts a floating-point number, subtracts - * 1.3 from it, and returns the result. (If @c bind1st had been used, - * the functor would perform 1.3 - x instead. - * - * Creator-wrapper functions like @c bind1st are intended to be used in - * calling algorithms. Their return values will be temporary objects. - * (The goal is to not require you to type names like - * @c std::binder1st> for declaring a variable to hold the - * return value from @c bind1st(std::plus(),5). - * - * These become more useful when combined with the composition functions. - * - * These functions are deprecated in C++11 and can be replaced by - * @c std::bind (or @c std::tr1::bind) which is more powerful and flexible, - * supporting functions with any number of arguments. Uses of @c bind1st - * can be replaced by @c std::bind(f, x, std::placeholders::_1) and - * @c bind2nd by @c std::bind(f, std::placeholders::_1, x). - * @{ - */ - /// One of the @link binders binder functors@endlink. - template - class binder1st - : public unary_function - { - protected: - _Operation op; - typename _Operation::first_argument_type value; - - public: - binder1st(const _Operation& __x, - const typename _Operation::first_argument_type& __y) - : op(__x), value(__y) { } - - typename _Operation::result_type - operator()(const typename _Operation::second_argument_type& __x) const - { return op(value, __x); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 109. Missing binders for non-const sequence elements - typename _Operation::result_type - operator()(typename _Operation::second_argument_type& __x) const - { return op(value, __x); } - } _GLIBCXX_DEPRECATED; - - /// One of the @link binders binder functors@endlink. - template - inline binder1st<_Operation> - bind1st(const _Operation& __fn, const _Tp& __x) - { - typedef typename _Operation::first_argument_type _Arg1_type; - return binder1st<_Operation>(__fn, _Arg1_type(__x)); - } - - /// One of the @link binders binder functors@endlink. - template - class binder2nd - : public unary_function - { - protected: - _Operation op; - typename _Operation::second_argument_type value; - - public: - binder2nd(const _Operation& __x, - const typename _Operation::second_argument_type& __y) - : op(__x), value(__y) { } - - typename _Operation::result_type - operator()(const typename _Operation::first_argument_type& __x) const - { return op(__x, value); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 109. Missing binders for non-const sequence elements - typename _Operation::result_type - operator()(typename _Operation::first_argument_type& __x) const - { return op(__x, value); } - } _GLIBCXX_DEPRECATED; - - /// One of the @link binders binder functors@endlink. - template - inline binder2nd<_Operation> - bind2nd(const _Operation& __fn, const _Tp& __x) - { - typedef typename _Operation::second_argument_type _Arg2_type; - return binder2nd<_Operation>(__fn, _Arg2_type(__x)); - } - /** @} */ - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#pragma GCC diagnostic pop - -#endif /* _BACKWARD_BINDERS_H */ diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_fun.h b/resources/sources/avr-libstdcpp/include/backward/hash_fun.h deleted file mode 100644 index 5d19f979a..000000000 --- a/resources/sources/avr-libstdcpp/include/backward/hash_fun.h +++ /dev/null @@ -1,170 +0,0 @@ -// 'struct hash' from SGI -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1996-1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file backward/hash_fun.h - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _BACKWARD_HASH_FUN_H -#define _BACKWARD_HASH_FUN_H 1 - -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using std::size_t; - - template - struct hash { }; - - inline size_t - __stl_hash_string(const char* __s) - { - unsigned long __h = 0; - for ( ; *__s; ++__s) - __h = 5 * __h + *__s; - return size_t(__h); - } - - template<> - struct hash - { - size_t - operator()(const char* __s) const - { return __stl_hash_string(__s); } - }; - - template<> - struct hash - { - size_t - operator()(const char* __s) const - { return __stl_hash_string(__s); } - }; - - template<> - struct hash - { - size_t - operator()(char __x) const - { return __x; } - }; - - template<> - struct hash - { - size_t - operator()(unsigned char __x) const - { return __x; } - }; - - template<> - struct hash - { - size_t - operator()(unsigned char __x) const - { return __x; } - }; - - template<> - struct hash - { - size_t - operator()(short __x) const - { return __x; } - }; - - template<> - struct hash - { - size_t - operator()(unsigned short __x) const - { return __x; } - }; - - template<> - struct hash - { - size_t - operator()(int __x) const - { return __x; } - }; - - template<> - struct hash - { - size_t - operator()(unsigned int __x) const - { return __x; } - }; - - template<> - struct hash - { - size_t - operator()(long __x) const - { return __x; } - }; - - template<> - struct hash - { - size_t - operator()(unsigned long __x) const - { return __x; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_map b/resources/sources/avr-libstdcpp/include/backward/hash_map deleted file mode 100644 index 93db70d56..000000000 --- a/resources/sources/avr-libstdcpp/include/backward/hash_map +++ /dev/null @@ -1,599 +0,0 @@ -// Hashing map implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file backward/hash_map - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _BACKWARD_HASH_MAP -#define _BACKWARD_HASH_MAP 1 - -#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH -#include -#endif - -#include -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using std::equal_to; - using std::allocator; - using std::pair; - using std::_Select1st; - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template, - class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> > - class hash_map - { - private: - typedef hashtable,_Key, _HashFn, - _Select1st >, - _EqualKey, _Alloc> _Ht; - - _Ht _M_ht; - - public: - typedef typename _Ht::key_type key_type; - typedef _Tp data_type; - typedef _Tp mapped_type; - typedef typename _Ht::value_type value_type; - typedef typename _Ht::hasher hasher; - typedef typename _Ht::key_equal key_equal; - - typedef typename _Ht::size_type size_type; - typedef typename _Ht::difference_type difference_type; - typedef typename _Ht::pointer pointer; - typedef typename _Ht::const_pointer const_pointer; - typedef typename _Ht::reference reference; - typedef typename _Ht::const_reference const_reference; - - typedef typename _Ht::iterator iterator; - typedef typename _Ht::const_iterator const_iterator; - - typedef typename _Ht::allocator_type allocator_type; - - hasher - hash_funct() const - { return _M_ht.hash_funct(); } - - key_equal - key_eq() const - { return _M_ht.key_eq(); } - - allocator_type - get_allocator() const - { return _M_ht.get_allocator(); } - - hash_map() - : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - - explicit - hash_map(size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - - hash_map(size_type __n, const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - - hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) {} - - template - hash_map(_InputIterator __f, _InputIterator __l) - : _M_ht(100, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) - { _M_ht.insert_unique(__f, __l); } - - size_type - size() const - { return _M_ht.size(); } - - size_type - max_size() const - { return _M_ht.max_size(); } - - _GLIBCXX_NODISCARD bool - empty() const - { return _M_ht.empty(); } - - void - swap(hash_map& __hs) - { _M_ht.swap(__hs._M_ht); } - - template - friend bool - operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&, - const hash_map<_K1, _T1, _HF, _EqK, _Al>&); - - iterator - begin() - { return _M_ht.begin(); } - - iterator - end() - { return _M_ht.end(); } - - const_iterator - begin() const - { return _M_ht.begin(); } - - const_iterator - end() const - { return _M_ht.end(); } - - pair - insert(const value_type& __obj) - { return _M_ht.insert_unique(__obj); } - - template - void - insert(_InputIterator __f, _InputIterator __l) - { _M_ht.insert_unique(__f, __l); } - - pair - insert_noresize(const value_type& __obj) - { return _M_ht.insert_unique_noresize(__obj); } - - iterator - find(const key_type& __key) - { return _M_ht.find(__key); } - - const_iterator - find(const key_type& __key) const - { return _M_ht.find(__key); } - - _Tp& - operator[](const key_type& __key) - { return _M_ht.find_or_insert(value_type(__key, _Tp())).second; } - - size_type - count(const key_type& __key) const - { return _M_ht.count(__key); } - - pair - equal_range(const key_type& __key) - { return _M_ht.equal_range(__key); } - - pair - equal_range(const key_type& __key) const - { return _M_ht.equal_range(__key); } - - size_type - erase(const key_type& __key) - {return _M_ht.erase(__key); } - - void - erase(iterator __it) - { _M_ht.erase(__it); } - - void - erase(iterator __f, iterator __l) - { _M_ht.erase(__f, __l); } - - void - clear() - { _M_ht.clear(); } - - void - resize(size_type __hint) - { _M_ht.resize(__hint); } - - size_type - bucket_count() const - { return _M_ht.bucket_count(); } - - size_type - max_bucket_count() const - { return _M_ht.max_bucket_count(); } - - size_type - elems_in_bucket(size_type __n) const - { return _M_ht.elems_in_bucket(__n); } - }; - - template - inline bool - operator==(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, - const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) - { return __hm1._M_ht == __hm2._M_ht; } - - template - inline bool - operator!=(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, - const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) - { return !(__hm1 == __hm2); } - - template - inline void - swap(hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, - hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) - { __hm1.swap(__hm2); } - - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template, - class _EqualKey = equal_to<_Key>, - class _Alloc = allocator<_Tp> > - class hash_multimap - { - // concept requirements - __glibcxx_class_requires(_Key, _SGIAssignableConcept) - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) - __glibcxx_class_requires3(_HashFn, size_t, _Key, _UnaryFunctionConcept) - __glibcxx_class_requires3(_EqualKey, _Key, _Key, _BinaryPredicateConcept) - - private: - typedef hashtable, _Key, _HashFn, - _Select1st >, _EqualKey, _Alloc> - _Ht; - - _Ht _M_ht; - - public: - typedef typename _Ht::key_type key_type; - typedef _Tp data_type; - typedef _Tp mapped_type; - typedef typename _Ht::value_type value_type; - typedef typename _Ht::hasher hasher; - typedef typename _Ht::key_equal key_equal; - - typedef typename _Ht::size_type size_type; - typedef typename _Ht::difference_type difference_type; - typedef typename _Ht::pointer pointer; - typedef typename _Ht::const_pointer const_pointer; - typedef typename _Ht::reference reference; - typedef typename _Ht::const_reference const_reference; - - typedef typename _Ht::iterator iterator; - typedef typename _Ht::const_iterator const_iterator; - - typedef typename _Ht::allocator_type allocator_type; - - hasher - hash_funct() const - { return _M_ht.hash_funct(); } - - key_equal - key_eq() const - { return _M_ht.key_eq(); } - - allocator_type - get_allocator() const - { return _M_ht.get_allocator(); } - - hash_multimap() - : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - - explicit - hash_multimap(size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - - hash_multimap(size_type __n, const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - - hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) {} - - template - hash_multimap(_InputIterator __f, _InputIterator __l) - : _M_ht(100, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) - { _M_ht.insert_equal(__f, __l); } - - size_type - size() const - { return _M_ht.size(); } - - size_type - max_size() const - { return _M_ht.max_size(); } - - _GLIBCXX_NODISCARD bool - empty() const - { return _M_ht.empty(); } - - void - swap(hash_multimap& __hs) - { _M_ht.swap(__hs._M_ht); } - - template - friend bool - operator==(const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&, - const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&); - - iterator - begin() - { return _M_ht.begin(); } - - iterator - end() - { return _M_ht.end(); } - - const_iterator - begin() const - { return _M_ht.begin(); } - - const_iterator - end() const - { return _M_ht.end(); } - - iterator - insert(const value_type& __obj) - { return _M_ht.insert_equal(__obj); } - - template - void - insert(_InputIterator __f, _InputIterator __l) - { _M_ht.insert_equal(__f,__l); } - - iterator - insert_noresize(const value_type& __obj) - { return _M_ht.insert_equal_noresize(__obj); } - - iterator - find(const key_type& __key) - { return _M_ht.find(__key); } - - const_iterator - find(const key_type& __key) const - { return _M_ht.find(__key); } - - size_type - count(const key_type& __key) const - { return _M_ht.count(__key); } - - pair - equal_range(const key_type& __key) - { return _M_ht.equal_range(__key); } - - pair - equal_range(const key_type& __key) const - { return _M_ht.equal_range(__key); } - - size_type - erase(const key_type& __key) - { return _M_ht.erase(__key); } - - void - erase(iterator __it) - { _M_ht.erase(__it); } - - void - erase(iterator __f, iterator __l) - { _M_ht.erase(__f, __l); } - - void - clear() - { _M_ht.clear(); } - - void - resize(size_type __hint) - { _M_ht.resize(__hint); } - - size_type - bucket_count() const - { return _M_ht.bucket_count(); } - - size_type - max_bucket_count() const - { return _M_ht.max_bucket_count(); } - - size_type - elems_in_bucket(size_type __n) const - { return _M_ht.elems_in_bucket(__n); } - }; - - template - inline bool - operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, - const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) - { return __hm1._M_ht == __hm2._M_ht; } - - template - inline bool - operator!=(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, - const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) - { return !(__hm1 == __hm2); } - - template - inline void - swap(hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, - hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) - { __hm1.swap(__hm2); } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Specialization of insert_iterator so that it will work for hash_map - // and hash_multimap. - template - class insert_iterator<__gnu_cxx::hash_map<_Key, _Tp, _HashFn, - _EqKey, _Alloc> > - { - protected: - typedef __gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc> - _Container; - _Container* container; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x) - : container(&__x) {} - - insert_iterator(_Container& __x, typename _Container::iterator) - : container(&__x) {} - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - container->insert(__value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() { return *this; } - - insert_iterator<_Container>& - operator++(int) - { return *this; } - }; - - template - class insert_iterator<__gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, - _EqKey, _Alloc> > - { - protected: - typedef __gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc> - _Container; - _Container* container; - typename _Container::iterator iter; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x) - : container(&__x) {} - - insert_iterator(_Container& __x, typename _Container::iterator) - : container(&__x) {} - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - container->insert(__value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() - { return *this; } - - insert_iterator<_Container>& - operator++(int) - { return *this; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_set b/resources/sources/avr-libstdcpp/include/backward/hash_set deleted file mode 100644 index 0b99302af..000000000 --- a/resources/sources/avr-libstdcpp/include/backward/hash_set +++ /dev/null @@ -1,569 +0,0 @@ -// Hashing set implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file backward/hash_set - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _BACKWARD_HASH_SET -#define _BACKWARD_HASH_SET 1 - -#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH -#include -#endif - -#include -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using std::equal_to; - using std::allocator; - using std::pair; - using std::_Identity; - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template, - class _EqualKey = equal_to<_Value>, - class _Alloc = allocator<_Value> > - class hash_set - { - // concept requirements - __glibcxx_class_requires(_Value, _SGIAssignableConcept) - __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) - __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) - - typedef __alloc_traits<_Alloc> _Alloc_traits; - - private: - typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, - _EqualKey, _Alloc> _Ht; - _Ht _M_ht; - - public: - typedef typename _Ht::key_type key_type; - typedef typename _Ht::value_type value_type; - typedef typename _Ht::hasher hasher; - typedef typename _Ht::key_equal key_equal; - - typedef typename _Ht::size_type size_type; - typedef typename _Ht::difference_type difference_type; - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; - - typedef typename _Ht::const_iterator iterator; - typedef typename _Ht::const_iterator const_iterator; - - typedef typename _Ht::allocator_type allocator_type; - - hasher - hash_funct() const - { return _M_ht.hash_funct(); } - - key_equal - key_eq() const - { return _M_ht.key_eq(); } - - allocator_type - get_allocator() const - { return _M_ht.get_allocator(); } - - hash_set() - : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - - explicit - hash_set(size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - - hash_set(size_type __n, const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - - hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) {} - - template - hash_set(_InputIterator __f, _InputIterator __l) - : _M_ht(100, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) - { _M_ht.insert_unique(__f, __l); } - - size_type - size() const - { return _M_ht.size(); } - - size_type - max_size() const - { return _M_ht.max_size(); } - - _GLIBCXX_NODISCARD bool - empty() const - { return _M_ht.empty(); } - - void - swap(hash_set& __hs) - { _M_ht.swap(__hs._M_ht); } - - template - friend bool - operator==(const hash_set<_Val, _HF, _EqK, _Al>&, - const hash_set<_Val, _HF, _EqK, _Al>&); - - iterator - begin() const - { return _M_ht.begin(); } - - iterator - end() const - { return _M_ht.end(); } - - pair - insert(const value_type& __obj) - { - pair __p = _M_ht.insert_unique(__obj); - return pair(__p.first, __p.second); - } - - template - void - insert(_InputIterator __f, _InputIterator __l) - { _M_ht.insert_unique(__f, __l); } - - pair - insert_noresize(const value_type& __obj) - { - pair __p - = _M_ht.insert_unique_noresize(__obj); - return pair(__p.first, __p.second); - } - - iterator - find(const key_type& __key) const - { return _M_ht.find(__key); } - - size_type - count(const key_type& __key) const - { return _M_ht.count(__key); } - - pair - equal_range(const key_type& __key) const - { return _M_ht.equal_range(__key); } - - size_type - erase(const key_type& __key) - {return _M_ht.erase(__key); } - - void - erase(iterator __it) - { _M_ht.erase(__it); } - - void - erase(iterator __f, iterator __l) - { _M_ht.erase(__f, __l); } - - void - clear() - { _M_ht.clear(); } - - void - resize(size_type __hint) - { _M_ht.resize(__hint); } - - size_type - bucket_count() const - { return _M_ht.bucket_count(); } - - size_type - max_bucket_count() const - { return _M_ht.max_bucket_count(); } - - size_type - elems_in_bucket(size_type __n) const - { return _M_ht.elems_in_bucket(__n); } - }; - - template - inline bool - operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, - const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) - { return __hs1._M_ht == __hs2._M_ht; } - - template - inline bool - operator!=(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, - const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) - { return !(__hs1 == __hs2); } - - template - inline void - swap(hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, - hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) - { __hs1.swap(__hs2); } - - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template, - class _EqualKey = equal_to<_Value>, - class _Alloc = allocator<_Value> > - class hash_multiset - { - // concept requirements - __glibcxx_class_requires(_Value, _SGIAssignableConcept) - __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) - __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) - - private: - typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, - _EqualKey, _Alloc> _Ht; - _Ht _M_ht; - - public: - typedef typename _Ht::key_type key_type; - typedef typename _Ht::value_type value_type; - typedef typename _Ht::hasher hasher; - typedef typename _Ht::key_equal key_equal; - - typedef typename _Ht::size_type size_type; - typedef typename _Ht::difference_type difference_type; - typedef typename _Alloc::pointer pointer; - typedef typename _Alloc::const_pointer const_pointer; - typedef typename _Alloc::reference reference; - typedef typename _Alloc::const_reference const_reference; - - typedef typename _Ht::const_iterator iterator; - typedef typename _Ht::const_iterator const_iterator; - - typedef typename _Ht::allocator_type allocator_type; - - hasher - hash_funct() const - { return _M_ht.hash_funct(); } - - key_equal - key_eq() const - { return _M_ht.key_eq(); } - - allocator_type - get_allocator() const - { return _M_ht.get_allocator(); } - - hash_multiset() - : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - - explicit - hash_multiset(size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - - hash_multiset(size_type __n, const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - - hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) {} - - template - hash_multiset(_InputIterator __f, _InputIterator __l) - : _M_ht(100, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) - { _M_ht.insert_equal(__f, __l); } - - size_type - size() const - { return _M_ht.size(); } - - size_type - max_size() const - { return _M_ht.max_size(); } - - _GLIBCXX_NODISCARD bool - empty() const - { return _M_ht.empty(); } - - void - swap(hash_multiset& hs) - { _M_ht.swap(hs._M_ht); } - - template - friend bool - operator==(const hash_multiset<_Val, _HF, _EqK, _Al>&, - const hash_multiset<_Val, _HF, _EqK, _Al>&); - - iterator - begin() const - { return _M_ht.begin(); } - - iterator - end() const - { return _M_ht.end(); } - - iterator - insert(const value_type& __obj) - { return _M_ht.insert_equal(__obj); } - - template - void - insert(_InputIterator __f, _InputIterator __l) - { _M_ht.insert_equal(__f,__l); } - - iterator - insert_noresize(const value_type& __obj) - { return _M_ht.insert_equal_noresize(__obj); } - - iterator - find(const key_type& __key) const - { return _M_ht.find(__key); } - - size_type - count(const key_type& __key) const - { return _M_ht.count(__key); } - - pair - equal_range(const key_type& __key) const - { return _M_ht.equal_range(__key); } - - size_type - erase(const key_type& __key) - { return _M_ht.erase(__key); } - - void - erase(iterator __it) - { _M_ht.erase(__it); } - - void - erase(iterator __f, iterator __l) - { _M_ht.erase(__f, __l); } - - void - clear() - { _M_ht.clear(); } - - void - resize(size_type __hint) - { _M_ht.resize(__hint); } - - size_type - bucket_count() const - { return _M_ht.bucket_count(); } - - size_type - max_bucket_count() const - { return _M_ht.max_bucket_count(); } - - size_type - elems_in_bucket(size_type __n) const - { return _M_ht.elems_in_bucket(__n); } - }; - - template - inline bool - operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, - const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) - { return __hs1._M_ht == __hs2._M_ht; } - - template - inline bool - operator!=(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, - const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) - { return !(__hs1 == __hs2); } - - template - inline void - swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, - hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) - { __hs1.swap(__hs2); } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Specialization of insert_iterator so that it will work for hash_set - // and hash_multiset. - template - class insert_iterator<__gnu_cxx::hash_set<_Value, _HashFcn, - _EqualKey, _Alloc> > - { - protected: - typedef __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc> - _Container; - _Container* container; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x) - : container(&__x) {} - - insert_iterator(_Container& __x, typename _Container::iterator) - : container(&__x) {} - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - container->insert(__value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() - { return *this; } - - insert_iterator<_Container>& - operator++(int) - { return *this; } - }; - - template - class insert_iterator<__gnu_cxx::hash_multiset<_Value, _HashFcn, - _EqualKey, _Alloc> > - { - protected: - typedef __gnu_cxx::hash_multiset<_Value, _HashFcn, _EqualKey, _Alloc> - _Container; - _Container* container; - typename _Container::iterator iter; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x) - : container(&__x) {} - - insert_iterator(_Container& __x, typename _Container::iterator) - : container(&__x) {} - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - container->insert(__value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() - { return *this; } - - insert_iterator<_Container>& - operator++(int) { return *this; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hashtable.h b/resources/sources/avr-libstdcpp/include/backward/hashtable.h deleted file mode 100644 index 1779fa44d..000000000 --- a/resources/sources/avr-libstdcpp/include/backward/hashtable.h +++ /dev/null @@ -1,1166 +0,0 @@ -// Hashtable implementation used by containers -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file backward/hashtable.h - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _BACKWARD_HASHTABLE_H -#define _BACKWARD_HASHTABLE_H 1 - -// Hashtable class, used to implement the hashed associative containers -// hash_set, hash_map, hash_multiset, and hash_multimap. - -#include -#include -#include -#include -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template - struct _Hashtable_node - { - _Hashtable_node* _M_next; - _Val _M_val; - }; - - template > - class hashtable; - - template - struct _Hashtable_iterator; - - template - struct _Hashtable_const_iterator; - - template - struct _Hashtable_iterator - { - typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> - _Hashtable; - typedef _Hashtable_iterator<_Val, _Key, _HashFcn, - _ExtractKey, _EqualKey, _Alloc> - iterator; - typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, - _ExtractKey, _EqualKey, _Alloc> - const_iterator; - typedef _Hashtable_node<_Val> _Node; - typedef std::forward_iterator_tag iterator_category; - typedef _Val value_type; - typedef std::ptrdiff_t difference_type; - typedef std::size_t size_type; - typedef _Val& reference; - typedef _Val* pointer; - - _Node* _M_cur; - _Hashtable* _M_ht; - - _Hashtable_iterator(_Node* __n, _Hashtable* __tab) - : _M_cur(__n), _M_ht(__tab) { } - - _Hashtable_iterator() { } - - reference - operator*() const - { return _M_cur->_M_val; } - - pointer - operator->() const - { return &(operator*()); } - - iterator& - operator++(); - - iterator - operator++(int); - - bool - operator==(const iterator& __it) const - { return _M_cur == __it._M_cur; } - - bool - operator!=(const iterator& __it) const - { return _M_cur != __it._M_cur; } - }; - - template - struct _Hashtable_const_iterator - { - typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> - _Hashtable; - typedef _Hashtable_iterator<_Val,_Key,_HashFcn, - _ExtractKey,_EqualKey,_Alloc> - iterator; - typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, - _ExtractKey, _EqualKey, _Alloc> - const_iterator; - typedef _Hashtable_node<_Val> _Node; - - typedef std::forward_iterator_tag iterator_category; - typedef _Val value_type; - typedef std::ptrdiff_t difference_type; - typedef std::size_t size_type; - typedef const _Val& reference; - typedef const _Val* pointer; - - const _Node* _M_cur; - const _Hashtable* _M_ht; - - _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab) - : _M_cur(__n), _M_ht(__tab) { } - - _Hashtable_const_iterator() { } - - _Hashtable_const_iterator(const iterator& __it) - : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { } - - reference - operator*() const - { return _M_cur->_M_val; } - - pointer - operator->() const - { return &(operator*()); } - - const_iterator& - operator++(); - - const_iterator - operator++(int); - - bool - operator==(const const_iterator& __it) const - { return _M_cur == __it._M_cur; } - - bool - operator!=(const const_iterator& __it) const - { return _M_cur != __it._M_cur; } - }; - - // Note: assumes long is at least 32 bits. - enum { _S_num_primes = 29 }; - - template - struct _Hashtable_prime_list - { - static const _PrimeType __stl_prime_list[_S_num_primes]; - - static const _PrimeType* - _S_get_prime_list(); - }; - - template const _PrimeType - _Hashtable_prime_list<_PrimeType>::__stl_prime_list[_S_num_primes] = - { - 5ul, 53ul, 97ul, 193ul, 389ul, - 769ul, 1543ul, 3079ul, 6151ul, 12289ul, - 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, - 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, - 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, - 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul - }; - - template inline const _PrimeType* - _Hashtable_prime_list<_PrimeType>::_S_get_prime_list() - { - return __stl_prime_list; - } - - inline unsigned long - __stl_next_prime(unsigned long __n) - { - const unsigned long* __first = _Hashtable_prime_list::_S_get_prime_list(); - const unsigned long* __last = __first + (int)_S_num_primes; - const unsigned long* pos = std::lower_bound(__first, __last, __n); - return pos == __last ? *(__last - 1) : *pos; - } - - // Forward declaration of operator==. - template - class hashtable; - - template - bool - operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, - const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2); - - // Hashtables handle allocators a bit differently than other - // containers do. If we're using standard-conforming allocators, then - // a hashtable unconditionally has a member variable to hold its - // allocator, even if it so happens that all instances of the - // allocator type are identical. This is because, for hashtables, - // this extra storage is negligible. Additionally, a base class - // wouldn't serve any other purposes; it wouldn't, for example, - // simplify the exception-handling code. - template - class hashtable - { - public: - typedef _Key key_type; - typedef _Val value_type; - typedef _HashFcn hasher; - typedef _EqualKey key_equal; - - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - - hasher - hash_funct() const - { return _M_hash; } - - key_equal - key_eq() const - { return _M_equals; } - - private: - typedef _Hashtable_node<_Val> _Node; - - public: - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind::other allocator_type; - - allocator_type - get_allocator() const - { return _M_node_allocator; } - - private: - typedef __gnu_cxx::__alloc_traits _Alloc_traits; - typedef typename _Alloc_traits::template rebind<_Node>::other - _Node_Alloc; - typedef typename _Alloc_traits::template rebind<_Node*>::other - _Nodeptr_Alloc; - typedef std::vector<_Node*, _Nodeptr_Alloc> _Vector_type; - - _Node_Alloc _M_node_allocator; - - _Node* - _M_get_node() - { return _M_node_allocator.allocate(1); } - - void - _M_put_node(_Node* __p) - { _M_node_allocator.deallocate(__p, 1); } - - private: - hasher _M_hash; - key_equal _M_equals; - _ExtractKey _M_get_key; - _Vector_type _M_buckets; - size_type _M_num_elements; - - public: - typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, - _EqualKey, _Alloc> - iterator; - typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, - _EqualKey, _Alloc> - const_iterator; - - friend struct - _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>; - - friend struct - _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, - _EqualKey, _Alloc>; - - public: - hashtable(size_type __n, const _HashFcn& __hf, - const _EqualKey& __eql, const _ExtractKey& __ext, - const allocator_type& __a = allocator_type()) - : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), - _M_get_key(__ext), _M_buckets(__a), _M_num_elements(0) - { _M_initialize_buckets(__n); } - - hashtable(size_type __n, const _HashFcn& __hf, - const _EqualKey& __eql, - const allocator_type& __a = allocator_type()) - : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), - _M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0) - { _M_initialize_buckets(__n); } - - hashtable(const hashtable& __ht) - : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash), - _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key), - _M_buckets(__ht.get_allocator()), _M_num_elements(0) - { _M_copy_from(__ht); } - - hashtable& - operator= (const hashtable& __ht) - { - if (&__ht != this) - { - clear(); - _M_hash = __ht._M_hash; - _M_equals = __ht._M_equals; - _M_get_key = __ht._M_get_key; - _M_copy_from(__ht); - } - return *this; - } - - ~hashtable() - { clear(); } - - size_type - size() const - { return _M_num_elements; } - - size_type - max_size() const - { return size_type(-1); } - - _GLIBCXX_NODISCARD bool - empty() const - { return size() == 0; } - - void - swap(hashtable& __ht) - { - std::swap(_M_hash, __ht._M_hash); - std::swap(_M_equals, __ht._M_equals); - std::swap(_M_get_key, __ht._M_get_key); - _M_buckets.swap(__ht._M_buckets); - std::swap(_M_num_elements, __ht._M_num_elements); - } - - iterator - begin() - { - for (size_type __n = 0; __n < _M_buckets.size(); ++__n) - if (_M_buckets[__n]) - return iterator(_M_buckets[__n], this); - return end(); - } - - iterator - end() - { return iterator(0, this); } - - const_iterator - begin() const - { - for (size_type __n = 0; __n < _M_buckets.size(); ++__n) - if (_M_buckets[__n]) - return const_iterator(_M_buckets[__n], this); - return end(); - } - - const_iterator - end() const - { return const_iterator(0, this); } - - template - friend bool - operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&, - const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&); - - public: - size_type - bucket_count() const - { return _M_buckets.size(); } - - size_type - max_bucket_count() const - { return _Hashtable_prime_list:: - _S_get_prime_list()[(int)_S_num_primes - 1]; - } - - size_type - elems_in_bucket(size_type __bucket) const - { - size_type __result = 0; - for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next) - __result += 1; - return __result; - } - - std::pair - insert_unique(const value_type& __obj) - { - resize(_M_num_elements + 1); - return insert_unique_noresize(__obj); - } - - iterator - insert_equal(const value_type& __obj) - { - resize(_M_num_elements + 1); - return insert_equal_noresize(__obj); - } - - std::pair - insert_unique_noresize(const value_type& __obj); - - iterator - insert_equal_noresize(const value_type& __obj); - - template - void - insert_unique(_InputIterator __f, _InputIterator __l) - { insert_unique(__f, __l, std::__iterator_category(__f)); } - - template - void - insert_equal(_InputIterator __f, _InputIterator __l) - { insert_equal(__f, __l, std::__iterator_category(__f)); } - - template - void - insert_unique(_InputIterator __f, _InputIterator __l, - std::input_iterator_tag) - { - for ( ; __f != __l; ++__f) - insert_unique(*__f); - } - - template - void - insert_equal(_InputIterator __f, _InputIterator __l, - std::input_iterator_tag) - { - for ( ; __f != __l; ++__f) - insert_equal(*__f); - } - - template - void - insert_unique(_ForwardIterator __f, _ForwardIterator __l, - std::forward_iterator_tag) - { - size_type __n = std::distance(__f, __l); - resize(_M_num_elements + __n); - for ( ; __n > 0; --__n, ++__f) - insert_unique_noresize(*__f); - } - - template - void - insert_equal(_ForwardIterator __f, _ForwardIterator __l, - std::forward_iterator_tag) - { - size_type __n = std::distance(__f, __l); - resize(_M_num_elements + __n); - for ( ; __n > 0; --__n, ++__f) - insert_equal_noresize(*__f); - } - - reference - find_or_insert(const value_type& __obj); - - iterator - find(const key_type& __key) - { - size_type __n = _M_bkt_num_key(__key); - _Node* __first; - for (__first = _M_buckets[__n]; - __first && !_M_equals(_M_get_key(__first->_M_val), __key); - __first = __first->_M_next) - { } - return iterator(__first, this); - } - - const_iterator - find(const key_type& __key) const - { - size_type __n = _M_bkt_num_key(__key); - const _Node* __first; - for (__first = _M_buckets[__n]; - __first && !_M_equals(_M_get_key(__first->_M_val), __key); - __first = __first->_M_next) - { } - return const_iterator(__first, this); - } - - size_type - count(const key_type& __key) const - { - const size_type __n = _M_bkt_num_key(__key); - size_type __result = 0; - - for (const _Node* __cur = _M_buckets[__n]; __cur; - __cur = __cur->_M_next) - if (_M_equals(_M_get_key(__cur->_M_val), __key)) - ++__result; - return __result; - } - - std::pair - equal_range(const key_type& __key); - - std::pair - equal_range(const key_type& __key) const; - - size_type - erase(const key_type& __key); - - void - erase(const iterator& __it); - - void - erase(iterator __first, iterator __last); - - void - erase(const const_iterator& __it); - - void - erase(const_iterator __first, const_iterator __last); - - void - resize(size_type __num_elements_hint); - - void - clear(); - - private: - size_type - _M_next_size(size_type __n) const - { return __stl_next_prime(__n); } - - void - _M_initialize_buckets(size_type __n) - { - const size_type __n_buckets = _M_next_size(__n); - _M_buckets.reserve(__n_buckets); - _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0); - _M_num_elements = 0; - } - - size_type - _M_bkt_num_key(const key_type& __key) const - { return _M_bkt_num_key(__key, _M_buckets.size()); } - - size_type - _M_bkt_num(const value_type& __obj) const - { return _M_bkt_num_key(_M_get_key(__obj)); } - - size_type - _M_bkt_num_key(const key_type& __key, std::size_t __n) const - { return _M_hash(__key) % __n; } - - size_type - _M_bkt_num(const value_type& __obj, std::size_t __n) const - { return _M_bkt_num_key(_M_get_key(__obj), __n); } - - _Node* - _M_new_node(const value_type& __obj) - { - _Node* __n = _M_get_node(); - __n->_M_next = 0; - __try - { - allocator_type __a = this->get_allocator(); - _Alloc_traits::construct(__a, &__n->_M_val, __obj); - return __n; - } - __catch(...) - { - _M_put_node(__n); - __throw_exception_again; - } - } - - void - _M_delete_node(_Node* __n) - { - allocator_type __a = this->get_allocator(); - _Alloc_traits::destroy(__a, &__n->_M_val); - _M_put_node(__n); - } - - void - _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last); - - void - _M_erase_bucket(const size_type __n, _Node* __last); - - void - _M_copy_from(const hashtable& __ht); - }; - - template - _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& - _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: - operator++() - { - const _Node* __old = _M_cur; - _M_cur = _M_cur->_M_next; - if (!_M_cur) - { - size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); - while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) - _M_cur = _M_ht->_M_buckets[__bucket]; - } - return *this; - } - - template - inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> - _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: - operator++(int) - { - iterator __tmp = *this; - ++*this; - return __tmp; - } - - template - _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& - _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: - operator++() - { - const _Node* __old = _M_cur; - _M_cur = _M_cur->_M_next; - if (!_M_cur) - { - size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); - while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) - _M_cur = _M_ht->_M_buckets[__bucket]; - } - return *this; - } - - template - inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> - _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: - operator++(int) - { - const_iterator __tmp = *this; - ++*this; - return __tmp; - } - - template - bool - operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, - const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) - { - typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node; - - if (__ht1._M_buckets.size() != __ht2._M_buckets.size()) - return false; - - for (std::size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) - { - _Node* __cur1 = __ht1._M_buckets[__n]; - _Node* __cur2 = __ht2._M_buckets[__n]; - // Check same length of lists - for (; __cur1 && __cur2; - __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next) - { } - if (__cur1 || __cur2) - return false; - // Now check one's elements are in the other - for (__cur1 = __ht1._M_buckets[__n] ; __cur1; - __cur1 = __cur1->_M_next) - { - bool _found__cur1 = false; - for (__cur2 = __ht2._M_buckets[__n]; - __cur2; __cur2 = __cur2->_M_next) - { - if (__cur1->_M_val == __cur2->_M_val) - { - _found__cur1 = true; - break; - } - } - if (!_found__cur1) - return false; - } - } - return true; - } - - template - inline bool - operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, - const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) - { return !(__ht1 == __ht2); } - - template - inline void - swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1, - hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) - { __ht1.swap(__ht2); } - - template - std::pair::iterator, - bool> - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - insert_unique_noresize(const value_type& __obj) - { - const size_type __n = _M_bkt_num(__obj); - _Node* __first = _M_buckets[__n]; - - for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) - if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) - return std::pair(iterator(__cur, this), false); - - _Node* __tmp = _M_new_node(__obj); - __tmp->_M_next = __first; - _M_buckets[__n] = __tmp; - ++_M_num_elements; - return std::pair(iterator(__tmp, this), true); - } - - template - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - insert_equal_noresize(const value_type& __obj) - { - const size_type __n = _M_bkt_num(__obj); - _Node* __first = _M_buckets[__n]; - - for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) - if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) - { - _Node* __tmp = _M_new_node(__obj); - __tmp->_M_next = __cur->_M_next; - __cur->_M_next = __tmp; - ++_M_num_elements; - return iterator(__tmp, this); - } - - _Node* __tmp = _M_new_node(__obj); - __tmp->_M_next = __first; - _M_buckets[__n] = __tmp; - ++_M_num_elements; - return iterator(__tmp, this); - } - - template - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - find_or_insert(const value_type& __obj) - { - resize(_M_num_elements + 1); - - size_type __n = _M_bkt_num(__obj); - _Node* __first = _M_buckets[__n]; - - for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) - if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) - return __cur->_M_val; - - _Node* __tmp = _M_new_node(__obj); - __tmp->_M_next = __first; - _M_buckets[__n] = __tmp; - ++_M_num_elements; - return __tmp->_M_val; - } - - template - std::pair::iterator, - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator> - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - equal_range(const key_type& __key) - { - typedef std::pair _Pii; - const size_type __n = _M_bkt_num_key(__key); - - for (_Node* __first = _M_buckets[__n]; __first; - __first = __first->_M_next) - if (_M_equals(_M_get_key(__first->_M_val), __key)) - { - for (_Node* __cur = __first->_M_next; __cur; - __cur = __cur->_M_next) - if (!_M_equals(_M_get_key(__cur->_M_val), __key)) - return _Pii(iterator(__first, this), iterator(__cur, this)); - for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) - if (_M_buckets[__m]) - return _Pii(iterator(__first, this), - iterator(_M_buckets[__m], this)); - return _Pii(iterator(__first, this), end()); - } - return _Pii(end(), end()); - } - - template - std::pair< - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator, - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator> - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - equal_range(const key_type& __key) const - { - typedef std::pair _Pii; - const size_type __n = _M_bkt_num_key(__key); - - for (const _Node* __first = _M_buckets[__n]; __first; - __first = __first->_M_next) - { - if (_M_equals(_M_get_key(__first->_M_val), __key)) - { - for (const _Node* __cur = __first->_M_next; __cur; - __cur = __cur->_M_next) - if (!_M_equals(_M_get_key(__cur->_M_val), __key)) - return _Pii(const_iterator(__first, this), - const_iterator(__cur, this)); - for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) - if (_M_buckets[__m]) - return _Pii(const_iterator(__first, this), - const_iterator(_M_buckets[__m], this)); - return _Pii(const_iterator(__first, this), end()); - } - } - return _Pii(end(), end()); - } - - template - typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(const key_type& __key) - { - const size_type __n = _M_bkt_num_key(__key); - _Node* __first = _M_buckets[__n]; - _Node* __saved_slot = 0; - size_type __erased = 0; - - if (__first) - { - _Node* __cur = __first; - _Node* __next = __cur->_M_next; - while (__next) - { - if (_M_equals(_M_get_key(__next->_M_val), __key)) - { - if (&_M_get_key(__next->_M_val) != &__key) - { - __cur->_M_next = __next->_M_next; - _M_delete_node(__next); - __next = __cur->_M_next; - ++__erased; - --_M_num_elements; - } - else - { - __saved_slot = __cur; - __cur = __next; - __next = __cur->_M_next; - } - } - else - { - __cur = __next; - __next = __cur->_M_next; - } - } - bool __delete_first = _M_equals(_M_get_key(__first->_M_val), __key); - if (__saved_slot) - { - __next = __saved_slot->_M_next; - __saved_slot->_M_next = __next->_M_next; - _M_delete_node(__next); - ++__erased; - --_M_num_elements; - } - if (__delete_first) - { - _M_buckets[__n] = __first->_M_next; - _M_delete_node(__first); - ++__erased; - --_M_num_elements; - } - } - return __erased; - } - - template - void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(const iterator& __it) - { - _Node* __p = __it._M_cur; - if (__p) - { - const size_type __n = _M_bkt_num(__p->_M_val); - _Node* __cur = _M_buckets[__n]; - - if (__cur == __p) - { - _M_buckets[__n] = __cur->_M_next; - _M_delete_node(__cur); - --_M_num_elements; - } - else - { - _Node* __next = __cur->_M_next; - while (__next) - { - if (__next == __p) - { - __cur->_M_next = __next->_M_next; - _M_delete_node(__next); - --_M_num_elements; - break; - } - else - { - __cur = __next; - __next = __cur->_M_next; - } - } - } - } - } - - template - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(iterator __first, iterator __last) - { - size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val) - : _M_buckets.size(); - - size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val) - : _M_buckets.size(); - - if (__first._M_cur == __last._M_cur) - return; - else if (__f_bucket == __l_bucket) - _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur); - else - { - _M_erase_bucket(__f_bucket, __first._M_cur, 0); - for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n) - _M_erase_bucket(__n, 0); - if (__l_bucket != _M_buckets.size()) - _M_erase_bucket(__l_bucket, __last._M_cur); - } - } - - template - inline void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(const_iterator __first, const_iterator __last) - { - erase(iterator(const_cast<_Node*>(__first._M_cur), - const_cast(__first._M_ht)), - iterator(const_cast<_Node*>(__last._M_cur), - const_cast(__last._M_ht))); - } - - template - inline void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - erase(const const_iterator& __it) - { erase(iterator(const_cast<_Node*>(__it._M_cur), - const_cast(__it._M_ht))); } - - template - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - resize(size_type __num_elements_hint) - { - const size_type __old_n = _M_buckets.size(); - if (__num_elements_hint > __old_n) - { - const size_type __n = _M_next_size(__num_elements_hint); - if (__n > __old_n) - { - _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator()); - __try - { - for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) - { - _Node* __first = _M_buckets[__bucket]; - while (__first) - { - size_type __new_bucket = _M_bkt_num(__first->_M_val, - __n); - _M_buckets[__bucket] = __first->_M_next; - __first->_M_next = __tmp[__new_bucket]; - __tmp[__new_bucket] = __first; - __first = _M_buckets[__bucket]; - } - } - _M_buckets.swap(__tmp); - } - __catch(...) - { - for (size_type __bucket = 0; __bucket < __tmp.size(); - ++__bucket) - { - while (__tmp[__bucket]) - { - _Node* __next = __tmp[__bucket]->_M_next; - _M_delete_node(__tmp[__bucket]); - __tmp[__bucket] = __next; - } - } - __throw_exception_again; - } - } - } - } - - template - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last) - { - _Node* __cur = _M_buckets[__n]; - if (__cur == __first) - _M_erase_bucket(__n, __last); - else - { - _Node* __next; - for (__next = __cur->_M_next; - __next != __first; - __cur = __next, __next = __cur->_M_next) - ; - while (__next != __last) - { - __cur->_M_next = __next->_M_next; - _M_delete_node(__next); - __next = __cur->_M_next; - --_M_num_elements; - } - } - } - - template - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - _M_erase_bucket(const size_type __n, _Node* __last) - { - _Node* __cur = _M_buckets[__n]; - while (__cur != __last) - { - _Node* __next = __cur->_M_next; - _M_delete_node(__cur); - __cur = __next; - _M_buckets[__n] = __cur; - --_M_num_elements; - } - } - - template - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - clear() - { - if (_M_num_elements == 0) - return; - - for (size_type __i = 0; __i < _M_buckets.size(); ++__i) - { - _Node* __cur = _M_buckets[__i]; - while (__cur != 0) - { - _Node* __next = __cur->_M_next; - _M_delete_node(__cur); - __cur = __next; - } - _M_buckets[__i] = 0; - } - _M_num_elements = 0; - } - - template - void - hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: - _M_copy_from(const hashtable& __ht) - { - _M_buckets.clear(); - _M_buckets.reserve(__ht._M_buckets.size()); - _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0); - __try - { - for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) { - const _Node* __cur = __ht._M_buckets[__i]; - if (__cur) - { - _Node* __local_copy = _M_new_node(__cur->_M_val); - _M_buckets[__i] = __local_copy; - - for (_Node* __next = __cur->_M_next; - __next; - __cur = __next, __next = __cur->_M_next) - { - __local_copy->_M_next = _M_new_node(__next->_M_val); - __local_copy = __local_copy->_M_next; - } - } - } - _M_num_elements = __ht._M_num_elements; - } - __catch(...) - { - clear(); - __throw_exception_again; - } - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bit b/resources/sources/avr-libstdcpp/include/bit deleted file mode 100644 index f4344820d..000000000 --- a/resources/sources/avr-libstdcpp/include/bit +++ /dev/null @@ -1,371 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2018-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/bit - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_BIT -#define _GLIBCXX_BIT 1 - -#pragma GCC system_header - -#if __cplusplus >= 201402L - -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup bit_manip Bit manipulation - * @ingroup numerics - * - * Utilities for examining and manipulating individual bits. - * - * @{ - */ - - /// @cond undoc - - template - constexpr _Tp - __rotl(_Tp __x, int __s) noexcept - { - constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; - const int __r = __s % _Nd; - if (__r == 0) - return __x; - else if (__r > 0) - return (__x << __r) | (__x >> ((_Nd - __r) % _Nd)); - else - return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r) - } - - template - constexpr _Tp - __rotr(_Tp __x, int __s) noexcept - { - constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; - const int __r = __s % _Nd; - if (__r == 0) - return __x; - else if (__r > 0) - return (__x >> __r) | (__x << ((_Nd - __r) % _Nd)); - else - return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r) - } - - template - constexpr int - __countl_zero(_Tp __x) noexcept - { - using __gnu_cxx::__int_traits; - constexpr auto _Nd = __int_traits<_Tp>::__digits; - - if (__x == 0) - return _Nd; - - constexpr auto _Nd_ull = __int_traits::__digits; - constexpr auto _Nd_ul = __int_traits::__digits; - constexpr auto _Nd_u = __int_traits::__digits; - - if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) - { - constexpr int __diff = _Nd_u - _Nd; - return __builtin_clz(__x) - __diff; - } - else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) - { - constexpr int __diff = _Nd_ul - _Nd; - return __builtin_clzl(__x) - __diff; - } - else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) - { - constexpr int __diff = _Nd_ull - _Nd; - return __builtin_clzll(__x) - __diff; - } - else // (_Nd > _Nd_ull) - { - static_assert(_Nd <= (2 * _Nd_ull), - "Maximum supported integer size is 128-bit"); - - unsigned long long __high = __x >> _Nd_ull; - if (__high != 0) - { - constexpr int __diff = (2 * _Nd_ull) - _Nd; - return __builtin_clzll(__high) - __diff; - } - constexpr auto __max_ull = __int_traits::__max; - unsigned long long __low = __x & __max_ull; - return (_Nd - _Nd_ull) + __builtin_clzll(__low); - } - } - - template - constexpr int - __countl_one(_Tp __x) noexcept - { - if (__x == __gnu_cxx::__int_traits<_Tp>::__max) - return __gnu_cxx::__int_traits<_Tp>::__digits; - return std::__countl_zero<_Tp>((_Tp)~__x); - } - - template - constexpr int - __countr_zero(_Tp __x) noexcept - { - using __gnu_cxx::__int_traits; - constexpr auto _Nd = __int_traits<_Tp>::__digits; - - if (__x == 0) - return _Nd; - - constexpr auto _Nd_ull = __int_traits::__digits; - constexpr auto _Nd_ul = __int_traits::__digits; - constexpr auto _Nd_u = __int_traits::__digits; - - if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) - return __builtin_ctz(__x); - else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) - return __builtin_ctzl(__x); - else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) - return __builtin_ctzll(__x); - else // (_Nd > _Nd_ull) - { - static_assert(_Nd <= (2 * _Nd_ull), - "Maximum supported integer size is 128-bit"); - - constexpr auto __max_ull = __int_traits::__max; - unsigned long long __low = __x & __max_ull; - if (__low != 0) - return __builtin_ctzll(__low); - unsigned long long __high = __x >> _Nd_ull; - return __builtin_ctzll(__high) + _Nd_ull; - } - } - - template - constexpr int - __countr_one(_Tp __x) noexcept - { - if (__x == __gnu_cxx::__int_traits<_Tp>::__max) - return __gnu_cxx::__int_traits<_Tp>::__digits; - return std::__countr_zero((_Tp)~__x); - } - - template - constexpr int - __popcount(_Tp __x) noexcept - { - using __gnu_cxx::__int_traits; - constexpr auto _Nd = __int_traits<_Tp>::__digits; - - if (__x == 0) - return 0; - - constexpr auto _Nd_ull = __int_traits::__digits; - constexpr auto _Nd_ul = __int_traits::__digits; - constexpr auto _Nd_u = __int_traits::__digits; - - if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) - return __builtin_popcount(__x); - else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) - return __builtin_popcountl(__x); - else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) - return __builtin_popcountll(__x); - else // (_Nd > _Nd_ull) - { - static_assert(_Nd <= (2 * _Nd_ull), - "Maximum supported integer size is 128-bit"); - - constexpr auto __max_ull = __int_traits::__max; - unsigned long long __low = __x & __max_ull; - unsigned long long __high = __x >> _Nd_ull; - return __builtin_popcountll(__low) + __builtin_popcountll(__high); - } - } - - template - constexpr bool - __has_single_bit(_Tp __x) noexcept - { return std::__popcount(__x) == 1; } - - template - constexpr _Tp - __bit_ceil(_Tp __x) noexcept - { - using __gnu_cxx::__int_traits; - constexpr auto _Nd = __int_traits<_Tp>::__digits; - if (__x == 0 || __x == 1) - return 1; - auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u)); - // If the shift exponent equals _Nd then the correct result is not - // representable as a value of _Tp, and so the result is undefined. - // Want that undefined behaviour to be detected in constant expressions, - // by UBSan, and by debug assertions. -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - if (!__builtin_is_constant_evaluated()) - { - __glibcxx_assert( __shift_exponent != __int_traits<_Tp>::__digits ); - } -#endif - using __promoted_type = decltype(__x << 1); - if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) - { - // If __x undergoes integral promotion then shifting by _Nd is - // not undefined. In order to make the shift undefined, so that - // it is diagnosed in constant expressions and by UBsan, we also - // need to "promote" the shift exponent to be too large for the - // promoted type. - const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2; - __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp; - } - return (_Tp)1u << __shift_exponent; - } - - template - constexpr _Tp - __bit_floor(_Tp __x) noexcept - { - constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; - if (__x == 0) - return 0; - return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x >> 1))); - } - - template - constexpr _Tp - __bit_width(_Tp __x) noexcept - { - constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; - return _Nd - std::__countl_zero(__x); - } - - /// @endcond - -#if __cplusplus > 201703L - -#define __cpp_lib_bitops 201907L - - /// @cond undoc - template - using _If_is_unsigned_integer - = enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>; - /// @endcond - - // [bit.rot], rotating - - /// Rotate `x` to the left by `s` bits. - template - [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> - rotl(_Tp __x, int __s) noexcept - { return std::__rotl(__x, __s); } - - /// Rotate `x` to the right by `s` bits. - template - [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> - rotr(_Tp __x, int __s) noexcept - { return std::__rotr(__x, __s); } - - // [bit.count], counting - - /// The number of contiguous zero bits, starting from the highest bit. - template - constexpr _If_is_unsigned_integer<_Tp, int> - countl_zero(_Tp __x) noexcept - { return std::__countl_zero(__x); } - - /// The number of contiguous one bits, starting from the highest bit. - template - constexpr _If_is_unsigned_integer<_Tp, int> - countl_one(_Tp __x) noexcept - { return std::__countl_one(__x); } - - /// The number of contiguous zero bits, starting from the lowest bit. - template - constexpr _If_is_unsigned_integer<_Tp, int> - countr_zero(_Tp __x) noexcept - { return std::__countr_zero(__x); } - - /// The number of contiguous one bits, starting from the lowest bit. - template - constexpr _If_is_unsigned_integer<_Tp, int> - countr_one(_Tp __x) noexcept - { return std::__countr_one(__x); } - - /// The number of bits set in `x`. - template - constexpr _If_is_unsigned_integer<_Tp, int> - popcount(_Tp __x) noexcept - { return std::__popcount(__x); } - - // [bit.pow.two], integral powers of 2 - -#define __cpp_lib_int_pow2 202002L - - /// True if `x` is a power of two, false otherwise. - template - constexpr _If_is_unsigned_integer<_Tp, bool> - has_single_bit(_Tp __x) noexcept - { return std::__has_single_bit(__x); } - - /// The smallest power-of-two not less than `x`. - template - constexpr _If_is_unsigned_integer<_Tp> - bit_ceil(_Tp __x) noexcept - { return std::__bit_ceil(__x); } - - /// The largest power-of-two not greater than `x`. - template - constexpr _If_is_unsigned_integer<_Tp> - bit_floor(_Tp __x) noexcept - { return std::__bit_floor(__x); } - - /// The smallest integer greater than the base-2 logarithm of `x`. - template - constexpr _If_is_unsigned_integer<_Tp> - bit_width(_Tp __x) noexcept - { return std::__bit_width(__x); } - -#define __cpp_lib_endian 201907L - - /// Byte order - enum class endian - { - little = __ORDER_LITTLE_ENDIAN__, - big = __ORDER_BIG_ENDIAN__, - native = __BYTE_ORDER__ - }; -#endif // C++2a - - /// @} - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++14 -#endif // _GLIBCXX_BIT diff --git a/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h b/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h deleted file mode 100644 index de0bd44f6..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h +++ /dev/null @@ -1,963 +0,0 @@ -// Forward declarations -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/algorithmfwd.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{algorithm} - */ - -#ifndef _GLIBCXX_ALGORITHMFWD_H -#define _GLIBCXX_ALGORITHMFWD_H 1 - -#pragma GCC system_header - -#include -#include -#include -#if __cplusplus >= 201103L -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /* - adjacent_find - all_of (C++11) - any_of (C++11) - binary_search - clamp (C++17) - copy - copy_backward - copy_if (C++11) - copy_n (C++11) - count - count_if - equal - equal_range - fill - fill_n - find - find_end - find_first_of - find_if - find_if_not (C++11) - for_each - generate - generate_n - includes - inplace_merge - is_heap (C++11) - is_heap_until (C++11) - is_partitioned (C++11) - is_sorted (C++11) - is_sorted_until (C++11) - iter_swap - lexicographical_compare - lower_bound - make_heap - max - max_element - merge - min - min_element - minmax (C++11) - minmax_element (C++11) - mismatch - next_permutation - none_of (C++11) - nth_element - partial_sort - partial_sort_copy - partition - partition_copy (C++11) - partition_point (C++11) - pop_heap - prev_permutation - push_heap - random_shuffle - remove - remove_copy - remove_copy_if - remove_if - replace - replace_copy - replace_copy_if - replace_if - reverse - reverse_copy - rotate - rotate_copy - search - search_n - set_difference - set_intersection - set_symmetric_difference - set_union - shuffle (C++11) - sort - sort_heap - stable_partition - stable_sort - swap - swap_ranges - transform - unique - unique_copy - upper_bound - */ - - /** - * @defgroup algorithms Algorithms - * - * Components for performing algorithmic operations. Includes - * non-modifying sequence, modifying (mutating) sequence, sorting, - * searching, merge, partition, heap, set, minima, maxima, and - * permutation operations. - */ - - /** - * @defgroup mutating_algorithms Mutating - * @ingroup algorithms - */ - - /** - * @defgroup non_mutating_algorithms Non-Mutating - * @ingroup algorithms - */ - - /** - * @defgroup sorting_algorithms Sorting - * @ingroup algorithms - */ - - /** - * @defgroup set_algorithms Set Operations - * @ingroup sorting_algorithms - * - * These algorithms are common set operations performed on sequences - * that are already sorted. The number of comparisons will be - * linear. - */ - - /** - * @defgroup binary_search_algorithms Binary Search - * @ingroup sorting_algorithms - * - * These algorithms are variations of a classic binary search, and - * all assume that the sequence being searched is already sorted. - * - * The number of comparisons will be logarithmic (and as few as - * possible). The number of steps through the sequence will be - * logarithmic for random-access iterators (e.g., pointers), and - * linear otherwise. - * - * The LWG has passed Defect Report 270, which notes: The - * proposed resolution reinterprets binary search. Instead of - * thinking about searching for a value in a sorted range, we view - * that as an important special case of a more general algorithm: - * searching for the partition point in a partitioned range. We - * also add a guarantee that the old wording did not: we ensure that - * the upper bound is no earlier than the lower bound, that the pair - * returned by equal_range is a valid range, and that the first part - * of that pair is the lower bound. - * - * The actual effect of the first sentence is that a comparison - * functor passed by the user doesn't necessarily need to induce a - * strict weak ordering relation. Rather, it partitions the range. - */ - - // adjacent_find - -#if __cplusplus > 201703L -# define __cpp_lib_constexpr_algorithms 201806L -#endif - -#if __cplusplus >= 201103L - template - _GLIBCXX20_CONSTEXPR - bool - all_of(_IIter, _IIter, _Predicate); - - template - _GLIBCXX20_CONSTEXPR - bool - any_of(_IIter, _IIter, _Predicate); -#endif - - template - _GLIBCXX20_CONSTEXPR - bool - binary_search(_FIter, _FIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - bool - binary_search(_FIter, _FIter, const _Tp&, _Compare); - -#if __cplusplus > 201402L - template - _GLIBCXX14_CONSTEXPR - const _Tp& - clamp(const _Tp&, const _Tp&, const _Tp&); - - template - _GLIBCXX14_CONSTEXPR - const _Tp& - clamp(const _Tp&, const _Tp&, const _Tp&, _Compare); -#endif - - template - _GLIBCXX20_CONSTEXPR - _OIter - copy(_IIter, _IIter, _OIter); - - template - _GLIBCXX20_CONSTEXPR - _BIter2 - copy_backward(_BIter1, _BIter1, _BIter2); - -#if __cplusplus >= 201103L - template - _GLIBCXX20_CONSTEXPR - _OIter - copy_if(_IIter, _IIter, _OIter, _Predicate); - - template - _GLIBCXX20_CONSTEXPR - _OIter - copy_n(_IIter, _Size, _OIter); -#endif - - // count - // count_if - - template - _GLIBCXX20_CONSTEXPR - pair<_FIter, _FIter> - equal_range(_FIter, _FIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - pair<_FIter, _FIter> - equal_range(_FIter, _FIter, const _Tp&, _Compare); - - template - _GLIBCXX20_CONSTEXPR - void - fill(_FIter, _FIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _OIter - fill_n(_OIter, _Size, const _Tp&); - - // find - - template - _GLIBCXX20_CONSTEXPR - _FIter1 - find_end(_FIter1, _FIter1, _FIter2, _FIter2); - - template - _GLIBCXX20_CONSTEXPR - _FIter1 - find_end(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); - - // find_first_of - // find_if - -#if __cplusplus >= 201103L - template - _GLIBCXX20_CONSTEXPR - _IIter - find_if_not(_IIter, _IIter, _Predicate); -#endif - - // for_each - // generate - // generate_n - - template - _GLIBCXX20_CONSTEXPR - bool - includes(_IIter1, _IIter1, _IIter2, _IIter2); - - template - _GLIBCXX20_CONSTEXPR - bool - includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); - - template - void - inplace_merge(_BIter, _BIter, _BIter); - - template - void - inplace_merge(_BIter, _BIter, _BIter, _Compare); - -#if __cplusplus >= 201103L - template - _GLIBCXX20_CONSTEXPR - bool - is_heap(_RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - bool - is_heap(_RAIter, _RAIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - _RAIter - is_heap_until(_RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - _RAIter - is_heap_until(_RAIter, _RAIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - bool - is_partitioned(_IIter, _IIter, _Predicate); - - template - _GLIBCXX20_CONSTEXPR - bool - is_permutation(_FIter1, _FIter1, _FIter2); - - template - _GLIBCXX20_CONSTEXPR - bool - is_permutation(_FIter1, _FIter1, _FIter2, _BinaryPredicate); - - template - _GLIBCXX20_CONSTEXPR - bool - is_sorted(_FIter, _FIter); - - template - _GLIBCXX20_CONSTEXPR - bool - is_sorted(_FIter, _FIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - _FIter - is_sorted_until(_FIter, _FIter); - - template - _GLIBCXX20_CONSTEXPR - _FIter - is_sorted_until(_FIter, _FIter, _Compare); -#endif - - template - _GLIBCXX20_CONSTEXPR - void - iter_swap(_FIter1, _FIter2); - - template - _GLIBCXX20_CONSTEXPR - _FIter - lower_bound(_FIter, _FIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _FIter - lower_bound(_FIter, _FIter, const _Tp&, _Compare); - - template - _GLIBCXX20_CONSTEXPR - void - make_heap(_RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - void - make_heap(_RAIter, _RAIter, _Compare); - - template - _GLIBCXX14_CONSTEXPR - const _Tp& - max(const _Tp&, const _Tp&); - - template - _GLIBCXX14_CONSTEXPR - const _Tp& - max(const _Tp&, const _Tp&, _Compare); - - // max_element - // merge - - template - _GLIBCXX14_CONSTEXPR - const _Tp& - min(const _Tp&, const _Tp&); - - template - _GLIBCXX14_CONSTEXPR - const _Tp& - min(const _Tp&, const _Tp&, _Compare); - - // min_element - -#if __cplusplus >= 201103L - template - _GLIBCXX14_CONSTEXPR - pair - minmax(const _Tp&, const _Tp&); - - template - _GLIBCXX14_CONSTEXPR - pair - minmax(const _Tp&, const _Tp&, _Compare); - - template - _GLIBCXX14_CONSTEXPR - pair<_FIter, _FIter> - minmax_element(_FIter, _FIter); - - template - _GLIBCXX14_CONSTEXPR - pair<_FIter, _FIter> - minmax_element(_FIter, _FIter, _Compare); - - template - _GLIBCXX14_CONSTEXPR - _Tp - min(initializer_list<_Tp>); - - template - _GLIBCXX14_CONSTEXPR - _Tp - min(initializer_list<_Tp>, _Compare); - - template - _GLIBCXX14_CONSTEXPR - _Tp - max(initializer_list<_Tp>); - - template - _GLIBCXX14_CONSTEXPR - _Tp - max(initializer_list<_Tp>, _Compare); - - template - _GLIBCXX14_CONSTEXPR - pair<_Tp, _Tp> - minmax(initializer_list<_Tp>); - - template - _GLIBCXX14_CONSTEXPR - pair<_Tp, _Tp> - minmax(initializer_list<_Tp>, _Compare); -#endif - - // mismatch - - template - _GLIBCXX20_CONSTEXPR - bool - next_permutation(_BIter, _BIter); - - template - _GLIBCXX20_CONSTEXPR - bool - next_permutation(_BIter, _BIter, _Compare); - -#if __cplusplus >= 201103L - template - _GLIBCXX20_CONSTEXPR - bool - none_of(_IIter, _IIter, _Predicate); -#endif - - // nth_element - // partial_sort - - template - _GLIBCXX20_CONSTEXPR - _RAIter - partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - _RAIter - partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter, _Compare); - - // partition - -#if __cplusplus >= 201103L - template - _GLIBCXX20_CONSTEXPR - pair<_OIter1, _OIter2> - partition_copy(_IIter, _IIter, _OIter1, _OIter2, _Predicate); - - template - _GLIBCXX20_CONSTEXPR - _FIter - partition_point(_FIter, _FIter, _Predicate); -#endif - - template - _GLIBCXX20_CONSTEXPR - void - pop_heap(_RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - void - pop_heap(_RAIter, _RAIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - bool - prev_permutation(_BIter, _BIter); - - template - _GLIBCXX20_CONSTEXPR - bool - prev_permutation(_BIter, _BIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - void - push_heap(_RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - void - push_heap(_RAIter, _RAIter, _Compare); - - // random_shuffle - - template - _GLIBCXX20_CONSTEXPR - _FIter - remove(_FIter, _FIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _FIter - remove_if(_FIter, _FIter, _Predicate); - - template - _GLIBCXX20_CONSTEXPR - _OIter - remove_copy(_IIter, _IIter, _OIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _OIter - remove_copy_if(_IIter, _IIter, _OIter, _Predicate); - - // replace - - template - _GLIBCXX20_CONSTEXPR - _OIter - replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _OIter - replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&); - - // replace_if - - template - _GLIBCXX20_CONSTEXPR - void - reverse(_BIter, _BIter); - - template - _GLIBCXX20_CONSTEXPR - _OIter - reverse_copy(_BIter, _BIter, _OIter); - - inline namespace _V2 - { - template - _GLIBCXX20_CONSTEXPR - _FIter - rotate(_FIter, _FIter, _FIter); - } - - template - _GLIBCXX20_CONSTEXPR - _OIter - rotate_copy(_FIter, _FIter, _FIter, _OIter); - - // search - // search_n - // set_difference - // set_intersection - // set_symmetric_difference - // set_union - -#if (__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99_STDINT_TR1) - template - void - shuffle(_RAIter, _RAIter, _UGenerator&&); -#endif - - template - _GLIBCXX20_CONSTEXPR - void - sort_heap(_RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - void - sort_heap(_RAIter, _RAIter, _Compare); - - template - _BIter - stable_partition(_BIter, _BIter, _Predicate); - -#if __cplusplus < 201103L - // For C++11 swap() is declared in . - - template - _GLIBCXX20_CONSTEXPR - inline void - swap(_Tp& __a, _Tp& __b); - - template - _GLIBCXX20_CONSTEXPR - inline void - swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]); -#endif - - template - _GLIBCXX20_CONSTEXPR - _FIter2 - swap_ranges(_FIter1, _FIter1, _FIter2); - - // transform - - template - _GLIBCXX20_CONSTEXPR - _FIter - unique(_FIter, _FIter); - - template - _GLIBCXX20_CONSTEXPR - _FIter - unique(_FIter, _FIter, _BinaryPredicate); - - // unique_copy - - template - _GLIBCXX20_CONSTEXPR - _FIter - upper_bound(_FIter, _FIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _FIter - upper_bound(_FIter, _FIter, const _Tp&, _Compare); - -_GLIBCXX_BEGIN_NAMESPACE_ALGO - - template - _GLIBCXX20_CONSTEXPR - _FIter - adjacent_find(_FIter, _FIter); - - template - _GLIBCXX20_CONSTEXPR - _FIter - adjacent_find(_FIter, _FIter, _BinaryPredicate); - - template - _GLIBCXX20_CONSTEXPR - typename iterator_traits<_IIter>::difference_type - count(_IIter, _IIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - typename iterator_traits<_IIter>::difference_type - count_if(_IIter, _IIter, _Predicate); - - template - _GLIBCXX20_CONSTEXPR - bool - equal(_IIter1, _IIter1, _IIter2); - - template - _GLIBCXX20_CONSTEXPR - bool - equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate); - - template - _GLIBCXX20_CONSTEXPR - _IIter - find(_IIter, _IIter, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _FIter1 - find_first_of(_FIter1, _FIter1, _FIter2, _FIter2); - - template - _GLIBCXX20_CONSTEXPR - _FIter1 - find_first_of(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); - - template - _GLIBCXX20_CONSTEXPR - _IIter - find_if(_IIter, _IIter, _Predicate); - - template - _GLIBCXX20_CONSTEXPR - _Funct - for_each(_IIter, _IIter, _Funct); - - template - _GLIBCXX20_CONSTEXPR - void - generate(_FIter, _FIter, _Generator); - - template - _GLIBCXX20_CONSTEXPR - _OIter - generate_n(_OIter, _Size, _Generator); - - template - _GLIBCXX20_CONSTEXPR - bool - lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2); - - template - _GLIBCXX20_CONSTEXPR - bool - lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); - - template - _GLIBCXX14_CONSTEXPR - _FIter - max_element(_FIter, _FIter); - - template - _GLIBCXX14_CONSTEXPR - _FIter - max_element(_FIter, _FIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - _OIter - merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); - - template - _GLIBCXX20_CONSTEXPR - _OIter - merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); - - template - _GLIBCXX14_CONSTEXPR - _FIter - min_element(_FIter, _FIter); - - template - _GLIBCXX14_CONSTEXPR - _FIter - min_element(_FIter, _FIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - pair<_IIter1, _IIter2> - mismatch(_IIter1, _IIter1, _IIter2); - - template - _GLIBCXX20_CONSTEXPR - pair<_IIter1, _IIter2> - mismatch(_IIter1, _IIter1, _IIter2, _BinaryPredicate); - - template - _GLIBCXX20_CONSTEXPR - void - nth_element(_RAIter, _RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - void - nth_element(_RAIter, _RAIter, _RAIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - void - partial_sort(_RAIter, _RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - void - partial_sort(_RAIter, _RAIter, _RAIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - _BIter - partition(_BIter, _BIter, _Predicate); - - template - void - random_shuffle(_RAIter, _RAIter); - - template - void - random_shuffle(_RAIter, _RAIter, -#if __cplusplus >= 201103L - _Generator&&); -#else - _Generator&); -#endif - - template - _GLIBCXX20_CONSTEXPR - void - replace(_FIter, _FIter, const _Tp&, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - void - replace_if(_FIter, _FIter, _Predicate, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _FIter1 - search(_FIter1, _FIter1, _FIter2, _FIter2); - - template - _GLIBCXX20_CONSTEXPR - _FIter1 - search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); - - template - _GLIBCXX20_CONSTEXPR - _FIter - search_n(_FIter, _FIter, _Size, const _Tp&); - - template - _GLIBCXX20_CONSTEXPR - _FIter - search_n(_FIter, _FIter, _Size, const _Tp&, _BinaryPredicate); - - template - _GLIBCXX20_CONSTEXPR - _OIter - set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); - - template - _GLIBCXX20_CONSTEXPR - _OIter - set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - _OIter - set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); - - template - _GLIBCXX20_CONSTEXPR - _OIter - set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - _OIter - set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); - - template - _GLIBCXX20_CONSTEXPR - _OIter - set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, - _OIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - _OIter - set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); - - template - _GLIBCXX20_CONSTEXPR - _OIter - set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - void - sort(_RAIter, _RAIter); - - template - _GLIBCXX20_CONSTEXPR - void - sort(_RAIter, _RAIter, _Compare); - - template - void - stable_sort(_RAIter, _RAIter); - - template - void - stable_sort(_RAIter, _RAIter, _Compare); - - template - _GLIBCXX20_CONSTEXPR - _OIter - transform(_IIter, _IIter, _OIter, _UnaryOperation); - - template - _GLIBCXX20_CONSTEXPR - _OIter - transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation); - - template - _GLIBCXX20_CONSTEXPR - _OIter - unique_copy(_IIter, _IIter, _OIter); - - template - _GLIBCXX20_CONSTEXPR - _OIter - unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate); - -_GLIBCXX_END_NAMESPACE_ALGO -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif - diff --git a/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h b/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h deleted file mode 100644 index 86d8ed221..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h +++ /dev/null @@ -1,743 +0,0 @@ -// Allocator traits -*- C++ -*- - -// Copyright (C) 2011-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/alloc_traits.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _ALLOC_TRAITS_H -#define _ALLOC_TRAITS_H 1 - -#include -#include -#if __cplusplus >= 201103L -# include -# include -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#if __cplusplus >= 201103L -#define __cpp_lib_allocator_traits_is_always_equal 201411 - - struct __allocator_traits_base - { - template - struct __rebind : __replace_first_arg<_Tp, _Up> { }; - - template - struct __rebind<_Tp, _Up, - __void_t::other>> - { using type = typename _Tp::template rebind<_Up>::other; }; - - protected: - template - using __pointer = typename _Tp::pointer; - template - using __c_pointer = typename _Tp::const_pointer; - template - using __v_pointer = typename _Tp::void_pointer; - template - using __cv_pointer = typename _Tp::const_void_pointer; - template - using __pocca = typename _Tp::propagate_on_container_copy_assignment; - template - using __pocma = typename _Tp::propagate_on_container_move_assignment; - template - using __pocs = typename _Tp::propagate_on_container_swap; - template - using __equal = typename _Tp::is_always_equal; - }; - - template - using __alloc_rebind - = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type; - - /** - * @brief Uniform interface to all allocator types. - * @ingroup allocators - */ - template - struct allocator_traits : __allocator_traits_base - { - /// The allocator type - typedef _Alloc allocator_type; - /// The allocated type - typedef typename _Alloc::value_type value_type; - - /** - * @brief The allocator's pointer type. - * - * @c Alloc::pointer if that type exists, otherwise @c value_type* - */ - using pointer = __detected_or_t; - - private: - // Select _Func<_Alloc> or pointer_traits::rebind<_Tp> - template class _Func, typename _Tp, typename = void> - struct _Ptr - { - using type = typename pointer_traits::template rebind<_Tp>; - }; - - template class _Func, typename _Tp> - struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> - { - using type = _Func<_Alloc>; - }; - - // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type - template - struct _Diff - { using type = typename pointer_traits<_PtrT>::difference_type; }; - - template - struct _Diff<_A2, _PtrT, __void_t> - { using type = typename _A2::difference_type; }; - - // Select _A2::size_type or make_unsigned<_DiffT>::type - template - struct _Size : make_unsigned<_DiffT> { }; - - template - struct _Size<_A2, _DiffT, __void_t> - { using type = typename _A2::size_type; }; - - public: - /** - * @brief The allocator's const pointer type. - * - * @c Alloc::const_pointer if that type exists, otherwise - * pointer_traits::rebind - */ - using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; - - /** - * @brief The allocator's void pointer type. - * - * @c Alloc::void_pointer if that type exists, otherwise - * pointer_traits::rebind - */ - using void_pointer = typename _Ptr<__v_pointer, void>::type; - - /** - * @brief The allocator's const void pointer type. - * - * @c Alloc::const_void_pointer if that type exists, otherwise - * pointer_traits::rebind - */ - using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; - - /** - * @brief The allocator's difference type - * - * @c Alloc::difference_type if that type exists, otherwise - * pointer_traits::difference_type - */ - using difference_type = typename _Diff<_Alloc, pointer>::type; - - /** - * @brief The allocator's size type - * - * @c Alloc::size_type if that type exists, otherwise - * make_unsigned::type - */ - using size_type = typename _Size<_Alloc, difference_type>::type; - - /** - * @brief How the allocator is propagated on copy assignment - * - * @c Alloc::propagate_on_container_copy_assignment if that type exists, - * otherwise @c false_type - */ - using propagate_on_container_copy_assignment - = __detected_or_t; - - /** - * @brief How the allocator is propagated on move assignment - * - * @c Alloc::propagate_on_container_move_assignment if that type exists, - * otherwise @c false_type - */ - using propagate_on_container_move_assignment - = __detected_or_t; - - /** - * @brief How the allocator is propagated on swap - * - * @c Alloc::propagate_on_container_swap if that type exists, - * otherwise @c false_type - */ - using propagate_on_container_swap - = __detected_or_t; - - /** - * @brief Whether all instances of the allocator type compare equal. - * - * @c Alloc::is_always_equal if that type exists, - * otherwise @c is_empty::type - */ - using is_always_equal - = __detected_or_t::type, __equal, _Alloc>; - - template - using rebind_alloc = __alloc_rebind<_Alloc, _Tp>; - template - using rebind_traits = allocator_traits>; - - private: - template - static constexpr auto - _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int) - -> decltype(__a.allocate(__n, __hint)) - { return __a.allocate(__n, __hint); } - - template - static constexpr pointer - _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...) - { return __a.allocate(__n); } - - template - struct __construct_helper - { - template()->construct( - std::declval<_Tp*>(), std::declval<_Args>()...))> - static true_type __test(int); - - template - static false_type __test(...); - - using type = decltype(__test<_Alloc>(0)); - }; - - template - using __has_construct - = typename __construct_helper<_Tp, _Args...>::type; - - template - static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>> - _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) - noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...))) - { __a.construct(__p, std::forward<_Args>(__args)...); } - - template - static _GLIBCXX14_CONSTEXPR - _Require<__and_<__not_<__has_construct<_Tp, _Args...>>, - is_constructible<_Tp, _Args...>>> - _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) - noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value) - { -#if __cplusplus <= 201703L - ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); -#else - std::construct_at(__p, std::forward<_Args>(__args)...); -#endif - } - - template - static _GLIBCXX14_CONSTEXPR auto - _S_destroy(_Alloc2& __a, _Tp* __p, int) - noexcept(noexcept(__a.destroy(__p))) - -> decltype(__a.destroy(__p)) - { __a.destroy(__p); } - - template - static _GLIBCXX14_CONSTEXPR void - _S_destroy(_Alloc2&, _Tp* __p, ...) - noexcept(std::is_nothrow_destructible<_Tp>::value) - { std::_Destroy(__p); } - - template - static constexpr auto - _S_max_size(_Alloc2& __a, int) - -> decltype(__a.max_size()) - { return __a.max_size(); } - - template - static constexpr size_type - _S_max_size(_Alloc2&, ...) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2466. allocator_traits::max_size() default behavior is incorrect - return __gnu_cxx::__numeric_traits::__max - / sizeof(value_type); - } - - template - static constexpr auto - _S_select(_Alloc2& __a, int) - -> decltype(__a.select_on_container_copy_construction()) - { return __a.select_on_container_copy_construction(); } - - template - static constexpr _Alloc2 - _S_select(_Alloc2& __a, ...) - { return __a; } - - public: - - /** - * @brief Allocate memory. - * @param __a An allocator. - * @param __n The number of objects to allocate space for. - * - * Calls @c a.allocate(n) - */ - _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer - allocate(_Alloc& __a, size_type __n) - { return __a.allocate(__n); } - - /** - * @brief Allocate memory. - * @param __a An allocator. - * @param __n The number of objects to allocate space for. - * @param __hint Aid to locality. - * @return Memory of suitable size and alignment for @a n objects - * of type @c value_type - * - * Returns a.allocate(n, hint) if that expression is - * well-formed, otherwise returns @c a.allocate(n) - */ - _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer - allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) - { return _S_allocate(__a, __n, __hint, 0); } - - /** - * @brief Deallocate memory. - * @param __a An allocator. - * @param __p Pointer to the memory to deallocate. - * @param __n The number of objects space was allocated for. - * - * Calls a.deallocate(p, n) - */ - static _GLIBCXX20_CONSTEXPR void - deallocate(_Alloc& __a, pointer __p, size_type __n) - { __a.deallocate(__p, __n); } - - /** - * @brief Construct an object of type @a _Tp - * @param __a An allocator. - * @param __p Pointer to memory of suitable size and alignment for Tp - * @param __args Constructor arguments. - * - * Calls __a.construct(__p, std::forward(__args)...) - * if that expression is well-formed, otherwise uses placement-new - * to construct an object of type @a _Tp at location @a __p from the - * arguments @a __args... - */ - template - static _GLIBCXX20_CONSTEXPR auto - construct(_Alloc& __a, _Tp* __p, _Args&&... __args) - noexcept(noexcept(_S_construct(__a, __p, - std::forward<_Args>(__args)...))) - -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...)) - { _S_construct(__a, __p, std::forward<_Args>(__args)...); } - - /** - * @brief Destroy an object of type @a _Tp - * @param __a An allocator. - * @param __p Pointer to the object to destroy - * - * Calls @c __a.destroy(__p) if that expression is well-formed, - * otherwise calls @c __p->~_Tp() - */ - template - static _GLIBCXX20_CONSTEXPR void - destroy(_Alloc& __a, _Tp* __p) - noexcept(noexcept(_S_destroy(__a, __p, 0))) - { _S_destroy(__a, __p, 0); } - - /** - * @brief The maximum supported allocation size - * @param __a An allocator. - * @return @c __a.max_size() or @c numeric_limits::max() - * - * Returns @c __a.max_size() if that expression is well-formed, - * otherwise returns @c numeric_limits::max() - */ - static _GLIBCXX20_CONSTEXPR size_type - max_size(const _Alloc& __a) noexcept - { return _S_max_size(__a, 0); } - - /** - * @brief Obtain an allocator to use when copying a container. - * @param __rhs An allocator. - * @return @c __rhs.select_on_container_copy_construction() or @a __rhs - * - * Returns @c __rhs.select_on_container_copy_construction() if that - * expression is well-formed, otherwise returns @a __rhs - */ - static _GLIBCXX20_CONSTEXPR _Alloc - select_on_container_copy_construction(const _Alloc& __rhs) - { return _S_select(__rhs, 0); } - }; - -#if __cplusplus > 201703L -# define __cpp_lib_constexpr_dynamic_alloc 201907L -#endif - - /// Partial specialization for std::allocator. - template - struct allocator_traits> - { - /// The allocator type - using allocator_type = allocator<_Tp>; - - /// The allocated type - using value_type = _Tp; - - /// The allocator's pointer type. - using pointer = _Tp*; - - /// The allocator's const pointer type. - using const_pointer = const _Tp*; - - /// The allocator's void pointer type. - using void_pointer = void*; - - /// The allocator's const void pointer type. - using const_void_pointer = const void*; - - /// The allocator's difference type - using difference_type = std::ptrdiff_t; - - /// The allocator's size type - using size_type = std::size_t; - - /// How the allocator is propagated on copy assignment - using propagate_on_container_copy_assignment = false_type; - - /// How the allocator is propagated on move assignment - using propagate_on_container_move_assignment = true_type; - - /// How the allocator is propagated on swap - using propagate_on_container_swap = false_type; - - /// Whether all instances of the allocator type compare equal. - using is_always_equal = true_type; - - template - using rebind_alloc = allocator<_Up>; - - template - using rebind_traits = allocator_traits>; - - /** - * @brief Allocate memory. - * @param __a An allocator. - * @param __n The number of objects to allocate space for. - * - * Calls @c a.allocate(n) - */ - _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer - allocate(allocator_type& __a, size_type __n) - { return __a.allocate(__n); } - - /** - * @brief Allocate memory. - * @param __a An allocator. - * @param __n The number of objects to allocate space for. - * @param __hint Aid to locality. - * @return Memory of suitable size and alignment for @a n objects - * of type @c value_type - * - * Returns a.allocate(n, hint) - */ - _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer - allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) - { -#if __cplusplus <= 201703L - return __a.allocate(__n, __hint); -#else - return __a.allocate(__n); -#endif - } - - /** - * @brief Deallocate memory. - * @param __a An allocator. - * @param __p Pointer to the memory to deallocate. - * @param __n The number of objects space was allocated for. - * - * Calls a.deallocate(p, n) - */ - static _GLIBCXX20_CONSTEXPR void - deallocate(allocator_type& __a, pointer __p, size_type __n) - { __a.deallocate(__p, __n); } - - /** - * @brief Construct an object of type `_Up` - * @param __a An allocator. - * @param __p Pointer to memory of suitable size and alignment for - * an object of type `_Up`. - * @param __args Constructor arguments. - * - * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` - * in C++11, C++14 and C++17. Changed in C++20 to call - * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. - */ - template - static _GLIBCXX20_CONSTEXPR void - construct(allocator_type& __a __attribute__((__unused__)), _Up* __p, - _Args&&... __args) - noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) - { -#if __cplusplus <= 201703L - __a.construct(__p, std::forward<_Args>(__args)...); -#else - std::construct_at(__p, std::forward<_Args>(__args)...); -#endif - } - - /** - * @brief Destroy an object of type @a _Up - * @param __a An allocator. - * @param __p Pointer to the object to destroy - * - * Calls @c __a.destroy(__p). - */ - template - static _GLIBCXX20_CONSTEXPR void - destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p) - noexcept(is_nothrow_destructible<_Up>::value) - { -#if __cplusplus <= 201703L - __a.destroy(__p); -#else - std::destroy_at(__p); -#endif - } - - /** - * @brief The maximum supported allocation size - * @param __a An allocator. - * @return @c __a.max_size() - */ - static _GLIBCXX20_CONSTEXPR size_type - max_size(const allocator_type& __a __attribute__((__unused__))) noexcept - { -#if __cplusplus <= 201703L - return __a.max_size(); -#else - return size_t(-1) / sizeof(value_type); -#endif - } - - /** - * @brief Obtain an allocator to use when copying a container. - * @param __rhs An allocator. - * @return @c __rhs - */ - static _GLIBCXX20_CONSTEXPR allocator_type - select_on_container_copy_construction(const allocator_type& __rhs) - { return __rhs; } - }; - -#if __cplusplus < 201703L - template - inline void - __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) - { __one = __two; } - - template - inline void - __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) - { } -#endif - - template - _GLIBCXX14_CONSTEXPR inline void - __alloc_on_copy(_Alloc& __one, const _Alloc& __two) - { - typedef allocator_traits<_Alloc> __traits; - typedef typename __traits::propagate_on_container_copy_assignment __pocca; -#if __cplusplus >= 201703L - if constexpr (__pocca::value) - __one = __two; -#else - __do_alloc_on_copy(__one, __two, __pocca()); -#endif - } - - template - constexpr _Alloc - __alloc_on_copy(const _Alloc& __a) - { - typedef allocator_traits<_Alloc> __traits; - return __traits::select_on_container_copy_construction(__a); - } - -#if __cplusplus < 201703L - template - inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) - { __one = std::move(__two); } - - template - inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) - { } -#endif - - template - _GLIBCXX14_CONSTEXPR inline void - __alloc_on_move(_Alloc& __one, _Alloc& __two) - { - typedef allocator_traits<_Alloc> __traits; - typedef typename __traits::propagate_on_container_move_assignment __pocma; -#if __cplusplus >= 201703L - if constexpr (__pocma::value) - __one = std::move(__two); -#else - __do_alloc_on_move(__one, __two, __pocma()); -#endif - } - -#if __cplusplus < 201703L - template - inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) - { - using std::swap; - swap(__one, __two); - } - - template - inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) - { } -#endif - - template - _GLIBCXX14_CONSTEXPR inline void - __alloc_on_swap(_Alloc& __one, _Alloc& __two) - { - typedef allocator_traits<_Alloc> __traits; - typedef typename __traits::propagate_on_container_swap __pocs; -#if __cplusplus >= 201703L - if constexpr (__pocs::value) - { - using std::swap; - swap(__one, __two); - } -#else - __do_alloc_on_swap(__one, __two, __pocs()); -#endif - } - - template, - typename = void> - struct __is_alloc_insertable_impl - : false_type - { }; - - template - struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT, - __void_t::construct( - std::declval<_Alloc&>(), std::declval<_ValueT*>(), - std::declval<_Tp>()))>> - : true_type - { }; - - // true if _Alloc::value_type is CopyInsertable into containers using _Alloc - // (might be wrong if _Alloc::construct exists but is not constrained, - // i.e. actually trying to use it would still be invalid. Use with caution.) - template - struct __is_copy_insertable - : __is_alloc_insertable_impl<_Alloc, - typename _Alloc::value_type const&>::type - { }; - - // std::allocator<_Tp> just requires CopyConstructible - template - struct __is_copy_insertable> - : is_copy_constructible<_Tp> - { }; - - // true if _Alloc::value_type is MoveInsertable into containers using _Alloc - // (might be wrong if _Alloc::construct exists but is not constrained, - // i.e. actually trying to use it would still be invalid. Use with caution.) - template - struct __is_move_insertable - : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type - { }; - - // std::allocator<_Tp> just requires MoveConstructible - template - struct __is_move_insertable> - : is_move_constructible<_Tp> - { }; - - // Trait to detect Allocator-like types. - template - struct __is_allocator : false_type { }; - - template - struct __is_allocator<_Alloc, - __void_t().allocate(size_t{}))>> - : true_type { }; - - template - using _RequireAllocator - = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type; - - template - using _RequireNotAllocator - = typename enable_if::value, _Alloc>::type; -#endif // C++11 - - /** - * Destroy a range of objects using the supplied allocator. For - * non-default allocators we do not optimize away invocation of - * destroy() even if _Tp has a trivial destructor. - */ - - template - void - _Destroy(_ForwardIterator __first, _ForwardIterator __last, - _Allocator& __alloc) - { - for (; __first != __last; ++__first) -#if __cplusplus < 201103L - __alloc.destroy(std::__addressof(*__first)); -#else - allocator_traits<_Allocator>::destroy(__alloc, - std::__addressof(*__first)); -#endif - } - - template - inline void - _Destroy(_ForwardIterator __first, _ForwardIterator __last, - allocator<_Tp>&) - { - _Destroy(__first, __last); - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // _ALLOC_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h b/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h deleted file mode 100644 index 5058ab084..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h +++ /dev/null @@ -1,104 +0,0 @@ -// Guarded Allocation -*- C++ -*- - -// Copyright (C) 2014-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/allocated_ptr.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _ALLOCATED_PTR_H -#define _ALLOCATED_PTR_H 1 - -#if __cplusplus < 201103L -# include -#else -# include -# include -# include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /// Non-standard RAII type for managing pointers obtained from allocators. - template - struct __allocated_ptr - { - using pointer = typename allocator_traits<_Alloc>::pointer; - using value_type = typename allocator_traits<_Alloc>::value_type; - - /// Take ownership of __ptr - __allocated_ptr(_Alloc& __a, pointer __ptr) noexcept - : _M_alloc(std::__addressof(__a)), _M_ptr(__ptr) - { } - - /// Convert __ptr to allocator's pointer type and take ownership of it - template>> - __allocated_ptr(_Alloc& __a, _Ptr __ptr) - : _M_alloc(std::__addressof(__a)), - _M_ptr(pointer_traits::pointer_to(*__ptr)) - { } - - /// Transfer ownership of the owned pointer - __allocated_ptr(__allocated_ptr&& __gd) noexcept - : _M_alloc(__gd._M_alloc), _M_ptr(__gd._M_ptr) - { __gd._M_ptr = nullptr; } - - /// Deallocate the owned pointer - ~__allocated_ptr() - { - if (_M_ptr != nullptr) - std::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1); - } - - /// Release ownership of the owned pointer - __allocated_ptr& - operator=(std::nullptr_t) noexcept - { - _M_ptr = nullptr; - return *this; - } - - /// Get the address that the owned pointer refers to. - value_type* get() { return std::__to_address(_M_ptr); } - - private: - _Alloc* _M_alloc; - pointer _M_ptr; - }; - - /// Allocate space for a single object using __a - template - __allocated_ptr<_Alloc> - __allocate_guarded(_Alloc& __a) - { - return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) }; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/allocator.h b/resources/sources/avr-libstdcpp/include/bits/allocator.h deleted file mode 100644 index d224aa3ec..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/allocator.h +++ /dev/null @@ -1,323 +0,0 @@ -// Allocators -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1996-1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/allocator.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _ALLOCATOR_H -#define _ALLOCATOR_H 1 - -#include // Define the base class to std::allocator. -#include -#if __cplusplus >= 201103L -#include -#endif - -#define __cpp_lib_incomplete_container_elements 201505 - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup allocators - * @{ - */ - - /// allocator specialization. - template<> - class allocator - { - public: - typedef void value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; -#if __cplusplus <= 201703L - typedef void* pointer; - typedef const void* const_pointer; - - template - struct rebind - { typedef allocator<_Tp1> other; }; -#else - allocator() = default; - - template - constexpr - allocator(const allocator<_Up>&) { } -#endif // ! C++20 - -#if __cplusplus >= 201103L && __cplusplus <= 201703L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2103. std::allocator propagate_on_container_move_assignment - typedef true_type propagate_on_container_move_assignment; - - typedef true_type is_always_equal; - - template - void - construct(_Up* __p, _Args&&... __args) - noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) - { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } - - template - void - destroy(_Up* __p) - noexcept(std::is_nothrow_destructible<_Up>::value) - { __p->~_Up(); } -#endif // C++11 to C++17 - }; - - /** - * @brief The @a standard allocator, as per [20.4]. - * - * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.allocator - * for further details. - * - * @tparam _Tp Type of allocated object. - */ - template - class allocator : public __allocator_base<_Tp> - { - public: - typedef _Tp value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; -#if __cplusplus <= 201703L - typedef _Tp* pointer; - typedef const _Tp* const_pointer; - typedef _Tp& reference; - typedef const _Tp& const_reference; - - template - struct rebind - { typedef allocator<_Tp1> other; }; -#endif - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2103. std::allocator propagate_on_container_move_assignment - typedef true_type propagate_on_container_move_assignment; - - typedef true_type is_always_equal; -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3035. std::allocator's constructors should be constexpr - _GLIBCXX20_CONSTEXPR - allocator() _GLIBCXX_NOTHROW { } - - _GLIBCXX20_CONSTEXPR - allocator(const allocator& __a) _GLIBCXX_NOTHROW - : __allocator_base<_Tp>(__a) { } - -#if __cplusplus >= 201103L - // Avoid implicit deprecation. - allocator& operator=(const allocator&) = default; -#endif - - template - _GLIBCXX20_CONSTEXPR - allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { } - -#if __cpp_constexpr_dynamic_alloc - constexpr -#endif - ~allocator() _GLIBCXX_NOTHROW { } - -#if __cplusplus > 201703L - [[nodiscard,__gnu__::__always_inline__]] - constexpr _Tp* - allocate(size_t __n) - { -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); -#endif - return __allocator_base<_Tp>::allocate(__n, 0); - } - - [[__gnu__::__always_inline__]] - constexpr void - deallocate(_Tp* __p, size_t __n) - { -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - { - ::operator delete(__p); - return; - } -#endif - __allocator_base<_Tp>::deallocate(__p, __n); - } -#endif // C++20 - - friend _GLIBCXX20_CONSTEXPR bool - operator==(const allocator&, const allocator&) _GLIBCXX_NOTHROW - { return true; } - -#if __cpp_impl_three_way_comparison < 201907L - friend _GLIBCXX20_CONSTEXPR bool - operator!=(const allocator&, const allocator&) _GLIBCXX_NOTHROW - { return false; } -#endif - - // Inherit everything else. - }; - - template - inline _GLIBCXX20_CONSTEXPR bool - operator==(const allocator<_T1>&, const allocator<_T2>&) - _GLIBCXX_NOTHROW - { return true; } - -#if __cpp_impl_three_way_comparison < 201907L - template - inline _GLIBCXX20_CONSTEXPR bool - operator!=(const allocator<_T1>&, const allocator<_T2>&) - _GLIBCXX_NOTHROW - { return false; } -#endif - - // Invalid allocator partial specializations. - // allocator_traits::rebind_alloc can be used to form a valid allocator type. - template - class allocator - { - public: - typedef _Tp value_type; - template allocator(const allocator<_Up>&) { } - }; - - template - class allocator - { - public: - typedef _Tp value_type; - template allocator(const allocator<_Up>&) { } - }; - - template - class allocator - { - public: - typedef _Tp value_type; - template allocator(const allocator<_Up>&) { } - }; - - /// @} group allocator - - // Inhibit implicit instantiations for required instantiations, - // which are defined via explicit instantiations elsewhere. -#if _GLIBCXX_EXTERN_TEMPLATE - extern template class allocator; - extern template class allocator; -#endif - - // Undefine. -#undef __allocator_base - - // To implement Option 3 of DR 431. - template - struct __alloc_swap - { static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } }; - - template - struct __alloc_swap<_Alloc, false> - { - static void - _S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT - { - // Precondition: swappable allocators. - if (__one != __two) - swap(__one, __two); - } - }; - - // Optimize for stateless allocators. - template - struct __alloc_neq - { - static bool - _S_do_it(const _Alloc&, const _Alloc&) - { return false; } - }; - - template - struct __alloc_neq<_Alloc, false> - { - static bool - _S_do_it(const _Alloc& __one, const _Alloc& __two) - { return __one != __two; } - }; - -#if __cplusplus >= 201103L - template, - is_nothrow_move_constructible>::value> - struct __shrink_to_fit_aux - { static bool _S_do_it(_Tp&) noexcept { return false; } }; - - template - struct __shrink_to_fit_aux<_Tp, true> - { - static bool - _S_do_it(_Tp& __c) noexcept - { -#if __cpp_exceptions - try - { - _Tp(__make_move_if_noexcept_iterator(__c.begin()), - __make_move_if_noexcept_iterator(__c.end()), - __c.get_allocator()).swap(__c); - return true; - } - catch(...) - { return false; } -#else - return false; -#endif - } - }; -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/atomic_base.h b/resources/sources/avr-libstdcpp/include/bits/atomic_base.h deleted file mode 100644 index b11de1edf..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/atomic_base.h +++ /dev/null @@ -1,1724 +0,0 @@ -// -*- C++ -*- header. - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/atomic_base.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{atomic} - */ - -#ifndef _GLIBCXX_ATOMIC_BASE_H -#define _GLIBCXX_ATOMIC_BASE_H 1 - -#pragma GCC system_header - -#include -#include -#include -#include - -#ifndef _GLIBCXX_ALWAYS_INLINE -#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup atomics Atomics - * - * Components for performing atomic operations. - * @{ - */ - - /// Enumeration for memory_order -#if __cplusplus > 201703L - enum class memory_order : int - { - relaxed, - consume, - acquire, - release, - acq_rel, - seq_cst - }; - - inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; - inline constexpr memory_order memory_order_consume = memory_order::consume; - inline constexpr memory_order memory_order_acquire = memory_order::acquire; - inline constexpr memory_order memory_order_release = memory_order::release; - inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; - inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; -#else - typedef enum memory_order - { - memory_order_relaxed, - memory_order_consume, - memory_order_acquire, - memory_order_release, - memory_order_acq_rel, - memory_order_seq_cst - } memory_order; -#endif - - enum __memory_order_modifier - { - __memory_order_mask = 0x0ffff, - __memory_order_modifier_mask = 0xffff0000, - __memory_order_hle_acquire = 0x10000, - __memory_order_hle_release = 0x20000 - }; - - constexpr memory_order - operator|(memory_order __m, __memory_order_modifier __mod) - { - return memory_order(int(__m) | int(__mod)); - } - - constexpr memory_order - operator&(memory_order __m, __memory_order_modifier __mod) - { - return memory_order(int(__m) & int(__mod)); - } - - // Drop release ordering as per [atomics.types.operations.req]/21 - constexpr memory_order - __cmpexch_failure_order2(memory_order __m) noexcept - { - return __m == memory_order_acq_rel ? memory_order_acquire - : __m == memory_order_release ? memory_order_relaxed : __m; - } - - constexpr memory_order - __cmpexch_failure_order(memory_order __m) noexcept - { - return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask) - | __memory_order_modifier(__m & __memory_order_modifier_mask)); - } - - _GLIBCXX_ALWAYS_INLINE void - atomic_thread_fence(memory_order __m) noexcept - { __atomic_thread_fence(int(__m)); } - - _GLIBCXX_ALWAYS_INLINE void - atomic_signal_fence(memory_order __m) noexcept - { __atomic_signal_fence(int(__m)); } - - /// kill_dependency - template - inline _Tp - kill_dependency(_Tp __y) noexcept - { - _Tp __ret(__y); - return __ret; - } - - - // Base types for atomics. - template - struct __atomic_base; - -#if __cplusplus <= 201703L -# define _GLIBCXX20_INIT(I) -#else -# define __cpp_lib_atomic_value_initialization 201911L -# define _GLIBCXX20_INIT(I) = I -#endif - -#define ATOMIC_VAR_INIT(_VI) { _VI } - - template - struct atomic; - - template - struct atomic<_Tp*>; - - /* The target's "set" value for test-and-set may not be exactly 1. */ -#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1 - typedef bool __atomic_flag_data_type; -#else - typedef unsigned char __atomic_flag_data_type; -#endif - - /** - * @brief Base type for atomic_flag. - * - * Base type is POD with data, allowing atomic_flag to derive from - * it and meet the standard layout type requirement. In addition to - * compatibility with a C interface, this allows different - * implementations of atomic_flag to use the same atomic operation - * functions, via a standard conversion to the __atomic_flag_base - * argument. - */ - _GLIBCXX_BEGIN_EXTERN_C - - struct __atomic_flag_base - { - __atomic_flag_data_type _M_i _GLIBCXX20_INIT({}); - }; - - _GLIBCXX_END_EXTERN_C - -#define ATOMIC_FLAG_INIT { 0 } - - /// atomic_flag - struct atomic_flag : public __atomic_flag_base - { - atomic_flag() noexcept = default; - ~atomic_flag() noexcept = default; - atomic_flag(const atomic_flag&) = delete; - atomic_flag& operator=(const atomic_flag&) = delete; - atomic_flag& operator=(const atomic_flag&) volatile = delete; - - // Conversion to ATOMIC_FLAG_INIT. - constexpr atomic_flag(bool __i) noexcept - : __atomic_flag_base{ _S_init(__i) } - { } - - _GLIBCXX_ALWAYS_INLINE bool - test_and_set(memory_order __m = memory_order_seq_cst) noexcept - { - return __atomic_test_and_set (&_M_i, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE bool - test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept - { - return __atomic_test_and_set (&_M_i, int(__m)); - } - -#if __cplusplus > 201703L -#define __cpp_lib_atomic_flag_test 201907L - - _GLIBCXX_ALWAYS_INLINE bool - test(memory_order __m = memory_order_seq_cst) const noexcept - { - __atomic_flag_data_type __v; - __atomic_load(&_M_i, &__v, int(__m)); - return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; - } - - _GLIBCXX_ALWAYS_INLINE bool - test(memory_order __m = memory_order_seq_cst) const volatile noexcept - { - __atomic_flag_data_type __v; - __atomic_load(&_M_i, &__v, int(__m)); - return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; - } - -#endif // C++20 - - _GLIBCXX_ALWAYS_INLINE void - clear(memory_order __m = memory_order_seq_cst) noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_consume); - __glibcxx_assert(__b != memory_order_acquire); - __glibcxx_assert(__b != memory_order_acq_rel); - - __atomic_clear (&_M_i, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE void - clear(memory_order __m = memory_order_seq_cst) volatile noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_consume); - __glibcxx_assert(__b != memory_order_acquire); - __glibcxx_assert(__b != memory_order_acq_rel); - - __atomic_clear (&_M_i, int(__m)); - } - - private: - static constexpr __atomic_flag_data_type - _S_init(bool __i) - { return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; } - }; - - - /// Base class for atomic integrals. - // - // For each of the integral types, define atomic_[integral type] struct - // - // atomic_bool bool - // atomic_char char - // atomic_schar signed char - // atomic_uchar unsigned char - // atomic_short short - // atomic_ushort unsigned short - // atomic_int int - // atomic_uint unsigned int - // atomic_long long - // atomic_ulong unsigned long - // atomic_llong long long - // atomic_ullong unsigned long long - // atomic_char8_t char8_t - // atomic_char16_t char16_t - // atomic_char32_t char32_t - // atomic_wchar_t wchar_t - // - // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or - // 8 bytes, since that is what GCC built-in functions for atomic - // memory access expect. - template - struct __atomic_base - { - using value_type = _ITp; - using difference_type = value_type; - - private: - typedef _ITp __int_type; - - static constexpr int _S_alignment = - sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp); - - alignas(_S_alignment) __int_type _M_i _GLIBCXX20_INIT(0); - - public: - __atomic_base() noexcept = default; - ~__atomic_base() noexcept = default; - __atomic_base(const __atomic_base&) = delete; - __atomic_base& operator=(const __atomic_base&) = delete; - __atomic_base& operator=(const __atomic_base&) volatile = delete; - - // Requires __int_type convertible to _M_i. - constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { } - - operator __int_type() const noexcept - { return load(); } - - operator __int_type() const volatile noexcept - { return load(); } - - __int_type - operator=(__int_type __i) noexcept - { - store(__i); - return __i; - } - - __int_type - operator=(__int_type __i) volatile noexcept - { - store(__i); - return __i; - } - - __int_type - operator++(int) noexcept - { return fetch_add(1); } - - __int_type - operator++(int) volatile noexcept - { return fetch_add(1); } - - __int_type - operator--(int) noexcept - { return fetch_sub(1); } - - __int_type - operator--(int) volatile noexcept - { return fetch_sub(1); } - - __int_type - operator++() noexcept - { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } - - __int_type - operator++() volatile noexcept - { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } - - __int_type - operator--() noexcept - { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } - - __int_type - operator--() volatile noexcept - { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } - - __int_type - operator+=(__int_type __i) noexcept - { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator+=(__int_type __i) volatile noexcept - { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator-=(__int_type __i) noexcept - { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator-=(__int_type __i) volatile noexcept - { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator&=(__int_type __i) noexcept - { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator&=(__int_type __i) volatile noexcept - { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator|=(__int_type __i) noexcept - { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator|=(__int_type __i) volatile noexcept - { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator^=(__int_type __i) noexcept - { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - __int_type - operator^=(__int_type __i) volatile noexcept - { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } - - bool - is_lock_free() const noexcept - { - // Use a fake, minimally aligned pointer. - return __atomic_is_lock_free(sizeof(_M_i), - reinterpret_cast(-_S_alignment)); - } - - bool - is_lock_free() const volatile noexcept - { - // Use a fake, minimally aligned pointer. - return __atomic_is_lock_free(sizeof(_M_i), - reinterpret_cast(-_S_alignment)); - } - - _GLIBCXX_ALWAYS_INLINE void - store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_acquire); - __glibcxx_assert(__b != memory_order_acq_rel); - __glibcxx_assert(__b != memory_order_consume); - - __atomic_store_n(&_M_i, __i, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE void - store(__int_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_acquire); - __glibcxx_assert(__b != memory_order_acq_rel); - __glibcxx_assert(__b != memory_order_consume); - - __atomic_store_n(&_M_i, __i, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE __int_type - load(memory_order __m = memory_order_seq_cst) const noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_release); - __glibcxx_assert(__b != memory_order_acq_rel); - - return __atomic_load_n(&_M_i, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE __int_type - load(memory_order __m = memory_order_seq_cst) const volatile noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_release); - __glibcxx_assert(__b != memory_order_acq_rel); - - return __atomic_load_n(&_M_i, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE __int_type - exchange(__int_type __i, - memory_order __m = memory_order_seq_cst) noexcept - { - return __atomic_exchange_n(&_M_i, __i, int(__m)); - } - - - _GLIBCXX_ALWAYS_INLINE __int_type - exchange(__int_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - return __atomic_exchange_n(&_M_i, __i, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_weak(__int_type& __i1, __int_type __i2, - memory_order __m1, memory_order __m2) noexcept - { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; - __glibcxx_assert(__b2 != memory_order_release); - __glibcxx_assert(__b2 != memory_order_acq_rel); - __glibcxx_assert(__b2 <= __b1); - - return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, - int(__m1), int(__m2)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_weak(__int_type& __i1, __int_type __i2, - memory_order __m1, - memory_order __m2) volatile noexcept - { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; - __glibcxx_assert(__b2 != memory_order_release); - __glibcxx_assert(__b2 != memory_order_acq_rel); - __glibcxx_assert(__b2 <= __b1); - - return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, - int(__m1), int(__m2)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_weak(__int_type& __i1, __int_type __i2, - memory_order __m = memory_order_seq_cst) noexcept - { - return compare_exchange_weak(__i1, __i2, __m, - __cmpexch_failure_order(__m)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_weak(__int_type& __i1, __int_type __i2, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - return compare_exchange_weak(__i1, __i2, __m, - __cmpexch_failure_order(__m)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_strong(__int_type& __i1, __int_type __i2, - memory_order __m1, memory_order __m2) noexcept - { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; - __glibcxx_assert(__b2 != memory_order_release); - __glibcxx_assert(__b2 != memory_order_acq_rel); - __glibcxx_assert(__b2 <= __b1); - - return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, - int(__m1), int(__m2)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_strong(__int_type& __i1, __int_type __i2, - memory_order __m1, - memory_order __m2) volatile noexcept - { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; - - __glibcxx_assert(__b2 != memory_order_release); - __glibcxx_assert(__b2 != memory_order_acq_rel); - __glibcxx_assert(__b2 <= __b1); - - return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, - int(__m1), int(__m2)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_strong(__int_type& __i1, __int_type __i2, - memory_order __m = memory_order_seq_cst) noexcept - { - return compare_exchange_strong(__i1, __i2, __m, - __cmpexch_failure_order(__m)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_strong(__int_type& __i1, __int_type __i2, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - return compare_exchange_strong(__i1, __i2, __m, - __cmpexch_failure_order(__m)); - } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_add(__int_type __i, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_fetch_add(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_add(__int_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_fetch_add(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_sub(__int_type __i, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_sub(__int_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_and(__int_type __i, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_fetch_and(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_and(__int_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_fetch_and(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_or(__int_type __i, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_fetch_or(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_or(__int_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_fetch_or(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_xor(__int_type __i, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __int_type - fetch_xor(__int_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } - }; - - - /// Partial specialization for pointer types. - template - struct __atomic_base<_PTp*> - { - private: - typedef _PTp* __pointer_type; - - __pointer_type _M_p _GLIBCXX20_INIT(nullptr); - - // Factored out to facilitate explicit specialization. - constexpr ptrdiff_t - _M_type_size(ptrdiff_t __d) const { return __d * sizeof(_PTp); } - - constexpr ptrdiff_t - _M_type_size(ptrdiff_t __d) const volatile { return __d * sizeof(_PTp); } - - public: - __atomic_base() noexcept = default; - ~__atomic_base() noexcept = default; - __atomic_base(const __atomic_base&) = delete; - __atomic_base& operator=(const __atomic_base&) = delete; - __atomic_base& operator=(const __atomic_base&) volatile = delete; - - // Requires __pointer_type convertible to _M_p. - constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { } - - operator __pointer_type() const noexcept - { return load(); } - - operator __pointer_type() const volatile noexcept - { return load(); } - - __pointer_type - operator=(__pointer_type __p) noexcept - { - store(__p); - return __p; - } - - __pointer_type - operator=(__pointer_type __p) volatile noexcept - { - store(__p); - return __p; - } - - __pointer_type - operator++(int) noexcept - { return fetch_add(1); } - - __pointer_type - operator++(int) volatile noexcept - { return fetch_add(1); } - - __pointer_type - operator--(int) noexcept - { return fetch_sub(1); } - - __pointer_type - operator--(int) volatile noexcept - { return fetch_sub(1); } - - __pointer_type - operator++() noexcept - { return __atomic_add_fetch(&_M_p, _M_type_size(1), - int(memory_order_seq_cst)); } - - __pointer_type - operator++() volatile noexcept - { return __atomic_add_fetch(&_M_p, _M_type_size(1), - int(memory_order_seq_cst)); } - - __pointer_type - operator--() noexcept - { return __atomic_sub_fetch(&_M_p, _M_type_size(1), - int(memory_order_seq_cst)); } - - __pointer_type - operator--() volatile noexcept - { return __atomic_sub_fetch(&_M_p, _M_type_size(1), - int(memory_order_seq_cst)); } - - __pointer_type - operator+=(ptrdiff_t __d) noexcept - { return __atomic_add_fetch(&_M_p, _M_type_size(__d), - int(memory_order_seq_cst)); } - - __pointer_type - operator+=(ptrdiff_t __d) volatile noexcept - { return __atomic_add_fetch(&_M_p, _M_type_size(__d), - int(memory_order_seq_cst)); } - - __pointer_type - operator-=(ptrdiff_t __d) noexcept - { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), - int(memory_order_seq_cst)); } - - __pointer_type - operator-=(ptrdiff_t __d) volatile noexcept - { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), - int(memory_order_seq_cst)); } - - bool - is_lock_free() const noexcept - { - // Produce a fake, minimally aligned pointer. - return __atomic_is_lock_free(sizeof(_M_p), - reinterpret_cast(-__alignof(_M_p))); - } - - bool - is_lock_free() const volatile noexcept - { - // Produce a fake, minimally aligned pointer. - return __atomic_is_lock_free(sizeof(_M_p), - reinterpret_cast(-__alignof(_M_p))); - } - - _GLIBCXX_ALWAYS_INLINE void - store(__pointer_type __p, - memory_order __m = memory_order_seq_cst) noexcept - { - memory_order __b = __m & __memory_order_mask; - - __glibcxx_assert(__b != memory_order_acquire); - __glibcxx_assert(__b != memory_order_acq_rel); - __glibcxx_assert(__b != memory_order_consume); - - __atomic_store_n(&_M_p, __p, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE void - store(__pointer_type __p, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_acquire); - __glibcxx_assert(__b != memory_order_acq_rel); - __glibcxx_assert(__b != memory_order_consume); - - __atomic_store_n(&_M_p, __p, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE __pointer_type - load(memory_order __m = memory_order_seq_cst) const noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_release); - __glibcxx_assert(__b != memory_order_acq_rel); - - return __atomic_load_n(&_M_p, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE __pointer_type - load(memory_order __m = memory_order_seq_cst) const volatile noexcept - { - memory_order __b = __m & __memory_order_mask; - __glibcxx_assert(__b != memory_order_release); - __glibcxx_assert(__b != memory_order_acq_rel); - - return __atomic_load_n(&_M_p, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE __pointer_type - exchange(__pointer_type __p, - memory_order __m = memory_order_seq_cst) noexcept - { - return __atomic_exchange_n(&_M_p, __p, int(__m)); - } - - - _GLIBCXX_ALWAYS_INLINE __pointer_type - exchange(__pointer_type __p, - memory_order __m = memory_order_seq_cst) volatile noexcept - { - return __atomic_exchange_n(&_M_p, __p, int(__m)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, - memory_order __m1, - memory_order __m2) noexcept - { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; - __glibcxx_assert(__b2 != memory_order_release); - __glibcxx_assert(__b2 != memory_order_acq_rel); - __glibcxx_assert(__b2 <= __b1); - - return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, - int(__m1), int(__m2)); - } - - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, - memory_order __m1, - memory_order __m2) volatile noexcept - { - memory_order __b2 = __m2 & __memory_order_mask; - memory_order __b1 = __m1 & __memory_order_mask; - - __glibcxx_assert(__b2 != memory_order_release); - __glibcxx_assert(__b2 != memory_order_acq_rel); - __glibcxx_assert(__b2 <= __b1); - - return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, - int(__m1), int(__m2)); - } - - _GLIBCXX_ALWAYS_INLINE __pointer_type - fetch_add(ptrdiff_t __d, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __pointer_type - fetch_add(ptrdiff_t __d, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __pointer_type - fetch_sub(ptrdiff_t __d, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } - - _GLIBCXX_ALWAYS_INLINE __pointer_type - fetch_sub(ptrdiff_t __d, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } - }; - -#if __cplusplus > 201703L - // Implementation details of atomic_ref and atomic. - namespace __atomic_impl - { - // Remove volatile and create a non-deduced context for value arguments. - template - using _Val = remove_volatile_t<_Tp>; - - // As above, but for difference_type arguments. - template - using _Diff = conditional_t, ptrdiff_t, _Val<_Tp>>; - - template - _GLIBCXX_ALWAYS_INLINE bool - is_lock_free() noexcept - { - // Produce a fake, minimally aligned pointer. - return __atomic_is_lock_free(_Size, reinterpret_cast(-_Align)); - } - - template - _GLIBCXX_ALWAYS_INLINE void - store(_Tp* __ptr, _Val<_Tp> __t, memory_order __m) noexcept - { __atomic_store(__ptr, std::__addressof(__t), int(__m)); } - - template - _GLIBCXX_ALWAYS_INLINE _Val<_Tp> - load(const _Tp* __ptr, memory_order __m) noexcept - { - alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; - auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); - __atomic_load(__ptr, __dest, int(__m)); - return *__dest; - } - - template - _GLIBCXX_ALWAYS_INLINE _Val<_Tp> - exchange(_Tp* __ptr, _Val<_Tp> __desired, memory_order __m) noexcept - { - alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; - auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); - __atomic_exchange(__ptr, std::__addressof(__desired), __dest, int(__m)); - return *__dest; - } - - template - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_weak(_Tp* __ptr, _Val<_Tp>& __expected, - _Val<_Tp> __desired, memory_order __success, - memory_order __failure) noexcept - { - return __atomic_compare_exchange(__ptr, std::__addressof(__expected), - std::__addressof(__desired), true, - int(__success), int(__failure)); - } - - template - _GLIBCXX_ALWAYS_INLINE bool - compare_exchange_strong(_Tp* __ptr, _Val<_Tp>& __expected, - _Val<_Tp> __desired, memory_order __success, - memory_order __failure) noexcept - { - return __atomic_compare_exchange(__ptr, std::__addressof(__expected), - std::__addressof(__desired), false, - int(__success), int(__failure)); - } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - fetch_add(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept - { return __atomic_fetch_add(__ptr, __i, int(__m)); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - fetch_sub(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept - { return __atomic_fetch_sub(__ptr, __i, int(__m)); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - fetch_and(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept - { return __atomic_fetch_and(__ptr, __i, int(__m)); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - fetch_or(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept - { return __atomic_fetch_or(__ptr, __i, int(__m)); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - fetch_xor(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept - { return __atomic_fetch_xor(__ptr, __i, int(__m)); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - __add_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept - { return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - __sub_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept - { return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - __and_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept - { return __atomic_and_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - __or_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept - { return __atomic_or_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } - - template - _GLIBCXX_ALWAYS_INLINE _Tp - __xor_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept - { return __atomic_xor_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } - - template - _Tp - __fetch_add_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept - { - _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); - _Val<_Tp> __newval = __oldval + __i; - while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, - memory_order_relaxed)) - __newval = __oldval + __i; - return __oldval; - } - - template - _Tp - __fetch_sub_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept - { - _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); - _Val<_Tp> __newval = __oldval - __i; - while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, - memory_order_relaxed)) - __newval = __oldval - __i; - return __oldval; - } - - template - _Tp - __add_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept - { - _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); - _Val<_Tp> __newval = __oldval + __i; - while (!compare_exchange_weak(__ptr, __oldval, __newval, - memory_order_seq_cst, - memory_order_relaxed)) - __newval = __oldval + __i; - return __newval; - } - - template - _Tp - __sub_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept - { - _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); - _Val<_Tp> __newval = __oldval - __i; - while (!compare_exchange_weak(__ptr, __oldval, __newval, - memory_order_seq_cst, - memory_order_relaxed)) - __newval = __oldval - __i; - return __newval; - } - } // namespace __atomic_impl - - // base class for atomic - template - struct __atomic_float - { - static_assert(is_floating_point_v<_Fp>); - - static constexpr size_t _S_alignment = __alignof__(_Fp); - - public: - using value_type = _Fp; - using difference_type = value_type; - - static constexpr bool is_always_lock_free - = __atomic_always_lock_free(sizeof(_Fp), 0); - - __atomic_float() = default; - - constexpr - __atomic_float(_Fp __t) : _M_fp(__t) - { } - - __atomic_float(const __atomic_float&) = delete; - __atomic_float& operator=(const __atomic_float&) = delete; - __atomic_float& operator=(const __atomic_float&) volatile = delete; - - _Fp - operator=(_Fp __t) volatile noexcept - { - this->store(__t); - return __t; - } - - _Fp - operator=(_Fp __t) noexcept - { - this->store(__t); - return __t; - } - - bool - is_lock_free() const volatile noexcept - { return __atomic_impl::is_lock_free(); } - - bool - is_lock_free() const noexcept - { return __atomic_impl::is_lock_free(); } - - void - store(_Fp __t, memory_order __m = memory_order_seq_cst) volatile noexcept - { __atomic_impl::store(&_M_fp, __t, __m); } - - void - store(_Fp __t, memory_order __m = memory_order_seq_cst) noexcept - { __atomic_impl::store(&_M_fp, __t, __m); } - - _Fp - load(memory_order __m = memory_order_seq_cst) const volatile noexcept - { return __atomic_impl::load(&_M_fp, __m); } - - _Fp - load(memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::load(&_M_fp, __m); } - - operator _Fp() const volatile noexcept { return this->load(); } - operator _Fp() const noexcept { return this->load(); } - - _Fp - exchange(_Fp __desired, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_impl::exchange(&_M_fp, __desired, __m); } - - _Fp - exchange(_Fp __desired, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_impl::exchange(&_M_fp, __desired, __m); } - - bool - compare_exchange_weak(_Fp& __expected, _Fp __desired, - memory_order __success, - memory_order __failure) noexcept - { - return __atomic_impl::compare_exchange_weak(&_M_fp, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_weak(_Fp& __expected, _Fp __desired, - memory_order __success, - memory_order __failure) volatile noexcept - { - return __atomic_impl::compare_exchange_weak(&_M_fp, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_strong(_Fp& __expected, _Fp __desired, - memory_order __success, - memory_order __failure) noexcept - { - return __atomic_impl::compare_exchange_strong(&_M_fp, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_strong(_Fp& __expected, _Fp __desired, - memory_order __success, - memory_order __failure) volatile noexcept - { - return __atomic_impl::compare_exchange_strong(&_M_fp, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_weak(_Fp& __expected, _Fp __desired, - memory_order __order = memory_order_seq_cst) - noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_weak(_Fp& __expected, _Fp __desired, - memory_order __order = memory_order_seq_cst) - volatile noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Fp& __expected, _Fp __desired, - memory_order __order = memory_order_seq_cst) - noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Fp& __expected, _Fp __desired, - memory_order __order = memory_order_seq_cst) - volatile noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - value_type - fetch_add(value_type __i, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } - - value_type - fetch_add(value_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } - - value_type - fetch_sub(value_type __i, - memory_order __m = memory_order_seq_cst) noexcept - { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } - - value_type - fetch_sub(value_type __i, - memory_order __m = memory_order_seq_cst) volatile noexcept - { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } - - value_type - operator+=(value_type __i) noexcept - { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } - - value_type - operator+=(value_type __i) volatile noexcept - { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } - - value_type - operator-=(value_type __i) noexcept - { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } - - value_type - operator-=(value_type __i) volatile noexcept - { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } - - private: - alignas(_S_alignment) _Fp _M_fp _GLIBCXX20_INIT(0); - }; -#undef _GLIBCXX20_INIT - - template, bool = is_floating_point_v<_Tp>> - struct __atomic_ref; - - // base class for non-integral, non-floating-point, non-pointer types - template - struct __atomic_ref<_Tp, false, false> - { - static_assert(is_trivially_copyable_v<_Tp>); - - // 1/2/4/8/16-byte types must be aligned to at least their size. - static constexpr int _S_min_alignment - = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 - ? 0 : sizeof(_Tp); - - public: - using value_type = _Tp; - - static constexpr bool is_always_lock_free - = __atomic_always_lock_free(sizeof(_Tp), 0); - - static constexpr size_t required_alignment - = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); - - __atomic_ref& operator=(const __atomic_ref&) = delete; - - explicit - __atomic_ref(_Tp& __t) : _M_ptr(std::__addressof(__t)) - { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } - - __atomic_ref(const __atomic_ref&) noexcept = default; - - _Tp - operator=(_Tp __t) const noexcept - { - this->store(__t); - return __t; - } - - operator _Tp() const noexcept { return this->load(); } - - bool - is_lock_free() const noexcept - { return __atomic_impl::is_lock_free(); } - - void - store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::store(_M_ptr, __t, __m); } - - _Tp - load(memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::load(_M_ptr, __m); } - - _Tp - exchange(_Tp __desired, memory_order __m = memory_order_seq_cst) - const noexcept - { return __atomic_impl::exchange(_M_ptr, __desired, __m); } - - bool - compare_exchange_weak(_Tp& __expected, _Tp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_weak(_M_ptr, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_strong(_Tp& __expected, _Tp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_strong(_M_ptr, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_weak(_Tp& __expected, _Tp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Tp& __expected, _Tp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - private: - _Tp* _M_ptr; - }; - - // base class for atomic_ref - template - struct __atomic_ref<_Tp, true, false> - { - static_assert(is_integral_v<_Tp>); - - public: - using value_type = _Tp; - using difference_type = value_type; - - static constexpr bool is_always_lock_free - = __atomic_always_lock_free(sizeof(_Tp), 0); - - static constexpr size_t required_alignment - = sizeof(_Tp) > alignof(_Tp) ? sizeof(_Tp) : alignof(_Tp); - - __atomic_ref() = delete; - __atomic_ref& operator=(const __atomic_ref&) = delete; - - explicit - __atomic_ref(_Tp& __t) : _M_ptr(&__t) - { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } - - __atomic_ref(const __atomic_ref&) noexcept = default; - - _Tp - operator=(_Tp __t) const noexcept - { - this->store(__t); - return __t; - } - - operator _Tp() const noexcept { return this->load(); } - - bool - is_lock_free() const noexcept - { - return __atomic_impl::is_lock_free(); - } - - void - store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::store(_M_ptr, __t, __m); } - - _Tp - load(memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::load(_M_ptr, __m); } - - _Tp - exchange(_Tp __desired, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::exchange(_M_ptr, __desired, __m); } - - bool - compare_exchange_weak(_Tp& __expected, _Tp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_weak(_M_ptr, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_strong(_Tp& __expected, _Tp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_strong(_M_ptr, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_weak(_Tp& __expected, _Tp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Tp& __expected, _Tp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - value_type - fetch_add(value_type __i, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_add(_M_ptr, __i, __m); } - - value_type - fetch_sub(value_type __i, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_sub(_M_ptr, __i, __m); } - - value_type - fetch_and(value_type __i, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_and(_M_ptr, __i, __m); } - - value_type - fetch_or(value_type __i, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_or(_M_ptr, __i, __m); } - - value_type - fetch_xor(value_type __i, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_xor(_M_ptr, __i, __m); } - - _GLIBCXX_ALWAYS_INLINE value_type - operator++(int) const noexcept - { return fetch_add(1); } - - _GLIBCXX_ALWAYS_INLINE value_type - operator--(int) const noexcept - { return fetch_sub(1); } - - value_type - operator++() const noexcept - { return __atomic_impl::__add_fetch(_M_ptr, value_type(1)); } - - value_type - operator--() const noexcept - { return __atomic_impl::__sub_fetch(_M_ptr, value_type(1)); } - - value_type - operator+=(value_type __i) const noexcept - { return __atomic_impl::__add_fetch(_M_ptr, __i); } - - value_type - operator-=(value_type __i) const noexcept - { return __atomic_impl::__sub_fetch(_M_ptr, __i); } - - value_type - operator&=(value_type __i) const noexcept - { return __atomic_impl::__and_fetch(_M_ptr, __i); } - - value_type - operator|=(value_type __i) const noexcept - { return __atomic_impl::__or_fetch(_M_ptr, __i); } - - value_type - operator^=(value_type __i) const noexcept - { return __atomic_impl::__xor_fetch(_M_ptr, __i); } - - private: - _Tp* _M_ptr; - }; - - // base class for atomic_ref - template - struct __atomic_ref<_Fp, false, true> - { - static_assert(is_floating_point_v<_Fp>); - - public: - using value_type = _Fp; - using difference_type = value_type; - - static constexpr bool is_always_lock_free - = __atomic_always_lock_free(sizeof(_Fp), 0); - - static constexpr size_t required_alignment = __alignof__(_Fp); - - __atomic_ref() = delete; - __atomic_ref& operator=(const __atomic_ref&) = delete; - - explicit - __atomic_ref(_Fp& __t) : _M_ptr(&__t) - { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } - - __atomic_ref(const __atomic_ref&) noexcept = default; - - _Fp - operator=(_Fp __t) const noexcept - { - this->store(__t); - return __t; - } - - operator _Fp() const noexcept { return this->load(); } - - bool - is_lock_free() const noexcept - { - return __atomic_impl::is_lock_free(); - } - - void - store(_Fp __t, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::store(_M_ptr, __t, __m); } - - _Fp - load(memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::load(_M_ptr, __m); } - - _Fp - exchange(_Fp __desired, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::exchange(_M_ptr, __desired, __m); } - - bool - compare_exchange_weak(_Fp& __expected, _Fp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_weak(_M_ptr, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_strong(_Fp& __expected, _Fp __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_strong(_M_ptr, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_weak(_Fp& __expected, _Fp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Fp& __expected, _Fp __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - value_type - fetch_add(value_type __i, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::__fetch_add_flt(_M_ptr, __i, __m); } - - value_type - fetch_sub(value_type __i, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::__fetch_sub_flt(_M_ptr, __i, __m); } - - value_type - operator+=(value_type __i) const noexcept - { return __atomic_impl::__add_fetch_flt(_M_ptr, __i); } - - value_type - operator-=(value_type __i) const noexcept - { return __atomic_impl::__sub_fetch_flt(_M_ptr, __i); } - - private: - _Fp* _M_ptr; - }; - - // base class for atomic_ref - template - struct __atomic_ref<_Tp*, false, false> - { - public: - using value_type = _Tp*; - using difference_type = ptrdiff_t; - - static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; - - static constexpr size_t required_alignment = __alignof__(_Tp*); - - __atomic_ref() = delete; - __atomic_ref& operator=(const __atomic_ref&) = delete; - - explicit - __atomic_ref(_Tp*& __t) : _M_ptr(std::__addressof(__t)) - { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } - - __atomic_ref(const __atomic_ref&) noexcept = default; - - _Tp* - operator=(_Tp* __t) const noexcept - { - this->store(__t); - return __t; - } - - operator _Tp*() const noexcept { return this->load(); } - - bool - is_lock_free() const noexcept - { - return __atomic_impl::is_lock_free(); - } - - void - store(_Tp* __t, memory_order __m = memory_order_seq_cst) const noexcept - { __atomic_impl::store(_M_ptr, __t, __m); } - - _Tp* - load(memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::load(_M_ptr, __m); } - - _Tp* - exchange(_Tp* __desired, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::exchange(_M_ptr, __desired, __m); } - - bool - compare_exchange_weak(_Tp*& __expected, _Tp* __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_weak(_M_ptr, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_strong(_Tp*& __expected, _Tp* __desired, - memory_order __success, - memory_order __failure) const noexcept - { - return __atomic_impl::compare_exchange_strong(_M_ptr, - __expected, __desired, - __success, __failure); - } - - bool - compare_exchange_weak(_Tp*& __expected, _Tp* __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_weak(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - bool - compare_exchange_strong(_Tp*& __expected, _Tp* __desired, - memory_order __order = memory_order_seq_cst) - const noexcept - { - return compare_exchange_strong(__expected, __desired, __order, - __cmpexch_failure_order(__order)); - } - - _GLIBCXX_ALWAYS_INLINE value_type - fetch_add(difference_type __d, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_add(_M_ptr, _S_type_size(__d), __m); } - - _GLIBCXX_ALWAYS_INLINE value_type - fetch_sub(difference_type __d, - memory_order __m = memory_order_seq_cst) const noexcept - { return __atomic_impl::fetch_sub(_M_ptr, _S_type_size(__d), __m); } - - value_type - operator++(int) const noexcept - { return fetch_add(1); } - - value_type - operator--(int) const noexcept - { return fetch_sub(1); } - - value_type - operator++() const noexcept - { - return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(1)); - } - - value_type - operator--() const noexcept - { - return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(1)); - } - - value_type - operator+=(difference_type __d) const noexcept - { - return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(__d)); - } - - value_type - operator-=(difference_type __d) const noexcept - { - return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(__d)); - } - - private: - static constexpr ptrdiff_t - _S_type_size(ptrdiff_t __d) noexcept - { - static_assert(is_object_v<_Tp>); - return __d * sizeof(_Tp); - } - - _Tp** _M_ptr; - }; - -#endif // C++2a - - // @} group atomics - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h b/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h deleted file mode 100644 index f0b57aeee..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h +++ /dev/null @@ -1,66 +0,0 @@ -// -*- C++ -*- header. - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/atomic_lockfree_defines.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{atomic} - */ - -#ifndef _GLIBCXX_ATOMIC_LOCK_FREE_H -#define _GLIBCXX_ATOMIC_LOCK_FREE_H 1 - -#pragma GCC system_header - -/** - * @addtogroup atomics - * @{ - */ - -/** - * Lock-free property. - * - * 0 indicates that the types are never lock-free. - * 1 indicates that the types are sometimes lock-free. - * 2 indicates that the types are always lock-free. - */ - -#if __cplusplus >= 201103L -#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE -#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE -#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE -#ifdef _GLIBCXX_USE_CHAR8_T -#define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE -#endif -#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE -#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE -#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE -#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE -#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE -#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE -#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE -#endif - -// @} group atomics - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h b/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h deleted file mode 100644 index f12c1bdc2..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h +++ /dev/null @@ -1,794 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2004-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, -// sell and distribute this software is granted provided this -// copyright notice appears in all copies. This software is provided -// "as is" without express or implied warranty, and with no claim as -// to its suitability for any purpose. -// - -/** @file bits/boost_concept_check.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iterator} - */ - -// GCC Note: based on version 1.12.0 of the Boost library. - -#ifndef _BOOST_CONCEPT_CHECK_H -#define _BOOST_CONCEPT_CHECK_H 1 - -#pragma GCC system_header - -#include -#include // for traits and tags - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wunused-local-typedefs" - -#define _IsUnused __attribute__ ((__unused__)) - -// When the C-C code is in use, we would like this function to do as little -// as possible at runtime, use as few resources as possible, and hopefully -// be elided out of existence... hmmm. -template -_GLIBCXX14_CONSTEXPR inline void __function_requires() -{ - void (_Concept::*__x)() _IsUnused = &_Concept::__constraints; -} - -// No definition: if this is referenced, there's a problem with -// the instantiating type not being one of the required integer types. -// Unfortunately, this results in a link-time error, not a compile-time error. -void __error_type_must_be_an_integer_type(); -void __error_type_must_be_an_unsigned_integer_type(); -void __error_type_must_be_a_signed_integer_type(); - -// ??? Should the "concept_checking*" structs begin with more than _ ? -#define _GLIBCXX_CLASS_REQUIRES(_type_var, _ns, _concept) \ - typedef void (_ns::_concept <_type_var>::* _func##_type_var##_concept)(); \ - template <_func##_type_var##_concept _Tp1> \ - struct _concept_checking##_type_var##_concept { }; \ - typedef _concept_checking##_type_var##_concept< \ - &_ns::_concept <_type_var>::__constraints> \ - _concept_checking_typedef##_type_var##_concept - -#define _GLIBCXX_CLASS_REQUIRES2(_type_var1, _type_var2, _ns, _concept) \ - typedef void (_ns::_concept <_type_var1,_type_var2>::* _func##_type_var1##_type_var2##_concept)(); \ - template <_func##_type_var1##_type_var2##_concept _Tp1> \ - struct _concept_checking##_type_var1##_type_var2##_concept { }; \ - typedef _concept_checking##_type_var1##_type_var2##_concept< \ - &_ns::_concept <_type_var1,_type_var2>::__constraints> \ - _concept_checking_typedef##_type_var1##_type_var2##_concept - -#define _GLIBCXX_CLASS_REQUIRES3(_type_var1, _type_var2, _type_var3, _ns, _concept) \ - typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3>::* _func##_type_var1##_type_var2##_type_var3##_concept)(); \ - template <_func##_type_var1##_type_var2##_type_var3##_concept _Tp1> \ - struct _concept_checking##_type_var1##_type_var2##_type_var3##_concept { }; \ - typedef _concept_checking##_type_var1##_type_var2##_type_var3##_concept< \ - &_ns::_concept <_type_var1,_type_var2,_type_var3>::__constraints> \ - _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_concept - -#define _GLIBCXX_CLASS_REQUIRES4(_type_var1, _type_var2, _type_var3, _type_var4, _ns, _concept) \ - typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::* _func##_type_var1##_type_var2##_type_var3##_type_var4##_concept)(); \ - template <_func##_type_var1##_type_var2##_type_var3##_type_var4##_concept _Tp1> \ - struct _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept { }; \ - typedef _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept< \ - &_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::__constraints> \ - _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_type_var4##_concept - - -template -struct _Aux_require_same { }; - -template -struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; - - template - struct _SameTypeConcept - { - void __constraints() { - typedef typename _Aux_require_same<_Tp1, _Tp2>::_Type _Required; - } - }; - - template - struct _IntegerConcept { - void __constraints() { - __error_type_must_be_an_integer_type(); - } - }; - template <> struct _IntegerConcept { void __constraints() {} }; - template <> struct _IntegerConcept { void __constraints(){} }; - template <> struct _IntegerConcept { void __constraints() {} }; - template <> struct _IntegerConcept { void __constraints() {} }; - template <> struct _IntegerConcept { void __constraints() {} }; - template <> struct _IntegerConcept { void __constraints() {} }; - template <> struct _IntegerConcept { void __constraints() {} }; - template <> struct _IntegerConcept - { void __constraints() {} }; - - template - struct _SignedIntegerConcept { - void __constraints() { - __error_type_must_be_a_signed_integer_type(); - } - }; - template <> struct _SignedIntegerConcept { void __constraints() {} }; - template <> struct _SignedIntegerConcept { void __constraints() {} }; - template <> struct _SignedIntegerConcept { void __constraints() {} }; - template <> struct _SignedIntegerConcept { void __constraints(){}}; - - template - struct _UnsignedIntegerConcept { - void __constraints() { - __error_type_must_be_an_unsigned_integer_type(); - } - }; - template <> struct _UnsignedIntegerConcept - { void __constraints() {} }; - template <> struct _UnsignedIntegerConcept - { void __constraints() {} }; - template <> struct _UnsignedIntegerConcept - { void __constraints() {} }; - template <> struct _UnsignedIntegerConcept - { void __constraints() {} }; - - //=========================================================================== - // Basic Concepts - - template - struct _DefaultConstructibleConcept - { - void __constraints() { - _Tp __a _IsUnused; // require default constructor - } - }; - - template - struct _AssignableConcept - { - void __constraints() { - __a = __a; // require assignment operator - __const_constraints(__a); - } - void __const_constraints(const _Tp& __b) { - __a = __b; // const required for argument to assignment - } - _Tp __a; - // possibly should be "Tp* a;" and then dereference "a" in constraint - // functions? present way would require a default ctor, i think... - }; - - template - struct _CopyConstructibleConcept - { - void __constraints() { - _Tp __a(__b); // require copy constructor - _Tp* __ptr _IsUnused = &__a; // require address of operator - __const_constraints(__a); - } - void __const_constraints(const _Tp& __a) { - _Tp __c _IsUnused(__a); // require const copy constructor - const _Tp* __ptr _IsUnused = &__a; // require const address of operator - } - _Tp __b; - }; - - // The SGI STL version of Assignable requires copy constructor and operator= - template - struct _SGIAssignableConcept - { - void __constraints() { - _Tp __b _IsUnused(__a); - __a = __a; // require assignment operator - __const_constraints(__a); - } - void __const_constraints(const _Tp& __b) { - _Tp __c _IsUnused(__b); - __a = __b; // const required for argument to assignment - } - _Tp __a; - }; - - template - struct _ConvertibleConcept - { - void __constraints() { - _To __y _IsUnused = __x; - } - _From __x; - }; - - // The C++ standard requirements for many concepts talk about return - // types that must be "convertible to bool". The problem with this - // requirement is that it leaves the door open for evil proxies that - // define things like operator|| with strange return types. Two - // possible solutions are: - // 1) require the return type to be exactly bool - // 2) stay with convertible to bool, and also - // specify stuff about all the logical operators. - // For now we just test for convertible to bool. - template - void __aux_require_boolean_expr(const _Tp& __t) { - bool __x _IsUnused = __t; - } - -// FIXME - template - struct _EqualityComparableConcept - { - void __constraints() { - __aux_require_boolean_expr(__a == __b); - } - _Tp __a, __b; - }; - - template - struct _LessThanComparableConcept - { - void __constraints() { - __aux_require_boolean_expr(__a < __b); - } - _Tp __a, __b; - }; - - // This is equivalent to SGI STL's LessThanComparable. - template - struct _ComparableConcept - { - void __constraints() { - __aux_require_boolean_expr(__a < __b); - __aux_require_boolean_expr(__a > __b); - __aux_require_boolean_expr(__a <= __b); - __aux_require_boolean_expr(__a >= __b); - } - _Tp __a, __b; - }; - -#define _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(_OP,_NAME) \ - template \ - struct _NAME { \ - void __constraints() { (void)__constraints_(); } \ - bool __constraints_() { \ - return __a _OP __b; \ - } \ - _First __a; \ - _Second __b; \ - } - -#define _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \ - template \ - struct _NAME { \ - void __constraints() { (void)__constraints_(); } \ - _Ret __constraints_() { \ - return __a _OP __b; \ - } \ - _First __a; \ - _Second __b; \ - } - - _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, _EqualOpConcept); - _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, _NotEqualOpConcept); - _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, _LessThanOpConcept); - _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, _LessEqualOpConcept); - _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, _GreaterThanOpConcept); - _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, _GreaterEqualOpConcept); - - _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, _PlusOpConcept); - _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, _TimesOpConcept); - _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, _DivideOpConcept); - _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, _SubtractOpConcept); - _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, _ModOpConcept); - -#undef _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT -#undef _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT - - //=========================================================================== - // Function Object Concepts - - template - struct _GeneratorConcept - { - void __constraints() { - const _Return& __r _IsUnused = __f();// require operator() member function - } - _Func __f; - }; - - - template - struct _GeneratorConcept<_Func,void> - { - void __constraints() { - __f(); // require operator() member function - } - _Func __f; - }; - - template - struct _UnaryFunctionConcept - { - void __constraints() { - __r = __f(__arg); // require operator() - } - _Func __f; - _Arg __arg; - _Return __r; - }; - - template - struct _UnaryFunctionConcept<_Func, void, _Arg> { - void __constraints() { - __f(__arg); // require operator() - } - _Func __f; - _Arg __arg; - }; - - template - struct _BinaryFunctionConcept - { - void __constraints() { - __r = __f(__first, __second); // require operator() - } - _Func __f; - _First __first; - _Second __second; - _Return __r; - }; - - template - struct _BinaryFunctionConcept<_Func, void, _First, _Second> - { - void __constraints() { - __f(__first, __second); // require operator() - } - _Func __f; - _First __first; - _Second __second; - }; - - template - struct _UnaryPredicateConcept - { - void __constraints() { - __aux_require_boolean_expr(__f(__arg)); // require op() returning bool - } - _Func __f; - _Arg __arg; - }; - - template - struct _BinaryPredicateConcept - { - void __constraints() { - __aux_require_boolean_expr(__f(__a, __b)); // require op() returning bool - } - _Func __f; - _First __a; - _Second __b; - }; - - // use this when functor is used inside a container class like std::set - template - struct _Const_BinaryPredicateConcept { - void __constraints() { - __const_constraints(__f); - } - void __const_constraints(const _Func& __fun) { - __function_requires<_BinaryPredicateConcept<_Func, _First, _Second> >(); - // operator() must be a const member function - __aux_require_boolean_expr(__fun(__a, __b)); - } - _Func __f; - _First __a; - _Second __b; - }; - - //=========================================================================== - // Iterator Concepts - - template - struct _TrivialIteratorConcept - { - void __constraints() { -// __function_requires< _DefaultConstructibleConcept<_Tp> >(); - __function_requires< _AssignableConcept<_Tp> >(); - __function_requires< _EqualityComparableConcept<_Tp> >(); -// typedef typename std::iterator_traits<_Tp>::value_type _V; - (void)*__i; // require dereference operator - } - _Tp __i; - }; - - template - struct _Mutable_TrivialIteratorConcept - { - void __constraints() { - __function_requires< _TrivialIteratorConcept<_Tp> >(); - *__i = *__j; // require dereference and assignment - } - _Tp __i, __j; - }; - - template - struct _InputIteratorConcept - { - void __constraints() { - __function_requires< _TrivialIteratorConcept<_Tp> >(); - // require iterator_traits typedef's - typedef typename std::iterator_traits<_Tp>::difference_type _Diff; -// __function_requires< _SignedIntegerConcept<_Diff> >(); - typedef typename std::iterator_traits<_Tp>::reference _Ref; - typedef typename std::iterator_traits<_Tp>::pointer _Pt; - typedef typename std::iterator_traits<_Tp>::iterator_category _Cat; - __function_requires< _ConvertibleConcept< - typename std::iterator_traits<_Tp>::iterator_category, - std::input_iterator_tag> >(); - ++__i; // require preincrement operator - __i++; // require postincrement operator - } - _Tp __i; - }; - - template - struct _OutputIteratorConcept - { - void __constraints() { - __function_requires< _AssignableConcept<_Tp> >(); - ++__i; // require preincrement operator - __i++; // require postincrement operator - *__i++ = __t; // require postincrement and assignment - } - _Tp __i; - _ValueT __t; - }; - - template - struct _ForwardIteratorConcept - { - void __constraints() { - __function_requires< _InputIteratorConcept<_Tp> >(); - __function_requires< _DefaultConstructibleConcept<_Tp> >(); - __function_requires< _ConvertibleConcept< - typename std::iterator_traits<_Tp>::iterator_category, - std::forward_iterator_tag> >(); - typedef typename std::iterator_traits<_Tp>::reference _Ref; - _Ref __r _IsUnused = *__i; - } - _Tp __i; - }; - - template - struct _Mutable_ForwardIteratorConcept - { - void __constraints() { - __function_requires< _ForwardIteratorConcept<_Tp> >(); - *__i++ = *__i; // require postincrement and assignment - } - _Tp __i; - }; - - template - struct _BidirectionalIteratorConcept - { - void __constraints() { - __function_requires< _ForwardIteratorConcept<_Tp> >(); - __function_requires< _ConvertibleConcept< - typename std::iterator_traits<_Tp>::iterator_category, - std::bidirectional_iterator_tag> >(); - --__i; // require predecrement operator - __i--; // require postdecrement operator - } - _Tp __i; - }; - - template - struct _Mutable_BidirectionalIteratorConcept - { - void __constraints() { - __function_requires< _BidirectionalIteratorConcept<_Tp> >(); - __function_requires< _Mutable_ForwardIteratorConcept<_Tp> >(); - *__i-- = *__i; // require postdecrement and assignment - } - _Tp __i; - }; - - - template - struct _RandomAccessIteratorConcept - { - void __constraints() { - __function_requires< _BidirectionalIteratorConcept<_Tp> >(); - __function_requires< _ComparableConcept<_Tp> >(); - __function_requires< _ConvertibleConcept< - typename std::iterator_traits<_Tp>::iterator_category, - std::random_access_iterator_tag> >(); - // ??? We don't use _Ref, are we just checking for "referenceability"? - typedef typename std::iterator_traits<_Tp>::reference _Ref; - - __i += __n; // require assignment addition operator - __i = __i + __n; __i = __n + __i; // require addition with difference type - __i -= __n; // require assignment subtraction op - __i = __i - __n; // require subtraction with - // difference type - __n = __i - __j; // require difference operator - (void)__i[__n]; // require element access operator - } - _Tp __a, __b; - _Tp __i, __j; - typename std::iterator_traits<_Tp>::difference_type __n; - }; - - template - struct _Mutable_RandomAccessIteratorConcept - { - void __constraints() { - __function_requires< _RandomAccessIteratorConcept<_Tp> >(); - __function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >(); - __i[__n] = *__i; // require element access and assignment - } - _Tp __i; - typename std::iterator_traits<_Tp>::difference_type __n; - }; - - //=========================================================================== - // Container Concepts - - template - struct _ContainerConcept - { - typedef typename _Container::value_type _Value_type; - typedef typename _Container::difference_type _Difference_type; - typedef typename _Container::size_type _Size_type; - typedef typename _Container::const_reference _Const_reference; - typedef typename _Container::const_pointer _Const_pointer; - typedef typename _Container::const_iterator _Const_iterator; - - void __constraints() { - __function_requires< _InputIteratorConcept<_Const_iterator> >(); - __function_requires< _AssignableConcept<_Container> >(); - const _Container __c; - __i = __c.begin(); - __i = __c.end(); - __n = __c.size(); - __n = __c.max_size(); - __b = __c.empty(); - } - bool __b; - _Const_iterator __i; - _Size_type __n; - }; - - template - struct _Mutable_ContainerConcept - { - typedef typename _Container::value_type _Value_type; - typedef typename _Container::reference _Reference; - typedef typename _Container::iterator _Iterator; - typedef typename _Container::pointer _Pointer; - - void __constraints() { - __function_requires< _ContainerConcept<_Container> >(); - __function_requires< _AssignableConcept<_Value_type> >(); - __function_requires< _InputIteratorConcept<_Iterator> >(); - - __i = __c.begin(); - __i = __c.end(); - __c.swap(__c2); - } - _Iterator __i; - _Container __c, __c2; - }; - - template - struct _ForwardContainerConcept - { - void __constraints() { - __function_requires< _ContainerConcept<_ForwardContainer> >(); - typedef typename _ForwardContainer::const_iterator _Const_iterator; - __function_requires< _ForwardIteratorConcept<_Const_iterator> >(); - } - }; - - template - struct _Mutable_ForwardContainerConcept - { - void __constraints() { - __function_requires< _ForwardContainerConcept<_ForwardContainer> >(); - __function_requires< _Mutable_ContainerConcept<_ForwardContainer> >(); - typedef typename _ForwardContainer::iterator _Iterator; - __function_requires< _Mutable_ForwardIteratorConcept<_Iterator> >(); - } - }; - - template - struct _ReversibleContainerConcept - { - typedef typename _ReversibleContainer::const_iterator _Const_iterator; - typedef typename _ReversibleContainer::const_reverse_iterator - _Const_reverse_iterator; - - void __constraints() { - __function_requires< _ForwardContainerConcept<_ReversibleContainer> >(); - __function_requires< _BidirectionalIteratorConcept<_Const_iterator> >(); - __function_requires< - _BidirectionalIteratorConcept<_Const_reverse_iterator> >(); - - const _ReversibleContainer __c; - _Const_reverse_iterator __i = __c.rbegin(); - __i = __c.rend(); - } - }; - - template - struct _Mutable_ReversibleContainerConcept - { - typedef typename _ReversibleContainer::iterator _Iterator; - typedef typename _ReversibleContainer::reverse_iterator _Reverse_iterator; - - void __constraints() { - __function_requires<_ReversibleContainerConcept<_ReversibleContainer> >(); - __function_requires< - _Mutable_ForwardContainerConcept<_ReversibleContainer> >(); - __function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator> >(); - __function_requires< - _Mutable_BidirectionalIteratorConcept<_Reverse_iterator> >(); - - _Reverse_iterator __i = __c.rbegin(); - __i = __c.rend(); - } - _ReversibleContainer __c; - }; - - template - struct _RandomAccessContainerConcept - { - typedef typename _RandomAccessContainer::size_type _Size_type; - typedef typename _RandomAccessContainer::const_reference _Const_reference; - typedef typename _RandomAccessContainer::const_iterator _Const_iterator; - typedef typename _RandomAccessContainer::const_reverse_iterator - _Const_reverse_iterator; - - void __constraints() { - __function_requires< - _ReversibleContainerConcept<_RandomAccessContainer> >(); - __function_requires< _RandomAccessIteratorConcept<_Const_iterator> >(); - __function_requires< - _RandomAccessIteratorConcept<_Const_reverse_iterator> >(); - - const _RandomAccessContainer __c; - _Const_reference __r _IsUnused = __c[__n]; - } - _Size_type __n; - }; - - template - struct _Mutable_RandomAccessContainerConcept - { - typedef typename _RandomAccessContainer::size_type _Size_type; - typedef typename _RandomAccessContainer::reference _Reference; - typedef typename _RandomAccessContainer::iterator _Iterator; - typedef typename _RandomAccessContainer::reverse_iterator _Reverse_iterator; - - void __constraints() { - __function_requires< - _RandomAccessContainerConcept<_RandomAccessContainer> >(); - __function_requires< - _Mutable_ReversibleContainerConcept<_RandomAccessContainer> >(); - __function_requires< _Mutable_RandomAccessIteratorConcept<_Iterator> >(); - __function_requires< - _Mutable_RandomAccessIteratorConcept<_Reverse_iterator> >(); - - _Reference __r _IsUnused = __c[__i]; - } - _Size_type __i; - _RandomAccessContainer __c; - }; - - // A Sequence is inherently mutable - template - struct _SequenceConcept - { - typedef typename _Sequence::reference _Reference; - typedef typename _Sequence::const_reference _Const_reference; - - void __constraints() { - // Matt Austern's book puts DefaultConstructible here, the C++ - // standard places it in Container - // function_requires< DefaultConstructible >(); - __function_requires< _Mutable_ForwardContainerConcept<_Sequence> >(); - __function_requires< _DefaultConstructibleConcept<_Sequence> >(); - - _Sequence - __c _IsUnused(__n, __t), - __c2 _IsUnused(__first, __last); - - __c.insert(__p, __t); - __c.insert(__p, __n, __t); - __c.insert(__p, __first, __last); - - __c.erase(__p); - __c.erase(__p, __q); - - _Reference __r _IsUnused = __c.front(); - - __const_constraints(__c); - } - void __const_constraints(const _Sequence& __c) { - _Const_reference __r _IsUnused = __c.front(); - } - typename _Sequence::value_type __t; - typename _Sequence::size_type __n; - typename _Sequence::value_type *__first, *__last; - typename _Sequence::iterator __p, __q; - }; - - template - struct _FrontInsertionSequenceConcept - { - void __constraints() { - __function_requires< _SequenceConcept<_FrontInsertionSequence> >(); - - __c.push_front(__t); - __c.pop_front(); - } - _FrontInsertionSequence __c; - typename _FrontInsertionSequence::value_type __t; - }; - - template - struct _BackInsertionSequenceConcept - { - typedef typename _BackInsertionSequence::reference _Reference; - typedef typename _BackInsertionSequence::const_reference _Const_reference; - - void __constraints() { - __function_requires< _SequenceConcept<_BackInsertionSequence> >(); - - __c.push_back(__t); - __c.pop_back(); - _Reference __r _IsUnused = __c.back(); - } - void __const_constraints(const _BackInsertionSequence& __c) { - _Const_reference __r _IsUnused = __c.back(); - }; - _BackInsertionSequence __c; - typename _BackInsertionSequence::value_type __t; - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#pragma GCC diagnostic pop -#undef _IsUnused - -#endif // _GLIBCXX_BOOST_CONCEPT_CHECK - - diff --git a/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h b/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h deleted file mode 100644 index 83dc80c34..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/c++0x_warning.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iosfwd} - */ - -#ifndef _CXX0X_WARNING_H -#define _CXX0X_WARNING_H 1 - -#if __cplusplus < 201103L -#error This file requires compiler and library support \ -for the ISO C++ 2011 standard. This support must be enabled \ -with the -std=c++11 or -std=gnu++11 compiler options. -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/c++allocator.h b/resources/sources/avr-libstdcpp/include/bits/c++allocator.h deleted file mode 100644 index 6392d2207..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/c++allocator.h +++ /dev/null @@ -1,59 +0,0 @@ -// Base to std::allocator -*- C++ -*- - -// Copyright (C) 2004-2018 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/c++allocator.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _GLIBCXX_CXX_ALLOCATOR_H -#define _GLIBCXX_CXX_ALLOCATOR_H 1 - -#include - -#if __cplusplus >= 201103L -namespace std -{ - /** - * @brief An alias to the base class for std::allocator. - * @ingroup allocators - * - * Used to set the std::allocator base class to - * __gnu_cxx::new_allocator. - * - * @tparam _Tp Type of allocated object. - */ - template - using __allocator_base = __gnu_cxx::new_allocator<_Tp>; -} -#else -// Define new_allocator as the base class to std::allocator. -# define __allocator_base __gnu_cxx::new_allocator -#endif - -#if defined(__SANITIZE_ADDRESS__) && !defined(_GLIBCXX_SANITIZE_STD_ALLOCATOR) -# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1 -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/c++config.h b/resources/sources/avr-libstdcpp/include/bits/c++config.h deleted file mode 100644 index 29b3eb2f0..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/c++config.h +++ /dev/null @@ -1,2074 +0,0 @@ -// Predefined symbols and macros -*- C++ -*- - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/c++config.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{version} - */ - -#ifndef _GLIBCXX_CXX_CONFIG_H -#define _GLIBCXX_CXX_CONFIG_H 1 - -// The major release number for the GCC release the C++ library belongs to. -#define _GLIBCXX_RELEASE 10 - -// The datestamp of the C++ library in compressed ISO date format. -#define __GLIBCXX__ 20201103 - -// Macros for various attributes. -// _GLIBCXX_PURE -// _GLIBCXX_CONST -// _GLIBCXX_NORETURN -// _GLIBCXX_NOTHROW -// _GLIBCXX_VISIBILITY -#ifndef _GLIBCXX_PURE -# define _GLIBCXX_PURE __attribute__ ((__pure__)) -#endif - -#ifndef _GLIBCXX_CONST -# define _GLIBCXX_CONST __attribute__ ((__const__)) -#endif - -#ifndef _GLIBCXX_NORETURN -# define _GLIBCXX_NORETURN __attribute__ ((__noreturn__)) -#endif - -// See below for C++ -#ifndef _GLIBCXX_NOTHROW -# ifndef __cplusplus -# define _GLIBCXX_NOTHROW __attribute__((__nothrow__)) -# endif -#endif - -// Macros for visibility attributes. -// _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY -// _GLIBCXX_VISIBILITY -#define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY - -#ifdef _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY -# define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V))) -#else -// If this is not supplied by the OS-specific or CPU-specific -// headers included below, it will be defined to an empty default. -# define _GLIBCXX_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY(V) -#endif - -// Macros for deprecated attributes. -// _GLIBCXX_USE_DEPRECATED -// _GLIBCXX_DEPRECATED -// _GLIBCXX_DEPRECATED_SUGGEST -// _GLIBCXX17_DEPRECATED -// _GLIBCXX20_DEPRECATED( string-literal ) -#ifndef _GLIBCXX_USE_DEPRECATED -# define _GLIBCXX_USE_DEPRECATED 1 -#endif - -#if defined(__DEPRECATED) && (__cplusplus >= 201103L) -# define _GLIBCXX_DEPRECATED __attribute__ ((__deprecated__)) -# define _GLIBCXX_DEPRECATED_SUGGEST(ALT) \ - __attribute__ ((__deprecated__ ("use '" ALT "' instead"))) -#else -# define _GLIBCXX_DEPRECATED -# define _GLIBCXX_DEPRECATED_SUGGEST(ALT) -#endif - -#if defined(__DEPRECATED) && (__cplusplus >= 201703L) -# define _GLIBCXX17_DEPRECATED [[__deprecated__]] -#else -# define _GLIBCXX17_DEPRECATED -#endif - -#if defined(__DEPRECATED) && (__cplusplus > 201703L) -# define _GLIBCXX20_DEPRECATED(MSG) [[deprecated(MSG)]] -#else -# define _GLIBCXX20_DEPRECATED(MSG) -#endif - -// Macros for ABI tag attributes. -#ifndef _GLIBCXX_ABI_TAG_CXX11 -# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11"))) -#endif - -// Macro to warn about unused results. -#if __cplusplus >= 201703L -# define _GLIBCXX_NODISCARD [[__nodiscard__]] -#else -# define _GLIBCXX_NODISCARD -#endif - - - -#ifdef __cplusplus - -// Macro for constexpr, to support in mixed 03/0x mode. -#ifndef _GLIBCXX_CONSTEXPR -# if __cplusplus >= 201103L -# define _GLIBCXX_CONSTEXPR constexpr -# define _GLIBCXX_USE_CONSTEXPR constexpr -# else -# define _GLIBCXX_CONSTEXPR -# define _GLIBCXX_USE_CONSTEXPR const -# endif -#endif - -#ifndef _GLIBCXX14_CONSTEXPR -# if __cplusplus >= 201402L -# define _GLIBCXX14_CONSTEXPR constexpr -# else -# define _GLIBCXX14_CONSTEXPR -# endif -#endif - -#ifndef _GLIBCXX17_CONSTEXPR -# if __cplusplus >= 201703L -# define _GLIBCXX17_CONSTEXPR constexpr -# else -# define _GLIBCXX17_CONSTEXPR -# endif -#endif - -#ifndef _GLIBCXX20_CONSTEXPR -# if __cplusplus > 201703L -# define _GLIBCXX20_CONSTEXPR constexpr -# else -# define _GLIBCXX20_CONSTEXPR -# endif -#endif - -#ifndef _GLIBCXX17_INLINE -# if __cplusplus >= 201703L -# define _GLIBCXX17_INLINE inline -# else -# define _GLIBCXX17_INLINE -# endif -#endif - -// Macro for noexcept, to support in mixed 03/0x mode. -#ifndef _GLIBCXX_NOEXCEPT -# if __cplusplus >= 201103L -# define _GLIBCXX_NOEXCEPT noexcept -# define _GLIBCXX_NOEXCEPT_IF(...) noexcept(__VA_ARGS__) -# define _GLIBCXX_USE_NOEXCEPT noexcept -# define _GLIBCXX_THROW(_EXC) -# else -# define _GLIBCXX_NOEXCEPT -# define _GLIBCXX_NOEXCEPT_IF(...) -# define _GLIBCXX_USE_NOEXCEPT throw() -# define _GLIBCXX_THROW(_EXC) throw(_EXC) -# endif -#endif - -#ifndef _GLIBCXX_NOTHROW -# define _GLIBCXX_NOTHROW _GLIBCXX_USE_NOEXCEPT -#endif - -#ifndef _GLIBCXX_THROW_OR_ABORT -# ifdef __cpp_exceptions -# define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC)) -# else -# define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort()) -# endif -#endif - -#ifdef __cpp_noexcept_function_type -#define _GLIBCXX_NOEXCEPT_PARM , bool _NE -#define _GLIBCXX_NOEXCEPT_QUAL noexcept (_NE) -#else -#define _GLIBCXX_NOEXCEPT_PARM -#define _GLIBCXX_NOEXCEPT_QUAL -#endif - -// Macro for extern template, ie controlling template linkage via use -// of extern keyword on template declaration. As documented in the g++ -// manual, it inhibits all implicit instantiations and is used -// throughout the library to avoid multiple weak definitions for -// required types that are already explicitly instantiated in the -// library binary. This substantially reduces the binary size of -// resulting executables. -// Special case: _GLIBCXX_EXTERN_TEMPLATE == -1 disallows extern -// templates only in basic_string, thus activating its debug-mode -// checks even at -O0. -# define _GLIBCXX_EXTERN_TEMPLATE 1 - -/* - Outline of libstdc++ namespaces. - - namespace std - { - namespace __debug { } - namespace __parallel { } - namespace __cxx1998 { } - - namespace __detail { - namespace __variant { } // C++17 - } - - namespace rel_ops { } - - namespace tr1 - { - namespace placeholders { } - namespace regex_constants { } - namespace __detail { } - } - - namespace tr2 { } - - namespace decimal { } - - namespace chrono { } // C++11 - namespace placeholders { } // C++11 - namespace regex_constants { } // C++11 - namespace this_thread { } // C++11 - inline namespace literals { // C++14 - inline namespace chrono_literals { } // C++14 - inline namespace complex_literals { } // C++14 - inline namespace string_literals { } // C++14 - inline namespace string_view_literals { } // C++17 - } - } - - namespace abi { } - - namespace __gnu_cxx - { - namespace __detail { } - } - - For full details see: - http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/namespaces.html -*/ -namespace std -{ - typedef __SIZE_TYPE__ size_t; - typedef __PTRDIFF_TYPE__ ptrdiff_t; - -#if __cplusplus >= 201103L - typedef decltype(nullptr) nullptr_t; -#endif -} - -# define _GLIBCXX_USE_DUAL_ABI 1 - -#ifndef _GLIBCXX_USE_DUAL_ABI -// Ignore any pre-defined value of _GLIBCXX_USE_CXX11_ABI -# undef _GLIBCXX_USE_CXX11_ABI -#endif - -#ifndef _GLIBCXX_USE_CXX11_ABI -# define _GLIBCXX_USE_CXX11_ABI 1 -#endif - -#ifdef _GLIBCXX_USE_CXX11_ABI -namespace std -{ - inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } -} -namespace __gnu_cxx -{ - inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } -} -# define _GLIBCXX_NAMESPACE_CXX11 __cxx11:: -# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 namespace __cxx11 { -# define _GLIBCXX_END_NAMESPACE_CXX11 } -# define _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_ABI_TAG_CXX11 -#else -# define _GLIBCXX_NAMESPACE_CXX11 -# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 -# define _GLIBCXX_END_NAMESPACE_CXX11 -# define _GLIBCXX_DEFAULT_ABI_TAG -#endif - -// Defined if inline namespaces are used for versioning. -//#define _GLIBCXX_INLINE_VERSION - -// Inline namespace for symbol versioning. -#ifdef _GLIBCXX_INLINE_VERSION -# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __8 { -# define _GLIBCXX_END_NAMESPACE_VERSION } - -namespace std -{ -inline _GLIBCXX_BEGIN_NAMESPACE_VERSION -#if __cplusplus >= 201402L - inline namespace literals { - inline namespace chrono_literals { } - inline namespace complex_literals { } - inline namespace string_literals { } -#if __cplusplus > 201402L - inline namespace string_view_literals { } -#endif // C++17 - } -#endif // C++14 -_GLIBCXX_END_NAMESPACE_VERSION -} - -namespace __gnu_cxx -{ -inline _GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_END_NAMESPACE_VERSION -} - -#else -# define _GLIBCXX_BEGIN_NAMESPACE_VERSION -# define _GLIBCXX_END_NAMESPACE_VERSION -#endif - -// Inline namespaces for special modes: debug, parallel. -#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) -namespace std -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Non-inline namespace for components replaced by alternates in active mode. - namespace __cxx1998 - { -# if _GLIBCXX_USE_CXX11_ABI - inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } -# endif - } - -_GLIBCXX_END_NAMESPACE_VERSION - - // Inline namespace for debug mode. -# ifdef _GLIBCXX_DEBUG - inline namespace __debug { } -# endif - - // Inline namespaces for parallel mode. -# ifdef _GLIBCXX_PARALLEL - inline namespace __parallel { } -# endif -} - -// Check for invalid usage and unsupported mixed-mode use. -# if defined(_GLIBCXX_DEBUG) && defined(_GLIBCXX_PARALLEL) -# error illegal use of multiple inlined namespaces -# endif - -// Check for invalid use due to lack for weak symbols. -# if __NO_INLINE__ && !__GXX_WEAK__ -# warning currently using inlined namespace mode which may fail \ - without inlining due to lack of weak symbols -# endif -#endif - -// Macros for namespace scope. Either namespace std:: or the name -// of some nested namespace within it corresponding to the active mode. -// _GLIBCXX_STD_A -// _GLIBCXX_STD_C -// -// Macros for opening/closing conditional namespaces. -// _GLIBCXX_BEGIN_NAMESPACE_ALGO -// _GLIBCXX_END_NAMESPACE_ALGO -// _GLIBCXX_BEGIN_NAMESPACE_CONTAINER -// _GLIBCXX_END_NAMESPACE_CONTAINER -#if defined(_GLIBCXX_DEBUG) -# define _GLIBCXX_STD_C __cxx1998 -# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER \ - namespace _GLIBCXX_STD_C { -# define _GLIBCXX_END_NAMESPACE_CONTAINER } -#else -# define _GLIBCXX_STD_C std -# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER -# define _GLIBCXX_END_NAMESPACE_CONTAINER -#endif - -#ifdef _GLIBCXX_PARALLEL -# define _GLIBCXX_STD_A __cxx1998 -# define _GLIBCXX_BEGIN_NAMESPACE_ALGO \ - namespace _GLIBCXX_STD_A { -# define _GLIBCXX_END_NAMESPACE_ALGO } -#else -# define _GLIBCXX_STD_A std -# define _GLIBCXX_BEGIN_NAMESPACE_ALGO -# define _GLIBCXX_END_NAMESPACE_ALGO -#endif - -// GLIBCXX_ABI Deprecated -// Define if compatibility should be provided for -mlong-double-64. -#undef _GLIBCXX_LONG_DOUBLE_COMPAT - -// Inline namespace for long double 128 mode. -#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ -namespace std -{ - inline namespace __gnu_cxx_ldbl128 { } -} -# define _GLIBCXX_NAMESPACE_LDBL __gnu_cxx_ldbl128:: -# define _GLIBCXX_BEGIN_NAMESPACE_LDBL namespace __gnu_cxx_ldbl128 { -# define _GLIBCXX_END_NAMESPACE_LDBL } -#else -# define _GLIBCXX_NAMESPACE_LDBL -# define _GLIBCXX_BEGIN_NAMESPACE_LDBL -# define _GLIBCXX_END_NAMESPACE_LDBL -#endif -#ifdef _GLIBCXX_USE_CXX11_ABI -# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_CXX11 -# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_CXX11 -# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_CXX11 -#else -# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_LDBL -# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_LDBL -# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_LDBL -#endif - -// Debug Mode implies checking assertions. -#if defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_ASSERTIONS) -# define _GLIBCXX_ASSERTIONS 1 -#endif - -// Disable std::string explicit instantiation declarations in order to assert. -#ifdef _GLIBCXX_ASSERTIONS -# undef _GLIBCXX_EXTERN_TEMPLATE -# define _GLIBCXX_EXTERN_TEMPLATE -1 -#endif - -// Assert. -#if defined(_GLIBCXX_ASSERTIONS) \ - || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PARALLEL_ASSERTIONS) -namespace std -{ - // Avoid the use of assert, because we're trying to keep the - // include out of the mix. - extern "C++" inline void - __replacement_assert(const char* __file, int __line, - const char* __function, const char* __condition) - { - __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, __line, - __function, __condition); - __builtin_abort(); - } -} -#define __glibcxx_assert_impl(_Condition) \ - do \ - { \ - if (! (_Condition)) \ - std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ - #_Condition); \ - } while (false) -#endif - -#if defined(_GLIBCXX_ASSERTIONS) -# define __glibcxx_assert(_Condition) __glibcxx_assert_impl(_Condition) -#else -# define __glibcxx_assert(_Condition) -#endif - -// Macros for race detectors. -// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) and -// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) should be used to explain -// atomic (lock-free) synchronization to race detectors: -// the race detector will infer a happens-before arc from the former to the -// latter when they share the same argument pointer. -// -// The most frequent use case for these macros (and the only case in the -// current implementation of the library) is atomic reference counting: -// void _M_remove_reference() -// { -// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount); -// if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount, -1) <= 0) -// { -// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount); -// _M_destroy(__a); -// } -// } -// The annotations in this example tell the race detector that all memory -// accesses occurred when the refcount was positive do not race with -// memory accesses which occurred after the refcount became zero. -#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE -# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) -#endif -#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER -# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) -#endif - -// Macros for C linkage: define extern "C" linkage only when using C++. -# define _GLIBCXX_BEGIN_EXTERN_C extern "C" { -# define _GLIBCXX_END_EXTERN_C } - -# define _GLIBCXX_USE_ALLOCATOR_NEW 1 - -#else // !__cplusplus -# define _GLIBCXX_BEGIN_EXTERN_C -# define _GLIBCXX_END_EXTERN_C -#endif - - -// First includes. - -// Pick up any OS-specific definitions. -//#include - -// Pick up any CPU-specific definitions. -//#include - -// If platform uses neither visibility nor psuedo-visibility, -// specify empty default for namespace annotation macros. -#ifndef _GLIBCXX_PSEUDO_VISIBILITY -# define _GLIBCXX_PSEUDO_VISIBILITY(V) -#endif - -// Certain function definitions that are meant to be overridable from -// user code are decorated with this macro. For some targets, this -// macro causes these definitions to be weak. -#ifndef _GLIBCXX_WEAK_DEFINITION -# define _GLIBCXX_WEAK_DEFINITION -#endif - -// By default, we assume that __GXX_WEAK__ also means that there is support -// for declaring functions as weak while not defining such functions. This -// allows for referring to functions provided by other libraries (e.g., -// libitm) without depending on them if the respective features are not used. -#ifndef _GLIBCXX_USE_WEAK_REF -# define _GLIBCXX_USE_WEAK_REF __GXX_WEAK__ -#endif - -// Conditionally enable annotations for the Transactional Memory TS on C++11. -// Most of the following conditions are due to limitations in the current -// implementation. -/*#if __cplusplus >= 201103L && _GLIBCXX_USE_CXX11_ABI \ - && _GLIBCXX_USE_DUAL_ABI && __cpp_transactional_memory >= 201505L \ - && !_GLIBCXX_FULLY_DYNAMIC_STRING && _GLIBCXX_USE_WEAK_REF \ - && _GLIBCXX_USE_ALLOCATOR_NEW -#define _GLIBCXX_TXN_SAFE transaction_safe -#define _GLIBCXX_TXN_SAFE_DYN transaction_safe_dynamic*/ -//#else -#define _GLIBCXX_TXN_SAFE -#define _GLIBCXX_TXN_SAFE_DYN -//#endif - -#if __cplusplus > 201402L -// In C++17 mathematical special functions are in namespace std. -# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 -#elif __cplusplus >= 201103L && __STDCPP_WANT_MATH_SPEC_FUNCS__ != 0 -// For C++11 and C++14 they are in namespace std when requested. -# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 -#endif - -// The remainder of the prewritten config is automatic; all the -// user hooks are listed above. - -// Create a boolean flag to be used to determine if --fast-math is set. -#ifdef __FAST_MATH__ -# define _GLIBCXX_FAST_MATH 1 -#else -# define _GLIBCXX_FAST_MATH 0 -#endif - -// This marks string literals in header files to be extracted for eventual -// translation. It is primarily used for messages in thrown exceptions; see -// src/functexcept.cc. We use __N because the more traditional _N is used -// for something else under certain OSes (see BADNAMES). - -// modm avr port: remove exception strings to save RAM -#define __N(msgid) ("") - -// For example, is known to #define min and max as macros... -#undef min -#undef max - -// N.B. these _GLIBCXX_USE_C99_XXX macros are defined unconditionally -// so they should be tested with #if not with #ifdef. -#if __cplusplus >= 201103L -# ifndef _GLIBCXX_USE_C99_MATH -# define _GLIBCXX_USE_C99_MATH _GLIBCXX11_USE_C99_MATH -# endif -# ifndef _GLIBCXX_USE_C99_COMPLEX -# define _GLIBCXX_USE_C99_COMPLEX _GLIBCXX11_USE_C99_COMPLEX -# endif -# ifndef _GLIBCXX_USE_C99_STDIO -# define _GLIBCXX_USE_C99_STDIO _GLIBCXX11_USE_C99_STDIO -# endif -# ifndef _GLIBCXX_USE_C99_STDLIB -# define _GLIBCXX_USE_C99_STDLIB _GLIBCXX11_USE_C99_STDLIB -# endif -# ifndef _GLIBCXX_USE_C99_WCHAR -# define _GLIBCXX_USE_C99_WCHAR _GLIBCXX11_USE_C99_WCHAR -# endif -#else -# ifndef _GLIBCXX_USE_C99_MATH -# define _GLIBCXX_USE_C99_MATH _GLIBCXX98_USE_C99_MATH -# endif -# ifndef _GLIBCXX_USE_C99_COMPLEX -# define _GLIBCXX_USE_C99_COMPLEX _GLIBCXX98_USE_C99_COMPLEX -# endif -# ifndef _GLIBCXX_USE_C99_STDIO -# define _GLIBCXX_USE_C99_STDIO _GLIBCXX98_USE_C99_STDIO -# endif -# ifndef _GLIBCXX_USE_C99_STDLIB -# define _GLIBCXX_USE_C99_STDLIB _GLIBCXX98_USE_C99_STDLIB -# endif -# ifndef _GLIBCXX_USE_C99_WCHAR -# define _GLIBCXX_USE_C99_WCHAR _GLIBCXX98_USE_C99_WCHAR -# endif -#endif - -// Unless explicitly specified, enable char8_t extensions only if the core -// language char8_t feature macro is defined. -#ifndef _GLIBCXX_USE_CHAR8_T -# ifdef __cpp_char8_t -# define _GLIBCXX_USE_CHAR8_T 1 -# endif -#endif -#ifdef _GLIBCXX_USE_CHAR8_T -# define __cpp_lib_char8_t 201907L -#endif - -/* Define if __float128 is supported on this host. */ -#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) -#undef _GLIBCXX_USE_FLOAT128 -#endif - -#if __GNUC__ >= 7 -// Assume these are available if the compiler claims to be a recent GCC: -# define _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP 1 -# define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 -# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 -# define _GLIBCXX_BUILTIN_IS_SAME_AS(T, U) __is_same_as(T, U) -# if __GNUC__ >= 9 -# define _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 1 -# endif -#elif defined(__is_identifier) && defined(__has_builtin) -// For non-GNU compilers: -# if ! __is_identifier(__has_unique_object_representations) -# define _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP 1 -# endif -# if ! __is_identifier(__is_aggregate) -# define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 -# endif -# if __has_builtin(__builtin_launder) -# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 -# endif -# if __has_builtin(__builtin_is_constant_evaluated) -# define _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 1 -# endif -# if ! __is_identifier(__is_same) -# define _GLIBCXX_BUILTIN_IS_SAME_AS(T, U) __is_same(T, U) -# endif -#endif // GCC - -// PSTL configuration - -#if __cplusplus >= 201703L -// This header is not installed for freestanding: -#if __has_include() -// Preserved here so we have some idea which version of upstream we've pulled in -// #define PSTL_VERSION 9000 - -// For now this defaults to being based on the presence of Thread Building Blocks -# ifndef _GLIBCXX_USE_TBB_PAR_BACKEND -# define _GLIBCXX_USE_TBB_PAR_BACKEND __has_include() -# endif -// This section will need some rework when a new (default) backend type is added -# if _GLIBCXX_USE_TBB_PAR_BACKEND -# define _PSTL_PAR_BACKEND_TBB -# else -# define _PSTL_PAR_BACKEND_SERIAL -# endif - -# define _PSTL_ASSERT(_Condition) __glibcxx_assert(_Condition) -# define _PSTL_ASSERT_MSG(_Condition, _Message) __glibcxx_assert(_Condition) - -#include -#endif // __has_include -#endif // C++17 - -// End of prewritten config; the settings discovered at configure time follow. -/* config.h. Generated from config.h.in by configure. */ -/* config.h.in. Generated from configure.ac by autoheader. */ - -/* Define to 1 if you have the `acosf' function. */ -#define _GLIBCXX_HAVE_ACOSF 1 - -/* Define to 1 if you have the `acosl' function. */ -/* #undef _GLIBCXX_HAVE_ACOSL */ - -/* Define to 1 if you have the `aligned_alloc' function. */ -/* #undef _GLIBCXX_HAVE_ALIGNED_ALLOC */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_ARPA_INET_H */ - -/* Define to 1 if you have the `asinf' function. */ -#define _GLIBCXX_HAVE_ASINF 1 - -/* Define to 1 if you have the `asinl' function. */ -/* #undef _GLIBCXX_HAVE_ASINL */ - -/* Define to 1 if the target assembler supports .symver directive. */ -#define _GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE 1 - -/* Define to 1 if you have the `atan2f' function. */ -#define _GLIBCXX_HAVE_ATAN2F 1 - -/* Define to 1 if you have the `atan2l' function. */ -/* #undef _GLIBCXX_HAVE_ATAN2L */ - -/* Define to 1 if you have the `atanf' function. */ -#define _GLIBCXX_HAVE_ATANF 1 - -/* Define to 1 if you have the `atanl' function. */ -/* #undef _GLIBCXX_HAVE_ATANL */ - -/* Defined if shared_ptr reference counting should use atomic operations. */ -/* #undef _GLIBCXX_HAVE_ATOMIC_LOCK_POLICY */ - -/* Define to 1 if you have the `at_quick_exit' function. */ -/* #undef _GLIBCXX_HAVE_AT_QUICK_EXIT */ - -/* Define to 1 if the target assembler supports thread-local storage. */ -/* #undef _GLIBCXX_HAVE_CC_TLS */ - -/* Define to 1 if you have the `ceilf' function. */ -#define _GLIBCXX_HAVE_CEILF 1 - -/* Define to 1 if you have the `ceill' function. */ -/* #undef _GLIBCXX_HAVE_CEILL */ - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_COMPLEX_H 1 - -/* Define to 1 if you have the `cosf' function. */ -#define _GLIBCXX_HAVE_COSF 1 - -/* Define to 1 if you have the `coshf' function. */ -#define _GLIBCXX_HAVE_COSHF 1 - -/* Define to 1 if you have the `coshl' function. */ -/* #undef _GLIBCXX_HAVE_COSHL */ - -/* Define to 1 if you have the `cosl' function. */ -/* #undef _GLIBCXX_HAVE_COSL */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_DIRENT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_DLFCN_H */ - -/* Define if EBADMSG exists. */ -//#define _GLIBCXX_HAVE_EBADMSG 1 - -/* Define if ECANCELED exists. */ -//#define _GLIBCXX_HAVE_ECANCELED 1 - -/* Define if ECHILD exists. */ -//#define _GLIBCXX_HAVE_ECHILD 1 - -/* Define if EIDRM exists. */ -//#define _GLIBCXX_HAVE_EIDRM 1 - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_ENDIAN_H */ - -/* Define if ENODATA exists. */ -//#define _GLIBCXX_HAVE_ENODATA 1 - -/* Define if ENOLINK exists. */ -//#define _GLIBCXX_HAVE_ENOLINK 1 - -/* Define if ENOSPC exists. */ -//#define _GLIBCXX_HAVE_ENOSPC 1 - -/* Define if ENOSR exists. */ -//#define _GLIBCXX_HAVE_ENOSR 1 - -/* Define if ENOSTR exists. */ -//#define _GLIBCXX_HAVE_ENOSTR 1 - -/* Define if ENOTRECOVERABLE exists. */ -//#define _GLIBCXX_HAVE_ENOTRECOVERABLE 1 - -/* Define if ENOTSUP exists. */ -//#define _GLIBCXX_HAVE_ENOTSUP 1 - -/* Define if EOVERFLOW exists. */ -//#define _GLIBCXX_HAVE_EOVERFLOW 1 - -/* Define if EOWNERDEAD exists. */ -//#define _GLIBCXX_HAVE_EOWNERDEAD 1 - -/* Define if EPERM exists. */ -//#define _GLIBCXX_HAVE_EPERM 1 - -/* Define if EPROTO exists. */ -//#define _GLIBCXX_HAVE_EPROTO 1 - -/* Define if ETIME exists. */ -//#define _GLIBCXX_HAVE_ETIME 1 - -/* Define if ETIMEDOUT exists. */ -//#define _GLIBCXX_HAVE_ETIMEDOUT 1 - -/* Define if ETXTBSY exists. */ -//#define _GLIBCXX_HAVE_ETXTBSY 1 - -/* Define if EWOULDBLOCK exists. */ -//#define _GLIBCXX_HAVE_EWOULDBLOCK 1 - -/* Define to 1 if GCC 4.6 supported std::exception_ptr for the target */ -/* #undef _GLIBCXX_HAVE_EXCEPTION_PTR_SINCE_GCC46 */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_EXECINFO_H */ - -/* Define to 1 if you have the `expf' function. */ -#define _GLIBCXX_HAVE_EXPF 1 - -/* Define to 1 if you have the `expl' function. */ -/* #undef _GLIBCXX_HAVE_EXPL */ - -/* Define to 1 if you have the `fabsf' function. */ -#define _GLIBCXX_HAVE_FABSF 1 - -/* Define to 1 if you have the `fabsl' function. */ -/* #undef _GLIBCXX_HAVE_FABSL */ - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_FCNTL_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_FENV_H */ - -/* Define to 1 if you have the `finite' function. */ -/* #undef _GLIBCXX_HAVE_FINITE */ - -/* Define to 1 if you have the `finitef' function. */ -/* #undef _GLIBCXX_HAVE_FINITEF */ - -/* Define to 1 if you have the `finitel' function. */ -/* #undef _GLIBCXX_HAVE_FINITEL */ - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_FLOAT_H 1 - -/* Define to 1 if you have the `floorf' function. */ -#define _GLIBCXX_HAVE_FLOORF 1 - -/* Define to 1 if you have the `floorl' function. */ -/* #undef _GLIBCXX_HAVE_FLOORL */ - -/* Define to 1 if you have the `fmodf' function. */ -#define _GLIBCXX_HAVE_FMODF 1 - -/* Define to 1 if you have the `fmodl' function. */ -/* #undef _GLIBCXX_HAVE_FMODL */ - -/* Define to 1 if you have the `fpclass' function. */ -/* #undef _GLIBCXX_HAVE_FPCLASS */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_FP_H */ - -/* Define to 1 if you have the `frexpf' function. */ -#define _GLIBCXX_HAVE_FREXPF 1 - -/* Define to 1 if you have the `frexpl' function. */ -/* #undef _GLIBCXX_HAVE_FREXPL */ - -/* Define if _Unwind_GetIPInfo is available. */ -//#define _GLIBCXX_HAVE_GETIPINFO 1 - -/* Define if gets is available in before C++14. */ -#define _GLIBCXX_HAVE_GETS 1 - -/* Define to 1 if you have the `hypot' function. */ -#define _GLIBCXX_HAVE_HYPOT 1 - -/* Define to 1 if you have the `hypotf' function. */ -/* #undef _GLIBCXX_HAVE_HYPOTF */ - -/* Define to 1 if you have the `hypotl' function. */ -/* #undef _GLIBCXX_HAVE_HYPOTL */ - -/* Define if you have the iconv() function. */ -//#define _GLIBCXX_HAVE_ICONV 1 - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_IEEEFP_H 1 - -/* Define if int64_t is available in . */ -#define _GLIBCXX_HAVE_INT64_T 1 - -/* Define if int64_t is a long. */ -/* #undef _GLIBCXX_HAVE_INT64_T_LONG */ - -/* Define if int64_t is a long long. */ -#define _GLIBCXX_HAVE_INT64_T_LONG_LONG 1 - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_INTTYPES_H 1 - -/* Define to 1 if you have the `isinf' function. */ -/* #undef _GLIBCXX_HAVE_ISINF */ - -/* Define to 1 if you have the `isinff' function. */ -/* #undef _GLIBCXX_HAVE_ISINFF */ - -/* Define to 1 if you have the `isinfl' function. */ -/* #undef _GLIBCXX_HAVE_ISINFL */ - -/* Define to 1 if you have the `isnan' function. */ -/* #undef _GLIBCXX_HAVE_ISNAN */ - -/* Define to 1 if you have the `isnanf' function. */ -/* #undef _GLIBCXX_HAVE_ISNANF */ - -/* Define to 1 if you have the `isnanl' function. */ -/* #undef _GLIBCXX_HAVE_ISNANL */ - -/* Defined if iswblank exists. */ -//#define _GLIBCXX_HAVE_ISWBLANK 1 - -/* Define if LC_MESSAGES is available in . */ -#define _GLIBCXX_HAVE_LC_MESSAGES 1 - -/* Define to 1 if you have the `ldexpf' function. */ -#define _GLIBCXX_HAVE_LDEXPF 1 - -/* Define to 1 if you have the `ldexpl' function. */ -/* #undef _GLIBCXX_HAVE_LDEXPL */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_LIBINTL_H */ - -/* Only used in build directory testsuite_hooks.h. */ -#define _GLIBCXX_HAVE_LIMIT_AS 0 - -/* Only used in build directory testsuite_hooks.h. */ -#define _GLIBCXX_HAVE_LIMIT_DATA 0 - -/* Only used in build directory testsuite_hooks.h. */ -#define _GLIBCXX_HAVE_LIMIT_FSIZE 0 - -/* Only used in build directory testsuite_hooks.h. */ -#define _GLIBCXX_HAVE_LIMIT_RSS 0 - -/* Only used in build directory testsuite_hooks.h. */ -#define _GLIBCXX_HAVE_LIMIT_VMEM 0 - -/* Define if futex syscall is available. */ -/* #undef _GLIBCXX_HAVE_LINUX_FUTEX */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_LINUX_RANDOM_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_LINUX_TYPES_H */ - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_LOCALE_H 1 - -/* Define to 1 if you have the `log10f' function. */ -#define _GLIBCXX_HAVE_LOG10F 1 - -/* Define to 1 if you have the `log10l' function. */ -/* #undef _GLIBCXX_HAVE_LOG10L */ - -/* Define to 1 if you have the `logf' function. */ -#define _GLIBCXX_HAVE_LOGF 1 - -/* Define to 1 if you have the `logl' function. */ -/* #undef _GLIBCXX_HAVE_LOGL */ - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_MACHINE_ENDIAN_H 1 - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_MACHINE_PARAM_H 1 - -/* Define if mbstate_t exists in wchar.h. */ -//#define _GLIBCXX_HAVE_MBSTATE_T 1 - -/* Define to 1 if you have the `memalign' function. */ -//#define _GLIBCXX_HAVE_MEMALIGN 1 - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_MEMORY_H 1 - -/* Define to 1 if you have the `modf' function. */ -/* #undef _GLIBCXX_HAVE_MODF */ - -/* Define to 1 if you have the `modff' function. */ -#define _GLIBCXX_HAVE_MODFF 1 - -/* Define to 1 if you have the `modfl' function. */ -/* #undef _GLIBCXX_HAVE_MODFL */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_NAN_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_NETDB_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_NETINET_IN_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_NETINET_TCP_H */ - -/* Define if defines obsolete isinf function. */ -/* #undef _GLIBCXX_HAVE_OBSOLETE_ISINF */ - -/* Define if defines obsolete isnan function. */ -/* #undef _GLIBCXX_HAVE_OBSOLETE_ISNAN */ - -/* Define if poll is available in . */ -/* #undef _GLIBCXX_HAVE_POLL */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_POLL_H */ - -/* Define to 1 if you have the `posix_memalign' function. */ -/* #undef _GLIBCXX_HAVE_POSIX_MEMALIGN */ - -/* Define to 1 if you have the `powf' function. */ -#define _GLIBCXX_HAVE_POWF 1 - -/* Define to 1 if you have the `powl' function. */ -/* #undef _GLIBCXX_HAVE_POWL */ - -/* Define to 1 if you have the `qfpclass' function. */ -/* #undef _GLIBCXX_HAVE_QFPCLASS */ - -/* Define to 1 if you have the `quick_exit' function. */ -/* #undef _GLIBCXX_HAVE_QUICK_EXIT */ - -/* Define to 1 if you have the `setenv' function. */ -/* #undef _GLIBCXX_HAVE_SETENV */ - -/* Define to 1 if you have the `sincos' function. */ -/* #undef _GLIBCXX_HAVE_SINCOS */ - -/* Define to 1 if you have the `sincosf' function. */ -/* #undef _GLIBCXX_HAVE_SINCOSF */ - -/* Define to 1 if you have the `sincosl' function. */ -/* #undef _GLIBCXX_HAVE_SINCOSL */ - -/* Define to 1 if you have the `sinf' function. */ -#define _GLIBCXX_HAVE_SINF 1 - -/* Define to 1 if you have the `sinhf' function. */ -#define _GLIBCXX_HAVE_SINHF 1 - -/* Define to 1 if you have the `sinhl' function. */ -/* #undef _GLIBCXX_HAVE_SINHL */ - -/* Define to 1 if you have the `sinl' function. */ -/* #undef _GLIBCXX_HAVE_SINL */ - -/* Defined if sleep exists. */ -//#define _GLIBCXX_HAVE_SLEEP 1 - -/* Define to 1 if you have the `sqrtf' function. */ -#define _GLIBCXX_HAVE_SQRTF 1 - -/* Define to 1 if you have the `sqrtl' function. */ -/* #undef _GLIBCXX_HAVE_SQRTL */ - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_STDALIGN_H 1 - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_STDBOOL_H 1 - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_STDINT_H 1 - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_STDLIB_H 1 - -/* Define if strerror_l is available in . */ -/* #undef _GLIBCXX_HAVE_STRERROR_L */ - -/* Define if strerror_r is available in . */ -#define _GLIBCXX_HAVE_STRERROR_R 1 - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_STRINGS_H 1 - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_STRING_H 1 - -/* Define to 1 if you have the `strtof' function. */ -#define _GLIBCXX_HAVE_STRTOF 1 - -/* Define to 1 if you have the `strtold' function. */ -/* #undef _GLIBCXX_HAVE_STRTOLD */ - -/* Define to 1 if `d_type' is a member of `struct dirent'. */ -/* #undef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE */ - -/* Define if strxfrm_l is available in . */ -/* #undef _GLIBCXX_HAVE_STRXFRM_L */ - -/* Define to 1 if the target runtime linker supports binding the same symbol - to different versions. */ -/* #undef _GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_FILIO_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_IOCTL_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_IPC_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_ISA_DEFS_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_MACHINE_H */ - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_SYS_PARAM_H 1 - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_SYS_RESOURCE_H 1 - -/* Define to 1 if you have a suitable header file */ -/* #undef _GLIBCXX_HAVE_SYS_SDT_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_SEM_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_SOCKET_H */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_STATVFS_H */ - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_SYS_STAT_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_SYSINFO_H */ - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_SYS_TIME_H 1 - -/* Define to 1 if you have the header file. */ -#define _GLIBCXX_HAVE_SYS_TYPES_H 1 - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_SYS_UIO_H */ - -/* Define if S_IFREG is available in . */ -/* #undef _GLIBCXX_HAVE_S_IFREG */ - -/* Define if S_ISREG is available in . */ -//#define _GLIBCXX_HAVE_S_ISREG 1 - -/* Define to 1 if you have the `tanf' function. */ -#define _GLIBCXX_HAVE_TANF 1 - -/* Define to 1 if you have the `tanhf' function. */ -#define _GLIBCXX_HAVE_TANHF 1 - -/* Define to 1 if you have the `tanhl' function. */ -/* #undef _GLIBCXX_HAVE_TANHL */ - -/* Define to 1 if you have the `tanl' function. */ -/* #undef _GLIBCXX_HAVE_TANL */ - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_TGMATH_H 1 - -/* Define to 1 if you have the `timespec_get' function. */ -/* #undef _GLIBCXX_HAVE_TIMESPEC_GET */ - -/* Define to 1 if the target supports thread-local storage. */ -/* #undef _GLIBCXX_HAVE_TLS */ - -/* Define to 1 if you have the header file. */ -/* #undef _GLIBCXX_HAVE_UCHAR_H */ - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_UNISTD_H 1 - -/* Defined if usleep exists. */ -//#define _GLIBCXX_HAVE_USLEEP 1 - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_UTIME_H 1 - -/* Defined if vfwscanf exists. */ -//#define _GLIBCXX_HAVE_VFWSCANF 1 - -/* Defined if vswscanf exists. */ -//#define _GLIBCXX_HAVE_VSWSCANF 1 - -/* Defined if vwscanf exists. */ -//#define _GLIBCXX_HAVE_VWSCANF 1 - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_WCHAR_H 1 - -/* Defined if wcstof exists. */ -//#define _GLIBCXX_HAVE_WCSTOF 1 - -/* Define to 1 if you have the header file. */ -//#define _GLIBCXX_HAVE_WCTYPE_H 1 - -/* Defined if Sleep exists. */ -/* #undef _GLIBCXX_HAVE_WIN32_SLEEP */ - -/* Define if writev is available in . */ -/* #undef _GLIBCXX_HAVE_WRITEV */ - -/* Define to 1 if you have the `_acosf' function. */ -/* #undef _GLIBCXX_HAVE__ACOSF */ - -/* Define to 1 if you have the `_acosl' function. */ -/* #undef _GLIBCXX_HAVE__ACOSL */ - -/* Define to 1 if you have the `_aligned_malloc' function. */ -/* #undef _GLIBCXX_HAVE__ALIGNED_MALLOC */ - -/* Define to 1 if you have the `_asinf' function. */ -/* #undef _GLIBCXX_HAVE__ASINF */ - -/* Define to 1 if you have the `_asinl' function. */ -/* #undef _GLIBCXX_HAVE__ASINL */ - -/* Define to 1 if you have the `_atan2f' function. */ -/* #undef _GLIBCXX_HAVE__ATAN2F */ - -/* Define to 1 if you have the `_atan2l' function. */ -/* #undef _GLIBCXX_HAVE__ATAN2L */ - -/* Define to 1 if you have the `_atanf' function. */ -/* #undef _GLIBCXX_HAVE__ATANF */ - -/* Define to 1 if you have the `_atanl' function. */ -/* #undef _GLIBCXX_HAVE__ATANL */ - -/* Define to 1 if you have the `_ceilf' function. */ -/* #undef _GLIBCXX_HAVE__CEILF */ - -/* Define to 1 if you have the `_ceill' function. */ -/* #undef _GLIBCXX_HAVE__CEILL */ - -/* Define to 1 if you have the `_cosf' function. */ -/* #undef _GLIBCXX_HAVE__COSF */ - -/* Define to 1 if you have the `_coshf' function. */ -/* #undef _GLIBCXX_HAVE__COSHF */ - -/* Define to 1 if you have the `_coshl' function. */ -/* #undef _GLIBCXX_HAVE__COSHL */ - -/* Define to 1 if you have the `_cosl' function. */ -/* #undef _GLIBCXX_HAVE__COSL */ - -/* Define to 1 if you have the `_expf' function. */ -/* #undef _GLIBCXX_HAVE__EXPF */ - -/* Define to 1 if you have the `_expl' function. */ -/* #undef _GLIBCXX_HAVE__EXPL */ - -/* Define to 1 if you have the `_fabsf' function. */ -/* #undef _GLIBCXX_HAVE__FABSF */ - -/* Define to 1 if you have the `_fabsl' function. */ -/* #undef _GLIBCXX_HAVE__FABSL */ - -/* Define to 1 if you have the `_finite' function. */ -/* #undef _GLIBCXX_HAVE__FINITE */ - -/* Define to 1 if you have the `_finitef' function. */ -/* #undef _GLIBCXX_HAVE__FINITEF */ - -/* Define to 1 if you have the `_finitel' function. */ -/* #undef _GLIBCXX_HAVE__FINITEL */ - -/* Define to 1 if you have the `_floorf' function. */ -/* #undef _GLIBCXX_HAVE__FLOORF */ - -/* Define to 1 if you have the `_floorl' function. */ -/* #undef _GLIBCXX_HAVE__FLOORL */ - -/* Define to 1 if you have the `_fmodf' function. */ -/* #undef _GLIBCXX_HAVE__FMODF */ - -/* Define to 1 if you have the `_fmodl' function. */ -/* #undef _GLIBCXX_HAVE__FMODL */ - -/* Define to 1 if you have the `_fpclass' function. */ -/* #undef _GLIBCXX_HAVE__FPCLASS */ - -/* Define to 1 if you have the `_frexpf' function. */ -/* #undef _GLIBCXX_HAVE__FREXPF */ - -/* Define to 1 if you have the `_frexpl' function. */ -/* #undef _GLIBCXX_HAVE__FREXPL */ - -/* Define to 1 if you have the `_hypot' function. */ -/* #undef _GLIBCXX_HAVE__HYPOT */ - -/* Define to 1 if you have the `_hypotf' function. */ -/* #undef _GLIBCXX_HAVE__HYPOTF */ - -/* Define to 1 if you have the `_hypotl' function. */ -/* #undef _GLIBCXX_HAVE__HYPOTL */ - -/* Define to 1 if you have the `_isinf' function. */ -/* #undef _GLIBCXX_HAVE__ISINF */ - -/* Define to 1 if you have the `_isinff' function. */ -/* #undef _GLIBCXX_HAVE__ISINFF */ - -/* Define to 1 if you have the `_isinfl' function. */ -/* #undef _GLIBCXX_HAVE__ISINFL */ - -/* Define to 1 if you have the `_isnan' function. */ -/* #undef _GLIBCXX_HAVE__ISNAN */ - -/* Define to 1 if you have the `_isnanf' function. */ -/* #undef _GLIBCXX_HAVE__ISNANF */ - -/* Define to 1 if you have the `_isnanl' function. */ -/* #undef _GLIBCXX_HAVE__ISNANL */ - -/* Define to 1 if you have the `_ldexpf' function. */ -/* #undef _GLIBCXX_HAVE__LDEXPF */ - -/* Define to 1 if you have the `_ldexpl' function. */ -/* #undef _GLIBCXX_HAVE__LDEXPL */ - -/* Define to 1 if you have the `_log10f' function. */ -/* #undef _GLIBCXX_HAVE__LOG10F */ - -/* Define to 1 if you have the `_log10l' function. */ -/* #undef _GLIBCXX_HAVE__LOG10L */ - -/* Define to 1 if you have the `_logf' function. */ -/* #undef _GLIBCXX_HAVE__LOGF */ - -/* Define to 1 if you have the `_logl' function. */ -/* #undef _GLIBCXX_HAVE__LOGL */ - -/* Define to 1 if you have the `_modf' function. */ -/* #undef _GLIBCXX_HAVE__MODF */ - -/* Define to 1 if you have the `_modff' function. */ -/* #undef _GLIBCXX_HAVE__MODFF */ - -/* Define to 1 if you have the `_modfl' function. */ -/* #undef _GLIBCXX_HAVE__MODFL */ - -/* Define to 1 if you have the `_powf' function. */ -/* #undef _GLIBCXX_HAVE__POWF */ - -/* Define to 1 if you have the `_powl' function. */ -/* #undef _GLIBCXX_HAVE__POWL */ - -/* Define to 1 if you have the `_qfpclass' function. */ -/* #undef _GLIBCXX_HAVE__QFPCLASS */ - -/* Define to 1 if you have the `_sincos' function. */ -/* #undef _GLIBCXX_HAVE__SINCOS */ - -/* Define to 1 if you have the `_sincosf' function. */ -/* #undef _GLIBCXX_HAVE__SINCOSF */ - -/* Define to 1 if you have the `_sincosl' function. */ -/* #undef _GLIBCXX_HAVE__SINCOSL */ - -/* Define to 1 if you have the `_sinf' function. */ -/* #undef _GLIBCXX_HAVE__SINF */ - -/* Define to 1 if you have the `_sinhf' function. */ -/* #undef _GLIBCXX_HAVE__SINHF */ - -/* Define to 1 if you have the `_sinhl' function. */ -/* #undef _GLIBCXX_HAVE__SINHL */ - -/* Define to 1 if you have the `_sinl' function. */ -/* #undef _GLIBCXX_HAVE__SINL */ - -/* Define to 1 if you have the `_sqrtf' function. */ -/* #undef _GLIBCXX_HAVE__SQRTF */ - -/* Define to 1 if you have the `_sqrtl' function. */ -/* #undef _GLIBCXX_HAVE__SQRTL */ - -/* Define to 1 if you have the `_tanf' function. */ -/* #undef _GLIBCXX_HAVE__TANF */ - -/* Define to 1 if you have the `_tanhf' function. */ -/* #undef _GLIBCXX_HAVE__TANHF */ - -/* Define to 1 if you have the `_tanhl' function. */ -/* #undef _GLIBCXX_HAVE__TANHL */ - -/* Define to 1 if you have the `_tanl' function. */ -/* #undef _GLIBCXX_HAVE__TANL */ - -/* Define to 1 if you have the `_wfopen' function. */ -/* #undef _GLIBCXX_HAVE__WFOPEN */ - -/* Define to 1 if you have the `__cxa_thread_atexit' function. */ -/* #undef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT */ - -/* Define to 1 if you have the `__cxa_thread_atexit_impl' function. */ -/* #undef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */ - -/* Define as const if the declaration of iconv() needs const. */ -/* #undef _GLIBCXX_ICONV_CONST */ - -/* Define to the sub-directory in which libtool stores uninstalled libraries. - */ -#define LT_OBJDIR ".libs/" - -/* Name of package */ -/* #undef _GLIBCXX_PACKAGE */ - -/* Define to the address where bug reports for this package should be sent. */ -#define _GLIBCXX_PACKAGE_BUGREPORT "" - -/* Define to the full name of this package. */ -#define _GLIBCXX_PACKAGE_NAME "package-unused" - -/* Define to the full name and version of this package. */ -#define _GLIBCXX_PACKAGE_STRING "package-unused version-unused" - -/* Define to the one symbol short name of this package. */ -#define _GLIBCXX_PACKAGE_TARNAME "libstdc++" - -/* Define to the home page for this package. */ -#define _GLIBCXX_PACKAGE_URL "" - -/* Define to the version of this package. */ -#define _GLIBCXX_PACKAGE__GLIBCXX_VERSION "version-unused" - -/* The size of `char', as computed by sizeof. */ -/* #undef SIZEOF_CHAR */ - -/* The size of `int', as computed by sizeof. */ -/* #undef SIZEOF_INT */ - -/* The size of `long', as computed by sizeof. */ -/* #undef SIZEOF_LONG */ - -/* The size of `short', as computed by sizeof. */ -/* #undef SIZEOF_SHORT */ - -/* The size of `void *', as computed by sizeof. */ -/* #undef SIZEOF_VOID_P */ - -/* Define to 1 if you have the ANSI C header files. */ -#define STDC_HEADERS 1 - -/* Version number of package */ -/* #undef _GLIBCXX_VERSION */ - -/* Number of bits in a file offset, on hosts where this is settable. */ -/* #undef _GLIBCXX_FILE_OFFSET_BITS */ - -/* Define if C99 functions in should be used in for - C++11. Using compiler builtins for these functions requires corresponding - C99 library functions to be present. */ -/* #undef _GLIBCXX11_USE_C99_COMPLEX */ - -/* Define if C99 functions or macros in should be imported in - in namespace std for C++11. */ -#define _GLIBCXX11_USE_C99_MATH 1 - -/* Define if C99 functions or macros in should be imported in - in namespace std for C++11. */ -#define _GLIBCXX11_USE_C99_STDIO 1 - -/* Define if C99 functions or macros in should be imported in - in namespace std for C++11. */ -#define _GLIBCXX11_USE_C99_STDLIB 1 - -/* Define if C99 functions or macros in should be imported in - in namespace std for C++11. */ -//#define _GLIBCXX11_USE_C99_WCHAR 1 - -/* Define if C99 functions in should be used in for - C++98. Using compiler builtins for these functions requires corresponding - C99 library functions to be present. */ -/* #undef _GLIBCXX98_USE_C99_COMPLEX */ - -/* Define if C99 functions or macros in should be imported in - in namespace std for C++98. */ -#define _GLIBCXX98_USE_C99_MATH 1 - -/* Define if C99 functions or macros in should be imported in - in namespace std for C++98. */ -#define _GLIBCXX98_USE_C99_STDIO 1 - -/* Define if C99 functions or macros in should be imported in - in namespace std for C++98. */ -#define _GLIBCXX98_USE_C99_STDLIB 1 - -/* Define if C99 functions or macros in should be imported in - in namespace std for C++98. */ -//#define _GLIBCXX98_USE_C99_WCHAR 1 - -/* Define if the compiler supports C++11 atomics. */ -/* #undef _GLIBCXX_ATOMIC_BUILTINS */ - -/* Define to use concept checking code from the boost libraries. */ -/* #undef _GLIBCXX_CONCEPT_CHECKS */ - -/* Define to 1 if a fully dynamic basic_string is wanted, 0 to disable, - undefined for platform defaults */ -#define _GLIBCXX_FULLY_DYNAMIC_STRING 0 - -/* Define if gthreads library is available. */ -/* #undef _GLIBCXX_HAS_GTHREADS */ - -/* Define to 1 if a full hosted library is built, or 0 if freestanding. */ -#define _GLIBCXX_HOSTED 1 - -/* Define if compatibility should be provided for -mlong-double-64. */ - -/* Define to the letter to which size_t is mangled. */ -#define _GLIBCXX_MANGLE_SIZE_T j - -/* Define if C99 llrint and llround functions are missing from . */ -#define _GLIBCXX_NO_C99_ROUNDING_FUNCS - -/* Define if ptrdiff_t is int. */ -#define _GLIBCXX_PTRDIFF_T_IS_INT 1 - -/* Define if using setrlimit to set resource limits during "make check" */ -/* #undef _GLIBCXX_RES_LIMITS */ - -/* Define if size_t is unsigned int. */ -#define _GLIBCXX_SIZE_T_IS_UINT 1 - -/* Define to the value of the EOF integer constant. */ -#define _GLIBCXX_STDIO_EOF -1 - -/* Define to the value of the SEEK_CUR integer constant. */ -#define _GLIBCXX_STDIO_SEEK_CUR 1 - -/* Define to the value of the SEEK_END integer constant. */ -#define _GLIBCXX_STDIO_SEEK_END 2 - -/* Define to use symbol versioning in the shared library. */ -/* #undef _GLIBCXX_SYMVER */ - -/* Define to use darwin versioning in the shared library. */ -/* #undef _GLIBCXX_SYMVER_DARWIN */ - -/* Define to use GNU versioning in the shared library. */ -/* #undef _GLIBCXX_SYMVER_GNU */ - -/* Define to use GNU namespace versioning in the shared library. */ -/* #undef _GLIBCXX_SYMVER_GNU_NAMESPACE */ - -/* Define to use Sun versioning in the shared library. */ -/* #undef _GLIBCXX_SYMVER_SUN */ - -/* Define if C11 functions in should be imported into namespace std - in . */ -/* #undef _GLIBCXX_USE_C11_UCHAR_CXX11 */ - -/* Define if C99 functions or macros from , , , - , and can be used or exposed. */ -/* #undef _GLIBCXX_USE_C99 */ - -/* Define if C99 functions in should be used in . - Using compiler builtins for these functions requires corresponding C99 - library functions to be present. */ -/* #undef _GLIBCXX_USE_C99_COMPLEX_TR1 */ - -/* Define if C99 functions in should be imported in in - namespace std::tr1. */ -#define _GLIBCXX_USE_C99_CTYPE_TR1 1 - -/* Define if C99 functions in should be imported in in - namespace std::tr1. */ -/* #undef _GLIBCXX_USE_C99_FENV_TR1 */ - -/* Define if C99 functions in should be imported in - in namespace std::tr1. */ -#define _GLIBCXX_USE_C99_INTTYPES_TR1 1 - -/* Define if wchar_t C99 functions in should be imported in - in namespace std::tr1. */ -#define _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1 1 - -/* Define if C99 functions or macros in should be imported in - in namespace std::tr1. */ -#define _GLIBCXX_USE_C99_MATH_TR1 1 - -/* Define if C99 types in should be imported in in - namespace std::tr1. */ -#define _GLIBCXX_USE_C99_STDINT_TR1 1 - -/* Defined if clock_gettime syscall has monotonic and realtime clock support. - */ -/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */ - -/* Defined if clock_gettime has monotonic clock support. */ -/* #undef _GLIBCXX_USE_CLOCK_MONOTONIC */ - -/* Defined if clock_gettime has realtime clock support. */ -/* #undef _GLIBCXX_USE_CLOCK_REALTIME */ - -/* Define if ISO/IEC TR 24733 decimal floating point types are supported on - this host. */ -/* #undef _GLIBCXX_USE_DECIMAL_FLOAT */ - -/* Define if /dev/random and /dev/urandom are available for - std::random_device. */ -/* #undef _GLIBCXX_USE_DEV_RANDOM */ - -/* Define if fchmod is available in . */ -//#define _GLIBCXX_USE_FCHMOD 1 - -/* Define if fchmodat is available in . */ -//#define _GLIBCXX_USE_FCHMODAT 1 - - -/* Defined if gettimeofday is available. */ -//#define _GLIBCXX_USE_GETTIMEOFDAY 1 - -/* Define if get_nprocs is available in . */ -/* #undef _GLIBCXX_USE_GET_NPROCS */ - -/* Define if __int128 is supported on this host. */ -/* #undef _GLIBCXX_USE_INT128 */ - -/* Define if LFS support is available. */ -/* #undef _GLIBCXX_USE_LFS */ - -/* Define if code specialized for long long should be used. */ -#define _GLIBCXX_USE_LONG_LONG 1 - -/* Define if lstat is available in . */ -/* #undef _GLIBCXX_USE_LSTAT */ - -/* Defined if nanosleep is available. */ -/* #undef _GLIBCXX_USE_NANOSLEEP */ - -/* Define if NLS translations are to be used. */ -/* #undef _GLIBCXX_USE_NLS */ - -/* Define if pthreads_num_processors_np is available in . */ -/* #undef _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP */ - -/* Define if pthread_cond_clockwait is available in . */ -/* #undef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT */ - -/* Define if pthread_mutex_clocklock is available in . */ -/* #undef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK */ - -/* Define if pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock are - available in . */ -/* #undef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK */ - -/* Define if POSIX read/write locks are available in . */ -/* #undef _GLIBCXX_USE_PTHREAD_RWLOCK_T */ - -/* Define if /dev/random and /dev/urandom are available for the random_device - of TR1 (Chapter 5.1). */ -/* #undef _GLIBCXX_USE_RANDOM_TR1 */ - -/* Define if usable realpath is available in . */ -/* #undef _GLIBCXX_USE_REALPATH */ - -/* Defined if sched_yield is available. */ -/* #undef _GLIBCXX_USE_SCHED_YIELD */ - -/* Define if _SC_NPROCESSORS_ONLN is available in . */ -//#define _GLIBCXX_USE_SC_NPROCESSORS_ONLN 1 - -/* Define if _SC_NPROC_ONLN is available in . */ -/* #undef _GLIBCXX_USE_SC_NPROC_ONLN */ - -/* Define if sendfile is available in . */ -/* #undef _GLIBCXX_USE_SENDFILE */ - -/* Define if struct stat has timespec members. */ -/* #undef _GLIBCXX_USE_ST_MTIM */ - -/* Define if sysctl(), CTL_HW and HW_NCPU are available in . */ -/* #undef _GLIBCXX_USE_SYSCTL_HW_NCPU */ - -/* Define if obsolescent tmpnam is available in . */ -#define _GLIBCXX_USE_TMPNAM 1 - -/* Define if utimensat and UTIME_OMIT are available in and - AT_FDCWD in . */ -/* #undef _GLIBCXX_USE_UTIMENSAT */ - -/* Define if code specialized for wchar_t should be used. */ -//#define _GLIBCXX_USE_WCHAR_T 1 - -/* Define to 1 if a verbose library is built, or 0 otherwise. */ -#define _GLIBCXX_VERBOSE 1 - -/* Defined if as can handle rdrand. */ -/* #undef _GLIBCXX_X86_RDRAND */ - -/* Defined if as can handle rdseed. */ -/* #undef _GLIBCXX_X86_RDSEED */ - -/* Define to 1 if mutex_timedlock is available. */ -//#define _GTHREAD_USE_MUTEX_TIMEDLOCK 1 - -/* Define for large files, on AIX-style hosts. */ -/* #undef _GLIBCXX_LARGE_FILES */ - -/* Define if all C++11 floating point overloads are available in . */ -#if __cplusplus >= 201103L -/* #undef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP */ -#endif - -/* Define if all C++11 integral type overloads are available in . */ -#if __cplusplus >= 201103L -/* #undef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT */ -#endif - -#if defined (_GLIBCXX_HAVE__ACOSF) && ! defined (_GLIBCXX_HAVE_ACOSF) -# define _GLIBCXX_HAVE_ACOSF 1 -# define acosf _acosf -#endif - -#if defined (_GLIBCXX_HAVE__ACOSL) && ! defined (_GLIBCXX_HAVE_ACOSL) -# define _GLIBCXX_HAVE_ACOSL 1 -# define acosl _acosl -#endif - -#if defined (_GLIBCXX_HAVE__ASINF) && ! defined (_GLIBCXX_HAVE_ASINF) -# define _GLIBCXX_HAVE_ASINF 1 -# define asinf _asinf -#endif - -#if defined (_GLIBCXX_HAVE__ASINL) && ! defined (_GLIBCXX_HAVE_ASINL) -# define _GLIBCXX_HAVE_ASINL 1 -# define asinl _asinl -#endif - -#if defined (_GLIBCXX_HAVE__ATAN2F) && ! defined (_GLIBCXX_HAVE_ATAN2F) -# define _GLIBCXX_HAVE_ATAN2F 1 -# define atan2f _atan2f -#endif - -#if defined (_GLIBCXX_HAVE__ATAN2L) && ! defined (_GLIBCXX_HAVE_ATAN2L) -# define _GLIBCXX_HAVE_ATAN2L 1 -# define atan2l _atan2l -#endif - -#if defined (_GLIBCXX_HAVE__ATANF) && ! defined (_GLIBCXX_HAVE_ATANF) -# define _GLIBCXX_HAVE_ATANF 1 -# define atanf _atanf -#endif - -#if defined (_GLIBCXX_HAVE__ATANL) && ! defined (_GLIBCXX_HAVE_ATANL) -# define _GLIBCXX_HAVE_ATANL 1 -# define atanl _atanl -#endif - -#if defined (_GLIBCXX_HAVE__CEILF) && ! defined (_GLIBCXX_HAVE_CEILF) -# define _GLIBCXX_HAVE_CEILF 1 -# define ceilf _ceilf -#endif - -#if defined (_GLIBCXX_HAVE__CEILL) && ! defined (_GLIBCXX_HAVE_CEILL) -# define _GLIBCXX_HAVE_CEILL 1 -# define ceill _ceill -#endif - -#if defined (_GLIBCXX_HAVE__COSF) && ! defined (_GLIBCXX_HAVE_COSF) -# define _GLIBCXX_HAVE_COSF 1 -# define cosf _cosf -#endif - -#if defined (_GLIBCXX_HAVE__COSHF) && ! defined (_GLIBCXX_HAVE_COSHF) -# define _GLIBCXX_HAVE_COSHF 1 -# define coshf _coshf -#endif - -#if defined (_GLIBCXX_HAVE__COSHL) && ! defined (_GLIBCXX_HAVE_COSHL) -# define _GLIBCXX_HAVE_COSHL 1 -# define coshl _coshl -#endif - -#if defined (_GLIBCXX_HAVE__COSL) && ! defined (_GLIBCXX_HAVE_COSL) -# define _GLIBCXX_HAVE_COSL 1 -# define cosl _cosl -#endif - -#if defined (_GLIBCXX_HAVE__EXPF) && ! defined (_GLIBCXX_HAVE_EXPF) -# define _GLIBCXX_HAVE_EXPF 1 -# define expf _expf -#endif - -#if defined (_GLIBCXX_HAVE__EXPL) && ! defined (_GLIBCXX_HAVE_EXPL) -# define _GLIBCXX_HAVE_EXPL 1 -# define expl _expl -#endif - -#if defined (_GLIBCXX_HAVE__FABSF) && ! defined (_GLIBCXX_HAVE_FABSF) -# define _GLIBCXX_HAVE_FABSF 1 -# define fabsf _fabsf -#endif - -#if defined (_GLIBCXX_HAVE__FABSL) && ! defined (_GLIBCXX_HAVE_FABSL) -# define _GLIBCXX_HAVE_FABSL 1 -# define fabsl _fabsl -#endif - -#if defined (_GLIBCXX_HAVE__FINITE) && ! defined (_GLIBCXX_HAVE_FINITE) -# define _GLIBCXX_HAVE_FINITE 1 -# define finite _finite -#endif - -#if defined (_GLIBCXX_HAVE__FINITEF) && ! defined (_GLIBCXX_HAVE_FINITEF) -# define _GLIBCXX_HAVE_FINITEF 1 -# define finitef _finitef -#endif - -#if defined (_GLIBCXX_HAVE__FINITEL) && ! defined (_GLIBCXX_HAVE_FINITEL) -# define _GLIBCXX_HAVE_FINITEL 1 -# define finitel _finitel -#endif - -#if defined (_GLIBCXX_HAVE__FLOORF) && ! defined (_GLIBCXX_HAVE_FLOORF) -# define _GLIBCXX_HAVE_FLOORF 1 -# define floorf _floorf -#endif - -#if defined (_GLIBCXX_HAVE__FLOORL) && ! defined (_GLIBCXX_HAVE_FLOORL) -# define _GLIBCXX_HAVE_FLOORL 1 -# define floorl _floorl -#endif - -#if defined (_GLIBCXX_HAVE__FMODF) && ! defined (_GLIBCXX_HAVE_FMODF) -# define _GLIBCXX_HAVE_FMODF 1 -# define fmodf _fmodf -#endif - -#if defined (_GLIBCXX_HAVE__FMODL) && ! defined (_GLIBCXX_HAVE_FMODL) -# define _GLIBCXX_HAVE_FMODL 1 -# define fmodl _fmodl -#endif - -#if defined (_GLIBCXX_HAVE__FPCLASS) && ! defined (_GLIBCXX_HAVE_FPCLASS) -# define _GLIBCXX_HAVE_FPCLASS 1 -# define fpclass _fpclass -#endif - -#if defined (_GLIBCXX_HAVE__FREXPF) && ! defined (_GLIBCXX_HAVE_FREXPF) -# define _GLIBCXX_HAVE_FREXPF 1 -# define frexpf _frexpf -#endif - -#if defined (_GLIBCXX_HAVE__FREXPL) && ! defined (_GLIBCXX_HAVE_FREXPL) -# define _GLIBCXX_HAVE_FREXPL 1 -# define frexpl _frexpl -#endif - -#if defined (_GLIBCXX_HAVE__HYPOT) && ! defined (_GLIBCXX_HAVE_HYPOT) -# define _GLIBCXX_HAVE_HYPOT 1 -# define hypot _hypot -#endif - -#if defined (_GLIBCXX_HAVE__HYPOTF) && ! defined (_GLIBCXX_HAVE_HYPOTF) -# define _GLIBCXX_HAVE_HYPOTF 1 -# define hypotf _hypotf -#endif - -#if defined (_GLIBCXX_HAVE__HYPOTL) && ! defined (_GLIBCXX_HAVE_HYPOTL) -# define _GLIBCXX_HAVE_HYPOTL 1 -# define hypotl _hypotl -#endif - -#if defined (_GLIBCXX_HAVE__ISINF) && ! defined (_GLIBCXX_HAVE_ISINF) -# define _GLIBCXX_HAVE_ISINF 1 -# define isinf _isinf -#endif - -#if defined (_GLIBCXX_HAVE__ISINFF) && ! defined (_GLIBCXX_HAVE_ISINFF) -# define _GLIBCXX_HAVE_ISINFF 1 -# define isinff _isinff -#endif - -#if defined (_GLIBCXX_HAVE__ISINFL) && ! defined (_GLIBCXX_HAVE_ISINFL) -# define _GLIBCXX_HAVE_ISINFL 1 -# define isinfl _isinfl -#endif - -#if defined (_GLIBCXX_HAVE__ISNAN) && ! defined (_GLIBCXX_HAVE_ISNAN) -# define _GLIBCXX_HAVE_ISNAN 1 -# define isnan _isnan -#endif - -#if defined (_GLIBCXX_HAVE__ISNANF) && ! defined (_GLIBCXX_HAVE_ISNANF) -# define _GLIBCXX_HAVE_ISNANF 1 -# define isnanf _isnanf -#endif - -#if defined (_GLIBCXX_HAVE__ISNANL) && ! defined (_GLIBCXX_HAVE_ISNANL) -# define _GLIBCXX_HAVE_ISNANL 1 -# define isnanl _isnanl -#endif - -#if defined (_GLIBCXX_HAVE__LDEXPF) && ! defined (_GLIBCXX_HAVE_LDEXPF) -# define _GLIBCXX_HAVE_LDEXPF 1 -# define ldexpf _ldexpf -#endif - -#if defined (_GLIBCXX_HAVE__LDEXPL) && ! defined (_GLIBCXX_HAVE_LDEXPL) -# define _GLIBCXX_HAVE_LDEXPL 1 -# define ldexpl _ldexpl -#endif - -#if defined (_GLIBCXX_HAVE__LOG10F) && ! defined (_GLIBCXX_HAVE_LOG10F) -# define _GLIBCXX_HAVE_LOG10F 1 -# define log10f _log10f -#endif - -#if defined (_GLIBCXX_HAVE__LOG10L) && ! defined (_GLIBCXX_HAVE_LOG10L) -# define _GLIBCXX_HAVE_LOG10L 1 -# define log10l _log10l -#endif - -#if defined (_GLIBCXX_HAVE__LOGF) && ! defined (_GLIBCXX_HAVE_LOGF) -# define _GLIBCXX_HAVE_LOGF 1 -# define logf _logf -#endif - -#if defined (_GLIBCXX_HAVE__LOGL) && ! defined (_GLIBCXX_HAVE_LOGL) -# define _GLIBCXX_HAVE_LOGL 1 -# define logl _logl -#endif - -#if defined (_GLIBCXX_HAVE__MODF) && ! defined (_GLIBCXX_HAVE_MODF) -# define _GLIBCXX_HAVE_MODF 1 -# define modf _modf -#endif - -#if defined (_GLIBCXX_HAVE__MODFF) && ! defined (_GLIBCXX_HAVE_MODFF) -# define _GLIBCXX_HAVE_MODFF 1 -# define modff _modff -#endif - -#if defined (_GLIBCXX_HAVE__MODFL) && ! defined (_GLIBCXX_HAVE_MODFL) -# define _GLIBCXX_HAVE_MODFL 1 -# define modfl _modfl -#endif - -#if defined (_GLIBCXX_HAVE__POWF) && ! defined (_GLIBCXX_HAVE_POWF) -# define _GLIBCXX_HAVE_POWF 1 -# define powf _powf -#endif - -#if defined (_GLIBCXX_HAVE__POWL) && ! defined (_GLIBCXX_HAVE_POWL) -# define _GLIBCXX_HAVE_POWL 1 -# define powl _powl -#endif - -#if defined (_GLIBCXX_HAVE__QFPCLASS) && ! defined (_GLIBCXX_HAVE_QFPCLASS) -# define _GLIBCXX_HAVE_QFPCLASS 1 -# define qfpclass _qfpclass -#endif - -#if defined (_GLIBCXX_HAVE__SINCOS) && ! defined (_GLIBCXX_HAVE_SINCOS) -# define _GLIBCXX_HAVE_SINCOS 1 -# define sincos _sincos -#endif - -#if defined (_GLIBCXX_HAVE__SINCOSF) && ! defined (_GLIBCXX_HAVE_SINCOSF) -# define _GLIBCXX_HAVE_SINCOSF 1 -# define sincosf _sincosf -#endif - -#if defined (_GLIBCXX_HAVE__SINCOSL) && ! defined (_GLIBCXX_HAVE_SINCOSL) -# define _GLIBCXX_HAVE_SINCOSL 1 -# define sincosl _sincosl -#endif - -#if defined (_GLIBCXX_HAVE__SINF) && ! defined (_GLIBCXX_HAVE_SINF) -# define _GLIBCXX_HAVE_SINF 1 -# define sinf _sinf -#endif - -#if defined (_GLIBCXX_HAVE__SINHF) && ! defined (_GLIBCXX_HAVE_SINHF) -# define _GLIBCXX_HAVE_SINHF 1 -# define sinhf _sinhf -#endif - -#if defined (_GLIBCXX_HAVE__SINHL) && ! defined (_GLIBCXX_HAVE_SINHL) -# define _GLIBCXX_HAVE_SINHL 1 -# define sinhl _sinhl -#endif - -#if defined (_GLIBCXX_HAVE__SINL) && ! defined (_GLIBCXX_HAVE_SINL) -# define _GLIBCXX_HAVE_SINL 1 -# define sinl _sinl -#endif - -#if defined (_GLIBCXX_HAVE__SQRTF) && ! defined (_GLIBCXX_HAVE_SQRTF) -# define _GLIBCXX_HAVE_SQRTF 1 -# define sqrtf _sqrtf -#endif - -#if defined (_GLIBCXX_HAVE__SQRTL) && ! defined (_GLIBCXX_HAVE_SQRTL) -# define _GLIBCXX_HAVE_SQRTL 1 -# define sqrtl _sqrtl -#endif - -#if defined (_GLIBCXX_HAVE__STRTOF) && ! defined (_GLIBCXX_HAVE_STRTOF) -# define _GLIBCXX_HAVE_STRTOF 1 -# define strtof _strtof -#endif - -#if defined (_GLIBCXX_HAVE__STRTOLD) && ! defined (_GLIBCXX_HAVE_STRTOLD) -# define _GLIBCXX_HAVE_STRTOLD 1 -# define strtold _strtold -#endif - -#if defined (_GLIBCXX_HAVE__TANF) && ! defined (_GLIBCXX_HAVE_TANF) -# define _GLIBCXX_HAVE_TANF 1 -# define tanf _tanf -#endif - -#if defined (_GLIBCXX_HAVE__TANHF) && ! defined (_GLIBCXX_HAVE_TANHF) -# define _GLIBCXX_HAVE_TANHF 1 -# define tanhf _tanhf -#endif - -#if defined (_GLIBCXX_HAVE__TANHL) && ! defined (_GLIBCXX_HAVE_TANHL) -# define _GLIBCXX_HAVE_TANHL 1 -# define tanhl _tanhl -#endif - -#if defined (_GLIBCXX_HAVE__TANL) && ! defined (_GLIBCXX_HAVE_TANL) -# define _GLIBCXX_HAVE_TANL 1 -# define tanl _tanl -#endif - -#endif // _GLIBCXX_CXX_CONFIG_H diff --git a/resources/sources/avr-libstdcpp/include/bits/char_traits.h b/resources/sources/avr-libstdcpp/include/bits/char_traits.h deleted file mode 100644 index c6da184e4..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/char_traits.h +++ /dev/null @@ -1,943 +0,0 @@ -// Character Traits for use by standard string and iostream -*- C++ -*- - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/char_traits.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{string} - */ - -// -// ISO C++ 14882: 21 Strings library -// - -#ifndef _CHAR_TRAITS_H -#define _CHAR_TRAITS_H 1 - -#pragma GCC system_header - -#include // std::copy, std::fill_n -#include // For streampos -#include // For WEOF, wmemmove, wmemset, etc. -#if __cplusplus > 201703L -# include -#endif - -#ifndef _GLIBCXX_ALWAYS_INLINE -# define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) -#endif - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @brief Mapping from character type to associated types. - * - * @note This is an implementation class for the generic version - * of char_traits. It defines int_type, off_type, pos_type, and - * state_type. By default these are unsigned long, streamoff, - * streampos, and mbstate_t. Users who need a different set of - * types, but who don't need to change the definitions of any function - * defined in char_traits, can specialize __gnu_cxx::_Char_types - * while leaving __gnu_cxx::char_traits alone. */ - template - struct _Char_types - { - typedef unsigned long int_type; - typedef std::streampos pos_type; - typedef std::streamoff off_type; - typedef std::mbstate_t state_type; - }; - - - /** - * @brief Base class used to implement std::char_traits. - * - * @note For any given actual character type, this definition is - * probably wrong. (Most of the member functions are likely to be - * right, but the int_type and state_type typedefs, and the eof() - * member function, are likely to be wrong.) The reason this class - * exists is so users can specialize it. Classes in namespace std - * may not be specialized for fundamental types, but classes in - * namespace __gnu_cxx may be. - * - * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types - * for advice on how to make use of this class for @a unusual character - * types. Also, check out include/ext/pod_char_traits.h. - */ - template - struct char_traits - { - typedef _CharT char_type; - typedef typename _Char_types<_CharT>::int_type int_type; - typedef typename _Char_types<_CharT>::pos_type pos_type; - typedef typename _Char_types<_CharT>::off_type off_type; - typedef typename _Char_types<_CharT>::state_type state_type; -#if __cpp_lib_three_way_comparison - using comparison_category = std::strong_ordering; -#endif - - static _GLIBCXX14_CONSTEXPR void - assign(char_type& __c1, const char_type& __c2) - { __c1 = __c2; } - - static _GLIBCXX_CONSTEXPR bool - eq(const char_type& __c1, const char_type& __c2) - { return __c1 == __c2; } - - static _GLIBCXX_CONSTEXPR bool - lt(const char_type& __c1, const char_type& __c2) - { return __c1 < __c2; } - - static _GLIBCXX14_CONSTEXPR int - compare(const char_type* __s1, const char_type* __s2, std::size_t __n); - - static _GLIBCXX14_CONSTEXPR std::size_t - length(const char_type* __s); - - static _GLIBCXX14_CONSTEXPR const char_type* - find(const char_type* __s, std::size_t __n, const char_type& __a); - - static _GLIBCXX20_CONSTEXPR char_type* - move(char_type* __s1, const char_type* __s2, std::size_t __n); - - static _GLIBCXX20_CONSTEXPR char_type* - copy(char_type* __s1, const char_type* __s2, std::size_t __n); - - static _GLIBCXX20_CONSTEXPR char_type* - assign(char_type* __s, std::size_t __n, char_type __a); - - static _GLIBCXX_CONSTEXPR char_type - to_char_type(const int_type& __c) - { return static_cast(__c); } - - static _GLIBCXX_CONSTEXPR int_type - to_int_type(const char_type& __c) - { return static_cast(__c); } - - static _GLIBCXX_CONSTEXPR bool - eq_int_type(const int_type& __c1, const int_type& __c2) - { return __c1 == __c2; } - - static _GLIBCXX_CONSTEXPR int_type - eof() - { return static_cast(_GLIBCXX_STDIO_EOF); } - - static _GLIBCXX_CONSTEXPR int_type - not_eof(const int_type& __c) - { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } - }; - - template - _GLIBCXX14_CONSTEXPR int - char_traits<_CharT>:: - compare(const char_type* __s1, const char_type* __s2, std::size_t __n) - { - for (std::size_t __i = 0; __i < __n; ++__i) - if (lt(__s1[__i], __s2[__i])) - return -1; - else if (lt(__s2[__i], __s1[__i])) - return 1; - return 0; - } - - template - _GLIBCXX14_CONSTEXPR std::size_t - char_traits<_CharT>:: - length(const char_type* __p) - { - std::size_t __i = 0; - while (!eq(__p[__i], char_type())) - ++__i; - return __i; - } - - template - _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* - char_traits<_CharT>:: - find(const char_type* __s, std::size_t __n, const char_type& __a) - { - for (std::size_t __i = 0; __i < __n; ++__i) - if (eq(__s[__i], __a)) - return __s + __i; - return 0; - } - - template - _GLIBCXX20_CONSTEXPR - typename char_traits<_CharT>::char_type* - char_traits<_CharT>:: - move(char_type* __s1, const char_type* __s2, std::size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - { - if (__s1 > __s2 && __s1 < __s2 + __n) - std::copy_backward(__s2, __s2 + __n, __s1); - else - std::copy(__s2, __s2 + __n, __s1); - return __s1; - } -#endif - return static_cast<_CharT*>(__builtin_memmove(__s1, __s2, - __n * sizeof(char_type))); - } - - template - _GLIBCXX20_CONSTEXPR - typename char_traits<_CharT>::char_type* - char_traits<_CharT>:: - copy(char_type* __s1, const char_type* __s2, std::size_t __n) - { - // NB: Inline std::copy so no recursive dependencies. - std::copy(__s2, __s2 + __n, __s1); - return __s1; - } - - template - _GLIBCXX20_CONSTEXPR - typename char_traits<_CharT>::char_type* - char_traits<_CharT>:: - assign(char_type* __s, std::size_t __n, char_type __a) - { - // NB: Inline std::fill_n so no recursive dependencies. - std::fill_n(__s, __n, __a); - return __s; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#if __cplusplus >= 201703L -#define __cpp_lib_constexpr_char_traits 201611 - - /** - * @brief Determine whether the characters of a NULL-terminated - * string are known at compile time. - * @param __s The string. - * - * Assumes that _CharT is a built-in character type. - */ - template - static _GLIBCXX_ALWAYS_INLINE constexpr bool - __constant_string_p(const _CharT* __s) - { -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - (void) __s; - // In constexpr contexts all strings should be constant. - return __builtin_is_constant_evaluated(); -#else - while (__builtin_constant_p(*__s) && *__s) - __s++; - return __builtin_constant_p(*__s); -#endif - } - - /** - * @brief Determine whether the characters of a character array are - * known at compile time. - * @param __a The character array. - * @param __n Number of characters. - * - * Assumes that _CharT is a built-in character type. - */ - template - static _GLIBCXX_ALWAYS_INLINE constexpr bool - __constant_char_array_p(const _CharT* __a, size_t __n) - { -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - (void) __a; - (void) __n; - // In constexpr contexts all character arrays should be constant. - return __builtin_is_constant_evaluated(); -#else - size_t __i = 0; - while (__i < __n && __builtin_constant_p(__a[__i])) - __i++; - return __i == __n; -#endif - } -#endif - - // 21.1 - /** - * @brief Basis for explicit traits specializations. - * - * @note For any given actual character type, this definition is - * probably wrong. Since this is just a thin wrapper around - * __gnu_cxx::char_traits, it is possible to achieve a more - * appropriate definition by specializing __gnu_cxx::char_traits. - * - * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types - * for advice on how to make use of this class for @a unusual character - * types. Also, check out include/ext/pod_char_traits.h. - */ - template - struct char_traits : public __gnu_cxx::char_traits<_CharT> - { }; - - - /// 21.1.3.1 char_traits specializations - template<> - struct char_traits - { - typedef char char_type; - typedef int int_type; - typedef streampos pos_type; - typedef streamoff off_type; - typedef mbstate_t state_type; -#if __cpp_lib_three_way_comparison - using comparison_category = strong_ordering; -#endif - - static _GLIBCXX17_CONSTEXPR void - assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { __c1 = __c2; } - - static _GLIBCXX_CONSTEXPR bool - eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 == __c2; } - - static _GLIBCXX_CONSTEXPR bool - lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { - // LWG 467. - return (static_cast(__c1) - < static_cast(__c2)); - } - - static _GLIBCXX17_CONSTEXPR int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return 0; -#if __cplusplus >= 201703L - if (__builtin_constant_p(__n) - && __constant_char_array_p(__s1, __n) - && __constant_char_array_p(__s2, __n)) - return __gnu_cxx::char_traits::compare(__s1, __s2, __n); -#endif - return __builtin_memcmp(__s1, __s2, __n); - } - - static _GLIBCXX17_CONSTEXPR size_t - length(const char_type* __s) - { -#if __cplusplus >= 201703L - if (__constant_string_p(__s)) - return __gnu_cxx::char_traits::length(__s); -#endif - return __builtin_strlen(__s); - } - - static _GLIBCXX17_CONSTEXPR const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { - if (__n == 0) - return 0; -#if __cplusplus >= 201703L - if (__builtin_constant_p(__n) - && __builtin_constant_p(__a) - && __constant_char_array_p(__s, __n)) - return __gnu_cxx::char_traits::find(__s, __n, __a); -#endif - return static_cast(__builtin_memchr(__s, __a, __n)); - } - - static _GLIBCXX20_CONSTEXPR char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::move(__s1, __s2, __n); -#endif - return static_cast(__builtin_memmove(__s1, __s2, __n)); - } - - static _GLIBCXX20_CONSTEXPR char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::copy(__s1, __s2, __n); -#endif - return static_cast(__builtin_memcpy(__s1, __s2, __n)); - } - - static _GLIBCXX20_CONSTEXPR char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - if (__n == 0) - return __s; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::assign(__s, __n, __a); -#endif - return static_cast(__builtin_memset(__s, __a, __n)); - } - - static _GLIBCXX_CONSTEXPR char_type - to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT - { return static_cast(__c); } - - // To keep both the byte 0xff and the eof symbol 0xffffffff - // from ending up as 0xffffffff. - static _GLIBCXX_CONSTEXPR int_type - to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT - { return static_cast(static_cast(__c)); } - - static _GLIBCXX_CONSTEXPR bool - eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 == __c2; } - - static _GLIBCXX_CONSTEXPR int_type - eof() _GLIBCXX_NOEXCEPT - { return static_cast(_GLIBCXX_STDIO_EOF); } - - static _GLIBCXX_CONSTEXPR int_type - not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT - { return (__c == eof()) ? 0 : __c; } - }; - - -#ifdef _GLIBCXX_USE_WCHAR_T - /// 21.1.3.2 char_traits specializations - template<> - struct char_traits - { - typedef wchar_t char_type; - typedef wint_t int_type; - typedef streamoff off_type; - typedef wstreampos pos_type; - typedef mbstate_t state_type; -#if __cpp_lib_three_way_comparison - using comparison_category = strong_ordering; -#endif - - static _GLIBCXX17_CONSTEXPR void - assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { __c1 = __c2; } - - static _GLIBCXX_CONSTEXPR bool - eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 == __c2; } - - static _GLIBCXX_CONSTEXPR bool - lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 < __c2; } - - static _GLIBCXX17_CONSTEXPR int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return 0; -#if __cplusplus >= 201703L - if (__builtin_constant_p(__n) - && __constant_char_array_p(__s1, __n) - && __constant_char_array_p(__s2, __n)) - return __gnu_cxx::char_traits::compare(__s1, __s2, __n); -#endif - return wmemcmp(__s1, __s2, __n); - } - - static _GLIBCXX17_CONSTEXPR size_t - length(const char_type* __s) - { -#if __cplusplus >= 201703L - if (__constant_string_p(__s)) - return __gnu_cxx::char_traits::length(__s); -#endif - return wcslen(__s); - } - - static _GLIBCXX17_CONSTEXPR const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { - if (__n == 0) - return 0; -#if __cplusplus >= 201703L - if (__builtin_constant_p(__n) - && __builtin_constant_p(__a) - && __constant_char_array_p(__s, __n)) - return __gnu_cxx::char_traits::find(__s, __n, __a); -#endif - return wmemchr(__s, __a, __n); - } - - static _GLIBCXX20_CONSTEXPR char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::move(__s1, __s2, __n); -#endif - return wmemmove(__s1, __s2, __n); - } - - static _GLIBCXX20_CONSTEXPR char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::copy(__s1, __s2, __n); -#endif - return wmemcpy(__s1, __s2, __n); - } - - static _GLIBCXX20_CONSTEXPR char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - if (__n == 0) - return __s; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::assign(__s, __n, __a); -#endif - return wmemset(__s, __a, __n); - } - - static _GLIBCXX_CONSTEXPR char_type - to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT - { return char_type(__c); } - - static _GLIBCXX_CONSTEXPR int_type - to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT - { return int_type(__c); } - - static _GLIBCXX_CONSTEXPR bool - eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 == __c2; } - - static _GLIBCXX_CONSTEXPR int_type - eof() _GLIBCXX_NOEXCEPT - { return static_cast(WEOF); } - - static _GLIBCXX_CONSTEXPR int_type - not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT - { return eq_int_type(__c, eof()) ? 0 : __c; } - }; -#endif //_GLIBCXX_USE_WCHAR_T - -#ifdef _GLIBCXX_USE_CHAR8_T - template<> - struct char_traits - { - typedef char8_t char_type; - typedef unsigned int int_type; - typedef u8streampos pos_type; - typedef streamoff off_type; - typedef mbstate_t state_type; -#if __cpp_lib_three_way_comparison - using comparison_category = strong_ordering; -#endif - - static _GLIBCXX17_CONSTEXPR void - assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { __c1 = __c2; } - - static _GLIBCXX_CONSTEXPR bool - eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 == __c2; } - - static _GLIBCXX_CONSTEXPR bool - lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 < __c2; } - - static _GLIBCXX17_CONSTEXPR int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return 0; -#if __cplusplus > 201402 - if (__builtin_constant_p(__n) - && __constant_char_array_p(__s1, __n) - && __constant_char_array_p(__s2, __n)) - return __gnu_cxx::char_traits::compare(__s1, __s2, __n); -#endif - return __builtin_memcmp(__s1, __s2, __n); - } - - static _GLIBCXX17_CONSTEXPR size_t - length(const char_type* __s) - { -#if __cplusplus > 201402 - if (__constant_string_p(__s)) - return __gnu_cxx::char_traits::length(__s); -#endif - size_t __i = 0; - while (!eq(__s[__i], char_type())) - ++__i; - return __i; - } - - static _GLIBCXX17_CONSTEXPR const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { - if (__n == 0) - return 0; -#if __cplusplus > 201402 - if (__builtin_constant_p(__n) - && __builtin_constant_p(__a) - && __constant_char_array_p(__s, __n)) - return __gnu_cxx::char_traits::find(__s, __n, __a); -#endif - return static_cast(__builtin_memchr(__s, __a, __n)); - } - - static _GLIBCXX20_CONSTEXPR char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::move(__s1, __s2, __n); -#endif - return static_cast(__builtin_memmove(__s1, __s2, __n)); - } - - static _GLIBCXX20_CONSTEXPR char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::copy(__s1, __s2, __n); -#endif - return static_cast(__builtin_memcpy(__s1, __s2, __n)); - } - - static _GLIBCXX20_CONSTEXPR char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - if (__n == 0) - return __s; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::assign(__s, __n, __a); -#endif - return static_cast(__builtin_memset(__s, __a, __n)); - } - - static _GLIBCXX_CONSTEXPR char_type - to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT - { return char_type(__c); } - - static _GLIBCXX_CONSTEXPR int_type - to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT - { return int_type(__c); } - - static _GLIBCXX_CONSTEXPR bool - eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT - { return __c1 == __c2; } - - static _GLIBCXX_CONSTEXPR int_type - eof() _GLIBCXX_NOEXCEPT - { return static_cast(-1); } - - static _GLIBCXX_CONSTEXPR int_type - not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT - { return eq_int_type(__c, eof()) ? 0 : __c; } - }; -#endif //_GLIBCXX_USE_CHAR8_T - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#if __cplusplus >= 201103L - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template<> - struct char_traits - { - typedef char16_t char_type; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - typedef uint_least16_t int_type; -#elif defined __UINT_LEAST16_TYPE__ - typedef __UINT_LEAST16_TYPE__ int_type; -#else - typedef make_unsigned::type int_type; -#endif - typedef streamoff off_type; - typedef u16streampos pos_type; - typedef mbstate_t state_type; -#if __cpp_lib_three_way_comparison - using comparison_category = strong_ordering; -#endif - - static _GLIBCXX17_CONSTEXPR void - assign(char_type& __c1, const char_type& __c2) noexcept - { __c1 = __c2; } - - static constexpr bool - eq(const char_type& __c1, const char_type& __c2) noexcept - { return __c1 == __c2; } - - static constexpr bool - lt(const char_type& __c1, const char_type& __c2) noexcept - { return __c1 < __c2; } - - static _GLIBCXX17_CONSTEXPR int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { - for (size_t __i = 0; __i < __n; ++__i) - if (lt(__s1[__i], __s2[__i])) - return -1; - else if (lt(__s2[__i], __s1[__i])) - return 1; - return 0; - } - - static _GLIBCXX17_CONSTEXPR size_t - length(const char_type* __s) - { - size_t __i = 0; - while (!eq(__s[__i], char_type())) - ++__i; - return __i; - } - - static _GLIBCXX17_CONSTEXPR const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { - for (size_t __i = 0; __i < __n; ++__i) - if (eq(__s[__i], __a)) - return __s + __i; - return 0; - } - - static _GLIBCXX20_CONSTEXPR char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::move(__s1, __s2, __n); -#endif - return (static_cast - (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); - } - - static _GLIBCXX20_CONSTEXPR char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::copy(__s1, __s2, __n); -#endif - return (static_cast - (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); - } - - static _GLIBCXX20_CONSTEXPR char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - for (size_t __i = 0; __i < __n; ++__i) - assign(__s[__i], __a); - return __s; - } - - static constexpr char_type - to_char_type(const int_type& __c) noexcept - { return char_type(__c); } - - static constexpr int_type - to_int_type(const char_type& __c) noexcept - { return __c == eof() ? int_type(0xfffd) : int_type(__c); } - - static constexpr bool - eq_int_type(const int_type& __c1, const int_type& __c2) noexcept - { return __c1 == __c2; } - - static constexpr int_type - eof() noexcept - { return static_cast(-1); } - - static constexpr int_type - not_eof(const int_type& __c) noexcept - { return eq_int_type(__c, eof()) ? 0 : __c; } - }; - - template<> - struct char_traits - { - typedef char32_t char_type; -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - typedef uint_least32_t int_type; -#elif defined __UINT_LEAST32_TYPE__ - typedef __UINT_LEAST32_TYPE__ int_type; -#else - typedef make_unsigned::type int_type; -#endif - typedef streamoff off_type; - typedef u32streampos pos_type; - typedef mbstate_t state_type; -#if __cpp_lib_three_way_comparison - using comparison_category = strong_ordering; -#endif - - static _GLIBCXX17_CONSTEXPR void - assign(char_type& __c1, const char_type& __c2) noexcept - { __c1 = __c2; } - - static constexpr bool - eq(const char_type& __c1, const char_type& __c2) noexcept - { return __c1 == __c2; } - - static constexpr bool - lt(const char_type& __c1, const char_type& __c2) noexcept - { return __c1 < __c2; } - - static _GLIBCXX17_CONSTEXPR int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { - for (size_t __i = 0; __i < __n; ++__i) - if (lt(__s1[__i], __s2[__i])) - return -1; - else if (lt(__s2[__i], __s1[__i])) - return 1; - return 0; - } - - static _GLIBCXX17_CONSTEXPR size_t - length(const char_type* __s) - { - size_t __i = 0; - while (!eq(__s[__i], char_type())) - ++__i; - return __i; - } - - static _GLIBCXX17_CONSTEXPR const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { - for (size_t __i = 0; __i < __n; ++__i) - if (eq(__s[__i], __a)) - return __s + __i; - return 0; - } - - static _GLIBCXX20_CONSTEXPR char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::move(__s1, __s2, __n); -#endif - return (static_cast - (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); - } - - static _GLIBCXX20_CONSTEXPR char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __gnu_cxx::char_traits::copy(__s1, __s2, __n); -#endif - return (static_cast - (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); - } - - static _GLIBCXX20_CONSTEXPR char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - for (size_t __i = 0; __i < __n; ++__i) - assign(__s[__i], __a); - return __s; - } - - static constexpr char_type - to_char_type(const int_type& __c) noexcept - { return char_type(__c); } - - static constexpr int_type - to_int_type(const char_type& __c) noexcept - { return int_type(__c); } - - static constexpr bool - eq_int_type(const int_type& __c1, const int_type& __c2) noexcept - { return __c1 == __c2; } - - static constexpr int_type - eof() noexcept - { return static_cast(-1); } - - static constexpr int_type - not_eof(const int_type& __c) noexcept - { return eq_int_type(__c, eof()) ? 0 : __c; } - }; - -#if __cpp_lib_three_way_comparison - namespace __detail - { - template - constexpr auto - __char_traits_cmp_cat(int __cmp) noexcept - { - if constexpr (requires { typename _ChTraits::comparison_category; }) - { - using _Cat = typename _ChTraits::comparison_category; - static_assert( !is_void_v> ); - return static_cast<_Cat>(__cmp <=> 0); - } - else - return static_cast(__cmp <=> 0); - } - } // namespace __detail -#endif // C++20 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 - -#endif // _CHAR_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/charconv.h b/resources/sources/avr-libstdcpp/include/bits/charconv.h deleted file mode 100644 index a3149bddb..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/charconv.h +++ /dev/null @@ -1,106 +0,0 @@ -// Numeric conversions (to_string, to_chars) -*- C++ -*- - -// Copyright (C) 2017-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/charconv.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{charconv} - */ - -#ifndef _GLIBCXX_CHARCONV_H -#define _GLIBCXX_CHARCONV_H 1 - -#pragma GCC system_header - -#if __cplusplus >= 201103L - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -namespace __detail -{ - // Generic implementation for arbitrary bases. - template - _GLIBCXX14_CONSTEXPR unsigned - __to_chars_len(_Tp __value, int __base = 10) noexcept - { - static_assert(is_integral<_Tp>::value, "implementation bug"); - static_assert(is_unsigned<_Tp>::value, "implementation bug"); - - unsigned __n = 1; - const unsigned __b2 = __base * __base; - const unsigned __b3 = __b2 * __base; - const unsigned long __b4 = __b3 * __base; - for (;;) - { - if (__value < (unsigned)__base) return __n; - if (__value < __b2) return __n + 1; - if (__value < __b3) return __n + 2; - if (__value < __b4) return __n + 3; - __value /= __b4; - __n += 4; - } - } - - // Write an unsigned integer value to the range [first,first+len). - // The caller is required to provide a buffer of exactly the right size - // (which can be determined by the __to_chars_len function). - template - void - __to_chars_10_impl(char* __first, unsigned __len, _Tp __val) noexcept - { - static_assert(is_integral<_Tp>::value, "implementation bug"); - static_assert(is_unsigned<_Tp>::value, "implementation bug"); - - static constexpr char __digits[201] = - "0001020304050607080910111213141516171819" - "2021222324252627282930313233343536373839" - "4041424344454647484950515253545556575859" - "6061626364656667686970717273747576777879" - "8081828384858687888990919293949596979899"; - unsigned __pos = __len - 1; - while (__val >= 100) - { - auto const __num = (__val % 100) * 2; - __val /= 100; - __first[__pos] = __digits[__num + 1]; - __first[__pos - 1] = __digits[__num]; - __pos -= 2; - } - if (__val >= 10) - { - auto const __num = __val * 2; - __first[1] = __digits[__num + 1]; - __first[0] = __digits[__num]; - } - else - __first[0] = '0' + __val; - } - -} // namespace __detail -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++11 -#endif // _GLIBCXX_CHARCONV_H diff --git a/resources/sources/avr-libstdcpp/include/bits/concept_check.h b/resources/sources/avr-libstdcpp/include/bits/concept_check.h deleted file mode 100644 index 8923a71fc..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/concept_check.h +++ /dev/null @@ -1,81 +0,0 @@ -// Concept-checking control -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/concept_check.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iterator} - */ - -#ifndef _CONCEPT_CHECK_H -#define _CONCEPT_CHECK_H 1 - -#pragma GCC system_header - -#include - -// All places in libstdc++-v3 where these are used, or /might/ be used, or -// don't need to be used, or perhaps /should/ be used, are commented with -// "concept requirements" (and maybe some more text). So grep like crazy -// if you're looking for additional places to use these. - -// Concept-checking code is off by default unless users turn it on via -// configure options or editing c++config.h. -// It is not supported for freestanding implementations. - -#if !defined(_GLIBCXX_CONCEPT_CHECKS) || !_GLIBCXX_HOSTED - -#define __glibcxx_function_requires(...) -#define __glibcxx_class_requires(_a,_b) -#define __glibcxx_class_requires2(_a,_b,_c) -#define __glibcxx_class_requires3(_a,_b,_c,_d) -#define __glibcxx_class_requires4(_a,_b,_c,_d,_e) - -#else // the checks are on - -#include - -// Note that the obvious and elegant approach of -// -//#define glibcxx_function_requires(C) debug::function_requires< debug::C >() -// -// won't work due to concept templates with more than one parameter, e.g., -// BinaryPredicateConcept. The preprocessor tries to split things up on -// the commas in the template argument list. We can't use an inner pair of -// parenthesis to hide the commas, because "debug::(Temp)" isn't -// a valid instantiation pattern. Thus, we steal a feature from C99. - -#define __glibcxx_function_requires(...) \ - __gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >(); -#define __glibcxx_class_requires(_a,_C) \ - _GLIBCXX_CLASS_REQUIRES(_a, __gnu_cxx, _C); -#define __glibcxx_class_requires2(_a,_b,_C) \ - _GLIBCXX_CLASS_REQUIRES2(_a, _b, __gnu_cxx, _C); -#define __glibcxx_class_requires3(_a,_b,_c,_C) \ - _GLIBCXX_CLASS_REQUIRES3(_a, _b, _c, __gnu_cxx, _C); -#define __glibcxx_class_requires4(_a,_b,_c,_d,_C) \ - _GLIBCXX_CLASS_REQUIRES4(_a, _b, _c, _d, __gnu_cxx, _C); - -#endif // enable/disable - -#endif // _GLIBCXX_CONCEPT_CHECK diff --git a/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h b/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h deleted file mode 100644 index ca83f590e..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h +++ /dev/null @@ -1,551 +0,0 @@ -// The -*- C++ -*- type traits classes for internal use in libstdc++ - -// Copyright (C) 2000-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/cpp_type_traits.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{ext/type_traits} - */ - -// Written by Gabriel Dos Reis - -#ifndef _CPP_TYPE_TRAITS_H -#define _CPP_TYPE_TRAITS_H 1 - -#pragma GCC system_header - -#include - -// -// This file provides some compile-time information about various types. -// These representations were designed, on purpose, to be constant-expressions -// and not types as found in . In particular, they -// can be used in control structures and the optimizer hopefully will do -// the obvious thing. -// -// Why integral expressions, and not functions nor types? -// Firstly, these compile-time entities are used as template-arguments -// so function return values won't work: We need compile-time entities. -// We're left with types and constant integral expressions. -// Secondly, from the point of view of ease of use, type-based compile-time -// information is -not- *that* convenient. One has to write lots of -// overloaded functions and to hope that the compiler will select the right -// one. As a net effect, the overall structure isn't very clear at first -// glance. -// Thirdly, partial ordering and overload resolution (of function templates) -// is highly costly in terms of compiler-resource. It is a Good Thing to -// keep these resource consumption as least as possible. -// -// See valarray_array.h for a case use. -// -// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06. -// -// Update 2005: types are also provided and has been -// removed. -// - -extern "C++" { - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - struct __true_type { }; - struct __false_type { }; - - template - struct __truth_type - { typedef __false_type __type; }; - - template<> - struct __truth_type - { typedef __true_type __type; }; - - // N.B. The conversions to bool are needed due to the issue - // explained in c++/19404. - template - struct __traitor - { - enum { __value = bool(_Sp::__value) || bool(_Tp::__value) }; - typedef typename __truth_type<__value>::__type __type; - }; - - // Compare for equality of types. - template - struct __are_same - { - enum { __value = 0 }; - typedef __false_type __type; - }; - - template - struct __are_same<_Tp, _Tp> - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - // Holds if the template-argument is a void type. - template - struct __is_void - { - enum { __value = 0 }; - typedef __false_type __type; - }; - - template<> - struct __is_void - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - // - // Integer types - // - template - struct __is_integer - { - enum { __value = 0 }; - typedef __false_type __type; - }; - - // Thirteen specializations (yes there are eleven standard integer - // types; long long and unsigned long long are - // supported as extensions). Up to four target-specific __int - // types are supported as well. - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - -# ifdef _GLIBCXX_USE_WCHAR_T - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; -# endif - -#ifdef _GLIBCXX_USE_CHAR8_T - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; -#endif - -#if __cplusplus >= 201103L - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; -#endif - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_integer - { - enum { __value = 1 }; - typedef __true_type __type; - }; - -#define __INT_N(TYPE) \ - template<> \ - struct __is_integer \ - { \ - enum { __value = 1 }; \ - typedef __true_type __type; \ - }; \ - template<> \ - struct __is_integer \ - { \ - enum { __value = 1 }; \ - typedef __true_type __type; \ - }; - -#ifdef __GLIBCXX_TYPE_INT_N_0 -__INT_N(__GLIBCXX_TYPE_INT_N_0) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_1 -__INT_N(__GLIBCXX_TYPE_INT_N_1) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_2 -__INT_N(__GLIBCXX_TYPE_INT_N_2) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_3 -__INT_N(__GLIBCXX_TYPE_INT_N_3) -#endif - -#undef __INT_N - - // - // Floating point types - // - template - struct __is_floating - { - enum { __value = 0 }; - typedef __false_type __type; - }; - - // three specializations (float, double and 'long double') - template<> - struct __is_floating - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_floating - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_floating - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - // - // Pointer types - // - template - struct __is_pointer - { - enum { __value = 0 }; - typedef __false_type __type; - }; - - template - struct __is_pointer<_Tp*> - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - // - // An arithmetic type is an integer type or a floating point type - // - template - struct __is_arithmetic - : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> > - { }; - - // - // A scalar type is an arithmetic type or a pointer type - // - template - struct __is_scalar - : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> > - { }; - - // - // For use in std::copy and std::find overloads for streambuf iterators. - // - template - struct __is_char - { - enum { __value = 0 }; - typedef __false_type __type; - }; - - template<> - struct __is_char - { - enum { __value = 1 }; - typedef __true_type __type; - }; - -#ifdef _GLIBCXX_USE_WCHAR_T - template<> - struct __is_char - { - enum { __value = 1 }; - typedef __true_type __type; - }; -#endif - - template - struct __is_byte - { - enum { __value = 0 }; - typedef __false_type __type; - }; - - template<> - struct __is_byte - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_byte - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template<> - struct __is_byte - { - enum { __value = 1 }; - typedef __true_type __type; - }; - -#if __cplusplus >= 201703L - enum class byte : unsigned char; - - template<> - struct __is_byte - { - enum { __value = 1 }; - typedef __true_type __type; - }; -#endif // C++17 - -#ifdef _GLIBCXX_USE_CHAR8_T - template<> - struct __is_byte - { - enum { __value = 1 }; - typedef __true_type __type; - }; -#endif - - template struct iterator_traits; - - // A type that is safe for use with memcpy, memmove, memcmp etc. - template - struct __is_nonvolatile_trivially_copyable - { - enum { __value = __is_trivially_copyable(_Tp) }; - }; - - // Cannot use memcpy/memmove/memcmp on volatile types even if they are - // trivially copyable, so ensure __memcpyable - // and similar will be false. - template - struct __is_nonvolatile_trivially_copyable - { - enum { __value = 0 }; - }; - - // Whether two iterator types can be used with memcpy/memmove. - template - struct __memcpyable - { - enum { __value = 0 }; - }; - - template - struct __memcpyable<_Tp*, _Tp*> - : __is_nonvolatile_trivially_copyable<_Tp> - { }; - - template - struct __memcpyable<_Tp*, const _Tp*> - : __is_nonvolatile_trivially_copyable<_Tp> - { }; - - // Whether two iterator types can be used with memcmp. - // This trait only says it's well-formed to use memcmp, not that it - // gives the right answer for a given algorithm. So for example, std::equal - // needs to add additional checks that the types are integers or pointers, - // because other trivially copyable types can overload operator==. - template - struct __memcmpable - { - enum { __value = 0 }; - }; - - // OK to use memcmp with pointers to trivially copyable types. - template - struct __memcmpable<_Tp*, _Tp*> - : __is_nonvolatile_trivially_copyable<_Tp> - { }; - - template - struct __memcmpable - : __is_nonvolatile_trivially_copyable<_Tp> - { }; - - template - struct __memcmpable<_Tp*, const _Tp*> - : __is_nonvolatile_trivially_copyable<_Tp> - { }; - - // Whether memcmp can be used to determine ordering for a type - // e.g. in std::lexicographical_compare or three-way comparisons. - // True for unsigned narrow character types (and std::byte). - template::__value> - struct __is_memcmp_ordered - { - static const bool __value = _Tp(-1) > _Tp(1); // is unsigned - }; - - template - struct __is_memcmp_ordered<_Tp, false> - { - static const bool __value = false; - }; - - // Whether two types can be compared using memcmp. - template - struct __is_memcmp_ordered_with - { - static const bool __value = __is_memcmp_ordered<_Tp>::__value - && __is_memcmp_ordered<_Up>::__value; - }; - - template - struct __is_memcmp_ordered_with<_Tp, _Up, false> - { - static const bool __value = false; - }; - -#if __cplusplus >= 201703L - // std::byte can only be compared to itself, not to other types. - template<> - struct __is_memcmp_ordered_with - { static constexpr bool __value = true; }; - - template - struct __is_memcmp_ordered_with<_Tp, std::byte, _SameSize> - { static constexpr bool __value = false; }; - - template - struct __is_memcmp_ordered_with - { static constexpr bool __value = false; }; -#endif - - // - // Move iterator type - // - template - struct __is_move_iterator - { - enum { __value = 0 }; - typedef __false_type __type; - }; - - // Fallback implementation of the function in bits/stl_iterator.h used to - // remove the move_iterator wrapper. - template - _GLIBCXX20_CONSTEXPR - inline _Iterator - __miter_base(_Iterator __it) - { return __it; } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -} // extern "C++" - -#endif //_CPP_TYPE_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h b/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h deleted file mode 100644 index 9e61a382b..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h +++ /dev/null @@ -1,60 +0,0 @@ -// cxxabi.h subset for cancellation -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of GCC. -// -// GCC is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3, or (at your option) -// any later version. -// -// GCC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/cxxabi_forced.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{cxxabi.h} - */ - -#ifndef _CXXABI_FORCED_H -#define _CXXABI_FORCED_H 1 - -#pragma GCC system_header - -#pragma GCC visibility push(default) - -#ifdef __cplusplus -namespace __cxxabiv1 -{ - /** - * @brief Thrown as part of forced unwinding. - * @ingroup exceptions - * - * A magic placeholder class that can be caught by reference to - * recognize forced unwinding. - */ - class __forced_unwind - { - virtual ~__forced_unwind() throw(); - - // Prevent catch by value. - virtual void __pure_dummy() = 0; - }; -} -#endif // __cplusplus - -#pragma GCC visibility pop - -#endif // __CXXABI_FORCED_H diff --git a/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h b/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h deleted file mode 100644 index 9ea0599ed..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h +++ /dev/null @@ -1,80 +0,0 @@ -// ABI Support -*- C++ -*- - -// Copyright (C) 2016-2020 Free Software Foundation, Inc. -// -// This file is part of GCC. -// -// GCC is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3, or (at your option) -// any later version. -// -// GCC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/cxxabi_init_exception.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. - */ - -#ifndef _CXXABI_INIT_EXCEPTION_H -#define _CXXABI_INIT_EXCEPTION_H 1 - -#pragma GCC system_header - -#pragma GCC visibility push(default) - -#include -#include - -#ifndef _GLIBCXX_CDTOR_CALLABI -#define _GLIBCXX_CDTOR_CALLABI -#define _GLIBCXX_HAVE_CDTOR_CALLABI 0 -#else -#define _GLIBCXX_HAVE_CDTOR_CALLABI 1 -#endif - -#ifdef __cplusplus - -namespace std -{ - class type_info; -} - -namespace __cxxabiv1 -{ - struct __cxa_refcounted_exception; - - extern "C" - { - // Allocate memory for the primary exception plus the thrown object. - void* - __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW; - - void - __cxa_free_exception(void*) _GLIBCXX_NOTHROW; - - // Initialize exception (this is a GNU extension) - __cxa_refcounted_exception* - __cxa_init_primary_exception(void *object, std::type_info *tinfo, - void (_GLIBCXX_CDTOR_CALLABI *dest) (void *)) _GLIBCXX_NOTHROW; - - } -} // namespace __cxxabiv1 - -#endif - -#pragma GCC visibility pop - -#endif // _CXXABI_INIT_EXCEPTION_H diff --git a/resources/sources/avr-libstdcpp/include/bits/deque.tcc b/resources/sources/avr-libstdcpp/include/bits/deque.tcc deleted file mode 100644 index b4943e8ea..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/deque.tcc +++ /dev/null @@ -1,1216 +0,0 @@ -// Deque implementation (out of line) -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/deque.tcc - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{deque} - */ - -#ifndef _DEQUE_TCC -#define _DEQUE_TCC 1 - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - -#if __cplusplus >= 201103L - template - void - deque<_Tp, _Alloc>:: - _M_default_initialize() - { - _Map_pointer __cur; - __try - { - for (__cur = this->_M_impl._M_start._M_node; - __cur < this->_M_impl._M_finish._M_node; - ++__cur) - std::__uninitialized_default_a(*__cur, *__cur + _S_buffer_size(), - _M_get_Tp_allocator()); - std::__uninitialized_default_a(this->_M_impl._M_finish._M_first, - this->_M_impl._M_finish._M_cur, - _M_get_Tp_allocator()); - } - __catch(...) - { - std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), - _M_get_Tp_allocator()); - __throw_exception_again; - } - } -#endif - - template - deque<_Tp, _Alloc>& - deque<_Tp, _Alloc>:: - operator=(const deque& __x) - { - if (&__x != this) - { -#if __cplusplus >= 201103L - if (_Alloc_traits::_S_propagate_on_copy_assign()) - { - if (!_Alloc_traits::_S_always_equal() - && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) - { - // Replacement allocator cannot free existing storage, - // so deallocate everything and take copy of __x's data. - _M_replace_map(__x, __x.get_allocator()); - std::__alloc_on_copy(_M_get_Tp_allocator(), - __x._M_get_Tp_allocator()); - return *this; - } - std::__alloc_on_copy(_M_get_Tp_allocator(), - __x._M_get_Tp_allocator()); - } -#endif - const size_type __len = size(); - if (__len >= __x.size()) - _M_erase_at_end(std::copy(__x.begin(), __x.end(), - this->_M_impl._M_start)); - else - { - const_iterator __mid = __x.begin() + difference_type(__len); - std::copy(__x.begin(), __mid, this->_M_impl._M_start); - _M_range_insert_aux(this->_M_impl._M_finish, __mid, __x.end(), - std::random_access_iterator_tag()); - } - } - return *this; - } - -#if __cplusplus >= 201103L - template - template -#if __cplusplus > 201402L - typename deque<_Tp, _Alloc>::reference -#else - void -#endif - deque<_Tp, _Alloc>:: - emplace_front(_Args&&... __args) - { - if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) - { - _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_start._M_cur - 1, - std::forward<_Args>(__args)...); - --this->_M_impl._M_start._M_cur; - } - else - _M_push_front_aux(std::forward<_Args>(__args)...); -#if __cplusplus > 201402L - return front(); -#endif - } - - template - template -#if __cplusplus > 201402L - typename deque<_Tp, _Alloc>::reference -#else - void -#endif - deque<_Tp, _Alloc>:: - emplace_back(_Args&&... __args) - { - if (this->_M_impl._M_finish._M_cur - != this->_M_impl._M_finish._M_last - 1) - { - _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_finish._M_cur, - std::forward<_Args>(__args)...); - ++this->_M_impl._M_finish._M_cur; - } - else - _M_push_back_aux(std::forward<_Args>(__args)...); -#if __cplusplus > 201402L - return back(); -#endif - } -#endif - -#if __cplusplus >= 201103L - template - template - typename deque<_Tp, _Alloc>::iterator - deque<_Tp, _Alloc>:: - emplace(const_iterator __position, _Args&&... __args) - { - if (__position._M_cur == this->_M_impl._M_start._M_cur) - { - emplace_front(std::forward<_Args>(__args)...); - return this->_M_impl._M_start; - } - else if (__position._M_cur == this->_M_impl._M_finish._M_cur) - { - emplace_back(std::forward<_Args>(__args)...); - iterator __tmp = this->_M_impl._M_finish; - --__tmp; - return __tmp; - } - else - return _M_insert_aux(__position._M_const_cast(), - std::forward<_Args>(__args)...); - } -#endif - - template - typename deque<_Tp, _Alloc>::iterator - deque<_Tp, _Alloc>:: -#if __cplusplus >= 201103L - insert(const_iterator __position, const value_type& __x) -#else - insert(iterator __position, const value_type& __x) -#endif - { - if (__position._M_cur == this->_M_impl._M_start._M_cur) - { - push_front(__x); - return this->_M_impl._M_start; - } - else if (__position._M_cur == this->_M_impl._M_finish._M_cur) - { - push_back(__x); - iterator __tmp = this->_M_impl._M_finish; - --__tmp; - return __tmp; - } - else - return _M_insert_aux(__position._M_const_cast(), __x); - } - - template - typename deque<_Tp, _Alloc>::iterator - deque<_Tp, _Alloc>:: - _M_erase(iterator __position) - { - iterator __next = __position; - ++__next; - const difference_type __index = __position - begin(); - if (static_cast(__index) < (size() >> 1)) - { - if (__position != begin()) - _GLIBCXX_MOVE_BACKWARD3(begin(), __position, __next); - pop_front(); - } - else - { - if (__next != end()) - _GLIBCXX_MOVE3(__next, end(), __position); - pop_back(); - } - return begin() + __index; - } - - template - typename deque<_Tp, _Alloc>::iterator - deque<_Tp, _Alloc>:: - _M_erase(iterator __first, iterator __last) - { - if (__first == __last) - return __first; - else if (__first == begin() && __last == end()) - { - clear(); - return end(); - } - else - { - const difference_type __n = __last - __first; - const difference_type __elems_before = __first - begin(); - if (static_cast(__elems_before) <= (size() - __n) / 2) - { - if (__first != begin()) - _GLIBCXX_MOVE_BACKWARD3(begin(), __first, __last); - _M_erase_at_begin(begin() + __n); - } - else - { - if (__last != end()) - _GLIBCXX_MOVE3(__last, end(), __first); - _M_erase_at_end(end() - __n); - } - return begin() + __elems_before; - } - } - - template - template - void - deque<_Tp, _Alloc>:: - _M_assign_aux(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag) - { - iterator __cur = begin(); - for (; __first != __last && __cur != end(); ++__cur, (void)++__first) - *__cur = *__first; - if (__first == __last) - _M_erase_at_end(__cur); - else - _M_range_insert_aux(end(), __first, __last, - std::__iterator_category(__first)); - } - - template - void - deque<_Tp, _Alloc>:: - _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) - { - if (__pos._M_cur == this->_M_impl._M_start._M_cur) - { - iterator __new_start = _M_reserve_elements_at_front(__n); - __try - { - std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start, - __x, _M_get_Tp_allocator()); - this->_M_impl._M_start = __new_start; - } - __catch(...) - { - _M_destroy_nodes(__new_start._M_node, - this->_M_impl._M_start._M_node); - __throw_exception_again; - } - } - else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) - { - iterator __new_finish = _M_reserve_elements_at_back(__n); - __try - { - std::__uninitialized_fill_a(this->_M_impl._M_finish, - __new_finish, __x, - _M_get_Tp_allocator()); - this->_M_impl._M_finish = __new_finish; - } - __catch(...) - { - _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, - __new_finish._M_node + 1); - __throw_exception_again; - } - } - else - _M_insert_aux(__pos, __n, __x); - } - -#if __cplusplus >= 201103L - template - void - deque<_Tp, _Alloc>:: - _M_default_append(size_type __n) - { - if (__n) - { - iterator __new_finish = _M_reserve_elements_at_back(__n); - __try - { - std::__uninitialized_default_a(this->_M_impl._M_finish, - __new_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish = __new_finish; - } - __catch(...) - { - _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, - __new_finish._M_node + 1); - __throw_exception_again; - } - } - } - - template - bool - deque<_Tp, _Alloc>:: - _M_shrink_to_fit() - { - const difference_type __front_capacity - = (this->_M_impl._M_start._M_cur - this->_M_impl._M_start._M_first); - if (__front_capacity == 0) - return false; - - const difference_type __back_capacity - = (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur); - if (__front_capacity + __back_capacity < _S_buffer_size()) - return false; - - return std::__shrink_to_fit_aux::_S_do_it(*this); - } -#endif - - template - void - deque<_Tp, _Alloc>:: - _M_fill_initialize(const value_type& __value) - { - _Map_pointer __cur; - __try - { - for (__cur = this->_M_impl._M_start._M_node; - __cur < this->_M_impl._M_finish._M_node; - ++__cur) - std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(), - __value, _M_get_Tp_allocator()); - std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first, - this->_M_impl._M_finish._M_cur, - __value, _M_get_Tp_allocator()); - } - __catch(...) - { - std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), - _M_get_Tp_allocator()); - __throw_exception_again; - } - } - - template - template - void - deque<_Tp, _Alloc>:: - _M_range_initialize(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag) - { - this->_M_initialize_map(0); - __try - { - for (; __first != __last; ++__first) -#if __cplusplus >= 201103L - emplace_back(*__first); -#else - push_back(*__first); -#endif - } - __catch(...) - { - clear(); - __throw_exception_again; - } - } - - template - template - void - deque<_Tp, _Alloc>:: - _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) - { - const size_type __n = std::distance(__first, __last); - this->_M_initialize_map(_S_check_init_len(__n, _M_get_Tp_allocator())); - - _Map_pointer __cur_node; - __try - { - for (__cur_node = this->_M_impl._M_start._M_node; - __cur_node < this->_M_impl._M_finish._M_node; - ++__cur_node) - { - _ForwardIterator __mid = __first; - std::advance(__mid, _S_buffer_size()); - std::__uninitialized_copy_a(__first, __mid, *__cur_node, - _M_get_Tp_allocator()); - __first = __mid; - } - std::__uninitialized_copy_a(__first, __last, - this->_M_impl._M_finish._M_first, - _M_get_Tp_allocator()); - } - __catch(...) - { - std::_Destroy(this->_M_impl._M_start, - iterator(*__cur_node, __cur_node), - _M_get_Tp_allocator()); - __throw_exception_again; - } - } - - // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1. - template -#if __cplusplus >= 201103L - template - void - deque<_Tp, _Alloc>:: - _M_push_back_aux(_Args&&... __args) -#else - void - deque<_Tp, _Alloc>:: - _M_push_back_aux(const value_type& __t) -#endif - { - if (size() == max_size()) - __throw_length_error( - __N("cannot create std::deque larger than max_size()")); - - _M_reserve_map_at_back(); - *(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node(); - __try - { -#if __cplusplus >= 201103L - _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_finish._M_cur, - std::forward<_Args>(__args)...); -#else - this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t); -#endif - this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - + 1); - this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first; - } - __catch(...) - { - _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1)); - __throw_exception_again; - } - } - - // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first. - template -#if __cplusplus >= 201103L - template - void - deque<_Tp, _Alloc>:: - _M_push_front_aux(_Args&&... __args) -#else - void - deque<_Tp, _Alloc>:: - _M_push_front_aux(const value_type& __t) -#endif - { - if (size() == max_size()) - __throw_length_error( - __N("cannot create std::deque larger than max_size()")); - - _M_reserve_map_at_front(); - *(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node(); - __try - { - this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node - - 1); - this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1; -#if __cplusplus >= 201103L - _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_start._M_cur, - std::forward<_Args>(__args)...); -#else - this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t); -#endif - } - __catch(...) - { - ++this->_M_impl._M_start; - _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1)); - __throw_exception_again; - } - } - - // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first. - template - void deque<_Tp, _Alloc>:: - _M_pop_back_aux() - { - _M_deallocate_node(this->_M_impl._M_finish._M_first); - this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1); - this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1; - _Alloc_traits::destroy(_M_get_Tp_allocator(), - this->_M_impl._M_finish._M_cur); - } - - // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1. - // Note that if the deque has at least one element (a precondition for this - // member function), and if - // _M_impl._M_start._M_cur == _M_impl._M_start._M_last, - // then the deque must have at least two nodes. - template - void deque<_Tp, _Alloc>:: - _M_pop_front_aux() - { - _Alloc_traits::destroy(_M_get_Tp_allocator(), - this->_M_impl._M_start._M_cur); - _M_deallocate_node(this->_M_impl._M_start._M_first); - this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1); - this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first; - } - - template - template - void - deque<_Tp, _Alloc>:: - _M_range_insert_aux(iterator __pos, - _InputIterator __first, _InputIterator __last, - std::input_iterator_tag) - { std::copy(__first, __last, std::inserter(*this, __pos)); } - - template - template - void - deque<_Tp, _Alloc>:: - _M_range_insert_aux(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) - { - const size_type __n = std::distance(__first, __last); - if (__pos._M_cur == this->_M_impl._M_start._M_cur) - { - iterator __new_start = _M_reserve_elements_at_front(__n); - __try - { - std::__uninitialized_copy_a(__first, __last, __new_start, - _M_get_Tp_allocator()); - this->_M_impl._M_start = __new_start; - } - __catch(...) - { - _M_destroy_nodes(__new_start._M_node, - this->_M_impl._M_start._M_node); - __throw_exception_again; - } - } - else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) - { - iterator __new_finish = _M_reserve_elements_at_back(__n); - __try - { - std::__uninitialized_copy_a(__first, __last, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish = __new_finish; - } - __catch(...) - { - _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, - __new_finish._M_node + 1); - __throw_exception_again; - } - } - else - _M_insert_aux(__pos, __first, __last, __n); - } - - template -#if __cplusplus >= 201103L - template - typename deque<_Tp, _Alloc>::iterator - deque<_Tp, _Alloc>:: - _M_insert_aux(iterator __pos, _Args&&... __args) - { - value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy -#else - typename deque<_Tp, _Alloc>::iterator - deque<_Tp, _Alloc>:: - _M_insert_aux(iterator __pos, const value_type& __x) - { - value_type __x_copy = __x; // XXX copy -#endif - difference_type __index = __pos - this->_M_impl._M_start; - if (static_cast(__index) < size() / 2) - { - push_front(_GLIBCXX_MOVE(front())); - iterator __front1 = this->_M_impl._M_start; - ++__front1; - iterator __front2 = __front1; - ++__front2; - __pos = this->_M_impl._M_start + __index; - iterator __pos1 = __pos; - ++__pos1; - _GLIBCXX_MOVE3(__front2, __pos1, __front1); - } - else - { - push_back(_GLIBCXX_MOVE(back())); - iterator __back1 = this->_M_impl._M_finish; - --__back1; - iterator __back2 = __back1; - --__back2; - __pos = this->_M_impl._M_start + __index; - _GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1); - } - *__pos = _GLIBCXX_MOVE(__x_copy); - return __pos; - } - - template - void - deque<_Tp, _Alloc>:: - _M_insert_aux(iterator __pos, size_type __n, const value_type& __x) - { - const difference_type __elems_before = __pos - this->_M_impl._M_start; - const size_type __length = this->size(); - value_type __x_copy = __x; - if (__elems_before < difference_type(__length / 2)) - { - iterator __new_start = _M_reserve_elements_at_front(__n); - iterator __old_start = this->_M_impl._M_start; - __pos = this->_M_impl._M_start + __elems_before; - __try - { - if (__elems_before >= difference_type(__n)) - { - iterator __start_n = (this->_M_impl._M_start - + difference_type(__n)); - std::__uninitialized_move_a(this->_M_impl._M_start, - __start_n, __new_start, - _M_get_Tp_allocator()); - this->_M_impl._M_start = __new_start; - _GLIBCXX_MOVE3(__start_n, __pos, __old_start); - std::fill(__pos - difference_type(__n), __pos, __x_copy); - } - else - { - std::__uninitialized_move_fill(this->_M_impl._M_start, - __pos, __new_start, - this->_M_impl._M_start, - __x_copy, - _M_get_Tp_allocator()); - this->_M_impl._M_start = __new_start; - std::fill(__old_start, __pos, __x_copy); - } - } - __catch(...) - { - _M_destroy_nodes(__new_start._M_node, - this->_M_impl._M_start._M_node); - __throw_exception_again; - } - } - else - { - iterator __new_finish = _M_reserve_elements_at_back(__n); - iterator __old_finish = this->_M_impl._M_finish; - const difference_type __elems_after = - difference_type(__length) - __elems_before; - __pos = this->_M_impl._M_finish - __elems_after; - __try - { - if (__elems_after > difference_type(__n)) - { - iterator __finish_n = (this->_M_impl._M_finish - - difference_type(__n)); - std::__uninitialized_move_a(__finish_n, - this->_M_impl._M_finish, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish = __new_finish; - _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); - std::fill(__pos, __pos + difference_type(__n), __x_copy); - } - else - { - std::__uninitialized_fill_move(this->_M_impl._M_finish, - __pos + difference_type(__n), - __x_copy, __pos, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish = __new_finish; - std::fill(__pos, __old_finish, __x_copy); - } - } - __catch(...) - { - _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, - __new_finish._M_node + 1); - __throw_exception_again; - } - } - } - - template - template - void - deque<_Tp, _Alloc>:: - _M_insert_aux(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - size_type __n) - { - const difference_type __elemsbefore = __pos - this->_M_impl._M_start; - const size_type __length = size(); - if (static_cast(__elemsbefore) < __length / 2) - { - iterator __new_start = _M_reserve_elements_at_front(__n); - iterator __old_start = this->_M_impl._M_start; - __pos = this->_M_impl._M_start + __elemsbefore; - __try - { - if (__elemsbefore >= difference_type(__n)) - { - iterator __start_n = (this->_M_impl._M_start - + difference_type(__n)); - std::__uninitialized_move_a(this->_M_impl._M_start, - __start_n, __new_start, - _M_get_Tp_allocator()); - this->_M_impl._M_start = __new_start; - _GLIBCXX_MOVE3(__start_n, __pos, __old_start); - std::copy(__first, __last, __pos - difference_type(__n)); - } - else - { - _ForwardIterator __mid = __first; - std::advance(__mid, difference_type(__n) - __elemsbefore); - std::__uninitialized_move_copy(this->_M_impl._M_start, - __pos, __first, __mid, - __new_start, - _M_get_Tp_allocator()); - this->_M_impl._M_start = __new_start; - std::copy(__mid, __last, __old_start); - } - } - __catch(...) - { - _M_destroy_nodes(__new_start._M_node, - this->_M_impl._M_start._M_node); - __throw_exception_again; - } - } - else - { - iterator __new_finish = _M_reserve_elements_at_back(__n); - iterator __old_finish = this->_M_impl._M_finish; - const difference_type __elemsafter = - difference_type(__length) - __elemsbefore; - __pos = this->_M_impl._M_finish - __elemsafter; - __try - { - if (__elemsafter > difference_type(__n)) - { - iterator __finish_n = (this->_M_impl._M_finish - - difference_type(__n)); - std::__uninitialized_move_a(__finish_n, - this->_M_impl._M_finish, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish = __new_finish; - _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); - std::copy(__first, __last, __pos); - } - else - { - _ForwardIterator __mid = __first; - std::advance(__mid, __elemsafter); - std::__uninitialized_copy_move(__mid, __last, __pos, - this->_M_impl._M_finish, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish = __new_finish; - std::copy(__first, __mid, __pos); - } - } - __catch(...) - { - _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, - __new_finish._M_node + 1); - __throw_exception_again; - } - } - } - - template - void - deque<_Tp, _Alloc>:: - _M_destroy_data_aux(iterator __first, iterator __last) - { - for (_Map_pointer __node = __first._M_node + 1; - __node < __last._M_node; ++__node) - std::_Destroy(*__node, *__node + _S_buffer_size(), - _M_get_Tp_allocator()); - - if (__first._M_node != __last._M_node) - { - std::_Destroy(__first._M_cur, __first._M_last, - _M_get_Tp_allocator()); - std::_Destroy(__last._M_first, __last._M_cur, - _M_get_Tp_allocator()); - } - else - std::_Destroy(__first._M_cur, __last._M_cur, - _M_get_Tp_allocator()); - } - - template - void - deque<_Tp, _Alloc>:: - _M_new_elements_at_front(size_type __new_elems) - { - if (this->max_size() - this->size() < __new_elems) - __throw_length_error(__N("deque::_M_new_elements_at_front")); - - const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1) - / _S_buffer_size()); - _M_reserve_map_at_front(__new_nodes); - size_type __i; - __try - { - for (__i = 1; __i <= __new_nodes; ++__i) - *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node(); - } - __catch(...) - { - for (size_type __j = 1; __j < __i; ++__j) - _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j)); - __throw_exception_again; - } - } - - template - void - deque<_Tp, _Alloc>:: - _M_new_elements_at_back(size_type __new_elems) - { - if (this->max_size() - this->size() < __new_elems) - __throw_length_error(__N("deque::_M_new_elements_at_back")); - - const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1) - / _S_buffer_size()); - _M_reserve_map_at_back(__new_nodes); - size_type __i; - __try - { - for (__i = 1; __i <= __new_nodes; ++__i) - *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node(); - } - __catch(...) - { - for (size_type __j = 1; __j < __i; ++__j) - _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j)); - __throw_exception_again; - } - } - - template - void - deque<_Tp, _Alloc>:: - _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front) - { - const size_type __old_num_nodes - = this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1; - const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add; - - _Map_pointer __new_nstart; - if (this->_M_impl._M_map_size > 2 * __new_num_nodes) - { - __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size - - __new_num_nodes) / 2 - + (__add_at_front ? __nodes_to_add : 0); - if (__new_nstart < this->_M_impl._M_start._M_node) - std::copy(this->_M_impl._M_start._M_node, - this->_M_impl._M_finish._M_node + 1, - __new_nstart); - else - std::copy_backward(this->_M_impl._M_start._M_node, - this->_M_impl._M_finish._M_node + 1, - __new_nstart + __old_num_nodes); - } - else - { - size_type __new_map_size = this->_M_impl._M_map_size - + std::max(this->_M_impl._M_map_size, - __nodes_to_add) + 2; - - _Map_pointer __new_map = this->_M_allocate_map(__new_map_size); - __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2 - + (__add_at_front ? __nodes_to_add : 0); - std::copy(this->_M_impl._M_start._M_node, - this->_M_impl._M_finish._M_node + 1, - __new_nstart); - _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); - - this->_M_impl._M_map = __new_map; - this->_M_impl._M_map_size = __new_map_size; - } - - this->_M_impl._M_start._M_set_node(__new_nstart); - this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1); - } - -_GLIBCXX_END_NAMESPACE_CONTAINER - - // Overload for deque::iterators, exploiting the "segmented-iterator - // optimization". - template - void - __fill_a1(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __first, - const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __last, - const _VTp& __value) - { - typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; - if (__first._M_node != __last._M_node) - { - std::__fill_a1(__first._M_cur, __first._M_last, __value); - - for (typename _Iter::_Map_pointer __node = __first._M_node + 1; - __node < __last._M_node; ++__node) - std::__fill_a1(*__node, *__node + _Iter::_S_buffer_size(), __value); - - std::__fill_a1(__last._M_first, __last._M_cur, __value); - } - else - std::__fill_a1(__first._M_cur, __last._M_cur, __value); - } - - template - _OI - __copy_move_dit(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, - _OI __result) - { - typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; - if (__first._M_node != __last._M_node) - { - __result - = std::__copy_move_a1<_IsMove>(__first._M_cur, __first._M_last, - __result); - - for (typename _Iter::_Map_pointer __node = __first._M_node + 1; - __node != __last._M_node; ++__node) - __result - = std::__copy_move_a1<_IsMove>(*__node, - *__node + _Iter::_S_buffer_size(), - __result); - - return std::__copy_move_a1<_IsMove>(__last._M_first, __last._M_cur, - __result); - } - - return std::__copy_move_a1<_IsMove>(__first._M_cur, __last._M_cur, - __result); - } - - template - _OI - __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, - _OI __result) - { return __copy_move_dit<_IsMove>(__first, __last, __result); } - - template - _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> - __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, - _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, - _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result) - { return __copy_move_dit<_IsMove>(__first, __last, __result); } - - template - typename __gnu_cxx::__enable_if< - __is_random_access_iter<_II>::__value, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type - __copy_move_a1(_II __first, _II __last, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result) - { - typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; - typedef typename _Iter::difference_type difference_type; - - difference_type __len = __last - __first; - while (__len > 0) - { - const difference_type __clen - = std::min(__len, __result._M_last - __result._M_cur); - std::__copy_move_a1<_IsMove>(__first, __first + __clen, - __result._M_cur); - - __first += __clen; - __result += __clen; - __len -= __clen; - } - - return __result; - } - - template - _OI - __copy_move_backward_dit( - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, - _OI __result) - { - typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; - if (__first._M_node != __last._M_node) - { - __result = std::__copy_move_backward_a1<_IsMove>( - __last._M_first, __last._M_cur, __result); - - for (typename _Iter::_Map_pointer __node = __last._M_node - 1; - __node != __first._M_node; --__node) - __result = std::__copy_move_backward_a1<_IsMove>( - *__node, *__node + _Iter::_S_buffer_size(), __result); - - return std::__copy_move_backward_a1<_IsMove>( - __first._M_cur, __first._M_last, __result); - } - - return std::__copy_move_backward_a1<_IsMove>( - __first._M_cur, __last._M_cur, __result); - } - - template - _OI - __copy_move_backward_a1( - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, - _OI __result) - { return __copy_move_backward_dit<_IsMove>(__first, __last, __result); } - - template - _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> - __copy_move_backward_a1( - _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, - _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, - _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result) - { return __copy_move_backward_dit<_IsMove>(__first, __last, __result); } - - template - typename __gnu_cxx::__enable_if< - __is_random_access_iter<_II>::__value, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type - __copy_move_backward_a1(_II __first, _II __last, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result) - { - typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; - typedef typename _Iter::difference_type difference_type; - - difference_type __len = __last - __first; - while (__len > 0) - { - difference_type __rlen = __result._M_cur - __result._M_first; - _Tp* __rend = __result._M_cur; - if (!__rlen) - { - __rlen = _Iter::_S_buffer_size(); - __rend = *(__result._M_node - 1) + __rlen; - } - - const difference_type __clen = std::min(__len, __rlen); - std::__copy_move_backward_a1<_IsMove>(__last - __clen, __last, __rend); - - __last -= __clen; - __result -= __clen; - __len -= __clen; - } - - return __result; - } - - template - bool - __equal_dit( - const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __first1, - const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __last1, - _II __first2) - { - typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; - if (__first1._M_node != __last1._M_node) - { - if (!std::__equal_aux1(__first1._M_cur, __first1._M_last, __first2)) - return false; - - __first2 += __first1._M_last - __first1._M_cur; - for (typename _Iter::_Map_pointer __node = __first1._M_node + 1; - __node != __last1._M_node; - __first2 += _Iter::_S_buffer_size(), ++__node) - if (!std::__equal_aux1(*__node, *__node + _Iter::_S_buffer_size(), - __first2)) - return false; - - return std::__equal_aux1(__last1._M_first, __last1._M_cur, __first2); - } - - return std::__equal_aux1(__first1._M_cur, __last1._M_cur, __first2); - } - - template - typename __gnu_cxx::__enable_if< - __is_random_access_iter<_II>::__value, bool>::__type - __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first1, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last1, - _II __first2) - { return std::__equal_dit(__first1, __last1, __first2); } - - template - bool - __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __first1, - _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __last1, - _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2> __first2) - { return std::__equal_dit(__first1, __last1, __first2); } - - template - typename __gnu_cxx::__enable_if< - __is_random_access_iter<_II>::__value, bool>::__type - __equal_aux1(_II __first1, _II __last1, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first2) - { - typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; - typedef typename _Iter::difference_type difference_type; - - difference_type __len = __last1 - __first1; - while (__len > 0) - { - const difference_type __clen - = std::min(__len, __first2._M_last - __first2._M_cur); - if (!std::__equal_aux1(__first1, __first1 + __clen, __first2._M_cur)) - return false; - - __first1 += __clen; - __len -= __clen; - __first2 += __clen; - } - - return true; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h b/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h deleted file mode 100644 index 3c12cfcf8..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h +++ /dev/null @@ -1,312 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/enable_special_members.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. - */ - -#ifndef _ENABLE_SPECIAL_MEMBERS_H -#define _ENABLE_SPECIAL_MEMBERS_H 1 - -#pragma GCC system_header - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - struct _Enable_default_constructor_tag - { - explicit constexpr _Enable_default_constructor_tag() = default; - }; - -/** - * @brief A mixin helper to conditionally enable or disable the default - * constructor. - * @sa _Enable_special_members - */ -template - struct _Enable_default_constructor - { - constexpr _Enable_default_constructor() noexcept = default; - constexpr _Enable_default_constructor(_Enable_default_constructor const&) - noexcept = default; - constexpr _Enable_default_constructor(_Enable_default_constructor&&) - noexcept = default; - _Enable_default_constructor& - operator=(_Enable_default_constructor const&) noexcept = default; - _Enable_default_constructor& - operator=(_Enable_default_constructor&&) noexcept = default; - - // Can be used in other ctors. - constexpr explicit - _Enable_default_constructor(_Enable_default_constructor_tag) { } - }; - - -/** - * @brief A mixin helper to conditionally enable or disable the default - * destructor. - * @sa _Enable_special_members - */ -template - struct _Enable_destructor { }; - -/** - * @brief A mixin helper to conditionally enable or disable the copy/move - * special members. - * @sa _Enable_special_members - */ -template - struct _Enable_copy_move { }; - -/** - * @brief A mixin helper to conditionally enable or disable the special - * members. - * - * The @c _Tag type parameter is to make mixin bases unique and thus avoid - * ambiguities. - */ -template - struct _Enable_special_members - : private _Enable_default_constructor<_Default, _Tag>, - private _Enable_destructor<_Destructor, _Tag>, - private _Enable_copy_move<_Copy, _CopyAssignment, - _Move, _MoveAssignment, - _Tag> - { }; - -// Boilerplate follows. - -template - struct _Enable_default_constructor - { - constexpr _Enable_default_constructor() noexcept = delete; - constexpr _Enable_default_constructor(_Enable_default_constructor const&) - noexcept = default; - constexpr _Enable_default_constructor(_Enable_default_constructor&&) - noexcept = default; - _Enable_default_constructor& - operator=(_Enable_default_constructor const&) noexcept = default; - _Enable_default_constructor& - operator=(_Enable_default_constructor&&) noexcept = default; - - // Can be used in other ctors. - constexpr explicit - _Enable_default_constructor(_Enable_default_constructor_tag) { } - }; - -template - struct _Enable_destructor - { ~_Enable_destructor() noexcept = delete; }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = default; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = default; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = default; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = default; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = default; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = default; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = default; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = delete; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = delete; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = delete; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = delete; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = delete; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = default; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = delete; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = delete; - }; - -template - struct _Enable_copy_move - { - constexpr _Enable_copy_move() noexcept = default; - constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; - constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move const&) noexcept = delete; - _Enable_copy_move& - operator=(_Enable_copy_move&&) noexcept = delete; - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // _ENABLE_SPECIAL_MEMBERS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/erase_if.h b/resources/sources/avr-libstdcpp/include/bits/erase_if.h deleted file mode 100644 index dc5e6ae58..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/erase_if.h +++ /dev/null @@ -1,72 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2015-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/erase_if.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. - */ - -#ifndef _GLIBCXX_ERASE_IF_H -#define _GLIBCXX_ERASE_IF_H 1 - -#pragma GCC system_header - -#if __cplusplus >= 201402L - -namespace std -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#if __cplusplus > 201703L -# define __cpp_lib_erase_if 202002L -#endif - - namespace __detail - { - template - typename _Container::size_type - __erase_nodes_if(_Container& __cont, _Predicate __pred) - { - typename _Container::size_type __num = 0; - for (auto __iter = __cont.begin(), __last = __cont.end(); - __iter != __last;) - { - if (__pred(*__iter)) - { - __iter = __cont.erase(__iter); - ++__num; - } - else - ++__iter; - } - return __num; - } - } // namespace __detail - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++14 - -#endif // _GLIBCXX_ERASE_IF_H diff --git a/resources/sources/avr-libstdcpp/include/bits/error_constants.h b/resources/sources/avr-libstdcpp/include/bits/error_constants.h deleted file mode 100644 index 203891454..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/error_constants.h +++ /dev/null @@ -1,180 +0,0 @@ -// Specific definitions for generic platforms -*- C++ -*- - -// Copyright (C) 2007-2024 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/error_constants.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{system_error} - */ - -#ifndef _GLIBCXX_ERROR_CONSTANTS -#define _GLIBCXX_ERROR_CONSTANTS 1 - -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - enum class errc - { - address_family_not_supported = EAFNOSUPPORT, - address_in_use = EADDRINUSE, - address_not_available = EADDRNOTAVAIL, - already_connected = EISCONN, - argument_list_too_long = E2BIG, - argument_out_of_domain = EDOM, - bad_address = EFAULT, - bad_file_descriptor = EBADF, - -#ifdef EBADMSG - bad_message = EBADMSG, -#endif - - broken_pipe = EPIPE, - connection_aborted = ECONNABORTED, - connection_already_in_progress = EALREADY, - connection_refused = ECONNREFUSED, - connection_reset = ECONNRESET, - cross_device_link = EXDEV, - destination_address_required = EDESTADDRREQ, - device_or_resource_busy = EBUSY, - directory_not_empty = ENOTEMPTY, - executable_format_error = ENOEXEC, - file_exists = EEXIST, - file_too_large = EFBIG, - filename_too_long = ENAMETOOLONG, - function_not_supported = ENOSYS, - host_unreachable = EHOSTUNREACH, - -#ifdef EIDRM - identifier_removed = EIDRM, -#endif - - illegal_byte_sequence = EILSEQ, - inappropriate_io_control_operation = ENOTTY, - interrupted = EINTR, - invalid_argument = EINVAL, - invalid_seek = ESPIPE, - io_error = EIO, - is_a_directory = EISDIR, - message_size = EMSGSIZE, - network_down = ENETDOWN, - network_reset = ENETRESET, - network_unreachable = ENETUNREACH, - no_buffer_space = ENOBUFS, - no_child_process = ECHILD, - -#ifdef ENOLINK - no_link = ENOLINK, -#endif - - no_lock_available = ENOLCK, - -#ifdef ENODATA - no_message_available = ENODATA, -#endif - - no_message = ENOMSG, - no_protocol_option = ENOPROTOOPT, - no_space_on_device = ENOSPC, - -#ifdef ENOSR - no_stream_resources = ENOSR, -#endif - - no_such_device_or_address = ENXIO, - no_such_device = ENODEV, - no_such_file_or_directory = ENOENT, - no_such_process = ESRCH, - not_a_directory = ENOTDIR, - not_a_socket = ENOTSOCK, - -#ifdef ENOSTR - not_a_stream = ENOSTR, -#endif - - not_connected = ENOTCONN, - not_enough_memory = ENOMEM, - -#ifdef ENOTSUP - not_supported = ENOTSUP, -#endif - -#ifdef ECANCELED - operation_canceled = ECANCELED, -#endif - - operation_in_progress = EINPROGRESS, - operation_not_permitted = EPERM, - operation_not_supported = EOPNOTSUPP, - operation_would_block = EWOULDBLOCK, - -#ifdef EOWNERDEAD - owner_dead = EOWNERDEAD, -#endif - - permission_denied = EACCES, - -#ifdef EPROTO - protocol_error = EPROTO, -#endif - - protocol_not_supported = EPROTONOSUPPORT, - read_only_file_system = EROFS, - resource_deadlock_would_occur = EDEADLK, - resource_unavailable_try_again = EAGAIN, - result_out_of_range = ERANGE, - -#ifdef ENOTRECOVERABLE - state_not_recoverable = ENOTRECOVERABLE, -#endif - -#ifdef ETIME - stream_timeout = ETIME, -#endif - -#ifdef ETXTBSY - text_file_busy = ETXTBSY, -#endif - - timed_out = ETIMEDOUT, - too_many_files_open_in_system = ENFILE, - too_many_files_open = EMFILE, - too_many_links = EMLINK, - too_many_symbolic_link_levels = ELOOP, - -#ifdef EOVERFLOW - value_too_large = EOVERFLOW, -#elif defined __AVR__ - value_too_large = 999, -#endif - - wrong_protocol_type = EPROTOTYPE - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/exception_defines.h b/resources/sources/avr-libstdcpp/include/bits/exception_defines.h deleted file mode 100644 index bc73d4194..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/exception_defines.h +++ /dev/null @@ -1,47 +0,0 @@ -// -fno-exceptions Support -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/exception_defines.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{exception} - */ - -#ifndef _EXCEPTION_DEFINES_H -#define _EXCEPTION_DEFINES_H 1 - -#pragma GCC system_header - -#if ! __cpp_exceptions -// Iff -fno-exceptions, transform error handling code to work without it. -# define __try if (true) -# define __catch(X) if (false) -# define __throw_exception_again -#else -// Else proceed normally. -# define __try try -# define __catch(X) catch(X) -# define __throw_exception_again throw -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/forward_list.h b/resources/sources/avr-libstdcpp/include/bits/forward_list.h deleted file mode 100644 index 49b2a9737..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/forward_list.h +++ /dev/null @@ -1,1514 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/forward_list.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{forward_list} - */ - -#ifndef _FORWARD_LIST_H -#define _FORWARD_LIST_H 1 - -#pragma GCC system_header - -#include -#include -#include -#include -#include -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - /** - * @brief A helper basic node class for %forward_list. - * This is just a linked list with nothing inside it. - * There are purely list shuffling utility methods here. - */ - struct _Fwd_list_node_base - { - _Fwd_list_node_base() = default; - _Fwd_list_node_base(_Fwd_list_node_base&& __x) noexcept - : _M_next(__x._M_next) - { __x._M_next = nullptr; } - - _Fwd_list_node_base(const _Fwd_list_node_base&) = delete; - _Fwd_list_node_base& operator=(const _Fwd_list_node_base&) = delete; - - _Fwd_list_node_base& - operator=(_Fwd_list_node_base&& __x) noexcept - { - _M_next = __x._M_next; - __x._M_next = nullptr; - return *this; - } - - _Fwd_list_node_base* _M_next = nullptr; - - _Fwd_list_node_base* - _M_transfer_after(_Fwd_list_node_base* __begin, - _Fwd_list_node_base* __end) noexcept - { - _Fwd_list_node_base* __keep = __begin->_M_next; - if (__end) - { - __begin->_M_next = __end->_M_next; - __end->_M_next = _M_next; - } - else - __begin->_M_next = nullptr; - _M_next = __keep; - return __end; - } - - void - _M_reverse_after() noexcept - { - _Fwd_list_node_base* __tail = _M_next; - if (!__tail) - return; - while (_Fwd_list_node_base* __temp = __tail->_M_next) - { - _Fwd_list_node_base* __keep = _M_next; - _M_next = __temp; - __tail->_M_next = __temp->_M_next; - _M_next->_M_next = __keep; - } - } - }; - - /** - * @brief A helper node class for %forward_list. - * This is just a linked list with uninitialized storage for a - * data value in each node. - * There is a sorting utility method. - */ - template - struct _Fwd_list_node - : public _Fwd_list_node_base - { - _Fwd_list_node() = default; - - __gnu_cxx::__aligned_buffer<_Tp> _M_storage; - - _Tp* - _M_valptr() noexcept - { return _M_storage._M_ptr(); } - - const _Tp* - _M_valptr() const noexcept - { return _M_storage._M_ptr(); } - }; - - /** - * @brief A forward_list::iterator. - * - * All the functions are op overloads. - */ - template - struct _Fwd_list_iterator - { - typedef _Fwd_list_iterator<_Tp> _Self; - typedef _Fwd_list_node<_Tp> _Node; - - typedef _Tp value_type; - typedef _Tp* pointer; - typedef _Tp& reference; - typedef ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - _Fwd_list_iterator() noexcept - : _M_node() { } - - explicit - _Fwd_list_iterator(_Fwd_list_node_base* __n) noexcept - : _M_node(__n) { } - - reference - operator*() const noexcept - { return *static_cast<_Node*>(this->_M_node)->_M_valptr(); } - - pointer - operator->() const noexcept - { return static_cast<_Node*>(this->_M_node)->_M_valptr(); } - - _Self& - operator++() noexcept - { - _M_node = _M_node->_M_next; - return *this; - } - - _Self - operator++(int) noexcept - { - _Self __tmp(*this); - _M_node = _M_node->_M_next; - return __tmp; - } - - /** - * @brief Forward list iterator equality comparison. - */ - friend bool - operator==(const _Self& __x, const _Self& __y) noexcept - { return __x._M_node == __y._M_node; } - -#if __cpp_impl_three_way_comparison < 201907L - /** - * @brief Forward list iterator inequality comparison. - */ - friend bool - operator!=(const _Self& __x, const _Self& __y) noexcept - { return __x._M_node != __y._M_node; } -#endif - - _Self - _M_next() const noexcept - { - if (_M_node) - return _Fwd_list_iterator(_M_node->_M_next); - else - return _Fwd_list_iterator(nullptr); - } - - _Fwd_list_node_base* _M_node; - }; - - /** - * @brief A forward_list::const_iterator. - * - * All the functions are op overloads. - */ - template - struct _Fwd_list_const_iterator - { - typedef _Fwd_list_const_iterator<_Tp> _Self; - typedef const _Fwd_list_node<_Tp> _Node; - typedef _Fwd_list_iterator<_Tp> iterator; - - typedef _Tp value_type; - typedef const _Tp* pointer; - typedef const _Tp& reference; - typedef ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - _Fwd_list_const_iterator() noexcept - : _M_node() { } - - explicit - _Fwd_list_const_iterator(const _Fwd_list_node_base* __n) noexcept - : _M_node(__n) { } - - _Fwd_list_const_iterator(const iterator& __iter) noexcept - : _M_node(__iter._M_node) { } - - reference - operator*() const noexcept - { return *static_cast<_Node*>(this->_M_node)->_M_valptr(); } - - pointer - operator->() const noexcept - { return static_cast<_Node*>(this->_M_node)->_M_valptr(); } - - _Self& - operator++() noexcept - { - _M_node = _M_node->_M_next; - return *this; - } - - _Self - operator++(int) noexcept - { - _Self __tmp(*this); - _M_node = _M_node->_M_next; - return __tmp; - } - - /** - * @brief Forward list const_iterator equality comparison. - */ - friend bool - operator==(const _Self& __x, const _Self& __y) noexcept - { return __x._M_node == __y._M_node; } - -#if __cpp_impl_three_way_comparison < 201907L - /** - * @brief Forward list const_iterator inequality comparison. - */ - friend bool - operator!=(const _Self& __x, const _Self& __y) noexcept - { return __x._M_node != __y._M_node; } -#endif - - _Self - _M_next() const noexcept - { - if (this->_M_node) - return _Fwd_list_const_iterator(_M_node->_M_next); - else - return _Fwd_list_const_iterator(nullptr); - } - - const _Fwd_list_node_base* _M_node; - }; - - /** - * @brief Base class for %forward_list. - */ - template - struct _Fwd_list_base - { - protected: - typedef __alloc_rebind<_Alloc, _Fwd_list_node<_Tp>> _Node_alloc_type; - typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; - - struct _Fwd_list_impl - : public _Node_alloc_type - { - _Fwd_list_node_base _M_head; - - _Fwd_list_impl() - noexcept(is_nothrow_default_constructible<_Node_alloc_type>::value) - : _Node_alloc_type(), _M_head() - { } - - _Fwd_list_impl(_Fwd_list_impl&&) = default; - - _Fwd_list_impl(_Fwd_list_impl&& __fl, _Node_alloc_type&& __a) - : _Node_alloc_type(std::move(__a)), _M_head(std::move(__fl._M_head)) - { } - - _Fwd_list_impl(_Node_alloc_type&& __a) - : _Node_alloc_type(std::move(__a)), _M_head() - { } - }; - - _Fwd_list_impl _M_impl; - - public: - typedef _Fwd_list_iterator<_Tp> iterator; - typedef _Fwd_list_const_iterator<_Tp> const_iterator; - typedef _Fwd_list_node<_Tp> _Node; - - _Node_alloc_type& - _M_get_Node_allocator() noexcept - { return this->_M_impl; } - - const _Node_alloc_type& - _M_get_Node_allocator() const noexcept - { return this->_M_impl; } - - _Fwd_list_base() = default; - - _Fwd_list_base(_Node_alloc_type&& __a) - : _M_impl(std::move(__a)) { } - - // When allocators are always equal. - _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a, - std::true_type) - : _M_impl(std::move(__lst._M_impl), std::move(__a)) - { } - - // When allocators are not always equal. - _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a); - - _Fwd_list_base(_Fwd_list_base&&) = default; - - ~_Fwd_list_base() - { _M_erase_after(&_M_impl._M_head, nullptr); } - - protected: - _Node* - _M_get_node() - { - auto __ptr = _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1); - return std::__to_address(__ptr); - } - - template - _Node* - _M_create_node(_Args&&... __args) - { - _Node* __node = this->_M_get_node(); - __try - { - ::new ((void*)__node) _Node; - _Node_alloc_traits::construct(_M_get_Node_allocator(), - __node->_M_valptr(), - std::forward<_Args>(__args)...); - } - __catch(...) - { - this->_M_put_node(__node); - __throw_exception_again; - } - return __node; - } - - template - _Fwd_list_node_base* - _M_insert_after(const_iterator __pos, _Args&&... __args); - - void - _M_put_node(_Node* __p) - { - typedef typename _Node_alloc_traits::pointer _Ptr; - auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__p); - _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ptr, 1); - } - - _Fwd_list_node_base* - _M_erase_after(_Fwd_list_node_base* __pos); - - _Fwd_list_node_base* - _M_erase_after(_Fwd_list_node_base* __pos, - _Fwd_list_node_base* __last); - }; - - /** - * @brief A standard container with linear time access to elements, - * and fixed time insertion/deletion at any point in the sequence. - * - * @ingroup sequences - * - * @tparam _Tp Type of element. - * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. - * - * Meets the requirements of a container, a - * sequence, including the - * optional sequence requirements with the - * %exception of @c at and @c operator[]. - * - * This is a @e singly @e linked %list. Traversal up the - * %list requires linear time, but adding and removing elements (or - * @e nodes) is done in constant time, regardless of where the - * change takes place. Unlike std::vector and std::deque, - * random-access iterators are not provided, so subscripting ( @c - * [] ) access is not allowed. For algorithms which only need - * sequential access, this lack makes no difference. - * - * Also unlike the other standard containers, std::forward_list provides - * specialized algorithms %unique to linked lists, such as - * splicing, sorting, and in-place reversal. - */ - template> - class forward_list : private _Fwd_list_base<_Tp, _Alloc> - { - static_assert(is_same::type, _Tp>::value, - "std::forward_list must have a non-const, non-volatile value_type"); -#if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same::value, - "std::forward_list must have the same value_type as its allocator"); -#endif - - private: - typedef _Fwd_list_base<_Tp, _Alloc> _Base; - typedef _Fwd_list_node_base _Node_base; - typedef typename _Base::_Node _Node; - typedef typename _Base::_Node_alloc_type _Node_alloc_type; - typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; - typedef allocator_traits<__alloc_rebind<_Alloc, _Tp>> _Alloc_traits; - - public: - // types: - typedef _Tp value_type; - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - - typedef typename _Base::iterator iterator; - typedef typename _Base::const_iterator const_iterator; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef _Alloc allocator_type; - - // 23.3.4.2 construct/copy/destroy: - - /** - * @brief Creates a %forward_list with no elements. - */ - forward_list() = default; - - /** - * @brief Creates a %forward_list with no elements. - * @param __al An allocator object. - */ - explicit - forward_list(const _Alloc& __al) noexcept - : _Base(_Node_alloc_type(__al)) - { } - - /** - * @brief Copy constructor with allocator argument. - * @param __list Input list to copy. - * @param __al An allocator object. - */ - forward_list(const forward_list& __list, const _Alloc& __al) - : _Base(_Node_alloc_type(__al)) - { _M_range_initialize(__list.begin(), __list.end()); } - - private: - forward_list(forward_list&& __list, _Node_alloc_type&& __al, - false_type) - : _Base(std::move(__list), std::move(__al)) - { - // If __list is not empty it means its allocator is not equal to __a, - // so we need to move from each element individually. - insert_after(cbefore_begin(), - std::__make_move_if_noexcept_iterator(__list.begin()), - std::__make_move_if_noexcept_iterator(__list.end())); - } - - forward_list(forward_list&& __list, _Node_alloc_type&& __al, - true_type) - noexcept - : _Base(std::move(__list), _Node_alloc_type(__al), true_type{}) - { } - - public: - /** - * @brief Move constructor with allocator argument. - * @param __list Input list to move. - * @param __al An allocator object. - */ - forward_list(forward_list&& __list, const _Alloc& __al) - noexcept(_Node_alloc_traits::_S_always_equal()) - : forward_list(std::move(__list), _Node_alloc_type(__al), - typename _Node_alloc_traits::is_always_equal{}) - { } - - /** - * @brief Creates a %forward_list with default constructed elements. - * @param __n The number of elements to initially create. - * @param __al An allocator object. - * - * This constructor creates the %forward_list with @a __n default - * constructed elements. - */ - explicit - forward_list(size_type __n, const _Alloc& __al = _Alloc()) - : _Base(_Node_alloc_type(__al)) - { _M_default_initialize(__n); } - - /** - * @brief Creates a %forward_list with copies of an exemplar element. - * @param __n The number of elements to initially create. - * @param __value An element to copy. - * @param __al An allocator object. - * - * This constructor fills the %forward_list with @a __n copies of - * @a __value. - */ - forward_list(size_type __n, const _Tp& __value, - const _Alloc& __al = _Alloc()) - : _Base(_Node_alloc_type(__al)) - { _M_fill_initialize(__n, __value); } - - /** - * @brief Builds a %forward_list from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __al An allocator object. - * - * Create a %forward_list consisting of copies of the elements from - * [@a __first,@a __last). This is linear in N (where N is - * distance(@a __first,@a __last)). - */ - template> - forward_list(_InputIterator __first, _InputIterator __last, - const _Alloc& __al = _Alloc()) - : _Base(_Node_alloc_type(__al)) - { _M_range_initialize(__first, __last); } - - /** - * @brief The %forward_list copy constructor. - * @param __list A %forward_list of identical element and allocator - * types. - */ - forward_list(const forward_list& __list) - : _Base(_Node_alloc_traits::_S_select_on_copy( - __list._M_get_Node_allocator())) - { _M_range_initialize(__list.begin(), __list.end()); } - - /** - * @brief The %forward_list move constructor. - * @param __list A %forward_list of identical element and allocator - * types. - * - * The newly-created %forward_list contains the exact contents of the - * moved instance. The contents of the moved instance are a valid, but - * unspecified %forward_list. - */ - forward_list(forward_list&&) = default; - - /** - * @brief Builds a %forward_list from an initializer_list - * @param __il An initializer_list of value_type. - * @param __al An allocator object. - * - * Create a %forward_list consisting of copies of the elements - * in the initializer_list @a __il. This is linear in __il.size(). - */ - forward_list(std::initializer_list<_Tp> __il, - const _Alloc& __al = _Alloc()) - : _Base(_Node_alloc_type(__al)) - { _M_range_initialize(__il.begin(), __il.end()); } - - /** - * @brief The forward_list dtor. - */ - ~forward_list() noexcept - { } - - /** - * @brief The %forward_list assignment operator. - * @param __list A %forward_list of identical element and allocator - * types. - * - * All the elements of @a __list are copied. - * - * Whether the allocator is copied depends on the allocator traits. - */ - forward_list& - operator=(const forward_list& __list); - - /** - * @brief The %forward_list move assignment operator. - * @param __list A %forward_list of identical element and allocator - * types. - * - * The contents of @a __list are moved into this %forward_list - * (without copying, if the allocators permit it). - * - * Afterwards @a __list is a valid, but unspecified %forward_list - * - * Whether the allocator is moved depends on the allocator traits. - */ - forward_list& - operator=(forward_list&& __list) - noexcept(_Node_alloc_traits::_S_nothrow_move()) - { - constexpr bool __move_storage = - _Node_alloc_traits::_S_propagate_on_move_assign() - || _Node_alloc_traits::_S_always_equal(); - _M_move_assign(std::move(__list), __bool_constant<__move_storage>()); - return *this; - } - - /** - * @brief The %forward_list initializer list assignment operator. - * @param __il An initializer_list of value_type. - * - * Replace the contents of the %forward_list with copies of the - * elements in the initializer_list @a __il. This is linear in - * __il.size(). - */ - forward_list& - operator=(std::initializer_list<_Tp> __il) - { - assign(__il); - return *this; - } - - /** - * @brief Assigns a range to a %forward_list. - * @param __first An input iterator. - * @param __last An input iterator. - * - * This function fills a %forward_list with copies of the elements - * in the range [@a __first,@a __last). - * - * Note that the assignment completely changes the %forward_list and - * that the number of elements of the resulting %forward_list is the - * same as the number of elements assigned. - */ - template> - void - assign(_InputIterator __first, _InputIterator __last) - { - typedef is_assignable<_Tp, decltype(*__first)> __assignable; - _M_assign(__first, __last, __assignable()); - } - - /** - * @brief Assigns a given value to a %forward_list. - * @param __n Number of elements to be assigned. - * @param __val Value to be assigned. - * - * This function fills a %forward_list with @a __n copies of the - * given value. Note that the assignment completely changes the - * %forward_list, and that the resulting %forward_list has __n - * elements. - */ - void - assign(size_type __n, const _Tp& __val) - { _M_assign_n(__n, __val, is_copy_assignable<_Tp>()); } - - /** - * @brief Assigns an initializer_list to a %forward_list. - * @param __il An initializer_list of value_type. - * - * Replace the contents of the %forward_list with copies of the - * elements in the initializer_list @a __il. This is linear in - * il.size(). - */ - void - assign(std::initializer_list<_Tp> __il) - { assign(__il.begin(), __il.end()); } - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const noexcept - { return allocator_type(this->_M_get_Node_allocator()); } - - // 23.3.4.3 iterators: - - /** - * Returns a read/write iterator that points before the first element - * in the %forward_list. Iteration is done in ordinary element order. - */ - iterator - before_begin() noexcept - { return iterator(&this->_M_impl._M_head); } - - /** - * Returns a read-only (constant) iterator that points before the - * first element in the %forward_list. Iteration is done in ordinary - * element order. - */ - const_iterator - before_begin() const noexcept - { return const_iterator(&this->_M_impl._M_head); } - - /** - * Returns a read/write iterator that points to the first element - * in the %forward_list. Iteration is done in ordinary element order. - */ - iterator - begin() noexcept - { return iterator(this->_M_impl._M_head._M_next); } - - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %forward_list. Iteration is done in ordinary - * element order. - */ - const_iterator - begin() const noexcept - { return const_iterator(this->_M_impl._M_head._M_next); } - - /** - * Returns a read/write iterator that points one past the last - * element in the %forward_list. Iteration is done in ordinary - * element order. - */ - iterator - end() noexcept - { return iterator(nullptr); } - - /** - * Returns a read-only iterator that points one past the last - * element in the %forward_list. Iteration is done in ordinary - * element order. - */ - const_iterator - end() const noexcept - { return const_iterator(nullptr); } - - /** - * Returns a read-only (constant) iterator that points to the - * first element in the %forward_list. Iteration is done in ordinary - * element order. - */ - const_iterator - cbegin() const noexcept - { return const_iterator(this->_M_impl._M_head._M_next); } - - /** - * Returns a read-only (constant) iterator that points before the - * first element in the %forward_list. Iteration is done in ordinary - * element order. - */ - const_iterator - cbefore_begin() const noexcept - { return const_iterator(&this->_M_impl._M_head); } - - /** - * Returns a read-only (constant) iterator that points one past - * the last element in the %forward_list. Iteration is done in - * ordinary element order. - */ - const_iterator - cend() const noexcept - { return const_iterator(nullptr); } - - /** - * Returns true if the %forward_list is empty. (Thus begin() would - * equal end().) - */ - _GLIBCXX_NODISCARD bool - empty() const noexcept - { return this->_M_impl._M_head._M_next == nullptr; } - - /** - * Returns the largest possible number of elements of %forward_list. - */ - size_type - max_size() const noexcept - { return _Node_alloc_traits::max_size(this->_M_get_Node_allocator()); } - - // 23.3.4.4 element access: - - /** - * Returns a read/write reference to the data at the first - * element of the %forward_list. - */ - reference - front() - { - _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); - return *__front->_M_valptr(); - } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %forward_list. - */ - const_reference - front() const - { - _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); - return *__front->_M_valptr(); - } - - // 23.3.4.5 modifiers: - - /** - * @brief Constructs object in %forward_list at the front of the - * list. - * @param __args Arguments. - * - * This function will insert an object of type Tp constructed - * with Tp(std::forward(args)...) at the front of the list - * Due to the nature of a %forward_list this operation can - * be done in constant time, and does not invalidate iterators - * and references. - */ - template -#if __cplusplus > 201402L - reference -#else - void -#endif - emplace_front(_Args&&... __args) - { - this->_M_insert_after(cbefore_begin(), - std::forward<_Args>(__args)...); -#if __cplusplus > 201402L - return front(); -#endif - } - - /** - * @brief Add data to the front of the %forward_list. - * @param __val Data to be added. - * - * This is a typical stack operation. The function creates an - * element at the front of the %forward_list and assigns the given - * data to it. Due to the nature of a %forward_list this operation - * can be done in constant time, and does not invalidate iterators - * and references. - */ - void - push_front(const _Tp& __val) - { this->_M_insert_after(cbefore_begin(), __val); } - - /** - * - */ - void - push_front(_Tp&& __val) - { this->_M_insert_after(cbefore_begin(), std::move(__val)); } - - /** - * @brief Removes first element. - * - * This is a typical stack operation. It shrinks the %forward_list - * by one. Due to the nature of a %forward_list this operation can - * be done in constant time, and only invalidates iterators/references - * to the element being removed. - * - * Note that no data is returned, and if the first element's data - * is needed, it should be retrieved before pop_front() is - * called. - */ - void - pop_front() - { this->_M_erase_after(&this->_M_impl._M_head); } - - /** - * @brief Constructs object in %forward_list after the specified - * iterator. - * @param __pos A const_iterator into the %forward_list. - * @param __args Arguments. - * @return An iterator that points to the inserted data. - * - * This function will insert an object of type T constructed - * with T(std::forward(args)...) after the specified - * location. Due to the nature of a %forward_list this operation can - * be done in constant time, and does not invalidate iterators - * and references. - */ - template - iterator - emplace_after(const_iterator __pos, _Args&&... __args) - { return iterator(this->_M_insert_after(__pos, - std::forward<_Args>(__args)...)); } - - /** - * @brief Inserts given value into %forward_list after specified - * iterator. - * @param __pos An iterator into the %forward_list. - * @param __val Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value after - * the specified location. Due to the nature of a %forward_list this - * operation can be done in constant time, and does not - * invalidate iterators and references. - */ - iterator - insert_after(const_iterator __pos, const _Tp& __val) - { return iterator(this->_M_insert_after(__pos, __val)); } - - /** - * - */ - iterator - insert_after(const_iterator __pos, _Tp&& __val) - { return iterator(this->_M_insert_after(__pos, std::move(__val))); } - - /** - * @brief Inserts a number of copies of given data into the - * %forward_list. - * @param __pos An iterator into the %forward_list. - * @param __n Number of elements to be inserted. - * @param __val Data to be inserted. - * @return An iterator pointing to the last inserted copy of - * @a val or @a pos if @a n == 0. - * - * This function will insert a specified number of copies of the - * given data after the location specified by @a pos. - * - * This operation is linear in the number of elements inserted and - * does not invalidate iterators and references. - */ - iterator - insert_after(const_iterator __pos, size_type __n, const _Tp& __val); - - /** - * @brief Inserts a range into the %forward_list. - * @param __pos An iterator into the %forward_list. - * @param __first An input iterator. - * @param __last An input iterator. - * @return An iterator pointing to the last inserted element or - * @a __pos if @a __first == @a __last. - * - * This function will insert copies of the data in the range - * [@a __first,@a __last) into the %forward_list after the - * location specified by @a __pos. - * - * This operation is linear in the number of elements inserted and - * does not invalidate iterators and references. - */ - template> - iterator - insert_after(const_iterator __pos, - _InputIterator __first, _InputIterator __last); - - /** - * @brief Inserts the contents of an initializer_list into - * %forward_list after the specified iterator. - * @param __pos An iterator into the %forward_list. - * @param __il An initializer_list of value_type. - * @return An iterator pointing to the last inserted element - * or @a __pos if @a __il is empty. - * - * This function will insert copies of the data in the - * initializer_list @a __il into the %forward_list before the location - * specified by @a __pos. - * - * This operation is linear in the number of elements inserted and - * does not invalidate iterators and references. - */ - iterator - insert_after(const_iterator __pos, std::initializer_list<_Tp> __il) - { return insert_after(__pos, __il.begin(), __il.end()); } - - /** - * @brief Removes the element pointed to by the iterator following - * @c pos. - * @param __pos Iterator pointing before element to be erased. - * @return An iterator pointing to the element following the one - * that was erased, or end() if no such element exists. - * - * This function will erase the element at the given position and - * thus shorten the %forward_list by one. - * - * Due to the nature of a %forward_list this operation can be done - * in constant time, and only invalidates iterators/references to - * the element being removed. The user is also cautioned that - * this function only erases the element, and that if the element - * is itself a pointer, the pointed-to memory is not touched in - * any way. Managing the pointer is the user's responsibility. - */ - iterator - erase_after(const_iterator __pos) - { return iterator(this->_M_erase_after(const_cast<_Node_base*> - (__pos._M_node))); } - - /** - * @brief Remove a range of elements. - * @param __pos Iterator pointing before the first element to be - * erased. - * @param __last Iterator pointing to one past the last element to be - * erased. - * @return @ __last. - * - * This function will erase the elements in the range - * @a (__pos,__last) and shorten the %forward_list accordingly. - * - * This operation is linear time in the size of the range and only - * invalidates iterators/references to the element being removed. - * The user is also cautioned that this function only erases the - * elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer - * is the user's responsibility. - */ - iterator - erase_after(const_iterator __pos, const_iterator __last) - { return iterator(this->_M_erase_after(const_cast<_Node_base*> - (__pos._M_node), - const_cast<_Node_base*> - (__last._M_node))); } - - /** - * @brief Swaps data with another %forward_list. - * @param __list A %forward_list of the same element and allocator - * types. - * - * This exchanges the elements between two lists in constant - * time. Note that the global std::swap() function is - * specialized such that std::swap(l1,l2) will feed to this - * function. - * - * Whether the allocators are swapped depends on the allocator traits. - */ - void - swap(forward_list& __list) noexcept - { - std::swap(this->_M_impl._M_head._M_next, - __list._M_impl._M_head._M_next); - _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(), - __list._M_get_Node_allocator()); - } - - /** - * @brief Resizes the %forward_list to the specified number of - * elements. - * @param __sz Number of elements the %forward_list should contain. - * - * This function will %resize the %forward_list to the specified - * number of elements. If the number is smaller than the - * %forward_list's current number of elements the %forward_list - * is truncated, otherwise the %forward_list is extended and the - * new elements are default constructed. - */ - void - resize(size_type __sz); - - /** - * @brief Resizes the %forward_list to the specified number of - * elements. - * @param __sz Number of elements the %forward_list should contain. - * @param __val Data with which new elements should be populated. - * - * This function will %resize the %forward_list to the specified - * number of elements. If the number is smaller than the - * %forward_list's current number of elements the %forward_list - * is truncated, otherwise the %forward_list is extended and new - * elements are populated with given data. - */ - void - resize(size_type __sz, const value_type& __val); - - /** - * @brief Erases all the elements. - * - * Note that this function only erases - * the elements, and that if the elements themselves are - * pointers, the pointed-to memory is not touched in any way. - * Managing the pointer is the user's responsibility. - */ - void - clear() noexcept - { this->_M_erase_after(&this->_M_impl._M_head, nullptr); } - - // 23.3.4.6 forward_list operations: - - /** - * @brief Insert contents of another %forward_list. - * @param __pos Iterator referencing the element to insert after. - * @param __list Source list. - * - * The elements of @a list are inserted in constant time after - * the element referenced by @a pos. @a list becomes an empty - * list. - * - * Requires this != @a x. - */ - void - splice_after(const_iterator __pos, forward_list&& __list) noexcept - { - if (!__list.empty()) - _M_splice_after(__pos, __list.before_begin(), __list.end()); - } - - void - splice_after(const_iterator __pos, forward_list& __list) noexcept - { splice_after(__pos, std::move(__list)); } - - /** - * @brief Insert element from another %forward_list. - * @param __pos Iterator referencing the element to insert after. - * @param __list Source list. - * @param __i Iterator referencing the element before the element - * to move. - * - * Removes the element in list @a list referenced by @a i and - * inserts it into the current list after @a pos. - */ - void - splice_after(const_iterator __pos, forward_list&& __list, - const_iterator __i) noexcept; - - void - splice_after(const_iterator __pos, forward_list& __list, - const_iterator __i) noexcept - { splice_after(__pos, std::move(__list), __i); } - - /** - * @brief Insert range from another %forward_list. - * @param __pos Iterator referencing the element to insert after. - * @param __list Source list. - * @param __before Iterator referencing before the start of range - * in list. - * @param __last Iterator referencing the end of range in list. - * - * Removes elements in the range (__before,__last) and inserts them - * after @a __pos in constant time. - * - * Undefined if @a __pos is in (__before,__last). - * @{ - */ - void - splice_after(const_iterator __pos, forward_list&&, - const_iterator __before, const_iterator __last) noexcept - { _M_splice_after(__pos, __before, __last); } - - void - splice_after(const_iterator __pos, forward_list&, - const_iterator __before, const_iterator __last) noexcept - { _M_splice_after(__pos, __before, __last); } - // @} - - private: -#if __cplusplus > 201703L -# define __cpp_lib_list_remove_return_type 201806L - using __remove_return_type = size_type; -# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG \ - __attribute__((__abi_tag__("__cxx20"))) -#else - using __remove_return_type = void; -# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG -#endif - public: - - /** - * @brief Remove all elements equal to value. - * @param __val The value to remove. - * - * Removes every element in the list equal to @a __val. - * Remaining elements stay in list order. Note that this - * function only erases the elements, and that if the elements - * themselves are pointers, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's - * responsibility. - */ - _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG - __remove_return_type - remove(const _Tp& __val); - - /** - * @brief Remove all elements satisfying a predicate. - * @param __pred Unary predicate function or object. - * - * Removes every element in the list for which the predicate - * returns true. Remaining elements stay in list order. Note - * that this function only erases the elements, and that if the - * elements themselves are pointers, the pointed-to memory is - * not touched in any way. Managing the pointer is the user's - * responsibility. - */ - template - __remove_return_type - remove_if(_Pred __pred); - - /** - * @brief Remove consecutive duplicate elements. - * - * For each consecutive set of elements with the same value, - * remove all but the first one. Remaining elements stay in - * list order. Note that this function only erases the - * elements, and that if the elements themselves are pointers, - * the pointed-to memory is not touched in any way. Managing - * the pointer is the user's responsibility. - */ - _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG - __remove_return_type - unique() - { return unique(std::equal_to<_Tp>()); } - -#undef _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG - - /** - * @brief Remove consecutive elements satisfying a predicate. - * @param __binary_pred Binary predicate function or object. - * - * For each consecutive set of elements [first,last) that - * satisfy predicate(first,i) where i is an iterator in - * [first,last), remove all but the first one. Remaining - * elements stay in list order. Note that this function only - * erases the elements, and that if the elements themselves are - * pointers, the pointed-to memory is not touched in any way. - * Managing the pointer is the user's responsibility. - */ - template - __remove_return_type - unique(_BinPred __binary_pred); - - /** - * @brief Merge sorted lists. - * @param __list Sorted list to merge. - * - * Assumes that both @a list and this list are sorted according to - * operator<(). Merges elements of @a __list into this list in - * sorted order, leaving @a __list empty when complete. Elements in - * this list precede elements in @a __list that are equal. - */ - void - merge(forward_list&& __list) - { merge(std::move(__list), std::less<_Tp>()); } - - void - merge(forward_list& __list) - { merge(std::move(__list)); } - - /** - * @brief Merge sorted lists according to comparison function. - * @param __list Sorted list to merge. - * @param __comp Comparison function defining sort order. - * - * Assumes that both @a __list and this list are sorted according to - * comp. Merges elements of @a __list into this list - * in sorted order, leaving @a __list empty when complete. Elements - * in this list precede elements in @a __list that are equivalent - * according to comp(). - */ - template - void - merge(forward_list&& __list, _Comp __comp); - - template - void - merge(forward_list& __list, _Comp __comp) - { merge(std::move(__list), __comp); } - - /** - * @brief Sort the elements of the list. - * - * Sorts the elements of this list in NlogN time. Equivalent - * elements remain in list order. - */ - void - sort() - { sort(std::less<_Tp>()); } - - /** - * @brief Sort the forward_list using a comparison function. - * - * Sorts the elements of this list in NlogN time. Equivalent - * elements remain in list order. - */ - template - void - sort(_Comp __comp); - - /** - * @brief Reverse the elements in list. - * - * Reverse the order of elements in the list in linear time. - */ - void - reverse() noexcept - { this->_M_impl._M_head._M_reverse_after(); } - - private: - // Called by the range constructor to implement [23.3.4.2]/9 - template - void - _M_range_initialize(_InputIterator __first, _InputIterator __last); - - // Called by forward_list(n,v,a), and the range constructor when it - // turns out to be the same thing. - void - _M_fill_initialize(size_type __n, const value_type& __value); - - // Called by splice_after and insert_after. - iterator - _M_splice_after(const_iterator __pos, const_iterator __before, - const_iterator __last); - - // Called by forward_list(n). - void - _M_default_initialize(size_type __n); - - // Called by resize(sz). - void - _M_default_insert_after(const_iterator __pos, size_type __n); - - // Called by operator=(forward_list&&) - void - _M_move_assign(forward_list&& __list, true_type) noexcept - { - clear(); - this->_M_impl._M_head._M_next = __list._M_impl._M_head._M_next; - __list._M_impl._M_head._M_next = nullptr; - std::__alloc_on_move(this->_M_get_Node_allocator(), - __list._M_get_Node_allocator()); - } - - // Called by operator=(forward_list&&) - void - _M_move_assign(forward_list&& __list, false_type) - { - if (__list._M_get_Node_allocator() == this->_M_get_Node_allocator()) - _M_move_assign(std::move(__list), true_type()); - else - // The rvalue's allocator cannot be moved, or is not equal, - // so we need to individually move each element. - this->assign(std::make_move_iterator(__list.begin()), - std::make_move_iterator(__list.end())); - } - - // Called by assign(_InputIterator, _InputIterator) if _Tp is - // CopyAssignable. - template - void - _M_assign(_InputIterator __first, _InputIterator __last, true_type) - { - auto __prev = before_begin(); - auto __curr = begin(); - auto __end = end(); - while (__curr != __end && __first != __last) - { - *__curr = *__first; - ++__prev; - ++__curr; - ++__first; - } - if (__first != __last) - insert_after(__prev, __first, __last); - else if (__curr != __end) - erase_after(__prev, __end); - } - - // Called by assign(_InputIterator, _InputIterator) if _Tp is not - // CopyAssignable. - template - void - _M_assign(_InputIterator __first, _InputIterator __last, false_type) - { - clear(); - insert_after(cbefore_begin(), __first, __last); - } - - // Called by assign(size_type, const _Tp&) if Tp is CopyAssignable - void - _M_assign_n(size_type __n, const _Tp& __val, true_type) - { - auto __prev = before_begin(); - auto __curr = begin(); - auto __end = end(); - while (__curr != __end && __n > 0) - { - *__curr = __val; - ++__prev; - ++__curr; - --__n; - } - if (__n > 0) - insert_after(__prev, __n, __val); - else if (__curr != __end) - erase_after(__prev, __end); - } - - // Called by assign(size_type, const _Tp&) if Tp is non-CopyAssignable - void - _M_assign_n(size_type __n, const _Tp& __val, false_type) - { - clear(); - insert_after(cbefore_begin(), __n, __val); - } - }; - -#if __cpp_deduction_guides >= 201606 - template::value_type, - typename _Allocator = allocator<_ValT>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireAllocator<_Allocator>> - forward_list(_InputIterator, _InputIterator, _Allocator = _Allocator()) - -> forward_list<_ValT, _Allocator>; -#endif - - /** - * @brief Forward list equality comparison. - * @param __lx A %forward_list - * @param __ly A %forward_list of the same type as @a __lx. - * @return True iff the elements of the forward lists are equal. - * - * This is an equivalence relation. It is linear in the number of - * elements of the forward lists. Deques are considered equivalent - * if corresponding elements compare equal. - */ - template - bool - operator==(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly); - -#if __cpp_lib_three_way_comparison - /** - * @brief Forward list ordering relation. - * @param __x A `forward_list`. - * @param __y A `forward_list` of the same type as `__x`. - * @return A value indicating whether `__x` is less than, equal to, - * greater than, or incomparable with `__y`. - * - * See `std::lexicographical_compare_three_way()` for how the determination - * is made. This operator is used to synthesize relational operators like - * `<` and `>=` etc. - */ - template - inline __detail::__synth3way_t<_Tp> - operator<=>(const forward_list<_Tp, _Alloc>& __x, - const forward_list<_Tp, _Alloc>& __y) - { - return std::lexicographical_compare_three_way(__x.begin(), __x.end(), - __y.begin(), __y.end(), - __detail::__synth3way); - } -#else - /** - * @brief Forward list ordering relation. - * @param __lx A %forward_list. - * @param __ly A %forward_list of the same type as @a __lx. - * @return True iff @a __lx is lexicographically less than @a __ly. - * - * This is a total ordering relation. It is linear in the number of - * elements of the forward lists. The elements must be comparable - * with @c <. - * - * See std::lexicographical_compare() for how the determination is made. - */ - template - inline bool - operator<(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) - { return std::lexicographical_compare(__lx.cbegin(), __lx.cend(), - __ly.cbegin(), __ly.cend()); } - - /// Based on operator== - template - inline bool - operator!=(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) - { return !(__lx == __ly); } - - /// Based on operator< - template - inline bool - operator>(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) - { return (__ly < __lx); } - - /// Based on operator< - template - inline bool - operator>=(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) - { return !(__lx < __ly); } - - /// Based on operator< - template - inline bool - operator<=(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) - { return !(__ly < __lx); } -#endif // three-way comparison - - /// See std::forward_list::swap(). - template - inline void - swap(forward_list<_Tp, _Alloc>& __lx, - forward_list<_Tp, _Alloc>& __ly) - noexcept(noexcept(__lx.swap(__ly))) - { __lx.swap(__ly); } - -_GLIBCXX_END_NAMESPACE_CONTAINER -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // _FORWARD_LIST_H diff --git a/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc b/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc deleted file mode 100644 index c42bdc0fd..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc +++ /dev/null @@ -1,517 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/forward_list.tcc - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{forward_list} - */ - -#ifndef _FORWARD_LIST_TCC -#define _FORWARD_LIST_TCC 1 - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - _Fwd_list_base<_Tp, _Alloc>:: - _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a) - : _M_impl(std::move(__a)) - { - if (__lst._M_get_Node_allocator() == _M_get_Node_allocator()) - this->_M_impl._M_head = std::move(__lst._M_impl._M_head); - } - - template - template - _Fwd_list_node_base* - _Fwd_list_base<_Tp, _Alloc>:: - _M_insert_after(const_iterator __pos, _Args&&... __args) - { - _Fwd_list_node_base* __to - = const_cast<_Fwd_list_node_base*>(__pos._M_node); - _Node* __thing = _M_create_node(std::forward<_Args>(__args)...); - __thing->_M_next = __to->_M_next; - __to->_M_next = __thing; - return __to->_M_next; - } - - template - _Fwd_list_node_base* - _Fwd_list_base<_Tp, _Alloc>:: - _M_erase_after(_Fwd_list_node_base* __pos) - { - _Node* __curr = static_cast<_Node*>(__pos->_M_next); - __pos->_M_next = __curr->_M_next; - _Node_alloc_traits::destroy(_M_get_Node_allocator(), - __curr->_M_valptr()); - __curr->~_Node(); - _M_put_node(__curr); - return __pos->_M_next; - } - - template - _Fwd_list_node_base* - _Fwd_list_base<_Tp, _Alloc>:: - _M_erase_after(_Fwd_list_node_base* __pos, - _Fwd_list_node_base* __last) - { - _Node* __curr = static_cast<_Node*>(__pos->_M_next); - while (__curr != __last) - { - _Node* __temp = __curr; - __curr = static_cast<_Node*>(__curr->_M_next); - _Node_alloc_traits::destroy(_M_get_Node_allocator(), - __temp->_M_valptr()); - __temp->~_Node(); - _M_put_node(__temp); - } - __pos->_M_next = __last; - return __last; - } - - // Called by the range constructor to implement [23.3.4.2]/9 - template - template - void - forward_list<_Tp, _Alloc>:: - _M_range_initialize(_InputIterator __first, _InputIterator __last) - { - _Node_base* __to = &this->_M_impl._M_head; - for (; __first != __last; ++__first) - { - __to->_M_next = this->_M_create_node(*__first); - __to = __to->_M_next; - } - } - - // Called by forward_list(n,v,a). - template - void - forward_list<_Tp, _Alloc>:: - _M_fill_initialize(size_type __n, const value_type& __value) - { - _Node_base* __to = &this->_M_impl._M_head; - for (; __n; --__n) - { - __to->_M_next = this->_M_create_node(__value); - __to = __to->_M_next; - } - } - - template - void - forward_list<_Tp, _Alloc>:: - _M_default_initialize(size_type __n) - { - _Node_base* __to = &this->_M_impl._M_head; - for (; __n; --__n) - { - __to->_M_next = this->_M_create_node(); - __to = __to->_M_next; - } - } - - template - forward_list<_Tp, _Alloc>& - forward_list<_Tp, _Alloc>:: - operator=(const forward_list& __list) - { - if (std::__addressof(__list) != this) - { - if (_Node_alloc_traits::_S_propagate_on_copy_assign()) - { - auto& __this_alloc = this->_M_get_Node_allocator(); - auto& __that_alloc = __list._M_get_Node_allocator(); - if (!_Node_alloc_traits::_S_always_equal() - && __this_alloc != __that_alloc) - { - // replacement allocator cannot free existing storage - clear(); - } - std::__alloc_on_copy(__this_alloc, __that_alloc); - } - assign(__list.cbegin(), __list.cend()); - } - return *this; - } - - template - void - forward_list<_Tp, _Alloc>:: - _M_default_insert_after(const_iterator __pos, size_type __n) - { - const_iterator __saved_pos = __pos; - __try - { - for (; __n; --__n) - __pos = emplace_after(__pos); - } - __catch(...) - { - erase_after(__saved_pos, ++__pos); - __throw_exception_again; - } - } - - template - void - forward_list<_Tp, _Alloc>:: - resize(size_type __sz) - { - iterator __k = before_begin(); - - size_type __len = 0; - while (__k._M_next() != end() && __len < __sz) - { - ++__k; - ++__len; - } - if (__len == __sz) - erase_after(__k, end()); - else - _M_default_insert_after(__k, __sz - __len); - } - - template - void - forward_list<_Tp, _Alloc>:: - resize(size_type __sz, const value_type& __val) - { - iterator __k = before_begin(); - - size_type __len = 0; - while (__k._M_next() != end() && __len < __sz) - { - ++__k; - ++__len; - } - if (__len == __sz) - erase_after(__k, end()); - else - insert_after(__k, __sz - __len, __val); - } - - template - typename forward_list<_Tp, _Alloc>::iterator - forward_list<_Tp, _Alloc>:: - _M_splice_after(const_iterator __pos, - const_iterator __before, const_iterator __last) - { - _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node); - _Node_base* __b = const_cast<_Node_base*>(__before._M_node); - _Node_base* __end = __b; - - while (__end && __end->_M_next != __last._M_node) - __end = __end->_M_next; - - if (__b != __end) - return iterator(__tmp->_M_transfer_after(__b, __end)); - else - return iterator(__tmp); - } - - template - void - forward_list<_Tp, _Alloc>:: - splice_after(const_iterator __pos, forward_list&&, - const_iterator __i) noexcept - { - const_iterator __j = __i; - ++__j; - - if (__pos == __i || __pos == __j) - return; - - _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node); - __tmp->_M_transfer_after(const_cast<_Node_base*>(__i._M_node), - const_cast<_Node_base*>(__j._M_node)); - } - - template - typename forward_list<_Tp, _Alloc>::iterator - forward_list<_Tp, _Alloc>:: - insert_after(const_iterator __pos, size_type __n, const _Tp& __val) - { - if (__n) - { - forward_list __tmp(__n, __val, get_allocator()); - return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end()); - } - else - return iterator(const_cast<_Node_base*>(__pos._M_node)); - } - - template - template - typename forward_list<_Tp, _Alloc>::iterator - forward_list<_Tp, _Alloc>:: - insert_after(const_iterator __pos, - _InputIterator __first, _InputIterator __last) - { - forward_list __tmp(__first, __last, get_allocator()); - if (!__tmp.empty()) - return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end()); - else - return iterator(const_cast<_Node_base*>(__pos._M_node)); - } - -#if __cplusplus > 201703L -# define _GLIBCXX20_ONLY(__expr) __expr -#else -# define _GLIBCXX20_ONLY(__expr) -#endif - - template - auto - forward_list<_Tp, _Alloc>:: - remove(const _Tp& __val) -> __remove_return_type - { - size_type __removed __attribute__((__unused__)) = 0; - _Node_base* __curr = &this->_M_impl._M_head; - _Node_base* __extra = nullptr; - - while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) - { - if (*__tmp->_M_valptr() == __val) - { - if (__tmp->_M_valptr() != std::__addressof(__val)) - { - this->_M_erase_after(__curr); - _GLIBCXX20_ONLY( __removed++ ); - continue; - } - else - __extra = __curr; - } - __curr = __curr->_M_next; - } - - if (__extra) - { - this->_M_erase_after(__extra); - _GLIBCXX20_ONLY( __removed++ ); - } - return _GLIBCXX20_ONLY( __removed ); - } - - template - template - auto - forward_list<_Tp, _Alloc>:: - remove_if(_Pred __pred) -> __remove_return_type - { - size_type __removed __attribute__((__unused__)) = 0; - _Node_base* __curr = &this->_M_impl._M_head; - while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) - { - if (__pred(*__tmp->_M_valptr())) - { - this->_M_erase_after(__curr); - _GLIBCXX20_ONLY( __removed++ ); - } - else - __curr = __curr->_M_next; - } - return _GLIBCXX20_ONLY( __removed ); - } - - template - template - auto - forward_list<_Tp, _Alloc>:: - unique(_BinPred __binary_pred) -> __remove_return_type - { - iterator __first = begin(); - iterator __last = end(); - if (__first == __last) - return _GLIBCXX20_ONLY(0); - size_type __removed __attribute__((__unused__)) = 0; - iterator __next = __first; - while (++__next != __last) - { - if (__binary_pred(*__first, *__next)) - { - erase_after(__first); - _GLIBCXX20_ONLY( __removed++ ); - } - else - __first = __next; - __next = __first; - } - return _GLIBCXX20_ONLY( __removed ); - } - -#undef _GLIBCXX20_ONLY - - template - template - void - forward_list<_Tp, _Alloc>:: - merge(forward_list&& __list, _Comp __comp) - { - _Node_base* __node = &this->_M_impl._M_head; - while (__node->_M_next && __list._M_impl._M_head._M_next) - { - if (__comp(*static_cast<_Node*> - (__list._M_impl._M_head._M_next)->_M_valptr(), - *static_cast<_Node*> - (__node->_M_next)->_M_valptr())) - __node->_M_transfer_after(&__list._M_impl._M_head, - __list._M_impl._M_head._M_next); - __node = __node->_M_next; - } - - if (__list._M_impl._M_head._M_next) - *__node = std::move(__list._M_impl._M_head); - } - - template - bool - operator==(const forward_list<_Tp, _Alloc>& __lx, - const forward_list<_Tp, _Alloc>& __ly) - { - // We don't have size() so we need to walk through both lists - // making sure both iterators are valid. - auto __ix = __lx.cbegin(); - auto __iy = __ly.cbegin(); - while (__ix != __lx.cend() && __iy != __ly.cend()) - { - if (!(*__ix == *__iy)) - return false; - ++__ix; - ++__iy; - } - if (__ix == __lx.cend() && __iy == __ly.cend()) - return true; - else - return false; - } - - template - template - void - forward_list<_Tp, _Alloc>:: - sort(_Comp __comp) - { - // If `next' is nullptr, return immediately. - _Node* __list = static_cast<_Node*>(this->_M_impl._M_head._M_next); - if (!__list) - return; - - unsigned long __insize = 1; - - while (1) - { - _Node* __p = __list; - __list = nullptr; - _Node* __tail = nullptr; - - // Count number of merges we do in this pass. - unsigned long __nmerges = 0; - - while (__p) - { - ++__nmerges; - // There exists a merge to be done. - // Step `insize' places along from p. - _Node* __q = __p; - unsigned long __psize = 0; - for (unsigned long __i = 0; __i < __insize; ++__i) - { - ++__psize; - __q = static_cast<_Node*>(__q->_M_next); - if (!__q) - break; - } - - // If q hasn't fallen off end, we have two lists to merge. - unsigned long __qsize = __insize; - - // Now we have two lists; merge them. - while (__psize > 0 || (__qsize > 0 && __q)) - { - // Decide whether next node of merge comes from p or q. - _Node* __e; - if (__psize == 0) - { - // p is empty; e must come from q. - __e = __q; - __q = static_cast<_Node*>(__q->_M_next); - --__qsize; - } - else if (__qsize == 0 || !__q) - { - // q is empty; e must come from p. - __e = __p; - __p = static_cast<_Node*>(__p->_M_next); - --__psize; - } - else if (!__comp(*__q->_M_valptr(), *__p->_M_valptr())) - { - // First node of q is not lower; e must come from p. - __e = __p; - __p = static_cast<_Node*>(__p->_M_next); - --__psize; - } - else - { - // First node of q is lower; e must come from q. - __e = __q; - __q = static_cast<_Node*>(__q->_M_next); - --__qsize; - } - - // Add the next node to the merged list. - if (__tail) - __tail->_M_next = __e; - else - __list = __e; - __tail = __e; - } - - // Now p has stepped `insize' places along, and q has too. - __p = __q; - } - __tail->_M_next = nullptr; - - // If we have done only one merge, we're finished. - // Allow for nmerges == 0, the empty list case. - if (__nmerges <= 1) - { - this->_M_impl._M_head._M_next = __list; - return; - } - - // Otherwise repeat, merging lists twice the size. - __insize *= 2; - } - } - -_GLIBCXX_END_NAMESPACE_CONTAINER -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _FORWARD_LIST_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bits/functexcept.h b/resources/sources/avr-libstdcpp/include/bits/functexcept.h deleted file mode 100644 index b7494f367..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/functexcept.h +++ /dev/null @@ -1,114 +0,0 @@ -// Function-Based Exception Support -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/functexcept.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{exception} - * - * This header provides support for -fno-exceptions. - */ - -// -// ISO C++ 14882: 19.1 Exception classes -// - -#ifndef _FUNCTEXCEPT_H -#define _FUNCTEXCEPT_H 1 - -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Helper for exception objects in - void - __throw_bad_exception(void) __attribute__((__noreturn__)); - - // Helper for exception objects in - void - __throw_bad_alloc(void) __attribute__((__noreturn__)); - - // Helper for exception objects in - void - __throw_bad_cast(void) __attribute__((__noreturn__)); - - void - __throw_bad_typeid(void) __attribute__((__noreturn__)); - - // Helpers for exception objects in - void - __throw_logic_error(const char* __s = "") __attribute__((__noreturn__)); - - void - __throw_domain_error(const char* __s = "") __attribute__((__noreturn__)); - - void - __throw_invalid_argument(const char* __s = "") __attribute__((__noreturn__)); - - void - __throw_length_error(const char* __s = "") __attribute__((__noreturn__)); - - void - __throw_out_of_range(const char* __s = "") __attribute__((__noreturn__)); - - inline void __attribute__((__noreturn__)) __attribute__((always_inline)) - __throw_out_of_range_fmt(const char*, ...) - { __throw_out_of_range(); } - - void - __throw_runtime_error(const char* __s = "") __attribute__((__noreturn__)); - - void - __throw_range_error(const char* __s = "") __attribute__((__noreturn__)); - - void - __throw_overflow_error(const char* __s = "") __attribute__((__noreturn__)); - - void - __throw_underflow_error(const char* __s = "") __attribute__((__noreturn__)); - - // Helpers for exception objects in - void - __throw_system_error(int) __attribute__((__noreturn__)); - - // Helpers for exception objects in - void - __throw_bad_function_call() __attribute__((__noreturn__)); - - void - __throw_bad_optional_access() __attribute__((__noreturn__)); - - void - __throw_bad_variant_access(const char* __s = "") __attribute__((__noreturn__)); - - void - __throw_bad_any_cast() __attribute__((__noreturn__)); - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/functional_hash.h b/resources/sources/avr-libstdcpp/include/bits/functional_hash.h deleted file mode 100644 index e50b047ff..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/functional_hash.h +++ /dev/null @@ -1,280 +0,0 @@ -// functional_hash.h header -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/functional_hash.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _FUNCTIONAL_HASH_H -#define _FUNCTIONAL_HASH_H 1 - -#pragma GCC system_header - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** @defgroup hashes Hashes - * @ingroup functors - * - * Hashing functors taking a variable type and returning a @c std::size_t. - * - * @{ - */ - - template - struct __hash_base - { - typedef _Result result_type _GLIBCXX17_DEPRECATED; - typedef _Arg argument_type _GLIBCXX17_DEPRECATED; - }; - - /// Primary class template hash. - template - struct hash; - - template - struct __poison_hash - { - static constexpr bool __enable_hash_call = false; - private: - // Private rather than deleted to be non-trivially-copyable. - __poison_hash(__poison_hash&&); - ~__poison_hash(); - }; - - template - struct __poison_hash<_Tp, __void_t()(declval<_Tp>()))>> - { - static constexpr bool __enable_hash_call = true; - }; - - // Helper struct for SFINAE-poisoning non-enum types. - template::value> - struct __hash_enum - { - private: - // Private rather than deleted to be non-trivially-copyable. - __hash_enum(__hash_enum&&); - ~__hash_enum(); - }; - - // Helper struct for hash with enum types. - template - struct __hash_enum<_Tp, true> : public __hash_base - { - size_t - operator()(_Tp __val) const noexcept - { - using __type = typename underlying_type<_Tp>::type; - return hash<__type>{}(static_cast<__type>(__val)); - } - }; - - /// Primary class template hash, usable for enum types only. - // Use with non-enum types still SFINAES. - template - struct hash : __hash_enum<_Tp> - { }; - - /// Partial specializations for pointer types. - template - struct hash<_Tp*> : public __hash_base - { - size_t - operator()(_Tp* __p) const noexcept - { return reinterpret_cast(__p); } - }; - - // Explicit specializations for integer types. -#define _Cxx_hashtable_define_trivial_hash(_Tp) \ - template<> \ - struct hash<_Tp> : public __hash_base \ - { \ - size_t \ - operator()(_Tp __val) const noexcept \ - { return static_cast(__val); } \ - }; - - /// Explicit specialization for bool. - _Cxx_hashtable_define_trivial_hash(bool) - - /// Explicit specialization for char. - _Cxx_hashtable_define_trivial_hash(char) - - /// Explicit specialization for signed char. - _Cxx_hashtable_define_trivial_hash(signed char) - - /// Explicit specialization for unsigned char. - _Cxx_hashtable_define_trivial_hash(unsigned char) - - /// Explicit specialization for wchar_t. - _Cxx_hashtable_define_trivial_hash(wchar_t) - -#ifdef _GLIBCXX_USE_CHAR8_T - /// Explicit specialization for char8_t. - _Cxx_hashtable_define_trivial_hash(char8_t) -#endif - - /// Explicit specialization for char16_t. - _Cxx_hashtable_define_trivial_hash(char16_t) - - /// Explicit specialization for char32_t. - _Cxx_hashtable_define_trivial_hash(char32_t) - - /// Explicit specialization for short. - _Cxx_hashtable_define_trivial_hash(short) - - /// Explicit specialization for int. - _Cxx_hashtable_define_trivial_hash(int) - - /// Explicit specialization for long. - _Cxx_hashtable_define_trivial_hash(long) - - /// Explicit specialization for long long. - _Cxx_hashtable_define_trivial_hash(long long) - - /// Explicit specialization for unsigned short. - _Cxx_hashtable_define_trivial_hash(unsigned short) - - /// Explicit specialization for unsigned int. - _Cxx_hashtable_define_trivial_hash(unsigned int) - - /// Explicit specialization for unsigned long. - _Cxx_hashtable_define_trivial_hash(unsigned long) - - /// Explicit specialization for unsigned long long. - _Cxx_hashtable_define_trivial_hash(unsigned long long) - -#ifdef __GLIBCXX_TYPE_INT_N_0 - _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0) - _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0 unsigned) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_1 - _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1) - _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1 unsigned) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_2 - _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2) - _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2 unsigned) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_3 - _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3) - _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3 unsigned) -#endif - -#undef _Cxx_hashtable_define_trivial_hash - - struct _Hash_impl - { - static size_t - hash(const void* __ptr, size_t __clength, - size_t __seed = static_cast(0xc70f6907UL)) - { return _Hash_bytes(__ptr, __clength, __seed); } - - template - static size_t - hash(const _Tp& __val) - { return hash(&__val, sizeof(__val)); } - - template - static size_t - __hash_combine(const _Tp& __val, size_t __hash) - { return hash(&__val, sizeof(__val), __hash); } - }; - - // A hash function similar to FNV-1a (see PR59406 for how it differs). - struct _Fnv_hash_impl - { - static size_t - hash(const void* __ptr, size_t __clength, - size_t __seed = static_cast(2166136261UL)) - { return _Fnv_hash_bytes(__ptr, __clength, __seed); } - - template - static size_t - hash(const _Tp& __val) - { return hash(&__val, sizeof(__val)); } - - template - static size_t - __hash_combine(const _Tp& __val, size_t __hash) - { return hash(&__val, sizeof(__val), __hash); } - }; - - /// Specialization for float. - template<> - struct hash : public __hash_base - { - size_t - operator()(float __val) const noexcept - { - // 0 and -0 both hash to zero. - return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0; - } - }; - - /// Specialization for double. - template<> - struct hash : public __hash_base - { - size_t - operator()(double __val) const noexcept - { - // 0 and -0 both hash to zero. - return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0; - } - }; - -#if __cplusplus >= 201703L - template<> - struct hash : public __hash_base - { - size_t - operator()(nullptr_t) const noexcept - { return 0; } - }; -#endif - - // @} group hashes - - // Hint about performance of hash functor. If not fast the hash-based - // containers will cache the hash code. - // Default behavior is to consider that hashers are fast unless specified - // otherwise. - template - struct __is_fast_hash : public std::true_type - { }; - - template<> - struct __is_fast_hash> : public std::false_type - { }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // _FUNCTIONAL_HASH_H diff --git a/resources/sources/avr-libstdcpp/include/bits/gslice.h b/resources/sources/avr-libstdcpp/include/bits/gslice.h deleted file mode 100644 index b252c3c1f..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/gslice.h +++ /dev/null @@ -1,185 +0,0 @@ -// The template and inlines for the -*- C++ -*- gslice class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/gslice.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _GSLICE_H -#define _GSLICE_H 1 - -#pragma GCC system_header - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup numeric_arrays - * @{ - */ - - /** - * @brief Class defining multi-dimensional subset of an array. - * - * The slice class represents a multi-dimensional subset of an array, - * specified by three parameter sets: start offset, size array, and stride - * array. The start offset is the index of the first element of the array - * that is part of the subset. The size and stride array describe each - * dimension of the slice. Size is the number of elements in that - * dimension, and stride is the distance in the array between successive - * elements in that dimension. Each dimension's size and stride is taken - * to begin at an array element described by the previous dimension. The - * size array and stride array must be the same size. - * - * For example, if you have offset==3, stride[0]==11, size[1]==3, - * stride[1]==3, then slice[0,0]==array[3], slice[0,1]==array[6], - * slice[0,2]==array[9], slice[1,0]==array[14], slice[1,1]==array[17], - * slice[1,2]==array[20]. - */ - class gslice - { - public: - /// Construct an empty slice. - gslice(); - - /** - * @brief Construct a slice. - * - * Constructs a slice with as many dimensions as the length of the @a l - * and @a s arrays. - * - * @param __o Offset in array of first element. - * @param __l Array of dimension lengths. - * @param __s Array of dimension strides between array elements. - */ - gslice(size_t __o, const valarray& __l, - const valarray& __s); - - // XXX: the IS says the copy-ctor and copy-assignment operators are - // synthesized by the compiler but they are just unsuitable - // for a ref-counted semantic - /// Copy constructor. - gslice(const gslice&); - - /// Destructor. - ~gslice(); - - // XXX: See the note above. - /// Assignment operator. - gslice& operator=(const gslice&); - - /// Return array offset of first slice element. - size_t start() const; - - /// Return array of sizes of slice dimensions. - valarray size() const; - - /// Return array of array strides for each dimension. - valarray stride() const; - - private: - struct _Indexer - { - size_t _M_count; - size_t _M_start; - valarray _M_size; - valarray _M_stride; - valarray _M_index; // Linear array of referenced indices - - _Indexer() - : _M_count(1), _M_start(0), _M_size(), _M_stride(), _M_index() {} - - _Indexer(size_t, const valarray&, - const valarray&); - - void - _M_increment_use() - { ++_M_count; } - - size_t - _M_decrement_use() - { return --_M_count; } - }; - - _Indexer* _M_index; - - template friend class valarray; - }; - - inline size_t - gslice::start() const - { return _M_index ? _M_index->_M_start : 0; } - - inline valarray - gslice::size() const - { return _M_index ? _M_index->_M_size : valarray(); } - - inline valarray - gslice::stride() const - { return _M_index ? _M_index->_M_stride : valarray(); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 543. valarray slice default constructor - inline - gslice::gslice() - : _M_index(new gslice::_Indexer()) {} - - inline - gslice::gslice(size_t __o, const valarray& __l, - const valarray& __s) - : _M_index(new gslice::_Indexer(__o, __l, __s)) {} - - inline - gslice::gslice(const gslice& __g) - : _M_index(__g._M_index) - { if (_M_index) _M_index->_M_increment_use(); } - - inline - gslice::~gslice() - { - if (_M_index && _M_index->_M_decrement_use() == 0) - delete _M_index; - } - - inline gslice& - gslice::operator=(const gslice& __g) - { - if (__g._M_index) - __g._M_index->_M_increment_use(); - if (_M_index && _M_index->_M_decrement_use() == 0) - delete _M_index; - _M_index = __g._M_index; - return *this; - } - - // @} group numeric_arrays - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _GSLICE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/gslice_array.h b/resources/sources/avr-libstdcpp/include/bits/gslice_array.h deleted file mode 100644 index 89fdda537..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/gslice_array.h +++ /dev/null @@ -1,223 +0,0 @@ -// The template and inlines for the -*- C++ -*- gslice_array class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/gslice_array.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _GSLICE_ARRAY_H -#define _GSLICE_ARRAY_H 1 - -#pragma GCC system_header - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup numeric_arrays - * @{ - */ - - /** - * @brief Reference to multi-dimensional subset of an array. - * - * A gslice_array is a reference to the actual elements of an array - * specified by a gslice. The way to get a gslice_array is to call - * operator[](gslice) on a valarray. The returned gslice_array then - * permits carrying operations out on the referenced subset of elements in - * the original valarray. For example, operator+=(valarray) will add - * values to the subset of elements in the underlying valarray this - * gslice_array refers to. - * - * @param Tp Element type. - */ - template - class gslice_array - { - public: - typedef _Tp value_type; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 253. valarray helper functions are almost entirely useless - - /// Copy constructor. Both slices refer to the same underlying array. - gslice_array(const gslice_array&); - - /// Assignment operator. Assigns slice elements to corresponding - /// elements of @a a. - gslice_array& operator=(const gslice_array&); - - /// Assign slice elements to corresponding elements of @a v. - void operator=(const valarray<_Tp>&) const; - /// Multiply slice elements by corresponding elements of @a v. - void operator*=(const valarray<_Tp>&) const; - /// Divide slice elements by corresponding elements of @a v. - void operator/=(const valarray<_Tp>&) const; - /// Modulo slice elements by corresponding elements of @a v. - void operator%=(const valarray<_Tp>&) const; - /// Add corresponding elements of @a v to slice elements. - void operator+=(const valarray<_Tp>&) const; - /// Subtract corresponding elements of @a v from slice elements. - void operator-=(const valarray<_Tp>&) const; - /// Logical xor slice elements with corresponding elements of @a v. - void operator^=(const valarray<_Tp>&) const; - /// Logical and slice elements with corresponding elements of @a v. - void operator&=(const valarray<_Tp>&) const; - /// Logical or slice elements with corresponding elements of @a v. - void operator|=(const valarray<_Tp>&) const; - /// Left shift slice elements by corresponding elements of @a v. - void operator<<=(const valarray<_Tp>&) const; - /// Right shift slice elements by corresponding elements of @a v. - void operator>>=(const valarray<_Tp>&) const; - /// Assign all slice elements to @a t. - void operator=(const _Tp&) const; - - template - void operator=(const _Expr<_Dom, _Tp>&) const; - template - void operator*=(const _Expr<_Dom, _Tp>&) const; - template - void operator/=(const _Expr<_Dom, _Tp>&) const; - template - void operator%=(const _Expr<_Dom, _Tp>&) const; - template - void operator+=(const _Expr<_Dom, _Tp>&) const; - template - void operator-=(const _Expr<_Dom, _Tp>&) const; - template - void operator^=(const _Expr<_Dom, _Tp>&) const; - template - void operator&=(const _Expr<_Dom, _Tp>&) const; - template - void operator|=(const _Expr<_Dom, _Tp>&) const; - template - void operator<<=(const _Expr<_Dom, _Tp>&) const; - template - void operator>>=(const _Expr<_Dom, _Tp>&) const; - - private: - _Array<_Tp> _M_array; - const valarray& _M_index; - - friend class valarray<_Tp>; - - gslice_array(_Array<_Tp>, const valarray&); - -#if __cplusplus < 201103L - // not implemented - gslice_array(); -#else - public: - gslice_array() = delete; -#endif - }; - - template - inline - gslice_array<_Tp>::gslice_array(_Array<_Tp> __a, - const valarray& __i) - : _M_array(__a), _M_index(__i) {} - - template - inline - gslice_array<_Tp>::gslice_array(const gslice_array<_Tp>& __a) - : _M_array(__a._M_array), _M_index(__a._M_index) {} - - template - inline gslice_array<_Tp>& - gslice_array<_Tp>::operator=(const gslice_array<_Tp>& __a) - { - std::__valarray_copy(_Array<_Tp>(__a._M_array), - _Array(__a._M_index), _M_index.size(), - _M_array, _Array(_M_index)); - return *this; - } - - template - inline void - gslice_array<_Tp>::operator=(const _Tp& __t) const - { - std::__valarray_fill(_M_array, _Array(_M_index), - _M_index.size(), __t); - } - - template - inline void - gslice_array<_Tp>::operator=(const valarray<_Tp>& __v) const - { - std::__valarray_copy(_Array<_Tp>(__v), __v.size(), - _M_array, _Array(_M_index)); - } - - template - template - inline void - gslice_array<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) const - { - std::__valarray_copy (__e, _M_index.size(), _M_array, - _Array(_M_index)); - } - -#undef _DEFINE_VALARRAY_OPERATOR -#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ - template \ - inline void \ - gslice_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ - { \ - _Array_augmented_##_Name(_M_array, _Array(_M_index), \ - _Array<_Tp>(__v), __v.size()); \ - } \ - \ - template \ - template \ - inline void \ - gslice_array<_Tp>::operator _Op##= (const _Expr<_Dom, _Tp>& __e) const\ - { \ - _Array_augmented_##_Name(_M_array, _Array(_M_index), __e,\ - _M_index.size()); \ - } - -_DEFINE_VALARRAY_OPERATOR(*, __multiplies) -_DEFINE_VALARRAY_OPERATOR(/, __divides) -_DEFINE_VALARRAY_OPERATOR(%, __modulus) -_DEFINE_VALARRAY_OPERATOR(+, __plus) -_DEFINE_VALARRAY_OPERATOR(-, __minus) -_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) -_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) -_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) -_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) -_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) - -#undef _DEFINE_VALARRAY_OPERATOR - - // @} group numeric_arrays - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _GSLICE_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h b/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h deleted file mode 100644 index 8d9c9eb24..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h +++ /dev/null @@ -1,59 +0,0 @@ -// Declarations for hash functions. -*- C++ -*- - -// Copyright (C) 2010-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/hash_bytes.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _HASH_BYTES_H -#define _HASH_BYTES_H 1 - -#pragma GCC system_header - -#include - -namespace std -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Hash function implementation for the nontrivial specialization. - // All of them are based on a primitive that hashes a pointer to a - // byte array. The actual hash algorithm is not guaranteed to stay - // the same from release to release -- it may be updated or tuned to - // improve hash quality or speed. - size_t - _Hash_bytes(const void* __ptr, size_t __len, size_t __seed); - - // A similar hash primitive, using the FNV hash algorithm. This - // algorithm is guaranteed to stay the same from release to release. - // (although it might not produce the same values on different - // machines.) - size_t - _Fnv_hash_bytes(const void* __ptr, size_t __len, size_t __seed); - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/hashtable.h b/resources/sources/avr-libstdcpp/include/bits/hashtable.h deleted file mode 100644 index b00319a66..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/hashtable.h +++ /dev/null @@ -1,2228 +0,0 @@ -// hashtable.h header -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/hashtable.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{unordered_map, unordered_set} - */ - -#ifndef _HASHTABLE_H -#define _HASHTABLE_H 1 - -#pragma GCC system_header - -#include -#if __cplusplus > 201402L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template - using __cache_default - = __not_<__and_, - // Mandatory to have erase not throwing. - __is_nothrow_invocable>>; - - /** - * Primary class template _Hashtable. - * - * @ingroup hashtable-detail - * - * @tparam _Value CopyConstructible type. - * - * @tparam _Key CopyConstructible type. - * - * @tparam _Alloc An allocator type - * ([lib.allocator.requirements]) whose _Alloc::value_type is - * _Value. As a conforming extension, we allow for - * _Alloc::value_type != _Value. - * - * @tparam _ExtractKey Function object that takes an object of type - * _Value and returns a value of type _Key. - * - * @tparam _Equal Function object that takes two objects of type k - * and returns a bool-like value that is true if the two objects - * are considered equal. - * - * @tparam _H1 The hash function. A unary function object with - * argument type _Key and result type size_t. Return values should - * be distributed over the entire range [0, numeric_limits:::max()]. - * - * @tparam _H2 The range-hashing function (in the terminology of - * Tavori and Dreizin). A binary function object whose argument - * types and result type are all size_t. Given arguments r and N, - * the return value is in the range [0, N). - * - * @tparam _Hash The ranged hash function (Tavori and Dreizin). A - * binary function whose argument types are _Key and size_t and - * whose result type is size_t. Given arguments k and N, the - * return value is in the range [0, N). Default: hash(k, N) = - * h2(h1(k), N). If _Hash is anything other than the default, _H1 - * and _H2 are ignored. - * - * @tparam _RehashPolicy Policy class with three members, all of - * which govern the bucket count. _M_next_bkt(n) returns a bucket - * count no smaller than n. _M_bkt_for_elements(n) returns a - * bucket count appropriate for an element count of n. - * _M_need_rehash(n_bkt, n_elt, n_ins) determines whether, if the - * current bucket count is n_bkt and the current element count is - * n_elt, we need to increase the bucket count. If so, returns - * make_pair(true, n), where n is the new bucket count. If not, - * returns make_pair(false, ) - * - * @tparam _Traits Compile-time class with three boolean - * std::integral_constant members: __cache_hash_code, __constant_iterators, - * __unique_keys. - * - * Each _Hashtable data structure has: - * - * - _Bucket[] _M_buckets - * - _Hash_node_base _M_before_begin - * - size_type _M_bucket_count - * - size_type _M_element_count - * - * with _Bucket being _Hash_node* and _Hash_node containing: - * - * - _Hash_node* _M_next - * - Tp _M_value - * - size_t _M_hash_code if cache_hash_code is true - * - * In terms of Standard containers the hashtable is like the aggregation of: - * - * - std::forward_list<_Node> containing the elements - * - std::vector::iterator> representing the buckets - * - * The non-empty buckets contain the node before the first node in the - * bucket. This design makes it possible to implement something like a - * std::forward_list::insert_after on container insertion and - * std::forward_list::erase_after on container erase - * calls. _M_before_begin is equivalent to - * std::forward_list::before_begin. Empty buckets contain - * nullptr. Note that one of the non-empty buckets contains - * &_M_before_begin which is not a dereferenceable node so the - * node pointer in a bucket shall never be dereferenced, only its - * next node can be. - * - * Walking through a bucket's nodes requires a check on the hash code to - * see if each node is still in the bucket. Such a design assumes a - * quite efficient hash functor and is one of the reasons it is - * highly advisable to set __cache_hash_code to true. - * - * The container iterators are simply built from nodes. This way - * incrementing the iterator is perfectly efficient independent of - * how many empty buckets there are in the container. - * - * On insert we compute the element's hash code and use it to find the - * bucket index. If the element must be inserted in an empty bucket - * we add it at the beginning of the singly linked list and make the - * bucket point to _M_before_begin. The bucket that used to point to - * _M_before_begin, if any, is updated to point to its new before - * begin node. - * - * On erase, the simple iterator design requires using the hash - * functor to get the index of the bucket to update. For this - * reason, when __cache_hash_code is set to false the hash functor must - * not throw and this is enforced by a static assertion. - * - * Functionality is implemented by decomposition into base classes, - * where the derived _Hashtable class is used in _Map_base, - * _Insert, _Rehash_base, and _Equality base classes to access the - * "this" pointer. _Hashtable_base is used in the base classes as a - * non-recursive, fully-completed-type so that detailed nested type - * information, such as iterator type and node type, can be - * used. This is similar to the "Curiously Recurring Template - * Pattern" (CRTP) technique, but uses a reconstructed, not - * explicitly passed, template pattern. - * - * Base class templates are: - * - __detail::_Hashtable_base - * - __detail::_Map_base - * - __detail::_Insert - * - __detail::_Rehash_base - * - __detail::_Equality - */ - template - class _Hashtable - : public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, - _H1, _H2, _Hash, _Traits>, - public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>, - public __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>, - public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>, - public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>, - private __detail::_Hashtable_alloc< - __alloc_rebind<_Alloc, - __detail::_Hash_node<_Value, - _Traits::__hash_cached::value>>> - { - static_assert(is_same::type, _Value>::value, - "unordered container must have a non-const, non-volatile value_type"); -#if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same{}, - "unordered container must have the same value_type as its allocator"); -#endif - - using __traits_type = _Traits; - using __hash_cached = typename __traits_type::__hash_cached; - using __node_type = __detail::_Hash_node<_Value, __hash_cached::value>; - using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>; - - using __hashtable_alloc = __detail::_Hashtable_alloc<__node_alloc_type>; - - using __value_alloc_traits = - typename __hashtable_alloc::__value_alloc_traits; - using __node_alloc_traits = - typename __hashtable_alloc::__node_alloc_traits; - using __node_base = typename __hashtable_alloc::__node_base; - using __bucket_type = typename __hashtable_alloc::__bucket_type; - - public: - typedef _Key key_type; - typedef _Value value_type; - typedef _Alloc allocator_type; - typedef _Equal key_equal; - - // mapped_type, if present, comes from _Map_base. - // hasher, if present, comes from _Hash_code_base/_Hashtable_base. - typedef typename __value_alloc_traits::pointer pointer; - typedef typename __value_alloc_traits::const_pointer const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - - private: - using __rehash_type = _RehashPolicy; - using __rehash_state = typename __rehash_type::_State; - - using __constant_iterators = typename __traits_type::__constant_iterators; - using __unique_keys = typename __traits_type::__unique_keys; - - using __key_extract = typename std::conditional< - __constant_iterators::value, - __detail::_Identity, - __detail::_Select1st>::type; - - using __hashtable_base = __detail:: - _Hashtable_base<_Key, _Value, _ExtractKey, - _Equal, _H1, _H2, _Hash, _Traits>; - - using __hash_code_base = typename __hashtable_base::__hash_code_base; - using __hash_code = typename __hashtable_base::__hash_code; - using __ireturn_type = typename __hashtable_base::__ireturn_type; - - using __map_base = __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>; - - using __rehash_base = __detail::_Rehash_base<_Key, _Value, _Alloc, - _ExtractKey, _Equal, - _H1, _H2, _Hash, - _RehashPolicy, _Traits>; - - using __eq_base = __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>; - - using __reuse_or_alloc_node_gen_t = - __detail::_ReuseOrAllocNode<__node_alloc_type>; - using __alloc_node_gen_t = - __detail::_AllocNode<__node_alloc_type>; - - // Simple RAII type for managing a node containing an element - struct _Scoped_node - { - // Take ownership of a node with a constructed element. - _Scoped_node(__node_type* __n, __hashtable_alloc* __h) - : _M_h(__h), _M_node(__n) { } - - // Allocate a node and construct an element within it. - template - _Scoped_node(__hashtable_alloc* __h, _Args&&... __args) - : _M_h(__h), - _M_node(__h->_M_allocate_node(std::forward<_Args>(__args)...)) - { } - - // Destroy element and deallocate node. - ~_Scoped_node() { if (_M_node) _M_h->_M_deallocate_node(_M_node); }; - - _Scoped_node(const _Scoped_node&) = delete; - _Scoped_node& operator=(const _Scoped_node&) = delete; - - __hashtable_alloc* _M_h; - __node_type* _M_node; - }; - - template - static constexpr - typename conditional::value, - const value_type&, value_type&&>::type - __fwd_value_for(value_type& __val) noexcept - { return std::move(__val); } - - // Metaprogramming for picking apart hash caching. - template - using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>; - - template - using __if_hash_not_cached = __or_<__hash_cached, _Cond>; - - // Compile-time diagnostics. - - // _Hash_code_base has everything protected, so use this derived type to - // access it. - struct __hash_code_base_access : __hash_code_base - { using __hash_code_base::_M_bucket_index; }; - - // Getting a bucket index from a node shall not throw because it is used - // in methods (erase, swap...) that shall not throw. - static_assert(noexcept(declval() - ._M_bucket_index((const __node_type*)nullptr, - (std::size_t)0)), - "Cache the hash code or qualify your functors involved" - " in hash code and bucket index computation with noexcept"); - - // When hash codes are cached local iterator inherits from H2 functor - // which must then be default constructible. - static_assert(__if_hash_cached>::value, - "Functor used to map hash code to bucket index" - " must be default constructible"); - - template - friend struct __detail::_Map_base; - - template - friend struct __detail::_Insert_base; - - template - friend struct __detail::_Insert; - - template - friend struct __detail::_Equality; - - public: - using size_type = typename __hashtable_base::size_type; - using difference_type = typename __hashtable_base::difference_type; - - using iterator = typename __hashtable_base::iterator; - using const_iterator = typename __hashtable_base::const_iterator; - - using local_iterator = typename __hashtable_base::local_iterator; - using const_local_iterator = typename __hashtable_base:: - const_local_iterator; - -#if __cplusplus > 201402L - using node_type = _Node_handle<_Key, _Value, __node_alloc_type>; - using insert_return_type = _Node_insert_return; -#endif - - private: - __bucket_type* _M_buckets = &_M_single_bucket; - size_type _M_bucket_count = 1; - __node_base _M_before_begin; - size_type _M_element_count = 0; - _RehashPolicy _M_rehash_policy; - - // A single bucket used when only need for 1 bucket. Especially - // interesting in move semantic to leave hashtable with only 1 bucket - // which is not allocated so that we can have those operations noexcept - // qualified. - // Note that we can't leave hashtable with 0 bucket without adding - // numerous checks in the code to avoid 0 modulus. - __bucket_type _M_single_bucket = nullptr; - - bool - _M_uses_single_bucket(__bucket_type* __bkts) const - { return __builtin_expect(__bkts == &_M_single_bucket, false); } - - bool - _M_uses_single_bucket() const - { return _M_uses_single_bucket(_M_buckets); } - - __hashtable_alloc& - _M_base_alloc() { return *this; } - - __bucket_type* - _M_allocate_buckets(size_type __bkt_count) - { - if (__builtin_expect(__bkt_count == 1, false)) - { - _M_single_bucket = nullptr; - return &_M_single_bucket; - } - - return __hashtable_alloc::_M_allocate_buckets(__bkt_count); - } - - void - _M_deallocate_buckets(__bucket_type* __bkts, size_type __bkt_count) - { - if (_M_uses_single_bucket(__bkts)) - return; - - __hashtable_alloc::_M_deallocate_buckets(__bkts, __bkt_count); - } - - void - _M_deallocate_buckets() - { _M_deallocate_buckets(_M_buckets, _M_bucket_count); } - - // Gets bucket begin, deals with the fact that non-empty buckets contain - // their before begin node. - __node_type* - _M_bucket_begin(size_type __bkt) const; - - __node_type* - _M_begin() const - { return static_cast<__node_type*>(_M_before_begin._M_nxt); } - - // Assign *this using another _Hashtable instance. Whether elements - // are copied or moved depends on the _Ht reference. - template - void - _M_assign_elements(_Ht&&); - - template - void - _M_assign(_Ht&&, const _NodeGenerator&); - - void - _M_move_assign(_Hashtable&&, true_type); - - void - _M_move_assign(_Hashtable&&, false_type); - - void - _M_reset() noexcept; - - _Hashtable(const _H1& __h1, const _H2& __h2, const _Hash& __h, - const _Equal& __eq, const _ExtractKey& __exk, - const allocator_type& __a) - : __hashtable_base(__exk, __h1, __h2, __h, __eq), - __hashtable_alloc(__node_alloc_type(__a)) - { } - - public: - // Constructor, destructor, assignment, swap - _Hashtable() = default; - _Hashtable(size_type __bkt_count_hint, - const _H1&, const _H2&, const _Hash&, - const _Equal&, const _ExtractKey&, - const allocator_type&); - - template - _Hashtable(_InputIterator __first, _InputIterator __last, - size_type __bkt_count_hint, - const _H1&, const _H2&, const _Hash&, - const _Equal&, const _ExtractKey&, - const allocator_type&); - - _Hashtable(const _Hashtable&); - - _Hashtable(_Hashtable&&) noexcept; - - _Hashtable(const _Hashtable&, const allocator_type&); - - _Hashtable(_Hashtable&&, const allocator_type&); - - // Use delegating constructors. - explicit - _Hashtable(const allocator_type& __a) - : __hashtable_alloc(__node_alloc_type(__a)) - { } - - explicit - _Hashtable(size_type __bkt_count_hint, - const _H1& __hf = _H1(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _Hashtable(__bkt_count_hint, __hf, _H2(), _Hash(), __eql, - __key_extract(), __a) - { } - - template - _Hashtable(_InputIterator __f, _InputIterator __l, - size_type __bkt_count_hint = 0, - const _H1& __hf = _H1(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _Hashtable(__f, __l, __bkt_count_hint, __hf, _H2(), _Hash(), __eql, - __key_extract(), __a) - { } - - _Hashtable(initializer_list __l, - size_type __bkt_count_hint = 0, - const _H1& __hf = _H1(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _Hashtable(__l.begin(), __l.end(), __bkt_count_hint, - __hf, _H2(), _Hash(), __eql, - __key_extract(), __a) - { } - - _Hashtable& - operator=(const _Hashtable& __ht); - - _Hashtable& - operator=(_Hashtable&& __ht) - noexcept(__node_alloc_traits::_S_nothrow_move() - && is_nothrow_move_assignable<_H1>::value - && is_nothrow_move_assignable<_Equal>::value) - { - constexpr bool __move_storage = - __node_alloc_traits::_S_propagate_on_move_assign() - || __node_alloc_traits::_S_always_equal(); - _M_move_assign(std::move(__ht), __bool_constant<__move_storage>()); - return *this; - } - - _Hashtable& - operator=(initializer_list __l) - { - __reuse_or_alloc_node_gen_t __roan(_M_begin(), *this); - _M_before_begin._M_nxt = nullptr; - clear(); - this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys()); - return *this; - } - - ~_Hashtable() noexcept; - - void - swap(_Hashtable&) - noexcept(__and_<__is_nothrow_swappable<_H1>, - __is_nothrow_swappable<_Equal>>::value); - - // Basic container operations - iterator - begin() noexcept - { return iterator(_M_begin()); } - - const_iterator - begin() const noexcept - { return const_iterator(_M_begin()); } - - iterator - end() noexcept - { return iterator(nullptr); } - - const_iterator - end() const noexcept - { return const_iterator(nullptr); } - - const_iterator - cbegin() const noexcept - { return const_iterator(_M_begin()); } - - const_iterator - cend() const noexcept - { return const_iterator(nullptr); } - - size_type - size() const noexcept - { return _M_element_count; } - - _GLIBCXX_NODISCARD bool - empty() const noexcept - { return size() == 0; } - - allocator_type - get_allocator() const noexcept - { return allocator_type(this->_M_node_allocator()); } - - size_type - max_size() const noexcept - { return __node_alloc_traits::max_size(this->_M_node_allocator()); } - - // Observers - key_equal - key_eq() const - { return this->_M_eq(); } - - // hash_function, if present, comes from _Hash_code_base. - - // Bucket operations - size_type - bucket_count() const noexcept - { return _M_bucket_count; } - - size_type - max_bucket_count() const noexcept - { return max_size(); } - - size_type - bucket_size(size_type __bkt) const - { return std::distance(begin(__bkt), end(__bkt)); } - - size_type - bucket(const key_type& __k) const - { return _M_bucket_index(__k, this->_M_hash_code(__k)); } - - local_iterator - begin(size_type __bkt) - { - return local_iterator(*this, _M_bucket_begin(__bkt), - __bkt, _M_bucket_count); - } - - local_iterator - end(size_type __bkt) - { return local_iterator(*this, nullptr, __bkt, _M_bucket_count); } - - const_local_iterator - begin(size_type __bkt) const - { - return const_local_iterator(*this, _M_bucket_begin(__bkt), - __bkt, _M_bucket_count); - } - - const_local_iterator - end(size_type __bkt) const - { return const_local_iterator(*this, nullptr, __bkt, _M_bucket_count); } - - // DR 691. - const_local_iterator - cbegin(size_type __bkt) const - { - return const_local_iterator(*this, _M_bucket_begin(__bkt), - __bkt, _M_bucket_count); - } - - const_local_iterator - cend(size_type __bkt) const - { return const_local_iterator(*this, nullptr, __bkt, _M_bucket_count); } - - float - load_factor() const noexcept - { - return static_cast(size()) / static_cast(bucket_count()); - } - - // max_load_factor, if present, comes from _Rehash_base. - - // Generalization of max_load_factor. Extension, not found in - // TR1. Only useful if _RehashPolicy is something other than - // the default. - const _RehashPolicy& - __rehash_policy() const - { return _M_rehash_policy; } - - void - __rehash_policy(const _RehashPolicy& __pol) - { _M_rehash_policy = __pol; } - - // Lookup. - iterator - find(const key_type& __k); - - const_iterator - find(const key_type& __k) const; - - size_type - count(const key_type& __k) const; - - std::pair - equal_range(const key_type& __k); - - std::pair - equal_range(const key_type& __k) const; - - protected: - // Bucket index computation helpers. - size_type - _M_bucket_index(__node_type* __n) const noexcept - { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); } - - size_type - _M_bucket_index(const key_type& __k, __hash_code __c) const - { return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); } - - // Find and insert helper functions and types - // Find the node before the one matching the criteria. - __node_base* - _M_find_before_node(size_type, const key_type&, __hash_code) const; - - __node_type* - _M_find_node(size_type __bkt, const key_type& __key, - __hash_code __c) const - { - __node_base* __before_n = _M_find_before_node(__bkt, __key, __c); - if (__before_n) - return static_cast<__node_type*>(__before_n->_M_nxt); - return nullptr; - } - - // Insert a node at the beginning of a bucket. - void - _M_insert_bucket_begin(size_type, __node_type*); - - // Remove the bucket first node - void - _M_remove_bucket_begin(size_type __bkt, __node_type* __next_n, - size_type __next_bkt); - - // Get the node before __n in the bucket __bkt - __node_base* - _M_get_previous_node(size_type __bkt, __node_base* __n); - - // Insert node __n with key __k and hash code __code, in bucket __bkt - // if no rehash (assumes no element with same key already present). - // Takes ownership of __n if insertion succeeds, throws otherwise. - iterator - _M_insert_unique_node(const key_type& __k, size_type __bkt, - __hash_code __code, __node_type* __n, - size_type __n_elt = 1); - - // Insert node __n with key __k and hash code __code. - // Takes ownership of __n if insertion succeeds, throws otherwise. - iterator - _M_insert_multi_node(__node_type* __hint, const key_type& __k, - __hash_code __code, __node_type* __n); - - template - std::pair - _M_emplace(true_type, _Args&&... __args); - - template - iterator - _M_emplace(false_type __uk, _Args&&... __args) - { return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); } - - // Emplace with hint, useless when keys are unique. - template - iterator - _M_emplace(const_iterator, true_type __uk, _Args&&... __args) - { return _M_emplace(__uk, std::forward<_Args>(__args)...).first; } - - template - iterator - _M_emplace(const_iterator, false_type, _Args&&... __args); - - template - std::pair - _M_insert(_Arg&&, const _NodeGenerator&, true_type, size_type = 1); - - template - iterator - _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen, - false_type __uk) - { - return _M_insert(cend(), std::forward<_Arg>(__arg), __node_gen, - __uk); - } - - // Insert with hint, not used when keys are unique. - template - iterator - _M_insert(const_iterator, _Arg&& __arg, - const _NodeGenerator& __node_gen, true_type __uk) - { - return - _M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).first; - } - - // Insert with hint when keys are not unique. - template - iterator - _M_insert(const_iterator, _Arg&&, - const _NodeGenerator&, false_type); - - size_type - _M_erase(true_type, const key_type&); - - size_type - _M_erase(false_type, const key_type&); - - iterator - _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n); - - public: - // Emplace - template - __ireturn_type - emplace(_Args&&... __args) - { return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); } - - template - iterator - emplace_hint(const_iterator __hint, _Args&&... __args) - { - return _M_emplace(__hint, __unique_keys(), - std::forward<_Args>(__args)...); - } - - // Insert member functions via inheritance. - - // Erase - iterator - erase(const_iterator); - - // LWG 2059. - iterator - erase(iterator __it) - { return erase(const_iterator(__it)); } - - size_type - erase(const key_type& __k) - { return _M_erase(__unique_keys(), __k); } - - iterator - erase(const_iterator, const_iterator); - - void - clear() noexcept; - - // Set number of buckets keeping it appropriate for container's number - // of elements. - void rehash(size_type __bkt_count); - - // DR 1189. - // reserve, if present, comes from _Rehash_base. - -#if __cplusplus > 201402L - /// Re-insert an extracted node into a container with unique keys. - insert_return_type - _M_reinsert_node(node_type&& __nh) - { - insert_return_type __ret; - if (__nh.empty()) - __ret.position = end(); - else - { - __glibcxx_assert(get_allocator() == __nh.get_allocator()); - - const key_type& __k = __nh._M_key(); - __hash_code __code = this->_M_hash_code(__k); - size_type __bkt = _M_bucket_index(__k, __code); - if (__node_type* __n = _M_find_node(__bkt, __k, __code)) - { - __ret.node = std::move(__nh); - __ret.position = iterator(__n); - __ret.inserted = false; - } - else - { - __ret.position - = _M_insert_unique_node(__k, __bkt, __code, __nh._M_ptr); - __nh._M_ptr = nullptr; - __ret.inserted = true; - } - } - return __ret; - } - - /// Re-insert an extracted node into a container with equivalent keys. - iterator - _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh) - { - if (__nh.empty()) - return end(); - - __glibcxx_assert(get_allocator() == __nh.get_allocator()); - - const key_type& __k = __nh._M_key(); - auto __code = this->_M_hash_code(__k); - auto __ret - = _M_insert_multi_node(__hint._M_cur, __k, __code, __nh._M_ptr); - __nh._M_ptr = nullptr; - return __ret; - } - - private: - node_type - _M_extract_node(size_t __bkt, __node_base* __prev_n) - { - __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); - if (__prev_n == _M_buckets[__bkt]) - _M_remove_bucket_begin(__bkt, __n->_M_next(), - __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0); - else if (__n->_M_nxt) - { - size_type __next_bkt = _M_bucket_index(__n->_M_next()); - if (__next_bkt != __bkt) - _M_buckets[__next_bkt] = __prev_n; - } - - __prev_n->_M_nxt = __n->_M_nxt; - __n->_M_nxt = nullptr; - --_M_element_count; - return { __n, this->_M_node_allocator() }; - } - - public: - // Extract a node. - node_type - extract(const_iterator __pos) - { - size_t __bkt = _M_bucket_index(__pos._M_cur); - return _M_extract_node(__bkt, - _M_get_previous_node(__bkt, __pos._M_cur)); - } - - /// Extract a node. - node_type - extract(const _Key& __k) - { - node_type __nh; - __hash_code __code = this->_M_hash_code(__k); - std::size_t __bkt = _M_bucket_index(__k, __code); - if (__node_base* __prev_node = _M_find_before_node(__bkt, __k, __code)) - __nh = _M_extract_node(__bkt, __prev_node); - return __nh; - } - - /// Merge from a compatible container into one with unique keys. - template - void - _M_merge_unique(_Compatible_Hashtable& __src) noexcept - { - static_assert(is_same_v, "Node types are compatible"); - __glibcxx_assert(get_allocator() == __src.get_allocator()); - - auto __n_elt = __src.size(); - for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) - { - auto __pos = __i++; - const key_type& __k = this->_M_extract()(*__pos); - __hash_code __code = this->_M_hash_code(__k); - size_type __bkt = _M_bucket_index(__k, __code); - if (_M_find_node(__bkt, __k, __code) == nullptr) - { - auto __nh = __src.extract(__pos); - _M_insert_unique_node(__k, __bkt, __code, __nh._M_ptr, - __n_elt); - __nh._M_ptr = nullptr; - __n_elt = 1; - } - else if (__n_elt != 1) - --__n_elt; - } - } - - /// Merge from a compatible container into one with equivalent keys. - template - void - _M_merge_multi(_Compatible_Hashtable& __src) noexcept - { - static_assert(is_same_v, "Node types are compatible"); - __glibcxx_assert(get_allocator() == __src.get_allocator()); - - this->reserve(size() + __src.size()); - for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) - _M_reinsert_node_multi(cend(), __src.extract(__i++)); - } -#endif // C++17 - - private: - // Helper rehash method used when keys are unique. - void _M_rehash_aux(size_type __bkt_count, true_type); - - // Helper rehash method used when keys can be non-unique. - void _M_rehash_aux(size_type __bkt_count, false_type); - - // Unconditionally change size of bucket array to n, restore - // hash policy state to __state on exception. - void _M_rehash(size_type __bkt_count, const __rehash_state& __state); - }; - - - // Definitions of class template _Hashtable's out-of-line member functions. - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_bucket_begin(size_type __bkt) const - -> __node_type* - { - __node_base* __n = _M_buckets[__bkt]; - return __n ? static_cast<__node_type*>(__n->_M_nxt) : nullptr; - } - - template - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _Hashtable(size_type __bkt_count_hint, - const _H1& __h1, const _H2& __h2, const _Hash& __h, - const _Equal& __eq, const _ExtractKey& __exk, - const allocator_type& __a) - : _Hashtable(__h1, __h2, __h, __eq, __exk, __a) - { - auto __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count_hint); - if (__bkt_count > _M_bucket_count) - { - _M_buckets = _M_allocate_buckets(__bkt_count); - _M_bucket_count = __bkt_count; - } - } - - template - template - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _Hashtable(_InputIterator __f, _InputIterator __l, - size_type __bkt_count_hint, - const _H1& __h1, const _H2& __h2, const _Hash& __h, - const _Equal& __eq, const _ExtractKey& __exk, - const allocator_type& __a) - : _Hashtable(__h1, __h2, __h, __eq, __exk, __a) - { - auto __nb_elems = __detail::__distance_fw(__f, __l); - auto __bkt_count = - _M_rehash_policy._M_next_bkt( - std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems), - __bkt_count_hint)); - - if (__bkt_count > _M_bucket_count) - { - _M_buckets = _M_allocate_buckets(__bkt_count); - _M_bucket_count = __bkt_count; - } - - for (; __f != __l; ++__f) - this->insert(*__f); - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - operator=(const _Hashtable& __ht) - -> _Hashtable& - { - if (&__ht == this) - return *this; - - if (__node_alloc_traits::_S_propagate_on_copy_assign()) - { - auto& __this_alloc = this->_M_node_allocator(); - auto& __that_alloc = __ht._M_node_allocator(); - if (!__node_alloc_traits::_S_always_equal() - && __this_alloc != __that_alloc) - { - // Replacement allocator cannot free existing storage. - this->_M_deallocate_nodes(_M_begin()); - _M_before_begin._M_nxt = nullptr; - _M_deallocate_buckets(); - _M_buckets = nullptr; - std::__alloc_on_copy(__this_alloc, __that_alloc); - __hashtable_base::operator=(__ht); - _M_bucket_count = __ht._M_bucket_count; - _M_element_count = __ht._M_element_count; - _M_rehash_policy = __ht._M_rehash_policy; - __alloc_node_gen_t __alloc_node_gen(*this); - __try - { - _M_assign(__ht, __alloc_node_gen); - } - __catch(...) - { - // _M_assign took care of deallocating all memory. Now we - // must make sure this instance remains in a usable state. - _M_reset(); - __throw_exception_again; - } - return *this; - } - std::__alloc_on_copy(__this_alloc, __that_alloc); - } - - // Reuse allocated buckets and nodes. - _M_assign_elements(__ht); - return *this; - } - - template - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_assign_elements(_Ht&& __ht) - { - __bucket_type* __former_buckets = nullptr; - std::size_t __former_bucket_count = _M_bucket_count; - const __rehash_state& __former_state = _M_rehash_policy._M_state(); - - if (_M_bucket_count != __ht._M_bucket_count) - { - __former_buckets = _M_buckets; - _M_buckets = _M_allocate_buckets(__ht._M_bucket_count); - _M_bucket_count = __ht._M_bucket_count; - } - else - __builtin_memset(_M_buckets, 0, - _M_bucket_count * sizeof(__bucket_type)); - - __try - { - __hashtable_base::operator=(std::forward<_Ht>(__ht)); - _M_element_count = __ht._M_element_count; - _M_rehash_policy = __ht._M_rehash_policy; - __reuse_or_alloc_node_gen_t __roan(_M_begin(), *this); - _M_before_begin._M_nxt = nullptr; - _M_assign(std::forward<_Ht>(__ht), __roan); - if (__former_buckets) - _M_deallocate_buckets(__former_buckets, __former_bucket_count); - } - __catch(...) - { - if (__former_buckets) - { - // Restore previous buckets. - _M_deallocate_buckets(); - _M_rehash_policy._M_reset(__former_state); - _M_buckets = __former_buckets; - _M_bucket_count = __former_bucket_count; - } - __builtin_memset(_M_buckets, 0, - _M_bucket_count * sizeof(__bucket_type)); - __throw_exception_again; - } - } - - template - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_assign(_Ht&& __ht, const _NodeGenerator& __node_gen) - { - __bucket_type* __buckets = nullptr; - if (!_M_buckets) - _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count); - - __try - { - if (!__ht._M_before_begin._M_nxt) - return; - - // First deal with the special first node pointed to by - // _M_before_begin. - __node_type* __ht_n = __ht._M_begin(); - __node_type* __this_n - = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v())); - this->_M_copy_code(__this_n, __ht_n); - _M_before_begin._M_nxt = __this_n; - _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin; - - // Then deal with other nodes. - __node_base* __prev_n = __this_n; - for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next()) - { - __this_n = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v())); - __prev_n->_M_nxt = __this_n; - this->_M_copy_code(__this_n, __ht_n); - size_type __bkt = _M_bucket_index(__this_n); - if (!_M_buckets[__bkt]) - _M_buckets[__bkt] = __prev_n; - __prev_n = __this_n; - } - } - __catch(...) - { - clear(); - if (__buckets) - _M_deallocate_buckets(); - __throw_exception_again; - } - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_reset() noexcept - { - _M_rehash_policy._M_reset(); - _M_bucket_count = 1; - _M_single_bucket = nullptr; - _M_buckets = &_M_single_bucket; - _M_before_begin._M_nxt = nullptr; - _M_element_count = 0; - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_move_assign(_Hashtable&& __ht, true_type) - { - this->_M_deallocate_nodes(_M_begin()); - _M_deallocate_buckets(); - __hashtable_base::operator=(std::move(__ht)); - _M_rehash_policy = __ht._M_rehash_policy; - if (!__ht._M_uses_single_bucket()) - _M_buckets = __ht._M_buckets; - else - { - _M_buckets = &_M_single_bucket; - _M_single_bucket = __ht._M_single_bucket; - } - _M_bucket_count = __ht._M_bucket_count; - _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt; - _M_element_count = __ht._M_element_count; - std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator()); - - // Fix buckets containing the _M_before_begin pointers that can't be - // moved. - if (_M_begin()) - _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; - __ht._M_reset(); - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_move_assign(_Hashtable&& __ht, false_type) - { - if (__ht._M_node_allocator() == this->_M_node_allocator()) - _M_move_assign(std::move(__ht), true_type()); - else - { - // Can't move memory, move elements then. - _M_assign_elements(std::move(__ht)); - __ht.clear(); - } - } - - template - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _Hashtable(const _Hashtable& __ht) - : __hashtable_base(__ht), - __map_base(__ht), - __rehash_base(__ht), - __hashtable_alloc( - __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())), - _M_buckets(nullptr), - _M_bucket_count(__ht._M_bucket_count), - _M_element_count(__ht._M_element_count), - _M_rehash_policy(__ht._M_rehash_policy) - { - __alloc_node_gen_t __alloc_node_gen(*this); - _M_assign(__ht, __alloc_node_gen); - } - - template - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _Hashtable(_Hashtable&& __ht) noexcept - : __hashtable_base(__ht), - __map_base(__ht), - __rehash_base(__ht), - __hashtable_alloc(std::move(__ht._M_base_alloc())), - _M_buckets(__ht._M_buckets), - _M_bucket_count(__ht._M_bucket_count), - _M_before_begin(__ht._M_before_begin._M_nxt), - _M_element_count(__ht._M_element_count), - _M_rehash_policy(__ht._M_rehash_policy) - { - // Update, if necessary, buckets if __ht is using its single bucket. - if (__ht._M_uses_single_bucket()) - { - _M_buckets = &_M_single_bucket; - _M_single_bucket = __ht._M_single_bucket; - } - - // Update, if necessary, bucket pointing to before begin that hasn't - // moved. - if (_M_begin()) - _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; - - __ht._M_reset(); - } - - template - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _Hashtable(const _Hashtable& __ht, const allocator_type& __a) - : __hashtable_base(__ht), - __map_base(__ht), - __rehash_base(__ht), - __hashtable_alloc(__node_alloc_type(__a)), - _M_buckets(), - _M_bucket_count(__ht._M_bucket_count), - _M_element_count(__ht._M_element_count), - _M_rehash_policy(__ht._M_rehash_policy) - { - __alloc_node_gen_t __alloc_node_gen(*this); - _M_assign(__ht, __alloc_node_gen); - } - - template - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _Hashtable(_Hashtable&& __ht, const allocator_type& __a) - : __hashtable_base(__ht), - __map_base(__ht), - __rehash_base(__ht), - __hashtable_alloc(__node_alloc_type(__a)), - _M_buckets(nullptr), - _M_bucket_count(__ht._M_bucket_count), - _M_element_count(__ht._M_element_count), - _M_rehash_policy(__ht._M_rehash_policy) - { - if (__ht._M_node_allocator() == this->_M_node_allocator()) - { - if (__ht._M_uses_single_bucket()) - { - _M_buckets = &_M_single_bucket; - _M_single_bucket = __ht._M_single_bucket; - } - else - _M_buckets = __ht._M_buckets; - - _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt; - // Update, if necessary, bucket pointing to before begin that hasn't - // moved. - if (_M_begin()) - _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; - __ht._M_reset(); - } - else - { - __alloc_node_gen_t __alloc_gen(*this); - - using _Fwd_Ht = typename - conditional<__move_if_noexcept_cond::value, - const _Hashtable&, _Hashtable&&>::type; - _M_assign(std::forward<_Fwd_Ht>(__ht), __alloc_gen); - __ht.clear(); - } - } - - template - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - ~_Hashtable() noexcept - { - clear(); - _M_deallocate_buckets(); - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - swap(_Hashtable& __x) - noexcept(__and_<__is_nothrow_swappable<_H1>, - __is_nothrow_swappable<_Equal>>::value) - { - // The only base class with member variables is hash_code_base. - // We define _Hash_code_base::_M_swap because different - // specializations have different members. - this->_M_swap(__x); - - std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator()); - std::swap(_M_rehash_policy, __x._M_rehash_policy); - - // Deal properly with potentially moved instances. - if (this->_M_uses_single_bucket()) - { - if (!__x._M_uses_single_bucket()) - { - _M_buckets = __x._M_buckets; - __x._M_buckets = &__x._M_single_bucket; - } - } - else if (__x._M_uses_single_bucket()) - { - __x._M_buckets = _M_buckets; - _M_buckets = &_M_single_bucket; - } - else - std::swap(_M_buckets, __x._M_buckets); - - std::swap(_M_bucket_count, __x._M_bucket_count); - std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt); - std::swap(_M_element_count, __x._M_element_count); - std::swap(_M_single_bucket, __x._M_single_bucket); - - // Fix buckets containing the _M_before_begin pointers that can't be - // swapped. - if (_M_begin()) - _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; - - if (__x._M_begin()) - __x._M_buckets[__x._M_bucket_index(__x._M_begin())] - = &__x._M_before_begin; - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - find(const key_type& __k) - -> iterator - { - __hash_code __code = this->_M_hash_code(__k); - std::size_t __bkt = _M_bucket_index(__k, __code); - __node_type* __p = _M_find_node(__bkt, __k, __code); - return __p ? iterator(__p) : end(); - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - find(const key_type& __k) const - -> const_iterator - { - __hash_code __code = this->_M_hash_code(__k); - std::size_t __bkt = _M_bucket_index(__k, __code); - __node_type* __p = _M_find_node(__bkt, __k, __code); - return __p ? const_iterator(__p) : end(); - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - count(const key_type& __k) const - -> size_type - { - __hash_code __code = this->_M_hash_code(__k); - std::size_t __bkt = _M_bucket_index(__k, __code); - __node_type* __p = _M_bucket_begin(__bkt); - if (!__p) - return 0; - - std::size_t __result = 0; - for (;; __p = __p->_M_next()) - { - if (this->_M_equals(__k, __code, __p)) - ++__result; - else if (__result) - // All equivalent values are next to each other, if we - // found a non-equivalent value after an equivalent one it - // means that we won't find any new equivalent value. - break; - if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __bkt) - break; - } - return __result; - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - equal_range(const key_type& __k) - -> pair - { - __hash_code __code = this->_M_hash_code(__k); - std::size_t __bkt = _M_bucket_index(__k, __code); - __node_type* __p = _M_find_node(__bkt, __k, __code); - - if (__p) - { - __node_type* __p1 = __p->_M_next(); - while (__p1 && _M_bucket_index(__p1) == __bkt - && this->_M_equals(__k, __code, __p1)) - __p1 = __p1->_M_next(); - - return std::make_pair(iterator(__p), iterator(__p1)); - } - else - return std::make_pair(end(), end()); - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - equal_range(const key_type& __k) const - -> pair - { - __hash_code __code = this->_M_hash_code(__k); - std::size_t __bkt = _M_bucket_index(__k, __code); - __node_type* __p = _M_find_node(__bkt, __k, __code); - - if (__p) - { - __node_type* __p1 = __p->_M_next(); - while (__p1 && _M_bucket_index(__p1) == __bkt - && this->_M_equals(__k, __code, __p1)) - __p1 = __p1->_M_next(); - - return std::make_pair(const_iterator(__p), const_iterator(__p1)); - } - else - return std::make_pair(end(), end()); - } - - // Find the node whose key compares equal to k in the bucket bkt. - // Return nullptr if no node is found. - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_find_before_node(size_type __bkt, const key_type& __k, - __hash_code __code) const - -> __node_base* - { - __node_base* __prev_p = _M_buckets[__bkt]; - if (!__prev_p) - return nullptr; - - for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);; - __p = __p->_M_next()) - { - if (this->_M_equals(__k, __code, __p)) - return __prev_p; - - if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __bkt) - break; - __prev_p = __p; - } - return nullptr; - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_insert_bucket_begin(size_type __bkt, __node_type* __node) - { - if (_M_buckets[__bkt]) - { - // Bucket is not empty, we just need to insert the new node - // after the bucket before begin. - __node->_M_nxt = _M_buckets[__bkt]->_M_nxt; - _M_buckets[__bkt]->_M_nxt = __node; - } - else - { - // The bucket is empty, the new node is inserted at the - // beginning of the singly-linked list and the bucket will - // contain _M_before_begin pointer. - __node->_M_nxt = _M_before_begin._M_nxt; - _M_before_begin._M_nxt = __node; - if (__node->_M_nxt) - // We must update former begin bucket that is pointing to - // _M_before_begin. - _M_buckets[_M_bucket_index(__node->_M_next())] = __node; - _M_buckets[__bkt] = &_M_before_begin; - } - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_remove_bucket_begin(size_type __bkt, __node_type* __next, - size_type __next_bkt) - { - if (!__next || __next_bkt != __bkt) - { - // Bucket is now empty - // First update next bucket if any - if (__next) - _M_buckets[__next_bkt] = _M_buckets[__bkt]; - - // Second update before begin node if necessary - if (&_M_before_begin == _M_buckets[__bkt]) - _M_before_begin._M_nxt = __next; - _M_buckets[__bkt] = nullptr; - } - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_get_previous_node(size_type __bkt, __node_base* __n) - -> __node_base* - { - __node_base* __prev_n = _M_buckets[__bkt]; - while (__prev_n->_M_nxt != __n) - __prev_n = __prev_n->_M_nxt; - return __prev_n; - } - - template - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_emplace(true_type, _Args&&... __args) - -> pair - { - // First build the node to get access to the hash code - _Scoped_node __node { this, std::forward<_Args>(__args)... }; - const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); - __hash_code __code = this->_M_hash_code(__k); - size_type __bkt = _M_bucket_index(__k, __code); - if (__node_type* __p = _M_find_node(__bkt, __k, __code)) - // There is already an equivalent node, no insertion - return std::make_pair(iterator(__p), false); - - // Insert the node - auto __pos = _M_insert_unique_node(__k, __bkt, __code, __node._M_node); - __node._M_node = nullptr; - return { __pos, true }; - } - - template - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_emplace(const_iterator __hint, false_type, _Args&&... __args) - -> iterator - { - // First build the node to get its hash code. - _Scoped_node __node { this, std::forward<_Args>(__args)... }; - const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); - - __hash_code __code = this->_M_hash_code(__k); - auto __pos - = _M_insert_multi_node(__hint._M_cur, __k, __code, __node._M_node); - __node._M_node = nullptr; - return __pos; - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_insert_unique_node(const key_type& __k, size_type __bkt, - __hash_code __code, __node_type* __node, - size_type __n_elt) - -> iterator - { - const __rehash_state& __saved_state = _M_rehash_policy._M_state(); - std::pair __do_rehash - = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, - __n_elt); - - if (__do_rehash.first) - { - _M_rehash(__do_rehash.second, __saved_state); - __bkt = _M_bucket_index(__k, __code); - } - - this->_M_store_code(__node, __code); - - // Always insert at the beginning of the bucket. - _M_insert_bucket_begin(__bkt, __node); - ++_M_element_count; - return iterator(__node); - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_insert_multi_node(__node_type* __hint, const key_type& __k, - __hash_code __code, __node_type* __node) - -> iterator - { - const __rehash_state& __saved_state = _M_rehash_policy._M_state(); - std::pair __do_rehash - = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1); - - if (__do_rehash.first) - _M_rehash(__do_rehash.second, __saved_state); - - this->_M_store_code(__node, __code); - size_type __bkt = _M_bucket_index(__k, __code); - - // Find the node before an equivalent one or use hint if it exists and - // if it is equivalent. - __node_base* __prev - = __builtin_expect(__hint != nullptr, false) - && this->_M_equals(__k, __code, __hint) - ? __hint - : _M_find_before_node(__bkt, __k, __code); - if (__prev) - { - // Insert after the node before the equivalent one. - __node->_M_nxt = __prev->_M_nxt; - __prev->_M_nxt = __node; - if (__builtin_expect(__prev == __hint, false)) - // hint might be the last bucket node, in this case we need to - // update next bucket. - if (__node->_M_nxt - && !this->_M_equals(__k, __code, __node->_M_next())) - { - size_type __next_bkt = _M_bucket_index(__node->_M_next()); - if (__next_bkt != __bkt) - _M_buckets[__next_bkt] = __node; - } - } - else - // The inserted node has no equivalent in the hashtable. We must - // insert the new node at the beginning of the bucket to preserve - // equivalent elements' relative positions. - _M_insert_bucket_begin(__bkt, __node); - ++_M_element_count; - return iterator(__node); - } - - // Insert v if no element with its key is already present. - template - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_insert(_Arg&& __v, const _NodeGenerator& __node_gen, true_type, - size_type __n_elt) - -> pair - { - const key_type& __k = this->_M_extract()(__v); - __hash_code __code = this->_M_hash_code(__k); - size_type __bkt = _M_bucket_index(__k, __code); - - if (__node_type* __node = _M_find_node(__bkt, __k, __code)) - return { iterator(__node), false }; - - _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)), this }; - auto __pos - = _M_insert_unique_node(__k, __bkt, __code, __node._M_node, __n_elt); - __node._M_node = nullptr; - return { __pos, true }; - } - - // Insert v unconditionally. - template - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_insert(const_iterator __hint, _Arg&& __v, - const _NodeGenerator& __node_gen, false_type) - -> iterator - { - // First compute the hash code so that we don't do anything if it - // throws. - __hash_code __code = this->_M_hash_code(this->_M_extract()(__v)); - - // Second allocate new node so that we don't rehash if it throws. - _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)), this }; - const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); - auto __pos - = _M_insert_multi_node(__hint._M_cur, __k, __code, __node._M_node); - __node._M_node = nullptr; - return __pos; - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - erase(const_iterator __it) - -> iterator - { - __node_type* __n = __it._M_cur; - std::size_t __bkt = _M_bucket_index(__n); - - // Look for previous node to unlink it from the erased one, this - // is why we need buckets to contain the before begin to make - // this search fast. - __node_base* __prev_n = _M_get_previous_node(__bkt, __n); - return _M_erase(__bkt, __prev_n, __n); - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n) - -> iterator - { - if (__prev_n == _M_buckets[__bkt]) - _M_remove_bucket_begin(__bkt, __n->_M_next(), - __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0); - else if (__n->_M_nxt) - { - size_type __next_bkt = _M_bucket_index(__n->_M_next()); - if (__next_bkt != __bkt) - _M_buckets[__next_bkt] = __prev_n; - } - - __prev_n->_M_nxt = __n->_M_nxt; - iterator __result(__n->_M_next()); - this->_M_deallocate_node(__n); - --_M_element_count; - - return __result; - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_erase(true_type, const key_type& __k) - -> size_type - { - __hash_code __code = this->_M_hash_code(__k); - std::size_t __bkt = _M_bucket_index(__k, __code); - - // Look for the node before the first matching node. - __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code); - if (!__prev_n) - return 0; - - // We found a matching node, erase it. - __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); - _M_erase(__bkt, __prev_n, __n); - return 1; - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_erase(false_type, const key_type& __k) - -> size_type - { - __hash_code __code = this->_M_hash_code(__k); - std::size_t __bkt = _M_bucket_index(__k, __code); - - // Look for the node before the first matching node. - __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code); - if (!__prev_n) - return 0; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 526. Is it undefined if a function in the standard changes - // in parameters? - // We use one loop to find all matching nodes and another to deallocate - // them so that the key stays valid during the first loop. It might be - // invalidated indirectly when destroying nodes. - __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); - __node_type* __n_last = __n; - std::size_t __n_last_bkt = __bkt; - do - { - __n_last = __n_last->_M_next(); - if (!__n_last) - break; - __n_last_bkt = _M_bucket_index(__n_last); - } - while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last)); - - // Deallocate nodes. - size_type __result = 0; - do - { - __node_type* __p = __n->_M_next(); - this->_M_deallocate_node(__n); - __n = __p; - ++__result; - --_M_element_count; - } - while (__n != __n_last); - - if (__prev_n == _M_buckets[__bkt]) - _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt); - else if (__n_last && __n_last_bkt != __bkt) - _M_buckets[__n_last_bkt] = __prev_n; - __prev_n->_M_nxt = __n_last; - return __result; - } - - template - auto - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - erase(const_iterator __first, const_iterator __last) - -> iterator - { - __node_type* __n = __first._M_cur; - __node_type* __last_n = __last._M_cur; - if (__n == __last_n) - return iterator(__n); - - std::size_t __bkt = _M_bucket_index(__n); - - __node_base* __prev_n = _M_get_previous_node(__bkt, __n); - bool __is_bucket_begin = __n == _M_bucket_begin(__bkt); - std::size_t __n_bkt = __bkt; - for (;;) - { - do - { - __node_type* __tmp = __n; - __n = __n->_M_next(); - this->_M_deallocate_node(__tmp); - --_M_element_count; - if (!__n) - break; - __n_bkt = _M_bucket_index(__n); - } - while (__n != __last_n && __n_bkt == __bkt); - if (__is_bucket_begin) - _M_remove_bucket_begin(__bkt, __n, __n_bkt); - if (__n == __last_n) - break; - __is_bucket_begin = true; - __bkt = __n_bkt; - } - - if (__n && (__n_bkt != __bkt || __is_bucket_begin)) - _M_buckets[__n_bkt] = __prev_n; - __prev_n->_M_nxt = __n; - return iterator(__n); - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - clear() noexcept - { - this->_M_deallocate_nodes(_M_begin()); - __builtin_memset(_M_buckets, 0, _M_bucket_count * sizeof(__bucket_type)); - _M_element_count = 0; - _M_before_begin._M_nxt = nullptr; - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - rehash(size_type __bkt_count) - { - const __rehash_state& __saved_state = _M_rehash_policy._M_state(); - __bkt_count - = std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1), - __bkt_count); - __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count); - - if (__bkt_count != _M_bucket_count) - _M_rehash(__bkt_count, __saved_state); - else - // No rehash, restore previous state to keep it consistent with - // container state. - _M_rehash_policy._M_reset(__saved_state); - } - - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_rehash(size_type __bkt_count, const __rehash_state& __state) - { - __try - { - _M_rehash_aux(__bkt_count, __unique_keys()); - } - __catch(...) - { - // A failure here means that buckets allocation failed. We only - // have to restore hash policy previous state. - _M_rehash_policy._M_reset(__state); - __throw_exception_again; - } - } - - // Rehash when there is no equivalent elements. - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_rehash_aux(size_type __bkt_count, true_type) - { - __bucket_type* __new_buckets = _M_allocate_buckets(__bkt_count); - __node_type* __p = _M_begin(); - _M_before_begin._M_nxt = nullptr; - std::size_t __bbegin_bkt = 0; - while (__p) - { - __node_type* __next = __p->_M_next(); - std::size_t __bkt - = __hash_code_base::_M_bucket_index(__p, __bkt_count); - if (!__new_buckets[__bkt]) - { - __p->_M_nxt = _M_before_begin._M_nxt; - _M_before_begin._M_nxt = __p; - __new_buckets[__bkt] = &_M_before_begin; - if (__p->_M_nxt) - __new_buckets[__bbegin_bkt] = __p; - __bbegin_bkt = __bkt; - } - else - { - __p->_M_nxt = __new_buckets[__bkt]->_M_nxt; - __new_buckets[__bkt]->_M_nxt = __p; - } - __p = __next; - } - - _M_deallocate_buckets(); - _M_bucket_count = __bkt_count; - _M_buckets = __new_buckets; - } - - // Rehash when there can be equivalent elements, preserve their relative - // order. - template - void - _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>:: - _M_rehash_aux(size_type __bkt_count, false_type) - { - __bucket_type* __new_buckets = _M_allocate_buckets(__bkt_count); - - __node_type* __p = _M_begin(); - _M_before_begin._M_nxt = nullptr; - std::size_t __bbegin_bkt = 0; - std::size_t __prev_bkt = 0; - __node_type* __prev_p = nullptr; - bool __check_bucket = false; - - while (__p) - { - __node_type* __next = __p->_M_next(); - std::size_t __bkt - = __hash_code_base::_M_bucket_index(__p, __bkt_count); - - if (__prev_p && __prev_bkt == __bkt) - { - // Previous insert was already in this bucket, we insert after - // the previously inserted one to preserve equivalent elements - // relative order. - __p->_M_nxt = __prev_p->_M_nxt; - __prev_p->_M_nxt = __p; - - // Inserting after a node in a bucket require to check that we - // haven't change the bucket last node, in this case next - // bucket containing its before begin node must be updated. We - // schedule a check as soon as we move out of the sequence of - // equivalent nodes to limit the number of checks. - __check_bucket = true; - } - else - { - if (__check_bucket) - { - // Check if we shall update the next bucket because of - // insertions into __prev_bkt bucket. - if (__prev_p->_M_nxt) - { - std::size_t __next_bkt - = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), - __bkt_count); - if (__next_bkt != __prev_bkt) - __new_buckets[__next_bkt] = __prev_p; - } - __check_bucket = false; - } - - if (!__new_buckets[__bkt]) - { - __p->_M_nxt = _M_before_begin._M_nxt; - _M_before_begin._M_nxt = __p; - __new_buckets[__bkt] = &_M_before_begin; - if (__p->_M_nxt) - __new_buckets[__bbegin_bkt] = __p; - __bbegin_bkt = __bkt; - } - else - { - __p->_M_nxt = __new_buckets[__bkt]->_M_nxt; - __new_buckets[__bkt]->_M_nxt = __p; - } - } - __prev_p = __p; - __prev_bkt = __bkt; - __p = __next; - } - - if (__check_bucket && __prev_p->_M_nxt) - { - std::size_t __next_bkt - = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), - __bkt_count); - if (__next_bkt != __prev_bkt) - __new_buckets[__next_bkt] = __prev_p; - } - - _M_deallocate_buckets(); - _M_bucket_count = __bkt_count; - _M_buckets = __new_buckets; - } - -#if __cplusplus > 201402L - template class _Hash_merge_helper { }; -#endif // C++17 - -#if __cpp_deduction_guides >= 201606 - // Used to constrain deduction guides - template - using _RequireNotAllocatorOrIntegral - = __enable_if_t, __is_allocator<_Hash>>::value>; -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // _HASHTABLE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h b/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h deleted file mode 100644 index ef1201349..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h +++ /dev/null @@ -1,2107 +0,0 @@ -// Internal policy header for unordered_set and unordered_map -*- C++ -*- - -// Copyright (C) 2010-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/hashtable_policy.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. - * @headername{unordered_map,unordered_set} - */ - -#ifndef _HASHTABLE_POLICY_H -#define _HASHTABLE_POLICY_H 1 - -#include // for std::tuple, std::forward_as_tuple -#include // for std::numeric_limits -#include // for std::min, std::is_permutation. - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template - class _Hashtable; - -namespace __detail -{ - /** - * @defgroup hashtable-detail Base and Implementation Classes - * @ingroup unordered_associative_containers - * @{ - */ - template - struct _Hashtable_base; - - // Helper function: return distance(first, last) for forward - // iterators, or 0/1 for input iterators. - template - inline typename std::iterator_traits<_Iterator>::difference_type - __distance_fw(_Iterator __first, _Iterator __last, - std::input_iterator_tag) - { return __first != __last ? 1 : 0; } - - template - inline typename std::iterator_traits<_Iterator>::difference_type - __distance_fw(_Iterator __first, _Iterator __last, - std::forward_iterator_tag) - { return std::distance(__first, __last); } - - template - inline typename std::iterator_traits<_Iterator>::difference_type - __distance_fw(_Iterator __first, _Iterator __last) - { return __distance_fw(__first, __last, - std::__iterator_category(__first)); } - - struct _Identity - { - template - _Tp&& - operator()(_Tp&& __x) const - { return std::forward<_Tp>(__x); } - }; - - struct _Select1st - { - template - auto - operator()(_Tp&& __x) const - -> decltype(std::get<0>(std::forward<_Tp>(__x))) - { return std::get<0>(std::forward<_Tp>(__x)); } - }; - - template - struct _Hashtable_alloc; - - // Functor recycling a pool of nodes and using allocation once the pool is - // empty. - template - struct _ReuseOrAllocNode - { - private: - using __node_alloc_type = _NodeAlloc; - using __hashtable_alloc = _Hashtable_alloc<__node_alloc_type>; - using __node_alloc_traits = - typename __hashtable_alloc::__node_alloc_traits; - using __node_type = typename __hashtable_alloc::__node_type; - - public: - _ReuseOrAllocNode(__node_type* __nodes, __hashtable_alloc& __h) - : _M_nodes(__nodes), _M_h(__h) { } - _ReuseOrAllocNode(const _ReuseOrAllocNode&) = delete; - - ~_ReuseOrAllocNode() - { _M_h._M_deallocate_nodes(_M_nodes); } - - template - __node_type* - operator()(_Arg&& __arg) const - { - if (_M_nodes) - { - __node_type* __node = _M_nodes; - _M_nodes = _M_nodes->_M_next(); - __node->_M_nxt = nullptr; - auto& __a = _M_h._M_node_allocator(); - __node_alloc_traits::destroy(__a, __node->_M_valptr()); - __try - { - __node_alloc_traits::construct(__a, __node->_M_valptr(), - std::forward<_Arg>(__arg)); - } - __catch(...) - { - _M_h._M_deallocate_node_ptr(__node); - __throw_exception_again; - } - return __node; - } - return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); - } - - private: - mutable __node_type* _M_nodes; - __hashtable_alloc& _M_h; - }; - - // Functor similar to the previous one but without any pool of nodes to - // recycle. - template - struct _AllocNode - { - private: - using __hashtable_alloc = _Hashtable_alloc<_NodeAlloc>; - using __node_type = typename __hashtable_alloc::__node_type; - - public: - _AllocNode(__hashtable_alloc& __h) - : _M_h(__h) { } - - template - __node_type* - operator()(_Arg&& __arg) const - { return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); } - - private: - __hashtable_alloc& _M_h; - }; - - // Auxiliary types used for all instantiations of _Hashtable nodes - // and iterators. - - /** - * struct _Hashtable_traits - * - * Important traits for hash tables. - * - * @tparam _Cache_hash_code Boolean value. True if the value of - * the hash function is stored along with the value. This is a - * time-space tradeoff. Storing it may improve lookup speed by - * reducing the number of times we need to call the _Hash or _Equal - * functors. - * - * @tparam _Constant_iterators Boolean value. True if iterator and - * const_iterator are both constant iterator types. This is true - * for unordered_set and unordered_multiset, false for - * unordered_map and unordered_multimap. - * - * @tparam _Unique_keys Boolean value. True if the return value - * of _Hashtable::count(k) is always at most one, false if it may - * be an arbitrary number. This is true for unordered_set and - * unordered_map, false for unordered_multiset and - * unordered_multimap. - */ - template - struct _Hashtable_traits - { - using __hash_cached = __bool_constant<_Cache_hash_code>; - using __constant_iterators = __bool_constant<_Constant_iterators>; - using __unique_keys = __bool_constant<_Unique_keys>; - }; - - /** - * struct _Hash_node_base - * - * Nodes, used to wrap elements stored in the hash table. A policy - * template parameter of class template _Hashtable controls whether - * nodes also store a hash code. In some cases (e.g. strings) this - * may be a performance win. - */ - struct _Hash_node_base - { - _Hash_node_base* _M_nxt; - - _Hash_node_base() noexcept : _M_nxt() { } - - _Hash_node_base(_Hash_node_base* __next) noexcept : _M_nxt(__next) { } - }; - - /** - * struct _Hash_node_value_base - * - * Node type with the value to store. - */ - template - struct _Hash_node_value_base : _Hash_node_base - { - typedef _Value value_type; - - __gnu_cxx::__aligned_buffer<_Value> _M_storage; - - _Value* - _M_valptr() noexcept - { return _M_storage._M_ptr(); } - - const _Value* - _M_valptr() const noexcept - { return _M_storage._M_ptr(); } - - _Value& - _M_v() noexcept - { return *_M_valptr(); } - - const _Value& - _M_v() const noexcept - { return *_M_valptr(); } - }; - - /** - * Primary template struct _Hash_node. - */ - template - struct _Hash_node; - - /** - * Specialization for nodes with caches, struct _Hash_node. - * - * Base class is __detail::_Hash_node_value_base. - */ - template - struct _Hash_node<_Value, true> : _Hash_node_value_base<_Value> - { - std::size_t _M_hash_code; - - _Hash_node* - _M_next() const noexcept - { return static_cast<_Hash_node*>(this->_M_nxt); } - }; - - /** - * Specialization for nodes without caches, struct _Hash_node. - * - * Base class is __detail::_Hash_node_value_base. - */ - template - struct _Hash_node<_Value, false> : _Hash_node_value_base<_Value> - { - _Hash_node* - _M_next() const noexcept - { return static_cast<_Hash_node*>(this->_M_nxt); } - }; - - /// Base class for node iterators. - template - struct _Node_iterator_base - { - using __node_type = _Hash_node<_Value, _Cache_hash_code>; - - __node_type* _M_cur; - - _Node_iterator_base(__node_type* __p) noexcept - : _M_cur(__p) { } - - void - _M_incr() noexcept - { _M_cur = _M_cur->_M_next(); } - }; - - template - inline bool - operator==(const _Node_iterator_base<_Value, _Cache_hash_code>& __x, - const _Node_iterator_base<_Value, _Cache_hash_code >& __y) - noexcept - { return __x._M_cur == __y._M_cur; } - - template - inline bool - operator!=(const _Node_iterator_base<_Value, _Cache_hash_code>& __x, - const _Node_iterator_base<_Value, _Cache_hash_code>& __y) - noexcept - { return __x._M_cur != __y._M_cur; } - - /// Node iterators, used to iterate through all the hashtable. - template - struct _Node_iterator - : public _Node_iterator_base<_Value, __cache> - { - private: - using __base_type = _Node_iterator_base<_Value, __cache>; - using __node_type = typename __base_type::__node_type; - - public: - typedef _Value value_type; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - using pointer = typename std::conditional<__constant_iterators, - const _Value*, _Value*>::type; - - using reference = typename std::conditional<__constant_iterators, - const _Value&, _Value&>::type; - - _Node_iterator() noexcept - : __base_type(0) { } - - explicit - _Node_iterator(__node_type* __p) noexcept - : __base_type(__p) { } - - reference - operator*() const noexcept - { return this->_M_cur->_M_v(); } - - pointer - operator->() const noexcept - { return this->_M_cur->_M_valptr(); } - - _Node_iterator& - operator++() noexcept - { - this->_M_incr(); - return *this; - } - - _Node_iterator - operator++(int) noexcept - { - _Node_iterator __tmp(*this); - this->_M_incr(); - return __tmp; - } - }; - - /// Node const_iterators, used to iterate through all the hashtable. - template - struct _Node_const_iterator - : public _Node_iterator_base<_Value, __cache> - { - private: - using __base_type = _Node_iterator_base<_Value, __cache>; - using __node_type = typename __base_type::__node_type; - - public: - typedef _Value value_type; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - typedef const _Value* pointer; - typedef const _Value& reference; - - _Node_const_iterator() noexcept - : __base_type(0) { } - - explicit - _Node_const_iterator(__node_type* __p) noexcept - : __base_type(__p) { } - - _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators, - __cache>& __x) noexcept - : __base_type(__x._M_cur) { } - - reference - operator*() const noexcept - { return this->_M_cur->_M_v(); } - - pointer - operator->() const noexcept - { return this->_M_cur->_M_valptr(); } - - _Node_const_iterator& - operator++() noexcept - { - this->_M_incr(); - return *this; - } - - _Node_const_iterator - operator++(int) noexcept - { - _Node_const_iterator __tmp(*this); - this->_M_incr(); - return __tmp; - } - }; - - // Many of class template _Hashtable's template parameters are policy - // classes. These are defaults for the policies. - - /// Default range hashing function: use division to fold a large number - /// into the range [0, N). - struct _Mod_range_hashing - { - typedef std::size_t first_argument_type; - typedef std::size_t second_argument_type; - typedef std::size_t result_type; - - result_type - operator()(first_argument_type __num, - second_argument_type __den) const noexcept - { return __num % __den; } - }; - - /// Default ranged hash function H. In principle it should be a - /// function object composed from objects of type H1 and H2 such that - /// h(k, N) = h2(h1(k), N), but that would mean making extra copies of - /// h1 and h2. So instead we'll just use a tag to tell class template - /// hashtable to do that composition. - struct _Default_ranged_hash { }; - - /// Default value for rehash policy. Bucket size is (usually) the - /// smallest prime that keeps the load factor small enough. - struct _Prime_rehash_policy - { - using __has_load_factor = true_type; - - _Prime_rehash_policy(float __z = 1.0) noexcept - : _M_max_load_factor(__z), _M_next_resize(0) { } - - float - max_load_factor() const noexcept - { return _M_max_load_factor; } - - // Return a bucket size no smaller than n. - std::size_t - _M_next_bkt(std::size_t __n) const; - - // Return a bucket count appropriate for n elements - std::size_t - _M_bkt_for_elements(std::size_t __n) const - { return __builtin_ceill(__n / (long double)_M_max_load_factor); } - - // __n_bkt is current bucket count, __n_elt is current element count, - // and __n_ins is number of elements to be inserted. Do we need to - // increase bucket count? If so, return make_pair(true, n), where n - // is the new bucket count. If not, return make_pair(false, 0). - std::pair - _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, - std::size_t __n_ins) const; - - typedef std::size_t _State; - - _State - _M_state() const - { return _M_next_resize; } - - void - _M_reset() noexcept - { _M_next_resize = 0; } - - void - _M_reset(_State __state) - { _M_next_resize = __state; } - - static const std::size_t _S_growth_factor = 2; - - float _M_max_load_factor; - mutable std::size_t _M_next_resize; - }; - - /// Range hashing function assuming that second arg is a power of 2. - struct _Mask_range_hashing - { - typedef std::size_t first_argument_type; - typedef std::size_t second_argument_type; - typedef std::size_t result_type; - - result_type - operator()(first_argument_type __num, - second_argument_type __den) const noexcept - { return __num & (__den - 1); } - }; - - /// Compute closest power of 2 not less than __n - inline std::size_t - __clp2(std::size_t __n) noexcept - { - // Equivalent to return __n ? std::bit_ceil(__n) : 0; - if (__n < 2) - return __n; - const unsigned __lz = sizeof(size_t) > sizeof(long) - ? __builtin_clzll(__n - 1ull) - : __builtin_clzl(__n - 1ul); - // Doing two shifts avoids undefined behaviour when __lz == 0. - return (size_t(1) << (numeric_limits::digits - __lz - 1)) << 1; - } - - /// Rehash policy providing power of 2 bucket numbers. Avoids modulo - /// operations. - struct _Power2_rehash_policy - { - using __has_load_factor = true_type; - - _Power2_rehash_policy(float __z = 1.0) noexcept - : _M_max_load_factor(__z), _M_next_resize(0) { } - - float - max_load_factor() const noexcept - { return _M_max_load_factor; } - - // Return a bucket size no smaller than n (as long as n is not above the - // highest power of 2). - std::size_t - _M_next_bkt(std::size_t __n) noexcept - { - if (__n == 0) - // Special case on container 1st initialization with 0 bucket count - // hint. We keep _M_next_resize to 0 to make sure that next time we - // want to add an element allocation will take place. - return 1; - - const auto __max_width = std::min(sizeof(size_t), 8); - const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1); - std::size_t __res = __clp2(__n); - - if (__res == 0) - __res = __max_bkt; - else if (__res == 1) - // If __res is 1 we force it to 2 to make sure there will be an - // allocation so that nothing need to be stored in the initial - // single bucket - __res = 2; - - if (__res == __max_bkt) - // Set next resize to the max value so that we never try to rehash again - // as we already reach the biggest possible bucket number. - // Note that it might result in max_load_factor not being respected. - _M_next_resize = numeric_limits::max(); - else - _M_next_resize - = __builtin_floorl(__res * (long double)_M_max_load_factor); - - return __res; - } - - // Return a bucket count appropriate for n elements - std::size_t - _M_bkt_for_elements(std::size_t __n) const noexcept - { return __builtin_ceill(__n / (long double)_M_max_load_factor); } - - // __n_bkt is current bucket count, __n_elt is current element count, - // and __n_ins is number of elements to be inserted. Do we need to - // increase bucket count? If so, return make_pair(true, n), where n - // is the new bucket count. If not, return make_pair(false, 0). - std::pair - _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, - std::size_t __n_ins) noexcept - { - if (__n_elt + __n_ins > _M_next_resize) - { - // If _M_next_resize is 0 it means that we have nothing allocated so - // far and that we start inserting elements. In this case we start - // with an initial bucket size of 11. - long double __min_bkts - = std::max(__n_elt + __n_ins, _M_next_resize ? 0 : 11) - / (long double)_M_max_load_factor; - if (__min_bkts >= __n_bkt) - return { true, - _M_next_bkt(std::max(__builtin_floorl(__min_bkts) + 1, - __n_bkt * _S_growth_factor)) }; - - _M_next_resize - = __builtin_floorl(__n_bkt * (long double)_M_max_load_factor); - return { false, 0 }; - } - else - return { false, 0 }; - } - - typedef std::size_t _State; - - _State - _M_state() const noexcept - { return _M_next_resize; } - - void - _M_reset() noexcept - { _M_next_resize = 0; } - - void - _M_reset(_State __state) noexcept - { _M_next_resize = __state; } - - static const std::size_t _S_growth_factor = 2; - - float _M_max_load_factor; - std::size_t _M_next_resize; - }; - - // Base classes for std::_Hashtable. We define these base classes - // because in some cases we want to do different things depending on - // the value of a policy class. In some cases the policy class - // affects which member functions and nested typedefs are defined; - // we handle that by specializing base class templates. Several of - // the base class templates need to access other members of class - // template _Hashtable, so we use a variant of the "Curiously - // Recurring Template Pattern" (CRTP) technique. - - /** - * Primary class template _Map_base. - * - * If the hashtable has a value type of the form pair and a - * key extraction policy (_ExtractKey) that returns the first part - * of the pair, the hashtable gets a mapped_type typedef. If it - * satisfies those criteria and also has unique keys, then it also - * gets an operator[]. - */ - template - struct _Map_base { }; - - /// Partial specialization, __unique_keys set to false. - template - struct _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, false> - { - using mapped_type = typename std::tuple_element<1, _Pair>::type; - }; - - /// Partial specialization, __unique_keys set to true. - template - struct _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, true> - { - private: - using __hashtable_base = __detail::_Hashtable_base<_Key, _Pair, - _Select1st, - _Equal, _H1, _H2, _Hash, - _Traits>; - - using __hashtable = _Hashtable<_Key, _Pair, _Alloc, - _Select1st, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>; - - using __hash_code = typename __hashtable_base::__hash_code; - using __node_type = typename __hashtable_base::__node_type; - - public: - using key_type = typename __hashtable_base::key_type; - using iterator = typename __hashtable_base::iterator; - using mapped_type = typename std::tuple_element<1, _Pair>::type; - - mapped_type& - operator[](const key_type& __k); - - mapped_type& - operator[](key_type&& __k); - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 761. unordered_map needs an at() member function. - mapped_type& - at(const key_type& __k); - - const mapped_type& - at(const key_type& __k) const; - }; - - template - auto - _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: - operator[](const key_type& __k) - -> mapped_type& - { - __hashtable* __h = static_cast<__hashtable*>(this); - __hash_code __code = __h->_M_hash_code(__k); - std::size_t __bkt = __h->_M_bucket_index(__k, __code); - if (__node_type* __node = __h->_M_find_node(__bkt, __k, __code)) - return __node->_M_v().second; - - typename __hashtable::_Scoped_node __node { - __h, - std::piecewise_construct, - std::tuple(__k), - std::tuple<>() - }; - auto __pos - = __h->_M_insert_unique_node(__k, __bkt, __code, __node._M_node); - __node._M_node = nullptr; - return __pos->second; - } - - template - auto - _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: - operator[](key_type&& __k) - -> mapped_type& - { - __hashtable* __h = static_cast<__hashtable*>(this); - __hash_code __code = __h->_M_hash_code(__k); - std::size_t __bkt = __h->_M_bucket_index(__k, __code); - if (__node_type* __node = __h->_M_find_node(__bkt, __k, __code)) - return __node->_M_v().second; - - typename __hashtable::_Scoped_node __node { - __h, - std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::tuple<>() - }; - auto __pos - = __h->_M_insert_unique_node(__k, __bkt, __code, __node._M_node); - __node._M_node = nullptr; - return __pos->second; - } - - template - auto - _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: - at(const key_type& __k) - -> mapped_type& - { - __hashtable* __h = static_cast<__hashtable*>(this); - __hash_code __code = __h->_M_hash_code(__k); - std::size_t __bkt = __h->_M_bucket_index(__k, __code); - __node_type* __p = __h->_M_find_node(__bkt, __k, __code); - - if (!__p) - __throw_out_of_range(__N("_Map_base::at")); - return __p->_M_v().second; - } - - template - auto - _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: - at(const key_type& __k) const - -> const mapped_type& - { - const __hashtable* __h = static_cast(this); - __hash_code __code = __h->_M_hash_code(__k); - std::size_t __bkt = __h->_M_bucket_index(__k, __code); - __node_type* __p = __h->_M_find_node(__bkt, __k, __code); - - if (!__p) - __throw_out_of_range(__N("_Map_base::at")); - return __p->_M_v().second; - } - - /** - * Primary class template _Insert_base. - * - * Defines @c insert member functions appropriate to all _Hashtables. - */ - template - struct _Insert_base - { - protected: - using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>; - - using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _Traits>; - - using value_type = typename __hashtable_base::value_type; - using iterator = typename __hashtable_base::iterator; - using const_iterator = typename __hashtable_base::const_iterator; - using size_type = typename __hashtable_base::size_type; - - using __unique_keys = typename __hashtable_base::__unique_keys; - using __ireturn_type = typename __hashtable_base::__ireturn_type; - using __node_type = _Hash_node<_Value, _Traits::__hash_cached::value>; - using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>; - using __node_gen_type = _AllocNode<__node_alloc_type>; - - __hashtable& - _M_conjure_hashtable() - { return *(static_cast<__hashtable*>(this)); } - - template - void - _M_insert_range(_InputIterator __first, _InputIterator __last, - const _NodeGetter&, true_type); - - template - void - _M_insert_range(_InputIterator __first, _InputIterator __last, - const _NodeGetter&, false_type); - - public: - __ireturn_type - insert(const value_type& __v) - { - __hashtable& __h = _M_conjure_hashtable(); - __node_gen_type __node_gen(__h); - return __h._M_insert(__v, __node_gen, __unique_keys()); - } - - iterator - insert(const_iterator __hint, const value_type& __v) - { - __hashtable& __h = _M_conjure_hashtable(); - __node_gen_type __node_gen(__h); - return __h._M_insert(__hint, __v, __node_gen, __unique_keys()); - } - - void - insert(initializer_list __l) - { this->insert(__l.begin(), __l.end()); } - - template - void - insert(_InputIterator __first, _InputIterator __last) - { - __hashtable& __h = _M_conjure_hashtable(); - __node_gen_type __node_gen(__h); - return _M_insert_range(__first, __last, __node_gen, __unique_keys()); - } - }; - - template - template - void - _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>:: - _M_insert_range(_InputIterator __first, _InputIterator __last, - const _NodeGetter& __node_gen, true_type) - { - size_type __n_elt = __detail::__distance_fw(__first, __last); - if (__n_elt == 0) - return; - - __hashtable& __h = _M_conjure_hashtable(); - for (; __first != __last; ++__first) - { - if (__h._M_insert(*__first, __node_gen, __unique_keys(), - __n_elt).second) - __n_elt = 1; - else if (__n_elt != 1) - --__n_elt; - } - } - - template - template - void - _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>:: - _M_insert_range(_InputIterator __first, _InputIterator __last, - const _NodeGetter& __node_gen, false_type) - { - using __rehash_type = typename __hashtable::__rehash_type; - using __rehash_state = typename __hashtable::__rehash_state; - using pair_type = std::pair; - - size_type __n_elt = __detail::__distance_fw(__first, __last); - if (__n_elt == 0) - return; - - __hashtable& __h = _M_conjure_hashtable(); - __rehash_type& __rehash = __h._M_rehash_policy; - const __rehash_state& __saved_state = __rehash._M_state(); - pair_type __do_rehash = __rehash._M_need_rehash(__h._M_bucket_count, - __h._M_element_count, - __n_elt); - - if (__do_rehash.first) - __h._M_rehash(__do_rehash.second, __saved_state); - - for (; __first != __last; ++__first) - __h._M_insert(*__first, __node_gen, __unique_keys()); - } - - /** - * Primary class template _Insert. - * - * Defines @c insert member functions that depend on _Hashtable policies, - * via partial specializations. - */ - template - struct _Insert; - - /// Specialization. - template - struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits, true> - : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits> - { - using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>; - - using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _Traits>; - - using value_type = typename __base_type::value_type; - using iterator = typename __base_type::iterator; - using const_iterator = typename __base_type::const_iterator; - - using __unique_keys = typename __base_type::__unique_keys; - using __ireturn_type = typename __hashtable_base::__ireturn_type; - using __hashtable = typename __base_type::__hashtable; - using __node_gen_type = typename __base_type::__node_gen_type; - - using __base_type::insert; - - __ireturn_type - insert(value_type&& __v) - { - __hashtable& __h = this->_M_conjure_hashtable(); - __node_gen_type __node_gen(__h); - return __h._M_insert(std::move(__v), __node_gen, __unique_keys()); - } - - iterator - insert(const_iterator __hint, value_type&& __v) - { - __hashtable& __h = this->_M_conjure_hashtable(); - __node_gen_type __node_gen(__h); - return __h._M_insert(__hint, std::move(__v), __node_gen, - __unique_keys()); - } - }; - - /// Specialization. - template - struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits, false> - : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits> - { - using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>; - using value_type = typename __base_type::value_type; - using iterator = typename __base_type::iterator; - using const_iterator = typename __base_type::const_iterator; - - using __unique_keys = typename __base_type::__unique_keys; - using __hashtable = typename __base_type::__hashtable; - using __ireturn_type = typename __base_type::__ireturn_type; - - using __base_type::insert; - - template - using __is_cons = std::is_constructible; - - template - using _IFcons = std::enable_if<__is_cons<_Pair>::value>; - - template - using _IFconsp = typename _IFcons<_Pair>::type; - - template> - __ireturn_type - insert(_Pair&& __v) - { - __hashtable& __h = this->_M_conjure_hashtable(); - return __h._M_emplace(__unique_keys(), std::forward<_Pair>(__v)); - } - - template> - iterator - insert(const_iterator __hint, _Pair&& __v) - { - __hashtable& __h = this->_M_conjure_hashtable(); - return __h._M_emplace(__hint, __unique_keys(), - std::forward<_Pair>(__v)); - } - }; - - template - using __has_load_factor = typename _Policy::__has_load_factor; - - /** - * Primary class template _Rehash_base. - * - * Give hashtable the max_load_factor functions and reserve iff the - * rehash policy supports it. - */ - template> - struct _Rehash_base; - - /// Specialization when rehash policy doesn't provide load factor management. - template - struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, - false_type> - { - }; - - /// Specialization when rehash policy provide load factor management. - template - struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, - true_type> - { - using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, - _Equal, _H1, _H2, _Hash, - _RehashPolicy, _Traits>; - - float - max_load_factor() const noexcept - { - const __hashtable* __this = static_cast(this); - return __this->__rehash_policy().max_load_factor(); - } - - void - max_load_factor(float __z) - { - __hashtable* __this = static_cast<__hashtable*>(this); - __this->__rehash_policy(_RehashPolicy(__z)); - } - - void - reserve(std::size_t __n) - { - __hashtable* __this = static_cast<__hashtable*>(this); - __this->rehash(__this->__rehash_policy()._M_bkt_for_elements(__n)); - } - }; - - /** - * Primary class template _Hashtable_ebo_helper. - * - * Helper class using EBO when it is not forbidden (the type is not - * final) and when it is worth it (the type is empty.) - */ - template - struct _Hashtable_ebo_helper; - - /// Specialization using EBO. - template - struct _Hashtable_ebo_helper<_Nm, _Tp, true> - : private _Tp - { - _Hashtable_ebo_helper() = default; - - template - _Hashtable_ebo_helper(_OtherTp&& __tp) - : _Tp(std::forward<_OtherTp>(__tp)) - { } - - const _Tp& _M_cget() const { return static_cast(*this); } - _Tp& _M_get() { return static_cast<_Tp&>(*this); } - }; - - /// Specialization not using EBO. - template - struct _Hashtable_ebo_helper<_Nm, _Tp, false> - { - _Hashtable_ebo_helper() = default; - - template - _Hashtable_ebo_helper(_OtherTp&& __tp) - : _M_tp(std::forward<_OtherTp>(__tp)) - { } - - const _Tp& _M_cget() const { return _M_tp; } - _Tp& _M_get() { return _M_tp; } - - private: - _Tp _M_tp; - }; - - /** - * Primary class template _Local_iterator_base. - * - * Base class for local iterators, used to iterate within a bucket - * but not between buckets. - */ - template - struct _Local_iterator_base; - - /** - * Primary class template _Hash_code_base. - * - * Encapsulates two policy issues that aren't quite orthogonal. - * (1) the difference between using a ranged hash function and using - * the combination of a hash function and a range-hashing function. - * In the former case we don't have such things as hash codes, so - * we have a dummy type as placeholder. - * (2) Whether or not we cache hash codes. Caching hash codes is - * meaningless if we have a ranged hash function. - * - * We also put the key extraction objects here, for convenience. - * Each specialization derives from one or more of the template - * parameters to benefit from Ebo. This is important as this type - * is inherited in some cases by the _Local_iterator_base type used - * to implement local_iterator and const_local_iterator. As with - * any iterator type we prefer to make it as small as possible. - * - * Primary template is unused except as a hook for specializations. - */ - template - struct _Hash_code_base; - - /// Specialization: ranged hash function, no caching hash codes. H1 - /// and H2 are provided but ignored. We define a dummy hash code type. - template - struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, false> - : private _Hashtable_ebo_helper<0, _ExtractKey>, - private _Hashtable_ebo_helper<1, _Hash> - { - private: - using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; - using __ebo_hash = _Hashtable_ebo_helper<1, _Hash>; - - protected: - typedef void* __hash_code; - typedef _Hash_node<_Value, false> __node_type; - - // We need the default constructor for the local iterators and _Hashtable - // default constructor. - _Hash_code_base() = default; - - _Hash_code_base(const _ExtractKey& __ex, const _H1&, const _H2&, - const _Hash& __h) - : __ebo_extract_key(__ex), __ebo_hash(__h) { } - - __hash_code - _M_hash_code(const _Key& __key) const - { return 0; } - - std::size_t - _M_bucket_index(const _Key& __k, __hash_code, - std::size_t __bkt_count) const - { return _M_ranged_hash()(__k, __bkt_count); } - - std::size_t - _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const - noexcept( noexcept(declval()(declval(), - (std::size_t)0)) ) - { return _M_ranged_hash()(_M_extract()(__p->_M_v()), __bkt_count); } - - void - _M_store_code(__node_type*, __hash_code) const - { } - - void - _M_copy_code(__node_type*, const __node_type*) const - { } - - void - _M_swap(_Hash_code_base& __x) - { - std::swap(__ebo_extract_key::_M_get(), - __x.__ebo_extract_key::_M_get()); - std::swap(__ebo_hash::_M_get(), __x.__ebo_hash::_M_get()); - } - - const _ExtractKey& - _M_extract() const { return __ebo_extract_key::_M_cget(); } - - const _Hash& - _M_ranged_hash() const { return __ebo_hash::_M_cget(); } - }; - - // No specialization for ranged hash function while caching hash codes. - // That combination is meaningless, and trying to do it is an error. - - /// Specialization: ranged hash function, cache hash codes. This - /// combination is meaningless, so we provide only a declaration - /// and no definition. - template - struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, true>; - - /// Specialization: hash function and range-hashing function, no - /// caching of hash codes. - /// Provides typedef and accessor required by C++ 11. - template - struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, - _Default_ranged_hash, false> - : private _Hashtable_ebo_helper<0, _ExtractKey>, - private _Hashtable_ebo_helper<1, _H1>, - private _Hashtable_ebo_helper<2, _H2> - { - private: - using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; - using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>; - using __ebo_h2 = _Hashtable_ebo_helper<2, _H2>; - - // Gives the local iterator implementation access to _M_bucket_index(). - friend struct _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, - _Default_ranged_hash, false>; - - public: - typedef _H1 hasher; - - hasher - hash_function() const - { return _M_h1(); } - - protected: - typedef std::size_t __hash_code; - typedef _Hash_node<_Value, false> __node_type; - - // We need the default constructor for the local iterators and _Hashtable - // default constructor. - _Hash_code_base() = default; - - _Hash_code_base(const _ExtractKey& __ex, - const _H1& __h1, const _H2& __h2, - const _Default_ranged_hash&) - : __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { } - - __hash_code - _M_hash_code(const _Key& __k) const - { - static_assert(__is_invocable{}, - "hash function must be invocable with an argument of key type"); - return _M_h1()(__k); - } - - std::size_t - _M_bucket_index(const _Key&, __hash_code __c, - std::size_t __bkt_count) const - { return _M_h2()(__c, __bkt_count); } - - std::size_t - _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const - noexcept( noexcept(declval()(declval())) - && noexcept(declval()((__hash_code)0, - (std::size_t)0)) ) - { return _M_h2()(_M_h1()(_M_extract()(__p->_M_v())), __bkt_count); } - - void - _M_store_code(__node_type*, __hash_code) const - { } - - void - _M_copy_code(__node_type*, const __node_type*) const - { } - - void - _M_swap(_Hash_code_base& __x) - { - std::swap(__ebo_extract_key::_M_get(), - __x.__ebo_extract_key::_M_get()); - std::swap(__ebo_h1::_M_get(), __x.__ebo_h1::_M_get()); - std::swap(__ebo_h2::_M_get(), __x.__ebo_h2::_M_get()); - } - - const _ExtractKey& - _M_extract() const { return __ebo_extract_key::_M_cget(); } - - const _H1& - _M_h1() const { return __ebo_h1::_M_cget(); } - - const _H2& - _M_h2() const { return __ebo_h2::_M_cget(); } - }; - - /// Specialization: hash function and range-hashing function, - /// caching hash codes. H is provided but ignored. Provides - /// typedef and accessor required by C++ 11. - template - struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, - _Default_ranged_hash, true> - : private _Hashtable_ebo_helper<0, _ExtractKey>, - private _Hashtable_ebo_helper<1, _H1>, - private _Hashtable_ebo_helper<2, _H2> - { - private: - // Gives the local iterator implementation access to _M_h2(). - friend struct _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, - _Default_ranged_hash, true>; - - using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; - using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>; - using __ebo_h2 = _Hashtable_ebo_helper<2, _H2>; - - public: - typedef _H1 hasher; - - hasher - hash_function() const - { return _M_h1(); } - - protected: - typedef std::size_t __hash_code; - typedef _Hash_node<_Value, true> __node_type; - - // We need the default constructor for _Hashtable default constructor. - _Hash_code_base() = default; - _Hash_code_base(const _ExtractKey& __ex, - const _H1& __h1, const _H2& __h2, - const _Default_ranged_hash&) - : __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { } - - __hash_code - _M_hash_code(const _Key& __k) const - { - static_assert(__is_invocable{}, - "hash function must be invocable with an argument of key type"); - return _M_h1()(__k); - } - - std::size_t - _M_bucket_index(const _Key&, __hash_code __c, - std::size_t __bkt_count) const - { return _M_h2()(__c, __bkt_count); } - - std::size_t - _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const - noexcept( noexcept(declval()((__hash_code)0, - (std::size_t)0)) ) - { return _M_h2()(__p->_M_hash_code, __bkt_count); } - - void - _M_store_code(__node_type* __n, __hash_code __c) const - { __n->_M_hash_code = __c; } - - void - _M_copy_code(__node_type* __to, const __node_type* __from) const - { __to->_M_hash_code = __from->_M_hash_code; } - - void - _M_swap(_Hash_code_base& __x) - { - std::swap(__ebo_extract_key::_M_get(), - __x.__ebo_extract_key::_M_get()); - std::swap(__ebo_h1::_M_get(), __x.__ebo_h1::_M_get()); - std::swap(__ebo_h2::_M_get(), __x.__ebo_h2::_M_get()); - } - - const _ExtractKey& - _M_extract() const { return __ebo_extract_key::_M_cget(); } - - const _H1& - _M_h1() const { return __ebo_h1::_M_cget(); } - - const _H2& - _M_h2() const { return __ebo_h2::_M_cget(); } - }; - - /// Partial specialization used when nodes contain a cached hash code. - template - struct _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, true> - : private _Hashtable_ebo_helper<0, _H2> - { - protected: - using __base_type = _Hashtable_ebo_helper<0, _H2>; - using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, true>; - - _Local_iterator_base() = default; - _Local_iterator_base(const __hash_code_base& __base, - _Hash_node<_Value, true>* __p, - std::size_t __bkt, std::size_t __bkt_count) - : __base_type(__base._M_h2()), - _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { } - - void - _M_incr() - { - _M_cur = _M_cur->_M_next(); - if (_M_cur) - { - std::size_t __bkt - = __base_type::_M_get()(_M_cur->_M_hash_code, - _M_bucket_count); - if (__bkt != _M_bucket) - _M_cur = nullptr; - } - } - - _Hash_node<_Value, true>* _M_cur; - std::size_t _M_bucket; - std::size_t _M_bucket_count; - - public: - const void* - _M_curr() const { return _M_cur; } // for equality ops - - std::size_t - _M_get_bucket() const { return _M_bucket; } // for debug mode - }; - - // Uninitialized storage for a _Hash_code_base. - // This type is DefaultConstructible and Assignable even if the - // _Hash_code_base type isn't, so that _Local_iterator_base<..., false> - // can be DefaultConstructible and Assignable. - template::value> - struct _Hash_code_storage - { - __gnu_cxx::__aligned_buffer<_Tp> _M_storage; - - _Tp* - _M_h() { return _M_storage._M_ptr(); } - - const _Tp* - _M_h() const { return _M_storage._M_ptr(); } - }; - - // Empty partial specialization for empty _Hash_code_base types. - template - struct _Hash_code_storage<_Tp, true> - { - static_assert( std::is_empty<_Tp>::value, "Type must be empty" ); - - // As _Tp is an empty type there will be no bytes written/read through - // the cast pointer, so no strict-aliasing violation. - _Tp* - _M_h() { return reinterpret_cast<_Tp*>(this); } - - const _Tp* - _M_h() const { return reinterpret_cast(this); } - }; - - template - using __hash_code_for_local_iter - = _Hash_code_storage<_Hash_code_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, false>>; - - // Partial specialization used when hash codes are not cached - template - struct _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, false> - : __hash_code_for_local_iter<_Key, _Value, _ExtractKey, _H1, _H2, _Hash> - { - protected: - using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, false>; - - _Local_iterator_base() : _M_bucket_count(-1) { } - - _Local_iterator_base(const __hash_code_base& __base, - _Hash_node<_Value, false>* __p, - std::size_t __bkt, std::size_t __bkt_count) - : _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) - { _M_init(__base); } - - ~_Local_iterator_base() - { - if (_M_bucket_count != -1) - _M_destroy(); - } - - _Local_iterator_base(const _Local_iterator_base& __iter) - : _M_cur(__iter._M_cur), _M_bucket(__iter._M_bucket), - _M_bucket_count(__iter._M_bucket_count) - { - if (_M_bucket_count != -1) - _M_init(*__iter._M_h()); - } - - _Local_iterator_base& - operator=(const _Local_iterator_base& __iter) - { - if (_M_bucket_count != -1) - _M_destroy(); - _M_cur = __iter._M_cur; - _M_bucket = __iter._M_bucket; - _M_bucket_count = __iter._M_bucket_count; - if (_M_bucket_count != -1) - _M_init(*__iter._M_h()); - return *this; - } - - void - _M_incr() - { - _M_cur = _M_cur->_M_next(); - if (_M_cur) - { - std::size_t __bkt = this->_M_h()->_M_bucket_index(_M_cur, - _M_bucket_count); - if (__bkt != _M_bucket) - _M_cur = nullptr; - } - } - - _Hash_node<_Value, false>* _M_cur; - std::size_t _M_bucket; - std::size_t _M_bucket_count; - - void - _M_init(const __hash_code_base& __base) - { ::new(this->_M_h()) __hash_code_base(__base); } - - void - _M_destroy() { this->_M_h()->~__hash_code_base(); } - - public: - const void* - _M_curr() const { return _M_cur; } // for equality ops and debug mode - - std::size_t - _M_get_bucket() const { return _M_bucket; } // for debug mode - }; - - template - inline bool - operator==(const _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, __cache>& __x, - const _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, __cache>& __y) - { return __x._M_curr() == __y._M_curr(); } - - template - inline bool - operator!=(const _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, __cache>& __x, - const _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, __cache>& __y) - { return __x._M_curr() != __y._M_curr(); } - - /// local iterators - template - struct _Local_iterator - : public _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, __cache> - { - private: - using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, __cache>; - using __hash_code_base = typename __base_type::__hash_code_base; - public: - typedef _Value value_type; - typedef typename std::conditional<__constant_iterators, - const _Value*, _Value*>::type - pointer; - typedef typename std::conditional<__constant_iterators, - const _Value&, _Value&>::type - reference; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - _Local_iterator() = default; - - _Local_iterator(const __hash_code_base& __base, - _Hash_node<_Value, __cache>* __n, - std::size_t __bkt, std::size_t __bkt_count) - : __base_type(__base, __n, __bkt, __bkt_count) - { } - - reference - operator*() const - { return this->_M_cur->_M_v(); } - - pointer - operator->() const - { return this->_M_cur->_M_valptr(); } - - _Local_iterator& - operator++() - { - this->_M_incr(); - return *this; - } - - _Local_iterator - operator++(int) - { - _Local_iterator __tmp(*this); - this->_M_incr(); - return __tmp; - } - }; - - /// local const_iterators - template - struct _Local_const_iterator - : public _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, __cache> - { - private: - using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, __cache>; - using __hash_code_base = typename __base_type::__hash_code_base; - - public: - typedef _Value value_type; - typedef const _Value* pointer; - typedef const _Value& reference; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - _Local_const_iterator() = default; - - _Local_const_iterator(const __hash_code_base& __base, - _Hash_node<_Value, __cache>* __n, - std::size_t __bkt, std::size_t __bkt_count) - : __base_type(__base, __n, __bkt, __bkt_count) - { } - - _Local_const_iterator(const _Local_iterator<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, - __constant_iterators, - __cache>& __x) - : __base_type(__x) - { } - - reference - operator*() const - { return this->_M_cur->_M_v(); } - - pointer - operator->() const - { return this->_M_cur->_M_valptr(); } - - _Local_const_iterator& - operator++() - { - this->_M_incr(); - return *this; - } - - _Local_const_iterator - operator++(int) - { - _Local_const_iterator __tmp(*this); - this->_M_incr(); - return __tmp; - } - }; - - /** - * Primary class template _Hashtable_base. - * - * Helper class adding management of _Equal functor to - * _Hash_code_base type. - * - * Base class templates are: - * - __detail::_Hash_code_base - * - __detail::_Hashtable_ebo_helper - */ - template - struct _Hashtable_base - : public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, - _Traits::__hash_cached::value>, - private _Hashtable_ebo_helper<0, _Equal> - { - public: - typedef _Key key_type; - typedef _Value value_type; - typedef _Equal key_equal; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - - using __traits_type = _Traits; - using __hash_cached = typename __traits_type::__hash_cached; - using __constant_iterators = typename __traits_type::__constant_iterators; - using __unique_keys = typename __traits_type::__unique_keys; - - using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, - _H1, _H2, _Hash, - __hash_cached::value>; - - using __hash_code = typename __hash_code_base::__hash_code; - using __node_type = typename __hash_code_base::__node_type; - - using iterator = __detail::_Node_iterator; - - using const_iterator = __detail::_Node_const_iterator; - - using local_iterator = __detail::_Local_iterator; - - using const_local_iterator = __detail::_Local_const_iterator; - - using __ireturn_type = typename std::conditional<__unique_keys::value, - std::pair, - iterator>::type; - private: - using _EqualEBO = _Hashtable_ebo_helper<0, _Equal>; - - template - struct _Equal_hash_code - { - static bool - _S_equals(__hash_code, const _NodeT&) - { return true; } - }; - - template - struct _Equal_hash_code<_Hash_node<_Ptr2, true>> - { - static bool - _S_equals(__hash_code __c, const _Hash_node<_Ptr2, true>& __n) - { return __c == __n._M_hash_code; } - }; - - protected: - _Hashtable_base() = default; - _Hashtable_base(const _ExtractKey& __ex, const _H1& __h1, const _H2& __h2, - const _Hash& __hash, const _Equal& __eq) - : __hash_code_base(__ex, __h1, __h2, __hash), _EqualEBO(__eq) - { } - - bool - _M_equals(const _Key& __k, __hash_code __c, __node_type* __n) const - { - static_assert(__is_invocable{}, - "key equality predicate must be invocable with two arguments of " - "key type"); - return _Equal_hash_code<__node_type>::_S_equals(__c, *__n) - && _M_eq()(__k, this->_M_extract()(__n->_M_v())); - } - - void - _M_swap(_Hashtable_base& __x) - { - __hash_code_base::_M_swap(__x); - std::swap(_EqualEBO::_M_get(), __x._EqualEBO::_M_get()); - } - - const _Equal& - _M_eq() const { return _EqualEBO::_M_cget(); } - }; - - /** - * Primary class template _Equality. - * - * This is for implementing equality comparison for unordered - * containers, per N3068, by John Lakos and Pablo Halpern. - * Algorithmically, we follow closely the reference implementations - * therein. - */ - template - struct _Equality; - - /// unordered_map and unordered_set specializations. - template - struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, true> - { - using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>; - - bool - _M_equal(const __hashtable&) const; - }; - - template - bool - _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: - _M_equal(const __hashtable& __other) const - { - using __node_base = typename __hashtable::__node_base; - using __node_type = typename __hashtable::__node_type; - const __hashtable* __this = static_cast(this); - if (__this->size() != __other.size()) - return false; - - for (auto __itx = __this->begin(); __itx != __this->end(); ++__itx) - { - std::size_t __ybkt = __other._M_bucket_index(__itx._M_cur); - __node_base* __prev_n = __other._M_buckets[__ybkt]; - if (!__prev_n) - return false; - - for (__node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);; - __n = __n->_M_next()) - { - if (__n->_M_v() == *__itx) - break; - - if (!__n->_M_nxt - || __other._M_bucket_index(__n->_M_next()) != __ybkt) - return false; - } - } - - return true; - } - - /// unordered_multiset and unordered_multimap specializations. - template - struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, false> - { - using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits>; - - bool - _M_equal(const __hashtable&) const; - }; - - template - bool - _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, - _H1, _H2, _Hash, _RehashPolicy, _Traits, false>:: - _M_equal(const __hashtable& __other) const - { - using __node_base = typename __hashtable::__node_base; - using __node_type = typename __hashtable::__node_type; - const __hashtable* __this = static_cast(this); - if (__this->size() != __other.size()) - return false; - - for (auto __itx = __this->begin(); __itx != __this->end();) - { - std::size_t __x_count = 1; - auto __itx_end = __itx; - for (++__itx_end; __itx_end != __this->end() - && __this->key_eq()(_ExtractKey()(*__itx), - _ExtractKey()(*__itx_end)); - ++__itx_end) - ++__x_count; - - std::size_t __ybkt = __other._M_bucket_index(__itx._M_cur); - __node_base* __y_prev_n = __other._M_buckets[__ybkt]; - if (!__y_prev_n) - return false; - - __node_type* __y_n = static_cast<__node_type*>(__y_prev_n->_M_nxt); - for (;; __y_n = __y_n->_M_next()) - { - if (__this->key_eq()(_ExtractKey()(__y_n->_M_v()), - _ExtractKey()(*__itx))) - break; - - if (!__y_n->_M_nxt - || __other._M_bucket_index(__y_n->_M_next()) != __ybkt) - return false; - } - - typename __hashtable::const_iterator __ity(__y_n); - for (auto __ity_end = __ity; __ity_end != __other.end(); ++__ity_end) - if (--__x_count == 0) - break; - - if (__x_count != 0) - return false; - - if (!std::is_permutation(__itx, __itx_end, __ity)) - return false; - - __itx = __itx_end; - } - return true; - } - - /** - * This type deals with all allocation and keeps an allocator instance - * through inheritance to benefit from EBO when possible. - */ - template - struct _Hashtable_alloc : private _Hashtable_ebo_helper<0, _NodeAlloc> - { - private: - using __ebo_node_alloc = _Hashtable_ebo_helper<0, _NodeAlloc>; - public: - using __node_type = typename _NodeAlloc::value_type; - using __node_alloc_type = _NodeAlloc; - // Use __gnu_cxx to benefit from _S_always_equal and al. - using __node_alloc_traits = __gnu_cxx::__alloc_traits<__node_alloc_type>; - - using __value_alloc_traits = typename __node_alloc_traits::template - rebind_traits; - - using __node_base = __detail::_Hash_node_base; - using __bucket_type = __node_base*; - using __bucket_alloc_type = - __alloc_rebind<__node_alloc_type, __bucket_type>; - using __bucket_alloc_traits = std::allocator_traits<__bucket_alloc_type>; - - _Hashtable_alloc() = default; - _Hashtable_alloc(const _Hashtable_alloc&) = default; - _Hashtable_alloc(_Hashtable_alloc&&) = default; - - template - _Hashtable_alloc(_Alloc&& __a) - : __ebo_node_alloc(std::forward<_Alloc>(__a)) - { } - - __node_alloc_type& - _M_node_allocator() - { return __ebo_node_alloc::_M_get(); } - - const __node_alloc_type& - _M_node_allocator() const - { return __ebo_node_alloc::_M_cget(); } - - // Allocate a node and construct an element within it. - template - __node_type* - _M_allocate_node(_Args&&... __args); - - // Destroy the element within a node and deallocate the node. - void - _M_deallocate_node(__node_type* __n); - - // Deallocate a node. - void - _M_deallocate_node_ptr(__node_type* __n); - - // Deallocate the linked list of nodes pointed to by __n. - // The elements within the nodes are destroyed. - void - _M_deallocate_nodes(__node_type* __n); - - __bucket_type* - _M_allocate_buckets(std::size_t __bkt_count); - - void - _M_deallocate_buckets(__bucket_type*, std::size_t __bkt_count); - }; - - // Definitions of class template _Hashtable_alloc's out-of-line member - // functions. - template - template - auto - _Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&&... __args) - -> __node_type* - { - auto __nptr = __node_alloc_traits::allocate(_M_node_allocator(), 1); - __node_type* __n = std::__to_address(__nptr); - __try - { - ::new ((void*)__n) __node_type; - __node_alloc_traits::construct(_M_node_allocator(), - __n->_M_valptr(), - std::forward<_Args>(__args)...); - return __n; - } - __catch(...) - { - __node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1); - __throw_exception_again; - } - } - - template - void - _Hashtable_alloc<_NodeAlloc>::_M_deallocate_node(__node_type* __n) - { - __node_alloc_traits::destroy(_M_node_allocator(), __n->_M_valptr()); - _M_deallocate_node_ptr(__n); - } - - template - void - _Hashtable_alloc<_NodeAlloc>::_M_deallocate_node_ptr(__node_type* __n) - { - typedef typename __node_alloc_traits::pointer _Ptr; - auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__n); - __n->~__node_type(); - __node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1); - } - - template - void - _Hashtable_alloc<_NodeAlloc>::_M_deallocate_nodes(__node_type* __n) - { - while (__n) - { - __node_type* __tmp = __n; - __n = __n->_M_next(); - _M_deallocate_node(__tmp); - } - } - - template - typename _Hashtable_alloc<_NodeAlloc>::__bucket_type* - _Hashtable_alloc<_NodeAlloc>::_M_allocate_buckets(std::size_t __bkt_count) - { - __bucket_alloc_type __alloc(_M_node_allocator()); - - auto __ptr = __bucket_alloc_traits::allocate(__alloc, __bkt_count); - __bucket_type* __p = std::__to_address(__ptr); - __builtin_memset(__p, 0, __bkt_count * sizeof(__bucket_type)); - return __p; - } - - template - void - _Hashtable_alloc<_NodeAlloc>::_M_deallocate_buckets(__bucket_type* __bkts, - std::size_t __bkt_count) - { - typedef typename __bucket_alloc_traits::pointer _Ptr; - auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__bkts); - __bucket_alloc_type __alloc(_M_node_allocator()); - __bucket_alloc_traits::deallocate(__alloc, __ptr, __bkt_count); - } - - //@} hashtable-detail -} // namespace __detail -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // _HASHTABLE_POLICY_H diff --git a/resources/sources/avr-libstdcpp/include/bits/indirect_array.h b/resources/sources/avr-libstdcpp/include/bits/indirect_array.h deleted file mode 100644 index 11fac3290..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/indirect_array.h +++ /dev/null @@ -1,212 +0,0 @@ -// The template and inlines for the -*- C++ -*- indirect_array class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/indirect_array.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _INDIRECT_ARRAY_H -#define _INDIRECT_ARRAY_H 1 - -#pragma GCC system_header - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup numeric_arrays - * @{ - */ - - /** - * @brief Reference to arbitrary subset of an array. - * - * An indirect_array is a reference to the actual elements of an array - * specified by an ordered array of indices. The way to get an - * indirect_array is to call operator[](valarray) on a valarray. - * The returned indirect_array then permits carrying operations out on the - * referenced subset of elements in the original valarray. - * - * For example, if an indirect_array is obtained using the array (4,2,0) as - * an argument, and then assigned to an array containing (1,2,3), then the - * underlying array will have array[0]==3, array[2]==2, and array[4]==1. - * - * @param Tp Element type. - */ - template - class indirect_array - { - public: - typedef _Tp value_type; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 253. valarray helper functions are almost entirely useless - - /// Copy constructor. Both slices refer to the same underlying array. - indirect_array(const indirect_array&); - - /// Assignment operator. Assigns elements to corresponding elements - /// of @a a. - indirect_array& operator=(const indirect_array&); - - /// Assign slice elements to corresponding elements of @a v. - void operator=(const valarray<_Tp>&) const; - /// Multiply slice elements by corresponding elements of @a v. - void operator*=(const valarray<_Tp>&) const; - /// Divide slice elements by corresponding elements of @a v. - void operator/=(const valarray<_Tp>&) const; - /// Modulo slice elements by corresponding elements of @a v. - void operator%=(const valarray<_Tp>&) const; - /// Add corresponding elements of @a v to slice elements. - void operator+=(const valarray<_Tp>&) const; - /// Subtract corresponding elements of @a v from slice elements. - void operator-=(const valarray<_Tp>&) const; - /// Logical xor slice elements with corresponding elements of @a v. - void operator^=(const valarray<_Tp>&) const; - /// Logical and slice elements with corresponding elements of @a v. - void operator&=(const valarray<_Tp>&) const; - /// Logical or slice elements with corresponding elements of @a v. - void operator|=(const valarray<_Tp>&) const; - /// Left shift slice elements by corresponding elements of @a v. - void operator<<=(const valarray<_Tp>&) const; - /// Right shift slice elements by corresponding elements of @a v. - void operator>>=(const valarray<_Tp>&) const; - /// Assign all slice elements to @a t. - void operator= (const _Tp&) const; - // ~indirect_array(); - - template - void operator=(const _Expr<_Dom, _Tp>&) const; - template - void operator*=(const _Expr<_Dom, _Tp>&) const; - template - void operator/=(const _Expr<_Dom, _Tp>&) const; - template - void operator%=(const _Expr<_Dom, _Tp>&) const; - template - void operator+=(const _Expr<_Dom, _Tp>&) const; - template - void operator-=(const _Expr<_Dom, _Tp>&) const; - template - void operator^=(const _Expr<_Dom, _Tp>&) const; - template - void operator&=(const _Expr<_Dom, _Tp>&) const; - template - void operator|=(const _Expr<_Dom, _Tp>&) const; - template - void operator<<=(const _Expr<_Dom, _Tp>&) const; - template - void operator>>=(const _Expr<_Dom, _Tp>&) const; - - private: - /// Copy constructor. Both slices refer to the same underlying array. - indirect_array(_Array<_Tp>, size_t, _Array); - - friend class valarray<_Tp>; - friend class gslice_array<_Tp>; - - const size_t _M_sz; - const _Array _M_index; - const _Array<_Tp> _M_array; - - // not implemented - indirect_array(); - }; - - template - inline - indirect_array<_Tp>::indirect_array(const indirect_array<_Tp>& __a) - : _M_sz(__a._M_sz), _M_index(__a._M_index), _M_array(__a._M_array) {} - - template - inline - indirect_array<_Tp>::indirect_array(_Array<_Tp> __a, size_t __s, - _Array __i) - : _M_sz(__s), _M_index(__i), _M_array(__a) {} - - template - inline indirect_array<_Tp>& - indirect_array<_Tp>::operator=(const indirect_array<_Tp>& __a) - { - std::__valarray_copy(__a._M_array, _M_sz, __a._M_index, _M_array, - _M_index); - return *this; - } - - template - inline void - indirect_array<_Tp>::operator=(const _Tp& __t) const - { std::__valarray_fill(_M_array, _M_index, _M_sz, __t); } - - template - inline void - indirect_array<_Tp>::operator=(const valarray<_Tp>& __v) const - { std::__valarray_copy(_Array<_Tp>(__v), _M_sz, _M_array, _M_index); } - - template - template - inline void - indirect_array<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) const - { std::__valarray_copy(__e, _M_sz, _M_array, _M_index); } - -#undef _DEFINE_VALARRAY_OPERATOR -#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ - template \ - inline void \ - indirect_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const\ - { \ - _Array_augmented_##_Name(_M_array, _M_index, _Array<_Tp>(__v), _M_sz); \ - } \ - \ - template \ - template \ - inline void \ - indirect_array<_Tp>::operator _Op##=(const _Expr<_Dom,_Tp>& __e) const\ - { \ - _Array_augmented_##_Name(_M_array, _M_index, __e, _M_sz); \ - } - -_DEFINE_VALARRAY_OPERATOR(*, __multiplies) -_DEFINE_VALARRAY_OPERATOR(/, __divides) -_DEFINE_VALARRAY_OPERATOR(%, __modulus) -_DEFINE_VALARRAY_OPERATOR(+, __plus) -_DEFINE_VALARRAY_OPERATOR(-, __minus) -_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) -_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) -_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) -_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) -_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) - -#undef _DEFINE_VALARRAY_OPERATOR - - // @} group numeric_arrays - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _INDIRECT_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/invoke.h b/resources/sources/avr-libstdcpp/include/bits/invoke.h deleted file mode 100644 index 18f5b9442..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/invoke.h +++ /dev/null @@ -1,163 +0,0 @@ -// Implementation of INVOKE -*- C++ -*- - -// Copyright (C) 2016-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/bits/invoke.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _GLIBCXX_INVOKE_H -#define _GLIBCXX_INVOKE_H 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup utilities - * @{ - */ - - // Used by __invoke_impl instead of std::forward<_Tp> so that a - // reference_wrapper is converted to an lvalue-reference. - template::type> - constexpr _Up&& - __invfwd(typename remove_reference<_Tp>::type& __t) noexcept - { return static_cast<_Up&&>(__t); } - - template - constexpr _Res - __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args) - { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); } - - template - constexpr _Res - __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t, - _Args&&... __args) - { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); } - - template - constexpr _Res - __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t, - _Args&&... __args) - { - return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...); - } - - template - constexpr _Res - __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t) - { return __invfwd<_Tp>(__t).*__f; } - - template - constexpr _Res - __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t) - { return (*std::forward<_Tp>(__t)).*__f; } - - /// Invoke a callable object. - template - constexpr typename __invoke_result<_Callable, _Args...>::type - __invoke(_Callable&& __fn, _Args&&... __args) - noexcept(__is_nothrow_invocable<_Callable, _Args...>::value) - { - using __result = __invoke_result<_Callable, _Args...>; - using __type = typename __result::type; - using __tag = typename __result::__invoke_type; - return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), - std::forward<_Args>(__args)...); - } - -#if __cplusplus >= 201703L - // INVOKE: Invoke a callable object and convert the result to R. - template - constexpr enable_if_t, _Res> - __invoke_r(_Callable&& __fn, _Args&&... __args) - noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>) - { - using __result = __invoke_result<_Callable, _Args...>; - using __type = typename __result::type; - using __tag = typename __result::__invoke_type; - if constexpr (is_void_v<_Res>) - std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), - std::forward<_Args>(__args)...); - else - return std::__invoke_impl<__type>(__tag{}, - std::forward<_Callable>(__fn), - std::forward<_Args>(__args)...); - } -#else // C++11 - template - using __can_invoke_as_void = __enable_if_t< - __and_, __is_invocable<_Callable, _Args...>>::value, - _Res - >; - - template - using __can_invoke_as_nonvoid = __enable_if_t< - __and_<__not_>, - is_convertible::type, - _Res> - >::value, - _Res - >; - - // INVOKE: Invoke a callable object and convert the result to R. - template - constexpr __can_invoke_as_nonvoid<_Res, _Callable, _Args...> - __invoke_r(_Callable&& __fn, _Args&&... __args) - { - using __result = __invoke_result<_Callable, _Args...>; - using __type = typename __result::type; - using __tag = typename __result::__invoke_type; - return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), - std::forward<_Args>(__args)...); - } - - // INVOKE when R is cv void - template - _GLIBCXX14_CONSTEXPR __can_invoke_as_void<_Res, _Callable, _Args...> - __invoke_r(_Callable&& __fn, _Args&&... __args) - { - using __result = __invoke_result<_Callable, _Args...>; - using __type = typename __result::type; - using __tag = typename __result::__invoke_type; - std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), - std::forward<_Args>(__args)...); - } -#endif // C++11 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++11 - -#endif // _GLIBCXX_INVOKE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h b/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h deleted file mode 100644 index 2721240e3..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h +++ /dev/null @@ -1,911 +0,0 @@ -// Concepts and traits for use with iterators -*- C++ -*- - -// Copyright (C) 2019-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/iterator_concepts.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iterator} - */ - -#ifndef _ITERATOR_CONCEPTS_H -#define _ITERATOR_CONCEPTS_H 1 - -#pragma GCC system_header - -#include -#include // to_address -#include // identity, ranges::less - -#if __cpp_lib_concepts -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - struct input_iterator_tag; - struct output_iterator_tag; - struct forward_iterator_tag; - struct bidirectional_iterator_tag; - struct random_access_iterator_tag; - struct contiguous_iterator_tag; - - template - struct iterator_traits; - - template requires is_object_v<_Tp> - struct iterator_traits<_Tp*>; - - template - struct __iterator_traits; - - namespace __detail - { - template - using __with_ref = _Tp&; - - template - concept __can_reference = requires { typename __with_ref<_Tp>; }; - - template - concept __dereferenceable = requires(_Tp& __t) - { - { *__t } -> __can_reference; - }; - } // namespace __detail - - template<__detail::__dereferenceable _Tp> - using iter_reference_t = decltype(*std::declval<_Tp&>()); - - namespace ranges - { - namespace __cust_imove - { - void iter_move(); - - template - concept __adl_imove - = (std::__detail::__class_or_enum>) - && requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); }; - - struct _IMove - { - private: - template - struct __result - { using type = iter_reference_t<_Tp>; }; - - template - requires __adl_imove<_Tp> - struct __result<_Tp> - { using type = decltype(iter_move(std::declval<_Tp>())); }; - - template - requires (!__adl_imove<_Tp>) - && is_lvalue_reference_v> - struct __result<_Tp> - { using type = remove_reference_t>&&; }; - - template - static constexpr bool - _S_noexcept() - { - if constexpr (__adl_imove<_Tp>) - return noexcept(iter_move(std::declval<_Tp>())); - else - return noexcept(*std::declval<_Tp>()); - } - - public: - // The result type of iter_move(std::declval<_Tp>()) - template - using __type = typename __result<_Tp>::type; - - template - constexpr __type<_Tp> - operator()(_Tp&& __e) const - noexcept(_S_noexcept<_Tp>()) - { - if constexpr (__adl_imove<_Tp>) - return iter_move(static_cast<_Tp&&>(__e)); - else if constexpr (is_lvalue_reference_v>) - return static_cast<__type<_Tp>>(*__e); - else - return *__e; - } - }; - } // namespace __cust_imove - - inline namespace __cust - { - inline constexpr __cust_imove::_IMove iter_move{}; - } // inline namespace __cust - } // namespace ranges - - template<__detail::__dereferenceable _Tp> - requires requires(_Tp& __t) - { { ranges::iter_move(__t) } -> __detail::__can_reference; } - using iter_rvalue_reference_t - = decltype(ranges::iter_move(std::declval<_Tp&>())); - - template struct incrementable_traits { }; - - template requires is_object_v<_Tp> - struct incrementable_traits<_Tp*> - { using difference_type = ptrdiff_t; }; - - template - struct incrementable_traits - : incrementable_traits<_Iter> { }; - - template requires requires { typename _Tp::difference_type; } - struct incrementable_traits<_Tp> - { using difference_type = typename _Tp::difference_type; }; - - template - requires (!requires { typename _Tp::difference_type; } - && requires(const _Tp& __a, const _Tp& __b) - { - requires (!is_void_v>); // PR c++/78173 - { __a - __b } -> integral; - }) - struct incrementable_traits<_Tp> - { - using difference_type - = make_signed_t() - std::declval<_Tp>())>; - }; - - namespace __detail - { - // An iterator such that iterator_traits<_Iter> names a specialization - // generated from the primary template. - template - concept __primary_traits_iter - = __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>); - - template - struct __iter_traits_impl - { using type = iterator_traits<_Iter>; }; - - template - requires __primary_traits_iter<_Iter> - struct __iter_traits_impl<_Iter, _Tp> - { using type = _Tp; }; - - // ITER_TRAITS - template - using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type; - - template - using __iter_diff_t = typename - __iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type; - } // namespace __detail - - template - using iter_difference_t = __detail::__iter_diff_t>; - - namespace __detail - { - template struct __cond_value_type { }; - - template requires is_object_v<_Tp> - struct __cond_value_type<_Tp> - { using value_type = remove_cv_t<_Tp>; }; - } // namespace __detail - - template struct indirectly_readable_traits { }; - - template - struct indirectly_readable_traits<_Tp*> - : __detail::__cond_value_type<_Tp> - { }; - - template requires is_array_v<_Iter> - struct indirectly_readable_traits<_Iter> - { using value_type = remove_cv_t>; }; - - template - struct indirectly_readable_traits - : indirectly_readable_traits<_Iter> - { }; - - template requires requires { typename _Tp::value_type; } - struct indirectly_readable_traits<_Tp> - : __detail::__cond_value_type - { }; - - template requires requires { typename _Tp::element_type; } - struct indirectly_readable_traits<_Tp> - : __detail::__cond_value_type - { }; - - namespace __detail - { - template - using __iter_value_t = typename - __iter_traits<_Tp, indirectly_readable_traits<_Tp>>::value_type; - } // namespace __detail - - template - using iter_value_t = __detail::__iter_value_t>; - - namespace __detail - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3420. cpp17-iterator should check [type] looks like an iterator first - template - concept __cpp17_iterator = requires(_Iter __it) - { - { *__it } -> __can_reference; - { ++__it } -> same_as<_Iter&>; - { *__it++ } -> __can_reference; - } && copyable<_Iter>; - - template - concept __cpp17_input_iterator = __cpp17_iterator<_Iter> - && equality_comparable<_Iter> - && requires(_Iter __it) - { - typename incrementable_traits<_Iter>::difference_type; - typename indirectly_readable_traits<_Iter>::value_type; - typename common_reference_t&&, - typename indirectly_readable_traits<_Iter>::value_type&>; - typename common_reference_t::value_type&>; - requires signed_integral< - typename incrementable_traits<_Iter>::difference_type>; - }; - - template - concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter> - && constructible_from<_Iter> - && is_lvalue_reference_v> - && same_as>, - typename indirectly_readable_traits<_Iter>::value_type> - && requires(_Iter __it) - { - { __it++ } -> convertible_to; - { *__it++ } -> same_as>; - }; - - template - concept __cpp17_bidi_iterator = __cpp17_fwd_iterator<_Iter> - && requires(_Iter __it) - { - { --__it } -> same_as<_Iter&>; - { __it-- } -> convertible_to; - { *__it-- } -> same_as>; - }; - - template - concept __cpp17_randacc_iterator = __cpp17_bidi_iterator<_Iter> - && totally_ordered<_Iter> - && requires(_Iter __it, - typename incrementable_traits<_Iter>::difference_type __n) - { - { __it += __n } -> same_as<_Iter&>; - { __it -= __n } -> same_as<_Iter&>; - { __it + __n } -> same_as<_Iter>; - { __n + __it } -> same_as<_Iter>; - { __it - __n } -> same_as<_Iter>; - { __it - __it } -> same_as; - { __it[__n] } -> convertible_to>; - }; - - template - concept __iter_with_nested_types = requires { - typename _Iter::iterator_category; - typename _Iter::value_type; - typename _Iter::difference_type; - typename _Iter::reference; - }; - - template - concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>; - - // FIXME: These have to be at namespace-scope because of PR 92103. - template - struct __ptr - { using type = void; }; - - template requires requires { typename _Iter::pointer; } - struct __ptr<_Iter, true> - { using type = typename _Iter::pointer; }; - - template requires requires { typename _Iter::pointer; } - struct __ptr<_Iter, false> - { using type = typename _Iter::pointer; }; - - template - requires (!requires { typename _Iter::pointer; } - && requires(_Iter& __it) { __it.operator->(); }) - struct __ptr<_Iter, true> - { using type = decltype(std::declval<_Iter&>().operator->()); }; - - template - struct __ref - { using type = iter_reference_t<_Iter>; }; - - template requires requires { typename _Iter::reference; } - struct __ref<_Iter> - { using type = typename _Iter::reference; }; - - template - struct __cat - { using type = input_iterator_tag; }; - - template - requires requires { typename _Iter::iterator_category; } - struct __cat<_Iter> - { using type = typename _Iter::iterator_category; }; - - template - requires (!requires { typename _Iter::iterator_category; } - && __detail::__cpp17_randacc_iterator<_Iter>) - struct __cat<_Iter> - { using type = random_access_iterator_tag; }; - - template - requires (!requires { typename _Iter::iterator_category; } - && __detail::__cpp17_bidi_iterator<_Iter>) - struct __cat<_Iter> - { using type = bidirectional_iterator_tag; }; - - template - requires (!requires { typename _Iter::iterator_category; } - && __detail::__cpp17_fwd_iterator<_Iter>) - struct __cat<_Iter> - { using type = forward_iterator_tag; }; - - template - struct __diff - { using type = void; }; - - template - requires requires { - typename incrementable_traits<_Iter>::difference_type; - } - struct __diff<_Iter> - { - using type = typename incrementable_traits<_Iter>::difference_type; - }; - - } // namespace __detail - - template - requires __detail::__iter_with_nested_types<_Iterator> - struct __iterator_traits<_Iterator, void> - { - using iterator_category = typename _Iterator::iterator_category; - using value_type = typename _Iterator::value_type; - using difference_type = typename _Iterator::difference_type; - using pointer = typename __detail::__ptr<_Iterator>::type; - using reference = typename _Iterator::reference; - }; - - template - requires __detail::__iter_without_nested_types<_Iterator> - && __detail::__cpp17_input_iterator<_Iterator> - struct __iterator_traits<_Iterator, void> - { - using iterator_category = typename __detail::__cat<_Iterator>::type; - using value_type - = typename indirectly_readable_traits<_Iterator>::value_type; - using difference_type - = typename incrementable_traits<_Iterator>::difference_type; - using pointer = typename __detail::__ptr<_Iterator, true>::type; - using reference = typename __detail::__ref<_Iterator>::type; - }; - - template - requires __detail::__iter_without_nested_types<_Iterator> - && __detail::__cpp17_iterator<_Iterator> - struct __iterator_traits<_Iterator, void> - { - using iterator_category = output_iterator_tag; - using value_type = void; - using difference_type = typename __detail::__diff<_Iterator>::type; - using pointer = void; - using reference = void; - }; - - namespace __detail - { - template - struct __iter_concept_impl; - - // ITER_CONCEPT(I) is ITER_TRAITS(I)::iterator_concept if that is valid. - template - requires requires { typename __iter_traits<_Iter>::iterator_concept; } - struct __iter_concept_impl<_Iter> - { using type = typename __iter_traits<_Iter>::iterator_concept; }; - - // Otherwise, ITER_TRAITS(I)::iterator_category if that is valid. - template - requires (!requires { typename __iter_traits<_Iter>::iterator_concept; } - && requires { typename __iter_traits<_Iter>::iterator_category; }) - struct __iter_concept_impl<_Iter> - { using type = typename __iter_traits<_Iter>::iterator_category; }; - - // Otherwise, random_access_tag if iterator_traits is not specialized. - template - requires (!requires { typename __iter_traits<_Iter>::iterator_concept; } - && !requires { typename __iter_traits<_Iter>::iterator_category; } - && __primary_traits_iter<_Iter>) - struct __iter_concept_impl<_Iter> - { using type = random_access_iterator_tag; }; - - // Otherwise, there is no ITER_CONCEPT(I) type. - template - struct __iter_concept_impl - { }; - - // ITER_CONCEPT - template - using __iter_concept = typename __iter_concept_impl<_Iter>::type; - - template - concept __indirectly_readable_impl = requires(const _In __in) - { - typename iter_value_t<_In>; - typename iter_reference_t<_In>; - typename iter_rvalue_reference_t<_In>; - { *__in } -> same_as>; - { ranges::iter_move(__in) } -> same_as>; - } - && common_reference_with&&, iter_value_t<_In>&> - && common_reference_with&&, - iter_rvalue_reference_t<_In>&&> - && common_reference_with&&, - const iter_value_t<_In>&>; - - } // namespace __detail - - /// Requirements for types that are readable by applying operator*. - template - concept indirectly_readable - = __detail::__indirectly_readable_impl>; - - template - using iter_common_reference_t - = common_reference_t, iter_value_t<_Tp>&>; - - /// Requirements for writing a value into an iterator's referenced object. - template - concept indirectly_writable = requires(_Out&& __o, _Tp&& __t) - { - *__o = std::forward<_Tp>(__t); - *std::forward<_Out>(__o) = std::forward<_Tp>(__t); - const_cast&&>(*__o) - = std::forward<_Tp>(__t); - const_cast&&>(*std::forward<_Out>(__o)) - = std::forward<_Tp>(__t); - }; - - namespace ranges::__detail - { -#if __SIZEOF_INT128__ - using __max_diff_type = __int128; - using __max_size_type = unsigned __int128; -#else - using __max_diff_type = long long; - using __max_size_type = unsigned long long; -#endif - - template - concept __is_integer_like = integral<_Tp> - || same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>; - - template - concept __is_signed_integer_like = signed_integral<_Tp> - || same_as<_Tp, __max_diff_type>; - - } // namespace ranges::__detail - - namespace __detail { using ranges::__detail::__is_signed_integer_like; } - - /// Requirements on types that can be incremented with ++. - template - concept weakly_incrementable = default_initializable<_Iter> - && movable<_Iter> - && requires(_Iter __i) - { - typename iter_difference_t<_Iter>; - requires __detail::__is_signed_integer_like>; - { ++__i } -> same_as<_Iter&>; - __i++; - }; - - template - concept incrementable = regular<_Iter> && weakly_incrementable<_Iter> - && requires(_Iter __i) { { __i++ } -> same_as<_Iter>; }; - - template - concept input_or_output_iterator - = requires(_Iter __i) { { *__i } -> __detail::__can_reference; } - && weakly_incrementable<_Iter>; - - template - concept sentinel_for = semiregular<_Sent> - && input_or_output_iterator<_Iter> - && __detail::__weakly_eq_cmp_with<_Sent, _Iter>; - - template - inline constexpr bool disable_sized_sentinel_for = false; - - template - concept sized_sentinel_for = sentinel_for<_Sent, _Iter> - && !disable_sized_sentinel_for, remove_cv_t<_Iter>> - && requires(const _Iter& __i, const _Sent& __s) - { - { __s - __i } -> same_as>; - { __i - __s } -> same_as>; - }; - - template - concept input_iterator = input_or_output_iterator<_Iter> - && indirectly_readable<_Iter> - && requires { typename __detail::__iter_concept<_Iter>; } - && derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>; - - template - concept output_iterator = input_or_output_iterator<_Iter> - && indirectly_writable<_Iter, _Tp> - && requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); }; - - template - concept forward_iterator = input_iterator<_Iter> - && derived_from<__detail::__iter_concept<_Iter>, forward_iterator_tag> - && incrementable<_Iter> && sentinel_for<_Iter, _Iter>; - - template - concept bidirectional_iterator = forward_iterator<_Iter> - && derived_from<__detail::__iter_concept<_Iter>, - bidirectional_iterator_tag> - && requires(_Iter __i) - { - { --__i } -> same_as<_Iter&>; - { __i-- } -> same_as<_Iter>; - }; - - template - concept random_access_iterator = bidirectional_iterator<_Iter> - && derived_from<__detail::__iter_concept<_Iter>, - random_access_iterator_tag> - && totally_ordered<_Iter> && sized_sentinel_for<_Iter, _Iter> - && requires(_Iter __i, const _Iter __j, - const iter_difference_t<_Iter> __n) - { - { __i += __n } -> same_as<_Iter&>; - { __j + __n } -> same_as<_Iter>; - { __n + __j } -> same_as<_Iter>; - { __i -= __n } -> same_as<_Iter&>; - { __j - __n } -> same_as<_Iter>; - { __j[__n] } -> same_as>; - }; - - template - concept contiguous_iterator = random_access_iterator<_Iter> - && derived_from<__detail::__iter_concept<_Iter>, contiguous_iterator_tag> - && is_lvalue_reference_v> - && same_as, remove_cvref_t>> - && requires(const _Iter& __i) - { - { std::to_address(__i) } - -> same_as>>; - }; - - // [indirectcallable], indirect callable requirements - - // [indirectcallable.indirectinvocable], indirect callables - - template - concept indirectly_unary_invocable = indirectly_readable<_Iter> - && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&> - && invocable<_Fn&, iter_reference_t<_Iter>> - && invocable<_Fn&, iter_common_reference_t<_Iter>> - && common_reference_with&>, - invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; - - template - concept indirectly_regular_unary_invocable = indirectly_readable<_Iter> - && copy_constructible<_Fn> - && regular_invocable<_Fn&, iter_value_t<_Iter>&> - && regular_invocable<_Fn&, iter_reference_t<_Iter>> - && regular_invocable<_Fn&, iter_common_reference_t<_Iter>> - && common_reference_with&>, - invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; - - template - concept indirect_unary_predicate = indirectly_readable<_Iter> - && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&> - && predicate<_Fn&, iter_reference_t<_Iter>> - && predicate<_Fn&, iter_common_reference_t<_Iter>>; - - template - concept indirect_binary_predicate - = indirectly_readable<_I1> && indirectly_readable<_I2> - && copy_constructible<_Fn> - && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> - && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> - && predicate<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> - && predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>> - && predicate<_Fn&, iter_common_reference_t<_I1>, - iter_common_reference_t<_I2>>; - - template - concept indirect_equivalence_relation - = indirectly_readable<_I1> && indirectly_readable<_I2> - && copy_constructible<_Fn> - && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> - && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> - && equivalence_relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> - && equivalence_relation<_Fn&, iter_reference_t<_I1>, - iter_reference_t<_I2>> - && equivalence_relation<_Fn&, iter_common_reference_t<_I1>, - iter_common_reference_t<_I2>>; - - template - concept indirect_strict_weak_order - = indirectly_readable<_I1> && indirectly_readable<_I2> - && copy_constructible<_Fn> - && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> - && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> - && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> - && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>> - && strict_weak_order<_Fn&, iter_common_reference_t<_I1>, - iter_common_reference_t<_I2>>; - - template - requires (indirectly_readable<_Is> && ...) - && invocable<_Fn, iter_reference_t<_Is>...> - using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>; - - /// [projected], projected - template _Proj> - struct projected - { - using value_type = remove_cvref_t>; - - indirect_result_t<_Proj&, _Iter> operator*() const; // not defined - }; - - template - struct incrementable_traits> - { using difference_type = iter_difference_t<_Iter>; }; - - // [alg.req], common algorithm requirements - - /// [alg.req.ind.move], concept `indirectly_movable` - - template - concept indirectly_movable = indirectly_readable<_In> - && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; - - template - concept indirectly_movable_storable = indirectly_movable<_In, _Out> - && indirectly_writable<_Out, iter_value_t<_In>> - && movable> - && constructible_from, iter_rvalue_reference_t<_In>> - && assignable_from&, iter_rvalue_reference_t<_In>>; - - /// [alg.req.ind.copy], concept `indirectly_copyable` - template - concept indirectly_copyable = indirectly_readable<_In> - && indirectly_writable<_Out, iter_reference_t<_In>>; - - template - concept indirectly_copyable_storable = indirectly_copyable<_In, _Out> - && indirectly_writable<_Out, iter_value_t<_In>&> - && indirectly_writable<_Out, const iter_value_t<_In>&> - && indirectly_writable<_Out, iter_value_t<_In>&&> - && indirectly_writable<_Out, const iter_value_t<_In>&&> - && copyable> - && constructible_from, iter_reference_t<_In>> - && assignable_from&, iter_reference_t<_In>>; - -namespace ranges -{ - namespace __cust_iswap - { - template - void iter_swap(_It1, _It2) = delete; - - template - concept __adl_iswap - = (std::__detail::__class_or_enum> - || std::__detail::__class_or_enum>) - && requires(_Tp&& __t, _Up&& __u) { - iter_swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); - }; - - template - constexpr iter_value_t<_Xp> - __iter_exchange_move(_Xp&& __x, _Yp&& __y) - noexcept(noexcept(iter_value_t<_Xp>(iter_move(__x))) - && noexcept(*__x = iter_move(__y))) - { - iter_value_t<_Xp> __old_value(iter_move(__x)); - *__x = iter_move(__y); - return __old_value; - } - - struct _IterSwap - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (__adl_iswap<_Tp, _Up>) - return noexcept(iter_swap(std::declval<_Tp>(), - std::declval<_Up>())); - else if constexpr (indirectly_readable<_Tp> - && indirectly_readable<_Up> - && swappable_with, iter_reference_t<_Up>>) - return noexcept(ranges::swap(*std::declval<_Tp>(), - *std::declval<_Up>())); - else - return noexcept(*std::declval<_Tp>() - = __iter_exchange_move(std::declval<_Up>(), - std::declval<_Tp>())); - } - - public: - template - requires __adl_iswap<_Tp, _Up> - || (indirectly_readable> - && indirectly_readable> - && swappable_with, iter_reference_t<_Up>>) - || (indirectly_movable_storable<_Tp, _Up> - && indirectly_movable_storable<_Up, _Tp>) - constexpr void - operator()(_Tp&& __e1, _Up&& __e2) const - noexcept(_S_noexcept<_Tp, _Up>()) - { - if constexpr (__adl_iswap<_Tp, _Up>) - iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2)); - else if constexpr (indirectly_readable<_Tp> - && indirectly_readable<_Up> - && swappable_with, iter_reference_t<_Up>>) - ranges::swap(*__e1, *__e2); - else - *__e1 = __iter_exchange_move(__e2, __e1); - } - }; - } // namespace __cust_iswap - - inline namespace __cust - { - inline constexpr __cust_iswap::_IterSwap iter_swap{}; - } // inline namespace __cust - -} // namespace ranges - - /// [alg.req.ind.swap], concept `indirectly_swappable` - template - concept indirectly_swappable - = indirectly_readable<_I1> && indirectly_readable<_I2> - && requires(const _I1 __i1, const _I2 __i2) - { - ranges::iter_swap(__i1, __i1); - ranges::iter_swap(__i2, __i2); - ranges::iter_swap(__i1, __i2); - ranges::iter_swap(__i2, __i1); - }; - - /// [alg.req.ind.cmp], concept `indirectly_comparable` - template - concept indirectly_comparable - = indirect_binary_predicate<_Rel, projected<_I1, _P1>, - projected<_I2, _P2>>; - - /// [alg.req.permutable], concept `permutable` - template - concept permutable = forward_iterator<_Iter> - && indirectly_movable_storable<_Iter, _Iter> - && indirectly_swappable<_Iter, _Iter>; - - /// [alg.req.mergeable], concept `mergeable` - template - concept mergeable = input_iterator<_I1> && input_iterator<_I2> - && weakly_incrementable<_Out> && indirectly_copyable<_I1, _Out> - && indirectly_copyable<_I2, _Out> - && indirect_strict_weak_order<_Rel, projected<_I1, _P1>, - projected<_I2, _P2>>; - - /// [alg.req.sortable], concept `sortable` - template - concept sortable = permutable<_Iter> - && indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>; - - struct unreachable_sentinel_t - { - template - friend constexpr bool - operator==(unreachable_sentinel_t, const _It&) noexcept - { return false; } - }; - - inline constexpr unreachable_sentinel_t unreachable_sentinel{}; - - struct default_sentinel_t { }; - inline constexpr default_sentinel_t default_sentinel{}; - - namespace __detail - { - template - constexpr decay_t<_Tp> - __decay_copy(_Tp&& __t) - noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) - { return std::forward<_Tp>(__t); } - - template - concept __member_begin = requires(_Tp& __t) - { - { __detail::__decay_copy(__t.begin()) } -> input_or_output_iterator; - }; - - void begin(auto&) = delete; - void begin(const auto&) = delete; - - template - concept __adl_begin = __class_or_enum> - && requires(_Tp& __t) - { - { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator; - }; - - // Simplified version of std::ranges::begin that only supports lvalues, - // for use by __range_iter_t below. - template - requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&> - auto - __ranges_begin(_Tp& __t) - { - if constexpr (is_array_v<_Tp>) - { - static_assert(sizeof(remove_all_extents_t<_Tp>) != 0, - "not array of incomplete type"); - return __t + 0; - } - else if constexpr (__member_begin<_Tp&>) - return __t.begin(); - else - return begin(__t); - } - - // Implementation of std::ranges::iterator_t, without using ranges::begin. - template - using __range_iter_t - = decltype(__detail::__ranges_begin(std::declval<_Tp&>())); - - } // namespace __detail - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 library concepts -#endif // _ITERATOR_CONCEPTS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/list.tcc b/resources/sources/avr-libstdcpp/include/bits/list.tcc deleted file mode 100644 index ce9e983c5..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/list.tcc +++ /dev/null @@ -1,633 +0,0 @@ -// List implementation (out of line) -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/list.tcc - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{list} - */ - -#ifndef _LIST_TCC -#define _LIST_TCC 1 - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - void - _List_base<_Tp, _Alloc>:: - _M_clear() _GLIBCXX_NOEXCEPT - { - typedef _List_node<_Tp> _Node; - __detail::_List_node_base* __cur = _M_impl._M_node._M_next; - while (__cur != &_M_impl._M_node) - { - _Node* __tmp = static_cast<_Node*>(__cur); - __cur = __tmp->_M_next; - _Tp* __val = __tmp->_M_valptr(); -#if __cplusplus >= 201103L - _Node_alloc_traits::destroy(_M_get_Node_allocator(), __val); -#else - _Tp_alloc_type(_M_get_Node_allocator()).destroy(__val); -#endif - _M_put_node(__tmp); - } - } - -#if __cplusplus >= 201103L - template - template - typename list<_Tp, _Alloc>::iterator - list<_Tp, _Alloc>:: - emplace(const_iterator __position, _Args&&... __args) - { - _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...); - __tmp->_M_hook(__position._M_const_cast()._M_node); - this->_M_inc_size(1); - return iterator(__tmp); - } -#endif - - template - typename list<_Tp, _Alloc>::iterator - list<_Tp, _Alloc>:: -#if __cplusplus >= 201103L - insert(const_iterator __position, const value_type& __x) -#else - insert(iterator __position, const value_type& __x) -#endif - { - _Node* __tmp = _M_create_node(__x); - __tmp->_M_hook(__position._M_const_cast()._M_node); - this->_M_inc_size(1); - return iterator(__tmp); - } - -#if __cplusplus >= 201103L - template - typename list<_Tp, _Alloc>::iterator - list<_Tp, _Alloc>:: - insert(const_iterator __position, size_type __n, const value_type& __x) - { - if (__n) - { - list __tmp(__n, __x, get_allocator()); - iterator __it = __tmp.begin(); - splice(__position, __tmp); - return __it; - } - return __position._M_const_cast(); - } - - template - template - typename list<_Tp, _Alloc>::iterator - list<_Tp, _Alloc>:: - insert(const_iterator __position, _InputIterator __first, - _InputIterator __last) - { - list __tmp(__first, __last, get_allocator()); - if (!__tmp.empty()) - { - iterator __it = __tmp.begin(); - splice(__position, __tmp); - return __it; - } - return __position._M_const_cast(); - } -#endif - - template - typename list<_Tp, _Alloc>::iterator - list<_Tp, _Alloc>:: -#if __cplusplus >= 201103L - erase(const_iterator __position) noexcept -#else - erase(iterator __position) -#endif - { - iterator __ret = iterator(__position._M_node->_M_next); - _M_erase(__position._M_const_cast()); - return __ret; - } - - // Return a const_iterator indicating the position to start inserting or - // erasing elements (depending whether the list is growing or shrinking), - // and set __new_size to the number of new elements that must be appended. - // Equivalent to the following, but performed optimally: - // if (__new_size < size()) { - // __new_size = 0; - // return std::next(begin(), __new_size); - // } else { - // __newsize -= size(); - // return end(); - // } - template - typename list<_Tp, _Alloc>::const_iterator - list<_Tp, _Alloc>:: - _M_resize_pos(size_type& __new_size) const - { - const_iterator __i; -#if _GLIBCXX_USE_CXX11_ABI - const size_type __len = size(); - if (__new_size < __len) - { - if (__new_size <= __len / 2) - { - __i = begin(); - std::advance(__i, __new_size); - } - else - { - __i = end(); - ptrdiff_t __num_erase = __len - __new_size; - std::advance(__i, -__num_erase); - } - __new_size = 0; - return __i; - } - else - __i = end(); -#else - size_type __len = 0; - for (__i = begin(); __i != end() && __len < __new_size; ++__i, ++__len) - ; -#endif - __new_size -= __len; - return __i; - } - -#if __cplusplus >= 201103L - template - void - list<_Tp, _Alloc>:: - _M_default_append(size_type __n) - { - size_type __i = 0; - __try - { - for (; __i < __n; ++__i) - emplace_back(); - } - __catch(...) - { - for (; __i; --__i) - pop_back(); - __throw_exception_again; - } - } - - template - void - list<_Tp, _Alloc>:: - resize(size_type __new_size) - { - const_iterator __i = _M_resize_pos(__new_size); - if (__new_size) - _M_default_append(__new_size); - else - erase(__i, end()); - } - - template - void - list<_Tp, _Alloc>:: - resize(size_type __new_size, const value_type& __x) - { - const_iterator __i = _M_resize_pos(__new_size); - if (__new_size) - insert(end(), __new_size, __x); - else - erase(__i, end()); - } -#else - template - void - list<_Tp, _Alloc>:: - resize(size_type __new_size, value_type __x) - { - const_iterator __i = _M_resize_pos(__new_size); - if (__new_size) - insert(end(), __new_size, __x); - else - erase(__i._M_const_cast(), end()); - } -#endif - - template - list<_Tp, _Alloc>& - list<_Tp, _Alloc>:: - operator=(const list& __x) - { - if (this != std::__addressof(__x)) - { -#if __cplusplus >= 201103L - if (_Node_alloc_traits::_S_propagate_on_copy_assign()) - { - auto& __this_alloc = this->_M_get_Node_allocator(); - auto& __that_alloc = __x._M_get_Node_allocator(); - if (!_Node_alloc_traits::_S_always_equal() - && __this_alloc != __that_alloc) - { - // replacement allocator cannot free existing storage - clear(); - } - std::__alloc_on_copy(__this_alloc, __that_alloc); - } -#endif - _M_assign_dispatch(__x.begin(), __x.end(), __false_type()); - } - return *this; - } - - template - void - list<_Tp, _Alloc>:: - _M_fill_assign(size_type __n, const value_type& __val) - { - iterator __i = begin(); - for (; __i != end() && __n > 0; ++__i, --__n) - *__i = __val; - if (__n > 0) - insert(end(), __n, __val); - else - erase(__i, end()); - } - - template - template - void - list<_Tp, _Alloc>:: - _M_assign_dispatch(_InputIterator __first2, _InputIterator __last2, - __false_type) - { - iterator __first1 = begin(); - iterator __last1 = end(); - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - *__first1 = *__first2; - if (__first2 == __last2) - erase(__first1, __last1); - else - insert(__last1, __first2, __last2); - } - -#if __cplusplus > 201703L -# define _GLIBCXX20_ONLY(__expr) __expr -#else -# define _GLIBCXX20_ONLY(__expr) -#endif - - template - typename list<_Tp, _Alloc>::__remove_return_type - list<_Tp, _Alloc>:: - remove(const value_type& __value) - { - size_type __removed __attribute__((__unused__)) = 0; - iterator __first = begin(); - iterator __last = end(); - iterator __extra = __last; - while (__first != __last) - { - iterator __next = __first; - ++__next; - if (*__first == __value) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 526. Is it undefined if a function in the standard changes - // in parameters? - if (std::__addressof(*__first) != std::__addressof(__value)) - { - _M_erase(__first); - _GLIBCXX20_ONLY( __removed++ ); - } - else - __extra = __first; - } - __first = __next; - } - if (__extra != __last) - { - _M_erase(__extra); - _GLIBCXX20_ONLY( __removed++ ); - } - return _GLIBCXX20_ONLY( __removed ); - } - - template - typename list<_Tp, _Alloc>::__remove_return_type - list<_Tp, _Alloc>:: - unique() - { - iterator __first = begin(); - iterator __last = end(); - if (__first == __last) - return _GLIBCXX20_ONLY( 0 ); - size_type __removed __attribute__((__unused__)) = 0; - iterator __next = __first; - while (++__next != __last) - { - if (*__first == *__next) - { - _M_erase(__next); - _GLIBCXX20_ONLY( __removed++ ); - } - else - __first = __next; - __next = __first; - } - return _GLIBCXX20_ONLY( __removed ); - } - - template - void - list<_Tp, _Alloc>:: -#if __cplusplus >= 201103L - merge(list&& __x) -#else - merge(list& __x) -#endif - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 300. list::merge() specification incomplete - if (this != std::__addressof(__x)) - { - _M_check_equal_allocators(__x); - - iterator __first1 = begin(); - iterator __last1 = end(); - iterator __first2 = __x.begin(); - iterator __last2 = __x.end(); - const size_t __orig_size = __x.size(); - __try { - while (__first1 != __last1 && __first2 != __last2) - if (*__first2 < *__first1) - { - iterator __next = __first2; - _M_transfer(__first1, __first2, ++__next); - __first2 = __next; - } - else - ++__first1; - if (__first2 != __last2) - _M_transfer(__last1, __first2, __last2); - - this->_M_inc_size(__x._M_get_size()); - __x._M_set_size(0); - } - __catch(...) - { - const size_t __dist = std::distance(__first2, __last2); - this->_M_inc_size(__orig_size - __dist); - __x._M_set_size(__dist); - __throw_exception_again; - } - } - } - - template - template - void - list<_Tp, _Alloc>:: -#if __cplusplus >= 201103L - merge(list&& __x, _StrictWeakOrdering __comp) -#else - merge(list& __x, _StrictWeakOrdering __comp) -#endif - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 300. list::merge() specification incomplete - if (this != std::__addressof(__x)) - { - _M_check_equal_allocators(__x); - - iterator __first1 = begin(); - iterator __last1 = end(); - iterator __first2 = __x.begin(); - iterator __last2 = __x.end(); - const size_t __orig_size = __x.size(); - __try - { - while (__first1 != __last1 && __first2 != __last2) - if (__comp(*__first2, *__first1)) - { - iterator __next = __first2; - _M_transfer(__first1, __first2, ++__next); - __first2 = __next; - } - else - ++__first1; - if (__first2 != __last2) - _M_transfer(__last1, __first2, __last2); - - this->_M_inc_size(__x._M_get_size()); - __x._M_set_size(0); - } - __catch(...) - { - const size_t __dist = std::distance(__first2, __last2); - this->_M_inc_size(__orig_size - __dist); - __x._M_set_size(__dist); - __throw_exception_again; - } - } - } - - template - void - list<_Tp, _Alloc>:: - sort() - { - // Do nothing if the list has length 0 or 1. - if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node - && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) - { - list __carry; - list __tmp[64]; - list * __fill = __tmp; - list * __counter; - __try - { - do - { - __carry.splice(__carry.begin(), *this, begin()); - - for(__counter = __tmp; - __counter != __fill && !__counter->empty(); - ++__counter) - { - __counter->merge(__carry); - __carry.swap(*__counter); - } - __carry.swap(*__counter); - if (__counter == __fill) - ++__fill; - } - while ( !empty() ); - - for (__counter = __tmp + 1; __counter != __fill; ++__counter) - __counter->merge(*(__counter - 1)); - swap( *(__fill - 1) ); - } - __catch(...) - { - this->splice(this->end(), __carry); - for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i) - this->splice(this->end(), __tmp[__i]); - __throw_exception_again; - } - } - } - - template - template - typename list<_Tp, _Alloc>::__remove_return_type - list<_Tp, _Alloc>:: - remove_if(_Predicate __pred) - { - size_type __removed __attribute__((__unused__)) = 0; - iterator __first = begin(); - iterator __last = end(); - while (__first != __last) - { - iterator __next = __first; - ++__next; - if (__pred(*__first)) - { - _M_erase(__first); - _GLIBCXX20_ONLY( __removed++ ); - } - __first = __next; - } - return _GLIBCXX20_ONLY( __removed ); - } - - template - template - typename list<_Tp, _Alloc>::__remove_return_type - list<_Tp, _Alloc>:: - unique(_BinaryPredicate __binary_pred) - { - iterator __first = begin(); - iterator __last = end(); - if (__first == __last) - return _GLIBCXX20_ONLY(0); - size_type __removed __attribute__((__unused__)) = 0; - iterator __next = __first; - while (++__next != __last) - { - if (__binary_pred(*__first, *__next)) - { - _M_erase(__next); - _GLIBCXX20_ONLY( __removed++ ); - } - else - __first = __next; - __next = __first; - } - return _GLIBCXX20_ONLY( __removed ); - } - -#undef _GLIBCXX20_ONLY - - template - template - void - list<_Tp, _Alloc>:: - sort(_StrictWeakOrdering __comp) - { - // Do nothing if the list has length 0 or 1. - if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node - && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) - { - list __carry; - list __tmp[64]; - list * __fill = __tmp; - list * __counter; - __try - { - do - { - __carry.splice(__carry.begin(), *this, begin()); - - for(__counter = __tmp; - __counter != __fill && !__counter->empty(); - ++__counter) - { - __counter->merge(__carry, __comp); - __carry.swap(*__counter); - } - __carry.swap(*__counter); - if (__counter == __fill) - ++__fill; - } - while ( !empty() ); - - for (__counter = __tmp + 1; __counter != __fill; ++__counter) - __counter->merge(*(__counter - 1), __comp); - swap(*(__fill - 1)); - } - __catch(...) - { - this->splice(this->end(), __carry); - for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i) - this->splice(this->end(), __tmp[__i]); - __throw_exception_again; - } - } - } - -_GLIBCXX_END_NAMESPACE_CONTAINER -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _LIST_TCC */ - diff --git a/resources/sources/avr-libstdcpp/include/bits/mask_array.h b/resources/sources/avr-libstdcpp/include/bits/mask_array.h deleted file mode 100644 index 579cd59e5..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/mask_array.h +++ /dev/null @@ -1,213 +0,0 @@ -// The template and inlines for the -*- C++ -*- mask_array class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/mask_array.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _MASK_ARRAY_H -#define _MASK_ARRAY_H 1 - -#pragma GCC system_header - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup numeric_arrays - * @{ - */ - - /** - * @brief Reference to selected subset of an array. - * - * A mask_array is a reference to the actual elements of an array specified - * by a bitmask in the form of an array of bool. The way to get a - * mask_array is to call operator[](valarray) on a valarray. The - * returned mask_array then permits carrying operations out on the - * referenced subset of elements in the original valarray. - * - * For example, if a mask_array is obtained using the array (false, true, - * false, true) as an argument, the mask array has two elements referring - * to array[1] and array[3] in the underlying array. - * - * @param Tp Element type. - */ - template - class mask_array - { - public: - typedef _Tp value_type; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 253. valarray helper functions are almost entirely useless - - /// Copy constructor. Both slices refer to the same underlying array. - mask_array (const mask_array&); - - /// Assignment operator. Assigns elements to corresponding elements - /// of @a a. - mask_array& operator=(const mask_array&); - - void operator=(const valarray<_Tp>&) const; - /// Multiply slice elements by corresponding elements of @a v. - void operator*=(const valarray<_Tp>&) const; - /// Divide slice elements by corresponding elements of @a v. - void operator/=(const valarray<_Tp>&) const; - /// Modulo slice elements by corresponding elements of @a v. - void operator%=(const valarray<_Tp>&) const; - /// Add corresponding elements of @a v to slice elements. - void operator+=(const valarray<_Tp>&) const; - /// Subtract corresponding elements of @a v from slice elements. - void operator-=(const valarray<_Tp>&) const; - /// Logical xor slice elements with corresponding elements of @a v. - void operator^=(const valarray<_Tp>&) const; - /// Logical and slice elements with corresponding elements of @a v. - void operator&=(const valarray<_Tp>&) const; - /// Logical or slice elements with corresponding elements of @a v. - void operator|=(const valarray<_Tp>&) const; - /// Left shift slice elements by corresponding elements of @a v. - void operator<<=(const valarray<_Tp>&) const; - /// Right shift slice elements by corresponding elements of @a v. - void operator>>=(const valarray<_Tp>&) const; - /// Assign all slice elements to @a t. - void operator=(const _Tp&) const; - - // ~mask_array (); - - template - void operator=(const _Expr<_Dom,_Tp>&) const; - template - void operator*=(const _Expr<_Dom,_Tp>&) const; - template - void operator/=(const _Expr<_Dom,_Tp>&) const; - template - void operator%=(const _Expr<_Dom,_Tp>&) const; - template - void operator+=(const _Expr<_Dom,_Tp>&) const; - template - void operator-=(const _Expr<_Dom,_Tp>&) const; - template - void operator^=(const _Expr<_Dom,_Tp>&) const; - template - void operator&=(const _Expr<_Dom,_Tp>&) const; - template - void operator|=(const _Expr<_Dom,_Tp>&) const; - template - void operator<<=(const _Expr<_Dom,_Tp>&) const; - template - void operator>>=(const _Expr<_Dom,_Tp>&) const; - - private: - mask_array(_Array<_Tp>, size_t, _Array); - friend class valarray<_Tp>; - - const size_t _M_sz; - const _Array _M_mask; - const _Array<_Tp> _M_array; - -#if __cplusplus < 201103L - // not implemented - mask_array(); -#else - public: - mask_array() = delete; -#endif - }; - - template - inline mask_array<_Tp>::mask_array(const mask_array<_Tp>& __a) - : _M_sz(__a._M_sz), _M_mask(__a._M_mask), _M_array(__a._M_array) {} - - template - inline - mask_array<_Tp>::mask_array(_Array<_Tp> __a, size_t __s, _Array __m) - : _M_sz(__s), _M_mask(__m), _M_array(__a) {} - - template - inline mask_array<_Tp>& - mask_array<_Tp>::operator=(const mask_array<_Tp>& __a) - { - std::__valarray_copy(__a._M_array, __a._M_mask, - _M_sz, _M_array, _M_mask); - return *this; - } - - template - inline void - mask_array<_Tp>::operator=(const _Tp& __t) const - { std::__valarray_fill(_M_array, _M_sz, _M_mask, __t); } - - template - inline void - mask_array<_Tp>::operator=(const valarray<_Tp>& __v) const - { std::__valarray_copy(_Array<_Tp>(__v), __v.size(), _M_array, _M_mask); } - - template - template - inline void - mask_array<_Tp>::operator=(const _Expr<_Ex, _Tp>& __e) const - { std::__valarray_copy(__e, __e.size(), _M_array, _M_mask); } - -#undef _DEFINE_VALARRAY_OPERATOR -#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ - template \ - inline void \ - mask_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ - { \ - _Array_augmented_##_Name(_M_array, _M_mask, \ - _Array<_Tp>(__v), __v.size()); \ - } \ - \ - template \ - template \ - inline void \ - mask_array<_Tp>::operator _Op##=(const _Expr<_Dom, _Tp>& __e) const\ - { \ - _Array_augmented_##_Name(_M_array, _M_mask, __e, __e.size()); \ - } - -_DEFINE_VALARRAY_OPERATOR(*, __multiplies) -_DEFINE_VALARRAY_OPERATOR(/, __divides) -_DEFINE_VALARRAY_OPERATOR(%, __modulus) -_DEFINE_VALARRAY_OPERATOR(+, __plus) -_DEFINE_VALARRAY_OPERATOR(-, __minus) -_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) -_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) -_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) -_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) -_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) - -#undef _DEFINE_VALARRAY_OPERATOR - - // @} group numeric_arrays - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _MASK_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h b/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h deleted file mode 100644 index af1a1c69c..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h +++ /dev/null @@ -1,82 +0,0 @@ -// Forward declarations -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1996-1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/memoryfwd.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _MEMORYFWD_H -#define _MEMORYFWD_H 1 - -#pragma GCC system_header - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup allocators Allocators - * @ingroup memory - * - * Classes encapsulating memory operations. - * - * @{ - */ - - template - class allocator; - -#if __cplusplus <= 201703L - template<> - class allocator; -#endif - -#if __cplusplus >= 201103L - /// Declare uses_allocator so it can be specialized in \ etc. - template - struct uses_allocator; -#endif - - /// @} group memory - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/move.h b/resources/sources/avr-libstdcpp/include/bits/move.h deleted file mode 100644 index 5a4dbdc82..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/move.h +++ /dev/null @@ -1,224 +0,0 @@ -// Move, forward and identity for C++11 + swap -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/move.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{utility} - */ - -#ifndef _MOVE_H -#define _MOVE_H 1 - -#include -#if __cplusplus < 201103L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Used, in C++03 mode too, by allocators, etc. - /** - * @brief Same as C++11 std::addressof - * @ingroup utilities - */ - template - inline _GLIBCXX_CONSTEXPR _Tp* - __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT - { return __builtin_addressof(__r); } - -#if __cplusplus >= 201103L - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#include // Brings in std::declval too. - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup utilities - * @{ - */ - - /** - * @brief Forward an lvalue. - * @return The parameter cast to the specified type. - * - * This function is used to implement "perfect forwarding". - */ - template - constexpr _Tp&& - forward(typename std::remove_reference<_Tp>::type& __t) noexcept - { return static_cast<_Tp&&>(__t); } - - /** - * @brief Forward an rvalue. - * @return The parameter cast to the specified type. - * - * This function is used to implement "perfect forwarding". - */ - template - constexpr _Tp&& - forward(typename std::remove_reference<_Tp>::type&& __t) noexcept - { - static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" - " substituting _Tp is an lvalue reference type"); - return static_cast<_Tp&&>(__t); - } - - /** - * @brief Convert a value to an rvalue. - * @param __t A thing of arbitrary type. - * @return The parameter cast to an rvalue-reference to allow moving it. - */ - template - constexpr typename std::remove_reference<_Tp>::type&& - move(_Tp&& __t) noexcept - { return static_cast::type&&>(__t); } - - - template - struct __move_if_noexcept_cond - : public __and_<__not_>, - is_copy_constructible<_Tp>>::type { }; - - /** - * @brief Conditionally convert a value to an rvalue. - * @param __x A thing of arbitrary type. - * @return The parameter, possibly cast to an rvalue-reference. - * - * Same as std::move unless the type's move constructor could throw and the - * type is copyable, in which case an lvalue-reference is returned instead. - */ - template - constexpr typename - conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type - move_if_noexcept(_Tp& __x) noexcept - { return std::move(__x); } - - // declval, from type_traits. - -#if __cplusplus > 201402L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2296. std::addressof should be constexpr -# define __cpp_lib_addressof_constexpr 201603 -#endif - /** - * @brief Returns the actual address of the object or function - * referenced by r, even in the presence of an overloaded - * operator&. - * @param __r Reference to an object or function. - * @return The actual address. - */ - template - inline _GLIBCXX17_CONSTEXPR _Tp* - addressof(_Tp& __r) noexcept - { return std::__addressof(__r); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2598. addressof works on temporaries - template - const _Tp* addressof(const _Tp&&) = delete; - - // C++11 version of std::exchange for internal use. - template - _GLIBCXX20_CONSTEXPR - inline _Tp - __exchange(_Tp& __obj, _Up&& __new_val) - { - _Tp __old_val = std::move(__obj); - __obj = std::forward<_Up>(__new_val); - return __old_val; - } - - /// @} group utilities - -#define _GLIBCXX_MOVE(__val) std::move(__val) -#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val) -#else -#define _GLIBCXX_MOVE(__val) (__val) -#define _GLIBCXX_FORWARD(_Tp, __val) (__val) -#endif - - /** - * @addtogroup utilities - * @{ - */ - - /** - * @brief Swaps two values. - * @param __a A thing of arbitrary type. - * @param __b Another thing of arbitrary type. - * @return Nothing. - */ - template - _GLIBCXX20_CONSTEXPR - inline -#if __cplusplus >= 201103L - typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>, - is_move_constructible<_Tp>, - is_move_assignable<_Tp>>::value>::type -#else - void -#endif - swap(_Tp& __a, _Tp& __b) - _GLIBCXX_NOEXCEPT_IF(__and_, - is_nothrow_move_assignable<_Tp>>::value) - { -#if __cplusplus < 201103L - // concept requirements - __glibcxx_function_requires(_SGIAssignableConcept<_Tp>) -#endif - _Tp __tmp = _GLIBCXX_MOVE(__a); - __a = _GLIBCXX_MOVE(__b); - __b = _GLIBCXX_MOVE(__tmp); - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 809. std::swap should be overloaded for array types. - /// Swap the contents of two arrays. - template - _GLIBCXX20_CONSTEXPR - inline -#if __cplusplus >= 201103L - typename enable_if<__is_swappable<_Tp>::value>::type -#else - void -#endif - swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) - _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Tp>::value) - { - for (size_t __n = 0; __n < _Nm; ++__n) - swap(__a[__n], __b[__n]); - } - - /// @} group utilities -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _MOVE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/node_handle.h b/resources/sources/avr-libstdcpp/include/bits/node_handle.h deleted file mode 100644 index cbf95f045..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/node_handle.h +++ /dev/null @@ -1,299 +0,0 @@ -// Node handles for containers -*- C++ -*- - -// Copyright (C) 2016-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/node_handle.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. - * @headername{map,set,unordered_map,unordered_set} - */ - -#ifndef _NODE_HANDLE -#define _NODE_HANDLE 1 - -#pragma GCC system_header - -#if __cplusplus > 201402L -# define __cpp_lib_node_extract 201606 - -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /// Base class for node handle types of maps and sets. - template - class _Node_handle_common - { - using _AllocTraits = allocator_traits<_NodeAlloc>; - - public: - using allocator_type = __alloc_rebind<_NodeAlloc, _Val>; - - allocator_type - get_allocator() const noexcept - { - __glibcxx_assert(!this->empty()); - return allocator_type(*_M_alloc); - } - - explicit operator bool() const noexcept { return _M_ptr != nullptr; } - - [[nodiscard]] bool empty() const noexcept { return _M_ptr == nullptr; } - - protected: - constexpr _Node_handle_common() noexcept : _M_ptr(), _M_alloc() {} - - ~_Node_handle_common() { _M_destroy(); } - - _Node_handle_common(_Node_handle_common&& __nh) noexcept - : _M_ptr(__nh._M_ptr), _M_alloc(std::move(__nh._M_alloc)) - { - __nh._M_ptr = nullptr; - __nh._M_alloc = nullopt; - } - - _Node_handle_common& - operator=(_Node_handle_common&& __nh) noexcept - { - _M_destroy(); - _M_ptr = __nh._M_ptr; - if constexpr (is_move_assignable_v<_NodeAlloc>) - { - if (_AllocTraits::propagate_on_container_move_assignment::value - || !this->_M_alloc) - this->_M_alloc = std::move(__nh._M_alloc); - else - { - __glibcxx_assert(this->_M_alloc == __nh._M_alloc); - } - } - else - { - __glibcxx_assert(_M_alloc); - } - __nh._M_ptr = nullptr; - __nh._M_alloc = nullopt; - return *this; - } - - _Node_handle_common(typename _AllocTraits::pointer __ptr, - const _NodeAlloc& __alloc) - : _M_ptr(__ptr), _M_alloc(__alloc) { } - - void - _M_swap(_Node_handle_common& __nh) noexcept - { - using std::swap; - swap(_M_ptr, __nh._M_ptr); - if (_AllocTraits::propagate_on_container_swap::value - || !_M_alloc || !__nh._M_alloc) - _M_alloc.swap(__nh._M_alloc); - else - { - __glibcxx_assert(_M_alloc == __nh._M_alloc); - } - } - - private: - void - _M_destroy() noexcept - { - if (_M_ptr != nullptr) - { - allocator_type __alloc(*_M_alloc); - allocator_traits::destroy(__alloc, - _M_ptr->_M_valptr()); - _AllocTraits::deallocate(*_M_alloc, _M_ptr, 1); - } - } - - protected: - typename _AllocTraits::pointer _M_ptr; - private: - optional<_NodeAlloc> _M_alloc; - - template - friend class _Rb_tree; - }; - - /// Node handle type for maps. - template - class _Node_handle : public _Node_handle_common<_Value, _NodeAlloc> - { - public: - constexpr _Node_handle() noexcept = default; - ~_Node_handle() = default; - _Node_handle(_Node_handle&&) noexcept = default; - - _Node_handle& - operator=(_Node_handle&&) noexcept = default; - - using key_type = _Key; - using mapped_type = typename _Value::second_type; - - key_type& - key() const noexcept - { - __glibcxx_assert(!this->empty()); - return *_M_pkey; - } - - mapped_type& - mapped() const noexcept - { - __glibcxx_assert(!this->empty()); - return *_M_pmapped; - } - - void - swap(_Node_handle& __nh) noexcept - { - this->_M_swap(__nh); - using std::swap; - swap(_M_pkey, __nh._M_pkey); - swap(_M_pmapped, __nh._M_pmapped); - } - - friend void - swap(_Node_handle& __x, _Node_handle& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - private: - using _AllocTraits = allocator_traits<_NodeAlloc>; - - _Node_handle(typename _AllocTraits::pointer __ptr, - const _NodeAlloc& __alloc) - : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) - { - if (__ptr) - { - auto& __key = const_cast<_Key&>(__ptr->_M_valptr()->first); - _M_pkey = _S_pointer_to(__key); - _M_pmapped = _S_pointer_to(__ptr->_M_valptr()->second); - } - else - { - _M_pkey = nullptr; - _M_pmapped = nullptr; - } - } - - template - using __pointer - = __ptr_rebind>; - - __pointer<_Key> _M_pkey = nullptr; - __pointer _M_pmapped = nullptr; - - template - __pointer<_Tp> - _S_pointer_to(_Tp& __obj) - { return pointer_traits<__pointer<_Tp>>::pointer_to(__obj); } - - const key_type& - _M_key() const noexcept { return key(); } - - template - friend class _Rb_tree; - - template - friend class _Hashtable; - }; - - /// Node handle type for sets. - template - class _Node_handle<_Value, _Value, _NodeAlloc> - : public _Node_handle_common<_Value, _NodeAlloc> - { - public: - constexpr _Node_handle() noexcept = default; - ~_Node_handle() = default; - _Node_handle(_Node_handle&&) noexcept = default; - - _Node_handle& - operator=(_Node_handle&&) noexcept = default; - - using value_type = _Value; - - value_type& - value() const noexcept - { - __glibcxx_assert(!this->empty()); - return *this->_M_ptr->_M_valptr(); - } - - void - swap(_Node_handle& __nh) noexcept - { this->_M_swap(__nh); } - - friend void - swap(_Node_handle& __x, _Node_handle& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - private: - using _AllocTraits = allocator_traits<_NodeAlloc>; - - _Node_handle(typename _AllocTraits::pointer __ptr, - const _NodeAlloc& __alloc) - : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) { } - - const value_type& - _M_key() const noexcept { return value(); } - - template - friend class _Rb_tree; - - template - friend class _Hashtable; - }; - - /// Return type of insert(node_handle&&) on unique maps/sets. - template - struct _Node_insert_return - { - _Iterator position = _Iterator(); - bool inserted = false; - _NodeHandle node; - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++17 -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h b/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h deleted file mode 100644 index 5e80907af..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h +++ /dev/null @@ -1,294 +0,0 @@ -// Components for compile-time parsing of numbers -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/parse_numbers.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{chrono} - */ - -#ifndef _GLIBCXX_PARSE_NUMBERS_H -#define _GLIBCXX_PARSE_NUMBERS_H 1 - -#pragma GCC system_header - -// From n3642.pdf except I added binary literals and digit separator '\''. - -#if __cplusplus >= 201402L - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -namespace __parse_int -{ - template - struct _Digit; - - template - struct _Digit<_Base, '0'> : integral_constant - { - using __valid = true_type; - }; - - template - struct _Digit<_Base, '1'> : integral_constant - { - using __valid = true_type; - }; - - template - struct _Digit_impl : integral_constant - { - static_assert(_Base > _Val, "invalid digit"); - using __valid = true_type; - }; - - template - struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2> - { }; - - template - struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3> - { }; - - template - struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4> - { }; - - template - struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5> - { }; - - template - struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6> - { }; - - template - struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7> - { }; - - template - struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8> - { }; - - template - struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9> - { }; - - template - struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa> - { }; - - template - struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa> - { }; - - template - struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb> - { }; - - template - struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb> - { }; - - template - struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc> - { }; - - template - struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc> - { }; - - template - struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd> - { }; - - template - struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd> - { }; - - template - struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe> - { }; - - template - struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe> - { }; - - template - struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf> - { }; - - template - struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf> - { }; - - // Digit separator - template - struct _Digit<_Base, '\''> : integral_constant - { - using __valid = false_type; - }; - -//------------------------------------------------------------------------------ - - template - using __ull_constant = integral_constant; - - template - struct _Power_help - { - using __next = typename _Power_help<_Base, _Digs...>::type; - using __valid_digit = typename _Digit<_Base, _Dig>::__valid; - using type - = __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>; - }; - - template - struct _Power_help<_Base, _Dig> - { - using __valid_digit = typename _Digit<_Base, _Dig>::__valid; - using type = __ull_constant<__valid_digit::value>; - }; - - template - struct _Power : _Power_help<_Base, _Digs...>::type - { }; - - template - struct _Power<_Base> : __ull_constant<0> - { }; - -//------------------------------------------------------------------------------ - - template - struct _Number_help - { - using __digit = _Digit<_Base, _Dig>; - using __valid_digit = typename __digit::__valid; - using __next = _Number_help<_Base, - __valid_digit::value ? _Pow / _Base : _Pow, - _Digs...>; - using type = __ull_constant<_Pow * __digit::value + __next::type::value>; - static_assert((type::value / _Pow) == __digit::value, - "integer literal does not fit in unsigned long long"); - }; - - // Skip past digit separators: - template - struct _Number_help<_Base, _Pow, '\'', _Dig, _Digs...> - : _Number_help<_Base, _Pow, _Dig, _Digs...> - { }; - - // Terminating case for recursion: - template - struct _Number_help<_Base, 1ULL, _Dig> - { - using type = __ull_constant<_Digit<_Base, _Dig>::value>; - }; - - template - struct _Number - : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type - { }; - - template - struct _Number<_Base> - : __ull_constant<0> - { }; - -//------------------------------------------------------------------------------ - - template - struct _Parse_int; - - template - struct _Parse_int<'0', 'b', _Digs...> - : _Number<2U, _Digs...>::type - { }; - - template - struct _Parse_int<'0', 'B', _Digs...> - : _Number<2U, _Digs...>::type - { }; - - template - struct _Parse_int<'0', 'x', _Digs...> - : _Number<16U, _Digs...>::type - { }; - - template - struct _Parse_int<'0', 'X', _Digs...> - : _Number<16U, _Digs...>::type - { }; - - template - struct _Parse_int<'0', _Digs...> - : _Number<8U, _Digs...>::type - { }; - - template - struct _Parse_int - : _Number<10U, _Digs...>::type - { }; - -} // namespace __parse_int - - -namespace __select_int -{ - template - struct _Select_int_base; - - template - struct _Select_int_base<_Val, _IntType, _Ints...> - : conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max), - integral_constant<_IntType, _Val>, - _Select_int_base<_Val, _Ints...>> - { }; - - template - struct _Select_int_base<_Val> - { }; - - template - using _Select_int = typename _Select_int_base< - __parse_int::_Parse_int<_Digs...>::value, - unsigned char, - unsigned short, - unsigned int, - unsigned long, - unsigned long long - >::type; - -} // namespace __select_int - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++14 - -#endif // _GLIBCXX_PARSE_NUMBERS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/postypes.h b/resources/sources/avr-libstdcpp/include/bits/postypes.h deleted file mode 100644 index 718ff4462..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/postypes.h +++ /dev/null @@ -1,253 +0,0 @@ -// Position types -*- C++ -*- - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/postypes.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iosfwd} - */ - -// -// ISO C++ 14882: 27.4.1 - Types -// ISO C++ 14882: 27.4.3 - Template class fpos -// - -#ifndef _GLIBCXX_POSTYPES_H -#define _GLIBCXX_POSTYPES_H 1 - -#pragma GCC system_header - -#include // For mbstate_t - -// XXX If is really needed, make sure to define the macros -// before including it, in order not to break (and -// in C++11). Reconsider all this as soon as possible... -#if (defined(_GLIBCXX_HAVE_INT64_T) && !defined(_GLIBCXX_HAVE_INT64_T_LONG) \ - && !defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)) - -#ifndef __STDC_LIMIT_MACROS -# define _UNDEF__STDC_LIMIT_MACROS -# define __STDC_LIMIT_MACROS -#endif -#ifndef __STDC_CONSTANT_MACROS -# define _UNDEF__STDC_CONSTANT_MACROS -# define __STDC_CONSTANT_MACROS -#endif -#include // For int64_t -#ifdef _UNDEF__STDC_LIMIT_MACROS -# undef __STDC_LIMIT_MACROS -# undef _UNDEF__STDC_LIMIT_MACROS -#endif -#ifdef _UNDEF__STDC_CONSTANT_MACROS -# undef __STDC_CONSTANT_MACROS -# undef _UNDEF__STDC_CONSTANT_MACROS -#endif - -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // The types streamoff, streampos and wstreampos and the class - // template fpos<> are described in clauses 21.1.2, 21.1.3, 27.1.2, - // 27.2, 27.4.1, 27.4.3 and D.6. Despite all this verbiage, the - // behaviour of these types is mostly implementation defined or - // unspecified. The behaviour in this implementation is as noted - // below. - - /** - * @brief Type used by fpos, char_traits, and char_traits. - * - * In clauses 21.1.3.1 and 27.4.1 streamoff is described as an - * implementation defined type. - * Note: In versions of GCC up to and including GCC 3.3, streamoff - * was typedef long. - */ -#ifdef _GLIBCXX_HAVE_INT64_T_LONG - typedef long streamoff; -#elif defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG) - typedef long long streamoff; -#elif defined(_GLIBCXX_HAVE_INT64_T) - typedef int64_t streamoff; -#else - typedef long long streamoff; -#endif - - /// Integral type for I/O operation counts and buffer sizes. - typedef ptrdiff_t streamsize; // Signed integral type - - /** - * @brief Class representing stream positions. - * - * The standard places no requirements upon the template parameter StateT. - * In this implementation StateT must be DefaultConstructible, - * CopyConstructible and Assignable. The standard only requires that fpos - * should contain a member of type StateT. In this implementation it also - * contains an offset stored as a signed integer. - * - * @param StateT Type passed to and returned from state(). - */ - template - class fpos - { - private: - streamoff _M_off; - _StateT _M_state; - - public: - // The standard doesn't require that fpos objects can be default - // constructed. This implementation provides a default - // constructor that initializes the offset to 0 and default - // constructs the state. - fpos() - : _M_off(0), _M_state() { } - - // The standard requires that fpos objects can be constructed - // from streamoff objects using the constructor syntax, and - // fails to give any meaningful semantics. In this - // implementation implicit conversion is also allowed, and this - // constructor stores the streamoff as the offset and default - // constructs the state. - /// Construct position from offset. - fpos(streamoff __off) - : _M_off(__off), _M_state() { } - -#if __cplusplus >= 201103L - fpos(const fpos&) = default; - fpos& operator=(const fpos&) = default; - ~fpos() = default; -#endif - - /// Convert to streamoff. - operator streamoff() const { return _M_off; } - - /// Remember the value of @a st. - void - state(_StateT __st) - { _M_state = __st; } - - /// Return the last set value of @a st. - _StateT - state() const - { return _M_state; } - - // The standard requires that this operator must be defined, but - // gives no semantics. In this implementation it just adds its - // argument to the stored offset and returns *this. - /// Add offset to this position. - fpos& - operator+=(streamoff __off) - { - _M_off += __off; - return *this; - } - - // The standard requires that this operator must be defined, but - // gives no semantics. In this implementation it just subtracts - // its argument from the stored offset and returns *this. - /// Subtract offset from this position. - fpos& - operator-=(streamoff __off) - { - _M_off -= __off; - return *this; - } - - // The standard requires that this operator must be defined, but - // defines its semantics only in terms of operator-. In this - // implementation it constructs a copy of *this, adds the - // argument to that copy using operator+= and then returns the - // copy. - /// Add position and offset. - fpos - operator+(streamoff __off) const - { - fpos __pos(*this); - __pos += __off; - return __pos; - } - - // The standard requires that this operator must be defined, but - // defines its semantics only in terms of operator+. In this - // implementation it constructs a copy of *this, subtracts the - // argument from that copy using operator-= and then returns the - // copy. - /// Subtract offset from position. - fpos - operator-(streamoff __off) const - { - fpos __pos(*this); - __pos -= __off; - return __pos; - } - - // The standard requires that this operator must be defined, but - // defines its semantics only in terms of operator+. In this - // implementation it returns the difference between the offset - // stored in *this and in the argument. - /// Subtract position to return offset. - streamoff - operator-(const fpos& __other) const - { return _M_off - __other._M_off; } - }; - - // The standard only requires that operator== must be an - // equivalence relation. In this implementation two fpos - // objects belong to the same equivalence class if the contained - // offsets compare equal. - /// Test if equivalent to another position. - template - inline bool - operator==(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs) - { return streamoff(__lhs) == streamoff(__rhs); } - - template - inline bool - operator!=(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs) - { return streamoff(__lhs) != streamoff(__rhs); } - - // Clauses 21.1.3.1 and 21.1.3.2 describe streampos and wstreampos - // as implementation defined types, but clause 27.2 requires that - // they must both be typedefs for fpos - /// File position for char streams. - typedef fpos streampos; - /// File position for wchar_t streams. - typedef fpos wstreampos; - -#ifdef _GLIBCXX_USE_CHAR8_T - /// File position for char8_t streams. - typedef fpos u8streampos; -#endif - -#if __cplusplus >= 201103L - /// File position for char16_t streams. - typedef fpos u16streampos; - /// File position for char32_t streams. - typedef fpos u32streampos; -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h b/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h deleted file mode 100644 index 7ac9a467d..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h +++ /dev/null @@ -1,405 +0,0 @@ -// Default predicates for internal use -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file predefined_ops.h - * This is an internal header file, included by other library headers. - * You should not attempt to use it directly. @headername{algorithm} - */ - -#ifndef _GLIBCXX_PREDEFINED_OPS_H -#define _GLIBCXX_PREDEFINED_OPS_H 1 - -namespace __gnu_cxx -{ -namespace __ops -{ - struct _Iter_less_iter - { - template - _GLIBCXX14_CONSTEXPR - bool - operator()(_Iterator1 __it1, _Iterator2 __it2) const - { return *__it1 < *__it2; } - }; - - _GLIBCXX14_CONSTEXPR - inline _Iter_less_iter - __iter_less_iter() - { return _Iter_less_iter(); } - - struct _Iter_less_val - { -#if __cplusplus >= 201103L - constexpr _Iter_less_val() = default; -#else - _Iter_less_val() { } -#endif - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_less_val(_Iter_less_iter) { } - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it, _Value& __val) const - { return *__it < __val; } - }; - - _GLIBCXX20_CONSTEXPR - inline _Iter_less_val - __iter_less_val() - { return _Iter_less_val(); } - - _GLIBCXX20_CONSTEXPR - inline _Iter_less_val - __iter_comp_val(_Iter_less_iter) - { return _Iter_less_val(); } - - struct _Val_less_iter - { -#if __cplusplus >= 201103L - constexpr _Val_less_iter() = default; -#else - _Val_less_iter() { } -#endif - - _GLIBCXX20_CONSTEXPR - explicit - _Val_less_iter(_Iter_less_iter) { } - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Value& __val, _Iterator __it) const - { return __val < *__it; } - }; - - _GLIBCXX20_CONSTEXPR - inline _Val_less_iter - __val_less_iter() - { return _Val_less_iter(); } - - _GLIBCXX20_CONSTEXPR - inline _Val_less_iter - __val_comp_iter(_Iter_less_iter) - { return _Val_less_iter(); } - - struct _Iter_equal_to_iter - { - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator1 __it1, _Iterator2 __it2) const - { return *__it1 == *__it2; } - }; - - _GLIBCXX20_CONSTEXPR - inline _Iter_equal_to_iter - __iter_equal_to_iter() - { return _Iter_equal_to_iter(); } - - struct _Iter_equal_to_val - { - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it, _Value& __val) const - { return *__it == __val; } - }; - - _GLIBCXX20_CONSTEXPR - inline _Iter_equal_to_val - __iter_equal_to_val() - { return _Iter_equal_to_val(); } - - _GLIBCXX20_CONSTEXPR - inline _Iter_equal_to_val - __iter_comp_val(_Iter_equal_to_iter) - { return _Iter_equal_to_val(); } - - template - struct _Iter_comp_iter - { - _Compare _M_comp; - - explicit _GLIBCXX14_CONSTEXPR - _Iter_comp_iter(_Compare __comp) - : _M_comp(_GLIBCXX_MOVE(__comp)) - { } - - template - _GLIBCXX14_CONSTEXPR - bool - operator()(_Iterator1 __it1, _Iterator2 __it2) - { return bool(_M_comp(*__it1, *__it2)); } - }; - - template - _GLIBCXX14_CONSTEXPR - inline _Iter_comp_iter<_Compare> - __iter_comp_iter(_Compare __comp) - { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } - - template - struct _Iter_comp_val - { - _Compare _M_comp; - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_comp_val(_Compare __comp) - : _M_comp(_GLIBCXX_MOVE(__comp)) - { } - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp) - : _M_comp(__comp._M_comp) - { } - -#if __cplusplus >= 201103L - _GLIBCXX20_CONSTEXPR - explicit - _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp) - : _M_comp(std::move(__comp._M_comp)) - { } -#endif - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it, _Value& __val) - { return bool(_M_comp(*__it, __val)); } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _Iter_comp_val<_Compare> - __iter_comp_val(_Compare __comp) - { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } - - template - _GLIBCXX20_CONSTEXPR - inline _Iter_comp_val<_Compare> - __iter_comp_val(_Iter_comp_iter<_Compare> __comp) - { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } - - template - struct _Val_comp_iter - { - _Compare _M_comp; - - _GLIBCXX20_CONSTEXPR - explicit - _Val_comp_iter(_Compare __comp) - : _M_comp(_GLIBCXX_MOVE(__comp)) - { } - - _GLIBCXX20_CONSTEXPR - explicit - _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp) - : _M_comp(__comp._M_comp) - { } - -#if __cplusplus >= 201103L - _GLIBCXX20_CONSTEXPR - explicit - _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp) - : _M_comp(std::move(__comp._M_comp)) - { } -#endif - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Value& __val, _Iterator __it) - { return bool(_M_comp(__val, *__it)); } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _Val_comp_iter<_Compare> - __val_comp_iter(_Compare __comp) - { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } - - template - _GLIBCXX20_CONSTEXPR - inline _Val_comp_iter<_Compare> - __val_comp_iter(_Iter_comp_iter<_Compare> __comp) - { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } - - template - struct _Iter_equals_val - { - _Value& _M_value; - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_equals_val(_Value& __value) - : _M_value(__value) - { } - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it) - { return *__it == _M_value; } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _Iter_equals_val<_Value> - __iter_equals_val(_Value& __val) - { return _Iter_equals_val<_Value>(__val); } - - template - struct _Iter_equals_iter - { - _Iterator1 _M_it1; - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_equals_iter(_Iterator1 __it1) - : _M_it1(__it1) - { } - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator2 __it2) - { return *__it2 == *_M_it1; } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _Iter_equals_iter<_Iterator> - __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it) - { return _Iter_equals_iter<_Iterator>(__it); } - - template - struct _Iter_pred - { - _Predicate _M_pred; - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_pred(_Predicate __pred) - : _M_pred(_GLIBCXX_MOVE(__pred)) - { } - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it) - { return bool(_M_pred(*__it)); } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _Iter_pred<_Predicate> - __pred_iter(_Predicate __pred) - { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); } - - template - struct _Iter_comp_to_val - { - _Compare _M_comp; - _Value& _M_value; - - _GLIBCXX20_CONSTEXPR - _Iter_comp_to_val(_Compare __comp, _Value& __value) - : _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value) - { } - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it) - { return bool(_M_comp(*__it, _M_value)); } - }; - - template - _Iter_comp_to_val<_Compare, _Value> - _GLIBCXX20_CONSTEXPR - __iter_comp_val(_Compare __comp, _Value &__val) - { - return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val); - } - - template - struct _Iter_comp_to_iter - { - _Compare _M_comp; - _Iterator1 _M_it1; - - _GLIBCXX20_CONSTEXPR - _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1) - : _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1) - { } - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator2 __it2) - { return bool(_M_comp(*__it2, *_M_it1)); } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _Iter_comp_to_iter<_Compare, _Iterator> - __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it) - { - return _Iter_comp_to_iter<_Compare, _Iterator>( - _GLIBCXX_MOVE(__comp._M_comp), __it); - } - - template - struct _Iter_negate - { - _Predicate _M_pred; - - _GLIBCXX20_CONSTEXPR - explicit - _Iter_negate(_Predicate __pred) - : _M_pred(_GLIBCXX_MOVE(__pred)) - { } - - template - _GLIBCXX20_CONSTEXPR - bool - operator()(_Iterator __it) - { return !bool(_M_pred(*__it)); } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _Iter_negate<_Predicate> - __negate(_Iter_pred<_Predicate> __pred) - { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); } - -} // namespace __ops -} // namespace __gnu_cxx - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h b/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h deleted file mode 100644 index 38f694df5..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h +++ /dev/null @@ -1,211 +0,0 @@ -// Pointer Traits -*- C++ -*- - -// Copyright (C) 2011-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/ptr_traits.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _PTR_TRAITS_H -#define _PTR_TRAITS_H 1 - -#if __cplusplus >= 201103L - -#include - -#if __cplusplus > 201703L -#define __cpp_lib_constexpr_memory 201811L -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - class __undefined; - - // Given Template return T, otherwise invalid. - template - struct __get_first_arg - { using type = __undefined; }; - - template class _Template, typename _Tp, - typename... _Types> - struct __get_first_arg<_Template<_Tp, _Types...>> - { using type = _Tp; }; - - template - using __get_first_arg_t = typename __get_first_arg<_Tp>::type; - - // Given Template and U return Template, otherwise invalid. - template - struct __replace_first_arg - { }; - - template class _Template, typename _Up, - typename _Tp, typename... _Types> - struct __replace_first_arg<_Template<_Tp, _Types...>, _Up> - { using type = _Template<_Up, _Types...>; }; - - template - using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type; - - template - using __make_not_void - = typename conditional::value, __undefined, _Tp>::type; - - /** - * @brief Uniform interface to all pointer-like types - * @ingroup pointer_abstractions - */ - template - struct pointer_traits - { - private: - template - using __element_type = typename _Tp::element_type; - - template - using __difference_type = typename _Tp::difference_type; - - template - struct __rebind : __replace_first_arg<_Tp, _Up> { }; - - template - struct __rebind<_Tp, _Up, __void_t>> - { using type = typename _Tp::template rebind<_Up>; }; - - public: - /// The pointer type. - using pointer = _Ptr; - - /// The type pointed to. - using element_type - = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>; - - /// The type used to represent the difference between two pointers. - using difference_type - = __detected_or_t; - - /// A pointer to a different type. - template - using rebind = typename __rebind<_Ptr, _Up>::type; - - static _Ptr - pointer_to(__make_not_void& __e) - { return _Ptr::pointer_to(__e); } - - static_assert(!is_same::value, - "pointer type defines element_type or is like SomePointer"); - }; - - /** - * @brief Partial specialization for built-in pointers. - * @ingroup pointer_abstractions - */ - template - struct pointer_traits<_Tp*> - { - /// The pointer type - typedef _Tp* pointer; - /// The type pointed to - typedef _Tp element_type; - /// Type used to represent the difference between two pointers - typedef ptrdiff_t difference_type; - - template - using rebind = _Up*; - - /** - * @brief Obtain a pointer to an object - * @param __r A reference to an object of type @c element_type - * @return @c addressof(__r) - */ - static _GLIBCXX20_CONSTEXPR pointer - pointer_to(__make_not_void& __r) noexcept - { return std::addressof(__r); } - }; - - /// Convenience alias for rebinding pointers. - template - using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; - - template - constexpr _Tp* - __to_address(_Tp* __ptr) noexcept - { - static_assert(!std::is_function<_Tp>::value, "not a function pointer"); - return __ptr; - } - -#if __cplusplus <= 201703L - template - constexpr typename std::pointer_traits<_Ptr>::element_type* - __to_address(const _Ptr& __ptr) - { return std::__to_address(__ptr.operator->()); } -#else - template - constexpr auto - __to_address(const _Ptr& __ptr) noexcept - -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) - { return std::pointer_traits<_Ptr>::to_address(__ptr); } - - template - constexpr auto - __to_address(const _Ptr& __ptr, _None...) noexcept - { - return std::__to_address(__ptr.operator->()); - } - -#define __cpp_lib_to_address 201711L - - /** - * @brief Obtain address referenced by a pointer to an object - * @param __ptr A pointer to an object - * @return @c __ptr - * @ingroup pointer_abstractions - */ - template - constexpr _Tp* - to_address(_Tp* __ptr) noexcept - { return std::__to_address(__ptr); } - - /** - * @brief Obtain address referenced by a pointer to an object - * @param __ptr A pointer to an object - * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is - well-formed, otherwise @c to_address(__ptr.operator->()) - * @ingroup pointer_abstractions - */ - template - constexpr auto - to_address(const _Ptr& __ptr) noexcept - { return std::__to_address(__ptr); } -#endif // C++2a - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/random.h b/resources/sources/avr-libstdcpp/include/bits/random.h deleted file mode 100644 index 0b0877394..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/random.h +++ /dev/null @@ -1,5183 +0,0 @@ -// random number generation -*- C++ -*- - -// Copyright (C) 2009-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** - * @file bits/random.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{random} - */ - -#ifndef _RANDOM_H -#define _RANDOM_H 1 - -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // [26.4] Random number generation - - /** - * @defgroup random Random Number Generation - * @ingroup numerics - * - * A facility for generating random numbers on selected distributions. - * @{ - */ - - // std::uniform_random_bit_generator is defined in - - /** - * @brief A function template for converting the output of a (integral) - * uniform random number generator to a floatng point result in the range - * [0-1). - */ - template - _RealType - generate_canonical(_UniformRandomNumberGenerator& __g); - - /* - * Implementation-space details. - */ - namespace __detail - { - template - (std::numeric_limits<_UIntType>::digits)> - struct _Shift - { static const _UIntType __value = 0; }; - - template - struct _Shift<_UIntType, __w, true> - { static const _UIntType __value = _UIntType(1) << __w; }; - - template - struct _Select_uint_least_t - { - static_assert(__which < 0, /* needs to be dependent */ - "sorry, would be too much trouble for a slow result"); - }; - - template - struct _Select_uint_least_t<__s, 4> - { typedef unsigned int type; }; - - template - struct _Select_uint_least_t<__s, 3> - { typedef unsigned long type; }; - - template - struct _Select_uint_least_t<__s, 2> - { typedef unsigned long long type; }; - -#ifdef _GLIBCXX_USE_INT128 - template - struct _Select_uint_least_t<__s, 1> - { typedef unsigned __int128 type; }; -#endif - - // Assume a != 0, a < m, c < m, x < m. - template= __m - 1), - bool __schrage_ok = __m % __a < __m / __a> - struct _Mod - { - typedef typename _Select_uint_least_t::type _Tp2; - static _Tp - __calc(_Tp __x) - { return static_cast<_Tp>((_Tp2(__a) * __x + __c) % __m); } - }; - - // Schrage. - template - struct _Mod<_Tp, __m, __a, __c, false, true> - { - static _Tp - __calc(_Tp __x); - }; - - // Special cases: - // - for m == 2^n or m == 0, unsigned integer overflow is safe. - // - a * (m - 1) + c fits in _Tp, there is no overflow. - template - struct _Mod<_Tp, __m, __a, __c, true, __s> - { - static _Tp - __calc(_Tp __x) - { - _Tp __res = __a * __x + __c; - if (__m) - __res %= __m; - return __res; - } - }; - - template - inline _Tp - __mod(_Tp __x) - { return _Mod<_Tp, __m, __a, __c>::__calc(__x); } - - /* - * An adaptor class for converting the output of any Generator into - * the input for a specific Distribution. - */ - template - struct _Adaptor - { - static_assert(std::is_floating_point<_DInputType>::value, - "template argument must be a floating point type"); - - public: - _Adaptor(_Engine& __g) - : _M_g(__g) { } - - _DInputType - min() const - { return _DInputType(0); } - - _DInputType - max() const - { return _DInputType(1); } - - /* - * Converts a value generated by the adapted random number generator - * into a value in the input domain for the dependent random number - * distribution. - */ - _DInputType - operator()() - { - return std::generate_canonical<_DInputType, - std::numeric_limits<_DInputType>::digits, - _Engine>(_M_g); - } - - private: - _Engine& _M_g; - }; - - template - using __seed_seq_generate_t = decltype( - std::declval<_Sseq&>().generate(std::declval(), - std::declval())); - - // Detect whether _Sseq is a valid seed sequence for - // a random number engine _Engine with result type _Res. - template> - using __is_seed_seq = __and_< - __not_, _Engine>>, - is_unsigned, - __not_> - >; - - } // namespace __detail - - /** - * @addtogroup random_generators Random Number Generators - * @ingroup random - * - * These classes define objects which provide random or pseudorandom - * numbers, either from a discrete or a continuous interval. The - * random number generator supplied as a part of this library are - * all uniform random number generators which provide a sequence of - * random number uniformly distributed over their range. - * - * A number generator is a function object with an operator() that - * takes zero arguments and returns a number. - * - * A compliant random number generator must satisfy the following - * requirements. - * - *
Random Number Generator Requirements
To be documented.
- * - * @{ - */ - - /** - * @brief A model of a linear congruential random number generator. - * - * A random number generator that produces pseudorandom numbers via - * linear function: - * @f[ - * x_{i+1}\leftarrow(ax_{i} + c) \bmod m - * @f] - * - * The template parameter @p _UIntType must be an unsigned integral type - * large enough to store values up to (__m-1). If the template parameter - * @p __m is 0, the modulus @p __m used is - * std::numeric_limits<_UIntType>::max() plus 1. Otherwise, the template - * parameters @p __a and @p __c must be less than @p __m. - * - * The size of the state is @f$1@f$. - */ - template - class linear_congruential_engine - { - static_assert(std::is_unsigned<_UIntType>::value, - "result_type must be an unsigned integral type"); - static_assert(__m == 0u || (__a < __m && __c < __m), - "template argument substituting __m out of bounds"); - - template - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, linear_congruential_engine, _UIntType>::value>::type; - - public: - /** The type of the generated random value. */ - typedef _UIntType result_type; - - /** The multiplier. */ - static constexpr result_type multiplier = __a; - /** An increment. */ - static constexpr result_type increment = __c; - /** The modulus. */ - static constexpr result_type modulus = __m; - static constexpr result_type default_seed = 1u; - - /** - * @brief Constructs a %linear_congruential_engine random number - * generator engine with seed 1. - */ - linear_congruential_engine() : linear_congruential_engine(default_seed) - { } - - /** - * @brief Constructs a %linear_congruential_engine random number - * generator engine with seed @p __s. The default seed value - * is 1. - * - * @param __s The initial seed value. - */ - explicit - linear_congruential_engine(result_type __s) - { seed(__s); } - - /** - * @brief Constructs a %linear_congruential_engine random number - * generator engine seeded from the seed sequence @p __q. - * - * @param __q the seed sequence. - */ - template> - explicit - linear_congruential_engine(_Sseq& __q) - { seed(__q); } - - /** - * @brief Reseeds the %linear_congruential_engine random number generator - * engine sequence to the seed @p __s. - * - * @param __s The new seed. - */ - void - seed(result_type __s = default_seed); - - /** - * @brief Reseeds the %linear_congruential_engine random number generator - * engine - * sequence using values from the seed sequence @p __q. - * - * @param __q the seed sequence. - */ - template - _If_seed_seq<_Sseq> - seed(_Sseq& __q); - - /** - * @brief Gets the smallest possible value in the output range. - * - * The minimum depends on the @p __c parameter: if it is zero, the - * minimum generated must be > 0, otherwise 0 is allowed. - */ - static constexpr result_type - min() - { return __c == 0u ? 1u : 0u; } - - /** - * @brief Gets the largest possible value in the output range. - */ - static constexpr result_type - max() - { return __m - 1u; } - - /** - * @brief Discard a sequence of random numbers. - */ - void - discard(unsigned long long __z) - { - for (; __z != 0ULL; --__z) - (*this)(); - } - - /** - * @brief Gets the next random number in the sequence. - */ - result_type - operator()() - { - _M_x = __detail::__mod<_UIntType, __m, __a, __c>(_M_x); - return _M_x; - } - - /** - * @brief Compares two linear congruential random number generator - * objects of the same type for equality. - * - * @param __lhs A linear congruential random number generator object. - * @param __rhs Another linear congruential random number generator - * object. - * - * @returns true if the infinite sequences of generated values - * would be equal, false otherwise. - */ - friend bool - operator==(const linear_congruential_engine& __lhs, - const linear_congruential_engine& __rhs) - { return __lhs._M_x == __rhs._M_x; } - - private: - _UIntType _M_x; - }; - - /** - * @brief Compares two linear congruential random number generator - * objects of the same type for inequality. - * - * @param __lhs A linear congruential random number generator object. - * @param __rhs Another linear congruential random number generator - * object. - * - * @returns true if the infinite sequences of generated values - * would be different, false otherwise. - */ - template - inline bool - operator!=(const std::linear_congruential_engine<_UIntType, __a, - __c, __m>& __lhs, - const std::linear_congruential_engine<_UIntType, __a, - __c, __m>& __rhs) - { return !(__lhs == __rhs); } - - - /** - * A generalized feedback shift register discrete random number generator. - * - * This algorithm avoids multiplication and division and is designed to be - * friendly to a pipelined architecture. If the parameters are chosen - * correctly, this generator will produce numbers with a very long period and - * fairly good apparent entropy, although still not cryptographically strong. - * - * The best way to use this generator is with the predefined mt19937 class. - * - * This algorithm was originally invented by Makoto Matsumoto and - * Takuji Nishimura. - * - * @tparam __w Word size, the number of bits in each element of - * the state vector. - * @tparam __n The degree of recursion. - * @tparam __m The period parameter. - * @tparam __r The separation point bit index. - * @tparam __a The last row of the twist matrix. - * @tparam __u The first right-shift tempering matrix parameter. - * @tparam __d The first right-shift tempering matrix mask. - * @tparam __s The first left-shift tempering matrix parameter. - * @tparam __b The first left-shift tempering matrix mask. - * @tparam __t The second left-shift tempering matrix parameter. - * @tparam __c The second left-shift tempering matrix mask. - * @tparam __l The second right-shift tempering matrix parameter. - * @tparam __f Initialization multiplier. - */ - template - class mersenne_twister_engine - { - static_assert(std::is_unsigned<_UIntType>::value, - "result_type must be an unsigned integral type"); - static_assert(1u <= __m && __m <= __n, - "template argument substituting __m out of bounds"); - static_assert(__r <= __w, "template argument substituting " - "__r out of bound"); - static_assert(__u <= __w, "template argument substituting " - "__u out of bound"); - static_assert(__s <= __w, "template argument substituting " - "__s out of bound"); - static_assert(__t <= __w, "template argument substituting " - "__t out of bound"); - static_assert(__l <= __w, "template argument substituting " - "__l out of bound"); - static_assert(__w <= std::numeric_limits<_UIntType>::digits, - "template argument substituting __w out of bound"); - static_assert(__a <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "template argument substituting __a out of bound"); - static_assert(__b <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "template argument substituting __b out of bound"); - static_assert(__c <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "template argument substituting __c out of bound"); - static_assert(__d <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "template argument substituting __d out of bound"); - static_assert(__f <= (__detail::_Shift<_UIntType, __w>::__value - 1), - "template argument substituting __f out of bound"); - - template - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, mersenne_twister_engine, _UIntType>::value>::type; - - public: - /** The type of the generated random value. */ - typedef _UIntType result_type; - - // parameter values - static constexpr size_t word_size = __w; - static constexpr size_t state_size = __n; - static constexpr size_t shift_size = __m; - static constexpr size_t mask_bits = __r; - static constexpr result_type xor_mask = __a; - static constexpr size_t tempering_u = __u; - static constexpr result_type tempering_d = __d; - static constexpr size_t tempering_s = __s; - static constexpr result_type tempering_b = __b; - static constexpr size_t tempering_t = __t; - static constexpr result_type tempering_c = __c; - static constexpr size_t tempering_l = __l; - static constexpr result_type initialization_multiplier = __f; - static constexpr result_type default_seed = 5489u; - - // constructors and member functions - - mersenne_twister_engine() : mersenne_twister_engine(default_seed) { } - - explicit - mersenne_twister_engine(result_type __sd) - { seed(__sd); } - - /** - * @brief Constructs a %mersenne_twister_engine random number generator - * engine seeded from the seed sequence @p __q. - * - * @param __q the seed sequence. - */ - template> - explicit - mersenne_twister_engine(_Sseq& __q) - { seed(__q); } - - void - seed(result_type __sd = default_seed); - - template - _If_seed_seq<_Sseq> - seed(_Sseq& __q); - - /** - * @brief Gets the smallest possible value in the output range. - */ - static constexpr result_type - min() - { return 0; } - - /** - * @brief Gets the largest possible value in the output range. - */ - static constexpr result_type - max() - { return __detail::_Shift<_UIntType, __w>::__value - 1; } - - /** - * @brief Discard a sequence of random numbers. - */ - void - discard(unsigned long long __z); - - result_type - operator()(); - - /** - * @brief Compares two % mersenne_twister_engine random number generator - * objects of the same type for equality. - * - * @param __lhs A % mersenne_twister_engine random number generator - * object. - * @param __rhs Another % mersenne_twister_engine random number - * generator object. - * - * @returns true if the infinite sequences of generated values - * would be equal, false otherwise. - */ - friend bool - operator==(const mersenne_twister_engine& __lhs, - const mersenne_twister_engine& __rhs) - { return (std::equal(__lhs._M_x, __lhs._M_x + state_size, __rhs._M_x) - && __lhs._M_p == __rhs._M_p); } - - private: - void _M_gen_rand(); - - _UIntType _M_x[state_size]; - size_t _M_p; - }; - - /** - * @brief Compares two % mersenne_twister_engine random number generator - * objects of the same type for inequality. - * - * @param __lhs A % mersenne_twister_engine random number generator - * object. - * @param __rhs Another % mersenne_twister_engine random number - * generator object. - * - * @returns true if the infinite sequences of generated values - * would be different, false otherwise. - */ - template - inline bool - operator!=(const std::mersenne_twister_engine<_UIntType, __w, __n, __m, - __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __lhs, - const std::mersenne_twister_engine<_UIntType, __w, __n, __m, - __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __rhs) - { return !(__lhs == __rhs); } - - - /** - * @brief The Marsaglia-Zaman generator. - * - * This is a model of a Generalized Fibonacci discrete random number - * generator, sometimes referred to as the SWC generator. - * - * A discrete random number generator that produces pseudorandom - * numbers using: - * @f[ - * x_{i}\leftarrow(x_{i - s} - x_{i - r} - carry_{i-1}) \bmod m - * @f] - * - * The size of the state is @f$r@f$ - * and the maximum period of the generator is @f$(m^r - m^s - 1)@f$. - */ - template - class subtract_with_carry_engine - { - static_assert(std::is_unsigned<_UIntType>::value, - "result_type must be an unsigned integral type"); - static_assert(0u < __s && __s < __r, - "0 < s < r"); - static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, - "template argument substituting __w out of bounds"); - - template - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, subtract_with_carry_engine, _UIntType>::value>::type; - - public: - /** The type of the generated random value. */ - typedef _UIntType result_type; - - // parameter values - static constexpr size_t word_size = __w; - static constexpr size_t short_lag = __s; - static constexpr size_t long_lag = __r; - static constexpr result_type default_seed = 19780503u; - - subtract_with_carry_engine() : subtract_with_carry_engine(default_seed) - { } - - /** - * @brief Constructs an explicitly seeded %subtract_with_carry_engine - * random number generator. - */ - explicit - subtract_with_carry_engine(result_type __sd) - { seed(__sd); } - - /** - * @brief Constructs a %subtract_with_carry_engine random number engine - * seeded from the seed sequence @p __q. - * - * @param __q the seed sequence. - */ - template> - explicit - subtract_with_carry_engine(_Sseq& __q) - { seed(__q); } - - /** - * @brief Seeds the initial state @f$x_0@f$ of the random number - * generator. - * - * N1688[4.19] modifies this as follows. If @p __value == 0, - * sets value to 19780503. In any case, with a linear - * congruential generator lcg(i) having parameters @f$ m_{lcg} = - * 2147483563, a_{lcg} = 40014, c_{lcg} = 0, and lcg(0) = value - * @f$, sets @f$ x_{-r} \dots x_{-1} @f$ to @f$ lcg(1) \bmod m - * \dots lcg(r) \bmod m @f$ respectively. If @f$ x_{-1} = 0 @f$ - * set carry to 1, otherwise sets carry to 0. - */ - void - seed(result_type __sd = default_seed); - - /** - * @brief Seeds the initial state @f$x_0@f$ of the - * % subtract_with_carry_engine random number generator. - */ - template - _If_seed_seq<_Sseq> - seed(_Sseq& __q); - - /** - * @brief Gets the inclusive minimum value of the range of random - * integers returned by this generator. - */ - static constexpr result_type - min() - { return 0; } - - /** - * @brief Gets the inclusive maximum value of the range of random - * integers returned by this generator. - */ - static constexpr result_type - max() - { return __detail::_Shift<_UIntType, __w>::__value - 1; } - - /** - * @brief Discard a sequence of random numbers. - */ - void - discard(unsigned long long __z) - { - for (; __z != 0ULL; --__z) - (*this)(); - } - - /** - * @brief Gets the next random number in the sequence. - */ - result_type - operator()(); - - /** - * @brief Compares two % subtract_with_carry_engine random number - * generator objects of the same type for equality. - * - * @param __lhs A % subtract_with_carry_engine random number generator - * object. - * @param __rhs Another % subtract_with_carry_engine random number - * generator object. - * - * @returns true if the infinite sequences of generated values - * would be equal, false otherwise. - */ - friend bool - operator==(const subtract_with_carry_engine& __lhs, - const subtract_with_carry_engine& __rhs) - { return (std::equal(__lhs._M_x, __lhs._M_x + long_lag, __rhs._M_x) - && __lhs._M_carry == __rhs._M_carry - && __lhs._M_p == __rhs._M_p); } - - private: - /// The state of the generator. This is a ring buffer. - _UIntType _M_x[long_lag]; - _UIntType _M_carry; ///< The carry - size_t _M_p; ///< Current index of x(i - r). - }; - - /** - * @brief Compares two % subtract_with_carry_engine random number - * generator objects of the same type for inequality. - * - * @param __lhs A % subtract_with_carry_engine random number generator - * object. - * @param __rhs Another % subtract_with_carry_engine random number - * generator object. - * - * @returns true if the infinite sequences of generated values - * would be different, false otherwise. - */ - template - inline bool - operator!=(const std::subtract_with_carry_engine<_UIntType, __w, - __s, __r>& __lhs, - const std::subtract_with_carry_engine<_UIntType, __w, - __s, __r>& __rhs) - { return !(__lhs == __rhs); } - - - /** - * Produces random numbers from some base engine by discarding blocks of - * data. - * - * 0 <= @p __r <= @p __p - */ - template - class discard_block_engine - { - static_assert(1 <= __r && __r <= __p, - "template argument substituting __r out of bounds"); - - public: - /** The type of the generated random value. */ - typedef typename _RandomNumberEngine::result_type result_type; - - template - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, discard_block_engine, result_type>::value>::type; - - // parameter values - static constexpr size_t block_size = __p; - static constexpr size_t used_block = __r; - - /** - * @brief Constructs a default %discard_block_engine engine. - * - * The underlying engine is default constructed as well. - */ - discard_block_engine() - : _M_b(), _M_n(0) { } - - /** - * @brief Copy constructs a %discard_block_engine engine. - * - * Copies an existing base class random number generator. - * @param __rng An existing (base class) engine object. - */ - explicit - discard_block_engine(const _RandomNumberEngine& __rng) - : _M_b(__rng), _M_n(0) { } - - /** - * @brief Move constructs a %discard_block_engine engine. - * - * Copies an existing base class random number generator. - * @param __rng An existing (base class) engine object. - */ - explicit - discard_block_engine(_RandomNumberEngine&& __rng) - : _M_b(std::move(__rng)), _M_n(0) { } - - /** - * @brief Seed constructs a %discard_block_engine engine. - * - * Constructs the underlying generator engine seeded with @p __s. - * @param __s A seed value for the base class engine. - */ - explicit - discard_block_engine(result_type __s) - : _M_b(__s), _M_n(0) { } - - /** - * @brief Generator construct a %discard_block_engine engine. - * - * @param __q A seed sequence. - */ - template> - explicit - discard_block_engine(_Sseq& __q) - : _M_b(__q), _M_n(0) - { } - - /** - * @brief Reseeds the %discard_block_engine object with the default - * seed for the underlying base class generator engine. - */ - void - seed() - { - _M_b.seed(); - _M_n = 0; - } - - /** - * @brief Reseeds the %discard_block_engine object with the default - * seed for the underlying base class generator engine. - */ - void - seed(result_type __s) - { - _M_b.seed(__s); - _M_n = 0; - } - - /** - * @brief Reseeds the %discard_block_engine object with the given seed - * sequence. - * @param __q A seed generator function. - */ - template - _If_seed_seq<_Sseq> - seed(_Sseq& __q) - { - _M_b.seed(__q); - _M_n = 0; - } - - /** - * @brief Gets a const reference to the underlying generator engine - * object. - */ - const _RandomNumberEngine& - base() const noexcept - { return _M_b; } - - /** - * @brief Gets the minimum value in the generated random number range. - */ - static constexpr result_type - min() - { return _RandomNumberEngine::min(); } - - /** - * @brief Gets the maximum value in the generated random number range. - */ - static constexpr result_type - max() - { return _RandomNumberEngine::max(); } - - /** - * @brief Discard a sequence of random numbers. - */ - void - discard(unsigned long long __z) - { - for (; __z != 0ULL; --__z) - (*this)(); - } - - /** - * @brief Gets the next value in the generated random number sequence. - */ - result_type - operator()(); - - /** - * @brief Compares two %discard_block_engine random number generator - * objects of the same type for equality. - * - * @param __lhs A %discard_block_engine random number generator object. - * @param __rhs Another %discard_block_engine random number generator - * object. - * - * @returns true if the infinite sequences of generated values - * would be equal, false otherwise. - */ - friend bool - operator==(const discard_block_engine& __lhs, - const discard_block_engine& __rhs) - { return __lhs._M_b == __rhs._M_b && __lhs._M_n == __rhs._M_n; } - - private: - _RandomNumberEngine _M_b; - size_t _M_n; - }; - - /** - * @brief Compares two %discard_block_engine random number generator - * objects of the same type for inequality. - * - * @param __lhs A %discard_block_engine random number generator object. - * @param __rhs Another %discard_block_engine random number generator - * object. - * - * @returns true if the infinite sequences of generated values - * would be different, false otherwise. - */ - template - inline bool - operator!=(const std::discard_block_engine<_RandomNumberEngine, __p, - __r>& __lhs, - const std::discard_block_engine<_RandomNumberEngine, __p, - __r>& __rhs) - { return !(__lhs == __rhs); } - - - /** - * Produces random numbers by combining random numbers from some base - * engine to produce random numbers with a specifies number of bits @p __w. - */ - template - class independent_bits_engine - { - static_assert(std::is_unsigned<_UIntType>::value, - "result_type must be an unsigned integral type"); - static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, - "template argument substituting __w out of bounds"); - - template - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, independent_bits_engine, _UIntType>::value>::type; - - public: - /** The type of the generated random value. */ - typedef _UIntType result_type; - - /** - * @brief Constructs a default %independent_bits_engine engine. - * - * The underlying engine is default constructed as well. - */ - independent_bits_engine() - : _M_b() { } - - /** - * @brief Copy constructs a %independent_bits_engine engine. - * - * Copies an existing base class random number generator. - * @param __rng An existing (base class) engine object. - */ - explicit - independent_bits_engine(const _RandomNumberEngine& __rng) - : _M_b(__rng) { } - - /** - * @brief Move constructs a %independent_bits_engine engine. - * - * Copies an existing base class random number generator. - * @param __rng An existing (base class) engine object. - */ - explicit - independent_bits_engine(_RandomNumberEngine&& __rng) - : _M_b(std::move(__rng)) { } - - /** - * @brief Seed constructs a %independent_bits_engine engine. - * - * Constructs the underlying generator engine seeded with @p __s. - * @param __s A seed value for the base class engine. - */ - explicit - independent_bits_engine(result_type __s) - : _M_b(__s) { } - - /** - * @brief Generator construct a %independent_bits_engine engine. - * - * @param __q A seed sequence. - */ - template> - explicit - independent_bits_engine(_Sseq& __q) - : _M_b(__q) - { } - - /** - * @brief Reseeds the %independent_bits_engine object with the default - * seed for the underlying base class generator engine. - */ - void - seed() - { _M_b.seed(); } - - /** - * @brief Reseeds the %independent_bits_engine object with the default - * seed for the underlying base class generator engine. - */ - void - seed(result_type __s) - { _M_b.seed(__s); } - - /** - * @brief Reseeds the %independent_bits_engine object with the given - * seed sequence. - * @param __q A seed generator function. - */ - template - _If_seed_seq<_Sseq> - seed(_Sseq& __q) - { _M_b.seed(__q); } - - /** - * @brief Gets a const reference to the underlying generator engine - * object. - */ - const _RandomNumberEngine& - base() const noexcept - { return _M_b; } - - /** - * @brief Gets the minimum value in the generated random number range. - */ - static constexpr result_type - min() - { return 0U; } - - /** - * @brief Gets the maximum value in the generated random number range. - */ - static constexpr result_type - max() - { return __detail::_Shift<_UIntType, __w>::__value - 1; } - - /** - * @brief Discard a sequence of random numbers. - */ - void - discard(unsigned long long __z) - { - for (; __z != 0ULL; --__z) - (*this)(); - } - - /** - * @brief Gets the next value in the generated random number sequence. - */ - result_type - operator()(); - - /** - * @brief Compares two %independent_bits_engine random number generator - * objects of the same type for equality. - * - * @param __lhs A %independent_bits_engine random number generator - * object. - * @param __rhs Another %independent_bits_engine random number generator - * object. - * - * @returns true if the infinite sequences of generated values - * would be equal, false otherwise. - */ - friend bool - operator==(const independent_bits_engine& __lhs, - const independent_bits_engine& __rhs) - { return __lhs._M_b == __rhs._M_b; } - - private: - _RandomNumberEngine _M_b; - }; - - /** - * @brief Compares two %independent_bits_engine random number generator - * objects of the same type for inequality. - * - * @param __lhs A %independent_bits_engine random number generator - * object. - * @param __rhs Another %independent_bits_engine random number generator - * object. - * - * @returns true if the infinite sequences of generated values - * would be different, false otherwise. - */ - template - inline bool - operator!=(const std::independent_bits_engine<_RandomNumberEngine, __w, - _UIntType>& __lhs, - const std::independent_bits_engine<_RandomNumberEngine, __w, - _UIntType>& __rhs) - { return !(__lhs == __rhs); } - - - - /** - * @brief Produces random numbers by combining random numbers from some - * base engine to produce random numbers with a specifies number of bits - * @p __k. - */ - template - class shuffle_order_engine - { - static_assert(1u <= __k, "template argument substituting " - "__k out of bound"); - - public: - /** The type of the generated random value. */ - typedef typename _RandomNumberEngine::result_type result_type; - - template - using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< - _Sseq, shuffle_order_engine, result_type>::value>::type; - - static constexpr size_t table_size = __k; - - /** - * @brief Constructs a default %shuffle_order_engine engine. - * - * The underlying engine is default constructed as well. - */ - shuffle_order_engine() - : _M_b() - { _M_initialize(); } - - /** - * @brief Copy constructs a %shuffle_order_engine engine. - * - * Copies an existing base class random number generator. - * @param __rng An existing (base class) engine object. - */ - explicit - shuffle_order_engine(const _RandomNumberEngine& __rng) - : _M_b(__rng) - { _M_initialize(); } - - /** - * @brief Move constructs a %shuffle_order_engine engine. - * - * Copies an existing base class random number generator. - * @param __rng An existing (base class) engine object. - */ - explicit - shuffle_order_engine(_RandomNumberEngine&& __rng) - : _M_b(std::move(__rng)) - { _M_initialize(); } - - /** - * @brief Seed constructs a %shuffle_order_engine engine. - * - * Constructs the underlying generator engine seeded with @p __s. - * @param __s A seed value for the base class engine. - */ - explicit - shuffle_order_engine(result_type __s) - : _M_b(__s) - { _M_initialize(); } - - /** - * @brief Generator construct a %shuffle_order_engine engine. - * - * @param __q A seed sequence. - */ - template> - explicit - shuffle_order_engine(_Sseq& __q) - : _M_b(__q) - { _M_initialize(); } - - /** - * @brief Reseeds the %shuffle_order_engine object with the default seed - for the underlying base class generator engine. - */ - void - seed() - { - _M_b.seed(); - _M_initialize(); - } - - /** - * @brief Reseeds the %shuffle_order_engine object with the default seed - * for the underlying base class generator engine. - */ - void - seed(result_type __s) - { - _M_b.seed(__s); - _M_initialize(); - } - - /** - * @brief Reseeds the %shuffle_order_engine object with the given seed - * sequence. - * @param __q A seed generator function. - */ - template - _If_seed_seq<_Sseq> - seed(_Sseq& __q) - { - _M_b.seed(__q); - _M_initialize(); - } - - /** - * Gets a const reference to the underlying generator engine object. - */ - const _RandomNumberEngine& - base() const noexcept - { return _M_b; } - - /** - * Gets the minimum value in the generated random number range. - */ - static constexpr result_type - min() - { return _RandomNumberEngine::min(); } - - /** - * Gets the maximum value in the generated random number range. - */ - static constexpr result_type - max() - { return _RandomNumberEngine::max(); } - - /** - * Discard a sequence of random numbers. - */ - void - discard(unsigned long long __z) - { - for (; __z != 0ULL; --__z) - (*this)(); - } - - /** - * Gets the next value in the generated random number sequence. - */ - result_type - operator()(); - - /** - * Compares two %shuffle_order_engine random number generator objects - * of the same type for equality. - * - * @param __lhs A %shuffle_order_engine random number generator object. - * @param __rhs Another %shuffle_order_engine random number generator - * object. - * - * @returns true if the infinite sequences of generated values - * would be equal, false otherwise. - */ - friend bool - operator==(const shuffle_order_engine& __lhs, - const shuffle_order_engine& __rhs) - { return (__lhs._M_b == __rhs._M_b - && std::equal(__lhs._M_v, __lhs._M_v + __k, __rhs._M_v) - && __lhs._M_y == __rhs._M_y); } - - - private: - void _M_initialize() - { - for (size_t __i = 0; __i < __k; ++__i) - _M_v[__i] = _M_b(); - _M_y = _M_b(); - } - - _RandomNumberEngine _M_b; - result_type _M_v[__k]; - result_type _M_y; - }; - - /** - * Compares two %shuffle_order_engine random number generator objects - * of the same type for inequality. - * - * @param __lhs A %shuffle_order_engine random number generator object. - * @param __rhs Another %shuffle_order_engine random number generator - * object. - * - * @returns true if the infinite sequences of generated values - * would be different, false otherwise. - */ - template - inline bool - operator!=(const std::shuffle_order_engine<_RandomNumberEngine, - __k>& __lhs, - const std::shuffle_order_engine<_RandomNumberEngine, - __k>& __rhs) - { return !(__lhs == __rhs); } - - - /** - * The classic Minimum Standard rand0 of Lewis, Goodman, and Miller. - */ - typedef linear_congruential_engine - minstd_rand0; - - /** - * An alternative LCR (Lehmer Generator function). - */ - typedef linear_congruential_engine - minstd_rand; - - /** - * The classic Mersenne Twister. - * - * Reference: - * M. Matsumoto and T. Nishimura, Mersenne Twister: A 623-Dimensionally - * Equidistributed Uniform Pseudo-Random Number Generator, ACM Transactions - * on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. - */ - typedef mersenne_twister_engine< - uint_fast32_t, - 32, 624, 397, 31, - 0x9908b0dfUL, 11, - 0xffffffffUL, 7, - 0x9d2c5680UL, 15, - 0xefc60000UL, 18, 1812433253UL> mt19937; - - /** - * An alternative Mersenne Twister. - */ - typedef mersenne_twister_engine< - uint_fast64_t, - 64, 312, 156, 31, - 0xb5026f5aa96619e9ULL, 29, - 0x5555555555555555ULL, 17, - 0x71d67fffeda60000ULL, 37, - 0xfff7eee000000000ULL, 43, - 6364136223846793005ULL> mt19937_64; - - typedef subtract_with_carry_engine - ranlux24_base; - - typedef subtract_with_carry_engine - ranlux48_base; - - typedef discard_block_engine ranlux24; - - typedef discard_block_engine ranlux48; - - typedef shuffle_order_engine knuth_b; - - typedef minstd_rand0 default_random_engine; - - /* @} */ // group random_generators - - /** - * @addtogroup random_distributions Random Number Distributions - * @ingroup random - * @{ - */ - - /** - * @addtogroup random_distributions_uniform Uniform Distributions - * @ingroup random_distributions - * @{ - */ - - // std::uniform_int_distribution is defined in - - /** - * @brief Return true if two uniform integer distributions have - * different parameters. - */ - template - inline bool - operator!=(const std::uniform_int_distribution<_IntType>& __d1, - const std::uniform_int_distribution<_IntType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief Uniform continuous distribution for random numbers. - * - * A continuous random distribution on the range [min, max) with equal - * probability throughout the range. The URNG should be real-valued and - * deliver number in the range [0, 1). - */ - template - class uniform_real_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef uniform_real_distribution<_RealType> distribution_type; - - param_type() : param_type(0) { } - - explicit - param_type(_RealType __a, _RealType __b = _RealType(1)) - : _M_a(__a), _M_b(__b) - { - __glibcxx_assert(_M_a <= _M_b); - } - - result_type - a() const - { return _M_a; } - - result_type - b() const - { return _M_b; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_a; - _RealType _M_b; - }; - - public: - /** - * @brief Constructs a uniform_real_distribution object. - * - * The lower bound is set to 0.0 and the upper bound to 1.0 - */ - uniform_real_distribution() : uniform_real_distribution(0.0) { } - - /** - * @brief Constructs a uniform_real_distribution object. - * - * @param __a [IN] The lower bound of the distribution. - * @param __b [IN] The upper bound of the distribution. - */ - explicit - uniform_real_distribution(_RealType __a, _RealType __b = _RealType(1)) - : _M_param(__a, __b) - { } - - explicit - uniform_real_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - * - * Does nothing for the uniform real distribution. - */ - void - reset() { } - - result_type - a() const - { return _M_param.a(); } - - result_type - b() const - { return _M_param.b(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the inclusive lower bound of the distribution range. - */ - result_type - min() const - { return this->a(); } - - /** - * @brief Returns the inclusive upper bound of the distribution range. - */ - result_type - max() const - { return this->b(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - return (__aurng() * (__p.b() - __p.a())) + __p.a(); - } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two uniform real distributions have - * the same parameters. - */ - friend bool - operator==(const uniform_real_distribution& __d1, - const uniform_real_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two uniform real distributions have - * different parameters. - */ - template - inline bool - operator!=(const std::uniform_real_distribution<_IntType>& __d1, - const std::uniform_real_distribution<_IntType>& __d2) - { return !(__d1 == __d2); } - - /* @} */ // group random_distributions_uniform - - /** - * @addtogroup random_distributions_normal Normal Distributions - * @ingroup random_distributions - * @{ - */ - - /** - * @brief A normal continuous distribution for random numbers. - * - * The formula for the normal probability density function is - * @f[ - * p(x|\mu,\sigma) = \frac{1}{\sigma \sqrt{2 \pi}} - * e^{- \frac{{x - \mu}^ {2}}{2 \sigma ^ {2}} } - * @f] - */ - template - class normal_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef normal_distribution<_RealType> distribution_type; - - param_type() : param_type(0.0) { } - - explicit - param_type(_RealType __mean, _RealType __stddev = _RealType(1)) - : _M_mean(__mean), _M_stddev(__stddev) - { - __glibcxx_assert(_M_stddev > _RealType(0)); - } - - _RealType - mean() const - { return _M_mean; } - - _RealType - stddev() const - { return _M_stddev; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return (__p1._M_mean == __p2._M_mean - && __p1._M_stddev == __p2._M_stddev); } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_mean; - _RealType _M_stddev; - }; - - public: - normal_distribution() : normal_distribution(0.0) { } - - /** - * Constructs a normal distribution with parameters @f$mean@f$ and - * standard deviation. - */ - explicit - normal_distribution(result_type __mean, - result_type __stddev = result_type(1)) - : _M_param(__mean, __stddev), _M_saved_available(false) - { } - - explicit - normal_distribution(const param_type& __p) - : _M_param(__p), _M_saved_available(false) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { _M_saved_available = false; } - - /** - * @brief Returns the mean of the distribution. - */ - _RealType - mean() const - { return _M_param.mean(); } - - /** - * @brief Returns the standard deviation of the distribution. - */ - _RealType - stddev() const - { return _M_param.stddev(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return std::numeric_limits::lowest(); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two normal distributions have - * the same parameters and the sequences that would - * be generated are equal. - */ - template - friend bool - operator==(const std::normal_distribution<_RealType1>& __d1, - const std::normal_distribution<_RealType1>& __d2); - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - result_type _M_saved; - bool _M_saved_available; - }; - - /** - * @brief Return true if two normal distributions are different. - */ - template - inline bool - operator!=(const std::normal_distribution<_RealType>& __d1, - const std::normal_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A lognormal_distribution random number distribution. - * - * The formula for the normal probability mass function is - * @f[ - * p(x|m,s) = \frac{1}{sx\sqrt{2\pi}} - * \exp{-\frac{(\ln{x} - m)^2}{2s^2}} - * @f] - */ - template - class lognormal_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef lognormal_distribution<_RealType> distribution_type; - - param_type() : param_type(0.0) { } - - explicit - param_type(_RealType __m, _RealType __s = _RealType(1)) - : _M_m(__m), _M_s(__s) - { } - - _RealType - m() const - { return _M_m; } - - _RealType - s() const - { return _M_s; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_m == __p2._M_m && __p1._M_s == __p2._M_s; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_m; - _RealType _M_s; - }; - - lognormal_distribution() : lognormal_distribution(0.0) { } - - explicit - lognormal_distribution(_RealType __m, _RealType __s = _RealType(1)) - : _M_param(__m, __s), _M_nd() - { } - - explicit - lognormal_distribution(const param_type& __p) - : _M_param(__p), _M_nd() - { } - - /** - * Resets the distribution state. - */ - void - reset() - { _M_nd.reset(); } - - /** - * - */ - _RealType - m() const - { return _M_param.m(); } - - _RealType - s() const - { return _M_param.s(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { return std::exp(__p.s() * _M_nd(__urng) + __p.m()); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two lognormal distributions have - * the same parameters and the sequences that would - * be generated are equal. - */ - friend bool - operator==(const lognormal_distribution& __d1, - const lognormal_distribution& __d2) - { return (__d1._M_param == __d2._M_param - && __d1._M_nd == __d2._M_nd); } - - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - - std::normal_distribution _M_nd; - }; - - /** - * @brief Return true if two lognormal distributions are different. - */ - template - inline bool - operator!=(const std::lognormal_distribution<_RealType>& __d1, - const std::lognormal_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A gamma continuous distribution for random numbers. - * - * The formula for the gamma probability density function is: - * @f[ - * p(x|\alpha,\beta) = \frac{1}{\beta\Gamma(\alpha)} - * (x/\beta)^{\alpha - 1} e^{-x/\beta} - * @f] - */ - template - class gamma_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef gamma_distribution<_RealType> distribution_type; - friend class gamma_distribution<_RealType>; - - param_type() : param_type(1.0) { } - - explicit - param_type(_RealType __alpha_val, _RealType __beta_val = _RealType(1)) - : _M_alpha(__alpha_val), _M_beta(__beta_val) - { - __glibcxx_assert(_M_alpha > _RealType(0)); - _M_initialize(); - } - - _RealType - alpha() const - { return _M_alpha; } - - _RealType - beta() const - { return _M_beta; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return (__p1._M_alpha == __p2._M_alpha - && __p1._M_beta == __p2._M_beta); } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - void - _M_initialize(); - - _RealType _M_alpha; - _RealType _M_beta; - - _RealType _M_malpha, _M_a2; - }; - - public: - /** - * @brief Constructs a gamma distribution with parameters 1 and 1. - */ - gamma_distribution() : gamma_distribution(1.0) { } - - /** - * @brief Constructs a gamma distribution with parameters - * @f$\alpha@f$ and @f$\beta@f$. - */ - explicit - gamma_distribution(_RealType __alpha_val, - _RealType __beta_val = _RealType(1)) - : _M_param(__alpha_val, __beta_val), _M_nd() - { } - - explicit - gamma_distribution(const param_type& __p) - : _M_param(__p), _M_nd() - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { _M_nd.reset(); } - - /** - * @brief Returns the @f$\alpha@f$ of the distribution. - */ - _RealType - alpha() const - { return _M_param.alpha(); } - - /** - * @brief Returns the @f$\beta@f$ of the distribution. - */ - _RealType - beta() const - { return _M_param.beta(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two gamma distributions have the same - * parameters and the sequences that would be generated - * are equal. - */ - friend bool - operator==(const gamma_distribution& __d1, - const gamma_distribution& __d2) - { return (__d1._M_param == __d2._M_param - && __d1._M_nd == __d2._M_nd); } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - - std::normal_distribution _M_nd; - }; - - /** - * @brief Return true if two gamma distributions are different. - */ - template - inline bool - operator!=(const std::gamma_distribution<_RealType>& __d1, - const std::gamma_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A chi_squared_distribution random number distribution. - * - * The formula for the normal probability mass function is - * @f$p(x|n) = \frac{x^{(n/2) - 1}e^{-x/2}}{\Gamma(n/2) 2^{n/2}}@f$ - */ - template - class chi_squared_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef chi_squared_distribution<_RealType> distribution_type; - - param_type() : param_type(1) { } - - explicit - param_type(_RealType __n) - : _M_n(__n) - { } - - _RealType - n() const - { return _M_n; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_n == __p2._M_n; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_n; - }; - - chi_squared_distribution() : chi_squared_distribution(1) { } - - explicit - chi_squared_distribution(_RealType __n) - : _M_param(__n), _M_gd(__n / 2) - { } - - explicit - chi_squared_distribution(const param_type& __p) - : _M_param(__p), _M_gd(__p.n() / 2) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { _M_gd.reset(); } - - /** - * - */ - _RealType - n() const - { return _M_param.n(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { - _M_param = __param; - typedef typename std::gamma_distribution::param_type - param_type; - _M_gd.param(param_type{__param.n() / 2}); - } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return 2 * _M_gd(__urng); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - typedef typename std::gamma_distribution::param_type - param_type; - return 2 * _M_gd(__urng, param_type(__p.n() / 2)); - } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate_impl(__f, __t, __urng); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { typename std::gamma_distribution::param_type - __p2(__p.n() / 2); - this->__generate_impl(__f, __t, __urng, __p2); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate_impl(__f, __t, __urng); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { typename std::gamma_distribution::param_type - __p2(__p.n() / 2); - this->__generate_impl(__f, __t, __urng, __p2); } - - /** - * @brief Return true if two Chi-squared distributions have - * the same parameters and the sequences that would be - * generated are equal. - */ - friend bool - operator==(const chi_squared_distribution& __d1, - const chi_squared_distribution& __d2) - { return __d1._M_param == __d2._M_param && __d1._M_gd == __d2._M_gd; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng); - - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const typename - std::gamma_distribution::param_type& __p); - - param_type _M_param; - - std::gamma_distribution _M_gd; - }; - - /** - * @brief Return true if two Chi-squared distributions are different. - */ - template - inline bool - operator!=(const std::chi_squared_distribution<_RealType>& __d1, - const std::chi_squared_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A cauchy_distribution random number distribution. - * - * The formula for the normal probability mass function is - * @f$p(x|a,b) = (\pi b (1 + (\frac{x-a}{b})^2))^{-1}@f$ - */ - template - class cauchy_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef cauchy_distribution<_RealType> distribution_type; - - param_type() : param_type(0) { } - - explicit - param_type(_RealType __a, _RealType __b = _RealType(1)) - : _M_a(__a), _M_b(__b) - { } - - _RealType - a() const - { return _M_a; } - - _RealType - b() const - { return _M_b; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_a; - _RealType _M_b; - }; - - cauchy_distribution() : cauchy_distribution(0.0) { } - - explicit - cauchy_distribution(_RealType __a, _RealType __b = 1.0) - : _M_param(__a, __b) - { } - - explicit - cauchy_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { } - - /** - * - */ - _RealType - a() const - { return _M_param.a(); } - - _RealType - b() const - { return _M_param.b(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return std::numeric_limits::lowest(); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two Cauchy distributions have - * the same parameters. - */ - friend bool - operator==(const cauchy_distribution& __d1, - const cauchy_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two Cauchy distributions have - * different parameters. - */ - template - inline bool - operator!=(const std::cauchy_distribution<_RealType>& __d1, - const std::cauchy_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - - /** - * @brief A fisher_f_distribution random number distribution. - * - * The formula for the normal probability mass function is - * @f[ - * p(x|m,n) = \frac{\Gamma((m+n)/2)}{\Gamma(m/2)\Gamma(n/2)} - * (\frac{m}{n})^{m/2} x^{(m/2)-1} - * (1 + \frac{mx}{n})^{-(m+n)/2} - * @f] - */ - template - class fisher_f_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef fisher_f_distribution<_RealType> distribution_type; - - param_type() : param_type(1) { } - - explicit - param_type(_RealType __m, _RealType __n = _RealType(1)) - : _M_m(__m), _M_n(__n) - { } - - _RealType - m() const - { return _M_m; } - - _RealType - n() const - { return _M_n; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_m == __p2._M_m && __p1._M_n == __p2._M_n; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_m; - _RealType _M_n; - }; - - fisher_f_distribution() : fisher_f_distribution(1.0) { } - - explicit - fisher_f_distribution(_RealType __m, - _RealType __n = _RealType(1)) - : _M_param(__m, __n), _M_gd_x(__m / 2), _M_gd_y(__n / 2) - { } - - explicit - fisher_f_distribution(const param_type& __p) - : _M_param(__p), _M_gd_x(__p.m() / 2), _M_gd_y(__p.n() / 2) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { - _M_gd_x.reset(); - _M_gd_y.reset(); - } - - /** - * - */ - _RealType - m() const - { return _M_param.m(); } - - _RealType - n() const - { return _M_param.n(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return (_M_gd_x(__urng) * n()) / (_M_gd_y(__urng) * m()); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - typedef typename std::gamma_distribution::param_type - param_type; - return ((_M_gd_x(__urng, param_type(__p.m() / 2)) * n()) - / (_M_gd_y(__urng, param_type(__p.n() / 2)) * m())); - } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate_impl(__f, __t, __urng); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate_impl(__f, __t, __urng); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two Fisher f distributions have - * the same parameters and the sequences that would - * be generated are equal. - */ - friend bool - operator==(const fisher_f_distribution& __d1, - const fisher_f_distribution& __d2) - { return (__d1._M_param == __d2._M_param - && __d1._M_gd_x == __d2._M_gd_x - && __d1._M_gd_y == __d2._M_gd_y); } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng); - - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - - std::gamma_distribution _M_gd_x, _M_gd_y; - }; - - /** - * @brief Return true if two Fisher f distributions are different. - */ - template - inline bool - operator!=(const std::fisher_f_distribution<_RealType>& __d1, - const std::fisher_f_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - /** - * @brief A student_t_distribution random number distribution. - * - * The formula for the normal probability mass function is: - * @f[ - * p(x|n) = \frac{1}{\sqrt(n\pi)} \frac{\Gamma((n+1)/2)}{\Gamma(n/2)} - * (1 + \frac{x^2}{n}) ^{-(n+1)/2} - * @f] - */ - template - class student_t_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef student_t_distribution<_RealType> distribution_type; - - param_type() : param_type(1) { } - - explicit - param_type(_RealType __n) - : _M_n(__n) - { } - - _RealType - n() const - { return _M_n; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_n == __p2._M_n; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_n; - }; - - student_t_distribution() : student_t_distribution(1.0) { } - - explicit - student_t_distribution(_RealType __n) - : _M_param(__n), _M_nd(), _M_gd(__n / 2, 2) - { } - - explicit - student_t_distribution(const param_type& __p) - : _M_param(__p), _M_nd(), _M_gd(__p.n() / 2, 2) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { - _M_nd.reset(); - _M_gd.reset(); - } - - /** - * - */ - _RealType - n() const - { return _M_param.n(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return std::numeric_limits::lowest(); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return _M_nd(__urng) * std::sqrt(n() / _M_gd(__urng)); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - typedef typename std::gamma_distribution::param_type - param_type; - - const result_type __g = _M_gd(__urng, param_type(__p.n() / 2, 2)); - return _M_nd(__urng) * std::sqrt(__p.n() / __g); - } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate_impl(__f, __t, __urng); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate_impl(__f, __t, __urng); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two Student t distributions have - * the same parameters and the sequences that would - * be generated are equal. - */ - friend bool - operator==(const student_t_distribution& __d1, - const student_t_distribution& __d2) - { return (__d1._M_param == __d2._M_param - && __d1._M_nd == __d2._M_nd && __d1._M_gd == __d2._M_gd); } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng); - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - - std::normal_distribution _M_nd; - std::gamma_distribution _M_gd; - }; - - /** - * @brief Return true if two Student t distributions are different. - */ - template - inline bool - operator!=(const std::student_t_distribution<_RealType>& __d1, - const std::student_t_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /* @} */ // group random_distributions_normal - - /** - * @addtogroup random_distributions_bernoulli Bernoulli Distributions - * @ingroup random_distributions - * @{ - */ - - /** - * @brief A Bernoulli random number distribution. - * - * Generates a sequence of true and false values with likelihood @f$p@f$ - * that true will come up and @f$(1 - p)@f$ that false will appear. - */ - class bernoulli_distribution - { - public: - /** The type of the range of the distribution. */ - typedef bool result_type; - - /** Parameter type. */ - struct param_type - { - typedef bernoulli_distribution distribution_type; - - param_type() : param_type(0.5) { } - - explicit - param_type(double __p) - : _M_p(__p) - { - __glibcxx_assert((_M_p >= 0.0) && (_M_p <= 1.0)); - } - - double - p() const - { return _M_p; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_p == __p2._M_p; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - double _M_p; - }; - - public: - /** - * @brief Constructs a Bernoulli distribution with likelihood 0.5. - */ - bernoulli_distribution() : bernoulli_distribution(0.5) { } - - /** - * @brief Constructs a Bernoulli distribution with likelihood @p p. - * - * @param __p [IN] The likelihood of a true result being returned. - * Must be in the interval @f$[0, 1]@f$. - */ - explicit - bernoulli_distribution(double __p) - : _M_param(__p) - { } - - explicit - bernoulli_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - * - * Does nothing for a Bernoulli distribution. - */ - void - reset() { } - - /** - * @brief Returns the @p p parameter of the distribution. - */ - double - p() const - { return _M_param.p(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return std::numeric_limits::min(); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - if ((__aurng() - __aurng.min()) - < __p.p() * (__aurng.max() - __aurng.min())) - return true; - return false; - } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two Bernoulli distributions have - * the same parameters. - */ - friend bool - operator==(const bernoulli_distribution& __d1, - const bernoulli_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two Bernoulli distributions have - * different parameters. - */ - inline bool - operator!=(const std::bernoulli_distribution& __d1, - const std::bernoulli_distribution& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A discrete binomial random number distribution. - * - * The formula for the binomial probability density function is - * @f$p(i|t,p) = \binom{t}{i} p^i (1 - p)^{t - i}@f$ where @f$t@f$ - * and @f$p@f$ are the parameters of the distribution. - */ - template - class binomial_distribution - { - static_assert(std::is_integral<_IntType>::value, - "result_type must be an integral type"); - - public: - /** The type of the range of the distribution. */ - typedef _IntType result_type; - - /** Parameter type. */ - struct param_type - { - typedef binomial_distribution<_IntType> distribution_type; - friend class binomial_distribution<_IntType>; - - param_type() : param_type(1) { } - - explicit - param_type(_IntType __t, double __p = 0.5) - : _M_t(__t), _M_p(__p) - { - __glibcxx_assert((_M_t >= _IntType(0)) - && (_M_p >= 0.0) - && (_M_p <= 1.0)); - _M_initialize(); - } - - _IntType - t() const - { return _M_t; } - - double - p() const - { return _M_p; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_t == __p2._M_t && __p1._M_p == __p2._M_p; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - void - _M_initialize(); - - _IntType _M_t; - double _M_p; - - double _M_q; -#if _GLIBCXX_USE_C99_MATH_TR1 - double _M_d1, _M_d2, _M_s1, _M_s2, _M_c, - _M_a1, _M_a123, _M_s, _M_lf, _M_lp1p; -#endif - bool _M_easy; - }; - - // constructors and member functions - - binomial_distribution() : binomial_distribution(1) { } - - explicit - binomial_distribution(_IntType __t, double __p = 0.5) - : _M_param(__t, __p), _M_nd() - { } - - explicit - binomial_distribution(const param_type& __p) - : _M_param(__p), _M_nd() - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { _M_nd.reset(); } - - /** - * @brief Returns the distribution @p t parameter. - */ - _IntType - t() const - { return _M_param.t(); } - - /** - * @brief Returns the distribution @p p parameter. - */ - double - p() const - { return _M_param.p(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return 0; } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return _M_param.t(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two binomial distributions have - * the same parameters and the sequences that would - * be generated are equal. - */ - friend bool - operator==(const binomial_distribution& __d1, - const binomial_distribution& __d2) -#ifdef _GLIBCXX_USE_C99_MATH_TR1 - { return __d1._M_param == __d2._M_param && __d1._M_nd == __d2._M_nd; } -#else - { return __d1._M_param == __d2._M_param; } -#endif - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - result_type - _M_waiting(_UniformRandomNumberGenerator& __urng, - _IntType __t, double __q); - - param_type _M_param; - - // NB: Unused when _GLIBCXX_USE_C99_MATH_TR1 is undefined. - std::normal_distribution _M_nd; - }; - - /** - * @brief Return true if two binomial distributions are different. - */ - template - inline bool - operator!=(const std::binomial_distribution<_IntType>& __d1, - const std::binomial_distribution<_IntType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A discrete geometric random number distribution. - * - * The formula for the geometric probability density function is - * @f$p(i|p) = p(1 - p)^{i}@f$ where @f$p@f$ is the parameter of the - * distribution. - */ - template - class geometric_distribution - { - static_assert(std::is_integral<_IntType>::value, - "result_type must be an integral type"); - - public: - /** The type of the range of the distribution. */ - typedef _IntType result_type; - - /** Parameter type. */ - struct param_type - { - typedef geometric_distribution<_IntType> distribution_type; - friend class geometric_distribution<_IntType>; - - param_type() : param_type(0.5) { } - - explicit - param_type(double __p) - : _M_p(__p) - { - __glibcxx_assert((_M_p > 0.0) && (_M_p < 1.0)); - _M_initialize(); - } - - double - p() const - { return _M_p; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_p == __p2._M_p; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - void - _M_initialize() - { _M_log_1_p = std::log(1.0 - _M_p); } - - double _M_p; - - double _M_log_1_p; - }; - - // constructors and member functions - - geometric_distribution() : geometric_distribution(0.5) { } - - explicit - geometric_distribution(double __p) - : _M_param(__p) - { } - - explicit - geometric_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - * - * Does nothing for the geometric distribution. - */ - void - reset() { } - - /** - * @brief Returns the distribution parameter @p p. - */ - double - p() const - { return _M_param.p(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return 0; } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two geometric distributions have - * the same parameters. - */ - friend bool - operator==(const geometric_distribution& __d1, - const geometric_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two geometric distributions have - * different parameters. - */ - template - inline bool - operator!=(const std::geometric_distribution<_IntType>& __d1, - const std::geometric_distribution<_IntType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A negative_binomial_distribution random number distribution. - * - * The formula for the negative binomial probability mass function is - * @f$p(i) = \binom{n}{i} p^i (1 - p)^{t - i}@f$ where @f$t@f$ - * and @f$p@f$ are the parameters of the distribution. - */ - template - class negative_binomial_distribution - { - static_assert(std::is_integral<_IntType>::value, - "result_type must be an integral type"); - - public: - /** The type of the range of the distribution. */ - typedef _IntType result_type; - - /** Parameter type. */ - struct param_type - { - typedef negative_binomial_distribution<_IntType> distribution_type; - - param_type() : param_type(1) { } - - explicit - param_type(_IntType __k, double __p = 0.5) - : _M_k(__k), _M_p(__p) - { - __glibcxx_assert((_M_k > 0) && (_M_p > 0.0) && (_M_p <= 1.0)); - } - - _IntType - k() const - { return _M_k; } - - double - p() const - { return _M_p; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_k == __p2._M_k && __p1._M_p == __p2._M_p; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _IntType _M_k; - double _M_p; - }; - - negative_binomial_distribution() : negative_binomial_distribution(1) { } - - explicit - negative_binomial_distribution(_IntType __k, double __p = 0.5) - : _M_param(__k, __p), _M_gd(__k, (1.0 - __p) / __p) - { } - - explicit - negative_binomial_distribution(const param_type& __p) - : _M_param(__p), _M_gd(__p.k(), (1.0 - __p.p()) / __p.p()) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { _M_gd.reset(); } - - /** - * @brief Return the @f$k@f$ parameter of the distribution. - */ - _IntType - k() const - { return _M_param.k(); } - - /** - * @brief Return the @f$p@f$ parameter of the distribution. - */ - double - p() const - { return _M_param.p(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng); - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate_impl(__f, __t, __urng); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate_impl(__f, __t, __urng); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two negative binomial distributions have - * the same parameters and the sequences that would be - * generated are equal. - */ - friend bool - operator==(const negative_binomial_distribution& __d1, - const negative_binomial_distribution& __d2) - { return __d1._M_param == __d2._M_param && __d1._M_gd == __d2._M_gd; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng); - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - - std::gamma_distribution _M_gd; - }; - - /** - * @brief Return true if two negative binomial distributions are different. - */ - template - inline bool - operator!=(const std::negative_binomial_distribution<_IntType>& __d1, - const std::negative_binomial_distribution<_IntType>& __d2) - { return !(__d1 == __d2); } - - - /* @} */ // group random_distributions_bernoulli - - /** - * @addtogroup random_distributions_poisson Poisson Distributions - * @ingroup random_distributions - * @{ - */ - - /** - * @brief A discrete Poisson random number distribution. - * - * The formula for the Poisson probability density function is - * @f$p(i|\mu) = \frac{\mu^i}{i!} e^{-\mu}@f$ where @f$\mu@f$ is the - * parameter of the distribution. - */ - template - class poisson_distribution - { - static_assert(std::is_integral<_IntType>::value, - "result_type must be an integral type"); - - public: - /** The type of the range of the distribution. */ - typedef _IntType result_type; - - /** Parameter type. */ - struct param_type - { - typedef poisson_distribution<_IntType> distribution_type; - friend class poisson_distribution<_IntType>; - - param_type() : param_type(1.0) { } - - explicit - param_type(double __mean) - : _M_mean(__mean) - { - __glibcxx_assert(_M_mean > 0.0); - _M_initialize(); - } - - double - mean() const - { return _M_mean; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_mean == __p2._M_mean; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - // Hosts either log(mean) or the threshold of the simple method. - void - _M_initialize(); - - double _M_mean; - - double _M_lm_thr; -#if _GLIBCXX_USE_C99_MATH_TR1 - double _M_lfm, _M_sm, _M_d, _M_scx, _M_1cx, _M_c2b, _M_cb; -#endif - }; - - // constructors and member functions - - poisson_distribution() : poisson_distribution(1.0) { } - - explicit - poisson_distribution(double __mean) - : _M_param(__mean), _M_nd() - { } - - explicit - poisson_distribution(const param_type& __p) - : _M_param(__p), _M_nd() - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { _M_nd.reset(); } - - /** - * @brief Returns the distribution parameter @p mean. - */ - double - mean() const - { return _M_param.mean(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return 0; } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two Poisson distributions have the same - * parameters and the sequences that would be generated - * are equal. - */ - friend bool - operator==(const poisson_distribution& __d1, - const poisson_distribution& __d2) -#ifdef _GLIBCXX_USE_C99_MATH_TR1 - { return __d1._M_param == __d2._M_param && __d1._M_nd == __d2._M_nd; } -#else - { return __d1._M_param == __d2._M_param; } -#endif - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - - // NB: Unused when _GLIBCXX_USE_C99_MATH_TR1 is undefined. - std::normal_distribution _M_nd; - }; - - /** - * @brief Return true if two Poisson distributions are different. - */ - template - inline bool - operator!=(const std::poisson_distribution<_IntType>& __d1, - const std::poisson_distribution<_IntType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief An exponential continuous distribution for random numbers. - * - * The formula for the exponential probability density function is - * @f$p(x|\lambda) = \lambda e^{-\lambda x}@f$. - * - * - * - * - * - * - * - * - *
Distribution Statistics
Mean@f$\frac{1}{\lambda}@f$
Median@f$\frac{\ln 2}{\lambda}@f$
Mode@f$zero@f$
Range@f$[0, \infty]@f$
Standard Deviation@f$\frac{1}{\lambda}@f$
- */ - template - class exponential_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef exponential_distribution<_RealType> distribution_type; - - param_type() : param_type(1.0) { } - - explicit - param_type(_RealType __lambda) - : _M_lambda(__lambda) - { - __glibcxx_assert(_M_lambda > _RealType(0)); - } - - _RealType - lambda() const - { return _M_lambda; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_lambda == __p2._M_lambda; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_lambda; - }; - - public: - /** - * @brief Constructs an exponential distribution with inverse scale - * parameter 1.0 - */ - exponential_distribution() : exponential_distribution(1.0) { } - - /** - * @brief Constructs an exponential distribution with inverse scale - * parameter @f$\lambda@f$. - */ - explicit - exponential_distribution(_RealType __lambda) - : _M_param(__lambda) - { } - - explicit - exponential_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - * - * Has no effect on exponential distributions. - */ - void - reset() { } - - /** - * @brief Returns the inverse scale parameter of the distribution. - */ - _RealType - lambda() const - { return _M_param.lambda(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - return -std::log(result_type(1) - __aurng()) / __p.lambda(); - } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two exponential distributions have the same - * parameters. - */ - friend bool - operator==(const exponential_distribution& __d1, - const exponential_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two exponential distributions have different - * parameters. - */ - template - inline bool - operator!=(const std::exponential_distribution<_RealType>& __d1, - const std::exponential_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A weibull_distribution random number distribution. - * - * The formula for the normal probability density function is: - * @f[ - * p(x|\alpha,\beta) = \frac{\alpha}{\beta} (\frac{x}{\beta})^{\alpha-1} - * \exp{(-(\frac{x}{\beta})^\alpha)} - * @f] - */ - template - class weibull_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef weibull_distribution<_RealType> distribution_type; - - param_type() : param_type(1.0) { } - - explicit - param_type(_RealType __a, _RealType __b = _RealType(1.0)) - : _M_a(__a), _M_b(__b) - { } - - _RealType - a() const - { return _M_a; } - - _RealType - b() const - { return _M_b; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_a; - _RealType _M_b; - }; - - weibull_distribution() : weibull_distribution(1.0) { } - - explicit - weibull_distribution(_RealType __a, _RealType __b = _RealType(1)) - : _M_param(__a, __b) - { } - - explicit - weibull_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { } - - /** - * @brief Return the @f$a@f$ parameter of the distribution. - */ - _RealType - a() const - { return _M_param.a(); } - - /** - * @brief Return the @f$b@f$ parameter of the distribution. - */ - _RealType - b() const - { return _M_param.b(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two Weibull distributions have the same - * parameters. - */ - friend bool - operator==(const weibull_distribution& __d1, - const weibull_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two Weibull distributions have different - * parameters. - */ - template - inline bool - operator!=(const std::weibull_distribution<_RealType>& __d1, - const std::weibull_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A extreme_value_distribution random number distribution. - * - * The formula for the normal probability mass function is - * @f[ - * p(x|a,b) = \frac{1}{b} - * \exp( \frac{a-x}{b} - \exp(\frac{a-x}{b})) - * @f] - */ - template - class extreme_value_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef extreme_value_distribution<_RealType> distribution_type; - - param_type() : param_type(0.0) { } - - explicit - param_type(_RealType __a, _RealType __b = _RealType(1.0)) - : _M_a(__a), _M_b(__b) - { } - - _RealType - a() const - { return _M_a; } - - _RealType - b() const - { return _M_b; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _RealType _M_a; - _RealType _M_b; - }; - - extreme_value_distribution() : extreme_value_distribution(0.0) { } - - explicit - extreme_value_distribution(_RealType __a, _RealType __b = _RealType(1)) - : _M_param(__a, __b) - { } - - explicit - extreme_value_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { } - - /** - * @brief Return the @f$a@f$ parameter of the distribution. - */ - _RealType - a() const - { return _M_param.a(); } - - /** - * @brief Return the @f$b@f$ parameter of the distribution. - */ - _RealType - b() const - { return _M_param.b(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return std::numeric_limits::lowest(); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { return std::numeric_limits::max(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two extreme value distributions have the same - * parameters. - */ - friend bool - operator==(const extreme_value_distribution& __d1, - const extreme_value_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two extreme value distributions have different - * parameters. - */ - template - inline bool - operator!=(const std::extreme_value_distribution<_RealType>& __d1, - const std::extreme_value_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A discrete_distribution random number distribution. - * - * The formula for the discrete probability mass function is - * - */ - template - class discrete_distribution - { - static_assert(std::is_integral<_IntType>::value, - "result_type must be an integral type"); - - public: - /** The type of the range of the distribution. */ - typedef _IntType result_type; - - /** Parameter type. */ - struct param_type - { - typedef discrete_distribution<_IntType> distribution_type; - friend class discrete_distribution<_IntType>; - - param_type() - : _M_prob(), _M_cp() - { } - - template - param_type(_InputIterator __wbegin, - _InputIterator __wend) - : _M_prob(__wbegin, __wend), _M_cp() - { _M_initialize(); } - - param_type(initializer_list __wil) - : _M_prob(__wil.begin(), __wil.end()), _M_cp() - { _M_initialize(); } - - template - param_type(size_t __nw, double __xmin, double __xmax, - _Func __fw); - - // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ - param_type(const param_type&) = default; - param_type& operator=(const param_type&) = default; - - std::vector - probabilities() const - { return _M_prob.empty() ? std::vector(1, 1.0) : _M_prob; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_prob == __p2._M_prob; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - void - _M_initialize(); - - std::vector _M_prob; - std::vector _M_cp; - }; - - discrete_distribution() - : _M_param() - { } - - template - discrete_distribution(_InputIterator __wbegin, - _InputIterator __wend) - : _M_param(__wbegin, __wend) - { } - - discrete_distribution(initializer_list __wl) - : _M_param(__wl) - { } - - template - discrete_distribution(size_t __nw, double __xmin, double __xmax, - _Func __fw) - : _M_param(__nw, __xmin, __xmax, __fw) - { } - - explicit - discrete_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { } - - /** - * @brief Returns the probabilities of the distribution. - */ - std::vector - probabilities() const - { - return _M_param._M_prob.empty() - ? std::vector(1, 1.0) : _M_param._M_prob; - } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { return result_type(0); } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { - return _M_param._M_prob.empty() - ? result_type(0) : result_type(_M_param._M_prob.size() - 1); - } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two discrete distributions have the same - * parameters. - */ - friend bool - operator==(const discrete_distribution& __d1, - const discrete_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two discrete distributions have different - * parameters. - */ - template - inline bool - operator!=(const std::discrete_distribution<_IntType>& __d1, - const std::discrete_distribution<_IntType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A piecewise_constant_distribution random number distribution. - * - * The formula for the piecewise constant probability mass function is - * - */ - template - class piecewise_constant_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef piecewise_constant_distribution<_RealType> distribution_type; - friend class piecewise_constant_distribution<_RealType>; - - param_type() - : _M_int(), _M_den(), _M_cp() - { } - - template - param_type(_InputIteratorB __bfirst, - _InputIteratorB __bend, - _InputIteratorW __wbegin); - - template - param_type(initializer_list<_RealType> __bi, _Func __fw); - - template - param_type(size_t __nw, _RealType __xmin, _RealType __xmax, - _Func __fw); - - // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ - param_type(const param_type&) = default; - param_type& operator=(const param_type&) = default; - - std::vector<_RealType> - intervals() const - { - if (_M_int.empty()) - { - std::vector<_RealType> __tmp(2); - __tmp[1] = _RealType(1); - return __tmp; - } - else - return _M_int; - } - - std::vector - densities() const - { return _M_den.empty() ? std::vector(1, 1.0) : _M_den; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_int == __p2._M_int && __p1._M_den == __p2._M_den; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - void - _M_initialize(); - - std::vector<_RealType> _M_int; - std::vector _M_den; - std::vector _M_cp; - }; - - piecewise_constant_distribution() - : _M_param() - { } - - template - piecewise_constant_distribution(_InputIteratorB __bfirst, - _InputIteratorB __bend, - _InputIteratorW __wbegin) - : _M_param(__bfirst, __bend, __wbegin) - { } - - template - piecewise_constant_distribution(initializer_list<_RealType> __bl, - _Func __fw) - : _M_param(__bl, __fw) - { } - - template - piecewise_constant_distribution(size_t __nw, - _RealType __xmin, _RealType __xmax, - _Func __fw) - : _M_param(__nw, __xmin, __xmax, __fw) - { } - - explicit - piecewise_constant_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - */ - void - reset() - { } - - /** - * @brief Returns a vector of the intervals. - */ - std::vector<_RealType> - intervals() const - { - if (_M_param._M_int.empty()) - { - std::vector<_RealType> __tmp(2); - __tmp[1] = _RealType(1); - return __tmp; - } - else - return _M_param._M_int; - } - - /** - * @brief Returns a vector of the probability densities. - */ - std::vector - densities() const - { - return _M_param._M_den.empty() - ? std::vector(1, 1.0) : _M_param._M_den; - } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { - return _M_param._M_int.empty() - ? result_type(0) : _M_param._M_int.front(); - } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { - return _M_param._M_int.empty() - ? result_type(1) : _M_param._M_int.back(); - } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two piecewise constant distributions have the - * same parameters. - */ - friend bool - operator==(const piecewise_constant_distribution& __d1, - const piecewise_constant_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two piecewise constant distributions have - * different parameters. - */ - template - inline bool - operator!=(const std::piecewise_constant_distribution<_RealType>& __d1, - const std::piecewise_constant_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /** - * @brief A piecewise_linear_distribution random number distribution. - * - * The formula for the piecewise linear probability mass function is - * - */ - template - class piecewise_linear_distribution - { - static_assert(std::is_floating_point<_RealType>::value, - "result_type must be a floating point type"); - - public: - /** The type of the range of the distribution. */ - typedef _RealType result_type; - - /** Parameter type. */ - struct param_type - { - typedef piecewise_linear_distribution<_RealType> distribution_type; - friend class piecewise_linear_distribution<_RealType>; - - param_type() - : _M_int(), _M_den(), _M_cp(), _M_m() - { } - - template - param_type(_InputIteratorB __bfirst, - _InputIteratorB __bend, - _InputIteratorW __wbegin); - - template - param_type(initializer_list<_RealType> __bl, _Func __fw); - - template - param_type(size_t __nw, _RealType __xmin, _RealType __xmax, - _Func __fw); - - // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ - param_type(const param_type&) = default; - param_type& operator=(const param_type&) = default; - - std::vector<_RealType> - intervals() const - { - if (_M_int.empty()) - { - std::vector<_RealType> __tmp(2); - __tmp[1] = _RealType(1); - return __tmp; - } - else - return _M_int; - } - - std::vector - densities() const - { return _M_den.empty() ? std::vector(2, 1.0) : _M_den; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_int == __p2._M_int && __p1._M_den == __p2._M_den; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - void - _M_initialize(); - - std::vector<_RealType> _M_int; - std::vector _M_den; - std::vector _M_cp; - std::vector _M_m; - }; - - piecewise_linear_distribution() - : _M_param() - { } - - template - piecewise_linear_distribution(_InputIteratorB __bfirst, - _InputIteratorB __bend, - _InputIteratorW __wbegin) - : _M_param(__bfirst, __bend, __wbegin) - { } - - template - piecewise_linear_distribution(initializer_list<_RealType> __bl, - _Func __fw) - : _M_param(__bl, __fw) - { } - - template - piecewise_linear_distribution(size_t __nw, - _RealType __xmin, _RealType __xmax, - _Func __fw) - : _M_param(__nw, __xmin, __xmax, __fw) - { } - - explicit - piecewise_linear_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * Resets the distribution state. - */ - void - reset() - { } - - /** - * @brief Return the intervals of the distribution. - */ - std::vector<_RealType> - intervals() const - { - if (_M_param._M_int.empty()) - { - std::vector<_RealType> __tmp(2); - __tmp[1] = _RealType(1); - return __tmp; - } - else - return _M_param._M_int; - } - - /** - * @brief Return a vector of the probability densities of the - * distribution. - */ - std::vector - densities() const - { - return _M_param._M_den.empty() - ? std::vector(2, 1.0) : _M_param._M_den; - } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the greatest lower bound value of the distribution. - */ - result_type - min() const - { - return _M_param._M_int.empty() - ? result_type(0) : _M_param._M_int.front(); - } - - /** - * @brief Returns the least upper bound value of the distribution. - */ - result_type - max() const - { - return _M_param._M_int.empty() - ? result_type(1) : _M_param._M_int.back(); - } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two piecewise linear distributions have the - * same parameters. - */ - friend bool - operator==(const piecewise_linear_distribution& __d1, - const piecewise_linear_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - /** - * @brief Return true if two piecewise linear distributions have - * different parameters. - */ - template - inline bool - operator!=(const std::piecewise_linear_distribution<_RealType>& __d1, - const std::piecewise_linear_distribution<_RealType>& __d2) - { return !(__d1 == __d2); } - - - /* @} */ // group random_distributions_poisson - - /* @} */ // group random_distributions - - /** - * @addtogroup random_utilities Random Number Utilities - * @ingroup random - * @{ - */ - - /** - * @brief The seed_seq class generates sequences of seeds for random - * number generators. - */ - class seed_seq - { - public: - /** The type of the seed vales. */ - typedef uint_least32_t result_type; - - /** Default constructor. */ - seed_seq() noexcept - : _M_v() - { } - - template - seed_seq(std::initializer_list<_IntType> __il); - - template - seed_seq(_InputIterator __begin, _InputIterator __end); - - // generating functions - template - void - generate(_RandomAccessIterator __begin, _RandomAccessIterator __end); - - // property functions - size_t size() const noexcept - { return _M_v.size(); } - - template - void - param(_OutputIterator __dest) const - { std::copy(_M_v.begin(), _M_v.end(), __dest); } - - // no copy functions - seed_seq(const seed_seq&) = delete; - seed_seq& operator=(const seed_seq&) = delete; - - private: - std::vector _M_v; - }; - - /* @} */ // group random_utilities - - /* @} */ // group random - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/random.tcc b/resources/sources/avr-libstdcpp/include/bits/random.tcc deleted file mode 100644 index a9b90d6ca..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/random.tcc +++ /dev/null @@ -1,2193 +0,0 @@ -// random number generation (out of line) -*- C++ -*- - -// Copyright (C) 2009-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/random.tcc - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{random} - */ - -#ifndef _RANDOM_TCC -#define _RANDOM_TCC 1 - -#include // std::accumulate and std::partial_sum - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /* - * (Further) implementation-space details. - */ - namespace __detail - { - // General case for x = (ax + c) mod m -- use Schrage's algorithm - // to avoid integer overflow. - // - // Preconditions: a > 0, m > 0. - // - // Note: only works correctly for __m % __a < __m / __a. - template - _Tp - _Mod<_Tp, __m, __a, __c, false, true>:: - __calc(_Tp __x) - { - if (__a == 1) - __x %= __m; - else - { - static const _Tp __q = __m / __a; - static const _Tp __r = __m % __a; - - _Tp __t1 = __a * (__x % __q); - _Tp __t2 = __r * (__x / __q); - if (__t1 >= __t2) - __x = __t1 - __t2; - else - __x = __m - __t2 + __t1; - } - - if (__c != 0) - { - const _Tp __d = __m - __x; - if (__d > __c) - __x += __c; - else - __x = __c - __d; - } - return __x; - } - - template - _OutputIterator - __normalize(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, const _Tp& __factor) - { - for (; __first != __last; ++__first, ++__result) - *__result = *__first / __factor; - return __result; - } - - } // namespace __detail - - template - constexpr _UIntType - linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier; - - template - constexpr _UIntType - linear_congruential_engine<_UIntType, __a, __c, __m>::increment; - - template - constexpr _UIntType - linear_congruential_engine<_UIntType, __a, __c, __m>::modulus; - - template - constexpr _UIntType - linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed; - - /** - * Seeds the LCR with integral value @p __s, adjusted so that the - * ring identity is never a member of the convergence set. - */ - template - void - linear_congruential_engine<_UIntType, __a, __c, __m>:: - seed(result_type __s) - { - if ((__detail::__mod<_UIntType, __m>(__c) == 0) - && (__detail::__mod<_UIntType, __m>(__s) == 0)) - _M_x = 1; - else - _M_x = __detail::__mod<_UIntType, __m>(__s); - } - - /** - * Seeds the LCR engine with a value generated by @p __q. - */ - template - template - auto - linear_congruential_engine<_UIntType, __a, __c, __m>:: - seed(_Sseq& __q) - -> _If_seed_seq<_Sseq> - { - const _UIntType __k0 = __m == 0 ? std::numeric_limits<_UIntType>::digits - : std::__lg(__m); - const _UIntType __k = (__k0 + 31) / 32; - uint_least32_t __arr[__k + 3]; - __q.generate(__arr + 0, __arr + __k + 3); - _UIntType __factor = 1u; - _UIntType __sum = 0u; - for (size_t __j = 0; __j < __k; ++__j) - { - __sum += __arr[__j + 3] * __factor; - __factor *= __detail::_Shift<_UIntType, 32>::__value; - } - seed(__sum); - } - - - template - constexpr size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::word_size; - - template - constexpr size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::state_size; - - template - constexpr size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::shift_size; - - template - constexpr size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::mask_bits; - - template - constexpr _UIntType - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::xor_mask; - - template - constexpr size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::tempering_u; - - template - constexpr _UIntType - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::tempering_d; - - template - constexpr size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::tempering_s; - - template - constexpr _UIntType - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::tempering_b; - - template - constexpr size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::tempering_t; - - template - constexpr _UIntType - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::tempering_c; - - template - constexpr size_t - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::tempering_l; - - template - constexpr _UIntType - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>:: - initialization_multiplier; - - template - constexpr _UIntType - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::default_seed; - - template - void - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>:: - seed(result_type __sd) - { - _M_x[0] = __detail::__mod<_UIntType, - __detail::_Shift<_UIntType, __w>::__value>(__sd); - - for (size_t __i = 1; __i < state_size; ++__i) - { - _UIntType __x = _M_x[__i - 1]; - __x ^= __x >> (__w - 2); - __x *= __f; - __x += __detail::__mod<_UIntType, __n>(__i); - _M_x[__i] = __detail::__mod<_UIntType, - __detail::_Shift<_UIntType, __w>::__value>(__x); - } - _M_p = state_size; - } - - template - template - auto - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>:: - seed(_Sseq& __q) - -> _If_seed_seq<_Sseq> - { - const _UIntType __upper_mask = (~_UIntType()) << __r; - const size_t __k = (__w + 31) / 32; - uint_least32_t __arr[__n * __k]; - __q.generate(__arr + 0, __arr + __n * __k); - - bool __zero = true; - for (size_t __i = 0; __i < state_size; ++__i) - { - _UIntType __factor = 1u; - _UIntType __sum = 0u; - for (size_t __j = 0; __j < __k; ++__j) - { - __sum += __arr[__k * __i + __j] * __factor; - __factor *= __detail::_Shift<_UIntType, 32>::__value; - } - _M_x[__i] = __detail::__mod<_UIntType, - __detail::_Shift<_UIntType, __w>::__value>(__sum); - - if (__zero) - { - if (__i == 0) - { - if ((_M_x[0] & __upper_mask) != 0u) - __zero = false; - } - else if (_M_x[__i] != 0u) - __zero = false; - } - } - if (__zero) - _M_x[0] = __detail::_Shift<_UIntType, __w - 1>::__value; - _M_p = state_size; - } - - template - void - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>:: - _M_gen_rand(void) - { - const _UIntType __upper_mask = (~_UIntType()) << __r; - const _UIntType __lower_mask = ~__upper_mask; - - for (size_t __k = 0; __k < (__n - __m); ++__k) - { - _UIntType __y = ((_M_x[__k] & __upper_mask) - | (_M_x[__k + 1] & __lower_mask)); - _M_x[__k] = (_M_x[__k + __m] ^ (__y >> 1) - ^ ((__y & 0x01) ? __a : 0)); - } - - for (size_t __k = (__n - __m); __k < (__n - 1); ++__k) - { - _UIntType __y = ((_M_x[__k] & __upper_mask) - | (_M_x[__k + 1] & __lower_mask)); - _M_x[__k] = (_M_x[__k + (__m - __n)] ^ (__y >> 1) - ^ ((__y & 0x01) ? __a : 0)); - } - - _UIntType __y = ((_M_x[__n - 1] & __upper_mask) - | (_M_x[0] & __lower_mask)); - _M_x[__n - 1] = (_M_x[__m - 1] ^ (__y >> 1) - ^ ((__y & 0x01) ? __a : 0)); - _M_p = 0; - } - - template - void - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>:: - discard(unsigned long long __z) - { - while (__z > state_size - _M_p) - { - __z -= state_size - _M_p; - _M_gen_rand(); - } - _M_p += __z; - } - - template - typename - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>::result_type - mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, - __s, __b, __t, __c, __l, __f>:: - operator()() - { - // Reload the vector - cost is O(n) amortized over n calls. - if (_M_p >= state_size) - _M_gen_rand(); - - // Calculate o(x(i)). - result_type __z = _M_x[_M_p++]; - __z ^= (__z >> __u) & __d; - __z ^= (__z << __s) & __b; - __z ^= (__z << __t) & __c; - __z ^= (__z >> __l); - - return __z; - } - - - template - constexpr size_t - subtract_with_carry_engine<_UIntType, __w, __s, __r>::word_size; - - template - constexpr size_t - subtract_with_carry_engine<_UIntType, __w, __s, __r>::short_lag; - - template - constexpr size_t - subtract_with_carry_engine<_UIntType, __w, __s, __r>::long_lag; - - template - constexpr _UIntType - subtract_with_carry_engine<_UIntType, __w, __s, __r>::default_seed; - - template - void - subtract_with_carry_engine<_UIntType, __w, __s, __r>:: - seed(result_type __value) - { - std::linear_congruential_engine - __lcg(__value == 0u ? default_seed : __value); - - const size_t __n = (__w + 31) / 32; - - for (size_t __i = 0; __i < long_lag; ++__i) - { - _UIntType __sum = 0u; - _UIntType __factor = 1u; - for (size_t __j = 0; __j < __n; ++__j) - { - __sum += __detail::__mod::__value> - (__lcg()) * __factor; - __factor *= __detail::_Shift<_UIntType, 32>::__value; - } - _M_x[__i] = __detail::__mod<_UIntType, - __detail::_Shift<_UIntType, __w>::__value>(__sum); - } - _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0; - _M_p = 0; - } - - template - template - auto - subtract_with_carry_engine<_UIntType, __w, __s, __r>:: - seed(_Sseq& __q) - -> _If_seed_seq<_Sseq> - { - const size_t __k = (__w + 31) / 32; - uint_least32_t __arr[__r * __k]; - __q.generate(__arr + 0, __arr + __r * __k); - - for (size_t __i = 0; __i < long_lag; ++__i) - { - _UIntType __sum = 0u; - _UIntType __factor = 1u; - for (size_t __j = 0; __j < __k; ++__j) - { - __sum += __arr[__k * __i + __j] * __factor; - __factor *= __detail::_Shift<_UIntType, 32>::__value; - } - _M_x[__i] = __detail::__mod<_UIntType, - __detail::_Shift<_UIntType, __w>::__value>(__sum); - } - _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0; - _M_p = 0; - } - - template - typename subtract_with_carry_engine<_UIntType, __w, __s, __r>:: - result_type - subtract_with_carry_engine<_UIntType, __w, __s, __r>:: - operator()() - { - // Derive short lag index from current index. - long __ps = _M_p - short_lag; - if (__ps < 0) - __ps += long_lag; - - // Calculate new x(i) without overflow or division. - // NB: Thanks to the requirements for _UIntType, _M_x[_M_p] + _M_carry - // cannot overflow. - _UIntType __xi; - if (_M_x[__ps] >= _M_x[_M_p] + _M_carry) - { - __xi = _M_x[__ps] - _M_x[_M_p] - _M_carry; - _M_carry = 0; - } - else - { - __xi = (__detail::_Shift<_UIntType, __w>::__value - - _M_x[_M_p] - _M_carry + _M_x[__ps]); - _M_carry = 1; - } - _M_x[_M_p] = __xi; - - // Adjust current index to loop around in ring buffer. - if (++_M_p >= long_lag) - _M_p = 0; - - return __xi; - } - - - template - constexpr size_t - discard_block_engine<_RandomNumberEngine, __p, __r>::block_size; - - template - constexpr size_t - discard_block_engine<_RandomNumberEngine, __p, __r>::used_block; - - template - typename discard_block_engine<_RandomNumberEngine, - __p, __r>::result_type - discard_block_engine<_RandomNumberEngine, __p, __r>:: - operator()() - { - if (_M_n >= used_block) - { - _M_b.discard(block_size - _M_n); - _M_n = 0; - } - ++_M_n; - return _M_b(); - } - - - template - typename independent_bits_engine<_RandomNumberEngine, __w, _UIntType>:: - result_type - independent_bits_engine<_RandomNumberEngine, __w, _UIntType>:: - operator()() - { - typedef typename _RandomNumberEngine::result_type _Eresult_type; - const _Eresult_type __r - = (_M_b.max() - _M_b.min() < std::numeric_limits<_Eresult_type>::max() - ? _M_b.max() - _M_b.min() + 1 : 0); - const unsigned __edig = std::numeric_limits<_Eresult_type>::digits; - const unsigned __m = __r ? std::__lg(__r) : __edig; - - typedef typename std::common_type<_Eresult_type, result_type>::type - __ctype; - const unsigned __cdig = std::numeric_limits<__ctype>::digits; - - unsigned __n, __n0; - __ctype __s0, __s1, __y0, __y1; - - for (size_t __i = 0; __i < 2; ++__i) - { - __n = (__w + __m - 1) / __m + __i; - __n0 = __n - __w % __n; - const unsigned __w0 = __w / __n; // __w0 <= __m - - __s0 = 0; - __s1 = 0; - if (__w0 < __cdig) - { - __s0 = __ctype(1) << __w0; - __s1 = __s0 << 1; - } - - __y0 = 0; - __y1 = 0; - if (__r) - { - __y0 = __s0 * (__r / __s0); - if (__s1) - __y1 = __s1 * (__r / __s1); - - if (__r - __y0 <= __y0 / __n) - break; - } - else - break; - } - - result_type __sum = 0; - for (size_t __k = 0; __k < __n0; ++__k) - { - __ctype __u; - do - __u = _M_b() - _M_b.min(); - while (__y0 && __u >= __y0); - __sum = __s0 * __sum + (__s0 ? __u % __s0 : __u); - } - for (size_t __k = __n0; __k < __n; ++__k) - { - __ctype __u; - do - __u = _M_b() - _M_b.min(); - while (__y1 && __u >= __y1); - __sum = __s1 * __sum + (__s1 ? __u % __s1 : __u); - } - return __sum; - } - - - template - constexpr size_t - shuffle_order_engine<_RandomNumberEngine, __k>::table_size; - - template - typename shuffle_order_engine<_RandomNumberEngine, __k>::result_type - shuffle_order_engine<_RandomNumberEngine, __k>:: - operator()() - { - size_t __j = __k * ((_M_y - _M_b.min()) - / (_M_b.max() - _M_b.min() + 1.0L)); - _M_y = _M_v[__j]; - _M_v[__j] = _M_b(); - - return _M_y; - } - - - template - template - void - uniform_real_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - auto __range = __p.b() - __p.a(); - while (__f != __t) - *__f++ = __aurng() * __range + __p.a(); - } - - - template - void - std::bernoulli_distribution:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - auto __limit = __p.p() * (__aurng.max() - __aurng.min()); - - while (__f != __t) - *__f++ = (__aurng() - __aurng.min()) < __limit; - } - - - template - template - typename geometric_distribution<_IntType>::result_type - geometric_distribution<_IntType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - // About the epsilon thing see this thread: - // http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00971.html - const double __naf = - (1 - std::numeric_limits::epsilon()) / 2; - // The largest _RealType convertible to _IntType. - const double __thr = - std::numeric_limits<_IntType>::max() + __naf; - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - - double __cand; - do - __cand = std::floor(std::log(1.0 - __aurng()) / __param._M_log_1_p); - while (__cand >= __thr); - - return result_type(__cand + __naf); - } - - template - template - void - geometric_distribution<_IntType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - // About the epsilon thing see this thread: - // http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00971.html - const double __naf = - (1 - std::numeric_limits::epsilon()) / 2; - // The largest _RealType convertible to _IntType. - const double __thr = - std::numeric_limits<_IntType>::max() + __naf; - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - - while (__f != __t) - { - double __cand; - do - __cand = std::floor(std::log(1.0 - __aurng()) - / __param._M_log_1_p); - while (__cand >= __thr); - - *__f++ = __cand + __naf; - } - } - - - // This is Leger's algorithm, also in Devroye, Ch. X, Example 1.5. - template - template - typename negative_binomial_distribution<_IntType>::result_type - negative_binomial_distribution<_IntType>:: - operator()(_UniformRandomNumberGenerator& __urng) - { - const double __y = _M_gd(__urng); - - // XXX Is the constructor too slow? - std::poisson_distribution __poisson(__y); - return __poisson(__urng); - } - - template - template - typename negative_binomial_distribution<_IntType>::result_type - negative_binomial_distribution<_IntType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - typedef typename std::gamma_distribution::param_type - param_type; - - const double __y = - _M_gd(__urng, param_type(__p.k(), (1.0 - __p.p()) / __p.p())); - - std::poisson_distribution __poisson(__y); - return __poisson(__urng); - } - - template - template - void - negative_binomial_distribution<_IntType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - while (__f != __t) - { - const double __y = _M_gd(__urng); - - // XXX Is the constructor too slow? - std::poisson_distribution __poisson(__y); - *__f++ = __poisson(__urng); - } - } - - template - template - void - negative_binomial_distribution<_IntType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - typename std::gamma_distribution::param_type - __p2(__p.k(), (1.0 - __p.p()) / __p.p()); - - while (__f != __t) - { - const double __y = _M_gd(__urng, __p2); - - std::poisson_distribution __poisson(__y); - *__f++ = __poisson(__urng); - } - } - - - template - void - poisson_distribution<_IntType>::param_type:: - _M_initialize() - { -#if _GLIBCXX_USE_C99_MATH_TR1 - if (_M_mean >= 12) - { - const double __m = std::floor(_M_mean); - _M_lm_thr = std::log(_M_mean); - _M_lfm = std::lgamma(__m + 1); - _M_sm = std::sqrt(__m); - - const double __pi_4 = 0.7853981633974483096156608458198757L; - const double __dx = std::sqrt(2 * __m * std::log(32 * __m - / __pi_4)); - _M_d = std::round(std::max(6.0, std::min(__m, __dx))); - const double __cx = 2 * __m + _M_d; - _M_scx = std::sqrt(__cx / 2); - _M_1cx = 1 / __cx; - - _M_c2b = std::sqrt(__pi_4 * __cx) * std::exp(_M_1cx); - _M_cb = 2 * __cx * std::exp(-_M_d * _M_1cx * (1 + _M_d / 2)) - / _M_d; - } - else -#endif - _M_lm_thr = std::exp(-_M_mean); - } - - /** - * A rejection algorithm when mean >= 12 and a simple method based - * upon the multiplication of uniform random variates otherwise. - * NB: The former is available only if _GLIBCXX_USE_C99_MATH_TR1 - * is defined. - * - * Reference: - * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, - * New York, 1986, Ch. X, Sects. 3.3 & 3.4 (+ Errata!). - */ - template - template - typename poisson_distribution<_IntType>::result_type - poisson_distribution<_IntType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); -#if _GLIBCXX_USE_C99_MATH_TR1 - if (__param.mean() >= 12) - { - double __x; - - // See comments above... - const double __naf = - (1 - std::numeric_limits::epsilon()) / 2; - const double __thr = - std::numeric_limits<_IntType>::max() + __naf; - - const double __m = std::floor(__param.mean()); - // sqrt(pi / 2) - const double __spi_2 = 1.2533141373155002512078826424055226L; - const double __c1 = __param._M_sm * __spi_2; - const double __c2 = __param._M_c2b + __c1; - const double __c3 = __c2 + 1; - const double __c4 = __c3 + 1; - // 1 / 78 - const double __178 = 0.0128205128205128205128205128205128L; - // e^(1 / 78) - const double __e178 = 1.0129030479320018583185514777512983L; - const double __c5 = __c4 + __e178; - const double __c = __param._M_cb + __c5; - const double __2cx = 2 * (2 * __m + __param._M_d); - - bool __reject = true; - do - { - const double __u = __c * __aurng(); - const double __e = -std::log(1.0 - __aurng()); - - double __w = 0.0; - - if (__u <= __c1) - { - const double __n = _M_nd(__urng); - const double __y = -std::abs(__n) * __param._M_sm - 1; - __x = std::floor(__y); - __w = -__n * __n / 2; - if (__x < -__m) - continue; - } - else if (__u <= __c2) - { - const double __n = _M_nd(__urng); - const double __y = 1 + std::abs(__n) * __param._M_scx; - __x = std::ceil(__y); - __w = __y * (2 - __y) * __param._M_1cx; - if (__x > __param._M_d) - continue; - } - else if (__u <= __c3) - // NB: This case not in the book, nor in the Errata, - // but should be ok... - __x = -1; - else if (__u <= __c4) - __x = 0; - else if (__u <= __c5) - { - __x = 1; - // Only in the Errata, see libstdc++/83237. - __w = __178; - } - else - { - const double __v = -std::log(1.0 - __aurng()); - const double __y = __param._M_d - + __v * __2cx / __param._M_d; - __x = std::ceil(__y); - __w = -__param._M_d * __param._M_1cx * (1 + __y / 2); - } - - __reject = (__w - __e - __x * __param._M_lm_thr - > __param._M_lfm - std::lgamma(__x + __m + 1)); - - __reject |= __x + __m >= __thr; - - } while (__reject); - - return result_type(__x + __m + __naf); - } - else -#endif - { - _IntType __x = 0; - double __prod = 1.0; - - do - { - __prod *= __aurng(); - __x += 1; - } - while (__prod > __param._M_lm_thr); - - return __x - 1; - } - } - - template - template - void - poisson_distribution<_IntType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - // We could duplicate everything from operator()... - while (__f != __t) - *__f++ = this->operator()(__urng, __param); - } - - - template - void - binomial_distribution<_IntType>::param_type:: - _M_initialize() - { - const double __p12 = _M_p <= 0.5 ? _M_p : 1.0 - _M_p; - - _M_easy = true; - -#if _GLIBCXX_USE_C99_MATH_TR1 - if (_M_t * __p12 >= 8) - { - _M_easy = false; - const double __np = std::floor(_M_t * __p12); - const double __pa = __np / _M_t; - const double __1p = 1 - __pa; - - const double __pi_4 = 0.7853981633974483096156608458198757L; - const double __d1x = - std::sqrt(__np * __1p * std::log(32 * __np - / (81 * __pi_4 * __1p))); - _M_d1 = std::round(std::max(1.0, __d1x)); - const double __d2x = - std::sqrt(__np * __1p * std::log(32 * _M_t * __1p - / (__pi_4 * __pa))); - _M_d2 = std::round(std::max(1.0, __d2x)); - - // sqrt(pi / 2) - const double __spi_2 = 1.2533141373155002512078826424055226L; - _M_s1 = std::sqrt(__np * __1p) * (1 + _M_d1 / (4 * __np)); - _M_s2 = std::sqrt(__np * __1p) * (1 + _M_d2 / (4 * _M_t * __1p)); - _M_c = 2 * _M_d1 / __np; - _M_a1 = std::exp(_M_c) * _M_s1 * __spi_2; - const double __a12 = _M_a1 + _M_s2 * __spi_2; - const double __s1s = _M_s1 * _M_s1; - _M_a123 = __a12 + (std::exp(_M_d1 / (_M_t * __1p)) - * 2 * __s1s / _M_d1 - * std::exp(-_M_d1 * _M_d1 / (2 * __s1s))); - const double __s2s = _M_s2 * _M_s2; - _M_s = (_M_a123 + 2 * __s2s / _M_d2 - * std::exp(-_M_d2 * _M_d2 / (2 * __s2s))); - _M_lf = (std::lgamma(__np + 1) - + std::lgamma(_M_t - __np + 1)); - _M_lp1p = std::log(__pa / __1p); - - _M_q = -std::log(1 - (__p12 - __pa) / __1p); - } - else -#endif - _M_q = -std::log(1 - __p12); - } - - template - template - typename binomial_distribution<_IntType>::result_type - binomial_distribution<_IntType>:: - _M_waiting(_UniformRandomNumberGenerator& __urng, - _IntType __t, double __q) - { - _IntType __x = 0; - double __sum = 0.0; - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - - do - { - if (__t == __x) - return __x; - const double __e = -std::log(1.0 - __aurng()); - __sum += __e / (__t - __x); - __x += 1; - } - while (__sum <= __q); - - return __x - 1; - } - - /** - * A rejection algorithm when t * p >= 8 and a simple waiting time - * method - the second in the referenced book - otherwise. - * NB: The former is available only if _GLIBCXX_USE_C99_MATH_TR1 - * is defined. - * - * Reference: - * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, - * New York, 1986, Ch. X, Sect. 4 (+ Errata!). - */ - template - template - typename binomial_distribution<_IntType>::result_type - binomial_distribution<_IntType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - result_type __ret; - const _IntType __t = __param.t(); - const double __p = __param.p(); - const double __p12 = __p <= 0.5 ? __p : 1.0 - __p; - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - -#if _GLIBCXX_USE_C99_MATH_TR1 - if (!__param._M_easy) - { - double __x; - - // See comments above... - const double __naf = - (1 - std::numeric_limits::epsilon()) / 2; - const double __thr = - std::numeric_limits<_IntType>::max() + __naf; - - const double __np = std::floor(__t * __p12); - - // sqrt(pi / 2) - const double __spi_2 = 1.2533141373155002512078826424055226L; - const double __a1 = __param._M_a1; - const double __a12 = __a1 + __param._M_s2 * __spi_2; - const double __a123 = __param._M_a123; - const double __s1s = __param._M_s1 * __param._M_s1; - const double __s2s = __param._M_s2 * __param._M_s2; - - bool __reject; - do - { - const double __u = __param._M_s * __aurng(); - - double __v; - - if (__u <= __a1) - { - const double __n = _M_nd(__urng); - const double __y = __param._M_s1 * std::abs(__n); - __reject = __y >= __param._M_d1; - if (!__reject) - { - const double __e = -std::log(1.0 - __aurng()); - __x = std::floor(__y); - __v = -__e - __n * __n / 2 + __param._M_c; - } - } - else if (__u <= __a12) - { - const double __n = _M_nd(__urng); - const double __y = __param._M_s2 * std::abs(__n); - __reject = __y >= __param._M_d2; - if (!__reject) - { - const double __e = -std::log(1.0 - __aurng()); - __x = std::floor(-__y); - __v = -__e - __n * __n / 2; - } - } - else if (__u <= __a123) - { - const double __e1 = -std::log(1.0 - __aurng()); - const double __e2 = -std::log(1.0 - __aurng()); - - const double __y = __param._M_d1 - + 2 * __s1s * __e1 / __param._M_d1; - __x = std::floor(__y); - __v = (-__e2 + __param._M_d1 * (1 / (__t - __np) - -__y / (2 * __s1s))); - __reject = false; - } - else - { - const double __e1 = -std::log(1.0 - __aurng()); - const double __e2 = -std::log(1.0 - __aurng()); - - const double __y = __param._M_d2 - + 2 * __s2s * __e1 / __param._M_d2; - __x = std::floor(-__y); - __v = -__e2 - __param._M_d2 * __y / (2 * __s2s); - __reject = false; - } - - __reject = __reject || __x < -__np || __x > __t - __np; - if (!__reject) - { - const double __lfx = - std::lgamma(__np + __x + 1) - + std::lgamma(__t - (__np + __x) + 1); - __reject = __v > __param._M_lf - __lfx - + __x * __param._M_lp1p; - } - - __reject |= __x + __np >= __thr; - } - while (__reject); - - __x += __np + __naf; - - const _IntType __z = _M_waiting(__urng, __t - _IntType(__x), - __param._M_q); - __ret = _IntType(__x) + __z; - } - else -#endif - __ret = _M_waiting(__urng, __t, __param._M_q); - - if (__p12 != __p) - __ret = __t - __ret; - return __ret; - } - - template - template - void - binomial_distribution<_IntType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - // We could duplicate everything from operator()... - while (__f != __t) - *__f++ = this->operator()(__urng, __param); - } - - - template - template - void - std::exponential_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - while (__f != __t) - *__f++ = -std::log(result_type(1) - __aurng()) / __p.lambda(); - } - - - /** - * Polar method due to Marsaglia. - * - * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, - * New York, 1986, Ch. V, Sect. 4.4. - */ - template - template - typename normal_distribution<_RealType>::result_type - normal_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - result_type __ret; - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - - if (_M_saved_available) - { - _M_saved_available = false; - __ret = _M_saved; - } - else - { - result_type __x, __y, __r2; - do - { - __x = result_type(2.0) * __aurng() - 1.0; - __y = result_type(2.0) * __aurng() - 1.0; - __r2 = __x * __x + __y * __y; - } - while (__r2 > 1.0 || __r2 == 0.0); - - const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); - _M_saved = __x * __mult; - _M_saved_available = true; - __ret = __y * __mult; - } - - __ret = __ret * __param.stddev() + __param.mean(); - return __ret; - } - - template - template - void - normal_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - - if (__f == __t) - return; - - if (_M_saved_available) - { - _M_saved_available = false; - *__f++ = _M_saved * __param.stddev() + __param.mean(); - - if (__f == __t) - return; - } - - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - - while (__f + 1 < __t) - { - result_type __x, __y, __r2; - do - { - __x = result_type(2.0) * __aurng() - 1.0; - __y = result_type(2.0) * __aurng() - 1.0; - __r2 = __x * __x + __y * __y; - } - while (__r2 > 1.0 || __r2 == 0.0); - - const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); - *__f++ = __y * __mult * __param.stddev() + __param.mean(); - *__f++ = __x * __mult * __param.stddev() + __param.mean(); - } - - if (__f != __t) - { - result_type __x, __y, __r2; - do - { - __x = result_type(2.0) * __aurng() - 1.0; - __y = result_type(2.0) * __aurng() - 1.0; - __r2 = __x * __x + __y * __y; - } - while (__r2 > 1.0 || __r2 == 0.0); - - const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); - _M_saved = __x * __mult; - _M_saved_available = true; - *__f = __y * __mult * __param.stddev() + __param.mean(); - } - } - - template - bool - operator==(const std::normal_distribution<_RealType>& __d1, - const std::normal_distribution<_RealType>& __d2) - { - if (__d1._M_param == __d2._M_param - && __d1._M_saved_available == __d2._M_saved_available) - { - if (__d1._M_saved_available - && __d1._M_saved == __d2._M_saved) - return true; - else if(!__d1._M_saved_available) - return true; - else - return false; - } - else - return false; - } - - - template - template - void - lognormal_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - while (__f != __t) - *__f++ = std::exp(__p.s() * _M_nd(__urng) + __p.m()); - } - - template - template - void - std::chi_squared_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - while (__f != __t) - *__f++ = 2 * _M_gd(__urng); - } - - template - template - void - std::chi_squared_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const typename - std::gamma_distribution::param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - while (__f != __t) - *__f++ = 2 * _M_gd(__urng, __p); - } - - - template - template - typename cauchy_distribution<_RealType>::result_type - cauchy_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - _RealType __u; - do - __u = __aurng(); - while (__u == 0.5); - - const _RealType __pi = 3.1415926535897932384626433832795029L; - return __p.a() + __p.b() * std::tan(__pi * __u); - } - - template - template - void - cauchy_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - const _RealType __pi = 3.1415926535897932384626433832795029L; - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - while (__f != __t) - { - _RealType __u; - do - __u = __aurng(); - while (__u == 0.5); - - *__f++ = __p.a() + __p.b() * std::tan(__pi * __u); - } - } - - - template - template - void - std::fisher_f_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - while (__f != __t) - *__f++ = ((_M_gd_x(__urng) * n()) / (_M_gd_y(__urng) * m())); - } - - template - template - void - std::fisher_f_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - typedef typename std::gamma_distribution::param_type - param_type; - param_type __p1(__p.m() / 2); - param_type __p2(__p.n() / 2); - while (__f != __t) - *__f++ = ((_M_gd_x(__urng, __p1) * n()) - / (_M_gd_y(__urng, __p2) * m())); - } - - - template - template - void - std::student_t_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - while (__f != __t) - *__f++ = _M_nd(__urng) * std::sqrt(n() / _M_gd(__urng)); - } - - template - template - void - std::student_t_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - typename std::gamma_distribution::param_type - __p2(__p.n() / 2, 2); - while (__f != __t) - *__f++ = _M_nd(__urng) * std::sqrt(__p.n() / _M_gd(__urng, __p2)); - } - - - template - void - gamma_distribution<_RealType>::param_type:: - _M_initialize() - { - _M_malpha = _M_alpha < 1.0 ? _M_alpha + _RealType(1.0) : _M_alpha; - - const _RealType __a1 = _M_malpha - _RealType(1.0) / _RealType(3.0); - _M_a2 = _RealType(1.0) / std::sqrt(_RealType(9.0) * __a1); - } - - /** - * Marsaglia, G. and Tsang, W. W. - * "A Simple Method for Generating Gamma Variables" - * ACM Transactions on Mathematical Software, 26, 3, 363-372, 2000. - */ - template - template - typename gamma_distribution<_RealType>::result_type - gamma_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - - result_type __u, __v, __n; - const result_type __a1 = (__param._M_malpha - - _RealType(1.0) / _RealType(3.0)); - - do - { - do - { - __n = _M_nd(__urng); - __v = result_type(1.0) + __param._M_a2 * __n; - } - while (__v <= 0.0); - - __v = __v * __v * __v; - __u = __aurng(); - } - while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n - && (std::log(__u) > (0.5 * __n * __n + __a1 - * (1.0 - __v + std::log(__v))))); - - if (__param.alpha() == __param._M_malpha) - return __a1 * __v * __param.beta(); - else - { - do - __u = __aurng(); - while (__u == 0.0); - - return (std::pow(__u, result_type(1.0) / __param.alpha()) - * __a1 * __v * __param.beta()); - } - } - - template - template - void - gamma_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - - result_type __u, __v, __n; - const result_type __a1 = (__param._M_malpha - - _RealType(1.0) / _RealType(3.0)); - - if (__param.alpha() == __param._M_malpha) - while (__f != __t) - { - do - { - do - { - __n = _M_nd(__urng); - __v = result_type(1.0) + __param._M_a2 * __n; - } - while (__v <= 0.0); - - __v = __v * __v * __v; - __u = __aurng(); - } - while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n - && (std::log(__u) > (0.5 * __n * __n + __a1 - * (1.0 - __v + std::log(__v))))); - - *__f++ = __a1 * __v * __param.beta(); - } - else - while (__f != __t) - { - do - { - do - { - __n = _M_nd(__urng); - __v = result_type(1.0) + __param._M_a2 * __n; - } - while (__v <= 0.0); - - __v = __v * __v * __v; - __u = __aurng(); - } - while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n - && (std::log(__u) > (0.5 * __n * __n + __a1 - * (1.0 - __v + std::log(__v))))); - - do - __u = __aurng(); - while (__u == 0.0); - - *__f++ = (std::pow(__u, result_type(1.0) / __param.alpha()) - * __a1 * __v * __param.beta()); - } - } - - - template - template - typename weibull_distribution<_RealType>::result_type - weibull_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - return __p.b() * std::pow(-std::log(result_type(1) - __aurng()), - result_type(1) / __p.a()); - } - - template - template - void - weibull_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - auto __inv_a = result_type(1) / __p.a(); - - while (__f != __t) - *__f++ = __p.b() * std::pow(-std::log(result_type(1) - __aurng()), - __inv_a); - } - - - template - template - typename extreme_value_distribution<_RealType>::result_type - extreme_value_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - return __p.a() - __p.b() * std::log(-std::log(result_type(1) - - __aurng())); - } - - template - template - void - extreme_value_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> - __aurng(__urng); - - while (__f != __t) - *__f++ = __p.a() - __p.b() * std::log(-std::log(result_type(1) - - __aurng())); - } - - - template - void - discrete_distribution<_IntType>::param_type:: - _M_initialize() - { - if (_M_prob.size() < 2) - { - _M_prob.clear(); - return; - } - - const double __sum = std::accumulate(_M_prob.begin(), - _M_prob.end(), 0.0); - // Now normalize the probabilites. - __detail::__normalize(_M_prob.begin(), _M_prob.end(), _M_prob.begin(), - __sum); - // Accumulate partial sums. - _M_cp.reserve(_M_prob.size()); - std::partial_sum(_M_prob.begin(), _M_prob.end(), - std::back_inserter(_M_cp)); - // Make sure the last cumulative probability is one. - _M_cp[_M_cp.size() - 1] = 1.0; - } - - template - template - discrete_distribution<_IntType>::param_type:: - param_type(size_t __nw, double __xmin, double __xmax, _Func __fw) - : _M_prob(), _M_cp() - { - const size_t __n = __nw == 0 ? 1 : __nw; - const double __delta = (__xmax - __xmin) / __n; - - _M_prob.reserve(__n); - for (size_t __k = 0; __k < __nw; ++__k) - _M_prob.push_back(__fw(__xmin + __k * __delta + 0.5 * __delta)); - - _M_initialize(); - } - - template - template - typename discrete_distribution<_IntType>::result_type - discrete_distribution<_IntType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - if (__param._M_cp.empty()) - return result_type(0); - - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - - const double __p = __aurng(); - auto __pos = std::lower_bound(__param._M_cp.begin(), - __param._M_cp.end(), __p); - - return __pos - __param._M_cp.begin(); - } - - template - template - void - discrete_distribution<_IntType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - - if (__param._M_cp.empty()) - { - while (__f != __t) - *__f++ = result_type(0); - return; - } - - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - - while (__f != __t) - { - const double __p = __aurng(); - auto __pos = std::lower_bound(__param._M_cp.begin(), - __param._M_cp.end(), __p); - - *__f++ = __pos - __param._M_cp.begin(); - } - } - - - template - void - piecewise_constant_distribution<_RealType>::param_type:: - _M_initialize() - { - if (_M_int.size() < 2 - || (_M_int.size() == 2 - && _M_int[0] == _RealType(0) - && _M_int[1] == _RealType(1))) - { - _M_int.clear(); - _M_den.clear(); - return; - } - - const double __sum = std::accumulate(_M_den.begin(), - _M_den.end(), 0.0); - - __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(), - __sum); - - _M_cp.reserve(_M_den.size()); - std::partial_sum(_M_den.begin(), _M_den.end(), - std::back_inserter(_M_cp)); - - // Make sure the last cumulative probability is one. - _M_cp[_M_cp.size() - 1] = 1.0; - - for (size_t __k = 0; __k < _M_den.size(); ++__k) - _M_den[__k] /= _M_int[__k + 1] - _M_int[__k]; - } - - template - template - piecewise_constant_distribution<_RealType>::param_type:: - param_type(_InputIteratorB __bbegin, - _InputIteratorB __bend, - _InputIteratorW __wbegin) - : _M_int(), _M_den(), _M_cp() - { - if (__bbegin != __bend) - { - for (;;) - { - _M_int.push_back(*__bbegin); - ++__bbegin; - if (__bbegin == __bend) - break; - - _M_den.push_back(*__wbegin); - ++__wbegin; - } - } - - _M_initialize(); - } - - template - template - piecewise_constant_distribution<_RealType>::param_type:: - param_type(initializer_list<_RealType> __bl, _Func __fw) - : _M_int(), _M_den(), _M_cp() - { - _M_int.reserve(__bl.size()); - for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter) - _M_int.push_back(*__biter); - - _M_den.reserve(_M_int.size() - 1); - for (size_t __k = 0; __k < _M_int.size() - 1; ++__k) - _M_den.push_back(__fw(0.5 * (_M_int[__k + 1] + _M_int[__k]))); - - _M_initialize(); - } - - template - template - piecewise_constant_distribution<_RealType>::param_type:: - param_type(size_t __nw, _RealType __xmin, _RealType __xmax, _Func __fw) - : _M_int(), _M_den(), _M_cp() - { - const size_t __n = __nw == 0 ? 1 : __nw; - const _RealType __delta = (__xmax - __xmin) / __n; - - _M_int.reserve(__n + 1); - for (size_t __k = 0; __k <= __nw; ++__k) - _M_int.push_back(__xmin + __k * __delta); - - _M_den.reserve(__n); - for (size_t __k = 0; __k < __nw; ++__k) - _M_den.push_back(__fw(_M_int[__k] + 0.5 * __delta)); - - _M_initialize(); - } - - template - template - typename piecewise_constant_distribution<_RealType>::result_type - piecewise_constant_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - - const double __p = __aurng(); - if (__param._M_cp.empty()) - return __p; - - auto __pos = std::lower_bound(__param._M_cp.begin(), - __param._M_cp.end(), __p); - const size_t __i = __pos - __param._M_cp.begin(); - - const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; - - return __param._M_int[__i] + (__p - __pref) / __param._M_den[__i]; - } - - template - template - void - piecewise_constant_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - - if (__param._M_cp.empty()) - { - while (__f != __t) - *__f++ = __aurng(); - return; - } - - while (__f != __t) - { - const double __p = __aurng(); - - auto __pos = std::lower_bound(__param._M_cp.begin(), - __param._M_cp.end(), __p); - const size_t __i = __pos - __param._M_cp.begin(); - - const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; - - *__f++ = (__param._M_int[__i] - + (__p - __pref) / __param._M_den[__i]); - } - } - - - template - void - piecewise_linear_distribution<_RealType>::param_type:: - _M_initialize() - { - if (_M_int.size() < 2 - || (_M_int.size() == 2 - && _M_int[0] == _RealType(0) - && _M_int[1] == _RealType(1) - && _M_den[0] == _M_den[1])) - { - _M_int.clear(); - _M_den.clear(); - return; - } - - double __sum = 0.0; - _M_cp.reserve(_M_int.size() - 1); - _M_m.reserve(_M_int.size() - 1); - for (size_t __k = 0; __k < _M_int.size() - 1; ++__k) - { - const _RealType __delta = _M_int[__k + 1] - _M_int[__k]; - __sum += 0.5 * (_M_den[__k + 1] + _M_den[__k]) * __delta; - _M_cp.push_back(__sum); - _M_m.push_back((_M_den[__k + 1] - _M_den[__k]) / __delta); - } - - // Now normalize the densities... - __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(), - __sum); - // ... and partial sums... - __detail::__normalize(_M_cp.begin(), _M_cp.end(), _M_cp.begin(), __sum); - // ... and slopes. - __detail::__normalize(_M_m.begin(), _M_m.end(), _M_m.begin(), __sum); - - // Make sure the last cumulative probablility is one. - _M_cp[_M_cp.size() - 1] = 1.0; - } - - template - template - piecewise_linear_distribution<_RealType>::param_type:: - param_type(_InputIteratorB __bbegin, - _InputIteratorB __bend, - _InputIteratorW __wbegin) - : _M_int(), _M_den(), _M_cp(), _M_m() - { - for (; __bbegin != __bend; ++__bbegin, ++__wbegin) - { - _M_int.push_back(*__bbegin); - _M_den.push_back(*__wbegin); - } - - _M_initialize(); - } - - template - template - piecewise_linear_distribution<_RealType>::param_type:: - param_type(initializer_list<_RealType> __bl, _Func __fw) - : _M_int(), _M_den(), _M_cp(), _M_m() - { - _M_int.reserve(__bl.size()); - _M_den.reserve(__bl.size()); - for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter) - { - _M_int.push_back(*__biter); - _M_den.push_back(__fw(*__biter)); - } - - _M_initialize(); - } - - template - template - piecewise_linear_distribution<_RealType>::param_type:: - param_type(size_t __nw, _RealType __xmin, _RealType __xmax, _Func __fw) - : _M_int(), _M_den(), _M_cp(), _M_m() - { - const size_t __n = __nw == 0 ? 1 : __nw; - const _RealType __delta = (__xmax - __xmin) / __n; - - _M_int.reserve(__n + 1); - _M_den.reserve(__n + 1); - for (size_t __k = 0; __k <= __nw; ++__k) - { - _M_int.push_back(__xmin + __k * __delta); - _M_den.push_back(__fw(_M_int[__k] + __delta)); - } - - _M_initialize(); - } - - template - template - typename piecewise_linear_distribution<_RealType>::result_type - piecewise_linear_distribution<_RealType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __detail::_Adaptor<_UniformRandomNumberGenerator, double> - __aurng(__urng); - - const double __p = __aurng(); - if (__param._M_cp.empty()) - return __p; - - auto __pos = std::lower_bound(__param._M_cp.begin(), - __param._M_cp.end(), __p); - const size_t __i = __pos - __param._M_cp.begin(); - - const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; - - const double __a = 0.5 * __param._M_m[__i]; - const double __b = __param._M_den[__i]; - const double __cm = __p - __pref; - - _RealType __x = __param._M_int[__i]; - if (__a == 0) - __x += __cm / __b; - else - { - const double __d = __b * __b + 4.0 * __a * __cm; - __x += 0.5 * (std::sqrt(__d) - __b) / __a; - } - - return __x; - } - - template - template - void - piecewise_linear_distribution<_RealType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - // We could duplicate everything from operator()... - while (__f != __t) - *__f++ = this->operator()(__urng, __param); - } - - - template - seed_seq::seed_seq(std::initializer_list<_IntType> __il) - { - for (auto __iter = __il.begin(); __iter != __il.end(); ++__iter) - _M_v.push_back(__detail::__mod::__value>(*__iter)); - } - - template - seed_seq::seed_seq(_InputIterator __begin, _InputIterator __end) - { - for (_InputIterator __iter = __begin; __iter != __end; ++__iter) - _M_v.push_back(__detail::__mod::__value>(*__iter)); - } - - template - void - seed_seq::generate(_RandomAccessIterator __begin, - _RandomAccessIterator __end) - { - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _Type; - - if (__begin == __end) - return; - - std::fill(__begin, __end, _Type(0x8b8b8b8bu)); - - const size_t __n = __end - __begin; - const size_t __s = _M_v.size(); - const size_t __t = (__n >= 623) ? 11 - : (__n >= 68) ? 7 - : (__n >= 39) ? 5 - : (__n >= 7) ? 3 - : (__n - 1) / 2; - const size_t __p = (__n - __t) / 2; - const size_t __q = __p + __t; - const size_t __m = std::max(size_t(__s + 1), __n); - - for (size_t __k = 0; __k < __m; ++__k) - { - _Type __arg = (__begin[__k % __n] - ^ __begin[(__k + __p) % __n] - ^ __begin[(__k - 1) % __n]); - _Type __r1 = __arg ^ (__arg >> 27); - __r1 = __detail::__mod<_Type, - __detail::_Shift<_Type, 32>::__value>(1664525u * __r1); - _Type __r2 = __r1; - if (__k == 0) - __r2 += __s; - else if (__k <= __s) - __r2 += __k % __n + _M_v[__k - 1]; - else - __r2 += __k % __n; - __r2 = __detail::__mod<_Type, - __detail::_Shift<_Type, 32>::__value>(__r2); - __begin[(__k + __p) % __n] += __r1; - __begin[(__k + __q) % __n] += __r2; - __begin[__k % __n] = __r2; - } - - for (size_t __k = __m; __k < __m + __n; ++__k) - { - _Type __arg = (__begin[__k % __n] - + __begin[(__k + __p) % __n] - + __begin[(__k - 1) % __n]); - _Type __r3 = __arg ^ (__arg >> 27); - __r3 = __detail::__mod<_Type, - __detail::_Shift<_Type, 32>::__value>(1566083941u * __r3); - _Type __r4 = __r3 - __k % __n; - __r4 = __detail::__mod<_Type, - __detail::_Shift<_Type, 32>::__value>(__r4); - __begin[(__k + __p) % __n] ^= __r3; - __begin[(__k + __q) % __n] ^= __r4; - __begin[__k % __n] = __r4; - } - } - - template - _RealType - generate_canonical(_UniformRandomNumberGenerator& __urng) - { - static_assert(std::is_floating_point<_RealType>::value, - "template argument must be a floating point type"); - - const size_t __b - = std::min(static_cast(std::numeric_limits<_RealType>::digits), - __bits); - const long double __r = static_cast(__urng.max()) - - static_cast(__urng.min()) + 1.0L; - const size_t __log2r = std::log(__r) / std::log(2.0L); - const size_t __m = std::max(1UL, - (__b + __log2r - 1UL) / __log2r); - _RealType __ret; - _RealType __sum = _RealType(0); - _RealType __tmp = _RealType(1); - for (size_t __k = __m; __k != 0; --__k) - { - __sum += _RealType(__urng() - __urng.min()) * __tmp; - __tmp *= __r; - } - __ret = __sum / __tmp; - if (__builtin_expect(__ret >= _RealType(1), 0)) - { -#if _GLIBCXX_USE_C99_MATH_TR1 - __ret = std::nextafter(_RealType(1), _RealType(0)); -#else - __ret = _RealType(1) - - std::numeric_limits<_RealType>::epsilon() / _RealType(2); -#endif - } - return __ret; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/range_access.h b/resources/sources/avr-libstdcpp/include/bits/range_access.h deleted file mode 100644 index 3919183c5..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/range_access.h +++ /dev/null @@ -1,1148 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2010-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/range_access.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iterator} - */ - -#ifndef _GLIBCXX_RANGE_ACCESS_H -#define _GLIBCXX_RANGE_ACCESS_H 1 - -#pragma GCC system_header - -#if __cplusplus >= 201103L -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @brief Return an iterator pointing to the first element of - * the container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - begin(_Container& __cont) -> decltype(__cont.begin()) - { return __cont.begin(); } - - /** - * @brief Return an iterator pointing to the first element of - * the const container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - begin(const _Container& __cont) -> decltype(__cont.begin()) - { return __cont.begin(); } - - /** - * @brief Return an iterator pointing to one past the last element of - * the container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - end(_Container& __cont) -> decltype(__cont.end()) - { return __cont.end(); } - - /** - * @brief Return an iterator pointing to one past the last element of - * the const container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - end(const _Container& __cont) -> decltype(__cont.end()) - { return __cont.end(); } - - /** - * @brief Return an iterator pointing to the first element of the array. - * @param __arr Array. - */ - template - inline _GLIBCXX14_CONSTEXPR _Tp* - begin(_Tp (&__arr)[_Nm]) - { return __arr; } - - /** - * @brief Return an iterator pointing to one past the last element - * of the array. - * @param __arr Array. - */ - template - inline _GLIBCXX14_CONSTEXPR _Tp* - end(_Tp (&__arr)[_Nm]) - { return __arr + _Nm; } - -#if __cplusplus >= 201402L - - template class valarray; - // These overloads must be declared for cbegin and cend to use them. - template _Tp* begin(valarray<_Tp>&); - template const _Tp* begin(const valarray<_Tp>&); - template _Tp* end(valarray<_Tp>&); - template const _Tp* end(const valarray<_Tp>&); - - /** - * @brief Return an iterator pointing to the first element of - * the const container. - * @param __cont Container. - */ - template - inline constexpr auto - cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont))) - -> decltype(std::begin(__cont)) - { return std::begin(__cont); } - - /** - * @brief Return an iterator pointing to one past the last element of - * the const container. - * @param __cont Container. - */ - template - inline constexpr auto - cend(const _Container& __cont) noexcept(noexcept(std::end(__cont))) - -> decltype(std::end(__cont)) - { return std::end(__cont); } - - /** - * @brief Return a reverse iterator pointing to the last element of - * the container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - rbegin(_Container& __cont) -> decltype(__cont.rbegin()) - { return __cont.rbegin(); } - - /** - * @brief Return a reverse iterator pointing to the last element of - * the const container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - rbegin(const _Container& __cont) -> decltype(__cont.rbegin()) - { return __cont.rbegin(); } - - /** - * @brief Return a reverse iterator pointing one past the first element of - * the container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - rend(_Container& __cont) -> decltype(__cont.rend()) - { return __cont.rend(); } - - /** - * @brief Return a reverse iterator pointing one past the first element of - * the const container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - rend(const _Container& __cont) -> decltype(__cont.rend()) - { return __cont.rend(); } - - /** - * @brief Return a reverse iterator pointing to the last element of - * the array. - * @param __arr Array. - */ - template - inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> - rbegin(_Tp (&__arr)[_Nm]) - { return reverse_iterator<_Tp*>(__arr + _Nm); } - - /** - * @brief Return a reverse iterator pointing one past the first element of - * the array. - * @param __arr Array. - */ - template - inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> - rend(_Tp (&__arr)[_Nm]) - { return reverse_iterator<_Tp*>(__arr); } - - /** - * @brief Return a reverse iterator pointing to the last element of - * the initializer_list. - * @param __il initializer_list. - */ - template - inline _GLIBCXX17_CONSTEXPR reverse_iterator - rbegin(initializer_list<_Tp> __il) - { return reverse_iterator(__il.end()); } - - /** - * @brief Return a reverse iterator pointing one past the first element of - * the initializer_list. - * @param __il initializer_list. - */ - template - inline _GLIBCXX17_CONSTEXPR reverse_iterator - rend(initializer_list<_Tp> __il) - { return reverse_iterator(__il.begin()); } - - /** - * @brief Return a reverse iterator pointing to the last element of - * the const container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont)) - { return std::rbegin(__cont); } - - /** - * @brief Return a reverse iterator pointing one past the first element of - * the const container. - * @param __cont Container. - */ - template - inline _GLIBCXX17_CONSTEXPR auto - crend(const _Container& __cont) -> decltype(std::rend(__cont)) - { return std::rend(__cont); } - -#endif // C++14 - -#if __cplusplus >= 201703L -#define __cpp_lib_nonmember_container_access 201411 - - /** - * @brief Return the size of a container. - * @param __cont Container. - */ - template - constexpr auto - size(const _Container& __cont) noexcept(noexcept(__cont.size())) - -> decltype(__cont.size()) - { return __cont.size(); } - - /** - * @brief Return the size of an array. - */ - template - constexpr size_t - size(const _Tp (&)[_Nm]) noexcept - { return _Nm; } - - /** - * @brief Return whether a container is empty. - * @param __cont Container. - */ - template - [[nodiscard]] constexpr auto - empty(const _Container& __cont) noexcept(noexcept(__cont.empty())) - -> decltype(__cont.empty()) - { return __cont.empty(); } - - /** - * @brief Return whether an array is empty (always false). - */ - template - [[nodiscard]] constexpr bool - empty(const _Tp (&)[_Nm]) noexcept - { return false; } - - /** - * @brief Return whether an initializer_list is empty. - * @param __il Initializer list. - */ - template - [[nodiscard]] constexpr bool - empty(initializer_list<_Tp> __il) noexcept - { return __il.size() == 0;} - - /** - * @brief Return the data pointer of a container. - * @param __cont Container. - */ - template - constexpr auto - data(_Container& __cont) noexcept(noexcept(__cont.data())) - -> decltype(__cont.data()) - { return __cont.data(); } - - /** - * @brief Return the data pointer of a const container. - * @param __cont Container. - */ - template - constexpr auto - data(const _Container& __cont) noexcept(noexcept(__cont.data())) - -> decltype(__cont.data()) - { return __cont.data(); } - - /** - * @brief Return the data pointer of an array. - * @param __array Array. - */ - template - constexpr _Tp* - data(_Tp (&__array)[_Nm]) noexcept - { return __array; } - - /** - * @brief Return the data pointer of an initializer list. - * @param __il Initializer list. - */ - template - constexpr const _Tp* - data(initializer_list<_Tp> __il) noexcept - { return __il.begin(); } - -#endif // C++17 - -#if __cplusplus > 201703L -#define __cpp_lib_ssize 201902L - template - constexpr auto - ssize(const _Container& __cont) - noexcept(noexcept(__cont.size())) - -> common_type_t> - { - using type = make_signed_t; - return static_cast>(__cont.size()); - } - - template - constexpr ptrdiff_t - ssize(const _Tp (&)[_Num]) noexcept - { return _Num; } - -#ifdef __cpp_lib_concepts -namespace ranges -{ - template - inline constexpr bool disable_sized_range = false; - - template - inline constexpr bool enable_borrowed_range = false; - - template - extern const bool enable_view; - - namespace __detail - { - template - constexpr make_unsigned_t<_Tp> - __to_unsigned_like(_Tp __t) noexcept - { return __t; } - - template> - using __make_unsigned_like_t - = conditional_t<_MaxDiff, __max_size_type, make_unsigned_t<_Tp>>; - - // Part of the constraints of ranges::borrowed_range - template - concept __maybe_borrowed_range - = is_lvalue_reference_v<_Tp> - || enable_borrowed_range>; - - } // namespace __detail - - namespace __cust_access - { - using std::ranges::__detail::__maybe_borrowed_range; - using std::__detail::__class_or_enum; - using std::__detail::__decay_copy; - using std::__detail::__member_begin; - using std::__detail::__adl_begin; - - struct _Begin - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (is_array_v>) - return true; - else if constexpr (__member_begin<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().begin())); - else - return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); - } - - public: - template<__maybe_borrowed_range _Tp> - requires is_array_v> || __member_begin<_Tp> - || __adl_begin<_Tp> - constexpr auto - operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) - { - if constexpr (is_array_v>) - { - static_assert(is_lvalue_reference_v<_Tp>); - using _Up = remove_all_extents_t>; - static_assert(sizeof(_Up) != 0, "not array of incomplete type"); - return __t + 0; - } - else if constexpr (__member_begin<_Tp>) - return __t.begin(); - else - return begin(__t); - } - }; - - template - concept __member_end = requires(_Tp& __t) - { - { __decay_copy(__t.end()) } - -> sentinel_for(__t)))>; - }; - - void end(auto&) = delete; - void end(const auto&) = delete; - - template - concept __adl_end = __class_or_enum> - && requires(_Tp& __t) - { - { __decay_copy(end(__t)) } - -> sentinel_for(__t)))>; - }; - - struct _End - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (is_bounded_array_v>) - return true; - else if constexpr (__member_end<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().end())); - else - return noexcept(__decay_copy(end(std::declval<_Tp&>()))); - } - - public: - template<__maybe_borrowed_range _Tp> - requires is_bounded_array_v> || __member_end<_Tp> - || __adl_end<_Tp> - constexpr auto - operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) - { - if constexpr (is_bounded_array_v>) - { - static_assert(is_lvalue_reference_v<_Tp>); - return __t + extent_v>; - } - else if constexpr (__member_end<_Tp>) - return __t.end(); - else - return end(__t); - } - }; - - template - constexpr decltype(auto) - __as_const(_Tp&& __t) noexcept - { - if constexpr (is_lvalue_reference_v<_Tp>) - return static_cast&>(__t); - else - return static_cast(__t); - } - - struct _CBegin - { - template - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_Begin{}(__cust_access::__as_const((_Tp&&)__e)))) - requires requires { _Begin{}(__cust_access::__as_const((_Tp&&)__e)); } - { - return _Begin{}(__cust_access::__as_const(std::forward<_Tp>(__e))); - } - }; - - struct _CEnd - { - template - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_End{}(__cust_access::__as_const((_Tp&&)__e)))) - requires requires { _End{}(__cust_access::__as_const((_Tp&&)__e)); } - { - return _End{}(__cust_access::__as_const(std::forward<_Tp>(__e))); - } - }; - - template - concept __member_rbegin = requires(_Tp& __t) - { - { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; - }; - - void rbegin(auto&) = delete; - void rbegin(const auto&) = delete; - - template - concept __adl_rbegin = __class_or_enum> - && requires(_Tp& __t) - { - { __decay_copy(rbegin(__t)) } -> input_or_output_iterator; - }; - - template - concept __reversable = requires(_Tp& __t) - { - { _Begin{}(__t) } -> bidirectional_iterator; - { _End{}(__t) } -> same_as; - }; - - struct _RBegin - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (__member_rbegin<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().rbegin())); - else if constexpr (__adl_rbegin<_Tp>) - return noexcept(__decay_copy(rbegin(std::declval<_Tp&>()))); - else - { - if constexpr (noexcept(_End{}(std::declval<_Tp&>()))) - { - using _It = decltype(_End{}(std::declval<_Tp&>())); - // std::reverse_iterator copy-initializes its member. - return is_nothrow_copy_constructible_v<_It>; - } - else - return false; - } - } - - public: - template<__maybe_borrowed_range _Tp> - requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp> - constexpr auto - operator()(_Tp&& __t) const - noexcept(_S_noexcept<_Tp>()) - { - if constexpr (__member_rbegin<_Tp>) - return __t.rbegin(); - else if constexpr (__adl_rbegin<_Tp>) - return rbegin(__t); - else - return std::make_reverse_iterator(_End{}(__t)); - } - }; - - template - concept __member_rend = requires(_Tp& __t) - { - { __decay_copy(__t.rend()) } - -> sentinel_for; - }; - - void rend(auto&) = delete; - void rend(const auto&) = delete; - - template - concept __adl_rend = __class_or_enum> - && requires(_Tp& __t) - { - { __decay_copy(rend(__t)) } - -> sentinel_for(__t)))>; - }; - - struct _REnd - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (__member_rend<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp&>().rend())); - else if constexpr (__adl_rend<_Tp>) - return noexcept(__decay_copy(rend(std::declval<_Tp&>()))); - else - { - if constexpr (noexcept(_Begin{}(std::declval<_Tp&>()))) - { - using _It = decltype(_Begin{}(std::declval<_Tp&>())); - // std::reverse_iterator copy-initializes its member. - return is_nothrow_copy_constructible_v<_It>; - } - else - return false; - } - } - - public: - template<__maybe_borrowed_range _Tp> - requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp> - constexpr auto - operator()(_Tp&& __t) const - noexcept(_S_noexcept<_Tp>()) - { - if constexpr (__member_rend<_Tp>) - return __t.rend(); - else if constexpr (__adl_rend<_Tp>) - return rend(__t); - else - return std::make_reverse_iterator(_Begin{}(__t)); - } - }; - - struct _CRBegin - { - template - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_RBegin{}(__cust_access::__as_const((_Tp&&)__e)))) - requires requires { _RBegin{}(__cust_access::__as_const((_Tp&&)__e)); } - { - return _RBegin{}(__cust_access::__as_const(std::forward<_Tp>(__e))); - } - }; - - struct _CREnd - { - template - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_REnd{}(__cust_access::__as_const((_Tp&&)__e)))) - requires requires { _REnd{}(__cust_access::__as_const((_Tp&&)__e)); } - { - return _REnd{}(__cust_access::__as_const(std::forward<_Tp>(__e))); - } - }; - - template - concept __member_size = !disable_sized_range> - && requires(_Tp&& __t) - { - { __decay_copy(std::forward<_Tp>(__t).size()) } - -> __detail::__is_integer_like; - }; - - void size(auto&) = delete; - void size(const auto&) = delete; - - template - concept __adl_size = __class_or_enum> - && !disable_sized_range> - && requires(_Tp&& __t) - { - { __decay_copy(size(std::forward<_Tp>(__t))) } - -> __detail::__is_integer_like; - }; - - template - concept __sentinel_size = requires(_Tp&& __t) - { - { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator; - - { _End{}(std::forward<_Tp>(__t)) } - -> sized_sentinel_for(__t)))>; - }; - - struct _Size - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (is_bounded_array_v>) - return true; - else if constexpr (__member_size<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp>().size())); - else if constexpr (__adl_size<_Tp>) - return noexcept(__decay_copy(size(std::declval<_Tp>()))); - else if constexpr (__sentinel_size<_Tp>) - return noexcept(_End{}(std::declval<_Tp>()) - - _Begin{}(std::declval<_Tp>())); - } - - public: - template - requires is_bounded_array_v> - || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp> - constexpr auto - operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) - { - if constexpr (is_bounded_array_v>) - { - return extent_v>; - } - else if constexpr (__member_size<_Tp>) - return std::forward<_Tp>(__e).size(); - else if constexpr (__adl_size<_Tp>) - return size(std::forward<_Tp>(__e)); - else if constexpr (__sentinel_size<_Tp>) - return __detail::__to_unsigned_like( - _End{}(std::forward<_Tp>(__e)) - - _Begin{}(std::forward<_Tp>(__e))); - } - }; - - struct _SSize - { - template - requires requires (_Tp&& __e) - { - _Begin{}(std::forward<_Tp>(__e)); - _Size{}(std::forward<_Tp>(__e)); - } - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_Size{}(std::forward<_Tp>(__e)))) - { - using __iter_type = decltype(_Begin{}(std::forward<_Tp>(__e))); - using __diff_type = iter_difference_t<__iter_type>; - using __gnu_cxx::__int_traits; - auto __size = _Size{}(std::forward<_Tp>(__e)); - if constexpr (integral<__diff_type>) - { - if constexpr (__int_traits<__diff_type>::__digits - < __int_traits::__digits) - return static_cast(__size); - } - return static_cast<__diff_type>(__size); - } - }; - - template - concept __member_empty = requires(_Tp&& __t) - { bool(std::forward<_Tp>(__t).empty()); }; - - template - concept __size0_empty = requires(_Tp&& __t) - { _Size{}(std::forward<_Tp>(__t)) == 0; }; - - template - concept __eq_iter_empty = requires(_Tp&& __t) - { - { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator; - bool(_Begin{}(std::forward<_Tp>(__t)) - == _End{}(std::forward<_Tp>(__t))); - }; - - struct _Empty - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (__member_empty<_Tp>) - return noexcept(std::declval<_Tp>().empty()); - else if constexpr (__size0_empty<_Tp>) - return noexcept(_Size{}(std::declval<_Tp>()) == 0); - else - return noexcept(bool(_Begin{}(std::declval<_Tp>()) - == _End{}(std::declval<_Tp>()))); - } - - public: - template - requires __member_empty<_Tp> || __size0_empty<_Tp> - || __eq_iter_empty<_Tp> - constexpr bool - operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) - { - if constexpr (__member_empty<_Tp>) - return bool(std::forward<_Tp>(__e).empty()); - else if constexpr (__size0_empty<_Tp>) - return _Size{}(std::forward<_Tp>(__e)) == 0; - else - return bool(_Begin{}(std::forward<_Tp>(__e)) - == _End{}(std::forward<_Tp>(__e))); - } - }; - - template - concept __pointer_to_object = is_pointer_v<_Tp> - && is_object_v>; - - template - concept __member_data = is_lvalue_reference_v<_Tp> - && requires(_Tp __t) { { __t.data() } -> __pointer_to_object; }; - - template - concept __begin_data = requires(_Tp&& __t) - { { _Begin{}(std::forward<_Tp>(__t)) } -> contiguous_iterator; }; - - struct _Data - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (__member_data<_Tp>) - return noexcept(__decay_copy(std::declval<_Tp>().data())); - else - return noexcept(_Begin{}(std::declval<_Tp>())); - } - - public: - template<__maybe_borrowed_range _Tp> - requires __member_data<_Tp> || __begin_data<_Tp> - constexpr auto - operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) - { - if constexpr (__member_data<_Tp>) - return __e.data(); - else - return std::to_address(_Begin{}(std::forward<_Tp>(__e))); - } - }; - - struct _CData - { - template - constexpr auto - operator()(_Tp&& __e) const - noexcept(noexcept(_Data{}(__cust_access::__as_const((_Tp&&)__e)))) - requires requires { _Data{}(__cust_access::__as_const((_Tp&&)__e)); } - { - return _Data{}(__cust_access::__as_const(std::forward<_Tp>(__e))); - } - }; - - } // namespace __cust_access - - inline namespace __cust - { - inline constexpr __cust_access::_Begin begin{}; - inline constexpr __cust_access::_End end{}; - inline constexpr __cust_access::_CBegin cbegin{}; - inline constexpr __cust_access::_CEnd cend{}; - inline constexpr __cust_access::_RBegin rbegin{}; - inline constexpr __cust_access::_REnd rend{}; - inline constexpr __cust_access::_CRBegin crbegin{}; - inline constexpr __cust_access::_CREnd crend{}; - inline constexpr __cust_access::_Size size{}; - inline constexpr __cust_access::_SSize ssize{}; - inline constexpr __cust_access::_Empty empty{}; - inline constexpr __cust_access::_Data data{}; - inline constexpr __cust_access::_CData cdata{}; - } - - /// [range.range] The range concept. - template - concept range = requires(_Tp& __t) - { - ranges::begin(__t); - ranges::end(__t); - }; - - /// [range.range] The borrowed_range concept. - template - concept borrowed_range - = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>; - - template - using iterator_t = std::__detail::__range_iter_t<_Tp>; - - template - using sentinel_t = decltype(ranges::end(std::declval<_Range&>())); - - template - using range_difference_t = iter_difference_t>; - - template - using range_value_t = iter_value_t>; - - template - using range_reference_t = iter_reference_t>; - - template - using range_rvalue_reference_t - = iter_rvalue_reference_t>; - - /// [range.sized] The sized_range concept. - template - concept sized_range = range<_Tp> - && requires(_Tp& __t) { ranges::size(__t); }; - - template - using range_size_t = decltype(ranges::size(std::declval<_Range&>())); - - // [range.refinements] - - /// A range for which ranges::begin returns an output iterator. - template - concept output_range - = range<_Range> && output_iterator, _Tp>; - - /// A range for which ranges::begin returns an input iterator. - template - concept input_range = range<_Tp> && input_iterator>; - - /// A range for which ranges::begin returns a forward iterator. - template - concept forward_range - = input_range<_Tp> && forward_iterator>; - - /// A range for which ranges::begin returns a bidirectional iterator. - template - concept bidirectional_range - = forward_range<_Tp> && bidirectional_iterator>; - - /// A range for which ranges::begin returns a random access iterator. - template - concept random_access_range - = bidirectional_range<_Tp> && random_access_iterator>; - - /// A range for which ranges::begin returns a contiguous iterator. - template - concept contiguous_range - = random_access_range<_Tp> && contiguous_iterator> - && requires(_Tp& __t) - { - { ranges::data(__t) } -> same_as>>; - }; - - /// A range for which ranges::begin and ranges::end return the same type. - template - concept common_range - = range<_Tp> && same_as, sentinel_t<_Tp>>; - - // [range.iter.ops] range iterator operations - - template - constexpr void - advance(_It& __it, iter_difference_t<_It> __n) - { - if constexpr (random_access_iterator<_It>) - __it += __n; - else if constexpr (bidirectional_iterator<_It>) - { - if (__n > 0) - { - do - { - ++__it; - } - while (--__n); - } - else if (__n < 0) - { - do - { - --__it; - } - while (++__n); - } - } - else - { -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated() && __n < 0) - throw "attempt to decrement a non-bidirectional iterator"; -#endif - __glibcxx_assert(__n >= 0); - while (__n-- > 0) - ++__it; - } - } - - template _Sent> - constexpr void - advance(_It& __it, _Sent __bound) - { - if constexpr (assignable_from<_It&, _Sent>) - __it = std::move(__bound); - else if constexpr (sized_sentinel_for<_Sent, _It>) - ranges::advance(__it, __bound - __it); - else - { - while (__it != __bound) - ++__it; - } - } - - template _Sent> - constexpr iter_difference_t<_It> - advance(_It& __it, iter_difference_t<_It> __n, _Sent __bound) - { - if constexpr (sized_sentinel_for<_Sent, _It>) - { - const auto __diff = __bound - __it; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated() - && !(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0))) - throw "inconsistent directions for distance and bound"; -#endif - // n and bound must not lead in opposite directions: - __glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0)); - const auto __absdiff = __diff < 0 ? -__diff : __diff; - const auto __absn = __n < 0 ? -__n : __n;; - if (__absn >= __absdiff) - { - ranges::advance(__it, __bound); - return __n - __diff; - } - else - { - ranges::advance(__it, __n); - return 0; - } - } - else if (__it == __bound || __n == 0) - return iter_difference_t<_It>(0); - else if (__n > 0) - { - iter_difference_t<_It> __m = 0; - do - { - ++__it; - ++__m; - } - while (__m != __n && __it != __bound); - return __n - __m; - } - else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>) - { - iter_difference_t<_It> __m = 0; - do - { - --__it; - --__m; - } - while (__m != __n && __it != __bound); - return __n - __m; - } - else - { -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated() && __n < 0) - throw "attempt to decrement a non-bidirectional iterator"; -#endif - __glibcxx_assert(__n >= 0); - return __n; - } - } - - template _Sent> - constexpr iter_difference_t<_It> - distance(_It __first, _Sent __last) - { - if constexpr (sized_sentinel_for<_Sent, _It>) - return __last - __first; - else - { - iter_difference_t<_It> __n = 0; - while (__first != __last) - { - ++__first; - ++__n; - } - return __n; - } - } - - template - constexpr range_difference_t<_Range> - distance(_Range&& __r) - { - if constexpr (sized_range<_Range>) - return static_cast>(ranges::size(__r)); - else - return ranges::distance(ranges::begin(__r), ranges::end(__r)); - } - - template - constexpr _It - next(_It __x) - { - ++__x; - return __x; - } - - template - constexpr _It - next(_It __x, iter_difference_t<_It> __n) - { - ranges::advance(__x, __n); - return __x; - } - - template _Sent> - constexpr _It - next(_It __x, _Sent __bound) - { - ranges::advance(__x, __bound); - return __x; - } - - template _Sent> - constexpr _It - next(_It __x, iter_difference_t<_It> __n, _Sent __bound) - { - ranges::advance(__x, __n, __bound); - return __x; - } - - template - constexpr _It - prev(_It __x) - { - --__x; - return __x; - } - - template - constexpr _It - prev(_It __x, iter_difference_t<_It> __n) - { - ranges::advance(__x, -__n); - return __x; - } - - template - constexpr _It - prev(_It __x, iter_difference_t<_It> __n, _It __bound) - { - ranges::advance(__x, -__n, __bound); - return __x; - } - -} // namespace ranges -#endif // library concepts -#endif // C++20 -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 - -#endif // _GLIBCXX_RANGE_ACCESS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/range_cmp.h b/resources/sources/avr-libstdcpp/include/bits/range_cmp.h deleted file mode 100644 index 0587c599c..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/range_cmp.h +++ /dev/null @@ -1,195 +0,0 @@ -// Concept-constrained comparison implementations -*- C++ -*- - -// Copyright (C) 2019-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/range_cmp.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _RANGE_CMP_H -#define _RANGE_CMP_H 1 - -#if __cplusplus > 201703L -# include -# include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - struct __is_transparent; // not defined - - // Define std::identity here so that and - // don't need to include to get it. - - /// [func.identity] The identity function. - struct identity - { - template - constexpr _Tp&& - operator()(_Tp&& __t) const noexcept - { return std::forward<_Tp>(__t); } - - using is_transparent = __is_transparent; - }; - -#ifdef __cpp_lib_concepts -// Define this here, included by all the headers that need to define it. -#define __cpp_lib_ranges 201911L - -namespace ranges -{ - namespace __detail - { - // BUILTIN-PTR-CMP(T, ==, U) - template - concept __eq_builtin_ptr_cmp - = requires (_Tp&& __t, _Up&& __u) { { __t == __u } -> same_as; } - && convertible_to<_Tp, const volatile void*> - && convertible_to<_Up, const volatile void*> - && (! requires(_Tp&& __t, _Up&& __u) - { operator==(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } - && - ! requires(_Tp&& __t, _Up&& __u) - { std::forward<_Tp>(__t).operator==(std::forward<_Up>(__u)); }); - - // BUILTIN-PTR-CMP(T, <, U) - template - concept __less_builtin_ptr_cmp - = requires (_Tp&& __t, _Up&& __u) { { __t < __u } -> same_as; } - && convertible_to<_Tp, const volatile void*> - && convertible_to<_Up, const volatile void*> - && (! requires(_Tp&& __t, _Up&& __u) - { operator<(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } - && ! requires(_Tp&& __t, _Up&& __u) - { std::forward<_Tp>(__t).operator<(std::forward<_Up>(__u)); }); - } // namespace __detail - - // [range.cmp] Concept-constrained comparisons - - /// ranges::equal_to function object type. - struct equal_to - { - template - requires equality_comparable_with<_Tp, _Up> - || __detail::__eq_builtin_ptr_cmp<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) - { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } - - using is_transparent = __is_transparent; - }; - - /// ranges::not_equal_to function object type. - struct not_equal_to - { - template - requires equality_comparable_with<_Tp, _Up> - || __detail::__eq_builtin_ptr_cmp<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::declval<_Up>() == std::declval<_Tp>())) - { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } - - using is_transparent = __is_transparent; - }; - - /// ranges::less function object type. - struct less - { - template - requires totally_ordered_with<_Tp, _Up> - || __detail::__less_builtin_ptr_cmp<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) - { - if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>) - { -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return __t < __u; -#endif - auto __x = reinterpret_cast<__UINTPTR_TYPE__>( - static_cast(std::forward<_Tp>(__t))); - auto __y = reinterpret_cast<__UINTPTR_TYPE__>( - static_cast(std::forward<_Up>(__u))); - return __x < __y; - } - else - return std::forward<_Tp>(__t) < std::forward<_Up>(__u); - } - - using is_transparent = __is_transparent; - }; - - /// ranges::greater function object type. - struct greater - { - template - requires totally_ordered_with<_Tp, _Up> - || __detail::__less_builtin_ptr_cmp<_Up, _Tp> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) - { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } - - using is_transparent = __is_transparent; - }; - - /// ranges::greater_equal function object type. - struct greater_equal - { - template - requires totally_ordered_with<_Tp, _Up> - || __detail::__less_builtin_ptr_cmp<_Tp, _Up> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) - { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } - - using is_transparent = __is_transparent; - }; - - /// ranges::less_equal function object type. - struct less_equal - { - template - requires totally_ordered_with<_Tp, _Up> - || __detail::__less_builtin_ptr_cmp<_Up, _Tp> - constexpr bool - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) - { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } - - using is_transparent = __is_transparent; - }; - -} // namespace ranges -#endif // library concepts -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 -#endif // _RANGE_CMP_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h b/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h deleted file mode 100644 index 4d4f74016..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h +++ /dev/null @@ -1,3792 +0,0 @@ -// Core algorithmic facilities -*- C++ -*- - -// Copyright (C) 2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/ranges_algo.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{algorithm} - */ - -#ifndef _RANGES_ALGO_H -#define _RANGES_ALGO_H 1 - -#if __cplusplus > 201703L - -#include -#include // concept uniform_random_bit_generator - -#if __cpp_lib_concepts -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -namespace ranges -{ - namespace __detail - { - template - constexpr auto - __make_comp_proj(_Comp& __comp, _Proj& __proj) - { - return [&] (auto&& __lhs, auto&& __rhs) -> bool { - using _TL = decltype(__lhs); - using _TR = decltype(__rhs); - return std::__invoke(__comp, - std::__invoke(__proj, std::forward<_TL>(__lhs)), - std::__invoke(__proj, std::forward<_TR>(__rhs))); - }; - } - - template - constexpr auto - __make_pred_proj(_Pred& __pred, _Proj& __proj) - { - return [&] (_Tp&& __arg) -> bool { - return std::__invoke(__pred, - std::__invoke(__proj, std::forward<_Tp>(__arg))); - }; - } - } // namespace __detail - - struct __all_of_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr bool - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - return false; - return true; - } - - template, _Proj>> - _Pred> - constexpr bool - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __all_of_fn all_of{}; - - struct __any_of_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr bool - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - return true; - return false; - } - - template, _Proj>> - _Pred> - constexpr bool - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __any_of_fn any_of{}; - - struct __none_of_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr bool - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - return false; - return true; - } - - template, _Proj>> - _Pred> - constexpr bool - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __none_of_fn none_of{}; - - template - struct in_fun_result - { - [[no_unique_address]] _Iter in; - [[no_unique_address]] _Fp fun; - - template - requires convertible_to - && convertible_to - constexpr - operator in_fun_result<_Iter2, _F2p>() const & - { return {in, fun}; } - - template - requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p> - constexpr - operator in_fun_result<_Iter2, _F2p>() && - { return {std::move(in), std::move(fun)}; } - }; - - template - using for_each_result = in_fun_result<_Iter, _Fp>; - - struct __for_each_fn - { - template _Sent, - typename _Proj = identity, - indirectly_unary_invocable> _Fun> - constexpr for_each_result<_Iter, _Fun> - operator()(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - std::__invoke(__f, std::__invoke(__proj, *__first)); - return { std::move(__first), std::move(__f) }; - } - - template, _Proj>> - _Fun> - constexpr for_each_result, _Fun> - operator()(_Range&& __r, _Fun __f, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__f), std::move(__proj)); - } - }; - - inline constexpr __for_each_fn for_each{}; - - template - using for_each_n_result = in_fun_result<_Iter, _Fp>; - - struct __for_each_n_fn - { - template> _Fun> - constexpr for_each_n_result<_Iter, _Fun> - operator()(_Iter __first, iter_difference_t<_Iter> __n, - _Fun __f, _Proj __proj = {}) const - { - if constexpr (random_access_iterator<_Iter>) - { - if (__n <= 0) - return {std::move(__first), std::move(__f)}; - auto __last = __first + __n; - return ranges::for_each(std::move(__first), std::move(__last), - std::move(__f), std::move(__proj)); - } - else - { - while (__n-- > 0) - { - std::__invoke(__f, std::__invoke(__proj, *__first)); - ++__first; - } - return {std::move(__first), std::move(__f)}; - } - } - }; - - inline constexpr __for_each_n_fn for_each_n{}; - - struct __find_fn - { - template _Sent, typename _Tp, - typename _Proj = identity> - requires indirect_binary_predicate, const _Tp*> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - const _Tp& __value, _Proj __proj = {}) const - { - while (__first != __last - && !(std::__invoke(__proj, *__first) == __value)) - ++__first; - return __first; - } - - template - requires indirect_binary_predicate, _Proj>, - const _Tp*> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - __value, std::move(__proj)); - } - }; - - inline constexpr __find_fn find{}; - - struct __find_if_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - while (__first != __last - && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__first; - return __first; - } - - template, _Proj>> - _Pred> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __find_if_fn find_if{}; - - struct __find_if_not_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - while (__first != __last - && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__first; - return __first; - } - - template, _Proj>> - _Pred> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __find_if_not_fn find_if_not{}; - - struct __find_first_of_fn - { - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr _Iter1 - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - for (; __first1 != __last1; ++__first1) - for (auto __iter = __first2; __iter != __last2; ++__iter) - if (std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__iter))) - return __first1; - return __first1; - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr borrowed_iterator_t<_Range1> - operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __find_first_of_fn find_first_of{}; - - struct __count_fn - { - template _Sent, - typename _Tp, typename _Proj = identity> - requires indirect_binary_predicate, - const _Tp*> - constexpr iter_difference_t<_Iter> - operator()(_Iter __first, _Sent __last, - const _Tp& __value, _Proj __proj = {}) const - { - iter_difference_t<_Iter> __n = 0; - for (; __first != __last; ++__first) - if (std::__invoke(__proj, *__first) == __value) - ++__n; - return __n; - } - - template - requires indirect_binary_predicate, _Proj>, - const _Tp*> - constexpr range_difference_t<_Range> - operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - __value, std::move(__proj)); - } - }; - - inline constexpr __count_fn count{}; - - struct __count_if_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr iter_difference_t<_Iter> - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - iter_difference_t<_Iter> __n = 0; - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__n; - return __n; - } - - template, _Proj>> - _Pred> - constexpr range_difference_t<_Range> - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __count_if_fn count_if{}; - - template - struct in_in_result - { - [[no_unique_address]] _Iter1 in1; - [[no_unique_address]] _Iter2 in2; - - template - requires convertible_to - && convertible_to - constexpr - operator in_in_result<_IIter1, _IIter2>() const & - { return {in1, in2}; } - - template - requires convertible_to<_Iter1, _IIter1> - && convertible_to<_Iter2, _IIter2> - constexpr - operator in_in_result<_IIter1, _IIter2>() && - { return {std::move(in1), std::move(in2)}; } - }; - - template - using mismatch_result = in_in_result<_Iter1, _Iter2>; - - struct __mismatch_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr mismatch_result<_Iter1, _Iter2> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - while (__first1 != __last1 && __first2 != __last2 - && (bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - { - ++__first1; - ++__first2; - } - return { std::move(__first1), std::move(__first2) }; - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr mismatch_result, iterator_t<_Range2>> - operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __mismatch_fn mismatch{}; - - struct __search_fn - { - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr subrange<_Iter1> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - if (__first1 == __last1 || __first2 == __last2) - return {__first1, __first1}; - - for (;;) - { - for (;;) - { - if (__first1 == __last1) - return {__first1, __first1}; - if (std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - break; - ++__first1; - } - auto __cur1 = __first1; - auto __cur2 = __first2; - for (;;) - { - if (++__cur2 == __last2) - return {__first1, ++__cur1}; - if (++__cur1 == __last1) - return {__cur1, __cur1}; - if (!(bool)std::__invoke(__pred, - std::__invoke(__proj1, *__cur1), - std::__invoke(__proj2, *__cur2))) - { - ++__first1; - break; - } - } - } - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr borrowed_subrange_t<_Range1> - operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __search_fn search{}; - - struct __search_n_fn - { - template _Sent, typename _Tp, - typename _Pred = ranges::equal_to, typename _Proj = identity> - requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj> - constexpr subrange<_Iter> - operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, - const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const - { - if (__count <= 0) - return {__first, __first}; - - auto __value_comp = [&] (_Rp&& __arg) { - return std::__invoke(__pred, std::forward<_Rp>(__arg), __value); - }; - if (__count == 1) - { - __first = ranges::find_if(std::move(__first), __last, - std::move(__value_comp), - std::move(__proj)); - if (__first == __last) - return {__first, __first}; - else - { - auto __end = __first; - return {__first, ++__end}; - } - } - - if constexpr (sized_sentinel_for<_Sent, _Iter>) - { - auto __tail_size = __last - __first; - auto __remainder = __count; - - while (__remainder <= __tail_size) - { - __first += __remainder; - __tail_size -= __remainder; - auto __backtrack = __first; - while (__value_comp(std::__invoke(__proj, *--__backtrack))) - { - if (--__remainder == 0) - return {__first - __count, __first}; - } - } - auto __i = __first + __tail_size; - return {__i, __i}; - } - else - { - __first = ranges::find_if(__first, __last, __value_comp, __proj); - while (__first != __last) - { - auto __n = __count; - auto __i = __first; - ++__i; - while (__i != __last && __n != 1 - && __value_comp(std::__invoke(__proj, *__i))) - { - ++__i; - --__n; - } - if (__n == 1) - return {__first, __i}; - if (__i == __last) - return {__i, __i}; - __first = ranges::find_if(++__i, __last, __value_comp, __proj); - } - return {__first, __first}; - } - } - - template - requires indirectly_comparable, const _Tp*, - _Pred, _Proj> - constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __r, range_difference_t<_Range> __count, - const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__count), __value, - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __search_n_fn search_n{}; - - struct __find_end_fn - { - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr subrange<_Iter1> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - if constexpr (bidirectional_iterator<_Iter1> - && bidirectional_iterator<_Iter2>) - { - auto __i1 = ranges::next(__first1, __last1); - auto __i2 = ranges::next(__first2, __last2); - auto __rresult - = ranges::search(reverse_iterator<_Iter1>{__i1}, - reverse_iterator<_Iter1>{__first1}, - reverse_iterator<_Iter2>{__i2}, - reverse_iterator<_Iter2>{__first2}, - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - auto __result_first = ranges::end(__rresult).base(); - auto __result_last = ranges::begin(__rresult).base(); - if (__result_last == __first1) - return {__i1, __i1}; - else - return {__result_first, __result_last}; - } - else - { - auto __i = ranges::next(__first1, __last1); - if (__first2 == __last2) - return {__i, __i}; - - auto __result_begin = __i; - auto __result_end = __i; - for (;;) - { - auto __new_range = ranges::search(__first1, __last1, - __first2, __last2, - __pred, __proj1, __proj2); - auto __new_result_begin = ranges::begin(__new_range); - auto __new_result_end = ranges::end(__new_range); - if (__new_result_begin == __last1) - return {__result_begin, __result_end}; - else - { - __result_begin = __new_result_begin; - __result_end = __new_result_end; - __first1 = __result_begin; - ++__first1; - } - } - } - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr borrowed_subrange_t<_Range1> - operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __find_end_fn find_end{}; - - struct __adjacent_find_fn - { - template _Sent, - typename _Proj = identity, - indirect_binary_predicate, - projected<_Iter, _Proj>> _Pred - = ranges::equal_to> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Pred __pred = {}, _Proj __proj = {}) const - { - if (__first == __last) - return __first; - auto __next = __first; - for (; ++__next != __last; __first = __next) - { - if (std::__invoke(__pred, - std::__invoke(__proj, *__first), - std::__invoke(__proj, *__next))) - return __first; - } - return __next; - } - - template, _Proj>, - projected, _Proj>> _Pred = ranges::equal_to> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __adjacent_find_fn adjacent_find{}; - - struct __is_permutation_fn - { - template _Sent1, - forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Proj1 = identity, typename _Proj2 = identity, - indirect_equivalence_relation, - projected<_Iter2, _Proj2>> _Pred - = ranges::equal_to> - constexpr bool - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - constexpr bool __sized_iters - = (sized_sentinel_for<_Sent1, _Iter1> - && sized_sentinel_for<_Sent2, _Iter2>); - if constexpr (__sized_iters) - { - auto __d1 = ranges::distance(__first1, __last1); - auto __d2 = ranges::distance(__first2, __last2); - if (__d1 != __d2) - return false; - } - - // Efficiently compare identical prefixes: O(N) if sequences - // have the same elements in the same order. - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - if (!(bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - break; - - if constexpr (__sized_iters) - { - if (__first1 == __last1) - return true; - } - else - { - auto __d1 = ranges::distance(__first1, __last1); - auto __d2 = ranges::distance(__first2, __last2); - if (__d1 == 0 && __d2 == 0) - return true; - if (__d1 != __d2) - return false; - } - - for (auto __scan = __first1; __scan != __last1; ++__scan) - { - auto __proj_scan = std::__invoke(__proj1, *__scan); - auto __comp_scan = [&] (_Tp&& __arg) { - return std::__invoke(__pred, __proj_scan, - std::forward<_Tp>(__arg)); - }; - if (__scan != ranges::find_if(__first1, __scan, - __comp_scan, __proj1)) - continue; // We've seen this one before. - - auto __matches = ranges::count_if(__first2, __last2, - __comp_scan, __proj2); - if (__matches == 0 - || ranges::count_if(__scan, __last1, - __comp_scan, __proj1) != __matches) - return false; - } - return true; - } - - template, _Proj1>, - projected, _Proj2>> _Pred = ranges::equal_to> - constexpr bool - operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __is_permutation_fn is_permutation{}; - - template - using copy_if_result = in_out_result<_Iter, _Out>; - - struct __copy_if_fn - { - template _Sent, - weakly_incrementable _Out, typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_Iter, _Out> - constexpr copy_if_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result, - _Pred __pred, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - { - *__result = *__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - - template, _Proj>> - _Pred> - requires indirectly_copyable, _Out> - constexpr copy_if_result, _Out> - operator()(_Range&& __r, _Out __result, - _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __copy_if_fn copy_if{}; - - template - using swap_ranges_result = in_in_result<_Iter1, _Iter2>; - - struct __swap_ranges_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2> - requires indirectly_swappable<_Iter1, _Iter2> - constexpr swap_ranges_result<_Iter1, _Iter2> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2) const - { - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - ranges::iter_swap(__first1, __first2); - return {std::move(__first1), std::move(__first2)}; - } - - template - requires indirectly_swappable, iterator_t<_Range2>> - constexpr swap_ranges_result, - borrowed_iterator_t<_Range2>> - operator()(_Range1&& __r1, _Range2&& __r2) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2)); - } - }; - - inline constexpr __swap_ranges_fn swap_ranges{}; - - template - using unary_transform_result = in_out_result<_Iter, _Out>; - - template - struct in_in_out_result - { - [[no_unique_address]] _Iter1 in1; - [[no_unique_address]] _Iter2 in2; - [[no_unique_address]] _Out out; - - template - requires convertible_to - && convertible_to - && convertible_to - constexpr - operator in_in_out_result<_IIter1, _IIter2, _OOut>() const & - { return {in1, in2, out}; } - - template - requires convertible_to<_Iter1, _IIter1> - && convertible_to<_Iter2, _IIter2> - && convertible_to<_Out, _OOut> - constexpr - operator in_in_out_result<_IIter1, _IIter2, _OOut>() && - { return {std::move(in1), std::move(in2), std::move(out)}; } - }; - - template - using binary_transform_result = in_in_out_result<_Iter1, _Iter2, _Out>; - - struct __transform_fn - { - template _Sent, - weakly_incrementable _Out, - copy_constructible _Fp, typename _Proj = identity> - requires indirectly_writable<_Out, - indirect_result_t<_Fp&, - projected<_Iter, _Proj>>> - constexpr unary_transform_result<_Iter, _Out> - operator()(_Iter __first1, _Sent __last1, _Out __result, - _Fp __op, _Proj __proj = {}) const - { - for (; __first1 != __last1; ++__first1, (void)++__result) - *__result = std::__invoke(__op, std::__invoke(__proj, *__first1)); - return {std::move(__first1), std::move(__result)}; - } - - template - requires indirectly_writable<_Out, - indirect_result_t<_Fp&, - projected, _Proj>>> - constexpr unary_transform_result, _Out> - operator()(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result), - std::move(__op), std::move(__proj)); - } - - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, copy_constructible _Fp, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_writable<_Out, - indirect_result_t<_Fp&, - projected<_Iter1, _Proj1>, - projected<_Iter2, _Proj2>>> - constexpr binary_transform_result<_Iter1, _Iter2, _Out> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Out __result, _Fp __binary_op, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2, ++__result) - *__result = std::__invoke(__binary_op, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2)); - return {std::move(__first1), std::move(__first2), std::move(__result)}; - } - - template - requires indirectly_writable<_Out, - indirect_result_t<_Fp&, - projected, _Proj1>, - projected, _Proj2>>> - constexpr binary_transform_result, - borrowed_iterator_t<_Range2>, _Out> - operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, _Fp __binary_op, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__binary_op), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __transform_fn transform{}; - - struct __replace_fn - { - template _Sent, - typename _Tp1, typename _Tp2, typename _Proj = identity> - requires indirectly_writable<_Iter, const _Tp2&> - && indirect_binary_predicate, - const _Tp1*> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - const _Tp1& __old_value, const _Tp2& __new_value, - _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (std::__invoke(__proj, *__first) == __old_value) - *__first = __new_value; - return __first; - } - - template - requires indirectly_writable, const _Tp2&> - && indirect_binary_predicate, _Proj>, - const _Tp1*> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, - const _Tp1& __old_value, const _Tp2& __new_value, - _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - __old_value, __new_value, std::move(__proj)); - } - }; - - inline constexpr __replace_fn replace{}; - - struct __replace_if_fn - { - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_writable<_Iter, const _Tp&> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - *__first = __new_value; - return std::move(__first); - } - - template, _Proj>> - _Pred> - requires indirectly_writable, const _Tp&> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, - _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), __new_value, std::move(__proj)); - } - }; - - inline constexpr __replace_if_fn replace_if{}; - - template - using replace_copy_result = in_out_result<_Iter, _Out>; - - struct __replace_copy_fn - { - template _Sent, - typename _Tp1, typename _Tp2, output_iterator _Out, - typename _Proj = identity> - requires indirectly_copyable<_Iter, _Out> - && indirect_binary_predicate, const _Tp1*> - constexpr replace_copy_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result, - const _Tp1& __old_value, const _Tp2& __new_value, - _Proj __proj = {}) const - { - for (; __first != __last; ++__first, (void)++__result) - if (std::__invoke(__proj, *__first) == __old_value) - *__result = __new_value; - else - *__result = *__first; - return {std::move(__first), std::move(__result)}; - } - - template _Out, typename _Proj = identity> - requires indirectly_copyable, _Out> - && indirect_binary_predicate, _Proj>, - const _Tp1*> - constexpr replace_copy_result, _Out> - operator()(_Range&& __r, _Out __result, - const _Tp1& __old_value, const _Tp2& __new_value, - _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result), __old_value, - __new_value, std::move(__proj)); - } - }; - - inline constexpr __replace_copy_fn replace_copy{}; - - template - using replace_copy_if_result = in_out_result<_Iter, _Out>; - - struct __replace_copy_if_fn - { - template _Sent, - typename _Tp, output_iterator _Out, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_Iter, _Out> - constexpr replace_copy_if_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result, - _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const - { - for (; __first != __last; ++__first, (void)++__result) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - *__result = __new_value; - else - *__result = *__first; - return {std::move(__first), std::move(__result)}; - } - - template _Out, - typename _Proj = identity, - indirect_unary_predicate, _Proj>> - _Pred> - requires indirectly_copyable, _Out> - constexpr replace_copy_if_result, _Out> - operator()(_Range&& __r, _Out __result, - _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result), std::move(__pred), - __new_value, std::move(__proj)); - } - }; - - inline constexpr __replace_copy_if_fn replace_copy_if{}; - - struct __generate_n_fn - { - template - requires invocable<_Fp&> - && indirectly_writable<_Out, invoke_result_t<_Fp&>> - constexpr _Out - operator()(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) const - { - for (; __n > 0; --__n, (void)++__first) - *__first = std::__invoke(__gen); - return __first; - } - }; - - inline constexpr __generate_n_fn generate_n{}; - - struct __generate_fn - { - template _Sent, - copy_constructible _Fp> - requires invocable<_Fp&> - && indirectly_writable<_Out, invoke_result_t<_Fp&>> - constexpr _Out - operator()(_Out __first, _Sent __last, _Fp __gen) const - { - for (; __first != __last; ++__first) - *__first = std::__invoke(__gen); - return __first; - } - - template - requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Fp __gen) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__gen)); - } - }; - - inline constexpr __generate_fn generate{}; - - struct __remove_if_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr subrange<_Iter> - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - __first = ranges::find_if(__first, __last, __pred, __proj); - if (__first == __last) - return {__first, __first}; - - auto __result = __first; - ++__first; - for (; __first != __last; ++__first) - if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) - { - *__result = std::move(*__first); - ++__result; - } - - return {__result, __first}; - } - - template, _Proj>> - _Pred> - requires permutable> - constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __remove_if_fn remove_if{}; - - struct __remove_fn - { - template _Sent, - typename _Tp, typename _Proj = identity> - requires indirect_binary_predicate, - const _Tp*> - constexpr subrange<_Iter> - operator()(_Iter __first, _Sent __last, - const _Tp& __value, _Proj __proj = {}) const - { - auto __pred = [&] (auto&& __arg) { - return std::forward(__arg) == __value; - }; - return ranges::remove_if(__first, __last, - std::move(__pred), std::move(__proj)); - } - - template - requires permutable> - && indirect_binary_predicate, _Proj>, - const _Tp*> - constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - __value, std::move(__proj)); - } - }; - - inline constexpr __remove_fn remove{}; - - template - using remove_copy_if_result = in_out_result<_Iter, _Out>; - - struct __remove_copy_if_fn - { - template _Sent, - weakly_incrementable _Out, typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_Iter, _Out> - constexpr remove_copy_if_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result, - _Pred __pred, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) - { - *__result = *__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - - template, _Proj>> - _Pred> - requires indirectly_copyable, _Out> - constexpr remove_copy_if_result, _Out> - operator()(_Range&& __r, _Out __result, - _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __remove_copy_if_fn remove_copy_if{}; - - template - using remove_copy_result = in_out_result<_Iter, _Out>; - - struct __remove_copy_fn - { - template _Sent, - weakly_incrementable _Out, typename _Tp, typename _Proj = identity> - requires indirectly_copyable<_Iter, _Out> - && indirect_binary_predicate, - const _Tp*> - constexpr remove_copy_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result, - const _Tp& __value, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (!(std::__invoke(__proj, *__first) == __value)) - { - *__result = *__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - - template - requires indirectly_copyable, _Out> - && indirect_binary_predicate, _Proj>, - const _Tp*> - constexpr remove_copy_result, _Out> - operator()(_Range&& __r, _Out __result, - const _Tp& __value, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result), __value, std::move(__proj)); - } - }; - - inline constexpr __remove_copy_fn remove_copy{}; - - struct __unique_fn - { - template _Sent, - typename _Proj = identity, - indirect_equivalence_relation< - projected<_Iter, _Proj>> _Comp = ranges::equal_to> - constexpr subrange<_Iter> - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - __first = ranges::adjacent_find(__first, __last, __comp, __proj); - if (__first == __last) - return {__first, __first}; - - auto __dest = __first; - ++__first; - while (++__first != __last) - if (!std::__invoke(__comp, - std::__invoke(__proj, *__dest), - std::__invoke(__proj, *__first))) - *++__dest = std::move(*__first); - return {++__dest, __first}; - } - - template, _Proj>> _Comp = ranges::equal_to> - requires permutable> - constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __unique_fn unique{}; - - template - using unique_copy_result = in_out_result<_Iter, _Out>; - - struct __unique_copy_fn - { - template _Sent, - weakly_incrementable _Out, typename _Proj = identity, - indirect_equivalence_relation< - projected<_Iter, _Proj>> _Comp = ranges::equal_to> - requires indirectly_copyable<_Iter, _Out> - && (forward_iterator<_Iter> - || (input_iterator<_Out> - && same_as, iter_value_t<_Out>>) - || indirectly_copyable_storable<_Iter, _Out>) - constexpr unique_copy_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __last) - return {std::move(__first), std::move(__result)}; - - // TODO: perform a closer comparison with reference implementations - if constexpr (forward_iterator<_Iter>) - { - auto __next = __first; - *__result = *__next; - while (++__next != __last) - if (!std::__invoke(__comp, - std::__invoke(__proj, *__first), - std::__invoke(__proj, *__next))) - { - __first = __next; - *++__result = *__first; - } - return {__next, std::move(++__result)}; - } - else if constexpr (input_iterator<_Out> - && same_as, iter_value_t<_Out>>) - { - *__result = *__first; - while (++__first != __last) - if (!std::__invoke(__comp, - std::__invoke(__proj, *__result), - std::__invoke(__proj, *__first))) - *++__result = *__first; - return {std::move(__first), std::move(++__result)}; - } - else // indirectly_copyable_storable<_Iter, _Out> - { - auto __value = *__first; - *__result = __value; - while (++__first != __last) - { - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__first), - std::__invoke(__proj, __value))) - { - __value = *__first; - *++__result = __value; - } - } - return {std::move(__first), std::move(++__result)}; - } - } - - template, _Proj>> _Comp = ranges::equal_to> - requires indirectly_copyable, _Out> - && (forward_iterator> - || (input_iterator<_Out> - && same_as, iter_value_t<_Out>>) - || indirectly_copyable_storable, _Out>) - constexpr unique_copy_result, _Out> - operator()(_Range&& __r, _Out __result, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __unique_copy_fn unique_copy{}; - - struct __reverse_fn - { - template _Sent> - requires permutable<_Iter> - constexpr _Iter - operator()(_Iter __first, _Sent __last) const - { - auto __i = ranges::next(__first, __last); - auto __tail = __i; - - if constexpr (random_access_iterator<_Iter>) - { - if (__first != __last) - { - --__tail; - while (__first < __tail) - { - ranges::iter_swap(__first, __tail); - ++__first; - --__tail; - } - } - return __i; - } - else - { - for (;;) - if (__first == __tail || __first == --__tail) - break; - else - { - ranges::iter_swap(__first, __tail); - ++__first; - } - return __i; - } - } - - template - requires permutable> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r) const - { - return (*this)(ranges::begin(__r), ranges::end(__r)); - } - }; - - inline constexpr __reverse_fn reverse{}; - - template - using reverse_copy_result = in_out_result<_Iter, _Out>; - - struct __reverse_copy_fn - { - template _Sent, - weakly_incrementable _Out> - requires indirectly_copyable<_Iter, _Out> - constexpr reverse_copy_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result) const - { - auto __i = ranges::next(__first, __last); - auto __tail = __i; - while (__first != __tail) - { - --__tail; - *__result = *__tail; - ++__result; - } - return {__i, __result}; - } - - template - requires indirectly_copyable, _Out> - constexpr reverse_copy_result, _Out> - operator()(_Range&& __r, _Out __result) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } - }; - - inline constexpr __reverse_copy_fn reverse_copy{}; - - struct __rotate_fn - { - template _Sent> - constexpr subrange<_Iter> - operator()(_Iter __first, _Iter __middle, _Sent __last) const - { - auto __lasti = ranges::next(__first, __last); - if (__first == __middle) - return {__lasti, __lasti}; - if (__last == __middle) - return {std::move(__first), std::move(__lasti)}; - - if constexpr (random_access_iterator<_Iter>) - { - auto __n = __lasti - __first; - auto __k = __middle - __first; - - if (__k == __n - __k) - { - ranges::swap_ranges(__first, __middle, __middle, __middle + __k); - return {std::move(__middle), std::move(__lasti)}; - } - - auto __p = __first; - auto __ret = __first + (__lasti - __middle); - - for (;;) - { - if (__k < __n - __k) - { - // TODO: is_pod is deprecated, but this condition is - // consistent with the STL implementation. - if constexpr (__is_pod(iter_value_t<_Iter>)) - if (__k == 1) - { - auto __t = std::move(*__p); - ranges::move(__p + 1, __p + __n, __p); - *(__p + __n - 1) = std::move(__t); - return {std::move(__ret), std::move(__lasti)}; - } - auto __q = __p + __k; - for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) - { - ranges::iter_swap(__p, __q); - ++__p; - ++__q; - } - __n %= __k; - if (__n == 0) - return {std::move(__ret), std::move(__lasti)}; - ranges::swap(__n, __k); - __k = __n - __k; - } - else - { - __k = __n - __k; - // TODO: is_pod is deprecated, but this condition is - // consistent with the STL implementation. - if constexpr (__is_pod(iter_value_t<_Iter>)) - if (__k == 1) - { - auto __t = std::move(*(__p + __n - 1)); - ranges::move_backward(__p, __p + __n - 1, __p + __n); - *__p = std::move(__t); - return {std::move(__ret), std::move(__lasti)}; - } - auto __q = __p + __n; - __p = __q - __k; - for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) - { - --__p; - --__q; - ranges::iter_swap(__p, __q); - } - __n %= __k; - if (__n == 0) - return {std::move(__ret), std::move(__lasti)}; - std::swap(__n, __k); - } - } - } - else if constexpr (bidirectional_iterator<_Iter>) - { - auto __tail = __lasti; - - ranges::reverse(__first, __middle); - ranges::reverse(__middle, __tail); - - while (__first != __middle && __middle != __tail) - { - ranges::iter_swap(__first, --__tail); - ++__first; - } - - if (__first == __middle) - { - ranges::reverse(__middle, __tail); - return {std::move(__tail), std::move(__lasti)}; - } - else - { - ranges::reverse(__first, __middle); - return {std::move(__first), std::move(__lasti)}; - } - } - else - { - auto __first2 = __middle; - do - { - ranges::iter_swap(__first, __first2); - ++__first; - ++__first2; - if (__first == __middle) - __middle = __first2; - } while (__first2 != __last); - - auto __ret = __first; - - __first2 = __middle; - - while (__first2 != __last) - { - ranges::iter_swap(__first, __first2); - ++__first; - ++__first2; - if (__first == __middle) - __middle = __first2; - else if (__first2 == __last) - __first2 = __middle; - } - return {std::move(__ret), std::move(__lasti)}; - } - } - - template - requires permutable> - constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __r, iterator_t<_Range> __middle) const - { - return (*this)(ranges::begin(__r), std::move(__middle), - ranges::end(__r)); - } - }; - - inline constexpr __rotate_fn rotate{}; - - template - using rotate_copy_result = in_out_result<_Iter, _Out>; - - struct __rotate_copy_fn - { - template _Sent, - weakly_incrementable _Out> - requires indirectly_copyable<_Iter, _Out> - constexpr rotate_copy_result<_Iter, _Out> - operator()(_Iter __first, _Iter __middle, _Sent __last, - _Out __result) const - { - auto __copy1 = ranges::copy(__middle, - std::move(__last), - std::move(__result)); - auto __copy2 = ranges::copy(std::move(__first), - std::move(__middle), - std::move(__copy1.out)); - return { std::move(__copy1.in), std::move(__copy2.out) }; - } - - template - requires indirectly_copyable, _Out> - constexpr rotate_copy_result, _Out> - operator()(_Range&& __r, iterator_t<_Range> __middle, _Out __result) const - { - return (*this)(ranges::begin(__r), std::move(__middle), - ranges::end(__r), std::move(__result)); - } - }; - - inline constexpr __rotate_copy_fn rotate_copy{}; - - struct __sample_fn - { - template _Sent, - weakly_incrementable _Out, typename _Gen> - requires (forward_iterator<_Iter> || random_access_iterator<_Out>) - && indirectly_copyable<_Iter, _Out> - && uniform_random_bit_generator> - _Out - operator()(_Iter __first, _Sent __last, _Out __out, - iter_difference_t<_Iter> __n, _Gen&& __g) const - { - if constexpr (forward_iterator<_Iter>) - { - // FIXME: Forwarding to std::sample here requires computing __lasti - // which may take linear time. - auto __lasti = ranges::next(__first, __last); - return std::sample(std::move(__first), std::move(__lasti), - std::move(__out), __n, std::forward<_Gen>(__g)); - } - else - { - using __distrib_type - = uniform_int_distribution>; - using __param_type = typename __distrib_type::param_type; - __distrib_type __d{}; - iter_difference_t<_Iter> __sample_sz = 0; - while (__first != __last && __sample_sz != __n) - { - __out[__sample_sz++] = *__first; - ++__first; - } - for (auto __pop_sz = __sample_sz; __first != __last; - ++__first, (void) ++__pop_sz) - { - const auto __k = __d(__g, __param_type{0, __pop_sz}); - if (__k < __n) - __out[__k] = *__first; - } - return __out + __sample_sz; - } - } - - template - requires (forward_range<_Range> || random_access_iterator<_Out>) - && indirectly_copyable, _Out> - && uniform_random_bit_generator> - _Out - operator()(_Range&& __r, _Out __out, - range_difference_t<_Range> __n, _Gen&& __g) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__out), __n, - std::forward<_Gen>(__g)); - } - }; - - inline constexpr __sample_fn sample{}; - -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - struct __shuffle_fn - { - template _Sent, - typename _Gen> - requires permutable<_Iter> - && uniform_random_bit_generator> - _Iter - operator()(_Iter __first, _Sent __last, _Gen&& __g) const - { - auto __lasti = ranges::next(__first, __last); - std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g)); - return __lasti; - } - - template - requires permutable> - && uniform_random_bit_generator> - borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Gen&& __g) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::forward<_Gen>(__g)); - } - }; - - inline constexpr __shuffle_fn shuffle{}; -#endif - - struct __push_heap_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - std::push_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __push_heap_fn push_heap{}; - - struct __pop_heap_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - std::pop_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __pop_heap_fn pop_heap{}; - - struct __make_heap_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - std::make_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __make_heap_fn make_heap{}; - - struct __sort_heap_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - std::sort_heap(__first, __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __sort_heap_fn sort_heap{}; - - struct __is_heap_until_fn - { - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - iter_difference_t<_Iter> __n = ranges::distance(__first, __last); - iter_difference_t<_Iter> __parent = 0, __child = 1; - for (; __child < __n; ++__child) - if (std::__invoke(__comp, - std::__invoke(__proj, *(__first + __parent)), - std::__invoke(__proj, *(__first + __child)))) - return __first + __child; - else if ((__child & 1) == 0) - ++__parent; - - return __first + __n; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __is_heap_until_fn is_heap_until{}; - - struct __is_heap_fn - { - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr bool - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (__last - == ranges::is_heap_until(__first, __last, - std::move(__comp), - std::move(__proj))); - } - - template, _Proj>> - _Comp = ranges::less> - constexpr bool - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __is_heap_fn is_heap{}; - - struct __sort_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - std::sort(std::move(__first), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __sort_fn sort{}; - - struct __stable_sort_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - std::stable_sort(std::move(__first), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __stable_sort_fn stable_sort{}; - - struct __partial_sort_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - operator()(_Iter __first, _Iter __middle, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __middle) - return ranges::next(__first, __last); - - ranges::make_heap(__first, __middle, __comp, __proj); - auto __i = __middle; - for (; __i != __last; ++__i) - if (std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__first))) - { - ranges::pop_heap(__first, __middle, __comp, __proj); - ranges::iter_swap(__middle-1, __i); - ranges::push_heap(__first, __middle, __comp, __proj); - } - ranges::sort_heap(__first, __middle, __comp, __proj); - - return __i; - } - - template - requires sortable, _Comp, _Proj> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, iterator_t<_Range> __middle, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), std::move(__middle), - ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __partial_sort_fn partial_sort{}; - - template - using partial_sort_copy_result = in_out_result<_Iter, _Out>; - - struct __partial_sort_copy_fn - { - template _Sent1, - random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_copyable<_Iter1, _Iter2> - && sortable<_Iter2, _Comp, _Proj2> - && indirect_strict_weak_order<_Comp, - projected<_Iter1, _Proj1>, - projected<_Iter2, _Proj2>> - constexpr partial_sort_copy_result<_Iter1, _Iter2> - operator()(_Iter1 __first, _Sent1 __last, - _Iter2 __result_first, _Sent2 __result_last, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - if (__result_first == __result_last) - { - // TODO: Eliminating the variable __lasti triggers an ICE. - auto __lasti = ranges::next(std::move(__first), - std::move(__last)); - return {std::move(__lasti), std::move(__result_first)}; - } - - auto __result_real_last = __result_first; - while (__first != __last && __result_real_last != __result_last) - { - *__result_real_last = *__first; - ++__result_real_last; - ++__first; - } - - ranges::make_heap(__result_first, __result_real_last, __comp, __proj2); - for (; __first != __last; ++__first) - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first), - std::__invoke(__proj2, *__result_first))) - { - ranges::pop_heap(__result_first, __result_real_last, - __comp, __proj2); - *(__result_real_last-1) = *__first; - ranges::push_heap(__result_first, __result_real_last, - __comp, __proj2); - } - ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2); - - return {std::move(__first), std::move(__result_real_last)}; - } - - template - requires indirectly_copyable, iterator_t<_Range2>> - && sortable, _Comp, _Proj2> - && indirect_strict_weak_order<_Comp, - projected, _Proj1>, - projected, _Proj2>> - constexpr partial_sort_copy_result, - borrowed_iterator_t<_Range2>> - operator()(_Range1&& __r, _Range2&& __out, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - ranges::begin(__out), ranges::end(__out), - std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __partial_sort_copy_fn partial_sort_copy{}; - - struct __is_sorted_until_fn - { - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __last) - return __first; - - auto __next = __first; - for (++__next; __next != __last; __first = __next, (void)++__next) - if (std::__invoke(__comp, - std::__invoke(__proj, *__next), - std::__invoke(__proj, *__first))) - return __next; - return __next; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __is_sorted_until_fn is_sorted_until{}; - - struct __is_sorted_fn - { - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr bool - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __last) - return true; - - auto __next = __first; - for (++__next; __next != __last; __first = __next, (void)++__next) - if (std::__invoke(__comp, - std::__invoke(__proj, *__next), - std::__invoke(__proj, *__first))) - return false; - return true; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr bool - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __is_sorted_fn is_sorted{}; - - struct __nth_element_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr _Iter - operator()(_Iter __first, _Iter __nth, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - std::nth_element(std::move(__first), std::move(__nth), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, iterator_t<_Range> __nth, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), std::move(__nth), - ranges::end(__r), std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __nth_element_fn nth_element{}; - - struct __lower_bound_fn - { - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const - { - auto __len = ranges::distance(__first, __last); - - while (__len > 0) - { - auto __half = __len / 2; - auto __middle = __first; - ranges::advance(__middle, __half); - if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value)) - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - else - __len = __half; - } - return __first; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - __value, std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __lower_bound_fn lower_bound{}; - - struct __upper_bound_fn - { - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const - { - auto __len = ranges::distance(__first, __last); - - while (__len > 0) - { - auto __half = __len / 2; - auto __middle = __first; - ranges::advance(__middle, __half); - if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle))) - __len = __half; - else - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - } - return __first; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - __value, std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __upper_bound_fn upper_bound{}; - - struct __equal_range_fn - { - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr subrange<_Iter> - operator()(_Iter __first, _Sent __last, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const - { - auto __len = ranges::distance(__first, __last); - - while (__len > 0) - { - auto __half = __len / 2; - auto __middle = __first; - ranges::advance(__middle, __half); - if (std::__invoke(__comp, - std::__invoke(__proj, *__middle), - __value)) - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - else if (std::__invoke(__comp, - __value, - std::__invoke(__proj, *__middle))) - __len = __half; - else - { - auto __left - = ranges::lower_bound(__first, __middle, - __value, __comp, __proj); - ranges::advance(__first, __len); - auto __right - = ranges::upper_bound(++__middle, __first, - __value, __comp, __proj); - return {__left, __right}; - } - } - return {__first, __first}; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __r, const _Tp& __value, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - __value, std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __equal_range_fn equal_range{}; - - struct __binary_search_fn - { - template _Sent, - typename _Tp, typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr bool - operator()(_Iter __first, _Sent __last, - const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const - { - auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj); - if (__i == __last) - return false; - return !(bool)std::__invoke(__comp, __value, - std::__invoke(__proj, *__i)); - } - - template, _Proj>> - _Comp = ranges::less> - constexpr bool - operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, - _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - __value, std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __binary_search_fn binary_search{}; - - struct __is_partitioned_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr bool - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - __first = ranges::find_if_not(std::move(__first), __last, - __pred, __proj); - if (__first == __last) - return true; - ++__first; - return ranges::none_of(std::move(__first), std::move(__last), - std::move(__pred), std::move(__proj)); - } - - template, _Proj>> - _Pred> - constexpr bool - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __is_partitioned_fn is_partitioned{}; - - struct __partition_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr subrange<_Iter> - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - if constexpr (bidirectional_iterator<_Iter>) - { - auto __lasti = ranges::next(__first, __last); - auto __tail = __lasti; - for (;;) - { - for (;;) - if (__first == __tail) - return {std::move(__first), std::move(__lasti)}; - else if (std::__invoke(__pred, - std::__invoke(__proj, *__first))) - ++__first; - else - break; - --__tail; - for (;;) - if (__first == __tail) - return {std::move(__first), std::move(__lasti)}; - else if (!(bool)std::__invoke(__pred, - std::__invoke(__proj, *__tail))) - --__tail; - else - break; - ranges::iter_swap(__first, __tail); - ++__first; - } - } - else - { - if (__first == __last) - return {std::move(__first), std::move(__first)}; - - while (std::__invoke(__pred, std::__invoke(__proj, *__first))) - if (++__first == __last) - return {std::move(__first), std::move(__first)}; - - auto __next = __first; - while (++__next != __last) - if (std::__invoke(__pred, std::__invoke(__proj, *__next))) - { - ranges::iter_swap(__first, __next); - ++__first; - } - - return {std::move(__first), std::move(__next)}; - } - } - - template, _Proj>> - _Pred> - requires permutable> - constexpr borrowed_subrange_t<_Range> - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __partition_fn partition{}; - - struct __stable_partition_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires permutable<_Iter> - subrange<_Iter> - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - auto __middle - = std::stable_partition(std::move(__first), __lasti, - __detail::__make_pred_proj(__pred, __proj)); - return {std::move(__middle), std::move(__lasti)}; - } - - template, _Proj>> - _Pred> - requires permutable> - borrowed_subrange_t<_Range> - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __stable_partition_fn stable_partition{}; - - template - struct in_out_out_result - { - [[no_unique_address]] _Iter in; - [[no_unique_address]] _Out1 out1; - [[no_unique_address]] _Out2 out2; - - template - requires convertible_to - && convertible_to - && convertible_to - constexpr - operator in_out_out_result<_IIter, _OOut1, _OOut2>() const & - { return {in, out1, out2}; } - - template - requires convertible_to<_Iter, _IIter> - && convertible_to<_Out1, _OOut1> - && convertible_to<_Out2, _OOut2> - constexpr - operator in_out_out_result<_IIter, _OOut1, _OOut2>() && - { return {std::move(in), std::move(out1), std::move(out2)}; } - }; - - template - using partition_copy_result = in_out_out_result<_Iter, _Out1, _Out2>; - - struct __partition_copy_fn - { - template _Sent, - weakly_incrementable _Out1, weakly_incrementable _O2, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - requires indirectly_copyable<_Iter, _Out1> - && indirectly_copyable<_Iter, _O2> - constexpr partition_copy_result<_Iter, _Out1, _O2> - operator()(_Iter __first, _Sent __last, - _Out1 __out_true, _O2 __out_false, - _Pred __pred, _Proj __proj = {}) const - { - for (; __first != __last; ++__first) - if (std::__invoke(__pred, std::__invoke(__proj, *__first))) - { - *__out_true = *__first; - ++__out_true; - } - else - { - *__out_false = *__first; - ++__out_false; - } - - return {std::move(__first), - std::move(__out_true), std::move(__out_false)}; - } - - template, _Proj>> - _Pred> - requires indirectly_copyable, _Out1> - && indirectly_copyable, _O2> - constexpr partition_copy_result, _Out1, _O2> - operator()(_Range&& __r, _Out1 out_true, _O2 out_false, - _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(out_true), std::move(out_false), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __partition_copy_fn partition_copy{}; - - struct __partition_point_fn - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Pred __pred, _Proj __proj = {}) const - { - auto __len = ranges::distance(__first, __last); - - while (__len > 0) - { - auto __half = __len / 2; - auto __middle = __first; - ranges::advance(__middle, __half); - if (std::__invoke(__pred, std::__invoke(__proj, *__middle))) - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - else - __len = __half; - } - return __first; - } - - template, _Proj>> - _Pred> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__pred), std::move(__proj)); - } - }; - - inline constexpr __partition_point_fn partition_point{}; - - template - using merge_result = in_in_out_result<_Iter1, _Iter2, _Out>; - - struct __merge_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr merge_result<_Iter1, _Iter2, _Out> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - while (__first1 != __last1 && __first2 != __last2) - { - if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - { - *__result = *__first2; - ++__first2; - } - else - { - *__result = *__first1; - ++__first1; - } - ++__result; - } - auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), - std::move(__result)); - auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), - std::move(__copy1.out)); - return { std::move(__copy1.in), std::move(__copy2.in), - std::move(__copy2.out) }; - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr merge_result, - borrowed_iterator_t<_Range2>, - _Out> - operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __merge_fn merge{}; - - struct __inplace_merge_fn - { - template _Sent, - typename _Comp = ranges::less, - typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - _Iter - operator()(_Iter __first, _Iter __middle, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - auto __lasti = ranges::next(__first, __last); - std::inplace_merge(std::move(__first), std::move(__middle), __lasti, - __detail::__make_comp_proj(__comp, __proj)); - return __lasti; - } - - template - requires sortable, _Comp, _Proj> - borrowed_iterator_t<_Range> - operator()(_Range&& __r, iterator_t<_Range> __middle, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), std::move(__middle), - ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __inplace_merge_fn inplace_merge{}; - - struct __includes_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Proj1 = identity, typename _Proj2 = identity, - indirect_strict_weak_order, - projected<_Iter2, _Proj2>> - _Comp = ranges::less> - constexpr bool - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - while (__first1 != __last1 && __first2 != __last2) - if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - return false; - else if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - ++__first1; - else - { - ++__first1; - ++__first2; - } - - return __first2 == __last2; - } - - template, _Proj1>, - projected, _Proj2>> - _Comp = ranges::less> - constexpr bool - operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __includes_fn includes{}; - - template - using set_union_result = in_in_out_result<_Iter1, _Iter2, _Out>; - - struct __set_union_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr set_union_result<_Iter1, _Iter2, _Out> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Out __result, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - while (__first1 != __last1 && __first2 != __last2) - { - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - { - *__result = *__first1; - ++__first1; - } - else if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - { - *__result = *__first2; - ++__first2; - } - else - { - *__result = *__first1; - ++__first1; - ++__first2; - } - ++__result; - } - auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), - std::move(__result)); - auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), - std::move(__copy1.out)); - return {std::move(__copy1.in), std::move(__copy2.in), - std::move(__copy2.out)}; - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr set_union_result, - borrowed_iterator_t<_Range2>, _Out> - operator()(_Range1&& __r1, _Range2&& __r2, - _Out __result, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __set_union_fn set_union{}; - - template - using set_intersection_result = in_in_out_result<_Iter1, _Iter2, _Out>; - - struct __set_intersection_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr set_intersection_result<_Iter1, _Iter2, _Out> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - while (__first1 != __last1 && __first2 != __last2) - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - ++__first1; - else if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - ++__first2; - else - { - *__result = *__first1; - ++__first1; - ++__first2; - ++__result; - } - // TODO: Eliminating these variables triggers an ICE. - auto __last1i = ranges::next(std::move(__first1), std::move(__last1)); - auto __last2i = ranges::next(std::move(__first2), std::move(__last2)); - return {std::move(__last1i), std::move(__last2i), std::move(__result)}; - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr set_intersection_result, - borrowed_iterator_t<_Range2>, _Out> - operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __set_intersection_fn set_intersection{}; - - template - using set_difference_result = in_out_result<_Iter, _Out>; - - struct __set_difference_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr set_difference_result<_Iter1, _Out> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - while (__first1 != __last1 && __first2 != __last2) - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - { - *__result = *__first1; - ++__first1; - ++__result; - } - else if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - ++__first2; - else - { - ++__first1; - ++__first2; - } - return ranges::copy(std::move(__first1), std::move(__last1), - std::move(__result)); - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr set_difference_result, _Out> - operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __set_difference_fn set_difference{}; - - template - using set_symmetric_difference_result - = in_in_out_result<_Iter1, _Iter2, _Out>; - - struct __set_symmetric_difference_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - weakly_incrementable _Out, typename _Comp = ranges::less, - typename _Proj1 = identity, typename _Proj2 = identity> - requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> - constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out> - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Out __result, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - while (__first1 != __last1 && __first2 != __last2) - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - { - *__result = *__first1; - ++__first1; - ++__result; - } - else if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - { - *__result = *__first2; - ++__first2; - ++__result; - } - else - { - ++__first1; - ++__first2; - } - auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), - std::move(__result)); - auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), - std::move(__copy1.out)); - return {std::move(__copy1.in), std::move(__copy2.in), - std::move(__copy2.out)}; - } - - template - requires mergeable, iterator_t<_Range2>, _Out, - _Comp, _Proj1, _Proj2> - constexpr set_symmetric_difference_result, - borrowed_iterator_t<_Range2>, - _Out> - operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__result), std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __set_symmetric_difference_fn set_symmetric_difference{}; - - struct __min_fn - { - template> - _Comp = ranges::less> - constexpr const _Tp& - operator()(const _Tp& __a, const _Tp& __b, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (std::__invoke(std::move(__comp), - std::__invoke(__proj, __b), - std::__invoke(__proj, __a))) - return __b; - else - return __a; - } - - template, _Proj>> - _Comp = ranges::less> - requires indirectly_copyable_storable, - range_value_t<_Range>*> - constexpr range_value_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - __glibcxx_assert(__first != __last); - auto __result = *__first; - while (++__first != __last) - { - auto __tmp = *__first; - if (std::__invoke(__comp, - std::__invoke(__proj, __tmp), - std::__invoke(__proj, __result))) - __result = std::move(__tmp); - } - return __result; - } - - template> - _Comp = ranges::less> - constexpr _Tp - operator()(initializer_list<_Tp> __r, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::subrange(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __min_fn min{}; - - struct __max_fn - { - template> - _Comp = ranges::less> - constexpr const _Tp& - operator()(const _Tp& __a, const _Tp& __b, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (std::__invoke(std::move(__comp), - std::__invoke(__proj, __a), - std::__invoke(__proj, __b))) - return __b; - else - return __a; - } - - template, _Proj>> - _Comp = ranges::less> - requires indirectly_copyable_storable, - range_value_t<_Range>*> - constexpr range_value_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - __glibcxx_assert(__first != __last); - auto __result = *__first; - while (++__first != __last) - { - auto __tmp = *__first; - if (std::__invoke(__comp, - std::__invoke(__proj, __result), - std::__invoke(__proj, __tmp))) - __result = std::move(__tmp); - } - return __result; - } - - template> - _Comp = ranges::less> - constexpr _Tp - operator()(initializer_list<_Tp> __r, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::subrange(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __max_fn max{}; - - struct __clamp_fn - { - template> _Comp - = ranges::less> - constexpr const _Tp& - operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, - _Comp __comp = {}, _Proj __proj = {}) const - { - __glibcxx_assert(!(std::__invoke(__comp, - std::__invoke(__proj, __hi), - std::__invoke(__proj, __lo)))); - auto&& __proj_val = std::__invoke(__proj, __val); - if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo))) - return __lo; - else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val)) - return __hi; - else - return __val; - } - }; - - inline constexpr __clamp_fn clamp{}; - - template - struct min_max_result - { - [[no_unique_address]] _Tp min; - [[no_unique_address]] _Tp max; - - template - requires convertible_to - constexpr - operator min_max_result<_Tp2>() const & - { return {min, max}; } - - template - requires convertible_to<_Tp, _Tp2> - constexpr - operator min_max_result<_Tp2>() && - { return {std::move(min), std::move(max)}; } - }; - - template - using minmax_result = min_max_result<_Tp>; - - struct __minmax_fn - { - template> - _Comp = ranges::less> - constexpr minmax_result - operator()(const _Tp& __a, const _Tp& __b, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (std::__invoke(std::move(__comp), - std::__invoke(__proj, __b), - std::__invoke(__proj, __a))) - return {__b, __a}; - else - return {__a, __b}; - } - - template, _Proj>> - _Comp = ranges::less> - requires indirectly_copyable_storable, - range_value_t<_Range>*> - constexpr minmax_result> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - auto __first = ranges::begin(__r); - auto __last = ranges::end(__r); - __glibcxx_assert(__first != __last); - minmax_result> __result = {*__first, *__first}; - while (++__first != __last) - { - auto __tmp = *__first; - if (std::__invoke(__comp, - std::__invoke(__proj, __tmp), - std::__invoke(__proj, __result.min))) - __result.min = std::move(__tmp); - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, __tmp), - std::__invoke(__proj, __result.max))) - __result.max = std::move(__tmp); - } - return __result; - } - - template> - _Comp = ranges::less> - constexpr minmax_result<_Tp> - operator()(initializer_list<_Tp> __r, - _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::subrange(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __minmax_fn minmax{}; - - struct __min_element_fn - { - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __last) - return __first; - - auto __i = __first; - while (++__i != __last) - { - if (std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__first))) - __first = __i; - } - return __first; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __min_element_fn min_element{}; - - struct __max_element_fn - { - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr _Iter - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __last) - return __first; - - auto __i = __first; - while (++__i != __last) - { - if (std::__invoke(__comp, - std::__invoke(__proj, *__first), - std::__invoke(__proj, *__i))) - __first = __i; - } - return __first; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __max_element_fn max_element{}; - - template - using minmax_element_result = min_max_result<_Iter>; - - struct __minmax_element_fn - { - template _Sent, - typename _Proj = identity, - indirect_strict_weak_order> - _Comp = ranges::less> - constexpr minmax_element_result<_Iter> - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __last) - return {__first, __first}; - - minmax_element_result<_Iter> __result = {__first, __first}; - auto __i = __first; - while (++__i != __last) - { - if (std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__result.min))) - __result.min = __i; - if (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__result.max))) - __result.max = __i; - } - return __result; - } - - template, _Proj>> - _Comp = ranges::less> - constexpr minmax_element_result> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __minmax_element_fn minmax_element{}; - - struct __lexicographical_compare_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Proj1 = identity, typename _Proj2 = identity, - indirect_strict_weak_order, - projected<_Iter2, _Proj2>> - _Comp = ranges::less> - constexpr bool - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, - _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - if constexpr (__detail::__is_normal_iterator<_Iter1> - && same_as<_Iter1, _Sent1>) - return (*this)(__first1.base(), __last1.base(), - std::move(__first2), std::move(__last2), - std::move(__comp), - std::move(__proj1), std::move(__proj2)); - else if constexpr (__detail::__is_normal_iterator<_Iter2> - && same_as<_Iter2, _Sent2>) - return (*this)(std::move(__first1), std::move(__last1), - __first2.base(), __last2.base(), - std::move(__comp), - std::move(__proj1), std::move(__proj2)); - else - { - constexpr bool __sized_iters - = (sized_sentinel_for<_Sent1, _Iter1> - && sized_sentinel_for<_Sent2, _Iter2>); - if constexpr (__sized_iters) - { - using _ValueType1 = iter_value_t<_Iter1>; - using _ValueType2 = iter_value_t<_Iter2>; - // This condition is consistent with the one in - // __lexicographical_compare_aux in . - constexpr bool __use_memcmp - = (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value - && __ptr_to_nonvolatile<_Iter1> - && __ptr_to_nonvolatile<_Iter2> - && (is_same_v<_Comp, ranges::less> - || is_same_v<_Comp, ranges::greater>) - && is_same_v<_Proj1, identity> - && is_same_v<_Proj2, identity>); - if constexpr (__use_memcmp) - { - const auto __d1 = __last1 - __first1; - const auto __d2 = __last2 - __first2; - - if (const auto __len = std::min(__d1, __d2)) - { - const auto __c - = std::__memcmp(__first1, __first2, __len); - if constexpr (is_same_v<_Comp, ranges::less>) - { - if (__c < 0) - return true; - if (__c > 0) - return false; - } - else if constexpr (is_same_v<_Comp, ranges::greater>) - { - if (__c > 0) - return true; - if (__c < 0) - return false; - } - } - return __d1 < __d2; - } - } - - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void) ++__first2) - { - if (std::__invoke(__comp, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - return true; - if (std::__invoke(__comp, - std::__invoke(__proj2, *__first2), - std::__invoke(__proj1, *__first1))) - return false; - } - return __first1 == __last1 && __first2 != __last2; - } - } - - template, _Proj1>, - projected, _Proj2>> - _Comp = ranges::less> - constexpr bool - operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__comp), - std::move(__proj1), std::move(__proj2)); - } - - private: - template> - static constexpr bool __ptr_to_nonvolatile - = is_pointer_v<_Iter> && !is_volatile_v>; - }; - - inline constexpr __lexicographical_compare_fn lexicographical_compare; - - template - struct in_found_result - { - [[no_unique_address]] _Iter in; - bool found; - - template - requires convertible_to - constexpr - operator in_found_result<_Iter2>() const & - { return {in, found}; } - - template - requires convertible_to<_Iter, _Iter2> - constexpr - operator in_found_result<_Iter2>() && - { return {std::move(in), found}; } - }; - - template - using next_permutation_result = in_found_result<_Iter>; - - struct __next_permutation_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr next_permutation_result<_Iter> - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __last) - return {std::move(__first), false}; - - auto __i = __first; - ++__i; - if (__i == __last) - return {std::move(__i), false}; - - auto __lasti = ranges::next(__first, __last); - __i = __lasti; - --__i; - - for (;;) - { - auto __ii = __i; - --__i; - if (std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *__ii))) - { - auto __j = __lasti; - while (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *__i), - std::__invoke(__proj, *--__j))) - ; - ranges::iter_swap(__i, __j); - ranges::reverse(__ii, __last); - return {std::move(__lasti), true}; - } - if (__i == __first) - { - ranges::reverse(__first, __last); - return {std::move(__lasti), false}; - } - } - } - - template - requires sortable, _Comp, _Proj> - constexpr next_permutation_result> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __next_permutation_fn next_permutation{}; - - template - using prev_permutation_result = in_found_result<_Iter>; - - struct __prev_permutation_fn - { - template _Sent, - typename _Comp = ranges::less, typename _Proj = identity> - requires sortable<_Iter, _Comp, _Proj> - constexpr prev_permutation_result<_Iter> - operator()(_Iter __first, _Sent __last, - _Comp __comp = {}, _Proj __proj = {}) const - { - if (__first == __last) - return {std::move(__first), false}; - - auto __i = __first; - ++__i; - if (__i == __last) - return {std::move(__i), false}; - - auto __lasti = ranges::next(__first, __last); - __i = __lasti; - --__i; - - for (;;) - { - auto __ii = __i; - --__i; - if (std::__invoke(__comp, - std::__invoke(__proj, *__ii), - std::__invoke(__proj, *__i))) - { - auto __j = __lasti; - while (!(bool)std::__invoke(__comp, - std::__invoke(__proj, *--__j), - std::__invoke(__proj, *__i))) - ; - ranges::iter_swap(__i, __j); - ranges::reverse(__ii, __last); - return {std::move(__lasti), true}; - } - if (__i == __first) - { - ranges::reverse(__first, __last); - return {std::move(__lasti), false}; - } - } - } - - template - requires sortable, _Comp, _Proj> - constexpr prev_permutation_result> - operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__comp), std::move(__proj)); - } - }; - - inline constexpr __prev_permutation_fn prev_permutation{}; - -} // namespace ranges - -#define __cpp_lib_shift 201806L - template - constexpr _ForwardIterator - shift_left(_ForwardIterator __first, _ForwardIterator __last, - typename iterator_traits<_ForwardIterator>::difference_type __n) - { - __glibcxx_assert(__n >= 0); - if (__n == 0) - return __last; - - auto __mid = ranges::next(__first, __n, __last); - if (__mid == __last) - return __first; - return std::move(std::move(__mid), std::move(__last), std::move(__first)); - } - - template - constexpr _ForwardIterator - shift_right(_ForwardIterator __first, _ForwardIterator __last, - typename iterator_traits<_ForwardIterator>::difference_type __n) - { - __glibcxx_assert(__n >= 0); - if (__n == 0) - return __first; - - using _Cat - = typename iterator_traits<_ForwardIterator>::iterator_category; - if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) - { - auto __mid = ranges::next(__last, -__n, __first); - if (__mid == __first) - return __last; - - return std::move_backward(std::move(__first), std::move(__mid), - std::move(__last)); - } - else - { - auto __result = ranges::next(__first, __n, __last); - if (__result == __last) - return __last; - - auto __dest_head = __first, __dest_tail = __result; - while (__dest_head != __result) - { - if (__dest_tail == __last) - { - // If we get here, then we must have - // 2*n >= distance(__first, __last) - // i.e. we are shifting out at least half of the range. In - // this case we can safely perform the shift with a single - // move. - std::move(std::move(__first), std::move(__dest_head), - std::move(__result)); - return __result; - } - ++__dest_head; - ++__dest_tail; - } - - for (;;) - { - // At the start of each iteration of this outer loop, the range - // [__first, __result) contains those elements that after shifting - // the whole range right by __n, should end up in - // [__dest_head, __dest_tail) in order. - - // The below inner loop swaps the elements of [__first, __result) - // and [__dest_head, __dest_tail), while simultaneously shifting - // the latter range by __n. - auto __cursor = __first; - while (__cursor != __result) - { - if (__dest_tail == __last) - { - // At this point the ranges [__first, result) and - // [__dest_head, dest_tail) are disjoint, so we can safely - // move the remaining elements. - __dest_head = std::move(__cursor, __result, - std::move(__dest_head)); - std::move(std::move(__first), std::move(__cursor), - std::move(__dest_head)); - return __result; - } - std::iter_swap(__cursor, __dest_head); - ++__dest_head; - ++__dest_tail; - ++__cursor; - } - } - } - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // concepts -#endif // C++20 -#endif // _RANGES_ALGO_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h b/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h deleted file mode 100644 index 618bc7d10..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h +++ /dev/null @@ -1,597 +0,0 @@ -// Core algorithmic facilities -*- C++ -*- - -// Copyright (C) 2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/ranges_algobase.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{algorithm} - */ - -#ifndef _RANGES_ALGOBASE_H -#define _RANGES_ALGOBASE_H 1 - -#if __cplusplus > 201703L - -#include -#include -// #include -#include -#include -#include // __is_byte - -#if __cpp_lib_concepts -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -namespace ranges -{ - namespace __detail - { - template - constexpr inline bool __is_normal_iterator = false; - - template - constexpr inline bool - __is_normal_iterator<__gnu_cxx::__normal_iterator<_Iterator, - _Container>> = true; - - template - constexpr inline bool __is_reverse_iterator = false; - - template - constexpr inline bool - __is_reverse_iterator> = true; - - template - constexpr inline bool __is_move_iterator = false; - - template - constexpr inline bool - __is_move_iterator> = true; - } // namespace __detail - - struct __equal_fn - { - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr bool - operator()(_Iter1 __first1, _Sent1 __last1, - _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - // TODO: implement more specializations to at least have parity with - // std::equal. - if constexpr (__detail::__is_normal_iterator<_Iter1> - && same_as<_Iter1, _Sent1>) - return (*this)(__first1.base(), __last1.base(), - std::move(__first2), std::move(__last2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - else if constexpr (__detail::__is_normal_iterator<_Iter2> - && same_as<_Iter2, _Sent2>) - return (*this)(std::move(__first1), std::move(__last1), - __first2.base(), __last2.base(), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - else if constexpr (sized_sentinel_for<_Sent1, _Iter1> - && sized_sentinel_for<_Sent2, _Iter2>) - { - auto __d1 = ranges::distance(__first1, __last1); - auto __d2 = ranges::distance(__first2, __last2); - if (__d1 != __d2) - return false; - - using _ValueType1 = iter_value_t<_Iter1>; - using _ValueType2 = iter_value_t<_Iter2>; - constexpr bool __use_memcmp - = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) - && __memcmpable<_Iter1, _Iter2>::__value - && is_same_v<_Pred, ranges::equal_to> - && is_same_v<_Proj1, identity> - && is_same_v<_Proj2, identity>); - if constexpr (__use_memcmp) - { - if (const size_t __len = (__last1 - __first1)) - return !std::__memcmp(__first1, __first2, __len); - return true; - } - else - { - for (; __first1 != __last1; ++__first1, (void)++__first2) - if (!(bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - return false; - return true; - } - } - else - { - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - if (!(bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - return false; - return __first1 == __last1 && __first2 == __last2; - } - } - - template - requires indirectly_comparable, iterator_t<_Range2>, - _Pred, _Proj1, _Proj2> - constexpr bool - operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, - _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const - { - return (*this)(ranges::begin(__r1), ranges::end(__r1), - ranges::begin(__r2), ranges::end(__r2), - std::move(__pred), - std::move(__proj1), std::move(__proj2)); - } - }; - - inline constexpr __equal_fn equal{}; - - template - struct in_out_result - { - [[no_unique_address]] _Iter in; - [[no_unique_address]] _Out out; - - template - requires convertible_to - && convertible_to - constexpr - operator in_out_result<_Iter2, _Out2>() const & - { return {in, out}; } - - template - requires convertible_to<_Iter, _Iter2> - && convertible_to<_Out, _Out2> - constexpr - operator in_out_result<_Iter2, _Out2>() && - { return {std::move(in), std::move(out)}; } - }; - - template - using copy_result = in_out_result<_Iter, _Out>; - - template - using move_result = in_out_result<_Iter, _Out>; - - template - using move_backward_result = in_out_result<_Iter1, _Iter2>; - - template - using copy_backward_result = in_out_result<_Iter1, _Iter2>; - - template _Sent, - bidirectional_iterator _Out> - requires (_IsMove - ? indirectly_movable<_Iter, _Out> - : indirectly_copyable<_Iter, _Out>) - constexpr conditional_t<_IsMove, - move_backward_result<_Iter, _Out>, - copy_backward_result<_Iter, _Out>> - __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result); - - template _Sent, - weakly_incrementable _Out> - requires (_IsMove - ? indirectly_movable<_Iter, _Out> - : indirectly_copyable<_Iter, _Out>) - constexpr conditional_t<_IsMove, - move_result<_Iter, _Out>, - copy_result<_Iter, _Out>> - __copy_or_move(_Iter __first, _Sent __last, _Out __result) - { - // TODO: implement more specializations to be at least on par with - // std::copy/std::move. - using __detail::__is_move_iterator; - using __detail::__is_reverse_iterator; - using __detail::__is_normal_iterator; - if constexpr (__is_move_iterator<_Iter> && same_as<_Iter, _Sent>) - { - auto [__in, __out] - = ranges::__copy_or_move(std::move(__first).base(), - std::move(__last).base(), - std::move(__result)); - return {move_iterator{std::move(__in)}, std::move(__out)}; - } - else if constexpr (__is_reverse_iterator<_Iter> && same_as<_Iter, _Sent> - && __is_reverse_iterator<_Out>) - { - auto [__in,__out] - = ranges::__copy_or_move_backward<_IsMove>(std::move(__last).base(), - std::move(__first).base(), - std::move(__result).base()); - return {reverse_iterator{std::move(__in)}, - reverse_iterator{std::move(__out)}}; - } - else if constexpr (__is_normal_iterator<_Iter> && same_as<_Iter, _Sent>) - { - auto [__in,__out] - = ranges::__copy_or_move<_IsMove>(__first.base(), __last.base(), - __result); - return {decltype(__first){__in}, std::move(__out)}; - } - else if constexpr (__is_normal_iterator<_Out>) - { - auto [__in,__out] - = ranges::__copy_or_move<_IsMove>(__first, __last, __result.base()); - return {std::move(__in), decltype(__result){__out}}; - } - else if constexpr (sized_sentinel_for<_Sent, _Iter>) - { -#ifdef __cpp_lib_is_constant_evaluated - if (!std::is_constant_evaluated()) -#endif - { - if constexpr (__memcpyable<_Iter, _Out>::__value) - { - using _ValueTypeI = iter_value_t<_Iter>; - static_assert(_IsMove - ? is_move_assignable_v<_ValueTypeI> - : is_copy_assignable_v<_ValueTypeI>); - auto __num = __last - __first; - if (__num) - __builtin_memmove(__result, __first, - sizeof(_ValueTypeI) * __num); - return {__first + __num, __result + __num}; - } - } - - for (auto __n = __last - __first; __n > 0; --__n) - { - if constexpr (_IsMove) - *__result = std::move(*__first); - else - *__result = *__first; - ++__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - else - { - while (__first != __last) - { - if constexpr (_IsMove) - *__result = std::move(*__first); - else - *__result = *__first; - ++__first; - ++__result; - } - return {std::move(__first), std::move(__result)}; - } - } - - struct __copy_fn - { - template _Sent, - weakly_incrementable _Out> - requires indirectly_copyable<_Iter, _Out> - constexpr copy_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result) const - { - return ranges::__copy_or_move(std::move(__first), - std::move(__last), - std::move(__result)); - } - - template - requires indirectly_copyable, _Out> - constexpr copy_result, _Out> - operator()(_Range&& __r, _Out __result) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } - }; - - inline constexpr __copy_fn copy{}; - - struct __move_fn - { - template _Sent, - weakly_incrementable _Out> - requires indirectly_movable<_Iter, _Out> - constexpr move_result<_Iter, _Out> - operator()(_Iter __first, _Sent __last, _Out __result) const - { - return ranges::__copy_or_move(std::move(__first), - std::move(__last), - std::move(__result)); - } - - template - requires indirectly_movable, _Out> - constexpr move_result, _Out> - operator()(_Range&& __r, _Out __result) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } - }; - - inline constexpr __move_fn move{}; - - template _Sent, - bidirectional_iterator _Out> - requires (_IsMove - ? indirectly_movable<_Iter, _Out> - : indirectly_copyable<_Iter, _Out>) - constexpr conditional_t<_IsMove, - move_backward_result<_Iter, _Out>, - copy_backward_result<_Iter, _Out>> - __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result) - { - // TODO: implement more specializations to be at least on par with - // std::copy_backward/std::move_backward. - using __detail::__is_reverse_iterator; - using __detail::__is_normal_iterator; - if constexpr (__is_reverse_iterator<_Iter> && same_as<_Iter, _Sent> - && __is_reverse_iterator<_Out>) - { - auto [__in,__out] - = ranges::__copy_or_move<_IsMove>(std::move(__last).base(), - std::move(__first).base(), - std::move(__result).base()); - return {reverse_iterator{std::move(__in)}, - reverse_iterator{std::move(__out)}}; - } - else if constexpr (__is_normal_iterator<_Iter> && same_as<_Iter, _Sent>) - { - auto [__in,__out] - = ranges::__copy_or_move_backward<_IsMove>(__first.base(), - __last.base(), - std::move(__result)); - return {decltype(__first){__in}, std::move(__out)}; - } - else if constexpr (__is_normal_iterator<_Out>) - { - auto [__in,__out] - = ranges::__copy_or_move_backward<_IsMove>(std::move(__first), - std::move(__last), - __result.base()); - return {std::move(__in), decltype(__result){__out}}; - } - else if constexpr (sized_sentinel_for<_Sent, _Iter>) - { -#ifdef __cpp_lib_is_constant_evaluated - if (!std::is_constant_evaluated()) -#endif - { - if constexpr (__memcpyable<_Out, _Iter>::__value) - { - using _ValueTypeI = iter_value_t<_Iter>; - static_assert(_IsMove - ? is_move_assignable_v<_ValueTypeI> - : is_copy_assignable_v<_ValueTypeI>); - auto __num = __last - __first; - if (__num) - __builtin_memmove(__result - __num, __first, - sizeof(_ValueTypeI) * __num); - return {__first + __num, __result - __num}; - } - } - - auto __lasti = ranges::next(__first, __last); - auto __tail = __lasti; - - for (auto __n = __last - __first; __n > 0; --__n) - { - --__tail; - --__result; - if constexpr (_IsMove) - *__result = std::move(*__tail); - else - *__result = *__tail; - } - return {std::move(__lasti), std::move(__result)}; - } - else - { - auto __lasti = ranges::next(__first, __last); - auto __tail = __lasti; - - while (__first != __tail) - { - --__tail; - --__result; - if constexpr (_IsMove) - *__result = std::move(*__tail); - else - *__result = *__tail; - } - return {std::move(__lasti), std::move(__result)}; - } - } - - struct __copy_backward_fn - { - template _Sent1, - bidirectional_iterator _Iter2> - requires indirectly_copyable<_Iter1, _Iter2> - constexpr copy_backward_result<_Iter1, _Iter2> - operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const - { - return ranges::__copy_or_move_backward(std::move(__first), - std::move(__last), - std::move(__result)); - } - - template - requires indirectly_copyable, _Iter> - constexpr copy_backward_result, _Iter> - operator()(_Range&& __r, _Iter __result) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } - }; - - inline constexpr __copy_backward_fn copy_backward{}; - - struct __move_backward_fn - { - template _Sent1, - bidirectional_iterator _Iter2> - requires indirectly_movable<_Iter1, _Iter2> - constexpr move_backward_result<_Iter1, _Iter2> - operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const - { - return ranges::__copy_or_move_backward(std::move(__first), - std::move(__last), - std::move(__result)); - } - - template - requires indirectly_movable, _Iter> - constexpr move_backward_result, _Iter> - operator()(_Range&& __r, _Iter __result) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), - std::move(__result)); - } - }; - - inline constexpr __move_backward_fn move_backward{}; - - template - using copy_n_result = in_out_result<_Iter, _Out>; - - struct __copy_n_fn - { - template - requires indirectly_copyable<_Iter, _Out> - constexpr copy_n_result<_Iter, _Out> - operator()(_Iter __first, iter_difference_t<_Iter> __n, - _Out __result) const - { - if constexpr (random_access_iterator<_Iter>) - return ranges::copy(__first, __first + __n, std::move(__result)); - else - { - for (; __n > 0; --__n, (void)++__result, (void)++__first) - *__result = *__first; - return {std::move(__first), std::move(__result)}; - } - } - }; - - inline constexpr __copy_n_fn copy_n{}; - - struct __fill_n_fn - { - template _Out> - constexpr _Out - operator()(_Out __first, iter_difference_t<_Out> __n, - const _Tp& __value) const - { - // TODO: implement more specializations to be at least on par with - // std::fill_n - if (__n <= 0) - return __first; - - // TODO: Generalize this optimization to contiguous iterators. - if constexpr (is_pointer_v<_Out> - // Note that __is_byte already implies !is_volatile. - && __is_byte>::__value - && integral<_Tp>) - { - __builtin_memset(__first, static_cast(__value), __n); - return __first + __n; - } - else if constexpr (is_scalar_v<_Tp>) - { - const auto __tmp = __value; - for (; __n > 0; --__n, (void)++__first) - *__first = __tmp; - return __first; - } - else - { - for (; __n > 0; --__n, (void)++__first) - *__first = __value; - return __first; - } - } - }; - - inline constexpr __fill_n_fn fill_n{}; - - struct __fill_fn - { - template _Out, sentinel_for<_Out> _Sent> - constexpr _Out - operator()(_Out __first, _Sent __last, const _Tp& __value) const - { - // TODO: implement more specializations to be at least on par with - // std::fill - if constexpr (sized_sentinel_for<_Sent, _Out>) - { - const auto __len = __last - __first; - return ranges::fill_n(__first, __len, __value); - } - else if constexpr (is_scalar_v<_Tp>) - { - const auto __tmp = __value; - for (; __first != __last; ++__first) - *__first = __tmp; - return __first; - } - else - { - for (; __first != __last; ++__first) - *__first = __value; - return __first; - } - } - - template _Range> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r, const _Tp& __value) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), __value); - } - }; - - inline constexpr __fill_fn fill{}; -} -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // concepts -#endif // C++20 -#endif // _RANGES_ALGOBASE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h b/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h deleted file mode 100644 index 25e664de7..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h +++ /dev/null @@ -1,574 +0,0 @@ -// Raw memory manipulators -*- C++ -*- - -// Copyright (C) 2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/ranges_uninitialized.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _RANGES_UNINITIALIZED_H -#define _RANGES_UNINITIALIZED_H 1 - -#if __cplusplus > 201703L -#if __cpp_lib_concepts - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -namespace ranges -{ - namespace __detail - { - template - constexpr void* - __voidify(_Tp& __obj) noexcept - { - return const_cast - (static_cast(std::__addressof(__obj))); - } - - template - concept __nothrow_input_iterator - = (input_iterator<_Iter> - && is_lvalue_reference_v> - && same_as>, - iter_value_t<_Iter>>); - - template - concept __nothrow_sentinel = sentinel_for<_Sent, _Iter>; - - template - concept __nothrow_input_range - = (range<_Range> - && __nothrow_input_iterator> - && __nothrow_sentinel, iterator_t<_Range>>); - - template - concept __nothrow_forward_iterator - = (__nothrow_input_iterator<_Iter> - && forward_iterator<_Iter> - && __nothrow_sentinel<_Iter, _Iter>); - - template - concept __nothrow_forward_range - = (__nothrow_input_range<_Range> - && __nothrow_forward_iterator>); - } // namespace __detail - - struct __destroy_fn - { - template<__detail::__nothrow_input_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent> - requires destructible> - constexpr _Iter - operator()(_Iter __first, _Sent __last) const noexcept; - - template<__detail::__nothrow_input_range _Range> - requires destructible> - constexpr borrowed_iterator_t<_Range> - operator()(_Range&& __r) const noexcept; - }; - - inline constexpr __destroy_fn destroy{}; - - namespace __detail - { - template - requires destructible> - struct _DestroyGuard - { - private: - _Iter _M_first; - const _Iter* _M_cur; - - public: - explicit - _DestroyGuard(const _Iter* __iter) - : _M_first(*__iter), _M_cur(__iter) - { } - - void - release() noexcept - { _M_cur = nullptr; } - - ~_DestroyGuard() - { - if (_M_cur != nullptr) - ranges::destroy(std::move(_M_first), *_M_cur); - } - }; - - template - requires destructible> - && is_trivially_destructible_v> - struct _DestroyGuard<_Iter> - { - explicit - _DestroyGuard(const _Iter*) - { } - - void - release() noexcept - { } - }; - } // namespace __detail - - struct __uninitialized_default_construct_fn - { - template<__detail::__nothrow_forward_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent> - requires default_initializable> - _Iter - operator()(_Iter __first, _Sent __last) const - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivially_default_constructible_v<_ValueType>) - return ranges::next(__first, __last); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __first != __last; ++__first) - ::new (__detail::__voidify(*__first)) _ValueType; - __guard.release(); - return __first; - } - } - - template<__detail::__nothrow_forward_range _Range> - requires default_initializable> - borrowed_iterator_t<_Range> - operator()(_Range&& __r) const - { - return (*this)(ranges::begin(__r), ranges::end(__r)); - } - }; - - inline constexpr __uninitialized_default_construct_fn - uninitialized_default_construct{}; - - struct __uninitialized_default_construct_n_fn - { - template<__detail::__nothrow_forward_iterator _Iter> - requires default_initializable> - _Iter - operator()(_Iter __first, iter_difference_t<_Iter> __n) const - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivially_default_constructible_v<_ValueType>) - return ranges::next(__first, __n); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __n > 0; ++__first, (void) --__n) - ::new (__detail::__voidify(*__first)) _ValueType; - __guard.release(); - return __first; - } - } - }; - - inline constexpr __uninitialized_default_construct_n_fn - uninitialized_default_construct_n; - - struct __uninitialized_value_construct_fn - { - template<__detail::__nothrow_forward_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent> - requires default_initializable> - _Iter - operator()(_Iter __first, _Sent __last) const - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivial_v<_ValueType> - && is_copy_assignable_v<_ValueType>) - return ranges::fill(__first, __last, _ValueType()); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __first != __last; ++__first) - ::new (__detail::__voidify(*__first)) _ValueType(); - __guard.release(); - return __first; - } - } - - template<__detail::__nothrow_forward_range _Range> - requires default_initializable> - borrowed_iterator_t<_Range> - operator()(_Range&& __r) const - { - return (*this)(ranges::begin(__r), ranges::end(__r)); - } - }; - - inline constexpr __uninitialized_value_construct_fn - uninitialized_value_construct{}; - - struct __uninitialized_value_construct_n_fn - { - template<__detail::__nothrow_forward_iterator _Iter> - requires default_initializable> - _Iter - operator()(_Iter __first, iter_difference_t<_Iter> __n) const - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivial_v<_ValueType> - && is_copy_assignable_v<_ValueType>) - return ranges::fill_n(__first, __n, _ValueType()); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __n > 0; ++__first, (void) --__n) - ::new (__detail::__voidify(*__first)) _ValueType(); - __guard.release(); - return __first; - } - } - }; - - inline constexpr __uninitialized_value_construct_n_fn - uninitialized_value_construct_n; - - template - using uninitialized_copy_result = in_out_result<_Iter, _Out>; - - struct __uninitialized_copy_fn - { - template _ISent, - __detail::__nothrow_forward_iterator _Out, - __detail::__nothrow_sentinel<_Out> _OSent> - requires constructible_from, iter_reference_t<_Iter>> - uninitialized_copy_result<_Iter, _Out> - operator()(_Iter __ifirst, _ISent __ilast, - _Out __ofirst, _OSent __olast) const - { - using _OutType = remove_reference_t>; - if constexpr (sized_sentinel_for<_ISent, _Iter> - && sized_sentinel_for<_OSent, _Out> - && is_trivial_v<_OutType> - && is_nothrow_assignable_v<_OutType&, - iter_reference_t<_Iter>>) - { - auto __d1 = __ilast - __ifirst; - auto __d2 = __olast - __ofirst; - return ranges::copy_n(std::move(__ifirst), std::min(__d1, __d2), - __ofirst); - } - else - { - auto __guard = __detail::_DestroyGuard(&__ofirst); - for (; __ifirst != __ilast && __ofirst != __olast; - ++__ofirst, (void)++__ifirst) - ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); - __guard.release(); - return {std::move(__ifirst), __ofirst}; - } - } - - template - requires constructible_from, - range_reference_t<_IRange>> - uninitialized_copy_result, - borrowed_iterator_t<_ORange>> - operator()(_IRange&& __inr, _ORange&& __outr) const - { - return (*this)(ranges::begin(__inr), ranges::end(__inr), - ranges::begin(__outr), ranges::end(__outr)); - } - }; - - inline constexpr __uninitialized_copy_fn uninitialized_copy{}; - - template - using uninitialized_copy_n_result = in_out_result<_Iter, _Out>; - - struct __uninitialized_copy_n_fn - { - template _Sent> - requires constructible_from, iter_reference_t<_Iter>> - uninitialized_copy_n_result<_Iter, _Out> - operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, - _Out __ofirst, _Sent __olast) const - { - using _OutType = remove_reference_t>; - if constexpr (sized_sentinel_for<_Sent, _Out> - && is_trivial_v<_OutType> - && is_nothrow_assignable_v<_OutType&, - iter_reference_t<_Iter>>) - { - auto __d = __olast - __ofirst; - return ranges::copy_n(std::move(__ifirst), std::min(__n, __d), - __ofirst); - } - else - { - auto __guard = __detail::_DestroyGuard(&__ofirst); - for (; __n > 0 && __ofirst != __olast; - ++__ofirst, (void)++__ifirst, (void)--__n) - ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); - __guard.release(); - return {std::move(__ifirst), __ofirst}; - } - } - }; - - inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{}; - - template - using uninitialized_move_result = in_out_result<_Iter, _Out>; - - struct __uninitialized_move_fn - { - template _ISent, - __detail::__nothrow_forward_iterator _Out, - __detail::__nothrow_sentinel<_Out> _OSent> - requires constructible_from, - iter_rvalue_reference_t<_Iter>> - uninitialized_move_result<_Iter, _Out> - operator()(_Iter __ifirst, _ISent __ilast, - _Out __ofirst, _OSent __olast) const - { - using _OutType = remove_reference_t>; - if constexpr (sized_sentinel_for<_ISent, _Iter> - && sized_sentinel_for<_OSent, _Out> - && is_trivial_v<_OutType> - && is_nothrow_assignable_v<_OutType&, - iter_rvalue_reference_t<_Iter>>) - { - auto __d1 = __ilast - __ifirst; - auto __d2 = __olast - __ofirst; - auto [__in, __out] - = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), - std::min(__d1, __d2), __ofirst); - return {std::move(__in).base(), __out}; - } - else - { - auto __guard = __detail::_DestroyGuard(&__ofirst); - for (; __ifirst != __ilast && __ofirst != __olast; - ++__ofirst, (void)++__ifirst) - ::new (__detail::__voidify(*__ofirst)) - _OutType(ranges::iter_move(__ifirst)); - __guard.release(); - return {std::move(__ifirst), __ofirst}; - } - } - - template - requires constructible_from, - range_rvalue_reference_t<_IRange>> - uninitialized_move_result, - borrowed_iterator_t<_ORange>> - operator()(_IRange&& __inr, _ORange&& __outr) const - { - return (*this)(ranges::begin(__inr), ranges::end(__inr), - ranges::begin(__outr), ranges::end(__outr)); - } - }; - - inline constexpr __uninitialized_move_fn uninitialized_move{}; - - template - using uninitialized_move_n_result = in_out_result<_Iter, _Out>; - - struct __uninitialized_move_n_fn - { - template _Sent> - requires constructible_from, - iter_rvalue_reference_t<_Iter>> - uninitialized_move_n_result<_Iter, _Out> - operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, - _Out __ofirst, _Sent __olast) const - { - using _OutType = remove_reference_t>; - if constexpr (sized_sentinel_for<_Sent, _Out> - && is_trivial_v<_OutType> - && is_nothrow_assignable_v<_OutType&, - iter_rvalue_reference_t<_Iter>>) - { - auto __d = __olast - __ofirst; - auto [__in, __out] - = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), - std::min(__n, __d), __ofirst); - return {std::move(__in).base(), __out}; - } - else - { - auto __guard = __detail::_DestroyGuard(&__ofirst); - for (; __n > 0 && __ofirst != __olast; - ++__ofirst, (void)++__ifirst, (void)--__n) - ::new (__detail::__voidify(*__ofirst)) - _OutType(ranges::iter_move(__ifirst)); - __guard.release(); - return {std::move(__ifirst), __ofirst}; - } - } - }; - - inline constexpr __uninitialized_move_n_fn uninitialized_move_n{}; - - struct __uninitialized_fill_fn - { - template<__detail::__nothrow_forward_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp> - requires constructible_from, const _Tp&> - _Iter - operator()(_Iter __first, _Sent __last, const _Tp& __x) const - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivial_v<_ValueType> - && is_nothrow_assignable_v<_ValueType&, const _Tp&>) - return ranges::fill(__first, __last, __x); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __first != __last; ++__first) - ::new (__detail::__voidify(*__first)) _ValueType(__x); - __guard.release(); - return __first; - } - } - - template<__detail::__nothrow_forward_range _Range, typename _Tp> - requires constructible_from, const _Tp&> - borrowed_iterator_t<_Range> - operator()(_Range&& __r, const _Tp& __x) const - { - return (*this)(ranges::begin(__r), ranges::end(__r), __x); - } - }; - - inline constexpr __uninitialized_fill_fn uninitialized_fill{}; - - struct __uninitialized_fill_n_fn - { - template<__detail::__nothrow_forward_iterator _Iter, typename _Tp> - requires constructible_from, const _Tp&> - _Iter - operator()(_Iter __first, iter_difference_t<_Iter> __n, - const _Tp& __x) const - { - using _ValueType = remove_reference_t>; - if constexpr (is_trivial_v<_ValueType> - && is_nothrow_assignable_v<_ValueType&, const _Tp&>) - return ranges::fill_n(__first, __n, __x); - else - { - auto __guard = __detail::_DestroyGuard(&__first); - for (; __n > 0; ++__first, (void)--__n) - ::new (__detail::__voidify(*__first)) _ValueType(__x); - __guard.release(); - return __first; - } - } - }; - - inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{}; - - struct __construct_at_fn - { - template - requires requires { - ::new (std::declval()) _Tp(std::declval<_Args>()...); - } - constexpr _Tp* - operator()(_Tp* __location, _Args&&... __args) const - noexcept(noexcept(std::construct_at(__location, - std::forward<_Args>(__args)...))) - { - return std::construct_at(__location, - std::forward<_Args>(__args)...); - } - }; - - inline constexpr __construct_at_fn construct_at{}; - - struct __destroy_at_fn - { - template - constexpr void - operator()(_Tp* __location) const noexcept - { - if constexpr (is_array_v<_Tp>) - ranges::destroy(ranges::begin(*__location), ranges::end(*__location)); - else - __location->~_Tp(); - } - }; - - inline constexpr __destroy_at_fn destroy_at{}; - - template<__detail::__nothrow_input_iterator _Iter, - __detail::__nothrow_sentinel<_Iter> _Sent> - requires destructible> - constexpr _Iter - __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept - { - if constexpr (is_trivially_destructible_v>) - return ranges::next(std::move(__first), __last); - else - { - for (; __first != __last; ++__first) - ranges::destroy_at(std::__addressof(*__first)); - return __first; - } - } - - template<__detail::__nothrow_input_range _Range> - requires destructible> - constexpr borrowed_iterator_t<_Range> - __destroy_fn::operator()(_Range&& __r) const noexcept - { - return (*this)(ranges::begin(__r), ranges::end(__r)); - } - - struct __destroy_n_fn - { - template<__detail::__nothrow_input_iterator _Iter> - requires destructible> - constexpr _Iter - operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept - { - if constexpr (is_trivially_destructible_v>) - return ranges::next(std::move(__first), __n); - else - { - for (; __n > 0; ++__first, (void)--__n) - ranges::destroy_at(std::__addressof(*__first)); - return __first; - } - } - }; - - inline constexpr __destroy_n_fn destroy_n{}; -} -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // concepts -#endif // C++20 -#endif // _RANGES_UNINITIALIZED_H diff --git a/resources/sources/avr-libstdcpp/include/bits/refwrap.h b/resources/sources/avr-libstdcpp/include/bits/refwrap.h deleted file mode 100644 index 717aa0162..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/refwrap.h +++ /dev/null @@ -1,401 +0,0 @@ -// Implementation of std::reference_wrapper -*- C++ -*- - -// Copyright (C) 2004-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/bits/refwrap.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _GLIBCXX_REFWRAP_H -#define _GLIBCXX_REFWRAP_H 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include // for unary_function and binary_function - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /// @cond undocumented - - /** - * Derives from @c unary_function or @c binary_function, or perhaps - * nothing, depending on the number of arguments provided. The - * primary template is the basis case, which derives nothing. - */ - template - struct _Maybe_unary_or_binary_function { }; - - /// Derives from @c unary_function, as appropriate. - template - struct _Maybe_unary_or_binary_function<_Res, _T1> - : std::unary_function<_T1, _Res> { }; - - /// Derives from @c binary_function, as appropriate. - template - struct _Maybe_unary_or_binary_function<_Res, _T1, _T2> - : std::binary_function<_T1, _T2, _Res> { }; - - template - struct _Mem_fn_traits; - - template - struct _Mem_fn_traits_base - { - using __result_type = _Res; - using __maybe_type - = _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>; - using __arity = integral_constant; - }; - -#define _GLIBCXX_MEM_FN_TRAITS2(_CV, _REF, _LVAL, _RVAL) \ - template \ - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF> \ - : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ - { \ - using __vararg = false_type; \ - }; \ - template \ - struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \ - : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ - { \ - using __vararg = true_type; \ - }; - -#define _GLIBCXX_MEM_FN_TRAITS(_REF, _LVAL, _RVAL) \ - _GLIBCXX_MEM_FN_TRAITS2( , _REF, _LVAL, _RVAL) \ - _GLIBCXX_MEM_FN_TRAITS2(const , _REF, _LVAL, _RVAL) \ - _GLIBCXX_MEM_FN_TRAITS2(volatile , _REF, _LVAL, _RVAL) \ - _GLIBCXX_MEM_FN_TRAITS2(const volatile, _REF, _LVAL, _RVAL) - -_GLIBCXX_MEM_FN_TRAITS( , true_type, true_type) -_GLIBCXX_MEM_FN_TRAITS(&, true_type, false_type) -_GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) - -#if __cplusplus > 201402L -_GLIBCXX_MEM_FN_TRAITS(noexcept, true_type, true_type) -_GLIBCXX_MEM_FN_TRAITS(& noexcept, true_type, false_type) -_GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) -#endif - -#undef _GLIBCXX_MEM_FN_TRAITS -#undef _GLIBCXX_MEM_FN_TRAITS2 - - /// If we have found a result_type, extract it. - template> - struct _Maybe_get_result_type - { }; - - template - struct _Maybe_get_result_type<_Functor, - __void_t> - { typedef typename _Functor::result_type result_type; }; - - /** - * Base class for any function object that has a weak result type, as - * defined in 20.8.2 [func.require] of C++11. - */ - template - struct _Weak_result_type_impl - : _Maybe_get_result_type<_Functor> - { }; - - /// Retrieve the result type for a function type. - template - struct _Weak_result_type_impl<_Res(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> - { typedef _Res result_type; }; - - /// Retrieve the result type for a varargs function type. - template - struct _Weak_result_type_impl<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> - { typedef _Res result_type; }; - - /// Retrieve the result type for a function pointer. - template - struct _Weak_result_type_impl<_Res(*)(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> - { typedef _Res result_type; }; - - /// Retrieve the result type for a varargs function pointer. - template - struct - _Weak_result_type_impl<_Res(*)(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> - { typedef _Res result_type; }; - - // Let _Weak_result_type_impl perform the real work. - template::value> - struct _Weak_result_type_memfun - : _Weak_result_type_impl<_Functor> - { }; - - // A pointer to member function has a weak result type. - template - struct _Weak_result_type_memfun<_MemFunPtr, true> - { - using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; - }; - - // A pointer to data member doesn't have a weak result type. - template - struct _Weak_result_type_memfun<_Func _Class::*, false> - { }; - - /** - * Strip top-level cv-qualifiers from the function object and let - * _Weak_result_type_memfun perform the real work. - */ - template - struct _Weak_result_type - : _Weak_result_type_memfun::type> - { }; - -#if __cplusplus <= 201703L - // Detect nested argument_type. - template> - struct _Refwrap_base_arg1 - { }; - - // Nested argument_type. - template - struct _Refwrap_base_arg1<_Tp, - __void_t> - { - typedef typename _Tp::argument_type argument_type; - }; - - // Detect nested first_argument_type and second_argument_type. - template> - struct _Refwrap_base_arg2 - { }; - - // Nested first_argument_type and second_argument_type. - template - struct _Refwrap_base_arg2<_Tp, - __void_t> - { - typedef typename _Tp::first_argument_type first_argument_type; - typedef typename _Tp::second_argument_type second_argument_type; - }; - - /** - * Derives from unary_function or binary_function when it - * can. Specializations handle all of the easy cases. The primary - * template determines what to do with a class type, which may - * derive from both unary_function and binary_function. - */ - template - struct _Reference_wrapper_base - : _Weak_result_type<_Tp>, _Refwrap_base_arg1<_Tp>, _Refwrap_base_arg2<_Tp> - { }; - - // - a function type (unary) - template - struct _Reference_wrapper_base<_Res(_T1) _GLIBCXX_NOEXCEPT_QUAL> - : unary_function<_T1, _Res> - { }; - - template - struct _Reference_wrapper_base<_Res(_T1) const> - : unary_function<_T1, _Res> - { }; - - template - struct _Reference_wrapper_base<_Res(_T1) volatile> - : unary_function<_T1, _Res> - { }; - - template - struct _Reference_wrapper_base<_Res(_T1) const volatile> - : unary_function<_T1, _Res> - { }; - - // - a function type (binary) - template - struct _Reference_wrapper_base<_Res(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> - : binary_function<_T1, _T2, _Res> - { }; - - template - struct _Reference_wrapper_base<_Res(_T1, _T2) const> - : binary_function<_T1, _T2, _Res> - { }; - - template - struct _Reference_wrapper_base<_Res(_T1, _T2) volatile> - : binary_function<_T1, _T2, _Res> - { }; - - template - struct _Reference_wrapper_base<_Res(_T1, _T2) const volatile> - : binary_function<_T1, _T2, _Res> - { }; - - // - a function pointer type (unary) - template - struct _Reference_wrapper_base<_Res(*)(_T1) _GLIBCXX_NOEXCEPT_QUAL> - : unary_function<_T1, _Res> - { }; - - // - a function pointer type (binary) - template - struct _Reference_wrapper_base<_Res(*)(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> - : binary_function<_T1, _T2, _Res> - { }; - - template::value> - struct _Reference_wrapper_base_memfun - : _Reference_wrapper_base<_Tp> - { }; - - template - struct _Reference_wrapper_base_memfun<_MemFunPtr, true> - : _Mem_fn_traits<_MemFunPtr>::__maybe_type - { - using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; - }; -#endif // ! C++20 - - /// @endcond - - /** - * @brief Primary class template for reference_wrapper. - * @ingroup functors - */ - template - class reference_wrapper -#if __cplusplus <= 201703L - // In C++20 std::reference_wrapper allows T to be incomplete, - // so checking for nested types could result in ODR violations. - : public _Reference_wrapper_base_memfun::type> -#endif - { - _Tp* _M_data; - - _GLIBCXX20_CONSTEXPR - static _Tp* _S_fun(_Tp& __r) noexcept { return std::__addressof(__r); } - - static void _S_fun(_Tp&&) = delete; - - template> - using __not_same - = typename enable_if::value>::type; - - public: - typedef _Tp type; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2993. reference_wrapper conversion from T&& - // 3041. Unnecessary decay in reference_wrapper - template, typename - = decltype(reference_wrapper::_S_fun(std::declval<_Up>()))> - _GLIBCXX20_CONSTEXPR - reference_wrapper(_Up&& __uref) - noexcept(noexcept(reference_wrapper::_S_fun(std::declval<_Up>()))) - : _M_data(reference_wrapper::_S_fun(std::forward<_Up>(__uref))) - { } - - reference_wrapper(const reference_wrapper&) = default; - - reference_wrapper& - operator=(const reference_wrapper&) = default; - - _GLIBCXX20_CONSTEXPR - operator _Tp&() const noexcept - { return this->get(); } - - _GLIBCXX20_CONSTEXPR - _Tp& - get() const noexcept - { return *_M_data; } - - template - _GLIBCXX20_CONSTEXPR - typename result_of<_Tp&(_Args&&...)>::type - operator()(_Args&&... __args) const - { -#if __cplusplus > 201703L - if constexpr (is_object_v) - static_assert(sizeof(type), "type must be complete"); -#endif - return std::__invoke(get(), std::forward<_Args>(__args)...); - } - }; - -#if __cpp_deduction_guides - template - reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; -#endif - - /// @relates reference_wrapper @{ - - /// Denotes a reference should be taken to a variable. - template - _GLIBCXX20_CONSTEXPR - inline reference_wrapper<_Tp> - ref(_Tp& __t) noexcept - { return reference_wrapper<_Tp>(__t); } - - /// Denotes a const reference should be taken to a variable. - template - _GLIBCXX20_CONSTEXPR - inline reference_wrapper - cref(const _Tp& __t) noexcept - { return reference_wrapper(__t); } - - template - void ref(const _Tp&&) = delete; - - template - void cref(const _Tp&&) = delete; - - /// std::ref overload to prevent wrapping a reference_wrapper - template - _GLIBCXX20_CONSTEXPR - inline reference_wrapper<_Tp> - ref(reference_wrapper<_Tp> __t) noexcept - { return __t; } - - /// std::cref overload to prevent wrapping a reference_wrapper - template - _GLIBCXX20_CONSTEXPR - inline reference_wrapper - cref(reference_wrapper<_Tp> __t) noexcept - { return { __t.get() }; } - - // @} - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++11 - -#endif // _GLIBCXX_REFWRAP_H diff --git a/resources/sources/avr-libstdcpp/include/bits/slice_array.h b/resources/sources/avr-libstdcpp/include/bits/slice_array.h deleted file mode 100644 index de33342e2..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/slice_array.h +++ /dev/null @@ -1,284 +0,0 @@ -// The template and inlines for the -*- C++ -*- slice_array class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/slice_array.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _SLICE_ARRAY_H -#define _SLICE_ARRAY_H 1 - -#pragma GCC system_header - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup numeric_arrays - * @{ - */ - - /** - * @brief Class defining one-dimensional subset of an array. - * - * The slice class represents a one-dimensional subset of an array, - * specified by three parameters: start offset, size, and stride. The - * start offset is the index of the first element of the array that is part - * of the subset. The size is the total number of elements in the subset. - * Stride is the distance between each successive array element to include - * in the subset. - * - * For example, with an array of size 10, and a slice with offset 1, size 3 - * and stride 2, the subset consists of array elements 1, 3, and 5. - */ - class slice - { - public: - /// Construct an empty slice. - slice(); - - /** - * @brief Construct a slice. - * - * @param __o Offset in array of first element. - * @param __d Number of elements in slice. - * @param __s Stride between array elements. - */ - slice(size_t __o, size_t __d, size_t __s); - - /// Return array offset of first slice element. - size_t start() const; - /// Return size of slice. - size_t size() const; - /// Return array stride of slice. - size_t stride() const; - -#if __cpp_impl_three_way_comparison >= 201907L - /// Equality comparison - friend bool operator==(const slice&, const slice&) = default; -#endif - - private: - size_t _M_off; // offset - size_t _M_sz; // size - size_t _M_st; // stride unit - }; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 543. valarray slice default constructor - inline - slice::slice() - : _M_off(0), _M_sz(0), _M_st(0) {} - - inline - slice::slice(size_t __o, size_t __d, size_t __s) - : _M_off(__o), _M_sz(__d), _M_st(__s) {} - - inline size_t - slice::start() const - { return _M_off; } - - inline size_t - slice::size() const - { return _M_sz; } - - inline size_t - slice::stride() const - { return _M_st; } - - /** - * @brief Reference to one-dimensional subset of an array. - * - * A slice_array is a reference to the actual elements of an array - * specified by a slice. The way to get a slice_array is to call - * operator[](slice) on a valarray. The returned slice_array then permits - * carrying operations out on the referenced subset of elements in the - * original valarray. For example, operator+=(valarray) will add values - * to the subset of elements in the underlying valarray this slice_array - * refers to. - * - * @param Tp Element type. - */ - template - class slice_array - { - public: - typedef _Tp value_type; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 253. valarray helper functions are almost entirely useless - - /// Copy constructor. Both slices refer to the same underlying array. - slice_array(const slice_array&); - - /// Assignment operator. Assigns slice elements to corresponding - /// elements of @a a. - slice_array& operator=(const slice_array&); - - /// Assign slice elements to corresponding elements of @a v. - void operator=(const valarray<_Tp>&) const; - /// Multiply slice elements by corresponding elements of @a v. - void operator*=(const valarray<_Tp>&) const; - /// Divide slice elements by corresponding elements of @a v. - void operator/=(const valarray<_Tp>&) const; - /// Modulo slice elements by corresponding elements of @a v. - void operator%=(const valarray<_Tp>&) const; - /// Add corresponding elements of @a v to slice elements. - void operator+=(const valarray<_Tp>&) const; - /// Subtract corresponding elements of @a v from slice elements. - void operator-=(const valarray<_Tp>&) const; - /// Logical xor slice elements with corresponding elements of @a v. - void operator^=(const valarray<_Tp>&) const; - /// Logical and slice elements with corresponding elements of @a v. - void operator&=(const valarray<_Tp>&) const; - /// Logical or slice elements with corresponding elements of @a v. - void operator|=(const valarray<_Tp>&) const; - /// Left shift slice elements by corresponding elements of @a v. - void operator<<=(const valarray<_Tp>&) const; - /// Right shift slice elements by corresponding elements of @a v. - void operator>>=(const valarray<_Tp>&) const; - /// Assign all slice elements to @a t. - void operator=(const _Tp &) const; - // ~slice_array (); - - template - void operator=(const _Expr<_Dom, _Tp>&) const; - template - void operator*=(const _Expr<_Dom, _Tp>&) const; - template - void operator/=(const _Expr<_Dom, _Tp>&) const; - template - void operator%=(const _Expr<_Dom, _Tp>&) const; - template - void operator+=(const _Expr<_Dom, _Tp>&) const; - template - void operator-=(const _Expr<_Dom, _Tp>&) const; - template - void operator^=(const _Expr<_Dom, _Tp>&) const; - template - void operator&=(const _Expr<_Dom, _Tp>&) const; - template - void operator|=(const _Expr<_Dom, _Tp>&) const; - template - void operator<<=(const _Expr<_Dom, _Tp>&) const; - template - void operator>>=(const _Expr<_Dom, _Tp>&) const; - - private: - friend class valarray<_Tp>; - slice_array(_Array<_Tp>, const slice&); - - const size_t _M_sz; - const size_t _M_stride; - const _Array<_Tp> _M_array; - -#if __cplusplus < 201103L - // not implemented - slice_array(); -#else - public: - slice_array() = delete; -#endif - }; - - template - inline - slice_array<_Tp>::slice_array(_Array<_Tp> __a, const slice& __s) - : _M_sz(__s.size()), _M_stride(__s.stride()), - _M_array(__a.begin() + __s.start()) {} - - template - inline - slice_array<_Tp>::slice_array(const slice_array<_Tp>& __a) - : _M_sz(__a._M_sz), _M_stride(__a._M_stride), _M_array(__a._M_array) {} - - // template - // inline slice_array<_Tp>::~slice_array () {} - - template - inline slice_array<_Tp>& - slice_array<_Tp>::operator=(const slice_array<_Tp>& __a) - { - std::__valarray_copy(__a._M_array, __a._M_sz, __a._M_stride, - _M_array, _M_stride); - return *this; - } - - template - inline void - slice_array<_Tp>::operator=(const _Tp& __t) const - { std::__valarray_fill(_M_array, _M_sz, _M_stride, __t); } - - template - inline void - slice_array<_Tp>::operator=(const valarray<_Tp>& __v) const - { std::__valarray_copy(_Array<_Tp>(__v), _M_array, _M_sz, _M_stride); } - - template - template - inline void - slice_array<_Tp>::operator=(const _Expr<_Dom,_Tp>& __e) const - { std::__valarray_copy(__e, _M_sz, _M_array, _M_stride); } - -#undef _DEFINE_VALARRAY_OPERATOR -#define _DEFINE_VALARRAY_OPERATOR(_Op,_Name) \ - template \ - inline void \ - slice_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ - { \ - _Array_augmented_##_Name(_M_array, _M_sz, _M_stride, _Array<_Tp>(__v));\ - } \ - \ - template \ - template \ - inline void \ - slice_array<_Tp>::operator _Op##=(const _Expr<_Dom,_Tp>& __e) const\ - { \ - _Array_augmented_##_Name(_M_array, _M_stride, __e, _M_sz); \ - } - - -_DEFINE_VALARRAY_OPERATOR(*, __multiplies) -_DEFINE_VALARRAY_OPERATOR(/, __divides) -_DEFINE_VALARRAY_OPERATOR(%, __modulus) -_DEFINE_VALARRAY_OPERATOR(+, __plus) -_DEFINE_VALARRAY_OPERATOR(-, __minus) -_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) -_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) -_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) -_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) -_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) - -#undef _DEFINE_VALARRAY_OPERATOR - - // @} group numeric_arrays - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _SLICE_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/std_abs.h b/resources/sources/avr-libstdcpp/include/bits/std_abs.h deleted file mode 100644 index b0451a3ab..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/std_abs.h +++ /dev/null @@ -1,111 +0,0 @@ -// -*- C++ -*- C library enhancements header. - -// Copyright (C) 2016-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/bits/std_abs.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{cmath, cstdlib} - */ - -#ifndef _GLIBCXX_BITS_STD_ABS_H -#define _GLIBCXX_BITS_STD_ABS_H - -#pragma GCC system_header - -#include - -#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS -#include_next -#ifdef __CORRECT_ISO_CPP_MATH_H_PROTO -# include_next -#endif -#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS - -#undef abs - -extern "C++" -{ -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using ::abs; - -#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO - inline long - abs(long __i) { return __builtin_labs(__i); } -#endif - -#ifdef _GLIBCXX_USE_LONG_LONG - inline long long - abs(long long __x) { return __builtin_llabs (__x); } -#endif - -// _GLIBCXX_RESOLVE_LIB_DEFECTS -// 2192. Validity and return type of std::abs(0u) is unclear -// 2294. should declare abs(double) -// 2735. std::abs(short), std::abs(signed char) and others should return int - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR double - abs(double __x) - { return __builtin_fabs(__x); } - - inline _GLIBCXX_CONSTEXPR float - abs(float __x) - { return __builtin_fabsf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - abs(long double __x) - { return __builtin_fabsl(__x); } -#endif - -#if defined(__GLIBCXX_TYPE_INT_N_0) - inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0 - abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; } -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) - inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1 - abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; } -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) - inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2 - abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; } -#endif -#if defined(__GLIBCXX_TYPE_INT_N_3) - inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 - abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; } -#endif - -#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) - inline _GLIBCXX_CONSTEXPR - __float128 - abs(__float128 __x) - { return __x < 0 ? -__x : __x; } -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -} // extern "C"++" - -#endif // _GLIBCXX_BITS_STD_ABS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/std_function.h b/resources/sources/avr-libstdcpp/include/bits/std_function.h deleted file mode 100644 index 4a3848030..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/std_function.h +++ /dev/null @@ -1,728 +0,0 @@ -// Implementation of std::function -*- C++ -*- - -// Copyright (C) 2004-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/bits/std_function.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _GLIBCXX_STD_FUNCTION_H -#define _GLIBCXX_STD_FUNCTION_H 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#if __cpp_rtti -# include -#endif -#include -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * Trait identifying "location-invariant" types, meaning that the - * address of the object (or any of its members) will not escape. - * Trivially copyable types are location-invariant and users can - * specialize this trait for other types. - */ - template - struct __is_location_invariant - : is_trivially_copyable<_Tp>::type - { }; - - class _Undefined_class; - - union _Nocopy_types - { - void* _M_object; - const void* _M_const_object; - void (*_M_function_pointer)(); - void (_Undefined_class::*_M_member_pointer)(); - }; - - union [[gnu::may_alias]] _Any_data - { - void* _M_access() { return &_M_pod_data[0]; } - const void* _M_access() const { return &_M_pod_data[0]; } - - template - _Tp& - _M_access() - { return *static_cast<_Tp*>(_M_access()); } - - template - const _Tp& - _M_access() const - { return *static_cast(_M_access()); } - - _Nocopy_types _M_unused; - char _M_pod_data[sizeof(_Nocopy_types)]; - }; - - enum _Manager_operation - { - __get_type_info, - __get_functor_ptr, - __clone_functor, - __destroy_functor - }; - - template - class function; - - /// Base class of all polymorphic function object wrappers. - class _Function_base - { - public: - static const size_t _M_max_size = sizeof(_Nocopy_types); - static const size_t _M_max_align = __alignof__(_Nocopy_types); - - template - class _Base_manager - { - protected: - static const bool __stored_locally = - (__is_location_invariant<_Functor>::value - && sizeof(_Functor) <= _M_max_size - && __alignof__(_Functor) <= _M_max_align - && (_M_max_align % __alignof__(_Functor) == 0)); - - typedef integral_constant _Local_storage; - - // Retrieve a pointer to the function object - static _Functor* - _M_get_pointer(const _Any_data& __source) - { - if _GLIBCXX17_CONSTEXPR (__stored_locally) - { - const _Functor& __f = __source._M_access<_Functor>(); - return const_cast<_Functor*>(std::__addressof(__f)); - } - else // have stored a pointer - return __source._M_access<_Functor*>(); - } - - // Clone a location-invariant function object that fits within - // an _Any_data structure. - static void - _M_clone(_Any_data& __dest, const _Any_data& __source, true_type) - { - ::new (__dest._M_access()) _Functor(__source._M_access<_Functor>()); - } - - // Clone a function object that is not location-invariant or - // that cannot fit into an _Any_data structure. - static void - _M_clone(_Any_data& __dest, const _Any_data& __source, false_type) - { - __dest._M_access<_Functor*>() = - new _Functor(*__source._M_access()); - } - - // Destroying a location-invariant object may still require - // destruction. - static void - _M_destroy(_Any_data& __victim, true_type) - { - __victim._M_access<_Functor>().~_Functor(); - } - - // Destroying an object located on the heap. - static void - _M_destroy(_Any_data& __victim, false_type) - { - delete __victim._M_access<_Functor*>(); - } - - public: - static bool - _M_manager(_Any_data& __dest, const _Any_data& __source, - _Manager_operation __op) - { - switch (__op) - { -#if __cpp_rtti - case __get_type_info: - __dest._M_access() = &typeid(_Functor); - break; -#endif - case __get_functor_ptr: - __dest._M_access<_Functor*>() = _M_get_pointer(__source); - break; - - case __clone_functor: - _M_clone(__dest, __source, _Local_storage()); - break; - - case __destroy_functor: - _M_destroy(__dest, _Local_storage()); - break; - } - return false; - } - - static void - _M_init_functor(_Any_data& __functor, _Functor&& __f) - { _M_init_functor(__functor, std::move(__f), _Local_storage()); } - - template - static bool - _M_not_empty_function(const function<_Signature>& __f) - { return static_cast(__f); } - - template - static bool - _M_not_empty_function(_Tp* __fp) - { return __fp != nullptr; } - - template - static bool - _M_not_empty_function(_Tp _Class::* __mp) - { return __mp != nullptr; } - - template - static bool - _M_not_empty_function(const _Tp&) - { return true; } - - private: - static void - _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type) - { ::new (__functor._M_access()) _Functor(std::move(__f)); } - - static void - _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type) - { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); } - }; - - _Function_base() : _M_manager(nullptr) { } - - ~_Function_base() - { - if (_M_manager) - _M_manager(_M_functor, _M_functor, __destroy_functor); - } - - bool _M_empty() const { return !_M_manager; } - - typedef bool (*_Manager_type)(_Any_data&, const _Any_data&, - _Manager_operation); - - _Any_data _M_functor; - _Manager_type _M_manager; - }; - - template - class _Function_handler; - - template - class _Function_handler<_Res(_ArgTypes...), _Functor> - : public _Function_base::_Base_manager<_Functor> - { - typedef _Function_base::_Base_manager<_Functor> _Base; - - public: - static bool - _M_manager(_Any_data& __dest, const _Any_data& __source, - _Manager_operation __op) - { - switch (__op) - { -#if __cpp_rtti - case __get_type_info: - __dest._M_access() = &typeid(_Functor); - break; -#endif - case __get_functor_ptr: - __dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source); - break; - - default: - _Base::_M_manager(__dest, __source, __op); - } - return false; - } - - static _Res - _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) - { - return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor), - std::forward<_ArgTypes>(__args)...); - } - }; - - /** - * @brief Primary class template for std::function. - * @ingroup functors - * - * Polymorphic function wrapper. - */ - template - class function<_Res(_ArgTypes...)> - : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, - private _Function_base - { - template> - struct _Callable - : __is_invocable_impl<_Res2, _Res>::type - { }; - - // Used so the return type convertibility checks aren't done when - // performing overload resolution for copy construction/assignment. - template - struct _Callable : false_type { }; - - template - using _Requires = typename enable_if<_Cond::value, _Tp>::type; - - public: - typedef _Res result_type; - - // [3.7.2.1] construct/copy/destroy - - /** - * @brief Default construct creates an empty function call wrapper. - * @post @c !(bool)*this - */ - function() noexcept - : _Function_base() { } - - /** - * @brief Creates an empty function call wrapper. - * @post @c !(bool)*this - */ - function(nullptr_t) noexcept - : _Function_base() { } - - /** - * @brief %Function copy constructor. - * @param __x A %function object with identical call signature. - * @post @c bool(*this) == bool(__x) - * - * The newly-created %function contains a copy of the target of @a - * __x (if it has one). - */ - function(const function& __x); - - /** - * @brief %Function move constructor. - * @param __x A %function object rvalue with identical call signature. - * - * The newly-created %function contains the target of @a __x - * (if it has one). - */ - function(function&& __x) noexcept : _Function_base() - { - __x.swap(*this); - } - - /** - * @brief Builds a %function that targets a copy of the incoming - * function object. - * @param __f A %function object that is callable with parameters of - * type @c T1, @c T2, ..., @c TN and returns a value convertible - * to @c Res. - * - * The newly-created %function object will target a copy of - * @a __f. If @a __f is @c reference_wrapper, then this function - * object will contain a reference to the function object @c - * __f.get(). If @a __f is a NULL function pointer or NULL - * pointer-to-member, the newly-created object will be empty. - * - * If @a __f is a non-NULL function pointer or an object of type @c - * reference_wrapper, this function will not throw. - */ - template>, void>, - typename = _Requires<_Callable<_Functor>, void>> - function(_Functor); - - /** - * @brief %Function assignment operator. - * @param __x A %function with identical call signature. - * @post @c (bool)*this == (bool)x - * @returns @c *this - * - * The target of @a __x is copied to @c *this. If @a __x has no - * target, then @c *this will be empty. - * - * If @a __x targets a function pointer or a reference to a function - * object, then this operation will not throw an %exception. - */ - function& - operator=(const function& __x) - { - function(__x).swap(*this); - return *this; - } - - /** - * @brief %Function move-assignment operator. - * @param __x A %function rvalue with identical call signature. - * @returns @c *this - * - * The target of @a __x is moved to @c *this. If @a __x has no - * target, then @c *this will be empty. - * - * If @a __x targets a function pointer or a reference to a function - * object, then this operation will not throw an %exception. - */ - function& - operator=(function&& __x) noexcept - { - function(std::move(__x)).swap(*this); - return *this; - } - - /** - * @brief %Function assignment to zero. - * @post @c !(bool)*this - * @returns @c *this - * - * The target of @c *this is deallocated, leaving it empty. - */ - function& - operator=(nullptr_t) noexcept - { - if (_M_manager) - { - _M_manager(_M_functor, _M_functor, __destroy_functor); - _M_manager = nullptr; - _M_invoker = nullptr; - } - return *this; - } - - /** - * @brief %Function assignment to a new target. - * @param __f A %function object that is callable with parameters of - * type @c T1, @c T2, ..., @c TN and returns a value convertible - * to @c Res. - * @return @c *this - * - * This %function object wrapper will target a copy of @a - * __f. If @a __f is @c reference_wrapper, then this function - * object will contain a reference to the function object @c - * __f.get(). If @a __f is a NULL function pointer or NULL - * pointer-to-member, @c this object will be empty. - * - * If @a __f is a non-NULL function pointer or an object of type @c - * reference_wrapper, this function will not throw. - */ - template - _Requires<_Callable::type>, function&> - operator=(_Functor&& __f) - { - function(std::forward<_Functor>(__f)).swap(*this); - return *this; - } - - /// @overload - template - function& - operator=(reference_wrapper<_Functor> __f) noexcept - { - function(__f).swap(*this); - return *this; - } - - // [3.7.2.2] function modifiers - - /** - * @brief Swap the targets of two %function objects. - * @param __x A %function with identical call signature. - * - * Swap the targets of @c this function object and @a __f. This - * function will not throw an %exception. - */ - void swap(function& __x) noexcept - { - std::swap(_M_functor, __x._M_functor); - std::swap(_M_manager, __x._M_manager); - std::swap(_M_invoker, __x._M_invoker); - } - - // [3.7.2.3] function capacity - - /** - * @brief Determine if the %function wrapper has a target. - * - * @return @c true when this %function object contains a target, - * or @c false when it is empty. - * - * This function will not throw an %exception. - */ - explicit operator bool() const noexcept - { return !_M_empty(); } - - // [3.7.2.4] function invocation - - /** - * @brief Invokes the function targeted by @c *this. - * @returns the result of the target. - * @throws bad_function_call when @c !(bool)*this - * - * The function call operator invokes the target function object - * stored by @c this. - */ - _Res operator()(_ArgTypes... __args) const; - -#if __cpp_rtti - // [3.7.2.5] function target access - /** - * @brief Determine the type of the target of this function object - * wrapper. - * - * @returns the type identifier of the target function object, or - * @c typeid(void) if @c !(bool)*this. - * - * This function will not throw an %exception. - */ - const type_info& target_type() const noexcept; - - /** - * @brief Access the stored target function object. - * - * @return Returns a pointer to the stored target function object, - * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL - * pointer. - * - * This function does not throw exceptions. - * - * @{ - */ - template _Functor* target() noexcept; - - template const _Functor* target() const noexcept; - // @} -#endif - - private: - using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...); - _Invoker_type _M_invoker; - }; - -#if __cpp_deduction_guides >= 201606 - template - struct __function_guide_helper - { }; - - template - struct __function_guide_helper< - _Res (_Tp::*) (_Args...) noexcept(_Nx) - > - { using type = _Res(_Args...); }; - - template - struct __function_guide_helper< - _Res (_Tp::*) (_Args...) & noexcept(_Nx) - > - { using type = _Res(_Args...); }; - - template - struct __function_guide_helper< - _Res (_Tp::*) (_Args...) const noexcept(_Nx) - > - { using type = _Res(_Args...); }; - - template - struct __function_guide_helper< - _Res (_Tp::*) (_Args...) const & noexcept(_Nx) - > - { using type = _Res(_Args...); }; - - template - function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>; - - template::type> - function(_Functor) -> function<_Signature>; -#endif - - // Out-of-line member definitions. - template - function<_Res(_ArgTypes...)>:: - function(const function& __x) - : _Function_base() - { - if (static_cast(__x)) - { - __x._M_manager(_M_functor, __x._M_functor, __clone_functor); - _M_invoker = __x._M_invoker; - _M_manager = __x._M_manager; - } - } - - template - template - function<_Res(_ArgTypes...)>:: - function(_Functor __f) - : _Function_base() - { - typedef _Function_handler<_Res(_ArgTypes...), _Functor> _My_handler; - - if (_My_handler::_M_not_empty_function(__f)) - { - _My_handler::_M_init_functor(_M_functor, std::move(__f)); - _M_invoker = &_My_handler::_M_invoke; - _M_manager = &_My_handler::_M_manager; - } - } - - template - _Res - function<_Res(_ArgTypes...)>:: - operator()(_ArgTypes... __args) const - { - if (_M_empty()) - __throw_bad_function_call(); - return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...); - } - -#if __cpp_rtti - template - const type_info& - function<_Res(_ArgTypes...)>:: - target_type() const noexcept - { - if (_M_manager) - { - _Any_data __typeinfo_result; - _M_manager(__typeinfo_result, _M_functor, __get_type_info); - return *__typeinfo_result._M_access(); - } - else - return typeid(void); - } - - template - template - _Functor* - function<_Res(_ArgTypes...)>:: - target() noexcept - { - const function* __const_this = this; - const _Functor* __func = __const_this->template target<_Functor>(); - return const_cast<_Functor*>(__func); - } - - template - template - const _Functor* - function<_Res(_ArgTypes...)>:: - target() const noexcept - { - if (typeid(_Functor) == target_type() && _M_manager) - { - _Any_data __ptr; - _M_manager(__ptr, _M_functor, __get_functor_ptr); - return __ptr._M_access(); - } - else - return nullptr; - } -#endif - - // [20.7.15.2.6] null pointer comparisons - - /** - * @brief Compares a polymorphic function object wrapper against 0 - * (the NULL pointer). - * @returns @c true if the wrapper has no target, @c false otherwise - * - * This function will not throw an %exception. - */ - template - inline bool - operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept - { return !static_cast(__f); } - -#if __cpp_impl_three_way_comparison < 201907L - /// @overload - template - inline bool - operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept - { return !static_cast(__f); } - - /** - * @brief Compares a polymorphic function object wrapper against 0 - * (the NULL pointer). - * @returns @c false if the wrapper has no target, @c true otherwise - * - * This function will not throw an %exception. - */ - template - inline bool - operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept - { return static_cast(__f); } - - /// @overload - template - inline bool - operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept - { return static_cast(__f); } -#endif - - // [20.7.15.2.7] specialized algorithms - - /** - * @brief Swap the targets of two polymorphic function object wrappers. - * - * This function will not throw an %exception. - */ - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps - template - inline void - swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept - { __x.swap(__y); } - -#if __cplusplus >= 201703L - namespace __detail::__variant - { - template struct _Never_valueless_alt; // see - - // Provide the strong exception-safety guarantee when emplacing a - // function into a variant. - template - struct _Never_valueless_alt> - : std::true_type - { }; - } // namespace __detail::__variant -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++11 -#endif // _GLIBCXX_STD_FUNCTION_H diff --git a/resources/sources/avr-libstdcpp/include/bits/std_mutex.h b/resources/sources/avr-libstdcpp/include/bits/std_mutex.h deleted file mode 100644 index aef12b679..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/std_mutex.h +++ /dev/null @@ -1,176 +0,0 @@ -// std::mutex implementation -*- C++ -*- - -// Copyright (C) 2003-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/std_mutex.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{mutex} - */ - -#ifndef _GLIBCXX_MUTEX_H -#define _GLIBCXX_MUTEX_H 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup mutexes Mutexes - * @ingroup concurrency - * - * Classes for mutex support. - * @{ - */ - -#ifdef _GLIBCXX_HAS_GTHREADS - // Common base class for std::mutex and std::timed_mutex - class __mutex_base - { - protected: - typedef __gthread_mutex_t __native_type; - -#ifdef __GTHREAD_MUTEX_INIT - __native_type _M_mutex = __GTHREAD_MUTEX_INIT; - - constexpr __mutex_base() noexcept = default; -#else - __native_type _M_mutex; - - __mutex_base() noexcept - { - // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) - __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); - } - - ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } -#endif - - __mutex_base(const __mutex_base&) = delete; - __mutex_base& operator=(const __mutex_base&) = delete; - }; - - /// The standard mutex type. - class mutex : private __mutex_base - { - public: - typedef __native_type* native_handle_type; - -#ifdef __GTHREAD_MUTEX_INIT - constexpr -#endif - mutex() noexcept = default; - ~mutex() = default; - - mutex(const mutex&) = delete; - mutex& operator=(const mutex&) = delete; - - void - lock() - { - int __e = __gthread_mutex_lock(&_M_mutex); - - // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) - if (__e) - __throw_system_error(__e); - } - - bool - try_lock() noexcept - { - // XXX EINVAL, EAGAIN, EBUSY - return !__gthread_mutex_trylock(&_M_mutex); - } - - void - unlock() - { - // XXX EINVAL, EAGAIN, EPERM - __gthread_mutex_unlock(&_M_mutex); - } - - native_handle_type - native_handle() noexcept - { return &_M_mutex; } - }; - -#endif // _GLIBCXX_HAS_GTHREADS - - /// Do not acquire ownership of the mutex. - struct defer_lock_t { explicit defer_lock_t() = default; }; - - /// Try to acquire ownership of the mutex without blocking. - struct try_to_lock_t { explicit try_to_lock_t() = default; }; - - /// Assume the calling thread has already obtained mutex ownership - /// and manage it. - struct adopt_lock_t { explicit adopt_lock_t() = default; }; - - /// Tag used to prevent a scoped lock from acquiring ownership of a mutex. - _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { }; - - /// Tag used to prevent a scoped lock from blocking if a mutex is locked. - _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { }; - - /// Tag used to make a scoped lock take ownership of a locked mutex. - _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { }; - - /** @brief A simple scoped lock type. - * - * A lock_guard controls mutex ownership within a scope, releasing - * ownership in the destructor. - */ - template - class lock_guard - { - public: - typedef _Mutex mutex_type; - - explicit lock_guard(mutex_type& __m) : _M_device(__m) - { _M_device.lock(); } - - lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m) - { } // calling thread owns mutex - - ~lock_guard() - { _M_device.unlock(); } - - lock_guard(const lock_guard&) = delete; - lock_guard& operator=(const lock_guard&) = delete; - - private: - mutex_type& _M_device; - }; - - // @} group mutexes -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -#endif // C++11 -#endif // _GLIBCXX_MUTEX_H diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_algo.h b/resources/sources/avr-libstdcpp/include/bits/stl_algo.h deleted file mode 100644 index 2eb637e85..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_algo.h +++ /dev/null @@ -1,5884 +0,0 @@ -// Algorithm implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_algo.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{algorithm} - */ - -#ifndef _STL_ALGO_H -#define _STL_ALGO_H 1 - -#include // for rand -#include -#include -#include // for _Temporary_buffer -#include - -#if __cplusplus >= 201103L -#include -#endif - -// See concept_check.h for the __glibcxx_*_requires macros. - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /// Swaps the median value of *__a, *__b and *__c under __comp to *__result - template - _GLIBCXX20_CONSTEXPR - void - __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b, - _Iterator __c, _Compare __comp) - { - if (__comp(__a, __b)) - { - if (__comp(__b, __c)) - std::iter_swap(__result, __b); - else if (__comp(__a, __c)) - std::iter_swap(__result, __c); - else - std::iter_swap(__result, __a); - } - else if (__comp(__a, __c)) - std::iter_swap(__result, __a); - else if (__comp(__b, __c)) - std::iter_swap(__result, __c); - else - std::iter_swap(__result, __b); - } - - /// Provided for stable_partition to use. - template - _GLIBCXX20_CONSTEXPR - inline _InputIterator - __find_if_not(_InputIterator __first, _InputIterator __last, - _Predicate __pred) - { - return std::__find_if(__first, __last, - __gnu_cxx::__ops::__negate(__pred), - std::__iterator_category(__first)); - } - - /// Like find_if_not(), but uses and updates a count of the - /// remaining range length instead of comparing against an end - /// iterator. - template - _GLIBCXX20_CONSTEXPR - _InputIterator - __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred) - { - for (; __len; --__len, (void) ++__first) - if (!__pred(__first)) - break; - return __first; - } - - // set_difference - // set_intersection - // set_symmetric_difference - // set_union - // for_each - // find - // find_if - // find_first_of - // adjacent_find - // count - // count_if - // search - - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator1 - __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, - _BinaryPredicate __predicate) - { - // Test for empty ranges - if (__first1 == __last1 || __first2 == __last2) - return __first1; - - // Test for a pattern of length 1. - _ForwardIterator2 __p1(__first2); - if (++__p1 == __last2) - return std::__find_if(__first1, __last1, - __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); - - // General case. - _ForwardIterator1 __current = __first1; - - for (;;) - { - __first1 = - std::__find_if(__first1, __last1, - __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); - - if (__first1 == __last1) - return __last1; - - _ForwardIterator2 __p = __p1; - __current = __first1; - if (++__current == __last1) - return __last1; - - while (__predicate(__current, __p)) - { - if (++__p == __last2) - return __first1; - if (++__current == __last1) - return __last1; - } - ++__first1; - } - return __first1; - } - - // search_n - - /** - * This is an helper function for search_n overloaded for forward iterators. - */ - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __search_n_aux(_ForwardIterator __first, _ForwardIterator __last, - _Integer __count, _UnaryPredicate __unary_pred, - std::forward_iterator_tag) - { - __first = std::__find_if(__first, __last, __unary_pred); - while (__first != __last) - { - typename iterator_traits<_ForwardIterator>::difference_type - __n = __count; - _ForwardIterator __i = __first; - ++__i; - while (__i != __last && __n != 1 && __unary_pred(__i)) - { - ++__i; - --__n; - } - if (__n == 1) - return __first; - if (__i == __last) - return __last; - __first = std::__find_if(++__i, __last, __unary_pred); - } - return __last; - } - - /** - * This is an helper function for search_n overloaded for random access - * iterators. - */ - template - _GLIBCXX20_CONSTEXPR - _RandomAccessIter - __search_n_aux(_RandomAccessIter __first, _RandomAccessIter __last, - _Integer __count, _UnaryPredicate __unary_pred, - std::random_access_iterator_tag) - { - typedef typename std::iterator_traits<_RandomAccessIter>::difference_type - _DistanceType; - - _DistanceType __tailSize = __last - __first; - _DistanceType __remainder = __count; - - while (__remainder <= __tailSize) // the main loop... - { - __first += __remainder; - __tailSize -= __remainder; - // __first here is always pointing to one past the last element of - // next possible match. - _RandomAccessIter __backTrack = __first; - while (__unary_pred(--__backTrack)) - { - if (--__remainder == 0) - return (__first - __count); // Success - } - __remainder = __count + 1 - (__first - __backTrack); - } - return __last; // Failure - } - - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __search_n(_ForwardIterator __first, _ForwardIterator __last, - _Integer __count, - _UnaryPredicate __unary_pred) - { - if (__count <= 0) - return __first; - - if (__count == 1) - return std::__find_if(__first, __last, __unary_pred); - - return std::__search_n_aux(__first, __last, __count, __unary_pred, - std::__iterator_category(__first)); - } - - // find_end for forward iterators. - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator1 - __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, - forward_iterator_tag, forward_iterator_tag, - _BinaryPredicate __comp) - { - if (__first2 == __last2) - return __last1; - - _ForwardIterator1 __result = __last1; - while (1) - { - _ForwardIterator1 __new_result - = std::__search(__first1, __last1, __first2, __last2, __comp); - if (__new_result == __last1) - return __result; - else - { - __result = __new_result; - __first1 = __new_result; - ++__first1; - } - } - } - - // find_end for bidirectional iterators (much faster). - template - _GLIBCXX20_CONSTEXPR - _BidirectionalIterator1 - __find_end(_BidirectionalIterator1 __first1, - _BidirectionalIterator1 __last1, - _BidirectionalIterator2 __first2, - _BidirectionalIterator2 __last2, - bidirectional_iterator_tag, bidirectional_iterator_tag, - _BinaryPredicate __comp) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator1>) - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator2>) - - typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1; - typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2; - - _RevIterator1 __rlast1(__first1); - _RevIterator2 __rlast2(__first2); - _RevIterator1 __rresult = std::__search(_RevIterator1(__last1), __rlast1, - _RevIterator2(__last2), __rlast2, - __comp); - - if (__rresult == __rlast1) - return __last1; - else - { - _BidirectionalIterator1 __result = __rresult.base(); - std::advance(__result, -std::distance(__first2, __last2)); - return __result; - } - } - - /** - * @brief Find last matching subsequence in a sequence. - * @ingroup non_mutating_algorithms - * @param __first1 Start of range to search. - * @param __last1 End of range to search. - * @param __first2 Start of sequence to match. - * @param __last2 End of sequence to match. - * @return The last iterator @c i in the range - * @p [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == - * @p *(__first2+N) for each @c N in the range @p - * [0,__last2-__first2), or @p __last1 if no such iterator exists. - * - * Searches the range @p [__first1,__last1) for a sub-sequence that - * compares equal value-by-value with the sequence given by @p - * [__first2,__last2) and returns an iterator to the __first - * element of the sub-sequence, or @p __last1 if the sub-sequence - * is not found. The sub-sequence will be the last such - * subsequence contained in [__first1,__last1). - * - * Because the sub-sequence must lie completely within the range @p - * [__first1,__last1) it must start at a position less than @p - * __last1-(__last2-__first2) where @p __last2-__first2 is the - * length of the sub-sequence. This means that the returned - * iterator @c i will be in the range @p - * [__first1,__last1-(__last2-__first2)) - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator1 - find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_ForwardIterator1>::value_type, - typename iterator_traits<_ForwardIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return std::__find_end(__first1, __last1, __first2, __last2, - std::__iterator_category(__first1), - std::__iterator_category(__first2), - __gnu_cxx::__ops::__iter_equal_to_iter()); - } - - /** - * @brief Find last matching subsequence in a sequence using a predicate. - * @ingroup non_mutating_algorithms - * @param __first1 Start of range to search. - * @param __last1 End of range to search. - * @param __first2 Start of sequence to match. - * @param __last2 End of sequence to match. - * @param __comp The predicate to use. - * @return The last iterator @c i in the range @p - * [__first1,__last1-(__last2-__first2)) such that @c - * predicate(*(i+N), @p (__first2+N)) is true for each @c N in the - * range @p [0,__last2-__first2), or @p __last1 if no such iterator - * exists. - * - * Searches the range @p [__first1,__last1) for a sub-sequence that - * compares equal value-by-value with the sequence given by @p - * [__first2,__last2) using comp as a predicate and returns an - * iterator to the first element of the sub-sequence, or @p __last1 - * if the sub-sequence is not found. The sub-sequence will be the - * last such subsequence contained in [__first,__last1). - * - * Because the sub-sequence must lie completely within the range @p - * [__first1,__last1) it must start at a position less than @p - * __last1-(__last2-__first2) where @p __last2-__first2 is the - * length of the sub-sequence. This means that the returned - * iterator @c i will be in the range @p - * [__first1,__last1-(__last2-__first2)) - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator1 - find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, - _BinaryPredicate __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator1>::value_type, - typename iterator_traits<_ForwardIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return std::__find_end(__first1, __last1, __first2, __last2, - std::__iterator_category(__first1), - std::__iterator_category(__first2), - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - -#if __cplusplus >= 201103L - /** - * @brief Checks that a predicate is true for all the elements - * of a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __pred A predicate. - * @return True if the check is true, false otherwise. - * - * Returns true if @p __pred is true for each element in the range - * @p [__first,__last), and false otherwise. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) - { return __last == std::find_if_not(__first, __last, __pred); } - - /** - * @brief Checks that a predicate is false for all the elements - * of a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __pred A predicate. - * @return True if the check is true, false otherwise. - * - * Returns true if @p __pred is false for each element in the range - * @p [__first,__last), and false otherwise. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) - { return __last == _GLIBCXX_STD_A::find_if(__first, __last, __pred); } - - /** - * @brief Checks that a predicate is true for at least one element - * of a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __pred A predicate. - * @return True if the check is true, false otherwise. - * - * Returns true if an element exists in the range @p - * [__first,__last) such that @p __pred is true, and false - * otherwise. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) - { return !std::none_of(__first, __last, __pred); } - - /** - * @brief Find the first element in a sequence for which a - * predicate is false. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __pred A predicate. - * @return The first iterator @c i in the range @p [__first,__last) - * such that @p __pred(*i) is false, or @p __last if no such iterator exists. - */ - template - _GLIBCXX20_CONSTEXPR - inline _InputIterator - find_if_not(_InputIterator __first, _InputIterator __last, - _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - return std::__find_if_not(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); - } - - /** - * @brief Checks whether the sequence is partitioned. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __pred A predicate. - * @return True if the range @p [__first,__last) is partioned by @p __pred, - * i.e. if all elements that satisfy @p __pred appear before those that - * do not. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_partitioned(_InputIterator __first, _InputIterator __last, - _Predicate __pred) - { - __first = std::find_if_not(__first, __last, __pred); - if (__first == __last) - return true; - ++__first; - return std::none_of(__first, __last, __pred); - } - - /** - * @brief Find the partition point of a partitioned range. - * @ingroup mutating_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __pred A predicate. - * @return An iterator @p mid such that @p all_of(__first, mid, __pred) - * and @p none_of(mid, __last, __pred) are both true. - */ - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - partition_point(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_ForwardIterator>::value_type>) - - // A specific debug-mode test will be necessary... - __glibcxx_requires_valid_range(__first, __last); - - typedef typename iterator_traits<_ForwardIterator>::difference_type - _DistanceType; - - _DistanceType __len = std::distance(__first, __last); - - while (__len > 0) - { - _DistanceType __half = __len >> 1; - _ForwardIterator __middle = __first; - std::advance(__middle, __half); - if (__pred(*__middle)) - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - else - __len = __half; - } - return __first; - } -#endif - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __remove_copy_if(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _Predicate __pred) - { - for (; __first != __last; ++__first) - if (!__pred(__first)) - { - *__result = *__first; - ++__result; - } - return __result; - } - - /** - * @brief Copy a sequence, removing elements of a given value. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @param __value The value to be removed. - * @return An iterator designating the end of the resulting sequence. - * - * Copies each element in the range @p [__first,__last) not equal - * to @p __value to the range beginning at @p __result. - * remove_copy() is stable, so the relative order of elements that - * are copied is unchanged. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - remove_copy(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, const _Tp& __value) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__remove_copy_if(__first, __last, __result, - __gnu_cxx::__ops::__iter_equals_val(__value)); - } - - /** - * @brief Copy a sequence, removing elements for which a predicate is true. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @param __pred A predicate. - * @return An iterator designating the end of the resulting sequence. - * - * Copies each element in the range @p [__first,__last) for which - * @p __pred returns false to the range beginning at @p __result. - * - * remove_copy_if() is stable, so the relative order of elements that are - * copied is unchanged. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - remove_copy_if(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__remove_copy_if(__first, __last, __result, - __gnu_cxx::__ops::__pred_iter(__pred)); - } - -#if __cplusplus >= 201103L - /** - * @brief Copy the elements of a sequence for which a predicate is true. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @param __pred A predicate. - * @return An iterator designating the end of the resulting sequence. - * - * Copies each element in the range @p [__first,__last) for which - * @p __pred returns true to the range beginning at @p __result. - * - * copy_if() is stable, so the relative order of elements that are - * copied is unchanged. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - copy_if(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first) - if (__pred(*__first)) - { - *__result = *__first; - ++__result; - } - return __result; - } - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result) - { - if (__n > 0) - { - while (true) - { - *__result = *__first; - ++__result; - if (--__n > 0) - ++__first; - else - break; - } - } - return __result; - } - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __copy_n(_InputIterator __first, _Size __n, - _OutputIterator __result, input_iterator_tag) - { - return std::__niter_wrap(__result, - __copy_n_a(__first, __n, - std::__niter_base(__result))); - } - - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - __copy_n(_RandomAccessIterator __first, _Size __n, - _OutputIterator __result, random_access_iterator_tag) - { return std::copy(__first, __first + __n, __result); } - - /** - * @brief Copies the range [first,first+n) into [result,result+n). - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __n The number of elements to copy. - * @param __result An output iterator. - * @return result+n. - * - * This inline function will boil down to a call to @c memmove whenever - * possible. Failing that, if random access iterators are passed, then the - * loop count will be known (and therefore a candidate for compiler - * optimizations such as unrolling). - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_can_increment(__first, __n); - __glibcxx_requires_can_increment(__result, __n); - - return std::__copy_n(__first, __n, __result, - std::__iterator_category(__first)); - } - - /** - * @brief Copy the elements of a sequence to separate output sequences - * depending on the truth value of a predicate. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __out_true An output iterator. - * @param __out_false An output iterator. - * @param __pred A predicate. - * @return A pair designating the ends of the resulting sequences. - * - * Copies each element in the range @p [__first,__last) for which - * @p __pred returns true to the range beginning at @p out_true - * and each element for which @p __pred returns false to @p __out_false. - */ - template - _GLIBCXX20_CONSTEXPR - pair<_OutputIterator1, _OutputIterator2> - partition_copy(_InputIterator __first, _InputIterator __last, - _OutputIterator1 __out_true, _OutputIterator2 __out_false, - _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator1, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator2, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first) - if (__pred(*__first)) - { - *__out_true = *__first; - ++__out_true; - } - else - { - *__out_false = *__first; - ++__out_false; - } - - return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); - } -#endif // C++11 - - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __remove_if(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred) - { - __first = std::__find_if(__first, __last, __pred); - if (__first == __last) - return __first; - _ForwardIterator __result = __first; - ++__first; - for (; __first != __last; ++__first) - if (!__pred(__first)) - { - *__result = _GLIBCXX_MOVE(*__first); - ++__result; - } - return __result; - } - - /** - * @brief Remove elements from a sequence. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __value The value to be removed. - * @return An iterator designating the end of the resulting sequence. - * - * All elements equal to @p __value are removed from the range - * @p [__first,__last). - * - * remove() is stable, so the relative order of elements that are - * not removed is unchanged. - * - * Elements between the end of the resulting sequence and @p __last - * are still present, but their value is unspecified. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - remove(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __value) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_ForwardIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__remove_if(__first, __last, - __gnu_cxx::__ops::__iter_equals_val(__value)); - } - - /** - * @brief Remove elements from a sequence using a predicate. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __pred A predicate. - * @return An iterator designating the end of the resulting sequence. - * - * All elements for which @p __pred returns true are removed from the range - * @p [__first,__last). - * - * remove_if() is stable, so the relative order of elements that are - * not removed is unchanged. - * - * Elements between the end of the resulting sequence and @p __last - * are still present, but their value is unspecified. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - remove_if(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__remove_if(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); - } - - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __adjacent_find(_ForwardIterator __first, _ForwardIterator __last, - _BinaryPredicate __binary_pred) - { - if (__first == __last) - return __last; - _ForwardIterator __next = __first; - while (++__next != __last) - { - if (__binary_pred(__first, __next)) - return __first; - __first = __next; - } - return __last; - } - - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __unique(_ForwardIterator __first, _ForwardIterator __last, - _BinaryPredicate __binary_pred) - { - // Skip the beginning, if already unique. - __first = std::__adjacent_find(__first, __last, __binary_pred); - if (__first == __last) - return __last; - - // Do the real copy work. - _ForwardIterator __dest = __first; - ++__first; - while (++__first != __last) - if (!__binary_pred(__dest, __first)) - *++__dest = _GLIBCXX_MOVE(*__first); - return ++__dest; - } - - /** - * @brief Remove consecutive duplicate values from a sequence. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @return An iterator designating the end of the resulting sequence. - * - * Removes all but the first element from each group of consecutive - * values that compare equal. - * unique() is stable, so the relative order of elements that are - * not removed is unchanged. - * Elements between the end of the resulting sequence and @p __last - * are still present, but their value is unspecified. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - unique(_ForwardIterator __first, _ForwardIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_EqualityComparableConcept< - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__unique(__first, __last, - __gnu_cxx::__ops::__iter_equal_to_iter()); - } - - /** - * @brief Remove consecutive values from a sequence using a predicate. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __binary_pred A binary predicate. - * @return An iterator designating the end of the resulting sequence. - * - * Removes all but the first element from each group of consecutive - * values for which @p __binary_pred returns true. - * unique() is stable, so the relative order of elements that are - * not removed is unchanged. - * Elements between the end of the resulting sequence and @p __last - * are still present, but their value is unspecified. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - unique(_ForwardIterator __first, _ForwardIterator __last, - _BinaryPredicate __binary_pred) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__unique(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); - } - - /** - * This is an uglified - * unique_copy(_InputIterator, _InputIterator, _OutputIterator, - * _BinaryPredicate) - * overloaded for forward iterators and output iterator as result. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __unique_copy(_ForwardIterator __first, _ForwardIterator __last, - _OutputIterator __result, _BinaryPredicate __binary_pred, - forward_iterator_tag, output_iterator_tag) - { - // concept requirements -- iterators already checked - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - - _ForwardIterator __next = __first; - *__result = *__first; - while (++__next != __last) - if (!__binary_pred(__first, __next)) - { - __first = __next; - *++__result = *__first; - } - return ++__result; - } - - /** - * This is an uglified - * unique_copy(_InputIterator, _InputIterator, _OutputIterator, - * _BinaryPredicate) - * overloaded for input iterators and output iterator as result. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __unique_copy(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _BinaryPredicate __binary_pred, - input_iterator_tag, output_iterator_tag) - { - // concept requirements -- iterators already checked - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_InputIterator>::value_type, - typename iterator_traits<_InputIterator>::value_type>) - - typename iterator_traits<_InputIterator>::value_type __value = *__first; - __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred)) - __rebound_pred - = __gnu_cxx::__ops::__iter_comp_val(__binary_pred); - *__result = __value; - while (++__first != __last) - if (!__rebound_pred(__first, __value)) - { - __value = *__first; - *++__result = __value; - } - return ++__result; - } - - /** - * This is an uglified - * unique_copy(_InputIterator, _InputIterator, _OutputIterator, - * _BinaryPredicate) - * overloaded for input iterators and forward iterator as result. - */ - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __unique_copy(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result, _BinaryPredicate __binary_pred, - input_iterator_tag, forward_iterator_tag) - { - // concept requirements -- iterators already checked - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_InputIterator>::value_type>) - *__result = *__first; - while (++__first != __last) - if (!__binary_pred(__result, __first)) - *++__result = *__first; - return ++__result; - } - - /** - * This is an uglified reverse(_BidirectionalIterator, - * _BidirectionalIterator) - * overloaded for bidirectional iterators. - */ - template - _GLIBCXX20_CONSTEXPR - void - __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, - bidirectional_iterator_tag) - { - while (true) - if (__first == __last || __first == --__last) - return; - else - { - std::iter_swap(__first, __last); - ++__first; - } - } - - /** - * This is an uglified reverse(_BidirectionalIterator, - * _BidirectionalIterator) - * overloaded for random access iterators. - */ - template - _GLIBCXX20_CONSTEXPR - void - __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, - random_access_iterator_tag) - { - if (__first == __last) - return; - --__last; - while (__first < __last) - { - std::iter_swap(__first, __last); - ++__first; - --__last; - } - } - - /** - * @brief Reverse a sequence. - * @ingroup mutating_algorithms - * @param __first A bidirectional iterator. - * @param __last A bidirectional iterator. - * @return reverse() returns no value. - * - * Reverses the order of the elements in the range @p [__first,__last), - * so that the first element becomes the last etc. - * For every @c i such that @p 0<=i<=(__last-__first)/2), @p reverse() - * swaps @p *(__first+i) and @p *(__last-(i+1)) - */ - template - _GLIBCXX20_CONSTEXPR - inline void - reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< - _BidirectionalIterator>) - __glibcxx_requires_valid_range(__first, __last); - std::__reverse(__first, __last, std::__iterator_category(__first)); - } - - /** - * @brief Copy a sequence, reversing its elements. - * @ingroup mutating_algorithms - * @param __first A bidirectional iterator. - * @param __last A bidirectional iterator. - * @param __result An output iterator. - * @return An iterator designating the end of the resulting sequence. - * - * Copies the elements in the range @p [__first,__last) to the - * range @p [__result,__result+(__last-__first)) such that the - * order of the elements is reversed. For every @c i such that @p - * 0<=i<=(__last-__first), @p reverse_copy() performs the - * assignment @p *(__result+(__last-__first)-1-i) = *(__first+i). - * The ranges @p [__first,__last) and @p - * [__result,__result+(__last-__first)) must not overlap. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, - _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_BidirectionalIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - while (__first != __last) - { - --__last; - *__result = *__last; - ++__result; - } - return __result; - } - - /** - * This is a helper function for the rotate algorithm specialized on RAIs. - * It returns the greatest common divisor of two integer values. - */ - template - _GLIBCXX20_CONSTEXPR - _EuclideanRingElement - __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n) - { - while (__n != 0) - { - _EuclideanRingElement __t = __m % __n; - __m = __n; - __n = __t; - } - return __m; - } - - inline namespace _V2 - { - - /// This is a helper function for the rotate algorithm. - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __rotate(_ForwardIterator __first, - _ForwardIterator __middle, - _ForwardIterator __last, - forward_iterator_tag) - { - if (__first == __middle) - return __last; - else if (__last == __middle) - return __first; - - _ForwardIterator __first2 = __middle; - do - { - std::iter_swap(__first, __first2); - ++__first; - ++__first2; - if (__first == __middle) - __middle = __first2; - } - while (__first2 != __last); - - _ForwardIterator __ret = __first; - - __first2 = __middle; - - while (__first2 != __last) - { - std::iter_swap(__first, __first2); - ++__first; - ++__first2; - if (__first == __middle) - __middle = __first2; - else if (__first2 == __last) - __first2 = __middle; - } - return __ret; - } - - /// This is a helper function for the rotate algorithm. - template - _GLIBCXX20_CONSTEXPR - _BidirectionalIterator - __rotate(_BidirectionalIterator __first, - _BidirectionalIterator __middle, - _BidirectionalIterator __last, - bidirectional_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< - _BidirectionalIterator>) - - if (__first == __middle) - return __last; - else if (__last == __middle) - return __first; - - std::__reverse(__first, __middle, bidirectional_iterator_tag()); - std::__reverse(__middle, __last, bidirectional_iterator_tag()); - - while (__first != __middle && __middle != __last) - { - std::iter_swap(__first, --__last); - ++__first; - } - - if (__first == __middle) - { - std::__reverse(__middle, __last, bidirectional_iterator_tag()); - return __last; - } - else - { - std::__reverse(__first, __middle, bidirectional_iterator_tag()); - return __first; - } - } - - /// This is a helper function for the rotate algorithm. - template - _GLIBCXX20_CONSTEXPR - _RandomAccessIterator - __rotate(_RandomAccessIterator __first, - _RandomAccessIterator __middle, - _RandomAccessIterator __last, - random_access_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - - if (__first == __middle) - return __last; - else if (__last == __middle) - return __first; - - typedef typename iterator_traits<_RandomAccessIterator>::difference_type - _Distance; - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _ValueType; - - _Distance __n = __last - __first; - _Distance __k = __middle - __first; - - if (__k == __n - __k) - { - std::swap_ranges(__first, __middle, __middle); - return __middle; - } - - _RandomAccessIterator __p = __first; - _RandomAccessIterator __ret = __first + (__last - __middle); - - for (;;) - { - if (__k < __n - __k) - { - if (__is_pod(_ValueType) && __k == 1) - { - _ValueType __t = _GLIBCXX_MOVE(*__p); - _GLIBCXX_MOVE3(__p + 1, __p + __n, __p); - *(__p + __n - 1) = _GLIBCXX_MOVE(__t); - return __ret; - } - _RandomAccessIterator __q = __p + __k; - for (_Distance __i = 0; __i < __n - __k; ++ __i) - { - std::iter_swap(__p, __q); - ++__p; - ++__q; - } - __n %= __k; - if (__n == 0) - return __ret; - std::swap(__n, __k); - __k = __n - __k; - } - else - { - __k = __n - __k; - if (__is_pod(_ValueType) && __k == 1) - { - _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1)); - _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n); - *__p = _GLIBCXX_MOVE(__t); - return __ret; - } - _RandomAccessIterator __q = __p + __n; - __p = __q - __k; - for (_Distance __i = 0; __i < __n - __k; ++ __i) - { - --__p; - --__q; - std::iter_swap(__p, __q); - } - __n %= __k; - if (__n == 0) - return __ret; - std::swap(__n, __k); - } - } - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 488. rotate throws away useful information - /** - * @brief Rotate the elements of a sequence. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __middle A forward iterator. - * @param __last A forward iterator. - * @return first + (last - middle). - * - * Rotates the elements of the range @p [__first,__last) by - * @p (__middle - __first) positions so that the element at @p __middle - * is moved to @p __first, the element at @p __middle+1 is moved to - * @p __first+1 and so on for each element in the range - * @p [__first,__last). - * - * This effectively swaps the ranges @p [__first,__middle) and - * @p [__middle,__last). - * - * Performs - * @p *(__first+(n+(__last-__middle))%(__last-__first))=*(__first+n) - * for each @p n in the range @p [0,__last-__first). - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - rotate(_ForwardIterator __first, _ForwardIterator __middle, - _ForwardIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_requires_valid_range(__first, __middle); - __glibcxx_requires_valid_range(__middle, __last); - - return std::__rotate(__first, __middle, __last, - std::__iterator_category(__first)); - } - - } // namespace _V2 - - /** - * @brief Copy a sequence, rotating its elements. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __middle A forward iterator. - * @param __last A forward iterator. - * @param __result An output iterator. - * @return An iterator designating the end of the resulting sequence. - * - * Copies the elements of the range @p [__first,__last) to the - * range beginning at @result, rotating the copied elements by - * @p (__middle-__first) positions so that the element at @p __middle - * is moved to @p __result, the element at @p __middle+1 is moved - * to @p __result+1 and so on for each element in the range @p - * [__first,__last). - * - * Performs - * @p *(__result+(n+(__last-__middle))%(__last-__first))=*(__first+n) - * for each @p n in the range @p [0,__last-__first). - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, - _ForwardIterator __last, _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __middle); - __glibcxx_requires_valid_range(__middle, __last); - - return std::copy(__first, __middle, - std::copy(__middle, __last, __result)); - } - - /// This is a helper function... - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __partition(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred, forward_iterator_tag) - { - if (__first == __last) - return __first; - - while (__pred(*__first)) - if (++__first == __last) - return __first; - - _ForwardIterator __next = __first; - - while (++__next != __last) - if (__pred(*__next)) - { - std::iter_swap(__first, __next); - ++__first; - } - - return __first; - } - - /// This is a helper function... - template - _GLIBCXX20_CONSTEXPR - _BidirectionalIterator - __partition(_BidirectionalIterator __first, _BidirectionalIterator __last, - _Predicate __pred, bidirectional_iterator_tag) - { - while (true) - { - while (true) - if (__first == __last) - return __first; - else if (__pred(*__first)) - ++__first; - else - break; - --__last; - while (true) - if (__first == __last) - return __first; - else if (!bool(__pred(*__last))) - --__last; - else - break; - std::iter_swap(__first, __last); - ++__first; - } - } - - // partition - - /// This is a helper function... - /// Requires __first != __last and !__pred(__first) - /// and __len == distance(__first, __last). - /// - /// !__pred(__first) allows us to guarantee that we don't - /// move-assign an element onto itself. - template - _ForwardIterator - __stable_partition_adaptive(_ForwardIterator __first, - _ForwardIterator __last, - _Predicate __pred, _Distance __len, - _Pointer __buffer, - _Distance __buffer_size) - { - if (__len == 1) - return __first; - - if (__len <= __buffer_size) - { - _ForwardIterator __result1 = __first; - _Pointer __result2 = __buffer; - - // The precondition guarantees that !__pred(__first), so - // move that element to the buffer before starting the loop. - // This ensures that we only call __pred once per element. - *__result2 = _GLIBCXX_MOVE(*__first); - ++__result2; - ++__first; - for (; __first != __last; ++__first) - if (__pred(__first)) - { - *__result1 = _GLIBCXX_MOVE(*__first); - ++__result1; - } - else - { - *__result2 = _GLIBCXX_MOVE(*__first); - ++__result2; - } - - _GLIBCXX_MOVE3(__buffer, __result2, __result1); - return __result1; - } - - _ForwardIterator __middle = __first; - std::advance(__middle, __len / 2); - _ForwardIterator __left_split = - std::__stable_partition_adaptive(__first, __middle, __pred, - __len / 2, __buffer, - __buffer_size); - - // Advance past true-predicate values to satisfy this - // function's preconditions. - _Distance __right_len = __len - __len / 2; - _ForwardIterator __right_split = - std::__find_if_not_n(__middle, __right_len, __pred); - - if (__right_len) - __right_split = - std::__stable_partition_adaptive(__right_split, __last, __pred, - __right_len, - __buffer, __buffer_size); - - return std::rotate(__left_split, __middle, __right_split); - } - - template - _ForwardIterator - __stable_partition(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred) - { - __first = std::__find_if_not(__first, __last, __pred); - - if (__first == __last) - return __first; - - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; - typedef typename iterator_traits<_ForwardIterator>::difference_type - _DistanceType; - - _Temporary_buffer<_ForwardIterator, _ValueType> - __buf(__first, std::distance(__first, __last)); - return - std::__stable_partition_adaptive(__first, __last, __pred, - _DistanceType(__buf.requested_size()), - __buf.begin(), - _DistanceType(__buf.size())); - } - - /** - * @brief Move elements for which a predicate is true to the beginning - * of a sequence, preserving relative ordering. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __pred A predicate functor. - * @return An iterator @p middle such that @p __pred(i) is true for each - * iterator @p i in the range @p [first,middle) and false for each @p i - * in the range @p [middle,last). - * - * Performs the same function as @p partition() with the additional - * guarantee that the relative ordering of elements in each group is - * preserved, so any two elements @p x and @p y in the range - * @p [__first,__last) such that @p __pred(x)==__pred(y) will have the same - * relative ordering after calling @p stable_partition(). - */ - template - inline _ForwardIterator - stable_partition(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__stable_partition(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); - } - - /// This is a helper function for the sort routines. - template - _GLIBCXX20_CONSTEXPR - void - __heap_select(_RandomAccessIterator __first, - _RandomAccessIterator __middle, - _RandomAccessIterator __last, _Compare __comp) - { - std::__make_heap(__first, __middle, __comp); - for (_RandomAccessIterator __i = __middle; __i < __last; ++__i) - if (__comp(__i, __first)) - std::__pop_heap(__first, __middle, __i, __comp); - } - - // partial_sort - - template - _GLIBCXX20_CONSTEXPR - _RandomAccessIterator - __partial_sort_copy(_InputIterator __first, _InputIterator __last, - _RandomAccessIterator __result_first, - _RandomAccessIterator __result_last, - _Compare __comp) - { - typedef typename iterator_traits<_InputIterator>::value_type - _InputValueType; - typedef iterator_traits<_RandomAccessIterator> _RItTraits; - typedef typename _RItTraits::difference_type _DistanceType; - - if (__result_first == __result_last) - return __result_last; - _RandomAccessIterator __result_real_last = __result_first; - while (__first != __last && __result_real_last != __result_last) - { - *__result_real_last = *__first; - ++__result_real_last; - ++__first; - } - - std::__make_heap(__result_first, __result_real_last, __comp); - while (__first != __last) - { - if (__comp(__first, __result_first)) - std::__adjust_heap(__result_first, _DistanceType(0), - _DistanceType(__result_real_last - - __result_first), - _InputValueType(*__first), __comp); - ++__first; - } - std::__sort_heap(__result_first, __result_real_last, __comp); - return __result_real_last; - } - - /** - * @brief Copy the smallest elements of a sequence. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __result_first A random-access iterator. - * @param __result_last Another random-access iterator. - * @return An iterator indicating the end of the resulting sequence. - * - * Copies and sorts the smallest N values from the range @p [__first,__last) - * to the range beginning at @p __result_first, where the number of - * elements to be copied, @p N, is the smaller of @p (__last-__first) and - * @p (__result_last-__result_first). - * After the sort if @e i and @e j are iterators in the range - * @p [__result_first,__result_first+N) such that i precedes j then - * *j<*i is false. - * The value returned is @p __result_first+N. - */ - template - _GLIBCXX20_CONSTEXPR - inline _RandomAccessIterator - partial_sort_copy(_InputIterator __first, _InputIterator __last, - _RandomAccessIterator __result_first, - _RandomAccessIterator __result_last) - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - typedef typename iterator_traits<_InputIterator>::value_type - _InputValueType; - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _OutputValueType; -#endif - - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, - _OutputValueType>) - __glibcxx_function_requires(_LessThanOpConcept<_InputValueType, - _OutputValueType>) - __glibcxx_function_requires(_LessThanComparableConcept<_OutputValueType>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - __glibcxx_requires_valid_range(__result_first, __result_last); - - return std::__partial_sort_copy(__first, __last, - __result_first, __result_last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Copy the smallest elements of a sequence using a predicate for - * comparison. - * @ingroup sorting_algorithms - * @param __first An input iterator. - * @param __last Another input iterator. - * @param __result_first A random-access iterator. - * @param __result_last Another random-access iterator. - * @param __comp A comparison functor. - * @return An iterator indicating the end of the resulting sequence. - * - * Copies and sorts the smallest N values from the range @p [__first,__last) - * to the range beginning at @p result_first, where the number of - * elements to be copied, @p N, is the smaller of @p (__last-__first) and - * @p (__result_last-__result_first). - * After the sort if @e i and @e j are iterators in the range - * @p [__result_first,__result_first+N) such that i precedes j then - * @p __comp(*j,*i) is false. - * The value returned is @p __result_first+N. - */ - template - _GLIBCXX20_CONSTEXPR - inline _RandomAccessIterator - partial_sort_copy(_InputIterator __first, _InputIterator __last, - _RandomAccessIterator __result_first, - _RandomAccessIterator __result_last, - _Compare __comp) - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - typedef typename iterator_traits<_InputIterator>::value_type - _InputValueType; - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _OutputValueType; -#endif - - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, - _OutputValueType>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - _InputValueType, _OutputValueType>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - _OutputValueType, _OutputValueType>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - __glibcxx_requires_valid_range(__result_first, __result_last); - - return std::__partial_sort_copy(__first, __last, - __result_first, __result_last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - /// This is a helper function for the sort routine. - template - _GLIBCXX20_CONSTEXPR - void - __unguarded_linear_insert(_RandomAccessIterator __last, - _Compare __comp) - { - typename iterator_traits<_RandomAccessIterator>::value_type - __val = _GLIBCXX_MOVE(*__last); - _RandomAccessIterator __next = __last; - --__next; - while (__comp(__val, __next)) - { - *__last = _GLIBCXX_MOVE(*__next); - __last = __next; - --__next; - } - *__last = _GLIBCXX_MOVE(__val); - } - - /// This is a helper function for the sort routine. - template - _GLIBCXX20_CONSTEXPR - void - __insertion_sort(_RandomAccessIterator __first, - _RandomAccessIterator __last, _Compare __comp) - { - if (__first == __last) return; - - for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) - { - if (__comp(__i, __first)) - { - typename iterator_traits<_RandomAccessIterator>::value_type - __val = _GLIBCXX_MOVE(*__i); - _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1); - *__first = _GLIBCXX_MOVE(__val); - } - else - std::__unguarded_linear_insert(__i, - __gnu_cxx::__ops::__val_comp_iter(__comp)); - } - } - - /// This is a helper function for the sort routine. - template - _GLIBCXX20_CONSTEXPR - inline void - __unguarded_insertion_sort(_RandomAccessIterator __first, - _RandomAccessIterator __last, _Compare __comp) - { - for (_RandomAccessIterator __i = __first; __i != __last; ++__i) - std::__unguarded_linear_insert(__i, - __gnu_cxx::__ops::__val_comp_iter(__comp)); - } - - /** - * @doctodo - * This controls some aspect of the sort routines. - */ - enum { _S_threshold = 16 }; - - /// This is a helper function for the sort routine. - template - _GLIBCXX20_CONSTEXPR - void - __final_insertion_sort(_RandomAccessIterator __first, - _RandomAccessIterator __last, _Compare __comp) - { - if (__last - __first > int(_S_threshold)) - { - std::__insertion_sort(__first, __first + int(_S_threshold), __comp); - std::__unguarded_insertion_sort(__first + int(_S_threshold), __last, - __comp); - } - else - std::__insertion_sort(__first, __last, __comp); - } - - /// This is a helper function... - template - _GLIBCXX20_CONSTEXPR - _RandomAccessIterator - __unguarded_partition(_RandomAccessIterator __first, - _RandomAccessIterator __last, - _RandomAccessIterator __pivot, _Compare __comp) - { - while (true) - { - while (__comp(__first, __pivot)) - ++__first; - --__last; - while (__comp(__pivot, __last)) - --__last; - if (!(__first < __last)) - return __first; - std::iter_swap(__first, __last); - ++__first; - } - } - - /// This is a helper function... - template - _GLIBCXX20_CONSTEXPR - inline _RandomAccessIterator - __unguarded_partition_pivot(_RandomAccessIterator __first, - _RandomAccessIterator __last, _Compare __comp) - { - _RandomAccessIterator __mid = __first + (__last - __first) / 2; - std::__move_median_to_first(__first, __first + 1, __mid, __last - 1, - __comp); - return std::__unguarded_partition(__first + 1, __last, __first, __comp); - } - - template - _GLIBCXX20_CONSTEXPR - inline void - __partial_sort(_RandomAccessIterator __first, - _RandomAccessIterator __middle, - _RandomAccessIterator __last, - _Compare __comp) - { - std::__heap_select(__first, __middle, __last, __comp); - std::__sort_heap(__first, __middle, __comp); - } - - /// This is a helper function for the sort routine. - template - _GLIBCXX20_CONSTEXPR - void - __introsort_loop(_RandomAccessIterator __first, - _RandomAccessIterator __last, - _Size __depth_limit, _Compare __comp) - { - while (__last - __first > int(_S_threshold)) - { - if (__depth_limit == 0) - { - std::__partial_sort(__first, __last, __last, __comp); - return; - } - --__depth_limit; - _RandomAccessIterator __cut = - std::__unguarded_partition_pivot(__first, __last, __comp); - std::__introsort_loop(__cut, __last, __depth_limit, __comp); - __last = __cut; - } - } - - // sort - - template - _GLIBCXX20_CONSTEXPR - inline void - __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - if (__first != __last) - { - std::__introsort_loop(__first, __last, - std::__lg(__last - __first) * 2, - __comp); - std::__final_insertion_sort(__first, __last, __comp); - } - } - - template - _GLIBCXX20_CONSTEXPR - void - __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth, - _RandomAccessIterator __last, _Size __depth_limit, - _Compare __comp) - { - while (__last - __first > 3) - { - if (__depth_limit == 0) - { - std::__heap_select(__first, __nth + 1, __last, __comp); - // Place the nth largest element in its final position. - std::iter_swap(__first, __nth); - return; - } - --__depth_limit; - _RandomAccessIterator __cut = - std::__unguarded_partition_pivot(__first, __last, __comp); - if (__cut <= __nth) - __first = __cut; - else - __last = __cut; - } - std::__insertion_sort(__first, __last, __comp); - } - - // nth_element - - // lower_bound moved to stl_algobase.h - - /** - * @brief Finds the first position in which @p __val could be inserted - * without changing the ordering. - * @ingroup binary_search_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __val The search term. - * @param __comp A functor to use for comparisons. - * @return An iterator pointing to the first element not less - * than @p __val, or end() if every element is less - * than @p __val. - * @ingroup binary_search_algorithms - * - * The comparison function should have the same effects on ordering as - * the function used for the initial sort. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - lower_bound(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_ForwardIterator>::value_type, _Tp>) - __glibcxx_requires_partitioned_lower_pred(__first, __last, - __val, __comp); - - return std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp)); - } - - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __upper_bound(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val, _Compare __comp) - { - typedef typename iterator_traits<_ForwardIterator>::difference_type - _DistanceType; - - _DistanceType __len = std::distance(__first, __last); - - while (__len > 0) - { - _DistanceType __half = __len >> 1; - _ForwardIterator __middle = __first; - std::advance(__middle, __half); - if (__comp(__val, __middle)) - __len = __half; - else - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - } - return __first; - } - - /** - * @brief Finds the last position in which @p __val could be inserted - * without changing the ordering. - * @ingroup binary_search_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __val The search term. - * @return An iterator pointing to the first element greater than @p __val, - * or end() if no elements are greater than @p __val. - * @ingroup binary_search_algorithms - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - upper_bound(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanOpConcept< - _Tp, typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_partitioned_upper(__first, __last, __val); - - return std::__upper_bound(__first, __last, __val, - __gnu_cxx::__ops::__val_less_iter()); - } - - /** - * @brief Finds the last position in which @p __val could be inserted - * without changing the ordering. - * @ingroup binary_search_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __val The search term. - * @param __comp A functor to use for comparisons. - * @return An iterator pointing to the first element greater than @p __val, - * or end() if no elements are greater than @p __val. - * @ingroup binary_search_algorithms - * - * The comparison function should have the same effects on ordering as - * the function used for the initial sort. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - upper_bound(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - _Tp, typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_partitioned_upper_pred(__first, __last, - __val, __comp); - - return std::__upper_bound(__first, __last, __val, - __gnu_cxx::__ops::__val_comp_iter(__comp)); - } - - template - _GLIBCXX20_CONSTEXPR - pair<_ForwardIterator, _ForwardIterator> - __equal_range(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val, - _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it) - { - typedef typename iterator_traits<_ForwardIterator>::difference_type - _DistanceType; - - _DistanceType __len = std::distance(__first, __last); - - while (__len > 0) - { - _DistanceType __half = __len >> 1; - _ForwardIterator __middle = __first; - std::advance(__middle, __half); - if (__comp_it_val(__middle, __val)) - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - else if (__comp_val_it(__val, __middle)) - __len = __half; - else - { - _ForwardIterator __left - = std::__lower_bound(__first, __middle, __val, __comp_it_val); - std::advance(__first, __len); - _ForwardIterator __right - = std::__upper_bound(++__middle, __first, __val, __comp_val_it); - return pair<_ForwardIterator, _ForwardIterator>(__left, __right); - } - } - return pair<_ForwardIterator, _ForwardIterator>(__first, __first); - } - - /** - * @brief Finds the largest subrange in which @p __val could be inserted - * at any place in it without changing the ordering. - * @ingroup binary_search_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __val The search term. - * @return An pair of iterators defining the subrange. - * @ingroup binary_search_algorithms - * - * This is equivalent to - * @code - * std::make_pair(lower_bound(__first, __last, __val), - * upper_bound(__first, __last, __val)) - * @endcode - * but does not actually call those functions. - */ - template - _GLIBCXX20_CONSTEXPR - inline pair<_ForwardIterator, _ForwardIterator> - equal_range(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_ForwardIterator>::value_type, _Tp>) - __glibcxx_function_requires(_LessThanOpConcept< - _Tp, typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_partitioned_lower(__first, __last, __val); - __glibcxx_requires_partitioned_upper(__first, __last, __val); - - return std::__equal_range(__first, __last, __val, - __gnu_cxx::__ops::__iter_less_val(), - __gnu_cxx::__ops::__val_less_iter()); - } - - /** - * @brief Finds the largest subrange in which @p __val could be inserted - * at any place in it without changing the ordering. - * @param __first An iterator. - * @param __last Another iterator. - * @param __val The search term. - * @param __comp A functor to use for comparisons. - * @return An pair of iterators defining the subrange. - * @ingroup binary_search_algorithms - * - * This is equivalent to - * @code - * std::make_pair(lower_bound(__first, __last, __val, __comp), - * upper_bound(__first, __last, __val, __comp)) - * @endcode - * but does not actually call those functions. - */ - template - _GLIBCXX20_CONSTEXPR - inline pair<_ForwardIterator, _ForwardIterator> - equal_range(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_ForwardIterator>::value_type, _Tp>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - _Tp, typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_partitioned_lower_pred(__first, __last, - __val, __comp); - __glibcxx_requires_partitioned_upper_pred(__first, __last, - __val, __comp); - - return std::__equal_range(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp), - __gnu_cxx::__ops::__val_comp_iter(__comp)); - } - - /** - * @brief Determines whether an element exists in a range. - * @ingroup binary_search_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __val The search term. - * @return True if @p __val (or its equivalent) is in [@p - * __first,@p __last ]. - * - * Note that this does not actually return an iterator to @p __val. For - * that, use std::find or a container's specialized find member functions. - */ - template - _GLIBCXX20_CONSTEXPR - bool - binary_search(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanOpConcept< - _Tp, typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_partitioned_lower(__first, __last, __val); - __glibcxx_requires_partitioned_upper(__first, __last, __val); - - _ForwardIterator __i - = std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_less_val()); - return __i != __last && !(__val < *__i); - } - - /** - * @brief Determines whether an element exists in a range. - * @ingroup binary_search_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __val The search term. - * @param __comp A functor to use for comparisons. - * @return True if @p __val (or its equivalent) is in @p [__first,__last]. - * - * Note that this does not actually return an iterator to @p __val. For - * that, use std::find or a container's specialized find member functions. - * - * The comparison function should have the same effects on ordering as - * the function used for the initial sort. - */ - template - _GLIBCXX20_CONSTEXPR - bool - binary_search(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - _Tp, typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_partitioned_lower_pred(__first, __last, - __val, __comp); - __glibcxx_requires_partitioned_upper_pred(__first, __last, - __val, __comp); - - _ForwardIterator __i - = std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_comp_val(__comp)); - return __i != __last && !bool(__comp(__val, *__i)); - } - - // merge - - /// This is a helper function for the __merge_adaptive routines. - template - void - __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - { - if (__comp(__first2, __first1)) - { - *__result = _GLIBCXX_MOVE(*__first2); - ++__first2; - } - else - { - *__result = _GLIBCXX_MOVE(*__first1); - ++__first1; - } - ++__result; - } - if (__first1 != __last1) - _GLIBCXX_MOVE3(__first1, __last1, __result); - } - - /// This is a helper function for the __merge_adaptive routines. - template - void - __move_merge_adaptive_backward(_BidirectionalIterator1 __first1, - _BidirectionalIterator1 __last1, - _BidirectionalIterator2 __first2, - _BidirectionalIterator2 __last2, - _BidirectionalIterator3 __result, - _Compare __comp) - { - if (__first1 == __last1) - { - _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); - return; - } - else if (__first2 == __last2) - return; - - --__last1; - --__last2; - while (true) - { - if (__comp(__last2, __last1)) - { - *--__result = _GLIBCXX_MOVE(*__last1); - if (__first1 == __last1) - { - _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); - return; - } - --__last1; - } - else - { - *--__result = _GLIBCXX_MOVE(*__last2); - if (__first2 == __last2) - return; - --__last2; - } - } - } - - /// This is a helper function for the merge routines. - template - _BidirectionalIterator1 - __rotate_adaptive(_BidirectionalIterator1 __first, - _BidirectionalIterator1 __middle, - _BidirectionalIterator1 __last, - _Distance __len1, _Distance __len2, - _BidirectionalIterator2 __buffer, - _Distance __buffer_size) - { - _BidirectionalIterator2 __buffer_end; - if (__len1 > __len2 && __len2 <= __buffer_size) - { - if (__len2) - { - __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); - _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last); - return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first); - } - else - return __first; - } - else if (__len1 <= __buffer_size) - { - if (__len1) - { - __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); - _GLIBCXX_MOVE3(__middle, __last, __first); - return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last); - } - else - return __last; - } - else - return std::rotate(__first, __middle, __last); - } - - /// This is a helper function for the merge routines. - template - void - __merge_adaptive(_BidirectionalIterator __first, - _BidirectionalIterator __middle, - _BidirectionalIterator __last, - _Distance __len1, _Distance __len2, - _Pointer __buffer, _Distance __buffer_size, - _Compare __comp) - { - if (__len1 <= __len2 && __len1 <= __buffer_size) - { - _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); - std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last, - __first, __comp); - } - else if (__len2 <= __buffer_size) - { - _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); - std::__move_merge_adaptive_backward(__first, __middle, __buffer, - __buffer_end, __last, __comp); - } - else - { - _BidirectionalIterator __first_cut = __first; - _BidirectionalIterator __second_cut = __middle; - _Distance __len11 = 0; - _Distance __len22 = 0; - if (__len1 > __len2) - { - __len11 = __len1 / 2; - std::advance(__first_cut, __len11); - __second_cut - = std::__lower_bound(__middle, __last, *__first_cut, - __gnu_cxx::__ops::__iter_comp_val(__comp)); - __len22 = std::distance(__middle, __second_cut); - } - else - { - __len22 = __len2 / 2; - std::advance(__second_cut, __len22); - __first_cut - = std::__upper_bound(__first, __middle, *__second_cut, - __gnu_cxx::__ops::__val_comp_iter(__comp)); - __len11 = std::distance(__first, __first_cut); - } - - _BidirectionalIterator __new_middle - = std::__rotate_adaptive(__first_cut, __middle, __second_cut, - __len1 - __len11, __len22, __buffer, - __buffer_size); - std::__merge_adaptive(__first, __first_cut, __new_middle, __len11, - __len22, __buffer, __buffer_size, __comp); - std::__merge_adaptive(__new_middle, __second_cut, __last, - __len1 - __len11, - __len2 - __len22, __buffer, - __buffer_size, __comp); - } - } - - /// This is a helper function for the merge routines. - template - void - __merge_without_buffer(_BidirectionalIterator __first, - _BidirectionalIterator __middle, - _BidirectionalIterator __last, - _Distance __len1, _Distance __len2, - _Compare __comp) - { - if (__len1 == 0 || __len2 == 0) - return; - - if (__len1 + __len2 == 2) - { - if (__comp(__middle, __first)) - std::iter_swap(__first, __middle); - return; - } - - _BidirectionalIterator __first_cut = __first; - _BidirectionalIterator __second_cut = __middle; - _Distance __len11 = 0; - _Distance __len22 = 0; - if (__len1 > __len2) - { - __len11 = __len1 / 2; - std::advance(__first_cut, __len11); - __second_cut - = std::__lower_bound(__middle, __last, *__first_cut, - __gnu_cxx::__ops::__iter_comp_val(__comp)); - __len22 = std::distance(__middle, __second_cut); - } - else - { - __len22 = __len2 / 2; - std::advance(__second_cut, __len22); - __first_cut - = std::__upper_bound(__first, __middle, *__second_cut, - __gnu_cxx::__ops::__val_comp_iter(__comp)); - __len11 = std::distance(__first, __first_cut); - } - - _BidirectionalIterator __new_middle - = std::rotate(__first_cut, __middle, __second_cut); - std::__merge_without_buffer(__first, __first_cut, __new_middle, - __len11, __len22, __comp); - std::__merge_without_buffer(__new_middle, __second_cut, __last, - __len1 - __len11, __len2 - __len22, __comp); - } - - template - void - __inplace_merge(_BidirectionalIterator __first, - _BidirectionalIterator __middle, - _BidirectionalIterator __last, - _Compare __comp) - { - typedef typename iterator_traits<_BidirectionalIterator>::value_type - _ValueType; - typedef typename iterator_traits<_BidirectionalIterator>::difference_type - _DistanceType; - - if (__first == __middle || __middle == __last) - return; - - const _DistanceType __len1 = std::distance(__first, __middle); - const _DistanceType __len2 = std::distance(__middle, __last); - - typedef _Temporary_buffer<_BidirectionalIterator, _ValueType> _TmpBuf; - _TmpBuf __buf(__first, __len1 + __len2); - - if (__buf.begin() == 0) - std::__merge_without_buffer - (__first, __middle, __last, __len1, __len2, __comp); - else - std::__merge_adaptive - (__first, __middle, __last, __len1, __len2, __buf.begin(), - _DistanceType(__buf.size()), __comp); - } - - /** - * @brief Merges two sorted ranges in place. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __middle Another iterator. - * @param __last Another iterator. - * @return Nothing. - * - * Merges two sorted and consecutive ranges, [__first,__middle) and - * [__middle,__last), and puts the result in [__first,__last). The - * output will be sorted. The sort is @e stable, that is, for - * equivalent elements in the two ranges, elements from the first - * range will always come before elements from the second. - * - * If enough additional memory is available, this takes (__last-__first)-1 - * comparisons. Otherwise an NlogN algorithm is used, where N is - * distance(__first,__last). - */ - template - inline void - inplace_merge(_BidirectionalIterator __first, - _BidirectionalIterator __middle, - _BidirectionalIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< - _BidirectionalIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_BidirectionalIterator>::value_type>) - __glibcxx_requires_sorted(__first, __middle); - __glibcxx_requires_sorted(__middle, __last); - __glibcxx_requires_irreflexive(__first, __last); - - std::__inplace_merge(__first, __middle, __last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Merges two sorted ranges in place. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __middle Another iterator. - * @param __last Another iterator. - * @param __comp A functor to use for comparisons. - * @return Nothing. - * - * Merges two sorted and consecutive ranges, [__first,__middle) and - * [middle,last), and puts the result in [__first,__last). The output will - * be sorted. The sort is @e stable, that is, for equivalent - * elements in the two ranges, elements from the first range will always - * come before elements from the second. - * - * If enough additional memory is available, this takes (__last-__first)-1 - * comparisons. Otherwise an NlogN algorithm is used, where N is - * distance(__first,__last). - * - * The comparison function should have the same effects on ordering as - * the function used for the initial sort. - */ - template - inline void - inplace_merge(_BidirectionalIterator __first, - _BidirectionalIterator __middle, - _BidirectionalIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< - _BidirectionalIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_BidirectionalIterator>::value_type, - typename iterator_traits<_BidirectionalIterator>::value_type>) - __glibcxx_requires_sorted_pred(__first, __middle, __comp); - __glibcxx_requires_sorted_pred(__middle, __last, __comp); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - std::__inplace_merge(__first, __middle, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - - /// This is a helper function for the __merge_sort_loop routines. - template - _OutputIterator - __move_merge(_InputIterator __first1, _InputIterator __last1, - _InputIterator __first2, _InputIterator __last2, - _OutputIterator __result, _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - { - if (__comp(__first2, __first1)) - { - *__result = _GLIBCXX_MOVE(*__first2); - ++__first2; - } - else - { - *__result = _GLIBCXX_MOVE(*__first1); - ++__first1; - } - ++__result; - } - return _GLIBCXX_MOVE3(__first2, __last2, - _GLIBCXX_MOVE3(__first1, __last1, - __result)); - } - - template - void - __merge_sort_loop(_RandomAccessIterator1 __first, - _RandomAccessIterator1 __last, - _RandomAccessIterator2 __result, _Distance __step_size, - _Compare __comp) - { - const _Distance __two_step = 2 * __step_size; - - while (__last - __first >= __two_step) - { - __result = std::__move_merge(__first, __first + __step_size, - __first + __step_size, - __first + __two_step, - __result, __comp); - __first += __two_step; - } - __step_size = std::min(_Distance(__last - __first), __step_size); - - std::__move_merge(__first, __first + __step_size, - __first + __step_size, __last, __result, __comp); - } - - template - _GLIBCXX20_CONSTEXPR - void - __chunk_insertion_sort(_RandomAccessIterator __first, - _RandomAccessIterator __last, - _Distance __chunk_size, _Compare __comp) - { - while (__last - __first >= __chunk_size) - { - std::__insertion_sort(__first, __first + __chunk_size, __comp); - __first += __chunk_size; - } - std::__insertion_sort(__first, __last, __comp); - } - - enum { _S_chunk_size = 7 }; - - template - void - __merge_sort_with_buffer(_RandomAccessIterator __first, - _RandomAccessIterator __last, - _Pointer __buffer, _Compare __comp) - { - typedef typename iterator_traits<_RandomAccessIterator>::difference_type - _Distance; - - const _Distance __len = __last - __first; - const _Pointer __buffer_last = __buffer + __len; - - _Distance __step_size = _S_chunk_size; - std::__chunk_insertion_sort(__first, __last, __step_size, __comp); - - while (__step_size < __len) - { - std::__merge_sort_loop(__first, __last, __buffer, - __step_size, __comp); - __step_size *= 2; - std::__merge_sort_loop(__buffer, __buffer_last, __first, - __step_size, __comp); - __step_size *= 2; - } - } - - template - void - __stable_sort_adaptive(_RandomAccessIterator __first, - _RandomAccessIterator __last, - _Pointer __buffer, _Distance __buffer_size, - _Compare __comp) - { - const _Distance __len = (__last - __first + 1) / 2; - const _RandomAccessIterator __middle = __first + __len; - if (__len > __buffer_size) - { - std::__stable_sort_adaptive(__first, __middle, __buffer, - __buffer_size, __comp); - std::__stable_sort_adaptive(__middle, __last, __buffer, - __buffer_size, __comp); - } - else - { - std::__merge_sort_with_buffer(__first, __middle, __buffer, __comp); - std::__merge_sort_with_buffer(__middle, __last, __buffer, __comp); - } - std::__merge_adaptive(__first, __middle, __last, - _Distance(__middle - __first), - _Distance(__last - __middle), - __buffer, __buffer_size, - __comp); - } - - /// This is a helper function for the stable sorting routines. - template - void - __inplace_stable_sort(_RandomAccessIterator __first, - _RandomAccessIterator __last, _Compare __comp) - { - if (__last - __first < 15) - { - std::__insertion_sort(__first, __last, __comp); - return; - } - _RandomAccessIterator __middle = __first + (__last - __first) / 2; - std::__inplace_stable_sort(__first, __middle, __comp); - std::__inplace_stable_sort(__middle, __last, __comp); - std::__merge_without_buffer(__first, __middle, __last, - __middle - __first, - __last - __middle, - __comp); - } - - // stable_sort - - // Set algorithms: includes, set_union, set_intersection, set_difference, - // set_symmetric_difference. All of these algorithms have the precondition - // that their input ranges are sorted and the postcondition that their output - // ranges are sorted. - - template - _GLIBCXX20_CONSTEXPR - bool - __includes(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - if (__comp(__first2, __first1)) - return false; - else if (__comp(__first1, __first2)) - ++__first1; - else - { - ++__first1; - ++__first2; - } - - return __first2 == __last2; - } - - /** - * @brief Determines whether all elements of a sequence exists in a range. - * @param __first1 Start of search range. - * @param __last1 End of search range. - * @param __first2 Start of sequence - * @param __last2 End of sequence. - * @return True if each element in [__first2,__last2) is contained in order - * within [__first1,__last1). False otherwise. - * @ingroup set_algorithms - * - * This operation expects both [__first1,__last1) and - * [__first2,__last2) to be sorted. Searches for the presence of - * each element in [__first2,__last2) within [__first1,__last1). - * The iterators over each range only move forward, so this is a - * linear algorithm. If an element in [__first2,__last2) is not - * found before the search iterator reaches @p __last2, false is - * returned. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - includes(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set(__first1, __last1, __first2); - __glibcxx_requires_sorted_set(__first2, __last2, __first1); - __glibcxx_requires_irreflexive2(__first1, __last1); - __glibcxx_requires_irreflexive2(__first2, __last2); - - return std::__includes(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Determines whether all elements of a sequence exists in a range - * using comparison. - * @ingroup set_algorithms - * @param __first1 Start of search range. - * @param __last1 End of search range. - * @param __first2 Start of sequence - * @param __last2 End of sequence. - * @param __comp Comparison function to use. - * @return True if each element in [__first2,__last2) is contained - * in order within [__first1,__last1) according to comp. False - * otherwise. @ingroup set_algorithms - * - * This operation expects both [__first1,__last1) and - * [__first2,__last2) to be sorted. Searches for the presence of - * each element in [__first2,__last2) within [__first1,__last1), - * using comp to decide. The iterators over each range only move - * forward, so this is a linear algorithm. If an element in - * [__first2,__last2) is not found before the search iterator - * reaches @p __last2, false is returned. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - includes(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); - __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); - __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); - __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - - return std::__includes(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - // nth_element - // merge - // set_difference - // set_intersection - // set_union - // stable_sort - // set_symmetric_difference - // min_element - // max_element - - template - _GLIBCXX20_CONSTEXPR - bool - __next_permutation(_BidirectionalIterator __first, - _BidirectionalIterator __last, _Compare __comp) - { - if (__first == __last) - return false; - _BidirectionalIterator __i = __first; - ++__i; - if (__i == __last) - return false; - __i = __last; - --__i; - - for(;;) - { - _BidirectionalIterator __ii = __i; - --__i; - if (__comp(__i, __ii)) - { - _BidirectionalIterator __j = __last; - while (!__comp(__i, --__j)) - {} - std::iter_swap(__i, __j); - std::__reverse(__ii, __last, - std::__iterator_category(__first)); - return true; - } - if (__i == __first) - { - std::__reverse(__first, __last, - std::__iterator_category(__first)); - return false; - } - } - } - - /** - * @brief Permute range into the next @e dictionary ordering. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @return False if wrapped to first permutation, true otherwise. - * - * Treats all permutations of the range as a set of @e dictionary sorted - * sequences. Permutes the current sequence into the next one of this set. - * Returns true if there are more sequences to generate. If the sequence - * is the largest of the set, the smallest is generated and false returned. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - next_permutation(_BidirectionalIterator __first, - _BidirectionalIterator __last) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_BidirectionalIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - return std::__next_permutation - (__first, __last, __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Permute range into the next @e dictionary ordering using - * comparison functor. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @param __comp A comparison functor. - * @return False if wrapped to first permutation, true otherwise. - * - * Treats all permutations of the range [__first,__last) as a set of - * @e dictionary sorted sequences ordered by @p __comp. Permutes the current - * sequence into the next one of this set. Returns true if there are more - * sequences to generate. If the sequence is the largest of the set, the - * smallest is generated and false returned. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - next_permutation(_BidirectionalIterator __first, - _BidirectionalIterator __last, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_BidirectionalIterator>::value_type, - typename iterator_traits<_BidirectionalIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - return std::__next_permutation - (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - _GLIBCXX20_CONSTEXPR - bool - __prev_permutation(_BidirectionalIterator __first, - _BidirectionalIterator __last, _Compare __comp) - { - if (__first == __last) - return false; - _BidirectionalIterator __i = __first; - ++__i; - if (__i == __last) - return false; - __i = __last; - --__i; - - for(;;) - { - _BidirectionalIterator __ii = __i; - --__i; - if (__comp(__ii, __i)) - { - _BidirectionalIterator __j = __last; - while (!__comp(--__j, __i)) - {} - std::iter_swap(__i, __j); - std::__reverse(__ii, __last, - std::__iterator_category(__first)); - return true; - } - if (__i == __first) - { - std::__reverse(__first, __last, - std::__iterator_category(__first)); - return false; - } - } - } - - /** - * @brief Permute range into the previous @e dictionary ordering. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @return False if wrapped to last permutation, true otherwise. - * - * Treats all permutations of the range as a set of @e dictionary sorted - * sequences. Permutes the current sequence into the previous one of this - * set. Returns true if there are more sequences to generate. If the - * sequence is the smallest of the set, the largest is generated and false - * returned. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - prev_permutation(_BidirectionalIterator __first, - _BidirectionalIterator __last) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_BidirectionalIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - return std::__prev_permutation(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Permute range into the previous @e dictionary ordering using - * comparison functor. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @param __comp A comparison functor. - * @return False if wrapped to last permutation, true otherwise. - * - * Treats all permutations of the range [__first,__last) as a set of - * @e dictionary sorted sequences ordered by @p __comp. Permutes the current - * sequence into the previous one of this set. Returns true if there are - * more sequences to generate. If the sequence is the smallest of the set, - * the largest is generated and false returned. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - prev_permutation(_BidirectionalIterator __first, - _BidirectionalIterator __last, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_BidirectionalIterator>::value_type, - typename iterator_traits<_BidirectionalIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - return std::__prev_permutation(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - // replace - // replace_if - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __replace_copy_if(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, - _Predicate __pred, const _Tp& __new_value) - { - for (; __first != __last; ++__first, (void)++__result) - if (__pred(__first)) - *__result = __new_value; - else - *__result = *__first; - return __result; - } - - /** - * @brief Copy a sequence, replacing each element of one value with another - * value. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @param __old_value The value to be replaced. - * @param __new_value The replacement value. - * @return The end of the output sequence, @p result+(last-first). - * - * Copies each element in the input range @p [__first,__last) to the - * output range @p [__result,__result+(__last-__first)) replacing elements - * equal to @p __old_value with @p __new_value. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - replace_copy(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, - const _Tp& __old_value, const _Tp& __new_value) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__replace_copy_if(__first, __last, __result, - __gnu_cxx::__ops::__iter_equals_val(__old_value), - __new_value); - } - - /** - * @brief Copy a sequence, replacing each value for which a predicate - * returns true with another value. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @param __pred A predicate. - * @param __new_value The replacement value. - * @return The end of the output sequence, @p __result+(__last-__first). - * - * Copies each element in the range @p [__first,__last) to the range - * @p [__result,__result+(__last-__first)) replacing elements for which - * @p __pred returns true with @p __new_value. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - replace_copy_if(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, - _Predicate __pred, const _Tp& __new_value) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__replace_copy_if(__first, __last, __result, - __gnu_cxx::__ops::__pred_iter(__pred), - __new_value); - } - -#if __cplusplus >= 201103L - /** - * @brief Determines whether the elements of a sequence are sorted. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @return True if the elements are sorted, false otherwise. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_sorted(_ForwardIterator __first, _ForwardIterator __last) - { return std::is_sorted_until(__first, __last) == __last; } - - /** - * @brief Determines whether the elements of a sequence are sorted - * according to a comparison functor. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __comp A comparison functor. - * @return True if the elements are sorted, false otherwise. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_sorted(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { return std::is_sorted_until(__first, __last, __comp) == __last; } - - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { - if (__first == __last) - return __last; - - _ForwardIterator __next = __first; - for (++__next; __next != __last; __first = __next, (void)++__next) - if (__comp(__next, __first)) - return __next; - return __next; - } - - /** - * @brief Determines the end of a sorted sequence. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @return An iterator pointing to the last iterator i in [__first, __last) - * for which the range [__first, i) is sorted. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - return std::__is_sorted_until(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Determines the end of a sorted sequence using comparison functor. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __comp A comparison functor. - * @return An iterator pointing to the last iterator i in [__first, __last) - * for which the range [__first, i) is sorted. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - return std::__is_sorted_until(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - /** - * @brief Determines min and max at once as an ordered pair. - * @ingroup sorting_algorithms - * @param __a A thing of arbitrary type. - * @param __b Another thing of arbitrary type. - * @return A pair(__b, __a) if __b is smaller than __a, pair(__a, - * __b) otherwise. - */ - template - _GLIBCXX14_CONSTEXPR - inline pair - minmax(const _Tp& __a, const _Tp& __b) - { - // concept requirements - __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) - - return __b < __a ? pair(__b, __a) - : pair(__a, __b); - } - - /** - * @brief Determines min and max at once as an ordered pair. - * @ingroup sorting_algorithms - * @param __a A thing of arbitrary type. - * @param __b Another thing of arbitrary type. - * @param __comp A @link comparison_functors comparison functor @endlink. - * @return A pair(__b, __a) if __b is smaller than __a, pair(__a, - * __b) otherwise. - */ - template - _GLIBCXX14_CONSTEXPR - inline pair - minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) - { - return __comp(__b, __a) ? pair(__b, __a) - : pair(__a, __b); - } - - template - _GLIBCXX14_CONSTEXPR - pair<_ForwardIterator, _ForwardIterator> - __minmax_element(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { - _ForwardIterator __next = __first; - if (__first == __last - || ++__next == __last) - return std::make_pair(__first, __first); - - _ForwardIterator __min{}, __max{}; - if (__comp(__next, __first)) - { - __min = __next; - __max = __first; - } - else - { - __min = __first; - __max = __next; - } - - __first = __next; - ++__first; - - while (__first != __last) - { - __next = __first; - if (++__next == __last) - { - if (__comp(__first, __min)) - __min = __first; - else if (!__comp(__first, __max)) - __max = __first; - break; - } - - if (__comp(__next, __first)) - { - if (__comp(__next, __min)) - __min = __next; - if (!__comp(__first, __max)) - __max = __first; - } - else - { - if (__comp(__first, __min)) - __min = __first; - if (!__comp(__next, __max)) - __max = __next; - } - - __first = __next; - ++__first; - } - - return std::make_pair(__min, __max); - } - - /** - * @brief Return a pair of iterators pointing to the minimum and maximum - * elements in a range. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @return make_pair(m, M), where m is the first iterator i in - * [__first, __last) such that no other element in the range is - * smaller, and where M is the last iterator i in [__first, __last) - * such that no other element in the range is larger. - */ - template - _GLIBCXX14_CONSTEXPR - inline pair<_ForwardIterator, _ForwardIterator> - minmax_element(_ForwardIterator __first, _ForwardIterator __last) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - return std::__minmax_element(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Return a pair of iterators pointing to the minimum and maximum - * elements in a range. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @param __comp Comparison functor. - * @return make_pair(m, M), where m is the first iterator i in - * [__first, __last) such that no other element in the range is - * smaller, and where M is the last iterator i in [__first, __last) - * such that no other element in the range is larger. - */ - template - _GLIBCXX14_CONSTEXPR - inline pair<_ForwardIterator, _ForwardIterator> - minmax_element(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - return std::__minmax_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - // N2722 + DR 915. - template - _GLIBCXX14_CONSTEXPR - inline _Tp - min(initializer_list<_Tp> __l) - { return *std::min_element(__l.begin(), __l.end()); } - - template - _GLIBCXX14_CONSTEXPR - inline _Tp - min(initializer_list<_Tp> __l, _Compare __comp) - { return *std::min_element(__l.begin(), __l.end(), __comp); } - - template - _GLIBCXX14_CONSTEXPR - inline _Tp - max(initializer_list<_Tp> __l) - { return *std::max_element(__l.begin(), __l.end()); } - - template - _GLIBCXX14_CONSTEXPR - inline _Tp - max(initializer_list<_Tp> __l, _Compare __comp) - { return *std::max_element(__l.begin(), __l.end(), __comp); } - - template - _GLIBCXX14_CONSTEXPR - inline pair<_Tp, _Tp> - minmax(initializer_list<_Tp> __l) - { - pair __p = - std::minmax_element(__l.begin(), __l.end()); - return std::make_pair(*__p.first, *__p.second); - } - - template - _GLIBCXX14_CONSTEXPR - inline pair<_Tp, _Tp> - minmax(initializer_list<_Tp> __l, _Compare __comp) - { - pair __p = - std::minmax_element(__l.begin(), __l.end(), __comp); - return std::make_pair(*__p.first, *__p.second); - } - - /** - * @brief Checks whether a permutation of the second sequence is equal - * to the first sequence. - * @ingroup non_mutating_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __pred A binary predicate. - * @return true if there exists a permutation of the elements in - * the range [__first2, __first2 + (__last1 - __first1)), - * beginning with ForwardIterator2 begin, such that - * equal(__first1, __last1, __begin, __pred) returns true; - * otherwise, returns false. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _BinaryPredicate __pred) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator1>::value_type, - typename iterator_traits<_ForwardIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - - return std::__is_permutation(__first1, __last1, __first2, - __gnu_cxx::__ops::__iter_comp_iter(__pred)); - } - -#if __cplusplus > 201103L - template - _GLIBCXX20_CONSTEXPR - bool - __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, - _BinaryPredicate __pred) - { - using _Cat1 - = typename iterator_traits<_ForwardIterator1>::iterator_category; - using _Cat2 - = typename iterator_traits<_ForwardIterator2>::iterator_category; - using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>; - using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>; - constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA(); - if (__ra_iters) - { - auto __d1 = std::distance(__first1, __last1); - auto __d2 = std::distance(__first2, __last2); - if (__d1 != __d2) - return false; - } - - // Efficiently compare identical prefixes: O(N) if sequences - // have the same elements in the same order. - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - if (!__pred(__first1, __first2)) - break; - - if (__ra_iters) - { - if (__first1 == __last1) - return true; - } - else - { - auto __d1 = std::distance(__first1, __last1); - auto __d2 = std::distance(__first2, __last2); - if (__d1 == 0 && __d2 == 0) - return true; - if (__d1 != __d2) - return false; - } - - for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) - { - if (__scan != std::__find_if(__first1, __scan, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) - continue; // We've seen this one before. - - auto __matches = std::__count_if(__first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); - if (0 == __matches - || std::__count_if(__scan, __last1, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) - != __matches) - return false; - } - return true; - } - - /** - * @brief Checks whether a permutaion of the second sequence is equal - * to the first sequence. - * @ingroup non_mutating_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of first range. - * @return true if there exists a permutation of the elements in the range - * [__first2, __last2), beginning with ForwardIterator2 begin, - * such that equal(__first1, __last1, begin) returns true; - * otherwise, returns false. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2) - { - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return - std::__is_permutation(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_equal_to_iter()); - } - - /** - * @brief Checks whether a permutation of the second sequence is equal - * to the first sequence. - * @ingroup non_mutating_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of first range. - * @param __pred A binary predicate. - * @return true if there exists a permutation of the elements in the range - * [__first2, __last2), beginning with ForwardIterator2 begin, - * such that equal(__first1, __last1, __begin, __pred) returns true; - * otherwise, returns false. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, - _BinaryPredicate __pred) - { - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return std::__is_permutation(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__pred)); - } - -#if __cplusplus > 201402L - -#define __cpp_lib_clamp 201603 - - /** - * @brief Returns the value clamped between lo and hi. - * @ingroup sorting_algorithms - * @param __val A value of arbitrary type. - * @param __lo A lower limit of arbitrary type. - * @param __hi An upper limit of arbitrary type. - * @return max(__val, __lo) if __val < __hi or min(__val, __hi) otherwise. - */ - template - constexpr const _Tp& - clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi) - { - __glibcxx_assert(!(__hi < __lo)); - return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val; - } - - /** - * @brief Returns the value clamped between lo and hi. - * @ingroup sorting_algorithms - * @param __val A value of arbitrary type. - * @param __lo A lower limit of arbitrary type. - * @param __hi An upper limit of arbitrary type. - * @param __comp A comparison functor. - * @return max(__val, __lo, __comp) if __comp(__val, __hi) - * or min(__val, __hi, __comp) otherwise. - */ - template - constexpr const _Tp& - clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Compare __comp) - { - __glibcxx_assert(!__comp(__hi, __lo)); - return __comp(__val, __lo) ? __lo : __comp(__hi, __val) ? __hi : __val; - } -#endif // C++17 -#endif // C++14 - -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - /** - * @brief Generate two uniformly distributed integers using a - * single distribution invocation. - * @param __b0 The upper bound for the first integer. - * @param __b1 The upper bound for the second integer. - * @param __g A UniformRandomBitGenerator. - * @return A pair (i, j) with i and j uniformly distributed - * over [0, __b0) and [0, __b1), respectively. - * - * Requires: __b0 * __b1 <= __g.max() - __g.min(). - * - * Using uniform_int_distribution with a range that is very - * small relative to the range of the generator ends up wasting - * potentially expensively generated randomness, since - * uniform_int_distribution does not store leftover randomness - * between invocations. - * - * If we know we want two integers in ranges that are sufficiently - * small, we can compose the ranges, use a single distribution - * invocation, and significantly reduce the waste. - */ - template - pair<_IntType, _IntType> - __gen_two_uniform_ints(_IntType __b0, _IntType __b1, - _UniformRandomBitGenerator&& __g) - { - _IntType __x - = uniform_int_distribution<_IntType>{0, (__b0 * __b1) - 1}(__g); - return std::make_pair(__x / __b1, __x % __b1); - } - - /** - * @brief Shuffle the elements of a sequence using a uniform random - * number generator. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __g A UniformRandomNumberGenerator (26.5.1.3). - * @return Nothing. - * - * Reorders the elements in the range @p [__first,__last) using @p __g to - * provide random numbers. - */ - template - void - shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, - _UniformRandomNumberGenerator&& __g) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return; - - typedef typename iterator_traits<_RandomAccessIterator>::difference_type - _DistanceType; - - typedef typename std::make_unsigned<_DistanceType>::type __ud_type; - typedef typename std::uniform_int_distribution<__ud_type> __distr_type; - typedef typename __distr_type::param_type __p_type; - - typedef typename remove_reference<_UniformRandomNumberGenerator>::type - _Gen; - typedef typename common_type::type - __uc_type; - - const __uc_type __urngrange = __g.max() - __g.min(); - const __uc_type __urange = __uc_type(__last - __first); - - if (__urngrange / __urange >= __urange) - // I.e. (__urngrange >= __urange * __urange) but without wrap issues. - { - _RandomAccessIterator __i = __first + 1; - - // Since we know the range isn't empty, an even number of elements - // means an uneven number of elements /to swap/, in which case we - // do the first one up front: - - if ((__urange % 2) == 0) - { - __distr_type __d{0, 1}; - std::iter_swap(__i++, __first + __d(__g)); - } - - // Now we know that __last - __i is even, so we do the rest in pairs, - // using a single distribution invocation to produce swap positions - // for two successive elements at a time: - - while (__i != __last) - { - const __uc_type __swap_range = __uc_type(__i - __first) + 1; - - const pair<__uc_type, __uc_type> __pospos = - __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g); - - std::iter_swap(__i++, __first + __pospos.first); - std::iter_swap(__i++, __first + __pospos.second); - } - - return; - } - - __distr_type __d; - - for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) - std::iter_swap(__i, __first + __d(__g, __p_type(0, __i - __first))); - } -#endif - -#endif // C++11 - -_GLIBCXX_BEGIN_NAMESPACE_ALGO - - /** - * @brief Apply a function to every element of a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __f A unary function object. - * @return @p __f - * - * Applies the function object @p __f to each element in the range - * @p [first,last). @p __f must not modify the order of the sequence. - * If @p __f has a return value it is ignored. - */ - template - _GLIBCXX20_CONSTEXPR - _Function - for_each(_InputIterator __first, _InputIterator __last, _Function __f) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_requires_valid_range(__first, __last); - for (; __first != __last; ++__first) - __f(*__first); - return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant. - } - -#if __cplusplus >= 201703L - /** - * @brief Apply a function to every element of a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __n A value convertible to an integer. - * @param __f A unary function object. - * @return `__first+__n` - * - * Applies the function object `__f` to each element in the range - * `[first, first+n)`. `__f` must not modify the order of the sequence. - * If `__f` has a return value it is ignored. - */ - template - _GLIBCXX20_CONSTEXPR - _InputIterator - for_each_n(_InputIterator __first, _Size __n, _Function __f) - { - auto __n2 = std::__size_to_integer(__n); - using _Cat = typename iterator_traits<_InputIterator>::iterator_category; - if constexpr (is_base_of_v) - { - if (__n2 <= 0) - return __first; - auto __last = __first + __n2; - std::for_each(__first, __last, std::move(__f)); - return __last; - } - else - { - while (__n2-->0) - { - __f(*__first); - ++__first; - } - return __first; - } - } -#endif // C++17 - - /** - * @brief Find the first occurrence of a value in a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __val The value to find. - * @return The first iterator @c i in the range @p [__first,__last) - * such that @c *i == @p __val, or @p __last if no such iterator exists. - */ - template - _GLIBCXX20_CONSTEXPR - inline _InputIterator - find(_InputIterator __first, _InputIterator __last, - const _Tp& __val) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - return std::__find_if(__first, __last, - __gnu_cxx::__ops::__iter_equals_val(__val)); - } - - /** - * @brief Find the first element in a sequence for which a - * predicate is true. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __pred A predicate. - * @return The first iterator @c i in the range @p [__first,__last) - * such that @p __pred(*i) is true, or @p __last if no such iterator exists. - */ - template - _GLIBCXX20_CONSTEXPR - inline _InputIterator - find_if(_InputIterator __first, _InputIterator __last, - _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__find_if(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); - } - - /** - * @brief Find element from a set in a sequence. - * @ingroup non_mutating_algorithms - * @param __first1 Start of range to search. - * @param __last1 End of range to search. - * @param __first2 Start of match candidates. - * @param __last2 End of match candidates. - * @return The first iterator @c i in the range - * @p [__first1,__last1) such that @c *i == @p *(i2) such that i2 is an - * iterator in [__first2,__last2), or @p __last1 if no such iterator exists. - * - * Searches the range @p [__first1,__last1) for an element that is - * equal to some element in the range [__first2,__last2). If - * found, returns an iterator in the range [__first1,__last1), - * otherwise returns @p __last1. - */ - template - _GLIBCXX20_CONSTEXPR - _InputIterator - find_first_of(_InputIterator __first1, _InputIterator __last1, - _ForwardIterator __first2, _ForwardIterator __last2) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - for (; __first1 != __last1; ++__first1) - for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) - if (*__first1 == *__iter) - return __first1; - return __last1; - } - - /** - * @brief Find element from a set in a sequence using a predicate. - * @ingroup non_mutating_algorithms - * @param __first1 Start of range to search. - * @param __last1 End of range to search. - * @param __first2 Start of match candidates. - * @param __last2 End of match candidates. - * @param __comp Predicate to use. - * @return The first iterator @c i in the range - * @p [__first1,__last1) such that @c comp(*i, @p *(i2)) is true - * and i2 is an iterator in [__first2,__last2), or @p __last1 if no - * such iterator exists. - * - - * Searches the range @p [__first1,__last1) for an element that is - * equal to some element in the range [__first2,__last2). If - * found, returns an iterator in the range [__first1,__last1), - * otherwise returns @p __last1. - */ - template - _GLIBCXX20_CONSTEXPR - _InputIterator - find_first_of(_InputIterator __first1, _InputIterator __last1, - _ForwardIterator __first2, _ForwardIterator __last2, - _BinaryPredicate __comp) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_InputIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - for (; __first1 != __last1; ++__first1) - for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) - if (__comp(*__first1, *__iter)) - return __first1; - return __last1; - } - - /** - * @brief Find two adjacent values in a sequence that are equal. - * @ingroup non_mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @return The first iterator @c i such that @c i and @c i+1 are both - * valid iterators in @p [__first,__last) and such that @c *i == @c *(i+1), - * or @p __last if no such iterator exists. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - adjacent_find(_ForwardIterator __first, _ForwardIterator __last) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_EqualityComparableConcept< - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__adjacent_find(__first, __last, - __gnu_cxx::__ops::__iter_equal_to_iter()); - } - - /** - * @brief Find two adjacent values in a sequence using a predicate. - * @ingroup non_mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __binary_pred A binary predicate. - * @return The first iterator @c i such that @c i and @c i+1 are both - * valid iterators in @p [__first,__last) and such that - * @p __binary_pred(*i,*(i+1)) is true, or @p __last if no such iterator - * exists. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - adjacent_find(_ForwardIterator __first, _ForwardIterator __last, - _BinaryPredicate __binary_pred) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__adjacent_find(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); - } - - /** - * @brief Count the number of copies of a value in a sequence. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __value The value to be counted. - * @return The number of iterators @c i in the range @p [__first,__last) - * for which @c *i == @p __value - */ - template - _GLIBCXX20_CONSTEXPR - inline typename iterator_traits<_InputIterator>::difference_type - count(_InputIterator __first, _InputIterator __last, const _Tp& __value) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__count_if(__first, __last, - __gnu_cxx::__ops::__iter_equals_val(__value)); - } - - /** - * @brief Count the elements of a sequence for which a predicate is true. - * @ingroup non_mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __pred A predicate. - * @return The number of iterators @c i in the range @p [__first,__last) - * for which @p __pred(*i) is true. - */ - template - _GLIBCXX20_CONSTEXPR - inline typename iterator_traits<_InputIterator>::difference_type - count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__count_if(__first, __last, - __gnu_cxx::__ops::__pred_iter(__pred)); - } - - /** - * @brief Search a sequence for a matching sub-sequence. - * @ingroup non_mutating_algorithms - * @param __first1 A forward iterator. - * @param __last1 A forward iterator. - * @param __first2 A forward iterator. - * @param __last2 A forward iterator. - * @return The first iterator @c i in the range @p - * [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == @p - * *(__first2+N) for each @c N in the range @p - * [0,__last2-__first2), or @p __last1 if no such iterator exists. - * - * Searches the range @p [__first1,__last1) for a sub-sequence that - * compares equal value-by-value with the sequence given by @p - * [__first2,__last2) and returns an iterator to the first element - * of the sub-sequence, or @p __last1 if the sub-sequence is not - * found. - * - * Because the sub-sequence must lie completely within the range @p - * [__first1,__last1) it must start at a position less than @p - * __last1-(__last2-__first2) where @p __last2-__first2 is the - * length of the sub-sequence. - * - * This means that the returned iterator @c i will be in the range - * @p [__first1,__last1-(__last2-__first2)) - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator1 - search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_ForwardIterator1>::value_type, - typename iterator_traits<_ForwardIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return std::__search(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_equal_to_iter()); - } - - /** - * @brief Search a sequence for a matching sub-sequence using a predicate. - * @ingroup non_mutating_algorithms - * @param __first1 A forward iterator. - * @param __last1 A forward iterator. - * @param __first2 A forward iterator. - * @param __last2 A forward iterator. - * @param __predicate A binary predicate. - * @return The first iterator @c i in the range - * @p [__first1,__last1-(__last2-__first2)) such that - * @p __predicate(*(i+N),*(__first2+N)) is true for each @c N in the range - * @p [0,__last2-__first2), or @p __last1 if no such iterator exists. - * - * Searches the range @p [__first1,__last1) for a sub-sequence that - * compares equal value-by-value with the sequence given by @p - * [__first2,__last2), using @p __predicate to determine equality, - * and returns an iterator to the first element of the - * sub-sequence, or @p __last1 if no such iterator exists. - * - * @see search(_ForwardIter1, _ForwardIter1, _ForwardIter2, _ForwardIter2) - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator1 - search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _ForwardIterator2 __last2, - _BinaryPredicate __predicate) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator1>::value_type, - typename iterator_traits<_ForwardIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return std::__search(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__predicate)); - } - - /** - * @brief Search a sequence for a number of consecutive values. - * @ingroup non_mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __count The number of consecutive values. - * @param __val The value to find. - * @return The first iterator @c i in the range @p - * [__first,__last-__count) such that @c *(i+N) == @p __val for - * each @c N in the range @p [0,__count), or @p __last if no such - * iterator exists. - * - * Searches the range @p [__first,__last) for @p count consecutive elements - * equal to @p __val. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - search_n(_ForwardIterator __first, _ForwardIterator __last, - _Integer __count, const _Tp& __val) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_ForwardIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__search_n(__first, __last, __count, - __gnu_cxx::__ops::__iter_equals_val(__val)); - } - - - /** - * @brief Search a sequence for a number of consecutive values using a - * predicate. - * @ingroup non_mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __count The number of consecutive values. - * @param __val The value to find. - * @param __binary_pred A binary predicate. - * @return The first iterator @c i in the range @p - * [__first,__last-__count) such that @p - * __binary_pred(*(i+N),__val) is true for each @c N in the range - * @p [0,__count), or @p __last if no such iterator exists. - * - * Searches the range @p [__first,__last) for @p __count - * consecutive elements for which the predicate returns true. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - search_n(_ForwardIterator __first, _ForwardIterator __last, - _Integer __count, const _Tp& __val, - _BinaryPredicate __binary_pred) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, - typename iterator_traits<_ForwardIterator>::value_type, _Tp>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__search_n(__first, __last, __count, - __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val)); - } - -#if __cplusplus > 201402L - /** @brief Search a sequence using a Searcher object. - * - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __searcher A callable object. - * @return @p __searcher(__first,__last).first - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - search(_ForwardIterator __first, _ForwardIterator __last, - const _Searcher& __searcher) - { return __searcher(__first, __last).first; } -#endif - - /** - * @brief Perform an operation on a sequence. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @param __unary_op A unary operator. - * @return An output iterator equal to @p __result+(__last-__first). - * - * Applies the operator to each element in the input range and assigns - * the results to successive elements of the output sequence. - * Evaluates @p *(__result+N)=unary_op(*(__first+N)) for each @c N in the - * range @p [0,__last-__first). - * - * @p unary_op must not alter its argument. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - transform(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _UnaryOperation __unary_op) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - // "the type returned by a _UnaryOperation" - __typeof__(__unary_op(*__first))>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first, (void)++__result) - *__result = __unary_op(*__first); - return __result; - } - - /** - * @brief Perform an operation on corresponding elements of two sequences. - * @ingroup mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __result An output iterator. - * @param __binary_op A binary operator. - * @return An output iterator equal to @p result+(last-first). - * - * Applies the operator to the corresponding elements in the two - * input ranges and assigns the results to successive elements of the - * output sequence. - * Evaluates @p - * *(__result+N)=__binary_op(*(__first1+N),*(__first2+N)) for each - * @c N in the range @p [0,__last1-__first1). - * - * @p binary_op must not alter either of its arguments. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - transform(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _OutputIterator __result, - _BinaryOperation __binary_op) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - // "the type returned by a _BinaryOperation" - __typeof__(__binary_op(*__first1,*__first2))>) - __glibcxx_requires_valid_range(__first1, __last1); - - for (; __first1 != __last1; ++__first1, (void)++__first2, ++__result) - *__result = __binary_op(*__first1, *__first2); - return __result; - } - - /** - * @brief Replace each occurrence of one value in a sequence with another - * value. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __old_value The value to be replaced. - * @param __new_value The replacement value. - * @return replace() returns no value. - * - * For each iterator @c i in the range @p [__first,__last) if @c *i == - * @p __old_value then the assignment @c *i = @p __new_value is performed. - */ - template - _GLIBCXX20_CONSTEXPR - void - replace(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __old_value, const _Tp& __new_value) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_ForwardIterator>::value_type, _Tp>) - __glibcxx_function_requires(_ConvertibleConcept<_Tp, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first) - if (*__first == __old_value) - *__first = __new_value; - } - - /** - * @brief Replace each value in a sequence for which a predicate returns - * true with another value. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __pred A predicate. - * @param __new_value The replacement value. - * @return replace_if() returns no value. - * - * For each iterator @c i in the range @p [__first,__last) if @p __pred(*i) - * is true then the assignment @c *i = @p __new_value is performed. - */ - template - _GLIBCXX20_CONSTEXPR - void - replace_if(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred, const _Tp& __new_value) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_ConvertibleConcept<_Tp, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first) - if (__pred(*__first)) - *__first = __new_value; - } - - /** - * @brief Assign the result of a function object to each value in a - * sequence. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __gen A function object taking no arguments and returning - * std::iterator_traits<_ForwardIterator>::value_type - * @return generate() returns no value. - * - * Performs the assignment @c *i = @p __gen() for each @c i in the range - * @p [__first,__last). - */ - template - _GLIBCXX20_CONSTEXPR - void - generate(_ForwardIterator __first, _ForwardIterator __last, - _Generator __gen) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_GeneratorConcept<_Generator, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first) - *__first = __gen(); - } - - /** - * @brief Assign the result of a function object to each value in a - * sequence. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __n The length of the sequence. - * @param __gen A function object taking no arguments and returning - * std::iterator_traits<_ForwardIterator>::value_type - * @return The end of the sequence, @p __first+__n - * - * Performs the assignment @c *i = @p __gen() for each @c i in the range - * @p [__first,__first+__n). - * - * If @p __n is negative, the function does nothing and returns @p __first. - */ - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 865. More algorithms that throw away information - // DR 426. search_n(), fill_n(), and generate_n() with negative n - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - generate_n(_OutputIterator __first, _Size __n, _Generator __gen) - { - // concept requirements - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - // "the type returned by a _Generator" - __typeof__(__gen())>) - - typedef __decltype(std::__size_to_integer(__n)) _IntSize; - for (_IntSize __niter = std::__size_to_integer(__n); - __niter > 0; --__niter, (void) ++__first) - *__first = __gen(); - return __first; - } - - /** - * @brief Copy a sequence, removing consecutive duplicate values. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @return An iterator designating the end of the resulting sequence. - * - * Copies each element in the range @p [__first,__last) to the range - * beginning at @p __result, except that only the first element is copied - * from groups of consecutive elements that compare equal. - * unique_copy() is stable, so the relative order of elements that are - * copied is unchanged. - * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 241. Does unique_copy() require CopyConstructible and Assignable? - * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 538. 241 again: Does unique_copy() require CopyConstructible and - * Assignable? - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - unique_copy(_InputIterator __first, _InputIterator __last, - _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_function_requires(_EqualityComparableConcept< - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return __result; - return std::__unique_copy(__first, __last, __result, - __gnu_cxx::__ops::__iter_equal_to_iter(), - std::__iterator_category(__first), - std::__iterator_category(__result)); - } - - /** - * @brief Copy a sequence, removing consecutive values using a predicate. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @param __binary_pred A binary predicate. - * @return An iterator designating the end of the resulting sequence. - * - * Copies each element in the range @p [__first,__last) to the range - * beginning at @p __result, except that only the first element is copied - * from groups of consecutive elements for which @p __binary_pred returns - * true. - * unique_copy() is stable, so the relative order of elements that are - * copied is unchanged. - * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 241. Does unique_copy() require CopyConstructible and Assignable? - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - unique_copy(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, - _BinaryPredicate __binary_pred) - { - // concept requirements -- predicates checked later - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return __result; - return std::__unique_copy(__first, __last, __result, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred), - std::__iterator_category(__first), - std::__iterator_category(__result)); - } - -#if _GLIBCXX_HOSTED - /** - * @brief Randomly shuffle the elements of a sequence. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @return Nothing. - * - * Reorder the elements in the range @p [__first,__last) using a random - * distribution, so that every possible ordering of the sequence is - * equally likely. - */ - template - inline void - random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first != __last) - for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) - { - // XXX rand() % N is not uniformly distributed - _RandomAccessIterator __j = __first - + std::rand() % ((__i - __first) + 1); - if (__i != __j) - std::iter_swap(__i, __j); - } - } -#endif - - /** - * @brief Shuffle the elements of a sequence using a random number - * generator. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __rand The RNG functor or function. - * @return Nothing. - * - * Reorders the elements in the range @p [__first,__last) using @p __rand to - * provide a random distribution. Calling @p __rand(N) for a positive - * integer @p N should return a randomly chosen integer from the - * range [0,N). - */ - template - void - random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, -#if __cplusplus >= 201103L - _RandomNumberGenerator&& __rand) -#else - _RandomNumberGenerator& __rand) -#endif - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return; - for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) - { - _RandomAccessIterator __j = __first + __rand((__i - __first) + 1); - if (__i != __j) - std::iter_swap(__i, __j); - } - } - - - /** - * @brief Move elements for which a predicate is true to the beginning - * of a sequence. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __pred A predicate functor. - * @return An iterator @p middle such that @p __pred(i) is true for each - * iterator @p i in the range @p [__first,middle) and false for each @p i - * in the range @p [middle,__last). - * - * @p __pred must not modify its operand. @p partition() does not preserve - * the relative ordering of elements in each group, use - * @p stable_partition() if this is needed. - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - partition(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__partition(__first, __last, __pred, - std::__iterator_category(__first)); - } - - - /** - * @brief Sort the smallest elements of a sequence. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __middle Another iterator. - * @param __last Another iterator. - * @return Nothing. - * - * Sorts the smallest @p (__middle-__first) elements in the range - * @p [first,last) and moves them to the range @p [__first,__middle). The - * order of the remaining elements in the range @p [__middle,__last) is - * undefined. - * After the sort if @e i and @e j are iterators in the range - * @p [__first,__middle) such that i precedes j and @e k is an iterator in - * the range @p [__middle,__last) then *j<*i and *k<*i are both false. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - partial_sort(_RandomAccessIterator __first, - _RandomAccessIterator __middle, - _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __middle); - __glibcxx_requires_valid_range(__middle, __last); - __glibcxx_requires_irreflexive(__first, __last); - - std::__partial_sort(__first, __middle, __last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Sort the smallest elements of a sequence using a predicate - * for comparison. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __middle Another iterator. - * @param __last Another iterator. - * @param __comp A comparison functor. - * @return Nothing. - * - * Sorts the smallest @p (__middle-__first) elements in the range - * @p [__first,__last) and moves them to the range @p [__first,__middle). The - * order of the remaining elements in the range @p [__middle,__last) is - * undefined. - * After the sort if @e i and @e j are iterators in the range - * @p [__first,__middle) such that i precedes j and @e k is an iterator in - * the range @p [__middle,__last) then @p *__comp(j,*i) and @p __comp(*k,*i) - * are both false. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - partial_sort(_RandomAccessIterator __first, - _RandomAccessIterator __middle, - _RandomAccessIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_RandomAccessIterator>::value_type, - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __middle); - __glibcxx_requires_valid_range(__middle, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - std::__partial_sort(__first, __middle, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - /** - * @brief Sort a sequence just enough to find a particular position. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __nth Another iterator. - * @param __last Another iterator. - * @return Nothing. - * - * Rearranges the elements in the range @p [__first,__last) so that @p *__nth - * is the same element that would have been in that position had the - * whole sequence been sorted. The elements either side of @p *__nth are - * not completely sorted, but for any iterator @e i in the range - * @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it - * holds that *j < *i is false. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, - _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __nth); - __glibcxx_requires_valid_range(__nth, __last); - __glibcxx_requires_irreflexive(__first, __last); - - if (__first == __last || __nth == __last) - return; - - std::__introselect(__first, __nth, __last, - std::__lg(__last - __first) * 2, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Sort a sequence just enough to find a particular position - * using a predicate for comparison. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __nth Another iterator. - * @param __last Another iterator. - * @param __comp A comparison functor. - * @return Nothing. - * - * Rearranges the elements in the range @p [__first,__last) so that @p *__nth - * is the same element that would have been in that position had the - * whole sequence been sorted. The elements either side of @p *__nth are - * not completely sorted, but for any iterator @e i in the range - * @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it - * holds that @p __comp(*j,*i) is false. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, - _RandomAccessIterator __last, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_RandomAccessIterator>::value_type, - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __nth); - __glibcxx_requires_valid_range(__nth, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - if (__first == __last || __nth == __last) - return; - - std::__introselect(__first, __nth, __last, - std::__lg(__last - __first) * 2, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - /** - * @brief Sort the elements of a sequence. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @return Nothing. - * - * Sorts the elements in the range @p [__first,__last) in ascending order, - * such that for each iterator @e i in the range @p [__first,__last-1), - * *(i+1)<*i is false. - * - * The relative ordering of equivalent elements is not preserved, use - * @p stable_sort() if this is needed. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - sort(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Sort the elements of a sequence using a predicate for comparison. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __comp A comparison functor. - * @return Nothing. - * - * Sorts the elements in the range @p [__first,__last) in ascending order, - * such that @p __comp(*(i+1),*i) is false for every iterator @e i in the - * range @p [__first,__last-1). - * - * The relative ordering of equivalent elements is not preserved, use - * @p stable_sort() if this is needed. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - sort(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_RandomAccessIterator>::value_type, - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __merge(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - { - if (__comp(__first2, __first1)) - { - *__result = *__first2; - ++__first2; - } - else - { - *__result = *__first1; - ++__first1; - } - ++__result; - } - return std::copy(__first2, __last2, - std::copy(__first1, __last1, __result)); - } - - /** - * @brief Merges two sorted ranges. - * @ingroup sorting_algorithms - * @param __first1 An iterator. - * @param __first2 Another iterator. - * @param __last1 Another iterator. - * @param __last2 Another iterator. - * @param __result An iterator pointing to the end of the merged range. - * @return An output iterator equal to @p __result + (__last1 - __first1) - * + (__last2 - __first2). - * - * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into - * the sorted range @p [__result, __result + (__last1-__first1) + - * (__last2-__first2)). Both input ranges must be sorted, and the - * output range must not overlap with either of the input ranges. - * The sort is @e stable, that is, for equivalent elements in the - * two ranges, elements from the first range will always come - * before elements from the second. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - merge(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set(__first1, __last1, __first2); - __glibcxx_requires_sorted_set(__first2, __last2, __first1); - __glibcxx_requires_irreflexive2(__first1, __last1); - __glibcxx_requires_irreflexive2(__first2, __last2); - - return _GLIBCXX_STD_A::__merge(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Merges two sorted ranges. - * @ingroup sorting_algorithms - * @param __first1 An iterator. - * @param __first2 Another iterator. - * @param __last1 Another iterator. - * @param __last2 Another iterator. - * @param __result An iterator pointing to the end of the merged range. - * @param __comp A functor to use for comparisons. - * @return An output iterator equal to @p __result + (__last1 - __first1) - * + (__last2 - __first2). - * - * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into - * the sorted range @p [__result, __result + (__last1-__first1) + - * (__last2-__first2)). Both input ranges must be sorted, and the - * output range must not overlap with either of the input ranges. - * The sort is @e stable, that is, for equivalent elements in the - * two ranges, elements from the first range will always come - * before elements from the second. - * - * The comparison function should have the same effects on ordering as - * the function used for the initial sort. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - merge(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); - __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); - __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); - __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - - return _GLIBCXX_STD_A::__merge(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - inline void - __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _ValueType; - typedef typename iterator_traits<_RandomAccessIterator>::difference_type - _DistanceType; - - typedef _Temporary_buffer<_RandomAccessIterator, _ValueType> _TmpBuf; - _TmpBuf __buf(__first, std::distance(__first, __last)); - - if (__buf.begin() == 0) - std::__inplace_stable_sort(__first, __last, __comp); - else - std::__stable_sort_adaptive(__first, __last, __buf.begin(), - _DistanceType(__buf.size()), __comp); - } - - /** - * @brief Sort the elements of a sequence, preserving the relative order - * of equivalent elements. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @return Nothing. - * - * Sorts the elements in the range @p [__first,__last) in ascending order, - * such that for each iterator @p i in the range @p [__first,__last-1), - * @p *(i+1)<*i is false. - * - * The relative ordering of equivalent elements is preserved, so any two - * elements @p x and @p y in the range @p [__first,__last) such that - * @p x - inline void - stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - _GLIBCXX_STD_A::__stable_sort(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Sort the elements of a sequence using a predicate for comparison, - * preserving the relative order of equivalent elements. - * @ingroup sorting_algorithms - * @param __first An iterator. - * @param __last Another iterator. - * @param __comp A comparison functor. - * @return Nothing. - * - * Sorts the elements in the range @p [__first,__last) in ascending order, - * such that for each iterator @p i in the range @p [__first,__last-1), - * @p __comp(*(i+1),*i) is false. - * - * The relative ordering of equivalent elements is preserved, so any two - * elements @p x and @p y in the range @p [__first,__last) such that - * @p __comp(x,y) is false and @p __comp(y,x) is false will have the same - * relative ordering after calling @p stable_sort(). - */ - template - inline void - stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_RandomAccessIterator>::value_type, - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - _GLIBCXX_STD_A::__stable_sort(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __set_union(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - { - if (__comp(__first1, __first2)) - { - *__result = *__first1; - ++__first1; - } - else if (__comp(__first2, __first1)) - { - *__result = *__first2; - ++__first2; - } - else - { - *__result = *__first1; - ++__first1; - ++__first2; - } - ++__result; - } - return std::copy(__first2, __last2, - std::copy(__first1, __last1, __result)); - } - - /** - * @brief Return the union of two sorted ranges. - * @ingroup set_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of second range. - * @param __result Start of output range. - * @return End of the output range. - * @ingroup set_algorithms - * - * This operation iterates over both ranges, copying elements present in - * each range in order to the output range. Iterators increment for each - * range. When the current element of one range is less than the other, - * that element is copied and the iterator advanced. If an element is - * contained in both ranges, the element from the first range is copied and - * both ranges advance. The output range may not overlap either input - * range. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - set_union(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set(__first1, __last1, __first2); - __glibcxx_requires_sorted_set(__first2, __last2, __first1); - __glibcxx_requires_irreflexive2(__first1, __last1); - __glibcxx_requires_irreflexive2(__first2, __last2); - - return _GLIBCXX_STD_A::__set_union(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Return the union of two sorted ranges using a comparison functor. - * @ingroup set_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of second range. - * @param __result Start of output range. - * @param __comp The comparison functor. - * @return End of the output range. - * @ingroup set_algorithms - * - * This operation iterates over both ranges, copying elements present in - * each range in order to the output range. Iterators increment for each - * range. When the current element of one range is less than the other - * according to @p __comp, that element is copied and the iterator advanced. - * If an equivalent element according to @p __comp is contained in both - * ranges, the element from the first range is copied and both ranges - * advance. The output range may not overlap either input range. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - set_union(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); - __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); - __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); - __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - - return _GLIBCXX_STD_A::__set_union(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - if (__comp(__first1, __first2)) - ++__first1; - else if (__comp(__first2, __first1)) - ++__first2; - else - { - *__result = *__first1; - ++__first1; - ++__first2; - ++__result; - } - return __result; - } - - /** - * @brief Return the intersection of two sorted ranges. - * @ingroup set_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of second range. - * @param __result Start of output range. - * @return End of the output range. - * @ingroup set_algorithms - * - * This operation iterates over both ranges, copying elements present in - * both ranges in order to the output range. Iterators increment for each - * range. When the current element of one range is less than the other, - * that iterator advances. If an element is contained in both ranges, the - * element from the first range is copied and both ranges advance. The - * output range may not overlap either input range. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set(__first1, __last1, __first2); - __glibcxx_requires_sorted_set(__first2, __last2, __first1); - __glibcxx_requires_irreflexive2(__first1, __last1); - __glibcxx_requires_irreflexive2(__first2, __last2); - - return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Return the intersection of two sorted ranges using comparison - * functor. - * @ingroup set_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of second range. - * @param __result Start of output range. - * @param __comp The comparison functor. - * @return End of the output range. - * @ingroup set_algorithms - * - * This operation iterates over both ranges, copying elements present in - * both ranges in order to the output range. Iterators increment for each - * range. When the current element of one range is less than the other - * according to @p __comp, that iterator advances. If an element is - * contained in both ranges according to @p __comp, the element from the - * first range is copied and both ranges advance. The output range may not - * overlap either input range. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); - __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); - __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); - __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - - return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __set_difference(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - if (__comp(__first1, __first2)) - { - *__result = *__first1; - ++__first1; - ++__result; - } - else if (__comp(__first2, __first1)) - ++__first2; - else - { - ++__first1; - ++__first2; - } - return std::copy(__first1, __last1, __result); - } - - /** - * @brief Return the difference of two sorted ranges. - * @ingroup set_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of second range. - * @param __result Start of output range. - * @return End of the output range. - * @ingroup set_algorithms - * - * This operation iterates over both ranges, copying elements present in - * the first range but not the second in order to the output range. - * Iterators increment for each range. When the current element of the - * first range is less than the second, that element is copied and the - * iterator advances. If the current element of the second range is less, - * the iterator advances, but no element is copied. If an element is - * contained in both ranges, no elements are copied and both ranges - * advance. The output range may not overlap either input range. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - set_difference(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set(__first1, __last1, __first2); - __glibcxx_requires_sorted_set(__first2, __last2, __first1); - __glibcxx_requires_irreflexive2(__first1, __last1); - __glibcxx_requires_irreflexive2(__first2, __last2); - - return _GLIBCXX_STD_A::__set_difference(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Return the difference of two sorted ranges using comparison - * functor. - * @ingroup set_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of second range. - * @param __result Start of output range. - * @param __comp The comparison functor. - * @return End of the output range. - * @ingroup set_algorithms - * - * This operation iterates over both ranges, copying elements present in - * the first range but not the second in order to the output range. - * Iterators increment for each range. When the current element of the - * first range is less than the second according to @p __comp, that element - * is copied and the iterator advances. If the current element of the - * second range is less, no element is copied and the iterator advances. - * If an element is contained in both ranges according to @p __comp, no - * elements are copied and both ranges advance. The output range may not - * overlap either input range. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - set_difference(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); - __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); - __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); - __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - - return _GLIBCXX_STD_A::__set_difference(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - __set_symmetric_difference(_InputIterator1 __first1, - _InputIterator1 __last1, - _InputIterator2 __first2, - _InputIterator2 __last2, - _OutputIterator __result, - _Compare __comp) - { - while (__first1 != __last1 && __first2 != __last2) - if (__comp(__first1, __first2)) - { - *__result = *__first1; - ++__first1; - ++__result; - } - else if (__comp(__first2, __first1)) - { - *__result = *__first2; - ++__first2; - ++__result; - } - else - { - ++__first1; - ++__first2; - } - return std::copy(__first2, __last2, - std::copy(__first1, __last1, __result)); - } - - /** - * @brief Return the symmetric difference of two sorted ranges. - * @ingroup set_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of second range. - * @param __result Start of output range. - * @return End of the output range. - * @ingroup set_algorithms - * - * This operation iterates over both ranges, copying elements present in - * one range but not the other in order to the output range. Iterators - * increment for each range. When the current element of one range is less - * than the other, that element is copied and the iterator advances. If an - * element is contained in both ranges, no elements are copied and both - * ranges advance. The output range may not overlap either input range. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set(__first1, __last1, __first2); - __glibcxx_requires_sorted_set(__first2, __last2, __first1); - __glibcxx_requires_irreflexive2(__first1, __last1); - __glibcxx_requires_irreflexive2(__first2, __last2); - - return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Return the symmetric difference of two sorted ranges using - * comparison functor. - * @ingroup set_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __last2 End of second range. - * @param __result Start of output range. - * @param __comp The comparison functor. - * @return End of the output range. - * @ingroup set_algorithms - * - * This operation iterates over both ranges, copying elements present in - * one range but not the other in order to the output range. Iterators - * increment for each range. When the current element of one range is less - * than the other according to @p comp, that element is copied and the - * iterator advances. If an element is contained in both ranges according - * to @p __comp, no elements are copied and both ranges advance. The output - * range may not overlap either input range. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _OutputIterator __result, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_InputIterator2>::value_type, - typename iterator_traits<_InputIterator1>::value_type>) - __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); - __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); - __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); - __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); - - return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, - __first2, __last2, __result, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - _GLIBCXX14_CONSTEXPR - _ForwardIterator - __min_element(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { - if (__first == __last) - return __first; - _ForwardIterator __result = __first; - while (++__first != __last) - if (__comp(__first, __result)) - __result = __first; - return __result; - } - - /** - * @brief Return the minimum element in a range. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @return Iterator referencing the first instance of the smallest value. - */ - template - _GLIBCXX14_CONSTEXPR - _ForwardIterator - inline min_element(_ForwardIterator __first, _ForwardIterator __last) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - return _GLIBCXX_STD_A::__min_element(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Return the minimum element in a range using comparison functor. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @param __comp Comparison functor. - * @return Iterator referencing the first instance of the smallest value - * according to __comp. - */ - template - _GLIBCXX14_CONSTEXPR - inline _ForwardIterator - min_element(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - return _GLIBCXX_STD_A::__min_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - - template - _GLIBCXX14_CONSTEXPR - _ForwardIterator - __max_element(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { - if (__first == __last) return __first; - _ForwardIterator __result = __first; - while (++__first != __last) - if (__comp(__result, __first)) - __result = __first; - return __result; - } - - /** - * @brief Return the maximum element in a range. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @return Iterator referencing the first instance of the largest value. - */ - template - _GLIBCXX14_CONSTEXPR - inline _ForwardIterator - max_element(_ForwardIterator __first, _ForwardIterator __last) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - return _GLIBCXX_STD_A::__max_element(__first, __last, - __gnu_cxx::__ops::__iter_less_iter()); - } - - /** - * @brief Return the maximum element in a range using comparison functor. - * @ingroup sorting_algorithms - * @param __first Start of range. - * @param __last End of range. - * @param __comp Comparison functor. - * @return Iterator referencing the first instance of the largest value - * according to __comp. - */ - template - _GLIBCXX14_CONSTEXPR - inline _ForwardIterator - max_element(_ForwardIterator __first, _ForwardIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, - typename iterator_traits<_ForwardIterator>::value_type, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - return _GLIBCXX_STD_A::__max_element(__first, __last, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - -#if __cplusplus >= 201402L - /// Reservoir sampling algorithm. - template - _RandomAccessIterator - __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag, - _RandomAccessIterator __out, random_access_iterator_tag, - _Size __n, _UniformRandomBitGenerator&& __g) - { - using __distrib_type = uniform_int_distribution<_Size>; - using __param_type = typename __distrib_type::param_type; - __distrib_type __d{}; - _Size __sample_sz = 0; - while (__first != __last && __sample_sz != __n) - { - __out[__sample_sz++] = *__first; - ++__first; - } - for (auto __pop_sz = __sample_sz; __first != __last; - ++__first, (void) ++__pop_sz) - { - const auto __k = __d(__g, __param_type{0, __pop_sz}); - if (__k < __n) - __out[__k] = *__first; - } - return __out + __sample_sz; - } - - /// Selection sampling algorithm. - template - _OutputIterator - __sample(_ForwardIterator __first, _ForwardIterator __last, - forward_iterator_tag, - _OutputIterator __out, _Cat, - _Size __n, _UniformRandomBitGenerator&& __g) - { - using __distrib_type = uniform_int_distribution<_Size>; - using __param_type = typename __distrib_type::param_type; - using _USize = make_unsigned_t<_Size>; - using _Gen = remove_reference_t<_UniformRandomBitGenerator>; - using __uc_type = common_type_t; - - if (__first == __last) - return __out; - - __distrib_type __d{}; - _Size __unsampled_sz = std::distance(__first, __last); - __n = std::min(__n, __unsampled_sz); - - // If possible, we use __gen_two_uniform_ints to efficiently produce - // two random numbers using a single distribution invocation: - - const __uc_type __urngrange = __g.max() - __g.min(); - if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz)) - // I.e. (__urngrange >= __unsampled_sz * __unsampled_sz) but without - // wrapping issues. - { - while (__n != 0 && __unsampled_sz >= 2) - { - const pair<_Size, _Size> __p = - __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g); - - --__unsampled_sz; - if (__p.first < __n) - { - *__out++ = *__first; - --__n; - } - - ++__first; - - if (__n == 0) break; - - --__unsampled_sz; - if (__p.second < __n) - { - *__out++ = *__first; - --__n; - } - - ++__first; - } - } - - // The loop above is otherwise equivalent to this one-at-a-time version: - - for (; __n != 0; ++__first) - if (__d(__g, __param_type{0, --__unsampled_sz}) < __n) - { - *__out++ = *__first; - --__n; - } - return __out; - } - -#if __cplusplus > 201402L -#define __cpp_lib_sample 201603 - /// Take a random sample from a population. - template - _SampleIterator - sample(_PopulationIterator __first, _PopulationIterator __last, - _SampleIterator __out, _Distance __n, - _UniformRandomBitGenerator&& __g) - { - using __pop_cat = typename - std::iterator_traits<_PopulationIterator>::iterator_category; - using __samp_cat = typename - std::iterator_traits<_SampleIterator>::iterator_category; - - static_assert( - __or_, - is_convertible<__samp_cat, random_access_iterator_tag>>::value, - "output range must use a RandomAccessIterator when input range" - " does not meet the ForwardIterator requirements"); - - static_assert(is_integral<_Distance>::value, - "sample size must be an integer type"); - - typename iterator_traits<_PopulationIterator>::difference_type __d = __n; - return _GLIBCXX_STD_A:: - __sample(__first, __last, __pop_cat{}, __out, __samp_cat{}, __d, - std::forward<_UniformRandomBitGenerator>(__g)); - } -#endif // C++17 -#endif // C++14 - -_GLIBCXX_END_NAMESPACE_ALGO -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_ALGO_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h b/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h deleted file mode 100644 index dd2bd1727..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h +++ /dev/null @@ -1,1959 +0,0 @@ -// Core algorithmic facilities -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996-1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_algobase.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{algorithm} - */ - -#ifndef _STL_ALGOBASE_H -#define _STL_ALGOBASE_H 1 - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include // For std::swap -#include -#if __cplusplus >= 201103L -# include -#endif -#if __cplusplus > 201703L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /* - * A constexpr wrapper for __builtin_memcmp. - * @param __num The number of elements of type _Tp (not bytes). - */ - template - _GLIBCXX14_CONSTEXPR - inline int - __memcmp(const _Tp* __first1, const _Up* __first2, size_t __num) - { -#if __cplusplus >= 201103L - static_assert(sizeof(_Tp) == sizeof(_Up), "can be compared with memcmp"); -#endif -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - { - for(; __num > 0; ++__first1, ++__first2, --__num) - if (*__first1 != *__first2) - return *__first1 < *__first2 ? -1 : 1; - return 0; - } - else -#endif - return __builtin_memcmp(__first1, __first2, sizeof(_Tp) * __num); - } - -#if __cplusplus < 201103L - // See http://gcc.gnu.org/ml/libstdc++/2004-08/msg00167.html: in a - // nutshell, we are partially implementing the resolution of DR 187, - // when it's safe, i.e., the value_types are equal. - template - struct __iter_swap - { - template - static void - iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) - { - typedef typename iterator_traits<_ForwardIterator1>::value_type - _ValueType1; - _ValueType1 __tmp = *__a; - *__a = *__b; - *__b = __tmp; - } - }; - - template<> - struct __iter_swap - { - template - static void - iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) - { - swap(*__a, *__b); - } - }; -#endif // C++03 - - /** - * @brief Swaps the contents of two iterators. - * @ingroup mutating_algorithms - * @param __a An iterator. - * @param __b Another iterator. - * @return Nothing. - * - * This function swaps the values pointed to by two iterators, not the - * iterators themselves. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator1>) - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator2>) - -#if __cplusplus < 201103L - typedef typename iterator_traits<_ForwardIterator1>::value_type - _ValueType1; - typedef typename iterator_traits<_ForwardIterator2>::value_type - _ValueType2; - - __glibcxx_function_requires(_ConvertibleConcept<_ValueType1, - _ValueType2>) - __glibcxx_function_requires(_ConvertibleConcept<_ValueType2, - _ValueType1>) - - typedef typename iterator_traits<_ForwardIterator1>::reference - _ReferenceType1; - typedef typename iterator_traits<_ForwardIterator2>::reference - _ReferenceType2; - std::__iter_swap<__are_same<_ValueType1, _ValueType2>::__value - && __are_same<_ValueType1&, _ReferenceType1>::__value - && __are_same<_ValueType2&, _ReferenceType2>::__value>:: - iter_swap(__a, __b); -#else - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 187. iter_swap underspecified - swap(*__a, *__b); -#endif - } - - /** - * @brief Swap the elements of two sequences. - * @ingroup mutating_algorithms - * @param __first1 A forward iterator. - * @param __last1 A forward iterator. - * @param __first2 A forward iterator. - * @return An iterator equal to @p first2+(last1-first1). - * - * Swaps each element in the range @p [first1,last1) with the - * corresponding element in the range @p [first2,(last1-first1)). - * The ranges must not overlap. - */ - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator2 - swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator1>) - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator2>) - __glibcxx_requires_valid_range(__first1, __last1); - - for (; __first1 != __last1; ++__first1, (void)++__first2) - std::iter_swap(__first1, __first2); - return __first2; - } - - /** - * @brief This does what you think it does. - * @ingroup sorting_algorithms - * @param __a A thing of arbitrary type. - * @param __b Another thing of arbitrary type. - * @return The lesser of the parameters. - * - * This is the simple classic generic implementation. It will work on - * temporary expressions, since they are only evaluated once, unlike a - * preprocessor macro. - */ - template - _GLIBCXX14_CONSTEXPR - inline const _Tp& - min(const _Tp& __a, const _Tp& __b) - { - // concept requirements - __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) - //return __b < __a ? __b : __a; - if (__b < __a) - return __b; - return __a; - } - - /** - * @brief This does what you think it does. - * @ingroup sorting_algorithms - * @param __a A thing of arbitrary type. - * @param __b Another thing of arbitrary type. - * @return The greater of the parameters. - * - * This is the simple classic generic implementation. It will work on - * temporary expressions, since they are only evaluated once, unlike a - * preprocessor macro. - */ - template - _GLIBCXX14_CONSTEXPR - inline const _Tp& - max(const _Tp& __a, const _Tp& __b) - { - // concept requirements - __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) - //return __a < __b ? __b : __a; - if (__a < __b) - return __b; - return __a; - } - - /** - * @brief This does what you think it does. - * @ingroup sorting_algorithms - * @param __a A thing of arbitrary type. - * @param __b Another thing of arbitrary type. - * @param __comp A @link comparison_functors comparison functor@endlink. - * @return The lesser of the parameters. - * - * This will work on temporary expressions, since they are only evaluated - * once, unlike a preprocessor macro. - */ - template - _GLIBCXX14_CONSTEXPR - inline const _Tp& - min(const _Tp& __a, const _Tp& __b, _Compare __comp) - { - //return __comp(__b, __a) ? __b : __a; - if (__comp(__b, __a)) - return __b; - return __a; - } - - /** - * @brief This does what you think it does. - * @ingroup sorting_algorithms - * @param __a A thing of arbitrary type. - * @param __b Another thing of arbitrary type. - * @param __comp A @link comparison_functors comparison functor@endlink. - * @return The greater of the parameters. - * - * This will work on temporary expressions, since they are only evaluated - * once, unlike a preprocessor macro. - */ - template - _GLIBCXX14_CONSTEXPR - inline const _Tp& - max(const _Tp& __a, const _Tp& __b, _Compare __comp) - { - //return __comp(__a, __b) ? __b : __a; - if (__comp(__a, __b)) - return __b; - return __a; - } - - // Fallback implementation of the function in bits/stl_iterator.h used to - // remove the __normal_iterator wrapper. See copy, fill, ... - template - _GLIBCXX20_CONSTEXPR - inline _Iterator - __niter_base(_Iterator __it) - _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) - { return __it; } - - // Reverse the __niter_base transformation to get a - // __normal_iterator back again (this assumes that __normal_iterator - // is only used to wrap random access iterators, like pointers). - template - _GLIBCXX20_CONSTEXPR - inline _From - __niter_wrap(_From __from, _To __res) - { return __from + (__res - std::__niter_base(__from)); } - - // No need to wrap, iterator already has the right type. - template - _GLIBCXX20_CONSTEXPR - inline _Iterator - __niter_wrap(const _Iterator&, _Iterator __res) - { return __res; } - - // All of these auxiliary structs serve two purposes. (1) Replace - // calls to copy with memmove whenever possible. (Memmove, not memcpy, - // because the input and output ranges are permitted to overlap.) - // (2) If we're using random access iterators, then write the loop as - // a for loop with an explicit count. - - template - struct __copy_move - { - template - _GLIBCXX20_CONSTEXPR - static _OI - __copy_m(_II __first, _II __last, _OI __result) - { - for (; __first != __last; ++__result, (void)++__first) - *__result = *__first; - return __result; - } - }; - -#if __cplusplus >= 201103L - template - struct __copy_move - { - template - _GLIBCXX20_CONSTEXPR - static _OI - __copy_m(_II __first, _II __last, _OI __result) - { - for (; __first != __last; ++__result, (void)++__first) - *__result = std::move(*__first); - return __result; - } - }; -#endif - - template<> - struct __copy_move - { - template - _GLIBCXX20_CONSTEXPR - static _OI - __copy_m(_II __first, _II __last, _OI __result) - { - typedef typename iterator_traits<_II>::difference_type _Distance; - for(_Distance __n = __last - __first; __n > 0; --__n) - { - *__result = *__first; - ++__first; - ++__result; - } - return __result; - } - }; - -#if __cplusplus >= 201103L - template<> - struct __copy_move - { - template - _GLIBCXX20_CONSTEXPR - static _OI - __copy_m(_II __first, _II __last, _OI __result) - { - typedef typename iterator_traits<_II>::difference_type _Distance; - for(_Distance __n = __last - __first; __n > 0; --__n) - { - *__result = std::move(*__first); - ++__first; - ++__result; - } - return __result; - } - }; -#endif - - template - struct __copy_move<_IsMove, true, random_access_iterator_tag> - { - template - _GLIBCXX20_CONSTEXPR - static _Tp* - __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) - { -#if __cplusplus >= 201103L - using __assignable = conditional<_IsMove, - is_move_assignable<_Tp>, - is_copy_assignable<_Tp>>; - // trivial types can have deleted assignment - static_assert( __assignable::type::value, "type is not assignable" ); -#endif - const ptrdiff_t _Num = __last - __first; - if (_Num) - __builtin_memmove(__result, __first, sizeof(_Tp) * _Num); - return __result + _Num; - } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _OI - __copy_move_a2(_II __first, _II __last, _OI __result) - { - typedef typename iterator_traits<_II>::iterator_category _Category; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return std::__copy_move<_IsMove, false, _Category>:: - __copy_m(__first, __last, __result); -#endif - return std::__copy_move<_IsMove, __memcpyable<_OI, _II>::__value, - _Category>::__copy_m(__first, __last, __result); - } - -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - struct _Deque_iterator; - -_GLIBCXX_END_NAMESPACE_CONTAINER - - template - _OI - __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, - _OI); - - template - _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> - __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, - _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, - _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>); - - template - typename __gnu_cxx::__enable_if< - __is_random_access_iter<_II>::__value, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type - __copy_move_a1(_II, _II, _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); - - template - _GLIBCXX20_CONSTEXPR - inline _OI - __copy_move_a1(_II __first, _II __last, _OI __result) - { return std::__copy_move_a2<_IsMove>(__first, __last, __result); } - - template - _GLIBCXX20_CONSTEXPR - inline _OI - __copy_move_a(_II __first, _II __last, _OI __result) - { - return std::__niter_wrap(__result, - std::__copy_move_a1<_IsMove>(std::__niter_base(__first), - std::__niter_base(__last), - std::__niter_base(__result))); - } - - /** - * @brief Copies the range [first,last) into result. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @return result + (last - first) - * - * This inline function will boil down to a call to @c memmove whenever - * possible. Failing that, if random access iterators are passed, then the - * loop count will be known (and therefore a candidate for compiler - * optimizations such as unrolling). Result may not be contained within - * [first,last); the copy_backward function should be used instead. - * - * Note that the end of the output range is permitted to be contained - * within [first,last). - */ - template - _GLIBCXX20_CONSTEXPR - inline _OI - copy(_II __first, _II __last, _OI __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_II>) - __glibcxx_function_requires(_OutputIteratorConcept<_OI, - typename iterator_traits<_II>::value_type>) - __glibcxx_requires_can_increment_range(__first, __last, __result); - - return std::__copy_move_a<__is_move_iterator<_II>::__value> - (std::__miter_base(__first), std::__miter_base(__last), __result); - } - -#if __cplusplus >= 201103L - /** - * @brief Moves the range [first,last) into result. - * @ingroup mutating_algorithms - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @return result + (last - first) - * - * This inline function will boil down to a call to @c memmove whenever - * possible. Failing that, if random access iterators are passed, then the - * loop count will be known (and therefore a candidate for compiler - * optimizations such as unrolling). Result may not be contained within - * [first,last); the move_backward function should be used instead. - * - * Note that the end of the output range is permitted to be contained - * within [first,last). - */ - template - _GLIBCXX20_CONSTEXPR - inline _OI - move(_II __first, _II __last, _OI __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_II>) - __glibcxx_function_requires(_OutputIteratorConcept<_OI, - typename iterator_traits<_II>::value_type>) - __glibcxx_requires_can_increment_range(__first, __last, __result); - - return std::__copy_move_a(std::__miter_base(__first), - std::__miter_base(__last), __result); - } - -#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::move(_Tp, _Up, _Vp) -#else -#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::copy(_Tp, _Up, _Vp) -#endif - - template - struct __copy_move_backward - { - template - _GLIBCXX20_CONSTEXPR - static _BI2 - __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) - { - while (__first != __last) - *--__result = *--__last; - return __result; - } - }; - -#if __cplusplus >= 201103L - template - struct __copy_move_backward - { - template - _GLIBCXX20_CONSTEXPR - static _BI2 - __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) - { - while (__first != __last) - *--__result = std::move(*--__last); - return __result; - } - }; -#endif - - template<> - struct __copy_move_backward - { - template - _GLIBCXX20_CONSTEXPR - static _BI2 - __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) - { - typename iterator_traits<_BI1>::difference_type - __n = __last - __first; - for (; __n > 0; --__n) - *--__result = *--__last; - return __result; - } - }; - -#if __cplusplus >= 201103L - template<> - struct __copy_move_backward - { - template - _GLIBCXX20_CONSTEXPR - static _BI2 - __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) - { - typename iterator_traits<_BI1>::difference_type - __n = __last - __first; - for (; __n > 0; --__n) - *--__result = std::move(*--__last); - return __result; - } - }; -#endif - - template - struct __copy_move_backward<_IsMove, true, random_access_iterator_tag> - { - template - _GLIBCXX20_CONSTEXPR - static _Tp* - __copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result) - { -#if __cplusplus >= 201103L - using __assignable = conditional<_IsMove, - is_move_assignable<_Tp>, - is_copy_assignable<_Tp>>; - // trivial types can have deleted assignment - static_assert( __assignable::type::value, "type is not assignable" ); -#endif - const ptrdiff_t _Num = __last - __first; - if (_Num) - __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num); - return __result - _Num; - } - }; - - template - _GLIBCXX20_CONSTEXPR - inline _BI2 - __copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result) - { - typedef typename iterator_traits<_BI1>::iterator_category _Category; -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return std::__copy_move_backward<_IsMove, false, _Category>:: - __copy_move_b(__first, __last, __result); -#endif - return std::__copy_move_backward<_IsMove, - __memcpyable<_BI2, _BI1>::__value, - _Category>::__copy_move_b(__first, - __last, - __result); - } - - template - _GLIBCXX20_CONSTEXPR - inline _BI2 - __copy_move_backward_a1(_BI1 __first, _BI1 __last, _BI2 __result) - { return std::__copy_move_backward_a2<_IsMove>(__first, __last, __result); } - - template - _OI - __copy_move_backward_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, - _OI); - - template - _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> - __copy_move_backward_a1( - _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, - _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, - _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>); - - template - typename __gnu_cxx::__enable_if< - __is_random_access_iter<_II>::__value, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type - __copy_move_backward_a1(_II, _II, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); - - template - _GLIBCXX20_CONSTEXPR - inline _OI - __copy_move_backward_a(_II __first, _II __last, _OI __result) - { - return std::__niter_wrap(__result, - std::__copy_move_backward_a1<_IsMove> - (std::__niter_base(__first), std::__niter_base(__last), - std::__niter_base(__result))); - } - - /** - * @brief Copies the range [first,last) into result. - * @ingroup mutating_algorithms - * @param __first A bidirectional iterator. - * @param __last A bidirectional iterator. - * @param __result A bidirectional iterator. - * @return result - (last - first) - * - * The function has the same effect as copy, but starts at the end of the - * range and works its way to the start, returning the start of the result. - * This inline function will boil down to a call to @c memmove whenever - * possible. Failing that, if random access iterators are passed, then the - * loop count will be known (and therefore a candidate for compiler - * optimizations such as unrolling). - * - * Result may not be in the range (first,last]. Use copy instead. Note - * that the start of the output range may overlap [first,last). - */ - template - _GLIBCXX20_CONSTEXPR - inline _BI2 - copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) - __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) - __glibcxx_function_requires(_ConvertibleConcept< - typename iterator_traits<_BI1>::value_type, - typename iterator_traits<_BI2>::value_type>) - __glibcxx_requires_can_decrement_range(__first, __last, __result); - - return std::__copy_move_backward_a<__is_move_iterator<_BI1>::__value> - (std::__miter_base(__first), std::__miter_base(__last), __result); - } - -#if __cplusplus >= 201103L - /** - * @brief Moves the range [first,last) into result. - * @ingroup mutating_algorithms - * @param __first A bidirectional iterator. - * @param __last A bidirectional iterator. - * @param __result A bidirectional iterator. - * @return result - (last - first) - * - * The function has the same effect as move, but starts at the end of the - * range and works its way to the start, returning the start of the result. - * This inline function will boil down to a call to @c memmove whenever - * possible. Failing that, if random access iterators are passed, then the - * loop count will be known (and therefore a candidate for compiler - * optimizations such as unrolling). - * - * Result may not be in the range (first,last]. Use move instead. Note - * that the start of the output range may overlap [first,last). - */ - template - _GLIBCXX20_CONSTEXPR - inline _BI2 - move_backward(_BI1 __first, _BI1 __last, _BI2 __result) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) - __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) - __glibcxx_function_requires(_ConvertibleConcept< - typename iterator_traits<_BI1>::value_type, - typename iterator_traits<_BI2>::value_type>) - __glibcxx_requires_can_decrement_range(__first, __last, __result); - - return std::__copy_move_backward_a(std::__miter_base(__first), - std::__miter_base(__last), - __result); - } - -#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::move_backward(_Tp, _Up, _Vp) -#else -#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::copy_backward(_Tp, _Up, _Vp) -#endif - - template - _GLIBCXX20_CONSTEXPR - inline typename - __gnu_cxx::__enable_if::__value, void>::__type - __fill_a1(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __value) - { - for (; __first != __last; ++__first) - *__first = __value; - } - - template - _GLIBCXX20_CONSTEXPR - inline typename - __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, void>::__type - __fill_a1(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __value) - { - const _Tp __tmp = __value; - for (; __first != __last; ++__first) - *__first = __tmp; - } - - // Specialization: for char types we can use memset. - template - _GLIBCXX20_CONSTEXPR - inline typename - __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, void>::__type - __fill_a1(_Tp* __first, _Tp* __last, const _Tp& __c) - { - const _Tp __tmp = __c; -#if __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - { - for (; __first != __last; ++__first) - *__first = __tmp; - return; - } -#endif - if (const size_t __len = __last - __first) - __builtin_memset(__first, static_cast(__tmp), __len); - } - - template - _GLIBCXX20_CONSTEXPR - inline void - __fill_a1(::__gnu_cxx::__normal_iterator<_Ite, _Cont> __first, - ::__gnu_cxx::__normal_iterator<_Ite, _Cont> __last, - const _Tp& __value) - { std::__fill_a1(__first.base(), __last.base(), __value); } - - template - void - __fill_a1(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&, - const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&, - const _VTp&); - - template - _GLIBCXX20_CONSTEXPR - inline void - __fill_a(_FIte __first, _FIte __last, const _Tp& __value) - { std::__fill_a1(__first, __last, __value); } - - /** - * @brief Fills the range [first,last) with copies of value. - * @ingroup mutating_algorithms - * @param __first A forward iterator. - * @param __last A forward iterator. - * @param __value A reference-to-const of arbitrary type. - * @return Nothing. - * - * This function fills a range with copies of the same value. For char - * types filling contiguous areas of memory, this becomes an inline call - * to @c memset or @c wmemset. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_requires_valid_range(__first, __last); - - std::__fill_a(__first, __last, __value); - } - - // Used by fill_n, generate_n, etc. to convert _Size to an integral type: - inline _GLIBCXX_CONSTEXPR int - __size_to_integer(int __n) { return __n; } - inline _GLIBCXX_CONSTEXPR unsigned - __size_to_integer(unsigned __n) { return __n; } - inline _GLIBCXX_CONSTEXPR long - __size_to_integer(long __n) { return __n; } - inline _GLIBCXX_CONSTEXPR unsigned long - __size_to_integer(unsigned long __n) { return __n; } - inline _GLIBCXX_CONSTEXPR long long - __size_to_integer(long long __n) { return __n; } - inline _GLIBCXX_CONSTEXPR unsigned long long - __size_to_integer(unsigned long long __n) { return __n; } - -#if defined(__GLIBCXX_TYPE_INT_N_0) - inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0 - __size_to_integer(__GLIBCXX_TYPE_INT_N_0 __n) { return __n; } - inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_0 - __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_0 __n) { return __n; } -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) - inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1 - __size_to_integer(__GLIBCXX_TYPE_INT_N_1 __n) { return __n; } - inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_1 - __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_1 __n) { return __n; } -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) - inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2 - __size_to_integer(__GLIBCXX_TYPE_INT_N_2 __n) { return __n; } - inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_2 - __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_2 __n) { return __n; } -#endif -#if defined(__GLIBCXX_TYPE_INT_N_3) - inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_3 - __size_to_integer(__GLIBCXX_TYPE_INT_N_3 __n) { return __n; } - inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 - __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_3 __n) { return __n; } -#endif - - inline _GLIBCXX_CONSTEXPR long long - __size_to_integer(float __n) { return __n; } - inline _GLIBCXX_CONSTEXPR long long - __size_to_integer(double __n) { return __n; } - inline _GLIBCXX_CONSTEXPR long long - __size_to_integer(long double __n) { return __n; } -#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) - inline _GLIBCXX_CONSTEXPR long long - __size_to_integer(__float128 __n) { return __n; } -#endif - - template - _GLIBCXX20_CONSTEXPR - inline typename - __gnu_cxx::__enable_if::__value, _OutputIterator>::__type - __fill_n_a1(_OutputIterator __first, _Size __n, const _Tp& __value) - { - for (; __n > 0; --__n, (void) ++__first) - *__first = __value; - return __first; - } - - template - _GLIBCXX20_CONSTEXPR - inline typename - __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, _OutputIterator>::__type - __fill_n_a1(_OutputIterator __first, _Size __n, const _Tp& __value) - { - const _Tp __tmp = __value; - for (; __n > 0; --__n, (void) ++__first) - *__first = __tmp; - return __first; - } - - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, - std::output_iterator_tag) - { -#if __cplusplus >= 201103L - static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); -#endif - return __fill_n_a1(__first, __n, __value); - } - - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, - std::input_iterator_tag) - { -#if __cplusplus >= 201103L - static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); -#endif - return __fill_n_a1(__first, __n, __value); - } - - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, - std::random_access_iterator_tag) - { -#if __cplusplus >= 201103L - static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); -#endif - if (__n <= 0) - return __first; - - __glibcxx_requires_can_increment(__first, __n); - - std::__fill_a(__first, __first + __n, __value); - return __first + __n; - } - - /** - * @brief Fills the range [first,first+n) with copies of value. - * @ingroup mutating_algorithms - * @param __first An output iterator. - * @param __n The count of copies to perform. - * @param __value A reference-to-const of arbitrary type. - * @return The iterator at first+n. - * - * This function fills a range with copies of the same value. For char - * types filling contiguous areas of memory, this becomes an inline call - * to @c memset or @c wmemset. - * - * If @p __n is negative, the function does nothing. - */ - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 865. More algorithms that throw away information - // DR 426. search_n(), fill_n(), and generate_n() with negative n - template - _GLIBCXX20_CONSTEXPR - inline _OI - fill_n(_OI __first, _Size __n, const _Tp& __value) - { - // concept requirements - __glibcxx_function_requires(_OutputIteratorConcept<_OI, _Tp>) - - return std::__fill_n_a(__first, std::__size_to_integer(__n), __value, - std::__iterator_category(__first)); - } - - template - struct __equal - { - template - _GLIBCXX20_CONSTEXPR - static bool - equal(_II1 __first1, _II1 __last1, _II2 __first2) - { - for (; __first1 != __last1; ++__first1, (void) ++__first2) - if (!(*__first1 == *__first2)) - return false; - return true; - } - }; - - template<> - struct __equal - { - template - _GLIBCXX20_CONSTEXPR - static bool - equal(const _Tp* __first1, const _Tp* __last1, const _Tp* __first2) - { - if (const size_t __len = (__last1 - __first1)) - return !std::__memcmp(__first1, __first2, __len); - return true; - } - }; - - template - typename __gnu_cxx::__enable_if< - __is_random_access_iter<_II>::__value, bool>::__type - __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, - _II); - - template - bool - __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, - _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, - _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>); - - template - typename __gnu_cxx::__enable_if< - __is_random_access_iter<_II>::__value, bool>::__type - __equal_aux1(_II, _II, - _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>); - - template - _GLIBCXX20_CONSTEXPR - inline bool - __equal_aux1(_II1 __first1, _II1 __last1, _II2 __first2) - { - typedef typename iterator_traits<_II1>::value_type _ValueType1; - const bool __simple = ((__is_integer<_ValueType1>::__value - || __is_pointer<_ValueType1>::__value) - && __memcmpable<_II1, _II2>::__value); - return std::__equal<__simple>::equal(__first1, __last1, __first2); - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2) - { - return std::__equal_aux1(std::__niter_base(__first1), - std::__niter_base(__last1), - std::__niter_base(__first2)); - } - - template - struct __lc_rai - { - template - _GLIBCXX20_CONSTEXPR - static _II1 - __newlast1(_II1, _II1 __last1, _II2, _II2) - { return __last1; } - - template - _GLIBCXX20_CONSTEXPR - static bool - __cnd2(_II __first, _II __last) - { return __first != __last; } - }; - - template<> - struct __lc_rai - { - template - _GLIBCXX20_CONSTEXPR - static _RAI1 - __newlast1(_RAI1 __first1, _RAI1 __last1, - _RAI2 __first2, _RAI2 __last2) - { - const typename iterator_traits<_RAI1>::difference_type - __diff1 = __last1 - __first1; - const typename iterator_traits<_RAI2>::difference_type - __diff2 = __last2 - __first2; - return __diff2 < __diff1 ? __first1 + __diff2 : __last1; - } - - template - static _GLIBCXX20_CONSTEXPR bool - __cnd2(_RAI, _RAI) - { return true; } - }; - - template - _GLIBCXX20_CONSTEXPR - bool - __lexicographical_compare_impl(_II1 __first1, _II1 __last1, - _II2 __first2, _II2 __last2, - _Compare __comp) - { - typedef typename iterator_traits<_II1>::iterator_category _Category1; - typedef typename iterator_traits<_II2>::iterator_category _Category2; - typedef std::__lc_rai<_Category1, _Category2> __rai_type; - - __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2); - for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2); - ++__first1, (void)++__first2) - { - if (__comp(__first1, __first2)) - return true; - if (__comp(__first2, __first1)) - return false; - } - return __first1 == __last1 && __first2 != __last2; - } - - template - struct __lexicographical_compare - { - template - _GLIBCXX20_CONSTEXPR - static bool - __lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) - { - using __gnu_cxx::__ops::__iter_less_iter; - return std::__lexicographical_compare_impl(__first1, __last1, - __first2, __last2, - __iter_less_iter()); - } - }; - - template<> - struct __lexicographical_compare - { - template - _GLIBCXX20_CONSTEXPR - static bool - __lc(const _Tp* __first1, const _Tp* __last1, - const _Up* __first2, const _Up* __last2) - { - const size_t __len1 = __last1 - __first1; - const size_t __len2 = __last2 - __first2; - if (const size_t __len = std::min(__len1, __len2)) - if (int __result = std::__memcmp(__first1, __first2, __len)) - return __result < 0; - return __len1 < __len2; - } - }; - - template - _GLIBCXX20_CONSTEXPR - inline bool - __lexicographical_compare_aux(_II1 __first1, _II1 __last1, - _II2 __first2, _II2 __last2) - { - typedef typename iterator_traits<_II1>::value_type _ValueType1; - typedef typename iterator_traits<_II2>::value_type _ValueType2; - const bool __simple = - (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value - && __is_pointer<_II1>::__value - && __is_pointer<_II2>::__value -#if __cplusplus > 201703L && __cpp_lib_concepts - // For C++20 iterator_traits::value_type is non-volatile - // so __is_byte could be true, but we can't use memcmp with - // volatile data. - && !is_volatile_v>> - && !is_volatile_v>> -#endif - ); - - return std::__lexicographical_compare<__simple>::__lc(__first1, __last1, - __first2, __last2); - } - - template - _GLIBCXX20_CONSTEXPR - _ForwardIterator - __lower_bound(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val, _Compare __comp) - { - typedef typename iterator_traits<_ForwardIterator>::difference_type - _DistanceType; - - _DistanceType __len = std::distance(__first, __last); - - while (__len > 0) - { - _DistanceType __half = __len >> 1; - _ForwardIterator __middle = __first; - std::advance(__middle, __half); - if (__comp(__middle, __val)) - { - __first = __middle; - ++__first; - __len = __len - __half - 1; - } - else - __len = __half; - } - return __first; - } - - /** - * @brief Finds the first position in which @a val could be inserted - * without changing the ordering. - * @param __first An iterator. - * @param __last Another iterator. - * @param __val The search term. - * @return An iterator pointing to the first element not less - * than @a val, or end() if every element is less than - * @a val. - * @ingroup binary_search_algorithms - */ - template - _GLIBCXX20_CONSTEXPR - inline _ForwardIterator - lower_bound(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __val) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanOpConcept< - typename iterator_traits<_ForwardIterator>::value_type, _Tp>) - __glibcxx_requires_partitioned_lower(__first, __last, __val); - - return std::__lower_bound(__first, __last, __val, - __gnu_cxx::__ops::__iter_less_val()); - } - - /// This is a helper function for the sort routines and for random.tcc. - // Precondition: __n > 0. - inline _GLIBCXX_CONSTEXPR int - __lg(int __n) - { return (int)sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } - - inline _GLIBCXX_CONSTEXPR unsigned - __lg(unsigned __n) - { return (int)sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } - - inline _GLIBCXX_CONSTEXPR long - __lg(long __n) - { return (int)sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } - - inline _GLIBCXX_CONSTEXPR unsigned long - __lg(unsigned long __n) - { return (int)sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } - - inline _GLIBCXX_CONSTEXPR long long - __lg(long long __n) - { return (int)sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } - - inline _GLIBCXX_CONSTEXPR unsigned long long - __lg(unsigned long long __n) - { return (int)sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } - -_GLIBCXX_BEGIN_NAMESPACE_ALGO - - /** - * @brief Tests a range for element-wise equality. - * @ingroup non_mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @return A boolean true or false. - * - * This compares the elements of two ranges using @c == and returns true or - * false depending on whether all of the corresponding elements of the - * ranges are equal. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - equal(_II1 __first1, _II1 __last1, _II2 __first2) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_II1>) - __glibcxx_function_requires(_InputIteratorConcept<_II2>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_II1>::value_type, - typename iterator_traits<_II2>::value_type>) - __glibcxx_requires_can_increment_range(__first1, __last1, __first2); - - return std::__equal_aux(__first1, __last1, __first2); - } - - /** - * @brief Tests a range for element-wise equality. - * @ingroup non_mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __binary_pred A binary predicate @link functors - * functor@endlink. - * @return A boolean true or false. - * - * This compares the elements of two ranges using the binary_pred - * parameter, and returns true or - * false depending on whether all of the corresponding elements of the - * ranges are equal. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - equal(_IIter1 __first1, _IIter1 __last1, - _IIter2 __first2, _BinaryPredicate __binary_pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) - __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) - __glibcxx_requires_valid_range(__first1, __last1); - - for (; __first1 != __last1; ++__first1, (void)++__first2) - if (!bool(__binary_pred(*__first1, *__first2))) - return false; - return true; - } - -#if __cplusplus >= 201103L - // 4-iterator version of std::equal for use in C++11. - template - _GLIBCXX20_CONSTEXPR - inline bool - __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) - { - using _RATag = random_access_iterator_tag; - using _Cat1 = typename iterator_traits<_II1>::iterator_category; - using _Cat2 = typename iterator_traits<_II2>::iterator_category; - using _RAIters = __and_, is_same<_Cat2, _RATag>>; - if (_RAIters()) - { - auto __d1 = std::distance(__first1, __last1); - auto __d2 = std::distance(__first2, __last2); - if (__d1 != __d2) - return false; - return _GLIBCXX_STD_A::equal(__first1, __last1, __first2); - } - - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - if (!(*__first1 == *__first2)) - return false; - return __first1 == __last1 && __first2 == __last2; - } - - // 4-iterator version of std::equal for use in C++11. - template - _GLIBCXX20_CONSTEXPR - inline bool - __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2, - _BinaryPredicate __binary_pred) - { - using _RATag = random_access_iterator_tag; - using _Cat1 = typename iterator_traits<_II1>::iterator_category; - using _Cat2 = typename iterator_traits<_II2>::iterator_category; - using _RAIters = __and_, is_same<_Cat2, _RATag>>; - if (_RAIters()) - { - auto __d1 = std::distance(__first1, __last1); - auto __d2 = std::distance(__first2, __last2); - if (__d1 != __d2) - return false; - return _GLIBCXX_STD_A::equal(__first1, __last1, __first2, - __binary_pred); - } - - for (; __first1 != __last1 && __first2 != __last2; - ++__first1, (void)++__first2) - if (!bool(__binary_pred(*__first1, *__first2))) - return false; - return __first1 == __last1 && __first2 == __last2; - } -#endif // C++11 - -#if __cplusplus > 201103L - -#define __cpp_lib_robust_nonmodifying_seq_ops 201304 - - /** - * @brief Tests a range for element-wise equality. - * @ingroup non_mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __last2 An input iterator. - * @return A boolean true or false. - * - * This compares the elements of two ranges using @c == and returns true or - * false depending on whether all of the corresponding elements of the - * ranges are equal. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - equal(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_II1>) - __glibcxx_function_requires(_InputIteratorConcept<_II2>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_II1>::value_type, - typename iterator_traits<_II2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2); - } - - /** - * @brief Tests a range for element-wise equality. - * @ingroup non_mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __last2 An input iterator. - * @param __binary_pred A binary predicate @link functors - * functor@endlink. - * @return A boolean true or false. - * - * This compares the elements of two ranges using the binary_pred - * parameter, and returns true or - * false depending on whether all of the corresponding elements of the - * ranges are equal. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - equal(_IIter1 __first1, _IIter1 __last1, - _IIter2 __first2, _IIter2 __last2, _BinaryPredicate __binary_pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) - __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2, - __binary_pred); - } -#endif // C++14 - - /** - * @brief Performs @b dictionary comparison on ranges. - * @ingroup sorting_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __last2 An input iterator. - * @return A boolean true or false. - * - * Returns true if the sequence of elements defined by the range - * [first1,last1) is lexicographically less than the sequence of elements - * defined by the range [first2,last2). Returns false otherwise. - * (Quoted from [25.3.8]/1.) If the iterators are all character pointers, - * then this is an inline call to @c memcmp. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - lexicographical_compare(_II1 __first1, _II1 __last1, - _II2 __first2, _II2 __last2) - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename iterator_traits<_II1>::value_type _ValueType1; - typedef typename iterator_traits<_II2>::value_type _ValueType2; -#endif - __glibcxx_function_requires(_InputIteratorConcept<_II1>) - __glibcxx_function_requires(_InputIteratorConcept<_II2>) - __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>) - __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return std::__lexicographical_compare_aux(std::__niter_base(__first1), - std::__niter_base(__last1), - std::__niter_base(__first2), - std::__niter_base(__last2)); - } - - /** - * @brief Performs @b dictionary comparison on ranges. - * @ingroup sorting_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __last2 An input iterator. - * @param __comp A @link comparison_functors comparison functor@endlink. - * @return A boolean true or false. - * - * The same as the four-parameter @c lexicographical_compare, but uses the - * comp parameter instead of @c <. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - lexicographical_compare(_II1 __first1, _II1 __last1, - _II2 __first2, _II2 __last2, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_II1>) - __glibcxx_function_requires(_InputIteratorConcept<_II2>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return std::__lexicographical_compare_impl - (__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__comp)); - } - -#if __cpp_lib_three_way_comparison - // Iter points to a contiguous range of unsigned narrow character type - // or std::byte, suitable for comparison by memcmp. - template - concept __is_byte_iter = contiguous_iterator<_Iter> - && __is_memcmp_ordered>::__value; - - // Return a struct with two members, initialized to the smaller of x and y - // (or x if they compare equal) and the result of the comparison x <=> y. - template - constexpr auto - __min_cmp(_Tp __x, _Tp __y) - { - struct _Res { - _Tp _M_min; - decltype(__x <=> __y) _M_cmp; - }; - auto __c = __x <=> __y; - if (__c > 0) - return _Res{__y, __c}; - return _Res{__x, __c}; - } - - /** - * @brief Performs dictionary comparison on ranges. - * @ingroup sorting_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __last2 An input iterator. - * @param __comp A @link comparison_functors comparison functor@endlink. - * @return The comparison category that `__comp(*__first1, *__first2)` - * returns. - */ - template - constexpr auto - lexicographical_compare_three_way(_InputIter1 __first1, - _InputIter1 __last1, - _InputIter2 __first2, - _InputIter2 __last2, - _Comp __comp) - -> decltype(__comp(*__first1, *__first2)) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIter1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIter2>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - -#if __cpp_lib_is_constant_evaluated - using _Cat = decltype(__comp(*__first1, *__first2)); - static_assert(same_as, _Cat>); - - if (!std::is_constant_evaluated()) - if constexpr (same_as<_Comp, __detail::_Synth3way> - || same_as<_Comp, compare_three_way>) - if constexpr (__is_byte_iter<_InputIter1>) - if constexpr (__is_byte_iter<_InputIter2>) - { - const auto [__len, __lencmp] - = std::__min_cmp(__last1 - __first1, __last2 - __first2); - if (__len) - { - const auto __c - = __builtin_memcmp(&*__first1, &*__first2, __len) <=> 0; - if (__c != 0) - return __c; - } - return __lencmp; - } -#endif // is_constant_evaluated - while (__first1 != __last1) - { - if (__first2 == __last2) - return strong_ordering::greater; - if (auto __cmp = __comp(*__first1, *__first2); __cmp != 0) - return __cmp; - ++__first1; - ++__first2; - } - return (__first2 == __last2) <=> true; // See PR 94006 - } - - template - constexpr auto - lexicographical_compare_three_way(_InputIter1 __first1, - _InputIter1 __last1, - _InputIter2 __first2, - _InputIter2 __last2) - { - return std::lexicographical_compare_three_way(__first1, __last1, - __first2, __last2, - compare_three_way{}); - } -#endif // three_way_comparison - - template - _GLIBCXX20_CONSTEXPR - pair<_InputIterator1, _InputIterator2> - __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _BinaryPredicate __binary_pred) - { - while (__first1 != __last1 && __binary_pred(__first1, __first2)) - { - ++__first1; - ++__first2; - } - return pair<_InputIterator1, _InputIterator2>(__first1, __first2); - } - - /** - * @brief Finds the places in ranges which don't match. - * @ingroup non_mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @return A pair of iterators pointing to the first mismatch. - * - * This compares the elements of two ranges using @c == and returns a pair - * of iterators. The first iterator points into the first range, the - * second iterator points into the second range, and the elements pointed - * to by the iterators are not equal. - */ - template - _GLIBCXX20_CONSTEXPR - inline pair<_InputIterator1, _InputIterator2> - mismatch(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - - return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, - __gnu_cxx::__ops::__iter_equal_to_iter()); - } - - /** - * @brief Finds the places in ranges which don't match. - * @ingroup non_mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __binary_pred A binary predicate @link functors - * functor@endlink. - * @return A pair of iterators pointing to the first mismatch. - * - * This compares the elements of two ranges using the binary_pred - * parameter, and returns a pair - * of iterators. The first iterator points into the first range, the - * second iterator points into the second range, and the elements pointed - * to by the iterators are not equal. - */ - template - _GLIBCXX20_CONSTEXPR - inline pair<_InputIterator1, _InputIterator2> - mismatch(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _BinaryPredicate __binary_pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_requires_valid_range(__first1, __last1); - - return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); - } - -#if __cplusplus > 201103L - - template - _GLIBCXX20_CONSTEXPR - pair<_InputIterator1, _InputIterator2> - __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _BinaryPredicate __binary_pred) - { - while (__first1 != __last1 && __first2 != __last2 - && __binary_pred(__first1, __first2)) - { - ++__first1; - ++__first2; - } - return pair<_InputIterator1, _InputIterator2>(__first1, __first2); - } - - /** - * @brief Finds the places in ranges which don't match. - * @ingroup non_mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __last2 An input iterator. - * @return A pair of iterators pointing to the first mismatch. - * - * This compares the elements of two ranges using @c == and returns a pair - * of iterators. The first iterator points into the first range, the - * second iterator points into the second range, and the elements pointed - * to by the iterators are not equal. - */ - template - _GLIBCXX20_CONSTEXPR - inline pair<_InputIterator1, _InputIterator2> - mismatch(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_InputIterator1>::value_type, - typename iterator_traits<_InputIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_equal_to_iter()); - } - - /** - * @brief Finds the places in ranges which don't match. - * @ingroup non_mutating_algorithms - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __last2 An input iterator. - * @param __binary_pred A binary predicate @link functors - * functor@endlink. - * @return A pair of iterators pointing to the first mismatch. - * - * This compares the elements of two ranges using the binary_pred - * parameter, and returns a pair - * of iterators. The first iterator points into the first range, the - * second iterator points into the second range, and the elements pointed - * to by the iterators are not equal. - */ - template - _GLIBCXX20_CONSTEXPR - inline pair<_InputIterator1, _InputIterator2> - mismatch(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _InputIterator2 __last2, - _BinaryPredicate __binary_pred) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); - } -#endif - -_GLIBCXX_END_NAMESPACE_ALGO - - /// This is an overload used by find algos for the Input Iterator case. - template - _GLIBCXX20_CONSTEXPR - inline _InputIterator - __find_if(_InputIterator __first, _InputIterator __last, - _Predicate __pred, input_iterator_tag) - { - while (__first != __last && !__pred(__first)) - ++__first; - return __first; - } - - /// This is an overload used by find algos for the RAI case. - template - _GLIBCXX20_CONSTEXPR - _RandomAccessIterator - __find_if(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Predicate __pred, random_access_iterator_tag) - { - typename iterator_traits<_RandomAccessIterator>::difference_type - __trip_count = (__last - __first) >> 2; - - for (; __trip_count > 0; --__trip_count) - { - if (__pred(__first)) - return __first; - ++__first; - - if (__pred(__first)) - return __first; - ++__first; - - if (__pred(__first)) - return __first; - ++__first; - - if (__pred(__first)) - return __first; - ++__first; - } - - switch (__last - __first) - { - case 3: - if (__pred(__first)) - return __first; - ++__first; - // FALLTHRU - case 2: - if (__pred(__first)) - return __first; - ++__first; - // FALLTHRU - case 1: - if (__pred(__first)) - return __first; - ++__first; - // FALLTHRU - case 0: - default: - return __last; - } - } - - template - _GLIBCXX20_CONSTEXPR - inline _Iterator - __find_if(_Iterator __first, _Iterator __last, _Predicate __pred) - { - return __find_if(__first, __last, __pred, - std::__iterator_category(__first)); - } - - template - _GLIBCXX20_CONSTEXPR - typename iterator_traits<_InputIterator>::difference_type - __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) - { - typename iterator_traits<_InputIterator>::difference_type __n = 0; - for (; __first != __last; ++__first) - if (__pred(__first)) - ++__n; - return __n; - } - -#if __cplusplus >= 201103L - template - _GLIBCXX20_CONSTEXPR - bool - __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2, _BinaryPredicate __pred) - { - // Efficiently compare identical prefixes: O(N) if sequences - // have the same elements in the same order. - for (; __first1 != __last1; ++__first1, (void)++__first2) - if (!__pred(__first1, __first2)) - break; - - if (__first1 == __last1) - return true; - - // Establish __last2 assuming equal ranges by iterating over the - // rest of the list. - _ForwardIterator2 __last2 = __first2; - std::advance(__last2, std::distance(__first1, __last1)); - for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) - { - if (__scan != std::__find_if(__first1, __scan, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) - continue; // We've seen this one before. - - auto __matches - = std::__count_if(__first2, __last2, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); - if (0 == __matches || - std::__count_if(__scan, __last1, - __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) - != __matches) - return false; - } - return true; - } - - /** - * @brief Checks whether a permutation of the second sequence is equal - * to the first sequence. - * @ingroup non_mutating_algorithms - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @return true if there exists a permutation of the elements in the range - * [__first2, __first2 + (__last1 - __first1)), beginning with - * ForwardIterator2 begin, such that equal(__first1, __last1, begin) - * returns true; otherwise, returns false. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, - _ForwardIterator2 __first2) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) - __glibcxx_function_requires(_EqualOpConcept< - typename iterator_traits<_ForwardIterator1>::value_type, - typename iterator_traits<_ForwardIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - - return std::__is_permutation(__first1, __last1, __first2, - __gnu_cxx::__ops::__iter_equal_to_iter()); - } -#endif // C++11 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h b/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h deleted file mode 100644 index f245e52b2..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h +++ /dev/null @@ -1,1363 +0,0 @@ -// vector specialization -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996-1999 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_bvector.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{vector} - */ - -#ifndef _STL_BVECTOR_H -#define _STL_BVECTOR_H 1 - -#if __cplusplus >= 201103L -#include -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - typedef unsigned long _Bit_type; - enum { _S_word_bit = int(__CHAR_BIT__ * sizeof(_Bit_type)) }; - - struct _Bit_reference - { - _Bit_type * _M_p; - _Bit_type _M_mask; - - _Bit_reference(_Bit_type * __x, _Bit_type __y) - : _M_p(__x), _M_mask(__y) { } - - _Bit_reference() _GLIBCXX_NOEXCEPT : _M_p(0), _M_mask(0) { } - -#if __cplusplus >= 201103L - _Bit_reference(const _Bit_reference&) = default; -#endif - - operator bool() const _GLIBCXX_NOEXCEPT - { return !!(*_M_p & _M_mask); } - - _Bit_reference& - operator=(bool __x) _GLIBCXX_NOEXCEPT - { - if (__x) - *_M_p |= _M_mask; - else - *_M_p &= ~_M_mask; - return *this; - } - - _Bit_reference& - operator=(const _Bit_reference& __x) _GLIBCXX_NOEXCEPT - { return *this = bool(__x); } - - bool - operator==(const _Bit_reference& __x) const - { return bool(*this) == bool(__x); } - - bool - operator<(const _Bit_reference& __x) const - { return !bool(*this) && bool(__x); } - - void - flip() _GLIBCXX_NOEXCEPT - { *_M_p ^= _M_mask; } - }; - -#if __cplusplus >= 201103L - inline void - swap(_Bit_reference __x, _Bit_reference __y) noexcept - { - bool __tmp = __x; - __x = __y; - __y = __tmp; - } - - inline void - swap(_Bit_reference __x, bool& __y) noexcept - { - bool __tmp = __x; - __x = __y; - __y = __tmp; - } - - inline void - swap(bool& __x, _Bit_reference __y) noexcept - { - bool __tmp = __x; - __x = __y; - __y = __tmp; - } -#endif - - struct _Bit_iterator_base - : public std::iterator - { - _Bit_type * _M_p; - unsigned int _M_offset; - - _Bit_iterator_base(_Bit_type * __x, unsigned int __y) - : _M_p(__x), _M_offset(__y) { } - - void - _M_bump_up() - { - if (_M_offset++ == int(_S_word_bit) - 1) - { - _M_offset = 0; - ++_M_p; - } - } - - void - _M_bump_down() - { - if (_M_offset-- == 0) - { - _M_offset = int(_S_word_bit) - 1; - --_M_p; - } - } - - void - _M_incr(ptrdiff_t __i) - { - difference_type __n = __i + _M_offset; - _M_p += __n / int(_S_word_bit); - __n = __n % int(_S_word_bit); - if (__n < 0) - { - __n += int(_S_word_bit); - --_M_p; - } - _M_offset = static_cast(__n); - } - - friend _GLIBCXX20_CONSTEXPR bool - operator==(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) - { return __x._M_p == __y._M_p && __x._M_offset == __y._M_offset; } - -#if __cpp_lib_three_way_comparison - friend constexpr strong_ordering - operator<=>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) - noexcept - { - if (const auto __cmp = __x._M_p <=> __y._M_p; __cmp != 0) - return __cmp; - return __x._M_offset <=> __y._M_offset; - } -#else - friend bool - operator<(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) - { - return __x._M_p < __y._M_p - || (__x._M_p == __y._M_p && __x._M_offset < __y._M_offset); - } - - friend bool - operator!=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) - { return !(__x == __y); } - - friend bool - operator>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) - { return __y < __x; } - - friend bool - operator<=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) - { return !(__y < __x); } - - friend bool - operator>=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) - { return !(__x < __y); } -#endif // three-way comparison - - friend ptrdiff_t - operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) - { - return (int(_S_word_bit) * (__x._M_p - __y._M_p) - + __x._M_offset - __y._M_offset); - } - }; - - struct _Bit_iterator : public _Bit_iterator_base - { - typedef _Bit_reference reference; -#if __cplusplus > 201703L - typedef void pointer; -#else - typedef _Bit_reference* pointer; -#endif - typedef _Bit_iterator iterator; - - _Bit_iterator() : _Bit_iterator_base(0, 0) { } - - _Bit_iterator(_Bit_type * __x, unsigned int __y) - : _Bit_iterator_base(__x, __y) { } - - iterator - _M_const_cast() const - { return *this; } - - reference - operator*() const - { return reference(_M_p, 1UL << _M_offset); } - - iterator& - operator++() - { - _M_bump_up(); - return *this; - } - - iterator - operator++(int) - { - iterator __tmp = *this; - _M_bump_up(); - return __tmp; - } - - iterator& - operator--() - { - _M_bump_down(); - return *this; - } - - iterator - operator--(int) - { - iterator __tmp = *this; - _M_bump_down(); - return __tmp; - } - - iterator& - operator+=(difference_type __i) - { - _M_incr(__i); - return *this; - } - - iterator& - operator-=(difference_type __i) - { - *this += -__i; - return *this; - } - - reference - operator[](difference_type __i) const - { return *(*this + __i); } - - friend iterator - operator+(const iterator& __x, difference_type __n) - { - iterator __tmp = __x; - __tmp += __n; - return __tmp; - } - - friend iterator - operator+(difference_type __n, const iterator& __x) - { return __x + __n; } - - friend iterator - operator-(const iterator& __x, difference_type __n) - { - iterator __tmp = __x; - __tmp -= __n; - return __tmp; - } - }; - - struct _Bit_const_iterator : public _Bit_iterator_base - { - typedef bool reference; - typedef bool const_reference; -#if __cplusplus > 201703L - typedef void pointer; -#else - typedef const bool* pointer; -#endif - typedef _Bit_const_iterator const_iterator; - - _Bit_const_iterator() : _Bit_iterator_base(0, 0) { } - - _Bit_const_iterator(_Bit_type * __x, unsigned int __y) - : _Bit_iterator_base(__x, __y) { } - - _Bit_const_iterator(const _Bit_iterator& __x) - : _Bit_iterator_base(__x._M_p, __x._M_offset) { } - - _Bit_iterator - _M_const_cast() const - { return _Bit_iterator(_M_p, _M_offset); } - - const_reference - operator*() const - { return _Bit_reference(_M_p, 1UL << _M_offset); } - - const_iterator& - operator++() - { - _M_bump_up(); - return *this; - } - - const_iterator - operator++(int) - { - const_iterator __tmp = *this; - _M_bump_up(); - return __tmp; - } - - const_iterator& - operator--() - { - _M_bump_down(); - return *this; - } - - const_iterator - operator--(int) - { - const_iterator __tmp = *this; - _M_bump_down(); - return __tmp; - } - - const_iterator& - operator+=(difference_type __i) - { - _M_incr(__i); - return *this; - } - - const_iterator& - operator-=(difference_type __i) - { - *this += -__i; - return *this; - } - - const_reference - operator[](difference_type __i) const - { return *(*this + __i); } - - friend const_iterator - operator+(const const_iterator& __x, difference_type __n) - { - const_iterator __tmp = __x; - __tmp += __n; - return __tmp; - } - - friend const_iterator - operator-(const const_iterator& __x, difference_type __n) - { - const_iterator __tmp = __x; - __tmp -= __n; - return __tmp; - } - - friend const_iterator - operator+(difference_type __n, const const_iterator& __x) - { return __x + __n; } - }; - - inline void - __fill_bvector(_Bit_type * __v, - unsigned int __first, unsigned int __last, bool __x) - { - const _Bit_type __fmask = ~0ul << __first; - const _Bit_type __lmask = ~0ul >> (_S_word_bit - __last); - const _Bit_type __mask = __fmask & __lmask; - - if (__x) - *__v |= __mask; - else - *__v &= ~__mask; - } - - inline void - fill(_Bit_iterator __first, _Bit_iterator __last, const bool& __x) - { - if (__first._M_p != __last._M_p) - { - _Bit_type* __first_p = __first._M_p; - if (__first._M_offset != 0) - __fill_bvector(__first_p++, __first._M_offset, _S_word_bit, __x); - - __builtin_memset(__first_p, __x ? ~0 : 0, - (__last._M_p - __first_p) * sizeof(_Bit_type)); - - if (__last._M_offset != 0) - __fill_bvector(__last._M_p, 0, __last._M_offset, __x); - } - else if (__first._M_offset != __last._M_offset) - __fill_bvector(__first._M_p, __first._M_offset, __last._M_offset, __x); - } - - template - struct _Bvector_base - { - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_Bit_type>::other _Bit_alloc_type; - typedef typename __gnu_cxx::__alloc_traits<_Bit_alloc_type> - _Bit_alloc_traits; - typedef typename _Bit_alloc_traits::pointer _Bit_pointer; - - struct _Bvector_impl_data - { - _Bit_iterator _M_start; - _Bit_iterator _M_finish; - _Bit_pointer _M_end_of_storage; - - _Bvector_impl_data() _GLIBCXX_NOEXCEPT - : _M_start(), _M_finish(), _M_end_of_storage() - { } - -#if __cplusplus >= 201103L - _Bvector_impl_data(_Bvector_impl_data&& __x) noexcept - : _M_start(__x._M_start), _M_finish(__x._M_finish) - , _M_end_of_storage(__x._M_end_of_storage) - { __x._M_reset(); } - - void - _M_move_data(_Bvector_impl_data&& __x) noexcept - { - this->_M_start = __x._M_start; - this->_M_finish = __x._M_finish; - this->_M_end_of_storage = __x._M_end_of_storage; - __x._M_reset(); - } -#endif - - void - _M_reset() _GLIBCXX_NOEXCEPT - { - _M_start = _M_finish = _Bit_iterator(); - _M_end_of_storage = _Bit_pointer(); - } - }; - - struct _Bvector_impl - : public _Bit_alloc_type, public _Bvector_impl_data - { - public: - _Bvector_impl() _GLIBCXX_NOEXCEPT_IF( - is_nothrow_default_constructible<_Bit_alloc_type>::value) - : _Bit_alloc_type() - { } - - _Bvector_impl(const _Bit_alloc_type& __a) _GLIBCXX_NOEXCEPT - : _Bit_alloc_type(__a) - { } - -#if __cplusplus >= 201103L - _Bvector_impl(_Bvector_impl&&) = default; -#endif - - _Bit_type* - _M_end_addr() const _GLIBCXX_NOEXCEPT - { - if (this->_M_end_of_storage) - return std::__addressof(this->_M_end_of_storage[-1]) + 1; - return 0; - } - }; - - public: - typedef _Alloc allocator_type; - - _Bit_alloc_type& - _M_get_Bit_allocator() _GLIBCXX_NOEXCEPT - { return this->_M_impl; } - - const _Bit_alloc_type& - _M_get_Bit_allocator() const _GLIBCXX_NOEXCEPT - { return this->_M_impl; } - - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_M_get_Bit_allocator()); } - -#if __cplusplus >= 201103L - _Bvector_base() = default; -#else - _Bvector_base() { } -#endif - - _Bvector_base(const allocator_type& __a) - : _M_impl(__a) { } - -#if __cplusplus >= 201103L - _Bvector_base(_Bvector_base&&) = default; -#endif - - ~_Bvector_base() - { this->_M_deallocate(); } - - protected: - _Bvector_impl _M_impl; - - _Bit_pointer - _M_allocate(size_t __n) - { return _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n)); } - - void - _M_deallocate() - { - if (_M_impl._M_start._M_p) - { - const size_t __n = _M_impl._M_end_addr() - _M_impl._M_start._M_p; - _Bit_alloc_traits::deallocate(_M_impl, - _M_impl._M_end_of_storage - __n, - __n); - _M_impl._M_reset(); - } - } - -#if __cplusplus >= 201103L - void - _M_move_data(_Bvector_base&& __x) noexcept - { _M_impl._M_move_data(std::move(__x._M_impl)); } -#endif - - static size_t - _S_nword(size_t __n) - { return (__n + int(_S_word_bit) - 1) / int(_S_word_bit); } - }; - -_GLIBCXX_END_NAMESPACE_CONTAINER -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -// Declare a partial specialization of vector. -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - /** - * @brief A specialization of vector for booleans which offers fixed time - * access to individual elements in any order. - * - * @ingroup sequences - * - * @tparam _Alloc Allocator type. - * - * Note that vector does not actually meet the requirements for being - * a container. This is because the reference and pointer types are not - * really references and pointers to bool. See DR96 for details. @see - * vector for function documentation. - * - * In some terminology a %vector can be described as a dynamic - * C-style array, it offers fast and efficient access to individual - * elements in any order and saves the user from worrying about - * memory and size allocation. Subscripting ( @c [] ) access is - * also provided as with C-style arrays. - */ - template - class vector : protected _Bvector_base<_Alloc> - { - typedef _Bvector_base<_Alloc> _Base; - typedef typename _Base::_Bit_pointer _Bit_pointer; - typedef typename _Base::_Bit_alloc_traits _Bit_alloc_traits; - -#if __cplusplus >= 201103L - friend struct std::hash; -#endif - - public: - typedef bool value_type; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Bit_reference reference; - typedef bool const_reference; - typedef _Bit_reference* pointer; - typedef const bool* const_pointer; - typedef _Bit_iterator iterator; - typedef _Bit_const_iterator const_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef _Alloc allocator_type; - - allocator_type - get_allocator() const - { return _Base::get_allocator(); } - - protected: - using _Base::_M_allocate; - using _Base::_M_deallocate; - using _Base::_S_nword; - using _Base::_M_get_Bit_allocator; - - public: -#if __cplusplus >= 201103L - vector() = default; -#else - vector() { } -#endif - - explicit - vector(const allocator_type& __a) - : _Base(__a) { } - -#if __cplusplus >= 201103L - explicit - vector(size_type __n, const allocator_type& __a = allocator_type()) - : vector(__n, false, __a) - { } - - vector(size_type __n, const bool& __value, - const allocator_type& __a = allocator_type()) -#else - explicit - vector(size_type __n, const bool& __value = bool(), - const allocator_type& __a = allocator_type()) -#endif - : _Base(__a) - { - _M_initialize(__n); - _M_initialize_value(__value); - } - - vector(const vector& __x) - : _Base(_Bit_alloc_traits::_S_select_on_copy(__x._M_get_Bit_allocator())) - { - _M_initialize(__x.size()); - _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); - } - -#if __cplusplus >= 201103L - vector(vector&&) = default; - - vector(vector&& __x, const allocator_type& __a) - noexcept(_Bit_alloc_traits::_S_always_equal()) - : _Base(__a) - { - if (__x.get_allocator() == __a) - this->_M_move_data(std::move(__x)); - else - { - _M_initialize(__x.size()); - _M_copy_aligned(__x.begin(), __x.end(), begin()); - __x.clear(); - } - } - - vector(const vector& __x, const allocator_type& __a) - : _Base(__a) - { - _M_initialize(__x.size()); - _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); - } - - vector(initializer_list __l, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - _M_initialize_range(__l.begin(), __l.end(), - random_access_iterator_tag()); - } -#endif - -#if __cplusplus >= 201103L - template> - vector(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { _M_initialize_dispatch(__first, __last, __false_type()); } -#else - template - vector(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_initialize_dispatch(__first, __last, _Integral()); - } -#endif - - ~vector() _GLIBCXX_NOEXCEPT { } - - vector& - operator=(const vector& __x) - { - if (&__x == this) - return *this; -#if __cplusplus >= 201103L - if (_Bit_alloc_traits::_S_propagate_on_copy_assign()) - { - if (this->_M_get_Bit_allocator() != __x._M_get_Bit_allocator()) - { - this->_M_deallocate(); - std::__alloc_on_copy(_M_get_Bit_allocator(), - __x._M_get_Bit_allocator()); - _M_initialize(__x.size()); - } - else - std::__alloc_on_copy(_M_get_Bit_allocator(), - __x._M_get_Bit_allocator()); - } -#endif - if (__x.size() > capacity()) - { - this->_M_deallocate(); - _M_initialize(__x.size()); - } - this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(), - begin()); - return *this; - } - -#if __cplusplus >= 201103L - vector& - operator=(vector&& __x) noexcept(_Bit_alloc_traits::_S_nothrow_move()) - { - if (_Bit_alloc_traits::_S_propagate_on_move_assign() - || this->_M_get_Bit_allocator() == __x._M_get_Bit_allocator()) - { - this->_M_deallocate(); - this->_M_move_data(std::move(__x)); - std::__alloc_on_move(_M_get_Bit_allocator(), - __x._M_get_Bit_allocator()); - } - else - { - if (__x.size() > capacity()) - { - this->_M_deallocate(); - _M_initialize(__x.size()); - } - this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(), - begin()); - __x.clear(); - } - return *this; - } - - vector& - operator=(initializer_list __l) - { - this->assign (__l.begin(), __l.end()); - return *this; - } -#endif - - // assign(), a generalized assignment member function. Two - // versions: one that takes a count, and one that takes a range. - // The range version is a member template, so we dispatch on whether - // or not the type is an integer. - void - assign(size_type __n, const bool& __x) - { _M_fill_assign(__n, __x); } - -#if __cplusplus >= 201103L - template> - void - assign(_InputIterator __first, _InputIterator __last) - { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } -#else - template - void - assign(_InputIterator __first, _InputIterator __last) - { - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_assign_dispatch(__first, __last, _Integral()); - } -#endif - -#if __cplusplus >= 201103L - void - assign(initializer_list __l) - { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); } -#endif - - iterator - begin() _GLIBCXX_NOEXCEPT - { return iterator(this->_M_impl._M_start._M_p, 0); } - - const_iterator - begin() const _GLIBCXX_NOEXCEPT - { return const_iterator(this->_M_impl._M_start._M_p, 0); } - - iterator - end() _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_finish; } - - const_iterator - end() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_finish; } - - reverse_iterator - rbegin() _GLIBCXX_NOEXCEPT - { return reverse_iterator(end()); } - - const_reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(end()); } - - reverse_iterator - rend() _GLIBCXX_NOEXCEPT - { return reverse_iterator(begin()); } - - const_reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(begin()); } - -#if __cplusplus >= 201103L - const_iterator - cbegin() const noexcept - { return const_iterator(this->_M_impl._M_start._M_p, 0); } - - const_iterator - cend() const noexcept - { return this->_M_impl._M_finish; } - - const_reverse_iterator - crbegin() const noexcept - { return const_reverse_iterator(end()); } - - const_reverse_iterator - crend() const noexcept - { return const_reverse_iterator(begin()); } -#endif - - size_type - size() const _GLIBCXX_NOEXCEPT - { return size_type(end() - begin()); } - - size_type - max_size() const _GLIBCXX_NOEXCEPT - { - const size_type __isize = - __gnu_cxx::__numeric_traits::__max - - int(_S_word_bit) + 1; - const size_type __asize - = _Bit_alloc_traits::max_size(_M_get_Bit_allocator()); - return (__asize <= __isize / int(_S_word_bit) - ? __asize * int(_S_word_bit) : __isize); - } - - size_type - capacity() const _GLIBCXX_NOEXCEPT - { return size_type(const_iterator(this->_M_impl._M_end_addr(), 0) - - begin()); } - - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return begin() == end(); } - - reference - operator[](size_type __n) - { - return *iterator(this->_M_impl._M_start._M_p - + __n / int(_S_word_bit), __n % int(_S_word_bit)); - } - - const_reference - operator[](size_type __n) const - { - return *const_iterator(this->_M_impl._M_start._M_p - + __n / int(_S_word_bit), __n % int(_S_word_bit)); - } - - protected: - void - _M_range_check(size_type __n) const - { - if (__n >= this->size()) - __throw_out_of_range_fmt(__N("vector::_M_range_check: __n " - "(which is %zu) >= this->size() " - "(which is %zu)"), - __n, this->size()); - } - - public: - reference - at(size_type __n) - { _M_range_check(__n); return (*this)[__n]; } - - const_reference - at(size_type __n) const - { _M_range_check(__n); return (*this)[__n]; } - - void - reserve(size_type __n) - { - if (__n > max_size()) - __throw_length_error(__N("vector::reserve")); - if (capacity() < __n) - _M_reallocate(__n); - } - - reference - front() - { return *begin(); } - - const_reference - front() const - { return *begin(); } - - reference - back() - { return *(end() - 1); } - - const_reference - back() const - { return *(end() - 1); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 464. Suggestion for new member functions in standard containers. - // N.B. DR 464 says nothing about vector but we need something - // here due to the way we are implementing DR 464 in the debug-mode - // vector class. - void - data() _GLIBCXX_NOEXCEPT { } - - void - push_back(bool __x) - { - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) - *this->_M_impl._M_finish++ = __x; - else - _M_insert_aux(end(), __x); - } - - void - swap(vector& __x) _GLIBCXX_NOEXCEPT - { - std::swap(this->_M_impl._M_start, __x._M_impl._M_start); - std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish); - std::swap(this->_M_impl._M_end_of_storage, - __x._M_impl._M_end_of_storage); - _Bit_alloc_traits::_S_on_swap(_M_get_Bit_allocator(), - __x._M_get_Bit_allocator()); - } - - // [23.2.5]/1, third-to-last entry in synopsis listing - static void - swap(reference __x, reference __y) _GLIBCXX_NOEXCEPT - { - bool __tmp = __x; - __x = __y; - __y = __tmp; - } - - iterator -#if __cplusplus >= 201103L - insert(const_iterator __position, const bool& __x = bool()) -#else - insert(iterator __position, const bool& __x = bool()) -#endif - { - const difference_type __n = __position - begin(); - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr() - && __position == end()) - *this->_M_impl._M_finish++ = __x; - else - _M_insert_aux(__position._M_const_cast(), __x); - return begin() + __n; - } - -#if __cplusplus >= 201103L - template> - iterator - insert(const_iterator __position, - _InputIterator __first, _InputIterator __last) - { - difference_type __offset = __position - cbegin(); - _M_insert_dispatch(__position._M_const_cast(), - __first, __last, __false_type()); - return begin() + __offset; - } -#else - template - void - insert(iterator __position, - _InputIterator __first, _InputIterator __last) - { - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_insert_dispatch(__position, __first, __last, _Integral()); - } -#endif - -#if __cplusplus >= 201103L - iterator - insert(const_iterator __position, size_type __n, const bool& __x) - { - difference_type __offset = __position - cbegin(); - _M_fill_insert(__position._M_const_cast(), __n, __x); - return begin() + __offset; - } -#else - void - insert(iterator __position, size_type __n, const bool& __x) - { _M_fill_insert(__position, __n, __x); } -#endif - -#if __cplusplus >= 201103L - iterator - insert(const_iterator __p, initializer_list __l) - { return this->insert(__p, __l.begin(), __l.end()); } -#endif - - void - pop_back() - { --this->_M_impl._M_finish; } - - iterator -#if __cplusplus >= 201103L - erase(const_iterator __position) -#else - erase(iterator __position) -#endif - { return _M_erase(__position._M_const_cast()); } - - iterator -#if __cplusplus >= 201103L - erase(const_iterator __first, const_iterator __last) -#else - erase(iterator __first, iterator __last) -#endif - { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } - - void - resize(size_type __new_size, bool __x = bool()) - { - if (__new_size < size()) - _M_erase_at_end(begin() + difference_type(__new_size)); - else - insert(end(), __new_size - size(), __x); - } - -#if __cplusplus >= 201103L - void - shrink_to_fit() - { _M_shrink_to_fit(); } -#endif - - void - flip() _GLIBCXX_NOEXCEPT - { - _Bit_type * const __end = this->_M_impl._M_end_addr(); - for (_Bit_type * __p = this->_M_impl._M_start._M_p; __p != __end; ++__p) - *__p = ~*__p; - } - - void - clear() _GLIBCXX_NOEXCEPT - { _M_erase_at_end(begin()); } - -#if __cplusplus >= 201103L - template -#if __cplusplus > 201402L - reference -#else - void -#endif - emplace_back(_Args&&... __args) - { - push_back(bool(__args...)); -#if __cplusplus > 201402L - return back(); -#endif - } - - template - iterator - emplace(const_iterator __pos, _Args&&... __args) - { return insert(__pos, bool(__args...)); } -#endif - - protected: - // Precondition: __first._M_offset == 0 && __result._M_offset == 0. - iterator - _M_copy_aligned(const_iterator __first, const_iterator __last, - iterator __result) - { - _Bit_type* __q = std::copy(__first._M_p, __last._M_p, __result._M_p); - return std::copy(const_iterator(__last._M_p, 0), __last, - iterator(__q, 0)); - } - - void - _M_initialize(size_type __n) - { - if (__n) - { - _Bit_pointer __q = this->_M_allocate(__n); - this->_M_impl._M_end_of_storage = __q + _S_nword(__n); - this->_M_impl._M_start = iterator(std::__addressof(*__q), 0); - } - else - { - this->_M_impl._M_end_of_storage = _Bit_pointer(); - this->_M_impl._M_start = iterator(0, 0); - } - this->_M_impl._M_finish = this->_M_impl._M_start + difference_type(__n); - - } - - void - _M_initialize_value(bool __x) - { - if (_Bit_type* __p = this->_M_impl._M_start._M_p) - __builtin_memset(__p, __x ? ~0 : 0, - (this->_M_impl._M_end_addr() - __p) - * sizeof(_Bit_type)); - } - - void - _M_reallocate(size_type __n); - -#if __cplusplus >= 201103L - bool - _M_shrink_to_fit(); -#endif - - // Check whether it's an integral type. If so, it's not an iterator. - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) - { - _M_initialize(static_cast(__n)); - _M_initialize_value(__x); - } - - template - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { _M_initialize_range(__first, __last, - std::__iterator_category(__first)); } - - template - void - _M_initialize_range(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag) - { - for (; __first != __last; ++__first) - push_back(*__first); - } - - template - void - _M_initialize_range(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) - { - const size_type __n = std::distance(__first, __last); - _M_initialize(__n); - std::copy(__first, __last, this->_M_impl._M_start); - } - -#if __cplusplus < 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { _M_fill_assign(__n, __val); } - - template - void - _M_assign_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } -#endif - - void - _M_fill_assign(size_t __n, bool __x) - { - if (__n > size()) - { - _M_initialize_value(__x); - insert(end(), __n - size(), __x); - } - else - { - _M_erase_at_end(begin() + __n); - _M_initialize_value(__x); - } - } - - template - void - _M_assign_aux(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag) - { - iterator __cur = begin(); - for (; __first != __last && __cur != end(); ++__cur, (void)++__first) - *__cur = *__first; - if (__first == __last) - _M_erase_at_end(__cur); - else - insert(end(), __first, __last); - } - - template - void - _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) - { - const size_type __len = std::distance(__first, __last); - if (__len < size()) - _M_erase_at_end(std::copy(__first, __last, begin())); - else - { - _ForwardIterator __mid = __first; - std::advance(__mid, size()); - std::copy(__first, __mid, begin()); - insert(end(), __mid, __last); - } - } - - // Check whether it's an integral type. If so, it's not an iterator. - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, - __true_type) - { _M_fill_insert(__pos, __n, __x); } - - template - void - _M_insert_dispatch(iterator __pos, - _InputIterator __first, _InputIterator __last, - __false_type) - { _M_insert_range(__pos, __first, __last, - std::__iterator_category(__first)); } - - void - _M_fill_insert(iterator __position, size_type __n, bool __x); - - template - void - _M_insert_range(iterator __pos, _InputIterator __first, - _InputIterator __last, std::input_iterator_tag) - { - for (; __first != __last; ++__first) - { - __pos = insert(__pos, *__first); - ++__pos; - } - } - - template - void - _M_insert_range(iterator __position, _ForwardIterator __first, - _ForwardIterator __last, std::forward_iterator_tag); - - void - _M_insert_aux(iterator __position, bool __x); - - size_type - _M_check_len(size_type __n, const char* __s) const - { - if (max_size() - size() < __n) - __throw_length_error(__N(__s)); - - const size_type __len = size() + std::max(size(), __n); - return (__len < size() || __len > max_size()) ? max_size() : __len; - } - - void - _M_erase_at_end(iterator __pos) - { this->_M_impl._M_finish = __pos; } - - iterator - _M_erase(iterator __pos); - - iterator - _M_erase(iterator __first, iterator __last); - }; - -_GLIBCXX_END_NAMESPACE_CONTAINER -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#if __cplusplus >= 201103L - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // DR 1182. - /// std::hash specialization for vector. - template - struct hash<_GLIBCXX_STD_C::vector> - : public __hash_base> - { - size_t - operator()(const _GLIBCXX_STD_C::vector&) const noexcept; - }; - -_GLIBCXX_END_NAMESPACE_VERSION -}// namespace std - -#endif // C++11 - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_construct.h b/resources/sources/avr-libstdcpp/include/bits/stl_construct.h deleted file mode 100644 index 72a7cb471..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_construct.h +++ /dev/null @@ -1,256 +0,0 @@ -// nonstandard construct and destroy functions -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_construct.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _STL_CONSTRUCT_H -#define _STL_CONSTRUCT_H 1 - -#include -#include -#include // for iterator_traits -#include // for advance - -/* This file provides the C++17 functions std::destroy_at, std::destroy, and - * std::destroy_n, and the C++20 function std::construct_at. - * It also provides std::_Construct, std::_Destroy,and std::_Destroy_n functions - * which are defined in all standard modes and so can be used in C++98-14 code. - * The _Destroy functions will dispatch to destroy_at during constant - * evaluation, because calls to that function are intercepted by the compiler - * to allow use in constant expressions. - */ - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#if __cplusplus >= 201703L - template - _GLIBCXX20_CONSTEXPR inline void - destroy_at(_Tp* __location) - { - if constexpr (__cplusplus > 201703L && is_array_v<_Tp>) - { - for (auto& __x : *__location) - std::destroy_at(std::__addressof(__x)); - } - else - __location->~_Tp(); - } - -#if __cplusplus > 201703L - template - constexpr auto - construct_at(_Tp* __location, _Args&&... __args) - noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...))) - -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...)) - { return ::new((void*)__location) _Tp(std::forward<_Args>(__args)...); } -#endif // C++20 -#endif// C++17 - - /** - * Constructs an object in existing memory by invoking an allocated - * object's constructor with an initializer. - */ -#if __cplusplus >= 201103L - template - inline void - _Construct(_Tp* __p, _Args&&... __args) - { ::new(static_cast(__p)) _Tp(std::forward<_Args>(__args)...); } -#else - template - inline void - _Construct(_T1* __p, const _T2& __value) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 402. wrong new expression in [some_]allocator::construct - ::new(static_cast(__p)) _T1(__value); - } -#endif - - template - inline void - _Construct_novalue(_T1* __p) - { ::new(static_cast(__p)) _T1; } - - template - _GLIBCXX20_CONSTEXPR void - _Destroy(_ForwardIterator __first, _ForwardIterator __last); - - /** - * Destroy the object pointed to by a pointer type. - */ - template - _GLIBCXX14_CONSTEXPR inline void - _Destroy(_Tp* __pointer) - { -#if __cplusplus > 201703L - std::destroy_at(__pointer); -#else - __pointer->~_Tp(); -#endif - } - - template - struct _Destroy_aux - { - template - static _GLIBCXX20_CONSTEXPR void - __destroy(_ForwardIterator __first, _ForwardIterator __last) - { - for (; __first != __last; ++__first) - std::_Destroy(std::__addressof(*__first)); - } - }; - - template<> - struct _Destroy_aux - { - template - static void - __destroy(_ForwardIterator, _ForwardIterator) { } - }; - - /** - * Destroy a range of objects. If the value_type of the object has - * a trivial destructor, the compiler should optimize all of this - * away, otherwise the objects' destructors must be invoked. - */ - template - _GLIBCXX20_CONSTEXPR inline void - _Destroy(_ForwardIterator __first, _ForwardIterator __last) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _Value_type; -#if __cplusplus >= 201103L - // A deleted destructor is trivial, this ensures we reject such types: - static_assert(is_destructible<_Value_type>::value, - "value type is destructible"); -#endif -#if __cplusplus > 201703L && defined __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return _Destroy_aux::__destroy(__first, __last); -#endif - std::_Destroy_aux<__has_trivial_destructor(_Value_type)>:: - __destroy(__first, __last); - } - - template - struct _Destroy_n_aux - { - template - static _GLIBCXX20_CONSTEXPR _ForwardIterator - __destroy_n(_ForwardIterator __first, _Size __count) - { - for (; __count > 0; (void)++__first, --__count) - std::_Destroy(std::__addressof(*__first)); - return __first; - } - }; - - template<> - struct _Destroy_n_aux - { - template - static _ForwardIterator - __destroy_n(_ForwardIterator __first, _Size __count) - { - std::advance(__first, __count); - return __first; - } - }; - - /** - * Destroy a range of objects. If the value_type of the object has - * a trivial destructor, the compiler should optimize all of this - * away, otherwise the objects' destructors must be invoked. - */ - template - _GLIBCXX20_CONSTEXPR inline _ForwardIterator - _Destroy_n(_ForwardIterator __first, _Size __count) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _Value_type; -#if __cplusplus >= 201103L - // A deleted destructor is trivial, this ensures we reject such types: - static_assert(is_destructible<_Value_type>::value, - "value type is destructible"); -#endif -#if __cplusplus > 201703L && defined __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - return _Destroy_n_aux::__destroy_n(__first, __count); -#endif - return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>:: - __destroy_n(__first, __count); - } - -#if __cplusplus >= 201703L - template - _GLIBCXX20_CONSTEXPR inline void - destroy(_ForwardIterator __first, _ForwardIterator __last) - { - std::_Destroy(__first, __last); - } - - template - _GLIBCXX20_CONSTEXPR inline _ForwardIterator - destroy_n(_ForwardIterator __first, _Size __count) - { - return std::_Destroy_n(__first, __count); - } -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_CONSTRUCT_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_deque.h b/resources/sources/avr-libstdcpp/include/bits/stl_deque.h deleted file mode 100644 index 3959dd789..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_deque.h +++ /dev/null @@ -1,2330 +0,0 @@ -// Deque implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_deque.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{deque} - */ - -#ifndef _STL_DEQUE_H -#define _STL_DEQUE_H 1 - -#include -#include -#include -#if __cplusplus >= 201103L -#include -#include // for __is_bitwise_relocatable -#endif -#if __cplusplus > 201703L -# include -#endif - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - /** - * @brief This function controls the size of memory nodes. - * @param __size The size of an element. - * @return The number (not byte size) of elements per node. - * - * This function started off as a compiler kludge from SGI, but - * seems to be a useful wrapper around a repeated constant - * expression. The @b 512 is tunable (and no other code needs to - * change), but no investigation has been done since inheriting the - * SGI code. Touch _GLIBCXX_DEQUE_BUF_SIZE only if you know what - * you are doing, however: changing it breaks the binary - * compatibility!! - */ - -#ifndef _GLIBCXX_DEQUE_BUF_SIZE -#define _GLIBCXX_DEQUE_BUF_SIZE 512 -#endif - - _GLIBCXX_CONSTEXPR inline size_t - __deque_buf_size(size_t __size) - { return (__size < _GLIBCXX_DEQUE_BUF_SIZE - ? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1)); } - - - /** - * @brief A deque::iterator. - * - * Quite a bit of intelligence here. Much of the functionality of - * deque is actually passed off to this class. A deque holds two - * of these internally, marking its valid range. Access to - * elements is done as offsets of either of those two, relying on - * operator overloading in this class. - * - * All the functions are op overloads except for _M_set_node. - */ - template - struct _Deque_iterator - { -#if __cplusplus < 201103L - typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; - typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; - typedef _Tp* _Elt_pointer; - typedef _Tp** _Map_pointer; -#else - private: - template - using __iter = _Deque_iterator<_Tp, _CvTp&, __ptr_rebind<_Ptr, _CvTp>>; - public: - typedef __iter<_Tp> iterator; - typedef __iter const_iterator; - typedef __ptr_rebind<_Ptr, _Tp> _Elt_pointer; - typedef __ptr_rebind<_Ptr, _Elt_pointer> _Map_pointer; -#endif - - static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT - { return __deque_buf_size(sizeof(_Tp)); } - - typedef std::random_access_iterator_tag iterator_category; - typedef _Tp value_type; - typedef _Ptr pointer; - typedef _Ref reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Deque_iterator _Self; - - _Elt_pointer _M_cur; - _Elt_pointer _M_first; - _Elt_pointer _M_last; - _Map_pointer _M_node; - - _Deque_iterator(_Elt_pointer __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT - : _M_cur(__x), _M_first(*__y), - _M_last(*__y + _S_buffer_size()), _M_node(__y) { } - - _Deque_iterator() _GLIBCXX_NOEXCEPT - : _M_cur(), _M_first(), _M_last(), _M_node() { } - -#if __cplusplus < 201103L - // Conversion from iterator to const_iterator. - _Deque_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT - : _M_cur(__x._M_cur), _M_first(__x._M_first), - _M_last(__x._M_last), _M_node(__x._M_node) { } -#else - // Conversion from iterator to const_iterator. - template, - is_same<_Iter, iterator>>> - _Deque_iterator(const _Iter& __x) noexcept - : _M_cur(__x._M_cur), _M_first(__x._M_first), - _M_last(__x._M_last), _M_node(__x._M_node) { } - - _Deque_iterator(const _Deque_iterator& __x) noexcept - : _M_cur(__x._M_cur), _M_first(__x._M_first), - _M_last(__x._M_last), _M_node(__x._M_node) { } - - _Deque_iterator& operator=(const _Deque_iterator&) = default; -#endif - - iterator - _M_const_cast() const _GLIBCXX_NOEXCEPT - { return iterator(_M_cur, _M_node); } - - reference - operator*() const _GLIBCXX_NOEXCEPT - { return *_M_cur; } - - pointer - operator->() const _GLIBCXX_NOEXCEPT - { return _M_cur; } - - _Self& - operator++() _GLIBCXX_NOEXCEPT - { - ++_M_cur; - if (_M_cur == _M_last) - { - _M_set_node(_M_node + 1); - _M_cur = _M_first; - } - return *this; - } - - _Self - operator++(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - ++*this; - return __tmp; - } - - _Self& - operator--() _GLIBCXX_NOEXCEPT - { - if (_M_cur == _M_first) - { - _M_set_node(_M_node - 1); - _M_cur = _M_last; - } - --_M_cur; - return *this; - } - - _Self - operator--(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - --*this; - return __tmp; - } - - _Self& - operator+=(difference_type __n) _GLIBCXX_NOEXCEPT - { - const difference_type __offset = __n + (_M_cur - _M_first); - if (__offset >= 0 && __offset < difference_type(_S_buffer_size())) - _M_cur += __n; - else - { - const difference_type __node_offset = - __offset > 0 ? __offset / difference_type(_S_buffer_size()) - : -difference_type((-__offset - 1) - / _S_buffer_size()) - 1; - _M_set_node(_M_node + __node_offset); - _M_cur = _M_first + (__offset - __node_offset - * difference_type(_S_buffer_size())); - } - return *this; - } - - _Self& - operator-=(difference_type __n) _GLIBCXX_NOEXCEPT - { return *this += -__n; } - - reference - operator[](difference_type __n) const _GLIBCXX_NOEXCEPT - { return *(*this + __n); } - - /** - * Prepares to traverse new_node. Sets everything except - * _M_cur, which should therefore be set by the caller - * immediately afterwards, based on _M_first and _M_last. - */ - void - _M_set_node(_Map_pointer __new_node) _GLIBCXX_NOEXCEPT - { - _M_node = __new_node; - _M_first = *__new_node; - _M_last = _M_first + difference_type(_S_buffer_size()); - } - - friend bool - operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_cur == __y._M_cur; } - - // Note: we also provide overloads whose operands are of the same type in - // order to avoid ambiguous overload resolution when std::rel_ops - // operators are in scope (for additional details, see libstdc++/3628) - template - friend bool - operator==(const _Self& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) - _GLIBCXX_NOEXCEPT - { return __x._M_cur == __y._M_cur; } - -#if __cpp_lib_three_way_comparison - friend strong_ordering - operator<=>(const _Self& __x, const _Self& __y) noexcept - { - if (const auto __cmp = __x._M_node <=> __y._M_node; __cmp != 0) - return __cmp; - return __x._M_cur <=> __y._M_cur; - } -#else - friend bool - operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return !(__x == __y); } - - template - friend bool - operator!=(const _Self& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) - _GLIBCXX_NOEXCEPT - { return !(__x == __y); } - - friend bool - operator<(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { - return (__x._M_node == __y._M_node) - ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); - } - - template - friend bool - operator<(const _Self& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) - _GLIBCXX_NOEXCEPT - { - return (__x._M_node == __y._M_node) - ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); - } - - friend bool - operator>(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __y < __x; } - - template - friend bool - operator>(const _Self& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) - _GLIBCXX_NOEXCEPT - { return __y < __x; } - - friend bool - operator<=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return !(__y < __x); } - - template - friend bool - operator<=(const _Self& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) - _GLIBCXX_NOEXCEPT - { return !(__y < __x); } - - friend bool - operator>=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return !(__x < __y); } - - template - friend bool - operator>=(const _Self& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) - _GLIBCXX_NOEXCEPT - { return !(__x < __y); } -#endif // three-way comparison - - friend difference_type - operator-(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { - return difference_type(_S_buffer_size()) - * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) - + (__y._M_last - __y._M_cur); - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // According to the resolution of DR179 not only the various comparison - // operators but also operator- must accept mixed iterator/const_iterator - // parameters. - template - friend difference_type - operator-(const _Self& __x, - const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT - { - return difference_type(_S_buffer_size()) - * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) - + (__y._M_last - __y._M_cur); - } - - friend _Self - operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT - { - _Self __tmp = __x; - __tmp += __n; - return __tmp; - } - - friend _Self - operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT - { - _Self __tmp = __x; - __tmp -= __n; - return __tmp; - } - - friend _Self - operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT - { return __x + __n; } - }; - - /** - * Deque base class. This class provides the unified face for %deque's - * allocation. This class's constructor and destructor allocate and - * deallocate (but do not initialize) storage. This makes %exception - * safety easier. - * - * Nothing in this class ever constructs or destroys an actual Tp element. - * (Deque handles that itself.) Only/All memory management is performed - * here. - */ - template - class _Deque_base - { - protected: - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_Tp>::other _Tp_alloc_type; - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; - -#if __cplusplus < 201103L - typedef _Tp* _Ptr; - typedef const _Tp* _Ptr_const; -#else - typedef typename _Alloc_traits::pointer _Ptr; - typedef typename _Alloc_traits::const_pointer _Ptr_const; -#endif - - typedef typename _Alloc_traits::template rebind<_Ptr>::other - _Map_alloc_type; - typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits; - - typedef _Alloc allocator_type; - - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_M_get_Tp_allocator()); } - - typedef _Deque_iterator<_Tp, _Tp&, _Ptr> iterator; - typedef _Deque_iterator<_Tp, const _Tp&, _Ptr_const> const_iterator; - - _Deque_base() - : _M_impl() - { _M_initialize_map(0); } - - _Deque_base(size_t __num_elements) - : _M_impl() - { _M_initialize_map(__num_elements); } - - _Deque_base(const allocator_type& __a, size_t __num_elements) - : _M_impl(__a) - { _M_initialize_map(__num_elements); } - - _Deque_base(const allocator_type& __a) - : _M_impl(__a) - { /* Caller must initialize map. */ } - -#if __cplusplus >= 201103L - _Deque_base(_Deque_base&& __x) - : _M_impl(std::move(__x._M_get_Tp_allocator())) - { - _M_initialize_map(0); - if (__x._M_impl._M_map) - this->_M_impl._M_swap_data(__x._M_impl); - } - - _Deque_base(_Deque_base&& __x, const allocator_type& __a) - : _M_impl(std::move(__x._M_impl), _Tp_alloc_type(__a)) - { __x._M_initialize_map(0); } - - _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_t __n) - : _M_impl(__a) - { - if (__x.get_allocator() == __a) - { - if (__x._M_impl._M_map) - { - _M_initialize_map(0); - this->_M_impl._M_swap_data(__x._M_impl); - } - } - else - { - _M_initialize_map(__n); - } - } -#endif - - ~_Deque_base() _GLIBCXX_NOEXCEPT; - - typedef typename iterator::_Map_pointer _Map_pointer; - - struct _Deque_impl_data - { - _Map_pointer _M_map; - size_t _M_map_size; - iterator _M_start; - iterator _M_finish; - - _Deque_impl_data() _GLIBCXX_NOEXCEPT - : _M_map(), _M_map_size(), _M_start(), _M_finish() - { } - -#if __cplusplus >= 201103L - _Deque_impl_data(const _Deque_impl_data&) = default; - _Deque_impl_data& - operator=(const _Deque_impl_data&) = default; - - _Deque_impl_data(_Deque_impl_data&& __x) noexcept - : _Deque_impl_data(__x) - { __x = _Deque_impl_data(); } -#endif - - void - _M_swap_data(_Deque_impl_data& __x) _GLIBCXX_NOEXCEPT - { - // Do not use std::swap(_M_start, __x._M_start), etc as it loses - // information used by TBAA. - std::swap(*this, __x); - } - }; - - // This struct encapsulates the implementation of the std::deque - // standard container and at the same time makes use of the EBO - // for empty allocators. - struct _Deque_impl - : public _Tp_alloc_type, public _Deque_impl_data - { - _Deque_impl() _GLIBCXX_NOEXCEPT_IF( - is_nothrow_default_constructible<_Tp_alloc_type>::value) - : _Tp_alloc_type() - { } - - _Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT - : _Tp_alloc_type(__a) - { } - -#if __cplusplus >= 201103L - _Deque_impl(_Deque_impl&&) = default; - - _Deque_impl(_Tp_alloc_type&& __a) noexcept - : _Tp_alloc_type(std::move(__a)) - { } - - _Deque_impl(_Deque_impl&& __d, _Tp_alloc_type&& __a) - : _Tp_alloc_type(std::move(__a)), _Deque_impl_data(std::move(__d)) - { } -#endif - }; - - _Tp_alloc_type& - _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT - { return this->_M_impl; } - - const _Tp_alloc_type& - _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT - { return this->_M_impl; } - - _Map_alloc_type - _M_get_map_allocator() const _GLIBCXX_NOEXCEPT - { return _Map_alloc_type(_M_get_Tp_allocator()); } - - _Ptr - _M_allocate_node() - { - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits; - return _Traits::allocate(_M_impl, __deque_buf_size(sizeof(_Tp))); - } - - void - _M_deallocate_node(_Ptr __p) _GLIBCXX_NOEXCEPT - { - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits; - _Traits::deallocate(_M_impl, __p, __deque_buf_size(sizeof(_Tp))); - } - - _Map_pointer - _M_allocate_map(size_t __n) - { - _Map_alloc_type __map_alloc = _M_get_map_allocator(); - return _Map_alloc_traits::allocate(__map_alloc, __n); - } - - void - _M_deallocate_map(_Map_pointer __p, size_t __n) _GLIBCXX_NOEXCEPT - { - _Map_alloc_type __map_alloc = _M_get_map_allocator(); - _Map_alloc_traits::deallocate(__map_alloc, __p, __n); - } - - void _M_initialize_map(size_t); - void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish); - void _M_destroy_nodes(_Map_pointer __nstart, - _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT; - enum { _S_initial_map_size = 8 }; - - _Deque_impl _M_impl; - }; - - template - _Deque_base<_Tp, _Alloc>:: - ~_Deque_base() _GLIBCXX_NOEXCEPT - { - if (this->_M_impl._M_map) - { - _M_destroy_nodes(this->_M_impl._M_start._M_node, - this->_M_impl._M_finish._M_node + 1); - _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); - } - } - - /** - * @brief Layout storage. - * @param __num_elements The count of T's for which to allocate space - * at first. - * @return Nothing. - * - * The initial underlying memory layout is a bit complicated... - */ - template - void - _Deque_base<_Tp, _Alloc>:: - _M_initialize_map(size_t __num_elements) - { - const size_t __num_nodes = (__num_elements / __deque_buf_size(sizeof(_Tp)) - + 1); - - this->_M_impl._M_map_size = std::max((size_t) _S_initial_map_size, - size_t(__num_nodes + 2)); - this->_M_impl._M_map = _M_allocate_map(this->_M_impl._M_map_size); - - // For "small" maps (needing less than _M_map_size nodes), allocation - // starts in the middle elements and grows outwards. So nstart may be - // the beginning of _M_map, but for small maps it may be as far in as - // _M_map+3. - - _Map_pointer __nstart = (this->_M_impl._M_map - + (this->_M_impl._M_map_size - __num_nodes) / 2); - _Map_pointer __nfinish = __nstart + __num_nodes; - - __try - { _M_create_nodes(__nstart, __nfinish); } - __catch(...) - { - _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); - this->_M_impl._M_map = _Map_pointer(); - this->_M_impl._M_map_size = 0; - __throw_exception_again; - } - - this->_M_impl._M_start._M_set_node(__nstart); - this->_M_impl._M_finish._M_set_node(__nfinish - 1); - this->_M_impl._M_start._M_cur = _M_impl._M_start._M_first; - this->_M_impl._M_finish._M_cur = (this->_M_impl._M_finish._M_first - + __num_elements - % __deque_buf_size(sizeof(_Tp))); - } - - template - void - _Deque_base<_Tp, _Alloc>:: - _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish) - { - _Map_pointer __cur; - __try - { - for (__cur = __nstart; __cur < __nfinish; ++__cur) - *__cur = this->_M_allocate_node(); - } - __catch(...) - { - _M_destroy_nodes(__nstart, __cur); - __throw_exception_again; - } - } - - template - void - _Deque_base<_Tp, _Alloc>:: - _M_destroy_nodes(_Map_pointer __nstart, - _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT - { - for (_Map_pointer __n = __nstart; __n < __nfinish; ++__n) - _M_deallocate_node(*__n); - } - - /** - * @brief A standard container using fixed-size memory allocation and - * constant-time manipulation of elements at either end. - * - * @ingroup sequences - * - * @tparam _Tp Type of element. - * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. - * - * Meets the requirements of a container, a - * reversible container, and a - * sequence, including the - * optional sequence requirements. - * - * In previous HP/SGI versions of deque, there was an extra template - * parameter so users could control the node size. This extension turned - * out to violate the C++ standard (it can be detected using template - * template parameters), and it was removed. - * - * Here's how a deque manages memory. Each deque has 4 members: - * - * - Tp** _M_map - * - size_t _M_map_size - * - iterator _M_start, _M_finish - * - * map_size is at least 8. %map is an array of map_size - * pointers-to-@a nodes. (The name %map has nothing to do with the - * std::map class, and @b nodes should not be confused with - * std::list's usage of @a node.) - * - * A @a node has no specific type name as such, but it is referred - * to as @a node in this file. It is a simple array-of-Tp. If Tp - * is very large, there will be one Tp element per node (i.e., an - * @a array of one). For non-huge Tp's, node size is inversely - * related to Tp size: the larger the Tp, the fewer Tp's will fit - * in a node. The goal here is to keep the total size of a node - * relatively small and constant over different Tp's, to improve - * allocator efficiency. - * - * Not every pointer in the %map array will point to a node. If - * the initial number of elements in the deque is small, the - * /middle/ %map pointers will be valid, and the ones at the edges - * will be unused. This same situation will arise as the %map - * grows: available %map pointers, if any, will be on the ends. As - * new nodes are created, only a subset of the %map's pointers need - * to be copied @a outward. - * - * Class invariants: - * - For any nonsingular iterator i: - * - i.node points to a member of the %map array. (Yes, you read that - * correctly: i.node does not actually point to a node.) The member of - * the %map array is what actually points to the node. - * - i.first == *(i.node) (This points to the node (first Tp element).) - * - i.last == i.first + node_size - * - i.cur is a pointer in the range [i.first, i.last). NOTE: - * the implication of this is that i.cur is always a dereferenceable - * pointer, even if i is a past-the-end iterator. - * - Start and Finish are always nonsingular iterators. NOTE: this - * means that an empty deque must have one node, a deque with > - class deque : protected _Deque_base<_Tp, _Alloc> - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -# endif - __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) -#endif - -#if __cplusplus >= 201103L - static_assert(is_same::type, _Tp>::value, - "std::deque must have a non-const, non-volatile value_type"); -# if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same::value, - "std::deque must have the same value_type as its allocator"); -# endif -#endif - - typedef _Deque_base<_Tp, _Alloc> _Base; - typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; - typedef typename _Base::_Alloc_traits _Alloc_traits; - typedef typename _Base::_Map_pointer _Map_pointer; - - public: - typedef _Tp value_type; - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; - typedef typename _Base::iterator iterator; - typedef typename _Base::const_iterator const_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; - - private: - static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT - { return __deque_buf_size(sizeof(_Tp)); } - - // Functions controlling memory layout, and nothing else. - using _Base::_M_initialize_map; - using _Base::_M_create_nodes; - using _Base::_M_destroy_nodes; - using _Base::_M_allocate_node; - using _Base::_M_deallocate_node; - using _Base::_M_allocate_map; - using _Base::_M_deallocate_map; - using _Base::_M_get_Tp_allocator; - - /** - * A total of four data members accumulated down the hierarchy. - * May be accessed via _M_impl.* - */ - using _Base::_M_impl; - - public: - // [23.2.1.1] construct/copy/destroy - // (assign() and get_allocator() are also listed in this section) - - /** - * @brief Creates a %deque with no elements. - */ -#if __cplusplus >= 201103L - deque() = default; -#else - deque() { } -#endif - - /** - * @brief Creates a %deque with no elements. - * @param __a An allocator object. - */ - explicit - deque(const allocator_type& __a) - : _Base(__a, 0) { } - -#if __cplusplus >= 201103L - /** - * @brief Creates a %deque with default constructed elements. - * @param __n The number of elements to initially create. - * @param __a An allocator. - * - * This constructor fills the %deque with @a n default - * constructed elements. - */ - explicit - deque(size_type __n, const allocator_type& __a = allocator_type()) - : _Base(__a, _S_check_init_len(__n, __a)) - { _M_default_initialize(); } - - /** - * @brief Creates a %deque with copies of an exemplar element. - * @param __n The number of elements to initially create. - * @param __value An element to copy. - * @param __a An allocator. - * - * This constructor fills the %deque with @a __n copies of @a __value. - */ - deque(size_type __n, const value_type& __value, - const allocator_type& __a = allocator_type()) - : _Base(__a, _S_check_init_len(__n, __a)) - { _M_fill_initialize(__value); } -#else - /** - * @brief Creates a %deque with copies of an exemplar element. - * @param __n The number of elements to initially create. - * @param __value An element to copy. - * @param __a An allocator. - * - * This constructor fills the %deque with @a __n copies of @a __value. - */ - explicit - deque(size_type __n, const value_type& __value = value_type(), - const allocator_type& __a = allocator_type()) - : _Base(__a, _S_check_init_len(__n, __a)) - { _M_fill_initialize(__value); } -#endif - - /** - * @brief %Deque copy constructor. - * @param __x A %deque of identical element and allocator types. - * - * The newly-created %deque uses a copy of the allocator object used - * by @a __x (unless the allocator traits dictate a different object). - */ - deque(const deque& __x) - : _Base(_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()), - __x.size()) - { std::__uninitialized_copy_a(__x.begin(), __x.end(), - this->_M_impl._M_start, - _M_get_Tp_allocator()); } - -#if __cplusplus >= 201103L - /** - * @brief %Deque move constructor. - * - * The newly-created %deque contains the exact contents of the - * moved instance. - * The contents of the moved instance are a valid, but unspecified - * %deque. - */ - deque(deque&&) = default; - - /// Copy constructor with alternative allocator - deque(const deque& __x, const allocator_type& __a) - : _Base(__a, __x.size()) - { std::__uninitialized_copy_a(__x.begin(), __x.end(), - this->_M_impl._M_start, - _M_get_Tp_allocator()); } - - /// Move constructor with alternative allocator - deque(deque&& __x, const allocator_type& __a) - : deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{}) - { } - - private: - deque(deque&& __x, const allocator_type& __a, true_type) - : _Base(std::move(__x), __a) - { } - - deque(deque&& __x, const allocator_type& __a, false_type) - : _Base(std::move(__x), __a, __x.size()) - { - if (__x.get_allocator() != __a && !__x.empty()) - { - std::__uninitialized_move_a(__x.begin(), __x.end(), - this->_M_impl._M_start, - _M_get_Tp_allocator()); - __x.clear(); - } - } - - public: - /** - * @brief Builds a %deque from an initializer list. - * @param __l An initializer_list. - * @param __a An allocator object. - * - * Create a %deque consisting of copies of the elements in the - * initializer_list @a __l. - * - * This will call the element type's copy constructor N times - * (where N is __l.size()) and do no memory reallocation. - */ - deque(initializer_list __l, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - _M_range_initialize(__l.begin(), __l.end(), - random_access_iterator_tag()); - } -#endif - - /** - * @brief Builds a %deque from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __a An allocator object. - * - * Create a %deque consisting of copies of the elements from [__first, - * __last). - * - * If the iterators are forward, bidirectional, or random-access, then - * this will call the elements' copy constructor N times (where N is - * distance(__first,__last)) and do no memory reallocation. But if only - * input iterators are used, then this will do at most 2N calls to the - * copy constructor, and logN memory reallocations. - */ -#if __cplusplus >= 201103L - template> - deque(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - _M_range_initialize(__first, __last, - std::__iterator_category(__first)); - } -#else - template - deque(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_initialize_dispatch(__first, __last, _Integral()); - } -#endif - - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibility. - */ - ~deque() - { _M_destroy_data(begin(), end(), _M_get_Tp_allocator()); } - - /** - * @brief %Deque assignment operator. - * @param __x A %deque of identical element and allocator types. - * - * All the elements of @a x are copied. - * - * The newly-created %deque uses a copy of the allocator object used - * by @a __x (unless the allocator traits dictate a different object). - */ - deque& - operator=(const deque& __x); - -#if __cplusplus >= 201103L - /** - * @brief %Deque move assignment operator. - * @param __x A %deque of identical element and allocator types. - * - * The contents of @a __x are moved into this deque (without copying, - * if the allocators permit it). - * @a __x is a valid, but unspecified %deque. - */ - deque& - operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal()) - { - using __always_equal = typename _Alloc_traits::is_always_equal; - _M_move_assign1(std::move(__x), __always_equal{}); - return *this; - } - - /** - * @brief Assigns an initializer list to a %deque. - * @param __l An initializer_list. - * - * This function fills a %deque with copies of the elements in the - * initializer_list @a __l. - * - * Note that the assignment completely changes the %deque and that the - * resulting %deque's size is the same as the number of elements - * assigned. - */ - deque& - operator=(initializer_list __l) - { - _M_assign_aux(__l.begin(), __l.end(), - random_access_iterator_tag()); - return *this; - } -#endif - - /** - * @brief Assigns a given value to a %deque. - * @param __n Number of elements to be assigned. - * @param __val Value to be assigned. - * - * This function fills a %deque with @a n copies of the given - * value. Note that the assignment completely changes the - * %deque and that the resulting %deque's size is the same as - * the number of elements assigned. - */ - void - assign(size_type __n, const value_type& __val) - { _M_fill_assign(__n, __val); } - - /** - * @brief Assigns a range to a %deque. - * @param __first An input iterator. - * @param __last An input iterator. - * - * This function fills a %deque with copies of the elements in the - * range [__first,__last). - * - * Note that the assignment completely changes the %deque and that the - * resulting %deque's size is the same as the number of elements - * assigned. - */ -#if __cplusplus >= 201103L - template> - void - assign(_InputIterator __first, _InputIterator __last) - { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } -#else - template - void - assign(_InputIterator __first, _InputIterator __last) - { - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_assign_dispatch(__first, __last, _Integral()); - } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Assigns an initializer list to a %deque. - * @param __l An initializer_list. - * - * This function fills a %deque with copies of the elements in the - * initializer_list @a __l. - * - * Note that the assignment completely changes the %deque and that the - * resulting %deque's size is the same as the number of elements - * assigned. - */ - void - assign(initializer_list __l) - { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); } -#endif - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return _Base::get_allocator(); } - - // iterators - /** - * Returns a read/write iterator that points to the first element in the - * %deque. Iteration is done in ordinary element order. - */ - iterator - begin() _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_start; } - - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %deque. Iteration is done in ordinary element order. - */ - const_iterator - begin() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_start; } - - /** - * Returns a read/write iterator that points one past the last - * element in the %deque. Iteration is done in ordinary - * element order. - */ - iterator - end() _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_finish; } - - /** - * Returns a read-only (constant) iterator that points one past - * the last element in the %deque. Iteration is done in - * ordinary element order. - */ - const_iterator - end() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_finish; } - - /** - * Returns a read/write reverse iterator that points to the - * last element in the %deque. Iteration is done in reverse - * element order. - */ - reverse_iterator - rbegin() _GLIBCXX_NOEXCEPT - { return reverse_iterator(this->_M_impl._M_finish); } - - /** - * Returns a read-only (constant) reverse iterator that points - * to the last element in the %deque. Iteration is done in - * reverse element order. - */ - const_reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(this->_M_impl._M_finish); } - - /** - * Returns a read/write reverse iterator that points to one - * before the first element in the %deque. Iteration is done - * in reverse element order. - */ - reverse_iterator - rend() _GLIBCXX_NOEXCEPT - { return reverse_iterator(this->_M_impl._M_start); } - - /** - * Returns a read-only (constant) reverse iterator that points - * to one before the first element in the %deque. Iteration is - * done in reverse element order. - */ - const_reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(this->_M_impl._M_start); } - -#if __cplusplus >= 201103L - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %deque. Iteration is done in ordinary element order. - */ - const_iterator - cbegin() const noexcept - { return this->_M_impl._M_start; } - - /** - * Returns a read-only (constant) iterator that points one past - * the last element in the %deque. Iteration is done in - * ordinary element order. - */ - const_iterator - cend() const noexcept - { return this->_M_impl._M_finish; } - - /** - * Returns a read-only (constant) reverse iterator that points - * to the last element in the %deque. Iteration is done in - * reverse element order. - */ - const_reverse_iterator - crbegin() const noexcept - { return const_reverse_iterator(this->_M_impl._M_finish); } - - /** - * Returns a read-only (constant) reverse iterator that points - * to one before the first element in the %deque. Iteration is - * done in reverse element order. - */ - const_reverse_iterator - crend() const noexcept - { return const_reverse_iterator(this->_M_impl._M_start); } -#endif - - // [23.2.1.2] capacity - /** Returns the number of elements in the %deque. */ - size_type - size() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_finish - this->_M_impl._M_start; } - - /** Returns the size() of the largest possible %deque. */ - size_type - max_size() const _GLIBCXX_NOEXCEPT - { return _S_max_size(_M_get_Tp_allocator()); } - -#if __cplusplus >= 201103L - /** - * @brief Resizes the %deque to the specified number of elements. - * @param __new_size Number of elements the %deque should contain. - * - * This function will %resize the %deque to the specified - * number of elements. If the number is smaller than the - * %deque's current size the %deque is truncated, otherwise - * default constructed elements are appended. - */ - void - resize(size_type __new_size) - { - const size_type __len = size(); - if (__new_size > __len) - _M_default_append(__new_size - __len); - else if (__new_size < __len) - _M_erase_at_end(this->_M_impl._M_start - + difference_type(__new_size)); - } - - /** - * @brief Resizes the %deque to the specified number of elements. - * @param __new_size Number of elements the %deque should contain. - * @param __x Data with which new elements should be populated. - * - * This function will %resize the %deque to the specified - * number of elements. If the number is smaller than the - * %deque's current size the %deque is truncated, otherwise the - * %deque is extended and new elements are populated with given - * data. - */ - void - resize(size_type __new_size, const value_type& __x) -#else - /** - * @brief Resizes the %deque to the specified number of elements. - * @param __new_size Number of elements the %deque should contain. - * @param __x Data with which new elements should be populated. - * - * This function will %resize the %deque to the specified - * number of elements. If the number is smaller than the - * %deque's current size the %deque is truncated, otherwise the - * %deque is extended and new elements are populated with given - * data. - */ - void - resize(size_type __new_size, value_type __x = value_type()) -#endif - { - const size_type __len = size(); - if (__new_size > __len) - _M_fill_insert(this->_M_impl._M_finish, __new_size - __len, __x); - else if (__new_size < __len) - _M_erase_at_end(this->_M_impl._M_start - + difference_type(__new_size)); - } - -#if __cplusplus >= 201103L - /** A non-binding request to reduce memory use. */ - void - shrink_to_fit() noexcept - { _M_shrink_to_fit(); } -#endif - - /** - * Returns true if the %deque is empty. (Thus begin() would - * equal end().) - */ - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_finish == this->_M_impl._M_start; } - - // element access - /** - * @brief Subscript access to the data contained in the %deque. - * @param __n The index of the element for which data should be - * accessed. - * @return Read/write reference to data. - * - * This operator allows for easy, array-style, data access. - * Note that data access with this operator is unchecked and - * out_of_range lookups are not defined. (For checked lookups - * see at().) - */ - reference - operator[](size_type __n) _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_subscript(__n); - return this->_M_impl._M_start[difference_type(__n)]; - } - - /** - * @brief Subscript access to the data contained in the %deque. - * @param __n The index of the element for which data should be - * accessed. - * @return Read-only (constant) reference to data. - * - * This operator allows for easy, array-style, data access. - * Note that data access with this operator is unchecked and - * out_of_range lookups are not defined. (For checked lookups - * see at().) - */ - const_reference - operator[](size_type __n) const _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_subscript(__n); - return this->_M_impl._M_start[difference_type(__n)]; - } - - protected: - /// Safety check used only from at(). - void - _M_range_check(size_type __n) const - { - if (__n >= this->size()) - __throw_out_of_range_fmt(__N("deque::_M_range_check: __n " - "(which is %zu)>= this->size() " - "(which is %zu)"), - __n, this->size()); - } - - public: - /** - * @brief Provides access to the data contained in the %deque. - * @param __n The index of the element for which data should be - * accessed. - * @return Read/write reference to data. - * @throw std::out_of_range If @a __n is an invalid index. - * - * This function provides for safer data access. The parameter - * is first checked that it is in the range of the deque. The - * function throws out_of_range if the check fails. - */ - reference - at(size_type __n) - { - _M_range_check(__n); - return (*this)[__n]; - } - - /** - * @brief Provides access to the data contained in the %deque. - * @param __n The index of the element for which data should be - * accessed. - * @return Read-only (constant) reference to data. - * @throw std::out_of_range If @a __n is an invalid index. - * - * This function provides for safer data access. The parameter is first - * checked that it is in the range of the deque. The function throws - * out_of_range if the check fails. - */ - const_reference - at(size_type __n) const - { - _M_range_check(__n); - return (*this)[__n]; - } - - /** - * Returns a read/write reference to the data at the first - * element of the %deque. - */ - reference - front() _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - return *begin(); - } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %deque. - */ - const_reference - front() const _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - return *begin(); - } - - /** - * Returns a read/write reference to the data at the last element of the - * %deque. - */ - reference - back() _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - iterator __tmp = end(); - --__tmp; - return *__tmp; - } - - /** - * Returns a read-only (constant) reference to the data at the last - * element of the %deque. - */ - const_reference - back() const _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - const_iterator __tmp = end(); - --__tmp; - return *__tmp; - } - - // [23.2.1.2] modifiers - /** - * @brief Add data to the front of the %deque. - * @param __x Data to be added. - * - * This is a typical stack operation. The function creates an - * element at the front of the %deque and assigns the given - * data to it. Due to the nature of a %deque this operation - * can be done in constant time. - */ - void - push_front(const value_type& __x) - { - if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) - { - _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_start._M_cur - 1, - __x); - --this->_M_impl._M_start._M_cur; - } - else - _M_push_front_aux(__x); - } - -#if __cplusplus >= 201103L - void - push_front(value_type&& __x) - { emplace_front(std::move(__x)); } - - template -#if __cplusplus > 201402L - reference -#else - void -#endif - emplace_front(_Args&&... __args); -#endif - - /** - * @brief Add data to the end of the %deque. - * @param __x Data to be added. - * - * This is a typical stack operation. The function creates an - * element at the end of the %deque and assigns the given data - * to it. Due to the nature of a %deque this operation can be - * done in constant time. - */ - void - push_back(const value_type& __x) - { - if (this->_M_impl._M_finish._M_cur - != this->_M_impl._M_finish._M_last - 1) - { - _Alloc_traits::construct(this->_M_impl, - this->_M_impl._M_finish._M_cur, __x); - ++this->_M_impl._M_finish._M_cur; - } - else - _M_push_back_aux(__x); - } - -#if __cplusplus >= 201103L - void - push_back(value_type&& __x) - { emplace_back(std::move(__x)); } - - template -#if __cplusplus > 201402L - reference -#else - void -#endif - emplace_back(_Args&&... __args); -#endif - - /** - * @brief Removes first element. - * - * This is a typical stack operation. It shrinks the %deque by one. - * - * Note that no data is returned, and if the first element's data is - * needed, it should be retrieved before pop_front() is called. - */ - void - pop_front() _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - if (this->_M_impl._M_start._M_cur - != this->_M_impl._M_start._M_last - 1) - { - _Alloc_traits::destroy(_M_get_Tp_allocator(), - this->_M_impl._M_start._M_cur); - ++this->_M_impl._M_start._M_cur; - } - else - _M_pop_front_aux(); - } - - /** - * @brief Removes last element. - * - * This is a typical stack operation. It shrinks the %deque by one. - * - * Note that no data is returned, and if the last element's data is - * needed, it should be retrieved before pop_back() is called. - */ - void - pop_back() _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - if (this->_M_impl._M_finish._M_cur - != this->_M_impl._M_finish._M_first) - { - --this->_M_impl._M_finish._M_cur; - _Alloc_traits::destroy(_M_get_Tp_allocator(), - this->_M_impl._M_finish._M_cur); - } - else - _M_pop_back_aux(); - } - -#if __cplusplus >= 201103L - /** - * @brief Inserts an object in %deque before specified iterator. - * @param __position A const_iterator into the %deque. - * @param __args Arguments. - * @return An iterator that points to the inserted data. - * - * This function will insert an object of type T constructed - * with T(std::forward(args)...) before the specified location. - */ - template - iterator - emplace(const_iterator __position, _Args&&... __args); - - /** - * @brief Inserts given value into %deque before specified iterator. - * @param __position A const_iterator into the %deque. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before the - * specified location. - */ - iterator - insert(const_iterator __position, const value_type& __x); -#else - /** - * @brief Inserts given value into %deque before specified iterator. - * @param __position An iterator into the %deque. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before the - * specified location. - */ - iterator - insert(iterator __position, const value_type& __x); -#endif - -#if __cplusplus >= 201103L - /** - * @brief Inserts given rvalue into %deque before specified iterator. - * @param __position A const_iterator into the %deque. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given rvalue before the - * specified location. - */ - iterator - insert(const_iterator __position, value_type&& __x) - { return emplace(__position, std::move(__x)); } - - /** - * @brief Inserts an initializer list into the %deque. - * @param __p An iterator into the %deque. - * @param __l An initializer_list. - * @return An iterator that points to the inserted data. - * - * This function will insert copies of the data in the - * initializer_list @a __l into the %deque before the location - * specified by @a __p. This is known as list insert. - */ - iterator - insert(const_iterator __p, initializer_list __l) - { - auto __offset = __p - cbegin(); - _M_range_insert_aux(__p._M_const_cast(), __l.begin(), __l.end(), - std::random_access_iterator_tag()); - return begin() + __offset; - } - - /** - * @brief Inserts a number of copies of given data into the %deque. - * @param __position A const_iterator into the %deque. - * @param __n Number of elements to be inserted. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a specified number of copies of the given - * data before the location specified by @a __position. - */ - iterator - insert(const_iterator __position, size_type __n, const value_type& __x) - { - difference_type __offset = __position - cbegin(); - _M_fill_insert(__position._M_const_cast(), __n, __x); - return begin() + __offset; - } -#else - /** - * @brief Inserts a number of copies of given data into the %deque. - * @param __position An iterator into the %deque. - * @param __n Number of elements to be inserted. - * @param __x Data to be inserted. - * - * This function will insert a specified number of copies of the given - * data before the location specified by @a __position. - */ - void - insert(iterator __position, size_type __n, const value_type& __x) - { _M_fill_insert(__position, __n, __x); } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Inserts a range into the %deque. - * @param __position A const_iterator into the %deque. - * @param __first An input iterator. - * @param __last An input iterator. - * @return An iterator that points to the inserted data. - * - * This function will insert copies of the data in the range - * [__first,__last) into the %deque before the location specified - * by @a __position. This is known as range insert. - */ - template> - iterator - insert(const_iterator __position, _InputIterator __first, - _InputIterator __last) - { - difference_type __offset = __position - cbegin(); - _M_range_insert_aux(__position._M_const_cast(), __first, __last, - std::__iterator_category(__first)); - return begin() + __offset; - } -#else - /** - * @brief Inserts a range into the %deque. - * @param __position An iterator into the %deque. - * @param __first An input iterator. - * @param __last An input iterator. - * - * This function will insert copies of the data in the range - * [__first,__last) into the %deque before the location specified - * by @a __position. This is known as range insert. - */ - template - void - insert(iterator __position, _InputIterator __first, - _InputIterator __last) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_insert_dispatch(__position, __first, __last, _Integral()); - } -#endif - - /** - * @brief Remove element at given position. - * @param __position Iterator pointing to element to be erased. - * @return An iterator pointing to the next element (or end()). - * - * This function will erase the element at the given position and thus - * shorten the %deque by one. - * - * The user is cautioned that - * this function only erases the element, and that if the element is - * itself a pointer, the pointed-to memory is not touched in any way. - * Managing the pointer is the user's responsibility. - */ - iterator -#if __cplusplus >= 201103L - erase(const_iterator __position) -#else - erase(iterator __position) -#endif - { return _M_erase(__position._M_const_cast()); } - - /** - * @brief Remove a range of elements. - * @param __first Iterator pointing to the first element to be erased. - * @param __last Iterator pointing to one past the last element to be - * erased. - * @return An iterator pointing to the element pointed to by @a last - * prior to erasing (or end()). - * - * This function will erase the elements in the range - * [__first,__last) and shorten the %deque accordingly. - * - * The user is cautioned that - * this function only erases the elements, and that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibility. - */ - iterator -#if __cplusplus >= 201103L - erase(const_iterator __first, const_iterator __last) -#else - erase(iterator __first, iterator __last) -#endif - { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } - - /** - * @brief Swaps data with another %deque. - * @param __x A %deque of the same element and allocator types. - * - * This exchanges the elements between two deques in constant time. - * (Four pointers, so it should be quite fast.) - * Note that the global std::swap() function is specialized such that - * std::swap(d1,d2) will feed to this function. - * - * Whether the allocators are swapped depends on the allocator traits. - */ - void - swap(deque& __x) _GLIBCXX_NOEXCEPT - { -#if __cplusplus >= 201103L - __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value - || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()); -#endif - _M_impl._M_swap_data(__x._M_impl); - _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), - __x._M_get_Tp_allocator()); - } - - /** - * Erases all the elements. Note that this function only erases the - * elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer is - * the user's responsibility. - */ - void - clear() _GLIBCXX_NOEXCEPT - { _M_erase_at_end(begin()); } - - protected: - // Internal constructor functions follow. - -#if __cplusplus < 201103L - // called by the range constructor to implement [23.1.1]/9 - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) - { - _M_initialize_map(_S_check_init_len(static_cast(__n), - _M_get_Tp_allocator())); - _M_fill_initialize(__x); - } - - // called by the range constructor to implement [23.1.1]/9 - template - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { - _M_range_initialize(__first, __last, - std::__iterator_category(__first)); - } -#endif - - static size_t - _S_check_init_len(size_t __n, const allocator_type& __a) - { - if (__n > _S_max_size(__a)) - __throw_length_error( - __N("cannot create std::deque larger than max_size()")); - return __n; - } - - static size_type - _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT - { - const size_t __diffmax = __gnu_cxx::__numeric_traits::__max; - const size_t __allocmax = _Alloc_traits::max_size(__a); - return (std::min)(__diffmax, __allocmax); - } - - // called by the second initialize_dispatch above - //@{ - /** - * @brief Fills the deque with whatever is in [first,last). - * @param __first An input iterator. - * @param __last An input iterator. - * @return Nothing. - * - * If the iterators are actually forward iterators (or better), then the - * memory layout can be done all at once. Else we move forward using - * push_back on each value from the iterator. - */ - template - void - _M_range_initialize(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag); - - // called by the second initialize_dispatch above - template - void - _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag); - //@} - - /** - * @brief Fills the %deque with copies of value. - * @param __value Initial value. - * @return Nothing. - * @pre _M_start and _M_finish have already been initialized, - * but none of the %deque's elements have yet been constructed. - * - * This function is called only when the user provides an explicit size - * (with or without an explicit exemplar value). - */ - void - _M_fill_initialize(const value_type& __value); - -#if __cplusplus >= 201103L - // called by deque(n). - void - _M_default_initialize(); -#endif - - // Internal assign functions follow. The *_aux functions do the actual - // assignment work for the range versions. - -#if __cplusplus < 201103L - // called by the range assign to implement [23.1.1]/9 - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { _M_fill_assign(__n, __val); } - - // called by the range assign to implement [23.1.1]/9 - template - void - _M_assign_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } -#endif - - // called by the second assign_dispatch above - template - void - _M_assign_aux(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag); - - // called by the second assign_dispatch above - template - void - _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) - { - const size_type __len = std::distance(__first, __last); - if (__len > size()) - { - _ForwardIterator __mid = __first; - std::advance(__mid, size()); - std::copy(__first, __mid, begin()); - _M_range_insert_aux(end(), __mid, __last, - std::__iterator_category(__first)); - } - else - _M_erase_at_end(std::copy(__first, __last, begin())); - } - - // Called by assign(n,t), and the range assign when it turns out - // to be the same thing. - void - _M_fill_assign(size_type __n, const value_type& __val) - { - if (__n > size()) - { - std::fill(begin(), end(), __val); - _M_fill_insert(end(), __n - size(), __val); - } - else - { - _M_erase_at_end(begin() + difference_type(__n)); - std::fill(begin(), end(), __val); - } - } - - //@{ - /// Helper functions for push_* and pop_*. -#if __cplusplus < 201103L - void _M_push_back_aux(const value_type&); - - void _M_push_front_aux(const value_type&); -#else - template - void _M_push_back_aux(_Args&&... __args); - - template - void _M_push_front_aux(_Args&&... __args); -#endif - - void _M_pop_back_aux(); - - void _M_pop_front_aux(); - //@} - - // Internal insert functions follow. The *_aux functions do the actual - // insertion work when all shortcuts fail. - -#if __cplusplus < 201103L - // called by the range insert to implement [23.1.1]/9 - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_insert_dispatch(iterator __pos, - _Integer __n, _Integer __x, __true_type) - { _M_fill_insert(__pos, __n, __x); } - - // called by the range insert to implement [23.1.1]/9 - template - void - _M_insert_dispatch(iterator __pos, - _InputIterator __first, _InputIterator __last, - __false_type) - { - _M_range_insert_aux(__pos, __first, __last, - std::__iterator_category(__first)); - } -#endif - - // called by the second insert_dispatch above - template - void - _M_range_insert_aux(iterator __pos, _InputIterator __first, - _InputIterator __last, std::input_iterator_tag); - - // called by the second insert_dispatch above - template - void - _M_range_insert_aux(iterator __pos, _ForwardIterator __first, - _ForwardIterator __last, std::forward_iterator_tag); - - // Called by insert(p,n,x), and the range insert when it turns out to be - // the same thing. Can use fill functions in optimal situations, - // otherwise passes off to insert_aux(p,n,x). - void - _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); - - // called by insert(p,x) -#if __cplusplus < 201103L - iterator - _M_insert_aux(iterator __pos, const value_type& __x); -#else - template - iterator - _M_insert_aux(iterator __pos, _Args&&... __args); -#endif - - // called by insert(p,n,x) via fill_insert - void - _M_insert_aux(iterator __pos, size_type __n, const value_type& __x); - - // called by range_insert_aux for forward iterators - template - void - _M_insert_aux(iterator __pos, - _ForwardIterator __first, _ForwardIterator __last, - size_type __n); - - - // Internal erase functions follow. - - void - _M_destroy_data_aux(iterator __first, iterator __last); - - // Called by ~deque(). - // NB: Doesn't deallocate the nodes. - template - void - _M_destroy_data(iterator __first, iterator __last, const _Alloc1&) - { _M_destroy_data_aux(__first, __last); } - - void - _M_destroy_data(iterator __first, iterator __last, - const std::allocator<_Tp>&) - { - if (!__has_trivial_destructor(value_type)) - _M_destroy_data_aux(__first, __last); - } - - // Called by erase(q1, q2). - void - _M_erase_at_begin(iterator __pos) - { - _M_destroy_data(begin(), __pos, _M_get_Tp_allocator()); - _M_destroy_nodes(this->_M_impl._M_start._M_node, __pos._M_node); - this->_M_impl._M_start = __pos; - } - - // Called by erase(q1, q2), resize(), clear(), _M_assign_aux, - // _M_fill_assign, operator=. - void - _M_erase_at_end(iterator __pos) - { - _M_destroy_data(__pos, end(), _M_get_Tp_allocator()); - _M_destroy_nodes(__pos._M_node + 1, - this->_M_impl._M_finish._M_node + 1); - this->_M_impl._M_finish = __pos; - } - - iterator - _M_erase(iterator __pos); - - iterator - _M_erase(iterator __first, iterator __last); - -#if __cplusplus >= 201103L - // Called by resize(sz). - void - _M_default_append(size_type __n); - - bool - _M_shrink_to_fit(); -#endif - - //@{ - /// Memory-handling helpers for the previous internal insert functions. - iterator - _M_reserve_elements_at_front(size_type __n) - { - const size_type __vacancies = this->_M_impl._M_start._M_cur - - this->_M_impl._M_start._M_first; - if (__n > __vacancies) - _M_new_elements_at_front(__n - __vacancies); - return this->_M_impl._M_start - difference_type(__n); - } - - iterator - _M_reserve_elements_at_back(size_type __n) - { - const size_type __vacancies = (this->_M_impl._M_finish._M_last - - this->_M_impl._M_finish._M_cur) - 1; - if (__n > __vacancies) - _M_new_elements_at_back(__n - __vacancies); - return this->_M_impl._M_finish + difference_type(__n); - } - - void - _M_new_elements_at_front(size_type __new_elements); - - void - _M_new_elements_at_back(size_type __new_elements); - //@} - - - //@{ - /** - * @brief Memory-handling helpers for the major %map. - * - * Makes sure the _M_map has space for new nodes. Does not - * actually add the nodes. Can invalidate _M_map pointers. - * (And consequently, %deque iterators.) - */ - void - _M_reserve_map_at_back(size_type __nodes_to_add = 1) - { - if (__nodes_to_add + 1 > this->_M_impl._M_map_size - - (this->_M_impl._M_finish._M_node - this->_M_impl._M_map)) - _M_reallocate_map(__nodes_to_add, false); - } - - void - _M_reserve_map_at_front(size_type __nodes_to_add = 1) - { - if (__nodes_to_add > size_type(this->_M_impl._M_start._M_node - - this->_M_impl._M_map)) - _M_reallocate_map(__nodes_to_add, true); - } - - void - _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front); - //@} - -#if __cplusplus >= 201103L - // Constant-time, nothrow move assignment when source object's memory - // can be moved because the allocators are equal. - void - _M_move_assign1(deque&& __x, /* always equal: */ true_type) noexcept - { - this->_M_impl._M_swap_data(__x._M_impl); - __x.clear(); - std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); - } - - // When the allocators are not equal the operation could throw, because - // we might need to allocate a new map for __x after moving from it - // or we might need to allocate new elements for *this. - void - _M_move_assign1(deque&& __x, /* always equal: */ false_type) - { - constexpr bool __move_storage = - _Alloc_traits::_S_propagate_on_move_assign(); - _M_move_assign2(std::move(__x), __bool_constant<__move_storage>()); - } - - // Destroy all elements and deallocate all memory, then replace - // with elements created from __args. - template - void - _M_replace_map(_Args&&... __args) - { - // Create new data first, so if allocation fails there are no effects. - deque __newobj(std::forward<_Args>(__args)...); - // Free existing storage using existing allocator. - clear(); - _M_deallocate_node(*begin()._M_node); // one node left after clear() - _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); - this->_M_impl._M_map = nullptr; - this->_M_impl._M_map_size = 0; - // Take ownership of replacement memory. - this->_M_impl._M_swap_data(__newobj._M_impl); - } - - // Do move assignment when the allocator propagates. - void - _M_move_assign2(deque&& __x, /* propagate: */ true_type) - { - // Make a copy of the original allocator state. - auto __alloc = __x._M_get_Tp_allocator(); - // The allocator propagates so storage can be moved from __x, - // leaving __x in a valid empty state with a moved-from allocator. - _M_replace_map(std::move(__x)); - // Move the corresponding allocator state too. - _M_get_Tp_allocator() = std::move(__alloc); - } - - // Do move assignment when it may not be possible to move source - // object's memory, resulting in a linear-time operation. - void - _M_move_assign2(deque&& __x, /* propagate: */ false_type) - { - if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator()) - { - // The allocators are equal so storage can be moved from __x, - // leaving __x in a valid empty state with its current allocator. - _M_replace_map(std::move(__x), __x.get_allocator()); - } - else - { - // The rvalue's allocator cannot be moved and is not equal, - // so we need to individually move each element. - _M_assign_aux(std::make_move_iterator(__x.begin()), - std::make_move_iterator(__x.end()), - std::random_access_iterator_tag()); - __x.clear(); - } - } -#endif - }; - -#if __cpp_deduction_guides >= 201606 - template::value_type, - typename _Allocator = allocator<_ValT>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireAllocator<_Allocator>> - deque(_InputIterator, _InputIterator, _Allocator = _Allocator()) - -> deque<_ValT, _Allocator>; -#endif - - /** - * @brief Deque equality comparison. - * @param __x A %deque. - * @param __y A %deque of the same type as @a __x. - * @return True iff the size and elements of the deques are equal. - * - * This is an equivalence relation. It is linear in the size of the - * deques. Deques are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. - */ - template - inline bool - operator==(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) - { return __x.size() == __y.size() - && std::equal(__x.begin(), __x.end(), __y.begin()); } - -#if __cpp_lib_three_way_comparison - /** - * @brief Deque ordering relation. - * @param __x A `deque`. - * @param __y A `deque` of the same type as `__x`. - * @return A value indicating whether `__x` is less than, equal to, - * greater than, or incomparable with `__y`. - * - * See `std::lexicographical_compare_three_way()` for how the determination - * is made. This operator is used to synthesize relational operators like - * `<` and `>=` etc. - */ - template - inline __detail::__synth3way_t<_Tp> - operator<=>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) - { - return std::lexicographical_compare_three_way(__x.begin(), __x.end(), - __y.begin(), __y.end(), - __detail::__synth3way); - } -#else - /** - * @brief Deque ordering relation. - * @param __x A %deque. - * @param __y A %deque of the same type as @a __x. - * @return True iff @a x is lexicographically less than @a __y. - * - * This is a total ordering relation. It is linear in the size of the - * deques. The elements must be comparable with @c <. - * - * See std::lexicographical_compare() for how the determination is made. - */ - template - inline bool - operator<(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) - { return std::lexicographical_compare(__x.begin(), __x.end(), - __y.begin(), __y.end()); } - - /// Based on operator== - template - inline bool - operator!=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) - { return !(__x == __y); } - - /// Based on operator< - template - inline bool - operator>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) - { return __y < __x; } - - /// Based on operator< - template - inline bool - operator<=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) - { return !(__y < __x); } - - /// Based on operator< - template - inline bool - operator>=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) - { return !(__x < __y); } -#endif // three-way comparison - - /// See std::deque::swap(). - template - inline void - swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) - _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -#undef _GLIBCXX_DEQUE_BUF_SIZE - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if __cplusplus >= 201103L - // std::allocator is safe, but it is not the only allocator - // for which this is valid. - template - struct __is_bitwise_relocatable<_GLIBCXX_STD_C::deque<_Tp>> - : true_type { }; -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_DEQUE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_function.h b/resources/sources/avr-libstdcpp/include/bits/stl_function.h deleted file mode 100644 index 77f8ccb05..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_function.h +++ /dev/null @@ -1,1395 +0,0 @@ -// Functor implementations -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996-1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_function.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{functional} - */ - -#ifndef _STL_FUNCTION_H -#define _STL_FUNCTION_H 1 - -#if __cplusplus > 201103L -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // 20.3.1 base classes - /** @defgroup functors Function Objects - * @ingroup utilities - * - * Function objects, or @e functors, are objects with an @c operator() - * defined and accessible. They can be passed as arguments to algorithm - * templates and used in place of a function pointer. Not only is the - * resulting expressiveness of the library increased, but the generated - * code can be more efficient than what you might write by hand. When we - * refer to @a functors, then, generally we include function pointers in - * the description as well. - * - * Often, functors are only created as temporaries passed to algorithm - * calls, rather than being created as named variables. - * - * Two examples taken from the standard itself follow. To perform a - * by-element addition of two vectors @c a and @c b containing @c double, - * and put the result in @c a, use - * \code - * transform (a.begin(), a.end(), b.begin(), a.begin(), plus()); - * \endcode - * To negate every element in @c a, use - * \code - * transform(a.begin(), a.end(), a.begin(), negate()); - * \endcode - * The addition and negation functions will be inlined directly. - * - * The standard functors are derived from structs named @c unary_function - * and @c binary_function. These two classes contain nothing but typedefs, - * to aid in generic (template) programming. If you write your own - * functors, you might consider doing the same. - * - * @{ - */ - /** - * This is one of the @link functors functor base classes@endlink. - */ - template - struct unary_function - { - /// @c argument_type is the type of the argument - typedef _Arg argument_type; - - /// @c result_type is the return type - typedef _Result result_type; - }; - - /** - * This is one of the @link functors functor base classes@endlink. - */ - template - struct binary_function - { - /// @c first_argument_type is the type of the first argument - typedef _Arg1 first_argument_type; - - /// @c second_argument_type is the type of the second argument - typedef _Arg2 second_argument_type; - - /// @c result_type is the return type - typedef _Result result_type; - }; - /** @} */ - - // 20.3.2 arithmetic - /** @defgroup arithmetic_functors Arithmetic Classes - * @ingroup functors - * - * Because basic math often needs to be done during an algorithm, - * the library provides functors for those operations. See the - * documentation for @link functors the base classes@endlink - * for examples of their use. - * - * @{ - */ - -#if __cplusplus > 201103L - struct __is_transparent; // undefined - - template - struct plus; - - template - struct minus; - - template - struct multiplies; - - template - struct divides; - - template - struct modulus; - - template - struct negate; -#endif - - /// One of the @link arithmetic_functors math functors@endlink. - template - struct plus : public binary_function<_Tp, _Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x, const _Tp& __y) const - { return __x + __y; } - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template - struct minus : public binary_function<_Tp, _Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x, const _Tp& __y) const - { return __x - __y; } - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template - struct multiplies : public binary_function<_Tp, _Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x, const _Tp& __y) const - { return __x * __y; } - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template - struct divides : public binary_function<_Tp, _Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x, const _Tp& __y) const - { return __x / __y; } - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template - struct modulus : public binary_function<_Tp, _Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x, const _Tp& __y) const - { return __x % __y; } - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template - struct negate : public unary_function<_Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x) const - { return -__x; } - }; - -#if __cplusplus > 201103L - -#define __cpp_lib_transparent_operators 201510 - - template<> - struct plus - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) + std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) + std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) + std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template<> - struct minus - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) - std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) - std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) - std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template<> - struct multiplies - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) * std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) * std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) * std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template<> - struct divides - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) / std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) / std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) / std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template<> - struct modulus - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) % std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) % std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) % std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link arithmetic_functors math functors@endlink. - template<> - struct negate - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t) const - noexcept(noexcept(-std::forward<_Tp>(__t))) - -> decltype(-std::forward<_Tp>(__t)) - { return -std::forward<_Tp>(__t); } - - typedef __is_transparent is_transparent; - }; -#endif - /** @} */ - - // 20.3.3 comparisons - /** @defgroup comparison_functors Comparison Classes - * @ingroup functors - * - * The library provides six wrapper functors for all the basic comparisons - * in C++, like @c <. - * - * @{ - */ -#if __cplusplus > 201103L - template - struct equal_to; - - template - struct not_equal_to; - - template - struct greater; - - template - struct less; - - template - struct greater_equal; - - template - struct less_equal; -#endif - - /// One of the @link comparison_functors comparison functors@endlink. - template - struct equal_to : public binary_function<_Tp, _Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x, const _Tp& __y) const - { return __x == __y; } - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template - struct not_equal_to : public binary_function<_Tp, _Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x, const _Tp& __y) const - { return __x != __y; } - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template - struct greater : public binary_function<_Tp, _Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x, const _Tp& __y) const - { return __x > __y; } - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template - struct less : public binary_function<_Tp, _Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x, const _Tp& __y) const - { return __x < __y; } - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template - struct greater_equal : public binary_function<_Tp, _Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x, const _Tp& __y) const - { return __x >= __y; } - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template - struct less_equal : public binary_function<_Tp, _Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x, const _Tp& __y) const - { return __x <= __y; } - }; - - // Partial specialization of std::greater for pointers. - template - struct greater<_Tp*> : public binary_function<_Tp*, _Tp*, bool> - { - _GLIBCXX14_CONSTEXPR bool - operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW - { -#if __cplusplus >= 201402L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - if (__builtin_is_constant_evaluated()) -#else - if (__builtin_constant_p(__x > __y)) -#endif - return __x > __y; -#endif - return (__UINTPTR_TYPE__)__x > (__UINTPTR_TYPE__)__y; - } - }; - - // Partial specialization of std::less for pointers. - template - struct less<_Tp*> : public binary_function<_Tp*, _Tp*, bool> - { - _GLIBCXX14_CONSTEXPR bool - operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW - { -#if __cplusplus >= 201402L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - if (__builtin_is_constant_evaluated()) -#else - if (__builtin_constant_p(__x < __y)) -#endif - return __x < __y; -#endif - return (__UINTPTR_TYPE__)__x < (__UINTPTR_TYPE__)__y; - } - }; - - // Partial specialization of std::greater_equal for pointers. - template - struct greater_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool> - { - _GLIBCXX14_CONSTEXPR bool - operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW - { -#if __cplusplus >= 201402L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - if (__builtin_is_constant_evaluated()) -#else - if (__builtin_constant_p(__x >= __y)) -#endif - return __x >= __y; -#endif - return (__UINTPTR_TYPE__)__x >= (__UINTPTR_TYPE__)__y; - } - }; - - // Partial specialization of std::less_equal for pointers. - template - struct less_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool> - { - _GLIBCXX14_CONSTEXPR bool - operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW - { -#if __cplusplus >= 201402L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - if (__builtin_is_constant_evaluated()) -#else - if (__builtin_constant_p(__x <= __y)) -#endif - return __x <= __y; -#endif - return (__UINTPTR_TYPE__)__x <= (__UINTPTR_TYPE__)__y; - } - }; - -#if __cplusplus >= 201402L - /// One of the @link comparison_functors comparison functors@endlink. - template<> - struct equal_to - { - template - constexpr auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) == std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) == std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template<> - struct not_equal_to - { - template - constexpr auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) != std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) != std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) != std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template<> - struct greater - { - template - constexpr auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) > std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) > std::forward<_Up>(__u)) - { - return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), - __ptr_cmp<_Tp, _Up>{}); - } - - template - constexpr bool - operator()(_Tp* __t, _Up* __u) const noexcept - { return greater>{}(__t, __u); } - - typedef __is_transparent is_transparent; - - private: - template - static constexpr decltype(auto) - _S_cmp(_Tp&& __t, _Up&& __u, false_type) - { return std::forward<_Tp>(__t) > std::forward<_Up>(__u); } - - template - static constexpr bool - _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept - { - return greater{}( - static_cast(std::forward<_Tp>(__t)), - static_cast(std::forward<_Up>(__u))); - } - - // True if there is no viable operator> member function. - template - struct __not_overloaded2 : true_type { }; - - // False if we can call T.operator>(U) - template - struct __not_overloaded2<_Tp, _Up, __void_t< - decltype(std::declval<_Tp>().operator>(std::declval<_Up>()))>> - : false_type { }; - - // True if there is no overloaded operator> for these operands. - template - struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; - - // False if we can call operator>(T,U) - template - struct __not_overloaded<_Tp, _Up, __void_t< - decltype(operator>(std::declval<_Tp>(), std::declval<_Up>()))>> - : false_type { }; - - template - using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, - is_convertible<_Tp, const volatile void*>, - is_convertible<_Up, const volatile void*>>; - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template<> - struct less - { - template - constexpr auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) < std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) < std::forward<_Up>(__u)) - { - return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), - __ptr_cmp<_Tp, _Up>{}); - } - - template - constexpr bool - operator()(_Tp* __t, _Up* __u) const noexcept - { return less>{}(__t, __u); } - - typedef __is_transparent is_transparent; - - private: - template - static constexpr decltype(auto) - _S_cmp(_Tp&& __t, _Up&& __u, false_type) - { return std::forward<_Tp>(__t) < std::forward<_Up>(__u); } - - template - static constexpr bool - _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept - { - return less{}( - static_cast(std::forward<_Tp>(__t)), - static_cast(std::forward<_Up>(__u))); - } - - // True if there is no viable operator< member function. - template - struct __not_overloaded2 : true_type { }; - - // False if we can call T.operator<(U) - template - struct __not_overloaded2<_Tp, _Up, __void_t< - decltype(std::declval<_Tp>().operator<(std::declval<_Up>()))>> - : false_type { }; - - // True if there is no overloaded operator< for these operands. - template - struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; - - // False if we can call operator<(T,U) - template - struct __not_overloaded<_Tp, _Up, __void_t< - decltype(operator<(std::declval<_Tp>(), std::declval<_Up>()))>> - : false_type { }; - - template - using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, - is_convertible<_Tp, const volatile void*>, - is_convertible<_Up, const volatile void*>>; - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template<> - struct greater_equal - { - template - constexpr auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) >= std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) >= std::forward<_Up>(__u)) - { - return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), - __ptr_cmp<_Tp, _Up>{}); - } - - template - constexpr bool - operator()(_Tp* __t, _Up* __u) const noexcept - { return greater_equal>{}(__t, __u); } - - typedef __is_transparent is_transparent; - - private: - template - static constexpr decltype(auto) - _S_cmp(_Tp&& __t, _Up&& __u, false_type) - { return std::forward<_Tp>(__t) >= std::forward<_Up>(__u); } - - template - static constexpr bool - _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept - { - return greater_equal{}( - static_cast(std::forward<_Tp>(__t)), - static_cast(std::forward<_Up>(__u))); - } - - // True if there is no viable operator>= member function. - template - struct __not_overloaded2 : true_type { }; - - // False if we can call T.operator>=(U) - template - struct __not_overloaded2<_Tp, _Up, __void_t< - decltype(std::declval<_Tp>().operator>=(std::declval<_Up>()))>> - : false_type { }; - - // True if there is no overloaded operator>= for these operands. - template - struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; - - // False if we can call operator>=(T,U) - template - struct __not_overloaded<_Tp, _Up, __void_t< - decltype(operator>=(std::declval<_Tp>(), std::declval<_Up>()))>> - : false_type { }; - - template - using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, - is_convertible<_Tp, const volatile void*>, - is_convertible<_Up, const volatile void*>>; - }; - - /// One of the @link comparison_functors comparison functors@endlink. - template<> - struct less_equal - { - template - constexpr auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) <= std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) <= std::forward<_Up>(__u)) - { - return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), - __ptr_cmp<_Tp, _Up>{}); - } - - template - constexpr bool - operator()(_Tp* __t, _Up* __u) const noexcept - { return less_equal>{}(__t, __u); } - - typedef __is_transparent is_transparent; - - private: - template - static constexpr decltype(auto) - _S_cmp(_Tp&& __t, _Up&& __u, false_type) - { return std::forward<_Tp>(__t) <= std::forward<_Up>(__u); } - - template - static constexpr bool - _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept - { - return less_equal{}( - static_cast(std::forward<_Tp>(__t)), - static_cast(std::forward<_Up>(__u))); - } - - // True if there is no viable operator<= member function. - template - struct __not_overloaded2 : true_type { }; - - // False if we can call T.operator<=(U) - template - struct __not_overloaded2<_Tp, _Up, __void_t< - decltype(std::declval<_Tp>().operator<=(std::declval<_Up>()))>> - : false_type { }; - - // True if there is no overloaded operator<= for these operands. - template - struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; - - // False if we can call operator<=(T,U) - template - struct __not_overloaded<_Tp, _Up, __void_t< - decltype(operator<=(std::declval<_Tp>(), std::declval<_Up>()))>> - : false_type { }; - - template - using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, - is_convertible<_Tp, const volatile void*>, - is_convertible<_Up, const volatile void*>>; - }; -#endif // C++14 - /** @} */ - - // 20.3.4 logical operations - /** @defgroup logical_functors Boolean Operations Classes - * @ingroup functors - * - * Here are wrapper functors for Boolean operations: @c &&, @c ||, - * and @c !. - * - * @{ - */ -#if __cplusplus > 201103L - template - struct logical_and; - - template - struct logical_or; - - template - struct logical_not; -#endif - - /// One of the @link logical_functors Boolean operations functors@endlink. - template - struct logical_and : public binary_function<_Tp, _Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x, const _Tp& __y) const - { return __x && __y; } - }; - - /// One of the @link logical_functors Boolean operations functors@endlink. - template - struct logical_or : public binary_function<_Tp, _Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x, const _Tp& __y) const - { return __x || __y; } - }; - - /// One of the @link logical_functors Boolean operations functors@endlink. - template - struct logical_not : public unary_function<_Tp, bool> - { - _GLIBCXX14_CONSTEXPR - bool - operator()(const _Tp& __x) const - { return !__x; } - }; - -#if __cplusplus > 201103L - /// One of the @link logical_functors Boolean operations functors@endlink. - template<> - struct logical_and - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) && std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) && std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) && std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link logical_functors Boolean operations functors@endlink. - template<> - struct logical_or - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) || std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) || std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) || std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - /// One of the @link logical_functors Boolean operations functors@endlink. - template<> - struct logical_not - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t) const - noexcept(noexcept(!std::forward<_Tp>(__t))) - -> decltype(!std::forward<_Tp>(__t)) - { return !std::forward<_Tp>(__t); } - - typedef __is_transparent is_transparent; - }; -#endif - /** @} */ - -#if __cplusplus > 201103L - template - struct bit_and; - - template - struct bit_or; - - template - struct bit_xor; - - template - struct bit_not; -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 660. Missing Bitwise Operations. - template - struct bit_and : public binary_function<_Tp, _Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x, const _Tp& __y) const - { return __x & __y; } - }; - - template - struct bit_or : public binary_function<_Tp, _Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x, const _Tp& __y) const - { return __x | __y; } - }; - - template - struct bit_xor : public binary_function<_Tp, _Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x, const _Tp& __y) const - { return __x ^ __y; } - }; - - template - struct bit_not : public unary_function<_Tp, _Tp> - { - _GLIBCXX14_CONSTEXPR - _Tp - operator()(const _Tp& __x) const - { return ~__x; } - }; - -#if __cplusplus > 201103L - template <> - struct bit_and - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) & std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) & std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) & std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - template <> - struct bit_or - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) | std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) | std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) | std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - template <> - struct bit_xor - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u))) - -> decltype(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u)) - { return std::forward<_Tp>(__t) ^ std::forward<_Up>(__u); } - - typedef __is_transparent is_transparent; - }; - - template <> - struct bit_not - { - template - _GLIBCXX14_CONSTEXPR - auto - operator()(_Tp&& __t) const - noexcept(noexcept(~std::forward<_Tp>(__t))) - -> decltype(~std::forward<_Tp>(__t)) - { return ~std::forward<_Tp>(__t); } - - typedef __is_transparent is_transparent; - }; -#endif - - // 20.3.5 negators - /** @defgroup negators Negators - * @ingroup functors - * - * The functions @c not1 and @c not2 each take a predicate functor - * and return an instance of @c unary_negate or - * @c binary_negate, respectively. These classes are functors whose - * @c operator() performs the stored predicate function and then returns - * the negation of the result. - * - * For example, given a vector of integers and a trivial predicate, - * \code - * struct IntGreaterThanThree - * : public std::unary_function - * { - * bool operator() (int x) { return x > 3; } - * }; - * - * std::find_if (v.begin(), v.end(), not1(IntGreaterThanThree())); - * \endcode - * The call to @c find_if will locate the first index (i) of @c v for which - * !(v[i] > 3) is true. - * - * The not1/unary_negate combination works on predicates taking a single - * argument. The not2/binary_negate combination works on predicates which - * take two arguments. - * - * @{ - */ - /// One of the @link negators negation functors@endlink. - template - class unary_negate - : public unary_function - { - protected: - _Predicate _M_pred; - - public: - _GLIBCXX14_CONSTEXPR - explicit - unary_negate(const _Predicate& __x) : _M_pred(__x) { } - - _GLIBCXX14_CONSTEXPR - bool - operator()(const typename _Predicate::argument_type& __x) const - { return !_M_pred(__x); } - }; - - /// One of the @link negators negation functors@endlink. - template - _GLIBCXX14_CONSTEXPR - inline unary_negate<_Predicate> - not1(const _Predicate& __pred) - { return unary_negate<_Predicate>(__pred); } - - /// One of the @link negators negation functors@endlink. - template - class binary_negate - : public binary_function - { - protected: - _Predicate _M_pred; - - public: - _GLIBCXX14_CONSTEXPR - explicit - binary_negate(const _Predicate& __x) : _M_pred(__x) { } - - _GLIBCXX14_CONSTEXPR - bool - operator()(const typename _Predicate::first_argument_type& __x, - const typename _Predicate::second_argument_type& __y) const - { return !_M_pred(__x, __y); } - }; - - /// One of the @link negators negation functors@endlink. - template - _GLIBCXX14_CONSTEXPR - inline binary_negate<_Predicate> - not2(const _Predicate& __pred) - { return binary_negate<_Predicate>(__pred); } - /** @} */ - - // 20.3.7 adaptors pointers functions - /** @defgroup pointer_adaptors Adaptors for pointers to functions - * @ingroup functors - * - * The advantage of function objects over pointers to functions is that - * the objects in the standard library declare nested typedefs describing - * their argument and result types with uniform names (e.g., @c result_type - * from the base classes @c unary_function and @c binary_function). - * Sometimes those typedefs are required, not just optional. - * - * Adaptors are provided to turn pointers to unary (single-argument) and - * binary (double-argument) functions into function objects. The - * long-winded functor @c pointer_to_unary_function is constructed with a - * function pointer @c f, and its @c operator() called with argument @c x - * returns @c f(x). The functor @c pointer_to_binary_function does the same - * thing, but with a double-argument @c f and @c operator(). - * - * The function @c ptr_fun takes a pointer-to-function @c f and constructs - * an instance of the appropriate functor. - * - * @{ - */ - /// One of the @link pointer_adaptors adaptors for function pointers@endlink. - template - class pointer_to_unary_function : public unary_function<_Arg, _Result> - { - protected: - _Result (*_M_ptr)(_Arg); - - public: - pointer_to_unary_function() { } - - explicit - pointer_to_unary_function(_Result (*__x)(_Arg)) - : _M_ptr(__x) { } - - _Result - operator()(_Arg __x) const - { return _M_ptr(__x); } - }; - - /// One of the @link pointer_adaptors adaptors for function pointers@endlink. - template - inline pointer_to_unary_function<_Arg, _Result> - ptr_fun(_Result (*__x)(_Arg)) - { return pointer_to_unary_function<_Arg, _Result>(__x); } - - /// One of the @link pointer_adaptors adaptors for function pointers@endlink. - template - class pointer_to_binary_function - : public binary_function<_Arg1, _Arg2, _Result> - { - protected: - _Result (*_M_ptr)(_Arg1, _Arg2); - - public: - pointer_to_binary_function() { } - - explicit - pointer_to_binary_function(_Result (*__x)(_Arg1, _Arg2)) - : _M_ptr(__x) { } - - _Result - operator()(_Arg1 __x, _Arg2 __y) const - { return _M_ptr(__x, __y); } - }; - - /// One of the @link pointer_adaptors adaptors for function pointers@endlink. - template - inline pointer_to_binary_function<_Arg1, _Arg2, _Result> - ptr_fun(_Result (*__x)(_Arg1, _Arg2)) - { return pointer_to_binary_function<_Arg1, _Arg2, _Result>(__x); } - /** @} */ - - template - struct _Identity - : public unary_function<_Tp, _Tp> - { - _Tp& - operator()(_Tp& __x) const - { return __x; } - - const _Tp& - operator()(const _Tp& __x) const - { return __x; } - }; - - // Partial specialization, avoids confusing errors in e.g. std::set. - template struct _Identity : _Identity<_Tp> { }; - - template - struct _Select1st - : public unary_function<_Pair, typename _Pair::first_type> - { - typename _Pair::first_type& - operator()(_Pair& __x) const - { return __x.first; } - - const typename _Pair::first_type& - operator()(const _Pair& __x) const - { return __x.first; } - -#if __cplusplus >= 201103L - template - typename _Pair2::first_type& - operator()(_Pair2& __x) const - { return __x.first; } - - template - const typename _Pair2::first_type& - operator()(const _Pair2& __x) const - { return __x.first; } -#endif - }; - - template - struct _Select2nd - : public unary_function<_Pair, typename _Pair::second_type> - { - typename _Pair::second_type& - operator()(_Pair& __x) const - { return __x.second; } - - const typename _Pair::second_type& - operator()(const _Pair& __x) const - { return __x.second; } - }; - - // 20.3.8 adaptors pointers members - /** @defgroup memory_adaptors Adaptors for pointers to members - * @ingroup functors - * - * There are a total of 8 = 2^3 function objects in this family. - * (1) Member functions taking no arguments vs member functions taking - * one argument. - * (2) Call through pointer vs call through reference. - * (3) Const vs non-const member function. - * - * All of this complexity is in the function objects themselves. You can - * ignore it by using the helper function mem_fun and mem_fun_ref, - * which create whichever type of adaptor is appropriate. - * - * @{ - */ - /// One of the @link memory_adaptors adaptors for member - /// pointers@endlink. - template - class mem_fun_t : public unary_function<_Tp*, _Ret> - { - public: - explicit - mem_fun_t(_Ret (_Tp::*__pf)()) - : _M_f(__pf) { } - - _Ret - operator()(_Tp* __p) const - { return (__p->*_M_f)(); } - - private: - _Ret (_Tp::*_M_f)(); - }; - - /// One of the @link memory_adaptors adaptors for member - /// pointers@endlink. - template - class const_mem_fun_t : public unary_function - { - public: - explicit - const_mem_fun_t(_Ret (_Tp::*__pf)() const) - : _M_f(__pf) { } - - _Ret - operator()(const _Tp* __p) const - { return (__p->*_M_f)(); } - - private: - _Ret (_Tp::*_M_f)() const; - }; - - /// One of the @link memory_adaptors adaptors for member - /// pointers@endlink. - template - class mem_fun_ref_t : public unary_function<_Tp, _Ret> - { - public: - explicit - mem_fun_ref_t(_Ret (_Tp::*__pf)()) - : _M_f(__pf) { } - - _Ret - operator()(_Tp& __r) const - { return (__r.*_M_f)(); } - - private: - _Ret (_Tp::*_M_f)(); - }; - - /// One of the @link memory_adaptors adaptors for member - /// pointers@endlink. - template - class const_mem_fun_ref_t : public unary_function<_Tp, _Ret> - { - public: - explicit - const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const) - : _M_f(__pf) { } - - _Ret - operator()(const _Tp& __r) const - { return (__r.*_M_f)(); } - - private: - _Ret (_Tp::*_M_f)() const; - }; - - /// One of the @link memory_adaptors adaptors for member - /// pointers@endlink. - template - class mem_fun1_t : public binary_function<_Tp*, _Arg, _Ret> - { - public: - explicit - mem_fun1_t(_Ret (_Tp::*__pf)(_Arg)) - : _M_f(__pf) { } - - _Ret - operator()(_Tp* __p, _Arg __x) const - { return (__p->*_M_f)(__x); } - - private: - _Ret (_Tp::*_M_f)(_Arg); - }; - - /// One of the @link memory_adaptors adaptors for member - /// pointers@endlink. - template - class const_mem_fun1_t : public binary_function - { - public: - explicit - const_mem_fun1_t(_Ret (_Tp::*__pf)(_Arg) const) - : _M_f(__pf) { } - - _Ret - operator()(const _Tp* __p, _Arg __x) const - { return (__p->*_M_f)(__x); } - - private: - _Ret (_Tp::*_M_f)(_Arg) const; - }; - - /// One of the @link memory_adaptors adaptors for member - /// pointers@endlink. - template - class mem_fun1_ref_t : public binary_function<_Tp, _Arg, _Ret> - { - public: - explicit - mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg)) - : _M_f(__pf) { } - - _Ret - operator()(_Tp& __r, _Arg __x) const - { return (__r.*_M_f)(__x); } - - private: - _Ret (_Tp::*_M_f)(_Arg); - }; - - /// One of the @link memory_adaptors adaptors for member - /// pointers@endlink. - template - class const_mem_fun1_ref_t : public binary_function<_Tp, _Arg, _Ret> - { - public: - explicit - const_mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg) const) - : _M_f(__pf) { } - - _Ret - operator()(const _Tp& __r, _Arg __x) const - { return (__r.*_M_f)(__x); } - - private: - _Ret (_Tp::*_M_f)(_Arg) const; - }; - - // Mem_fun adaptor helper functions. There are only two: - // mem_fun and mem_fun_ref. - template - inline mem_fun_t<_Ret, _Tp> - mem_fun(_Ret (_Tp::*__f)()) - { return mem_fun_t<_Ret, _Tp>(__f); } - - template - inline const_mem_fun_t<_Ret, _Tp> - mem_fun(_Ret (_Tp::*__f)() const) - { return const_mem_fun_t<_Ret, _Tp>(__f); } - - template - inline mem_fun_ref_t<_Ret, _Tp> - mem_fun_ref(_Ret (_Tp::*__f)()) - { return mem_fun_ref_t<_Ret, _Tp>(__f); } - - template - inline const_mem_fun_ref_t<_Ret, _Tp> - mem_fun_ref(_Ret (_Tp::*__f)() const) - { return const_mem_fun_ref_t<_Ret, _Tp>(__f); } - - template - inline mem_fun1_t<_Ret, _Tp, _Arg> - mem_fun(_Ret (_Tp::*__f)(_Arg)) - { return mem_fun1_t<_Ret, _Tp, _Arg>(__f); } - - template - inline const_mem_fun1_t<_Ret, _Tp, _Arg> - mem_fun(_Ret (_Tp::*__f)(_Arg) const) - { return const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); } - - template - inline mem_fun1_ref_t<_Ret, _Tp, _Arg> - mem_fun_ref(_Ret (_Tp::*__f)(_Arg)) - { return mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } - - template - inline const_mem_fun1_ref_t<_Ret, _Tp, _Arg> - mem_fun_ref(_Ret (_Tp::*__f)(_Arg) const) - { return const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } - - /** @} */ - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#if (__cplusplus < 201103L) || _GLIBCXX_USE_DEPRECATED -# include -#endif - -#endif /* _STL_FUNCTION_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_heap.h b/resources/sources/avr-libstdcpp/include/bits/stl_heap.h deleted file mode 100644 index 52e3a3b44..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_heap.h +++ /dev/null @@ -1,583 +0,0 @@ -// Heap implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * Copyright (c) 1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_heap.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{queue} - */ - -#ifndef _STL_HEAP_H -#define _STL_HEAP_H 1 - -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup heap_algorithms Heap - * @ingroup sorting_algorithms - */ - - template - _GLIBCXX20_CONSTEXPR - _Distance - __is_heap_until(_RandomAccessIterator __first, _Distance __n, - _Compare& __comp) - { - _Distance __parent = 0; - for (_Distance __child = 1; __child < __n; ++__child) - { - if (__comp(__first + __parent, __first + __child)) - return __child; - if ((__child & 1) == 0) - ++__parent; - } - return __n; - } - - // __is_heap, a predicate testing whether or not a range is a heap. - // This function is an extension, not part of the C++ standard. - template - _GLIBCXX20_CONSTEXPR - inline bool - __is_heap(_RandomAccessIterator __first, _Distance __n) - { - __gnu_cxx::__ops::_Iter_less_iter __comp; - return std::__is_heap_until(__first, __n, __comp) == __n; - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n) - { - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - return std::__is_heap_until(__first, __n, __cmp) == __n; - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) - { return std::__is_heap(__first, std::distance(__first, __last)); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - return std::__is_heap(__first, _GLIBCXX_MOVE(__comp), - std::distance(__first, __last)); - } - - // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap, - // + is_heap and is_heap_until in C++0x. - - template - _GLIBCXX20_CONSTEXPR - void - __push_heap(_RandomAccessIterator __first, - _Distance __holeIndex, _Distance __topIndex, _Tp __value, - _Compare& __comp) - { - _Distance __parent = (__holeIndex - 1) / 2; - while (__holeIndex > __topIndex && __comp(__first + __parent, __value)) - { - *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent)); - __holeIndex = __parent; - __parent = (__holeIndex - 1) / 2; - } - *(__first + __holeIndex) = _GLIBCXX_MOVE(__value); - } - - /** - * @brief Push an element onto a heap. - * @param __first Start of heap. - * @param __last End of heap + element. - * @ingroup heap_algorithms - * - * This operation pushes the element at last-1 onto the valid heap - * over the range [__first,__last-1). After completion, - * [__first,__last) is a valid heap. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _ValueType; - typedef typename iterator_traits<_RandomAccessIterator>::difference_type - _DistanceType; - - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - __glibcxx_requires_heap(__first, __last - 1); - - __gnu_cxx::__ops::_Iter_less_val __comp; - _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); - std::__push_heap(__first, _DistanceType((__last - __first) - 1), - _DistanceType(0), _GLIBCXX_MOVE(__value), __comp); - } - - /** - * @brief Push an element onto a heap using comparison functor. - * @param __first Start of heap. - * @param __last End of heap + element. - * @param __comp Comparison functor. - * @ingroup heap_algorithms - * - * This operation pushes the element at __last-1 onto the valid - * heap over the range [__first,__last-1). After completion, - * [__first,__last) is a valid heap. Compare operations are - * performed using comp. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _ValueType; - typedef typename iterator_traits<_RandomAccessIterator>::difference_type - _DistanceType; - - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - __glibcxx_requires_heap_pred(__first, __last - 1, __comp); - - __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) - __cmp(_GLIBCXX_MOVE(__comp)); - _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); - std::__push_heap(__first, _DistanceType((__last - __first) - 1), - _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp); - } - - template - _GLIBCXX20_CONSTEXPR - void - __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, - _Distance __len, _Tp __value, _Compare __comp) - { - const _Distance __topIndex = __holeIndex; - _Distance __secondChild = __holeIndex; - while (__secondChild < (__len - 1) / 2) - { - __secondChild = 2 * (__secondChild + 1); - if (__comp(__first + __secondChild, - __first + (__secondChild - 1))) - __secondChild--; - *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild)); - __holeIndex = __secondChild; - } - if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2) - { - __secondChild = 2 * (__secondChild + 1); - *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first - + (__secondChild - 1))); - __holeIndex = __secondChild - 1; - } - __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) - __cmp(_GLIBCXX_MOVE(__comp)); - std::__push_heap(__first, __holeIndex, __topIndex, - _GLIBCXX_MOVE(__value), __cmp); - } - - template - _GLIBCXX20_CONSTEXPR - inline void - __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _RandomAccessIterator __result, _Compare& __comp) - { - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _ValueType; - typedef typename iterator_traits<_RandomAccessIterator>::difference_type - _DistanceType; - - _ValueType __value = _GLIBCXX_MOVE(*__result); - *__result = _GLIBCXX_MOVE(*__first); - std::__adjust_heap(__first, _DistanceType(0), - _DistanceType(__last - __first), - _GLIBCXX_MOVE(__value), __comp); - } - - /** - * @brief Pop an element off a heap. - * @param __first Start of heap. - * @param __last End of heap. - * @pre [__first, __last) is a valid, non-empty range. - * @ingroup heap_algorithms - * - * This operation pops the top of the heap. The elements __first - * and __last-1 are swapped and [__first,__last-1) is made into a - * heap. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_non_empty_range(__first, __last); - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - __glibcxx_requires_heap(__first, __last); - - if (__last - __first > 1) - { - --__last; - __gnu_cxx::__ops::_Iter_less_iter __comp; - std::__pop_heap(__first, __last, __last, __comp); - } - } - - /** - * @brief Pop an element off a heap using comparison functor. - * @param __first Start of heap. - * @param __last End of heap. - * @param __comp Comparison functor to use. - * @ingroup heap_algorithms - * - * This operation pops the top of the heap. The elements __first - * and __last-1 are swapped and [__first,__last-1) is made into a - * heap. Comparisons are made using comp. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - pop_heap(_RandomAccessIterator __first, - _RandomAccessIterator __last, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - __glibcxx_requires_non_empty_range(__first, __last); - __glibcxx_requires_heap_pred(__first, __last, __comp); - - if (__last - __first > 1) - { - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - --__last; - std::__pop_heap(__first, __last, __last, __cmp); - } - } - - template - _GLIBCXX20_CONSTEXPR - void - __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare& __comp) - { - typedef typename iterator_traits<_RandomAccessIterator>::value_type - _ValueType; - typedef typename iterator_traits<_RandomAccessIterator>::difference_type - _DistanceType; - - if (__last - __first < 2) - return; - - const _DistanceType __len = __last - __first; - _DistanceType __parent = (__len - 2) / 2; - while (true) - { - _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent)); - std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value), - __comp); - if (__parent == 0) - return; - __parent--; - } - } - - /** - * @brief Construct a heap over a range. - * @param __first Start of heap. - * @param __last End of heap. - * @ingroup heap_algorithms - * - * This operation makes the elements in [__first,__last) into a heap. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - __gnu_cxx::__ops::_Iter_less_iter __comp; - std::__make_heap(__first, __last, __comp); - } - - /** - * @brief Construct a heap over a range using comparison functor. - * @param __first Start of heap. - * @param __last End of heap. - * @param __comp Comparison functor to use. - * @ingroup heap_algorithms - * - * This operation makes the elements in [__first,__last) into a heap. - * Comparisons are made using __comp. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - std::__make_heap(__first, __last, __cmp); - } - - template - _GLIBCXX20_CONSTEXPR - void - __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare& __comp) - { - while (__last - __first > 1) - { - --__last; - std::__pop_heap(__first, __last, __last, __comp); - } - } - - /** - * @brief Sort a heap. - * @param __first Start of heap. - * @param __last End of heap. - * @ingroup heap_algorithms - * - * This operation sorts the valid heap in the range [__first,__last). - */ - template - _GLIBCXX20_CONSTEXPR - inline void - sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - __glibcxx_requires_heap(__first, __last); - - __gnu_cxx::__ops::_Iter_less_iter __comp; - std::__sort_heap(__first, __last, __comp); - } - - /** - * @brief Sort a heap using comparison functor. - * @param __first Start of heap. - * @param __last End of heap. - * @param __comp Comparison functor to use. - * @ingroup heap_algorithms - * - * This operation sorts the valid heap in the range [__first,__last). - * Comparisons are made using __comp. - */ - template - _GLIBCXX20_CONSTEXPR - inline void - sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - __glibcxx_requires_heap_pred(__first, __last, __comp); - - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - std::__sort_heap(__first, __last, __cmp); - } - -#if __cplusplus >= 201103L - /** - * @brief Search the end of a heap. - * @param __first Start of range. - * @param __last End of range. - * @return An iterator pointing to the first element not in the heap. - * @ingroup heap_algorithms - * - * This operation returns the last iterator i in [__first, __last) for which - * the range [__first, i) is a heap. - */ - template - _GLIBCXX20_CONSTEXPR - inline _RandomAccessIterator - is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive(__first, __last); - - __gnu_cxx::__ops::_Iter_less_iter __comp; - return __first + - std::__is_heap_until(__first, std::distance(__first, __last), __comp); - } - - /** - * @brief Search the end of a heap using comparison functor. - * @param __first Start of range. - * @param __last End of range. - * @param __comp Comparison functor to use. - * @return An iterator pointing to the first element not in the heap. - * @ingroup heap_algorithms - * - * This operation returns the last iterator i in [__first, __last) for which - * the range [__first, i) is a heap. Comparisons are made using __comp. - */ - template - _GLIBCXX20_CONSTEXPR - inline _RandomAccessIterator - is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - return __first - + std::__is_heap_until(__first, std::distance(__first, __last), __cmp); - } - - /** - * @brief Determines whether a range is a heap. - * @param __first Start of range. - * @param __last End of range. - * @return True if range is a heap, false otherwise. - * @ingroup heap_algorithms - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) - { return std::is_heap_until(__first, __last) == __last; } - - /** - * @brief Determines whether a range is a heap using comparison functor. - * @param __first Start of range. - * @param __last End of range. - * @param __comp Comparison functor to use. - * @return True if range is a heap, false otherwise. - * @ingroup heap_algorithms - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_irreflexive_pred(__first, __last, __comp); - - const auto __dist = std::distance(__first, __last); - typedef __decltype(__comp) _Cmp; - __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); - return std::__is_heap_until(__first, __dist, __cmp) == __dist; - } -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _STL_HEAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h deleted file mode 100644 index 7d293ce3f..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h +++ /dev/null @@ -1,2238 +0,0 @@ -// Iterators -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996-1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_iterator.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iterator} - * - * This file implements reverse_iterator, back_insert_iterator, - * front_insert_iterator, insert_iterator, __normal_iterator, and their - * supporting functions and overloaded operators. - */ - -#ifndef _STL_ITERATOR_H -#define _STL_ITERATOR_H 1 - -#include -#include -#include -#include -#include - -#if __cplusplus >= 201103L -# include -#endif - -#if __cplusplus > 201703L -# define __cpp_lib_array_constexpr 201811L -# define __cpp_lib_constexpr_iterator 201811L -#elif __cplusplus == 201703L -# define __cpp_lib_array_constexpr 201803L -#endif - -#if __cplusplus > 201703L -# include -# include -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup iterators - * @{ - */ - -#if __cplusplus > 201703L && __cpp_lib_concepts - namespace __detail - { - // Weaken iterator_category _Cat to _Limit if it is derived from that, - // otherwise use _Otherwise. - template - using __clamp_iter_cat - = conditional_t, _Limit, _Otherwise>; - } -#endif - - // 24.4.1 Reverse iterators - /** - * Bidirectional and random access iterators have corresponding reverse - * %iterator adaptors that iterate through the data structure in the - * opposite direction. They have the same signatures as the corresponding - * iterators. The fundamental relation between a reverse %iterator and its - * corresponding %iterator @c i is established by the identity: - * @code - * &*(reverse_iterator(i)) == &*(i - 1) - * @endcode - * - * This mapping is dictated by the fact that while there is always a - * pointer past the end of an array, there might not be a valid pointer - * before the beginning of an array. [24.4.1]/1,2 - * - * Reverse iterators can be tricky and surprising at first. Their - * semantics make sense, however, and the trickiness is a side effect of - * the requirement that the iterators must be safe. - */ - template - class reverse_iterator - : public iterator::iterator_category, - typename iterator_traits<_Iterator>::value_type, - typename iterator_traits<_Iterator>::difference_type, - typename iterator_traits<_Iterator>::pointer, - typename iterator_traits<_Iterator>::reference> - { - protected: - _Iterator current; - - typedef iterator_traits<_Iterator> __traits_type; - - public: - typedef _Iterator iterator_type; - typedef typename __traits_type::difference_type difference_type; - typedef typename __traits_type::pointer pointer; - typedef typename __traits_type::reference reference; - -#if __cplusplus > 201703L && __cpp_lib_concepts - using iterator_concept - = conditional_t, - random_access_iterator_tag, - bidirectional_iterator_tag>; - using iterator_category - = __detail::__clamp_iter_cat; -#endif - - /** - * The default constructor value-initializes member @p current. - * If it is a pointer, that means it is zero-initialized. - */ - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 235 No specification of default ctor for reverse_iterator - // 1012. reverse_iterator default ctor should value initialize - _GLIBCXX17_CONSTEXPR - reverse_iterator() : current() { } - - /** - * This %iterator will move in the opposite direction that @p x does. - */ - explicit _GLIBCXX17_CONSTEXPR - reverse_iterator(iterator_type __x) : current(__x) { } - - /** - * The copy constructor is normal. - */ - _GLIBCXX17_CONSTEXPR - reverse_iterator(const reverse_iterator& __x) - : current(__x.current) { } - -#if __cplusplus >= 201103L - reverse_iterator& operator=(const reverse_iterator&) = default; -#endif - - /** - * A %reverse_iterator across other types can be copied if the - * underlying %iterator can be converted to the type of @c current. - */ - template - _GLIBCXX17_CONSTEXPR - reverse_iterator(const reverse_iterator<_Iter>& __x) - : current(__x.base()) { } - - /** - * @return @c current, the %iterator used for underlying work. - */ - _GLIBCXX17_CONSTEXPR iterator_type - base() const - { return current; } - - /** - * @return A reference to the value at @c --current - * - * This requires that @c --current is dereferenceable. - * - * @warning This implementation requires that for an iterator of the - * underlying iterator type, @c x, a reference obtained by - * @c *x remains valid after @c x has been modified or - * destroyed. This is a bug: http://gcc.gnu.org/PR51823 - */ - _GLIBCXX17_CONSTEXPR reference - operator*() const - { - _Iterator __tmp = current; - return *--__tmp; - } - - /** - * @return A pointer to the value at @c --current - * - * This requires that @c --current is dereferenceable. - */ - _GLIBCXX17_CONSTEXPR pointer - operator->() const -#if __cplusplus > 201703L && __cpp_concepts >= 201907L - requires is_pointer_v<_Iterator> - || requires(const _Iterator __i) { __i.operator->(); } -#endif - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 1052. operator-> should also support smart pointers - _Iterator __tmp = current; - --__tmp; - return _S_to_pointer(__tmp); - } - - /** - * @return @c *this - * - * Decrements the underlying iterator. - */ - _GLIBCXX17_CONSTEXPR reverse_iterator& - operator++() - { - --current; - return *this; - } - - /** - * @return The original value of @c *this - * - * Decrements the underlying iterator. - */ - _GLIBCXX17_CONSTEXPR reverse_iterator - operator++(int) - { - reverse_iterator __tmp = *this; - --current; - return __tmp; - } - - /** - * @return @c *this - * - * Increments the underlying iterator. - */ - _GLIBCXX17_CONSTEXPR reverse_iterator& - operator--() - { - ++current; - return *this; - } - - /** - * @return A reverse_iterator with the previous value of @c *this - * - * Increments the underlying iterator. - */ - _GLIBCXX17_CONSTEXPR reverse_iterator - operator--(int) - { - reverse_iterator __tmp = *this; - ++current; - return __tmp; - } - - /** - * @return A reverse_iterator that refers to @c current - @a __n - * - * The underlying iterator must be a Random Access Iterator. - */ - _GLIBCXX17_CONSTEXPR reverse_iterator - operator+(difference_type __n) const - { return reverse_iterator(current - __n); } - - /** - * @return *this - * - * Moves the underlying iterator backwards @a __n steps. - * The underlying iterator must be a Random Access Iterator. - */ - _GLIBCXX17_CONSTEXPR reverse_iterator& - operator+=(difference_type __n) - { - current -= __n; - return *this; - } - - /** - * @return A reverse_iterator that refers to @c current - @a __n - * - * The underlying iterator must be a Random Access Iterator. - */ - _GLIBCXX17_CONSTEXPR reverse_iterator - operator-(difference_type __n) const - { return reverse_iterator(current + __n); } - - /** - * @return *this - * - * Moves the underlying iterator forwards @a __n steps. - * The underlying iterator must be a Random Access Iterator. - */ - _GLIBCXX17_CONSTEXPR reverse_iterator& - operator-=(difference_type __n) - { - current += __n; - return *this; - } - - /** - * @return The value at @c current - @a __n - 1 - * - * The underlying iterator must be a Random Access Iterator. - */ - _GLIBCXX17_CONSTEXPR reference - operator[](difference_type __n) const - { return *(*this + __n); } - -#if __cplusplus > 201703L && __cpp_lib_concepts - friend constexpr iter_rvalue_reference_t<_Iterator> - iter_move(const reverse_iterator& __i) - noexcept(is_nothrow_copy_constructible_v<_Iterator> - && noexcept(ranges::iter_move(--std::declval<_Iterator&>()))) - { - auto __tmp = __i.base(); - return ranges::iter_move(--__tmp); - } - - template _Iter2> - friend constexpr void - iter_swap(const reverse_iterator& __x, - const reverse_iterator<_Iter2>& __y) - noexcept(is_nothrow_copy_constructible_v<_Iterator> - && is_nothrow_copy_constructible_v<_Iter2> - && noexcept(ranges::iter_swap(--std::declval<_Iterator&>(), - --std::declval<_Iter2&>()))) - { - auto __xtmp = __x.base(); - auto __ytmp = __y.base(); - ranges::iter_swap(--__xtmp, --__ytmp); - } -#endif - - private: - template - static _GLIBCXX17_CONSTEXPR _Tp* - _S_to_pointer(_Tp* __p) - { return __p; } - - template - static _GLIBCXX17_CONSTEXPR pointer - _S_to_pointer(_Tp __t) - { return __t.operator->(); } - }; - - //@{ - /** - * @param __x A %reverse_iterator. - * @param __y A %reverse_iterator. - * @return A simple bool. - * - * Reverse iterators forward comparisons to their underlying base() - * iterators. - * - */ -#if __cplusplus <= 201703L || ! defined __cpp_lib_concepts - template - inline _GLIBCXX17_CONSTEXPR bool - operator==(const reverse_iterator<_Iterator>& __x, - const reverse_iterator<_Iterator>& __y) - { return __x.base() == __y.base(); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator<(const reverse_iterator<_Iterator>& __x, - const reverse_iterator<_Iterator>& __y) - { return __y.base() < __x.base(); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator!=(const reverse_iterator<_Iterator>& __x, - const reverse_iterator<_Iterator>& __y) - { return !(__x == __y); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator>(const reverse_iterator<_Iterator>& __x, - const reverse_iterator<_Iterator>& __y) - { return __y < __x; } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator<=(const reverse_iterator<_Iterator>& __x, - const reverse_iterator<_Iterator>& __y) - { return !(__y < __x); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator>=(const reverse_iterator<_Iterator>& __x, - const reverse_iterator<_Iterator>& __y) - { return !(__x < __y); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 280. Comparison of reverse_iterator to const reverse_iterator. - template - inline _GLIBCXX17_CONSTEXPR bool - operator==(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - { return __x.base() == __y.base(); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator<(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - { return __y.base() < __x.base(); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator!=(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - { return !(__x == __y); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator>(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - { return __y < __x; } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator<=(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - { return !(__y < __x); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator>=(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - { return !(__x < __y); } -#else // C++20 - template - constexpr bool - operator==(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - requires requires { { __x.base() == __y.base() } -> convertible_to; } - { return __x.base() == __y.base(); } - - template - constexpr bool - operator!=(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - requires requires { { __x.base() != __y.base() } -> convertible_to; } - { return __x.base() != __y.base(); } - - template - constexpr bool - operator<(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - requires requires { { __x.base() > __y.base() } -> convertible_to; } - { return __x.base() > __y.base(); } - - template - constexpr bool - operator>(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - requires requires { { __x.base() < __y.base() } -> convertible_to; } - { return __x.base() < __y.base(); } - - template - constexpr bool - operator<=(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - requires requires { { __x.base() >= __y.base() } -> convertible_to; } - { return __x.base() >= __y.base(); } - - template - constexpr bool - operator>=(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - requires requires { { __x.base() <= __y.base() } -> convertible_to; } - { return __x.base() <= __y.base(); } - - template _IteratorR> - constexpr compare_three_way_result_t<_IteratorL, _IteratorR> - operator<=>(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - { return __y.base() <=> __x.base(); } -#endif // C++20 - //@} - -#if __cplusplus < 201103L - template - inline typename reverse_iterator<_Iterator>::difference_type - operator-(const reverse_iterator<_Iterator>& __x, - const reverse_iterator<_Iterator>& __y) - { return __y.base() - __x.base(); } - - template - inline typename reverse_iterator<_IteratorL>::difference_type - operator-(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - { return __y.base() - __x.base(); } -#else - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 685. reverse_iterator/move_iterator difference has invalid signatures - template - inline _GLIBCXX17_CONSTEXPR auto - operator-(const reverse_iterator<_IteratorL>& __x, - const reverse_iterator<_IteratorR>& __y) - -> decltype(__y.base() - __x.base()) - { return __y.base() - __x.base(); } -#endif - - template - inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> - operator+(typename reverse_iterator<_Iterator>::difference_type __n, - const reverse_iterator<_Iterator>& __x) - { return reverse_iterator<_Iterator>(__x.base() - __n); } - -#if __cplusplus >= 201103L - // Same as C++14 make_reverse_iterator but used in C++11 mode too. - template - inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> - __make_reverse_iterator(_Iterator __i) - { return reverse_iterator<_Iterator>(__i); } - -# if __cplusplus >= 201402L -# define __cpp_lib_make_reverse_iterator 201402 - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 2285. make_reverse_iterator - /// Generator function for reverse_iterator. - template - inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> - make_reverse_iterator(_Iterator __i) - { return reverse_iterator<_Iterator>(__i); } - -# if __cplusplus > 201703L && defined __cpp_lib_concepts - template - requires (!sized_sentinel_for<_Iterator1, _Iterator2>) - inline constexpr bool - disable_sized_sentinel_for, - reverse_iterator<_Iterator2>> = true; -# endif // C++20 -# endif // C++14 - - template - _GLIBCXX20_CONSTEXPR - auto - __niter_base(reverse_iterator<_Iterator> __it) - -> decltype(__make_reverse_iterator(__niter_base(__it.base()))) - { return __make_reverse_iterator(__niter_base(__it.base())); } - - template - struct __is_move_iterator > - : __is_move_iterator<_Iterator> - { }; - - template - _GLIBCXX20_CONSTEXPR - auto - __miter_base(reverse_iterator<_Iterator> __it) - -> decltype(__make_reverse_iterator(__miter_base(__it.base()))) - { return __make_reverse_iterator(__miter_base(__it.base())); } -#endif // C++11 - - // 24.4.2.2.1 back_insert_iterator - /** - * @brief Turns assignment into insertion. - * - * These are output iterators, constructed from a container-of-T. - * Assigning a T to the iterator appends it to the container using - * push_back. - * - * Tip: Using the back_inserter function to create these iterators can - * save typing. - */ - template - class back_insert_iterator - : public iterator - { - protected: - _Container* container; - - public: - /// A nested typedef for the type of whatever container you used. - typedef _Container container_type; -#if __cplusplus > 201703L - using difference_type = ptrdiff_t; - - constexpr back_insert_iterator() noexcept : container(nullptr) { } -#endif - - /// The only way to create this %iterator is with a container. - explicit _GLIBCXX20_CONSTEXPR - back_insert_iterator(_Container& __x) - : container(std::__addressof(__x)) { } - - /** - * @param __value An instance of whatever type - * container_type::const_reference is; presumably a - * reference-to-const T for container. - * @return This %iterator, for chained operations. - * - * This kind of %iterator doesn't really have a @a position in the - * container (you can think of the position as being permanently at - * the end, if you like). Assigning a value to the %iterator will - * always append the value to the end of the container. - */ -#if __cplusplus < 201103L - back_insert_iterator& - operator=(typename _Container::const_reference __value) - { - container->push_back(__value); - return *this; - } -#else - _GLIBCXX20_CONSTEXPR - back_insert_iterator& - operator=(const typename _Container::value_type& __value) - { - container->push_back(__value); - return *this; - } - - _GLIBCXX20_CONSTEXPR - back_insert_iterator& - operator=(typename _Container::value_type&& __value) - { - container->push_back(std::move(__value)); - return *this; - } -#endif - - /// Simply returns *this. - _GLIBCXX20_CONSTEXPR - back_insert_iterator& - operator*() - { return *this; } - - /// Simply returns *this. (This %iterator does not @a move.) - _GLIBCXX20_CONSTEXPR - back_insert_iterator& - operator++() - { return *this; } - - /// Simply returns *this. (This %iterator does not @a move.) - _GLIBCXX20_CONSTEXPR - back_insert_iterator - operator++(int) - { return *this; } - }; - - /** - * @param __x A container of arbitrary type. - * @return An instance of back_insert_iterator working on @p __x. - * - * This wrapper function helps in creating back_insert_iterator instances. - * Typing the name of the %iterator requires knowing the precise full - * type of the container, which can be tedious and impedes generic - * programming. Using this function lets you take advantage of automatic - * template parameter deduction, making the compiler match the correct - * types for you. - */ - template - _GLIBCXX20_CONSTEXPR - inline back_insert_iterator<_Container> - back_inserter(_Container& __x) - { return back_insert_iterator<_Container>(__x); } - - /** - * @brief Turns assignment into insertion. - * - * These are output iterators, constructed from a container-of-T. - * Assigning a T to the iterator prepends it to the container using - * push_front. - * - * Tip: Using the front_inserter function to create these iterators can - * save typing. - */ - template - class front_insert_iterator - : public iterator - { - protected: - _Container* container; - - public: - /// A nested typedef for the type of whatever container you used. - typedef _Container container_type; -#if __cplusplus > 201703L - using difference_type = ptrdiff_t; - - constexpr front_insert_iterator() noexcept : container(nullptr) { } -#endif - - /// The only way to create this %iterator is with a container. - explicit _GLIBCXX20_CONSTEXPR - front_insert_iterator(_Container& __x) - : container(std::__addressof(__x)) { } - - /** - * @param __value An instance of whatever type - * container_type::const_reference is; presumably a - * reference-to-const T for container. - * @return This %iterator, for chained operations. - * - * This kind of %iterator doesn't really have a @a position in the - * container (you can think of the position as being permanently at - * the front, if you like). Assigning a value to the %iterator will - * always prepend the value to the front of the container. - */ -#if __cplusplus < 201103L - front_insert_iterator& - operator=(typename _Container::const_reference __value) - { - container->push_front(__value); - return *this; - } -#else - _GLIBCXX20_CONSTEXPR - front_insert_iterator& - operator=(const typename _Container::value_type& __value) - { - container->push_front(__value); - return *this; - } - - _GLIBCXX20_CONSTEXPR - front_insert_iterator& - operator=(typename _Container::value_type&& __value) - { - container->push_front(std::move(__value)); - return *this; - } -#endif - - /// Simply returns *this. - _GLIBCXX20_CONSTEXPR - front_insert_iterator& - operator*() - { return *this; } - - /// Simply returns *this. (This %iterator does not @a move.) - _GLIBCXX20_CONSTEXPR - front_insert_iterator& - operator++() - { return *this; } - - /// Simply returns *this. (This %iterator does not @a move.) - _GLIBCXX20_CONSTEXPR - front_insert_iterator - operator++(int) - { return *this; } - }; - - /** - * @param __x A container of arbitrary type. - * @return An instance of front_insert_iterator working on @p x. - * - * This wrapper function helps in creating front_insert_iterator instances. - * Typing the name of the %iterator requires knowing the precise full - * type of the container, which can be tedious and impedes generic - * programming. Using this function lets you take advantage of automatic - * template parameter deduction, making the compiler match the correct - * types for you. - */ - template - _GLIBCXX20_CONSTEXPR - inline front_insert_iterator<_Container> - front_inserter(_Container& __x) - { return front_insert_iterator<_Container>(__x); } - - /** - * @brief Turns assignment into insertion. - * - * These are output iterators, constructed from a container-of-T. - * Assigning a T to the iterator inserts it in the container at the - * %iterator's position, rather than overwriting the value at that - * position. - * - * (Sequences will actually insert a @e copy of the value before the - * %iterator's position.) - * - * Tip: Using the inserter function to create these iterators can - * save typing. - */ - template - class insert_iterator - : public iterator - { -#if __cplusplus > 201703L && defined __cpp_lib_concepts - using _Iter = std::__detail::__range_iter_t<_Container>; - - protected: - _Container* container = nullptr; - _Iter iter = _Iter(); -#else - typedef typename _Container::iterator _Iter; - - protected: - _Container* container; - _Iter iter; -#endif - - public: - /// A nested typedef for the type of whatever container you used. - typedef _Container container_type; - -#if __cplusplus > 201703L && defined __cpp_lib_concepts - using difference_type = ptrdiff_t; - - insert_iterator() = default; -#endif - - /** - * The only way to create this %iterator is with a container and an - * initial position (a normal %iterator into the container). - */ - _GLIBCXX20_CONSTEXPR - insert_iterator(_Container& __x, _Iter __i) - : container(std::__addressof(__x)), iter(__i) {} - - /** - * @param __value An instance of whatever type - * container_type::const_reference is; presumably a - * reference-to-const T for container. - * @return This %iterator, for chained operations. - * - * This kind of %iterator maintains its own position in the - * container. Assigning a value to the %iterator will insert the - * value into the container at the place before the %iterator. - * - * The position is maintained such that subsequent assignments will - * insert values immediately after one another. For example, - * @code - * // vector v contains A and Z - * - * insert_iterator i (v, ++v.begin()); - * i = 1; - * i = 2; - * i = 3; - * - * // vector v contains A, 1, 2, 3, and Z - * @endcode - */ -#if __cplusplus < 201103L - insert_iterator& - operator=(typename _Container::const_reference __value) - { - iter = container->insert(iter, __value); - ++iter; - return *this; - } -#else - _GLIBCXX20_CONSTEXPR - insert_iterator& - operator=(const typename _Container::value_type& __value) - { - iter = container->insert(iter, __value); - ++iter; - return *this; - } - - _GLIBCXX20_CONSTEXPR - insert_iterator& - operator=(typename _Container::value_type&& __value) - { - iter = container->insert(iter, std::move(__value)); - ++iter; - return *this; - } -#endif - - /// Simply returns *this. - _GLIBCXX20_CONSTEXPR - insert_iterator& - operator*() - { return *this; } - - /// Simply returns *this. (This %iterator does not @a move.) - _GLIBCXX20_CONSTEXPR - insert_iterator& - operator++() - { return *this; } - - /// Simply returns *this. (This %iterator does not @a move.) - _GLIBCXX20_CONSTEXPR - insert_iterator& - operator++(int) - { return *this; } - }; - - /** - * @param __x A container of arbitrary type. - * @param __i An iterator into the container. - * @return An instance of insert_iterator working on @p __x. - * - * This wrapper function helps in creating insert_iterator instances. - * Typing the name of the %iterator requires knowing the precise full - * type of the container, which can be tedious and impedes generic - * programming. Using this function lets you take advantage of automatic - * template parameter deduction, making the compiler match the correct - * types for you. - */ -#if __cplusplus > 201703L && defined __cpp_lib_concepts - template - constexpr insert_iterator<_Container> - inserter(_Container& __x, std::__detail::__range_iter_t<_Container> __i) - { return insert_iterator<_Container>(__x, __i); } -#else - template - inline insert_iterator<_Container> - inserter(_Container& __x, _Iterator __i) - { - return insert_iterator<_Container>(__x, - typename _Container::iterator(__i)); - } -#endif - - // @} group iterators - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // This iterator adapter is @a normal in the sense that it does not - // change the semantics of any of the operators of its iterator - // parameter. Its primary purpose is to convert an iterator that is - // not a class, e.g. a pointer, into an iterator that is a class. - // The _Container parameter exists solely so that different containers - // using this template can instantiate different types, even if the - // _Iterator parameter is the same. - template - class __normal_iterator - { - protected: - _Iterator _M_current; - - typedef std::iterator_traits<_Iterator> __traits_type; - - public: - typedef _Iterator iterator_type; - typedef typename __traits_type::iterator_category iterator_category; - typedef typename __traits_type::value_type value_type; - typedef typename __traits_type::difference_type difference_type; - typedef typename __traits_type::reference reference; - typedef typename __traits_type::pointer pointer; - -#if __cplusplus > 201703L && __cpp_lib_concepts - using iterator_concept = std::__detail::__iter_concept<_Iterator>; -#endif - - _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT - : _M_current(_Iterator()) { } - - explicit _GLIBCXX20_CONSTEXPR - __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT - : _M_current(__i) { } - - // Allow iterator to const_iterator conversion - template - _GLIBCXX20_CONSTEXPR - __normal_iterator(const __normal_iterator<_Iter, - typename __enable_if< - (std::__are_same<_Iter, typename _Container::pointer>::__value), - _Container>::__type>& __i) _GLIBCXX_NOEXCEPT - : _M_current(__i.base()) { } - - // Forward iterator requirements - _GLIBCXX20_CONSTEXPR - reference - operator*() const _GLIBCXX_NOEXCEPT - { return *_M_current; } - - _GLIBCXX20_CONSTEXPR - pointer - operator->() const _GLIBCXX_NOEXCEPT - { return _M_current; } - - _GLIBCXX20_CONSTEXPR - __normal_iterator& - operator++() _GLIBCXX_NOEXCEPT - { - ++_M_current; - return *this; - } - - _GLIBCXX20_CONSTEXPR - __normal_iterator - operator++(int) _GLIBCXX_NOEXCEPT - { return __normal_iterator(_M_current++); } - - // Bidirectional iterator requirements - _GLIBCXX20_CONSTEXPR - __normal_iterator& - operator--() _GLIBCXX_NOEXCEPT - { - --_M_current; - return *this; - } - - _GLIBCXX20_CONSTEXPR - __normal_iterator - operator--(int) _GLIBCXX_NOEXCEPT - { return __normal_iterator(_M_current--); } - - // Random access iterator requirements - _GLIBCXX20_CONSTEXPR - reference - operator[](difference_type __n) const _GLIBCXX_NOEXCEPT - { return _M_current[__n]; } - - _GLIBCXX20_CONSTEXPR - __normal_iterator& - operator+=(difference_type __n) _GLIBCXX_NOEXCEPT - { _M_current += __n; return *this; } - - _GLIBCXX20_CONSTEXPR - __normal_iterator - operator+(difference_type __n) const _GLIBCXX_NOEXCEPT - { return __normal_iterator(_M_current + __n); } - - _GLIBCXX20_CONSTEXPR - __normal_iterator& - operator-=(difference_type __n) _GLIBCXX_NOEXCEPT - { _M_current -= __n; return *this; } - - _GLIBCXX20_CONSTEXPR - __normal_iterator - operator-(difference_type __n) const _GLIBCXX_NOEXCEPT - { return __normal_iterator(_M_current - __n); } - - _GLIBCXX20_CONSTEXPR - const _Iterator& - base() const _GLIBCXX_NOEXCEPT - { return _M_current; } - }; - - // Note: In what follows, the left- and right-hand-side iterators are - // allowed to vary in types (conceptually in cv-qualification) so that - // comparison between cv-qualified and non-cv-qualified iterators be - // valid. However, the greedy and unfriendly operators in std::rel_ops - // will make overload resolution ambiguous (when in scope) if we don't - // provide overloads whose operands are of the same type. Can someone - // remind me what generic programming is about? -- Gaby - -#if __cpp_lib_three_way_comparison - template - requires requires (_IteratorL __lhs, _IteratorR __rhs) - { { __lhs == __rhs } -> std::convertible_to; } - constexpr bool - operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - noexcept(noexcept(__lhs.base() == __rhs.base())) - { return __lhs.base() == __rhs.base(); } - - template - constexpr std::__detail::__synth3way_t<_IteratorR, _IteratorL> - operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) - { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } -#else - // Forward iterator requirements - template - _GLIBCXX20_CONSTEXPR - inline bool - operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() == __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator==(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() == __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() != __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() != __rhs.base(); } - - // Random access iterator requirements - template - inline bool - operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() < __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator<(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() < __rhs.base(); } - - template - inline bool - operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() > __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator>(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() > __rhs.base(); } - - template - inline bool - operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() <= __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() <= __rhs.base(); } - - template - inline bool - operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() >= __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() >= __rhs.base(); } -#endif // three-way comparison - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // According to the resolution of DR179 not only the various comparison - // operators but also operator- must accept mixed iterator/const_iterator - // parameters. - template -#if __cplusplus >= 201103L - // DR 685. - _GLIBCXX20_CONSTEXPR - inline auto - operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept - -> decltype(__lhs.base() - __rhs.base()) -#else - inline typename __normal_iterator<_IteratorL, _Container>::difference_type - operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, - const __normal_iterator<_IteratorR, _Container>& __rhs) -#endif - { return __lhs.base() - __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline typename __normal_iterator<_Iterator, _Container>::difference_type - operator-(const __normal_iterator<_Iterator, _Container>& __lhs, - const __normal_iterator<_Iterator, _Container>& __rhs) - _GLIBCXX_NOEXCEPT - { return __lhs.base() - __rhs.base(); } - - template - _GLIBCXX20_CONSTEXPR - inline __normal_iterator<_Iterator, _Container> - operator+(typename __normal_iterator<_Iterator, _Container>::difference_type - __n, const __normal_iterator<_Iterator, _Container>& __i) - _GLIBCXX_NOEXCEPT - { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template - _GLIBCXX20_CONSTEXPR - _Iterator - __niter_base(__gnu_cxx::__normal_iterator<_Iterator, _Container> __it) - _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) - { return __it.base(); } - -#if __cplusplus >= 201103L - /** - * @addtogroup iterators - * @{ - */ - -#if __cplusplus > 201703L && __cpp_lib_concepts - template - class move_sentinel - { - public: - constexpr - move_sentinel() - noexcept(is_nothrow_default_constructible_v<_Sent>) - : _M_last() { } - - constexpr explicit - move_sentinel(_Sent __s) - noexcept(is_nothrow_move_constructible_v<_Sent>) - : _M_last(std::move(__s)) { } - - template requires convertible_to - constexpr - move_sentinel(const move_sentinel<_S2>& __s) - noexcept(is_nothrow_constructible_v<_Sent, const _S2&>) - : _M_last(__s.base()) - { } - - template requires assignable_from<_Sent&, const _S2&> - constexpr move_sentinel& - operator=(const move_sentinel<_S2>& __s) - noexcept(is_nothrow_assignable_v<_Sent, const _S2&>) - { - _M_last = __s.base(); - return *this; - } - - constexpr _Sent - base() const - noexcept(is_nothrow_copy_constructible_v<_Sent>) - { return _M_last; } - - private: - _Sent _M_last; - }; -#endif // C++20 - - // 24.4.3 Move iterators - /** - * Class template move_iterator is an iterator adapter with the same - * behavior as the underlying iterator except that its dereference - * operator implicitly converts the value returned by the underlying - * iterator's dereference operator to an rvalue reference. Some - * generic algorithms can be called with move iterators to replace - * copying with moving. - */ - template - class move_iterator - { - _Iterator _M_current; - - using __traits_type = iterator_traits<_Iterator>; -#if __cplusplus > 201703L && __cpp_lib_concepts - using __base_cat = typename __traits_type::iterator_category; -#else - using __base_ref = typename __traits_type::reference; -#endif - - public: - using iterator_type = _Iterator; - -#if __cplusplus > 201703L && __cpp_lib_concepts - using iterator_concept = input_iterator_tag; - using iterator_category - = __detail::__clamp_iter_cat<__base_cat, random_access_iterator_tag>; - using value_type = iter_value_t<_Iterator>; - using difference_type = iter_difference_t<_Iterator>; - using pointer = _Iterator; - using reference = iter_rvalue_reference_t<_Iterator>; -#else - typedef typename __traits_type::iterator_category iterator_category; - typedef typename __traits_type::value_type value_type; - typedef typename __traits_type::difference_type difference_type; - // NB: DR 680. - typedef _Iterator pointer; - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2106. move_iterator wrapping iterators returning prvalues - typedef typename conditional::value, - typename remove_reference<__base_ref>::type&&, - __base_ref>::type reference; -#endif - - _GLIBCXX17_CONSTEXPR - move_iterator() - : _M_current() { } - - explicit _GLIBCXX17_CONSTEXPR - move_iterator(iterator_type __i) - : _M_current(std::move(__i)) { } - - template - _GLIBCXX17_CONSTEXPR - move_iterator(const move_iterator<_Iter>& __i) - : _M_current(__i.base()) { } - -#if __cplusplus <= 201703L - _GLIBCXX17_CONSTEXPR iterator_type - base() const - { return _M_current; } -#else - constexpr iterator_type - base() const & -#if __cpp_lib_concepts - requires copy_constructible -#endif - { return _M_current; } - - constexpr iterator_type - base() && - { return std::move(_M_current); } -#endif - - _GLIBCXX17_CONSTEXPR reference - operator*() const -#if __cplusplus > 201703L && __cpp_lib_concepts - { return ranges::iter_move(_M_current); } -#else - { return static_cast(*_M_current); } -#endif - - _GLIBCXX17_CONSTEXPR pointer - operator->() const - { return _M_current; } - - _GLIBCXX17_CONSTEXPR move_iterator& - operator++() - { - ++_M_current; - return *this; - } - - _GLIBCXX17_CONSTEXPR move_iterator - operator++(int) - { - move_iterator __tmp = *this; - ++_M_current; - return __tmp; - } - -#if __cpp_lib_concepts - constexpr void - operator++(int) requires (!forward_iterator<_Iterator>) - { ++_M_current; } -#endif - - _GLIBCXX17_CONSTEXPR move_iterator& - operator--() - { - --_M_current; - return *this; - } - - _GLIBCXX17_CONSTEXPR move_iterator - operator--(int) - { - move_iterator __tmp = *this; - --_M_current; - return __tmp; - } - - _GLIBCXX17_CONSTEXPR move_iterator - operator+(difference_type __n) const - { return move_iterator(_M_current + __n); } - - _GLIBCXX17_CONSTEXPR move_iterator& - operator+=(difference_type __n) - { - _M_current += __n; - return *this; - } - - _GLIBCXX17_CONSTEXPR move_iterator - operator-(difference_type __n) const - { return move_iterator(_M_current - __n); } - - _GLIBCXX17_CONSTEXPR move_iterator& - operator-=(difference_type __n) - { - _M_current -= __n; - return *this; - } - - _GLIBCXX17_CONSTEXPR reference - operator[](difference_type __n) const -#if __cplusplus > 201703L && __cpp_lib_concepts - { return ranges::iter_move(_M_current + __n); } -#else - { return std::move(_M_current[__n]); } -#endif - -#if __cplusplus > 201703L && __cpp_lib_concepts - template _Sent> - friend constexpr bool - operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) - { return __x.base() == __y.base(); } - - template _Sent> - friend constexpr iter_difference_t<_Iterator> - operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) - { return __x.base() - __y.base(); } - - template _Sent> - friend constexpr iter_difference_t<_Iterator> - operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) - { return __x.base() - __y.base(); } - - friend constexpr iter_rvalue_reference_t<_Iterator> - iter_move(const move_iterator& __i) - noexcept(noexcept(ranges::iter_move(__i._M_current))) - { return ranges::iter_move(__i._M_current); } - - template _Iter2> - friend constexpr void - iter_swap(const move_iterator& __x, const move_iterator<_Iter2>& __y) - noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) - { return ranges::iter_swap(__x._M_current, __y._M_current); } -#endif // C++20 - }; - - template - inline _GLIBCXX17_CONSTEXPR bool - operator==(const move_iterator<_IteratorL>& __x, - const move_iterator<_IteratorR>& __y) -#if __cplusplus > 201703L && __cpp_lib_concepts - requires requires { { __x.base() == __y.base() } -> convertible_to; } -#endif - { return __x.base() == __y.base(); } - -#if __cpp_lib_three_way_comparison - template _IteratorR> - constexpr compare_three_way_result_t<_IteratorL, _IteratorR> - operator<=>(const move_iterator<_IteratorL>& __x, - const move_iterator<_IteratorR>& __y) - { return __x.base() <=> __y.base(); } -#else - template - inline _GLIBCXX17_CONSTEXPR bool - operator!=(const move_iterator<_IteratorL>& __x, - const move_iterator<_IteratorR>& __y) - { return !(__x == __y); } -#endif - - template - inline _GLIBCXX17_CONSTEXPR bool - operator<(const move_iterator<_IteratorL>& __x, - const move_iterator<_IteratorR>& __y) -#if __cplusplus > 201703L && __cpp_lib_concepts - requires requires { { __x.base() < __y.base() } -> convertible_to; } -#endif - { return __x.base() < __y.base(); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator<=(const move_iterator<_IteratorL>& __x, - const move_iterator<_IteratorR>& __y) -#if __cplusplus > 201703L && __cpp_lib_concepts - requires requires { { __y.base() < __x.base() } -> convertible_to; } -#endif - { return !(__y < __x); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator>(const move_iterator<_IteratorL>& __x, - const move_iterator<_IteratorR>& __y) -#if __cplusplus > 201703L && __cpp_lib_concepts - requires requires { { __y.base() < __x.base() } -> convertible_to; } -#endif - { return __y < __x; } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator>=(const move_iterator<_IteratorL>& __x, - const move_iterator<_IteratorR>& __y) -#if __cplusplus > 201703L && __cpp_lib_concepts - requires requires { { __x.base() < __y.base() } -> convertible_to; } -#endif - { return !(__x < __y); } - -#if ! (__cplusplus > 201703L && __cpp_lib_concepts) - // Note: See __normal_iterator operators note from Gaby to understand - // why we have these extra overloads for some move_iterator operators. - - // These extra overloads are not needed in C++20, because the ones above - // are constrained with a requires-clause and so overload resolution will - // prefer them to greedy unconstrained function templates. - - template - inline _GLIBCXX17_CONSTEXPR bool - operator==(const move_iterator<_Iterator>& __x, - const move_iterator<_Iterator>& __y) - { return __x.base() == __y.base(); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator!=(const move_iterator<_Iterator>& __x, - const move_iterator<_Iterator>& __y) - { return !(__x == __y); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator<(const move_iterator<_Iterator>& __x, - const move_iterator<_Iterator>& __y) - { return __x.base() < __y.base(); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator<=(const move_iterator<_Iterator>& __x, - const move_iterator<_Iterator>& __y) - { return !(__y < __x); } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator>(const move_iterator<_Iterator>& __x, - const move_iterator<_Iterator>& __y) - { return __y < __x; } - - template - inline _GLIBCXX17_CONSTEXPR bool - operator>=(const move_iterator<_Iterator>& __x, - const move_iterator<_Iterator>& __y) - { return !(__x < __y); } -#endif // ! C++20 - - // DR 685. - template - inline _GLIBCXX17_CONSTEXPR auto - operator-(const move_iterator<_IteratorL>& __x, - const move_iterator<_IteratorR>& __y) - -> decltype(__x.base() - __y.base()) - { return __x.base() - __y.base(); } - - template - inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> - operator+(typename move_iterator<_Iterator>::difference_type __n, - const move_iterator<_Iterator>& __x) - { return __x + __n; } - - template - inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> - make_move_iterator(_Iterator __i) - { return move_iterator<_Iterator>(std::move(__i)); } - - template::value_type>::value, - _Iterator, move_iterator<_Iterator>>::type> - inline _GLIBCXX17_CONSTEXPR _ReturnType - __make_move_if_noexcept_iterator(_Iterator __i) - { return _ReturnType(__i); } - - // Overload for pointers that matches std::move_if_noexcept more closely, - // returning a constant iterator when we don't want to move. - template::value, - const _Tp*, move_iterator<_Tp*>>::type> - inline _GLIBCXX17_CONSTEXPR _ReturnType - __make_move_if_noexcept_iterator(_Tp* __i) - { return _ReturnType(__i); } - -#if __cplusplus > 201703L && __cpp_lib_concepts - // [iterators.common] Common iterators - - namespace __detail - { - template - concept __common_iter_has_arrow = indirectly_readable - && (requires(const _It& __it) { __it.operator->(); } - || is_reference_v> - || constructible_from, iter_reference_t<_It>>); - - } // namespace __detail - - /// An iterator/sentinel adaptor for representing a non-common range. - template _Sent> - requires (!same_as<_It, _Sent>) && copyable<_It> - class common_iterator - { - template - static constexpr bool - _S_noexcept1() - { - if constexpr (is_trivially_default_constructible_v<_Tp>) - return is_nothrow_assignable_v<_Tp, _Up>; - else - return is_nothrow_constructible_v<_Tp, _Up>; - } - - template - static constexpr bool - _S_noexcept() - { return _S_noexcept1<_It, _It2>() && _S_noexcept1<_Sent, _Sent2>(); } - - class _Proxy - { - iter_value_t<_It> _M_keep; - - _Proxy(iter_reference_t<_It>&& __x) - : _M_keep(std::move(__x)) { } - - friend class common_iterator; - - public: - const iter_value_t<_It>* - operator->() const - { return std::__addressof(_M_keep); } - }; - - public: - constexpr - common_iterator() - noexcept(is_nothrow_default_constructible_v<_It>) - : _M_it(), _M_index(0) - { } - - constexpr - common_iterator(_It __i) - noexcept(is_nothrow_move_constructible_v<_It>) - : _M_it(std::move(__i)), _M_index(0) - { } - - constexpr - common_iterator(_Sent __s) - noexcept(is_nothrow_move_constructible_v<_Sent>) - : _M_sent(std::move(__s)), _M_index(1) - { } - - template - requires convertible_to - && convertible_to - constexpr - common_iterator(const common_iterator<_It2, _Sent2>& __x) - noexcept(_S_noexcept()) - : _M_valueless(), _M_index(__x._M_index) - { - if (_M_index == 0) - { - if constexpr (is_trivially_default_constructible_v<_It>) - _M_it = std::move(__x._M_it); - else - ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); - } - else if (_M_index == 1) - { - if constexpr (is_trivially_default_constructible_v<_Sent>) - _M_sent = std::move(__x._M_sent); - else - ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); - } - } - - constexpr - common_iterator(const common_iterator& __x) - noexcept(_S_noexcept()) - : _M_valueless(), _M_index(__x._M_index) - { - if (_M_index == 0) - { - if constexpr (is_trivially_default_constructible_v<_It>) - _M_it = std::move(__x._M_it); - else - ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); - } - else if (_M_index == 1) - { - if constexpr (is_trivially_default_constructible_v<_Sent>) - _M_sent = std::move(__x._M_sent); - else - ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); - } - } - - common_iterator& - operator=(const common_iterator& __x) - noexcept(is_nothrow_copy_assignable_v<_It> - && is_nothrow_copy_assignable_v<_Sent> - && is_nothrow_copy_constructible_v<_It> - && is_nothrow_copy_constructible_v<_Sent>) - { - return this->operator=<_It, _Sent>(__x); - } - - template - requires convertible_to - && convertible_to - && assignable_from<_It&, const _It2&> - && assignable_from<_Sent&, const _Sent2&> - common_iterator& - operator=(const common_iterator<_It2, _Sent2>& __x) - noexcept(is_nothrow_constructible_v<_It, const _It2&> - && is_nothrow_constructible_v<_Sent, const _Sent2&> - && is_nothrow_assignable_v<_It, const _It2&> - && is_nothrow_assignable_v<_Sent, const _Sent2&>) - { - switch(_M_index << 2 | __x._M_index) - { - case 0b0000: - _M_it = __x._M_it; - break; - case 0b0101: - _M_sent = __x._M_sent; - break; - case 0b0001: - _M_it.~_It(); - _M_index = -1; - [[fallthrough]]; - case 0b1001: - ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); - _M_index = 1; - break; - case 0b0100: - _M_sent.~_Sent(); - _M_index = -1; - [[fallthrough]]; - case 0b1000: - ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); - _M_index = 0; - break; - default: - __glibcxx_assert(__x._M_has_value()); - __builtin_unreachable(); - } - return *this; - } - - ~common_iterator() - { - switch (_M_index) - { - case 0: - _M_it.~_It(); - break; - case 1: - _M_sent.~_Sent(); - break; - } - } - - decltype(auto) - operator*() - { - __glibcxx_assert(_M_index == 0); - return *_M_it; - } - - decltype(auto) - operator*() const requires __detail::__dereferenceable - { - __glibcxx_assert(_M_index == 0); - return *_M_it; - } - - decltype(auto) - operator->() const requires __detail::__common_iter_has_arrow<_It> - { - __glibcxx_assert(_M_index == 0); - if constexpr (is_pointer_v<_It> || requires { _M_it.operator->(); }) - return _M_it; - else if constexpr (is_reference_v>) - { - auto&& __tmp = *_M_it; - return std::__addressof(__tmp); - } - else - return _Proxy{*_M_it}; - } - - common_iterator& - operator++() - { - __glibcxx_assert(_M_index == 0); - ++_M_it; - return *this; - } - - decltype(auto) - operator++(int) - { - __glibcxx_assert(_M_index == 0); - if constexpr (forward_iterator<_It>) - { - common_iterator __tmp = *this; - ++*this; - return __tmp; - } - else - return _M_it++; - } - - template _Sent2> - requires sentinel_for<_Sent, _It2> - friend bool - operator==(const common_iterator& __x, - const common_iterator<_It2, _Sent2>& __y) - { - switch(__x._M_index << 2 | __y._M_index) - { - case 0b0000: - case 0b0101: - return true; - case 0b0001: - return __x._M_it == __y._M_sent; - case 0b0100: - return __x._M_sent == __y._M_it; - default: - __glibcxx_assert(__x._M_has_value()); - __glibcxx_assert(__y._M_has_value()); - __builtin_unreachable(); - } - } - - template _Sent2> - requires sentinel_for<_Sent, _It2> && equality_comparable_with<_It, _It2> - friend bool - operator==(const common_iterator& __x, - const common_iterator<_It2, _Sent2>& __y) - { - switch(__x._M_index << 2 | __y._M_index) - { - case 0b0101: - return true; - case 0b0000: - return __x._M_it == __y._M_it; - case 0b0001: - return __x._M_it == __y._M_sent; - case 0b0100: - return __x._M_sent == __y._M_it; - default: - __glibcxx_assert(__x._M_has_value()); - __glibcxx_assert(__y._M_has_value()); - __builtin_unreachable(); - } - } - - template _It2, sized_sentinel_for<_It> _Sent2> - requires sized_sentinel_for<_Sent, _It2> - friend iter_difference_t<_It2> - operator-(const common_iterator& __x, - const common_iterator<_It2, _Sent2>& __y) - { - switch(__x._M_index << 2 | __y._M_index) - { - case 0b0101: - return 0; - case 0b0000: - return __x._M_it - __y._M_it; - case 0b0001: - return __x._M_it - __y._M_sent; - case 0b0100: - return __x._M_sent - __y._M_it; - default: - __glibcxx_assert(__x._M_has_value()); - __glibcxx_assert(__y._M_has_value()); - __builtin_unreachable(); - } - } - - friend iter_rvalue_reference_t<_It> - iter_move(const common_iterator& __i) - noexcept(noexcept(ranges::iter_move(std::declval()))) - requires input_iterator<_It> - { - __glibcxx_assert(__i._M_index == 0); - return ranges::iter_move(__i._M_it); - } - - template _It2, typename _Sent2> - friend void - iter_swap(const common_iterator& __x, - const common_iterator<_It2, _Sent2>& __y) - noexcept(noexcept(ranges::iter_swap(std::declval(), - std::declval()))) - { - __glibcxx_assert(__x._M_index == 0); - __glibcxx_assert(__y._M_index == 0); - return ranges::iter_swap(__x._M_it, __y._M_it); - } - - private: - template _Sent2> - friend class common_iterator; - - bool _M_has_value() const noexcept { return _M_index < 2; } - - union - { - _It _M_it; - _Sent _M_sent; - unsigned char _M_valueless; - }; - unsigned char _M_index; // 0==_M_it, 1==_M_sent, 2==valueless - }; - - template - struct incrementable_traits> - { - using difference_type = iter_difference_t<_It>; - }; - - namespace __detail - { - // FIXME: This has to be at namespace-scope because of PR 92103. - template - struct __common_iter_ptr - { - using type = void; - }; - - template - requires __detail::__common_iter_has_arrow<_It> - struct __common_iter_ptr<_It, _Sent> - { - using common_iterator = std::common_iterator<_It, _Sent>; - - using type - = decltype(std::declval().operator->()); - }; - } // namespace __detail - - template - struct iterator_traits> - { - using iterator_concept = conditional_t, - forward_iterator_tag, input_iterator_tag>; - using iterator_category = __detail::__clamp_iter_cat< - typename iterator_traits<_It>::iterator_category, - forward_iterator_tag, input_iterator_tag>; - using value_type = iter_value_t<_It>; - using difference_type = iter_difference_t<_It>; - using pointer = typename __detail::__common_iter_ptr<_It, _Sent>::type; - using reference = iter_reference_t<_It>; - }; - - // [iterators.counted] Counted iterators - - /// An iterator adaptor that keeps track of the distance to the end. - template - class counted_iterator - { - public: - using iterator_type = _It; - - constexpr counted_iterator() = default; - - constexpr - counted_iterator(_It __i, iter_difference_t<_It> __n) - : _M_current(std::move(__i)), _M_length(__n) - { __glibcxx_assert(__n >= 0); } - - template - requires convertible_to - constexpr - counted_iterator(const counted_iterator<_It2>& __x) - : _M_current(__x._M_current), _M_length(__x._M_length) - { } - - template - requires assignable_from<_It&, const _It2&> - constexpr counted_iterator& - operator=(const counted_iterator<_It2>& __x) - { - _M_current = __x._M_current; - _M_length = __x._M_length; - return *this; - } - - constexpr _It - base() const & - noexcept(is_nothrow_copy_constructible_v<_It>) - requires copy_constructible<_It> - { return _M_current; } - - constexpr _It - base() && - noexcept(is_nothrow_move_constructible_v<_It>) - { return std::move(_M_current); } - - constexpr iter_difference_t<_It> - count() const noexcept { return _M_length; } - - constexpr decltype(auto) - operator*() - noexcept(noexcept(*_M_current)) - { return *_M_current; } - - constexpr decltype(auto) - operator*() const - noexcept(noexcept(*_M_current)) - requires __detail::__dereferenceable - { return *_M_current; } - - constexpr counted_iterator& - operator++() - { - __glibcxx_assert(_M_length > 0); - ++_M_current; - --_M_length; - return *this; - } - - decltype(auto) - operator++(int) - { - __glibcxx_assert(_M_length > 0); - --_M_length; - __try - { - return _M_current++; - } __catch(...) { - ++_M_length; - __throw_exception_again; - } - - } - - constexpr counted_iterator - operator++(int) requires forward_iterator<_It> - { - auto __tmp = *this; - ++*this; - return __tmp; - } - - constexpr counted_iterator& - operator--() requires bidirectional_iterator<_It> - { - --_M_current; - ++_M_length; - return *this; - } - - constexpr counted_iterator - operator--(int) requires bidirectional_iterator<_It> - { - auto __tmp = *this; - --*this; - return __tmp; - } - - constexpr counted_iterator - operator+(iter_difference_t<_It> __n) const - requires random_access_iterator<_It> - { return counted_iterator(_M_current + __n, _M_length - __n); } - - friend constexpr counted_iterator - operator+(iter_difference_t<_It> __n, const counted_iterator& __x) - requires random_access_iterator<_It> - { return __x + __n; } - - constexpr counted_iterator& - operator+=(iter_difference_t<_It> __n) - requires random_access_iterator<_It> - { - __glibcxx_assert(__n <= _M_length); - _M_current += __n; - _M_length -= __n; - return *this; - } - - constexpr counted_iterator - operator-(iter_difference_t<_It> __n) const - requires random_access_iterator<_It> - { return counted_iterator(_M_current - __n, _M_length + __n); } - - template _It2> - friend constexpr iter_difference_t<_It2> - operator-(const counted_iterator& __x, - const counted_iterator<_It2>& __y) - { return __y._M_length - __x._M_length; } - - friend constexpr iter_difference_t<_It> - operator-(const counted_iterator& __x, default_sentinel_t) - { return -__x._M_length; } - - friend constexpr iter_difference_t<_It> - operator-(default_sentinel_t, const counted_iterator& __y) - { return __y._M_length; } - - constexpr counted_iterator& - operator-=(iter_difference_t<_It> __n) - requires random_access_iterator<_It> - { - __glibcxx_assert(-__n <= _M_length); - _M_current -= __n; - _M_length += __n; - return *this; - } - - constexpr decltype(auto) - operator[](iter_difference_t<_It> __n) const - noexcept(noexcept(_M_current[__n])) - requires random_access_iterator<_It> - { - __glibcxx_assert(__n < _M_length); - return _M_current[__n]; - } - - template _It2> - friend constexpr bool - operator==(const counted_iterator& __x, - const counted_iterator<_It2>& __y) - { return __x._M_length == __y._M_length; } - - friend constexpr bool - operator==(const counted_iterator& __x, default_sentinel_t) - { return __x._M_length == 0; } - - template _It2> - friend constexpr strong_ordering - operator<=>(const counted_iterator& __x, - const counted_iterator<_It2>& __y) - { return __y._M_length <=> __x._M_length; } - - private: - template friend class counted_iterator; - - _It _M_current = _It(); - iter_difference_t<_It> _M_length = 0; - - friend constexpr iter_rvalue_reference_t<_It> - iter_move(const counted_iterator& __i) - noexcept(noexcept(ranges::iter_move(__i._M_current))) - requires input_iterator<_It> - { return ranges::iter_move(__i._M_current); } - - template _It2> - friend constexpr void - iter_swap(const counted_iterator& __x, - const counted_iterator<_It2>& __y) - noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) - { ranges::iter_swap(__x._M_current, __y._M_current); } - }; - - template - struct incrementable_traits> - { - using difference_type = iter_difference_t<_It>; - }; - - template - struct iterator_traits> : iterator_traits<_It> - { - using pointer = void; - }; -#endif // C++20 - - // @} group iterators - - template - auto - __niter_base(move_iterator<_Iterator> __it) - -> decltype(make_move_iterator(__niter_base(__it.base()))) - { return make_move_iterator(__niter_base(__it.base())); } - - template - struct __is_move_iterator > - { - enum { __value = 1 }; - typedef __true_type __type; - }; - - template - auto - __miter_base(move_iterator<_Iterator> __it) - -> decltype(__miter_base(__it.base())) - { return __miter_base(__it.base()); } - -#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter) -#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) \ - std::__make_move_if_noexcept_iterator(_Iter) -#else -#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) (_Iter) -#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter) -#endif // C++11 - -#if __cpp_deduction_guides >= 201606 - // These helper traits are used for deduction guides - // of associative containers. - template - using __iter_key_t = remove_const_t< - typename iterator_traits<_InputIterator>::value_type::first_type>; - - template - using __iter_val_t = - typename iterator_traits<_InputIterator>::value_type::second_type; - - template - struct pair; - - template - using __iter_to_alloc_t = - pair>, - __iter_val_t<_InputIterator>>; -#endif // __cpp_deduction_guides - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h deleted file mode 100644 index 076b7781c..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h +++ /dev/null @@ -1,239 +0,0 @@ -// Functions used by iterators -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996-1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_iterator_base_funcs.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iterator} - * - * This file contains all of the general iterator-related utility - * functions, such as distance() and advance(). - */ - -#ifndef _STL_ITERATOR_BASE_FUNCS_H -#define _STL_ITERATOR_BASE_FUNCS_H 1 - -#pragma GCC system_header - -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - // Forward declaration for the overloads of __distance. - template struct _List_iterator; - template struct _List_const_iterator; -_GLIBCXX_END_NAMESPACE_CONTAINER - - template - inline _GLIBCXX14_CONSTEXPR - typename iterator_traits<_InputIterator>::difference_type - __distance(_InputIterator __first, _InputIterator __last, - input_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - - typename iterator_traits<_InputIterator>::difference_type __n = 0; - while (__first != __last) - { - ++__first; - ++__n; - } - return __n; - } - - template - inline _GLIBCXX14_CONSTEXPR - typename iterator_traits<_RandomAccessIterator>::difference_type - __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, - random_access_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_RandomAccessIteratorConcept< - _RandomAccessIterator>) - return __last - __first; - } - -#if _GLIBCXX_USE_CXX11_ABI - // Forward declaration because of the qualified call in distance. - template - ptrdiff_t - __distance(_GLIBCXX_STD_C::_List_iterator<_Tp>, - _GLIBCXX_STD_C::_List_iterator<_Tp>, - input_iterator_tag); - - template - ptrdiff_t - __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>, - _GLIBCXX_STD_C::_List_const_iterator<_Tp>, - input_iterator_tag); -#endif - - /** - * @brief A generalization of pointer arithmetic. - * @param __first An input iterator. - * @param __last An input iterator. - * @return The distance between them. - * - * Returns @c n such that __first + n == __last. This requires - * that @p __last must be reachable from @p __first. Note that @c - * n may be negative. - * - * For random access iterators, this uses their @c + and @c - operations - * and are constant time. For other %iterator classes they are linear time. - */ - template - inline _GLIBCXX17_CONSTEXPR - typename iterator_traits<_InputIterator>::difference_type - distance(_InputIterator __first, _InputIterator __last) - { - // concept requirements -- taken care of in __distance - return std::__distance(__first, __last, - std::__iterator_category(__first)); - } - - template - inline _GLIBCXX14_CONSTEXPR void - __advance(_InputIterator& __i, _Distance __n, input_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_assert(__n >= 0); - while (__n--) - ++__i; - } - - template - inline _GLIBCXX14_CONSTEXPR void - __advance(_BidirectionalIterator& __i, _Distance __n, - bidirectional_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator>) - if (__n > 0) - while (__n--) - ++__i; - else - while (__n++) - --__i; - } - - template - inline _GLIBCXX14_CONSTEXPR void - __advance(_RandomAccessIterator& __i, _Distance __n, - random_access_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_RandomAccessIteratorConcept< - _RandomAccessIterator>) - if (__builtin_constant_p(__n) && __n == 1) - ++__i; - else if (__builtin_constant_p(__n) && __n == -1) - --__i; - else - __i += __n; - } - - /** - * @brief A generalization of pointer arithmetic. - * @param __i An input iterator. - * @param __n The @a delta by which to change @p __i. - * @return Nothing. - * - * This increments @p i by @p n. For bidirectional and random access - * iterators, @p __n may be negative, in which case @p __i is decremented. - * - * For random access iterators, this uses their @c + and @c - operations - * and are constant time. For other %iterator classes they are linear time. - */ - template - inline _GLIBCXX17_CONSTEXPR void - advance(_InputIterator& __i, _Distance __n) - { - // concept requirements -- taken care of in __advance - typename iterator_traits<_InputIterator>::difference_type __d = __n; - std::__advance(__i, __d, std::__iterator_category(__i)); - } - -#if __cplusplus >= 201103L - - template - inline _GLIBCXX17_CONSTEXPR _InputIterator - next(_InputIterator __x, typename - iterator_traits<_InputIterator>::difference_type __n = 1) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - std::advance(__x, __n); - return __x; - } - - template - inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator - prev(_BidirectionalIterator __x, typename - iterator_traits<_BidirectionalIterator>::difference_type __n = 1) - { - // concept requirements - __glibcxx_function_requires(_BidirectionalIteratorConcept< - _BidirectionalIterator>) - std::advance(__x, -__n); - return __x; - } - -#endif // C++11 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _STL_ITERATOR_BASE_FUNCS_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h deleted file mode 100644 index aa02af59d..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h +++ /dev/null @@ -1,271 +0,0 @@ -// Types used in iterator implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996-1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_iterator_base_types.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{iterator} - * - * This file contains all of the general iterator-related utility types, - * such as iterator_traits and struct iterator. - */ - -#ifndef _STL_ITERATOR_BASE_TYPES_H -#define _STL_ITERATOR_BASE_TYPES_H 1 - -#pragma GCC system_header - -#include - -#if __cplusplus >= 201103L -# include // For __void_t, is_convertible -#endif - -#if __cplusplus > 201703L && __cpp_concepts >= 201907L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup iterators Iterators - * Abstractions for uniform iterating through various underlying types. - */ - //@{ - - /** - * @defgroup iterator_tags Iterator Tags - * These are empty types, used to distinguish different iterators. The - * distinction is not made by what they contain, but simply by what they - * are. Different underlying algorithms can then be used based on the - * different operations supported by different iterator types. - */ - //@{ - /// Marking input iterators. - struct input_iterator_tag { }; - - /// Marking output iterators. - struct output_iterator_tag { }; - - /// Forward iterators support a superset of input iterator operations. - struct forward_iterator_tag : public input_iterator_tag { }; - - /// Bidirectional iterators support a superset of forward iterator - /// operations. - struct bidirectional_iterator_tag : public forward_iterator_tag { }; - - /// Random-access iterators support a superset of bidirectional - /// iterator operations. - struct random_access_iterator_tag : public bidirectional_iterator_tag { }; - -#if __cplusplus > 201703L - /// Contiguous iterators point to objects stored contiguously in memory. - struct contiguous_iterator_tag : public random_access_iterator_tag { }; -#endif - //@} - - /** - * @brief Common %iterator class. - * - * This class does nothing but define nested typedefs. %Iterator classes - * can inherit from this class to save some work. The typedefs are then - * used in specializations and overloading. - * - * In particular, there are no default implementations of requirements - * such as @c operator++ and the like. (How could there be?) - */ - template - struct iterator - { - /// One of the @link iterator_tags tag types@endlink. - typedef _Category iterator_category; - /// The type "pointed to" by the iterator. - typedef _Tp value_type; - /// Distance between iterators is represented as this type. - typedef _Distance difference_type; - /// This type represents a pointer-to-value_type. - typedef _Pointer pointer; - /// This type represents a reference-to-value_type. - typedef _Reference reference; - }; - - /** - * @brief Traits class for iterators. - * - * This class does nothing but define nested typedefs. The general - * version simply @a forwards the nested typedefs from the Iterator - * argument. Specialized versions for pointers and pointers-to-const - * provide tighter, more correct semantics. - */ - template - struct iterator_traits; - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14 - template> - struct __iterator_traits { }; - -#if ! __cpp_lib_concepts - - template - struct __iterator_traits<_Iterator, - __void_t> - { - typedef typename _Iterator::iterator_category iterator_category; - typedef typename _Iterator::value_type value_type; - typedef typename _Iterator::difference_type difference_type; - typedef typename _Iterator::pointer pointer; - typedef typename _Iterator::reference reference; - }; -#endif // ! concepts - - template - struct iterator_traits - : public __iterator_traits<_Iterator> { }; - -#else // ! C++11 - template - struct iterator_traits - { - typedef typename _Iterator::iterator_category iterator_category; - typedef typename _Iterator::value_type value_type; - typedef typename _Iterator::difference_type difference_type; - typedef typename _Iterator::pointer pointer; - typedef typename _Iterator::reference reference; - }; -#endif // C++11 - -#if __cplusplus > 201703L - /// Partial specialization for object pointer types. - template -#if __cpp_concepts >= 201907L - requires is_object_v<_Tp> -#endif - struct iterator_traits<_Tp*> - { - using iterator_concept = contiguous_iterator_tag; - using iterator_category = random_access_iterator_tag; - using value_type = remove_cv_t<_Tp>; - using difference_type = ptrdiff_t; - using pointer = _Tp*; - using reference = _Tp&; - }; -#else - /// Partial specialization for pointer types. - template - struct iterator_traits<_Tp*> - { - typedef random_access_iterator_tag iterator_category; - typedef _Tp value_type; - typedef ptrdiff_t difference_type; - typedef _Tp* pointer; - typedef _Tp& reference; - }; - - /// Partial specialization for const pointer types. - template - struct iterator_traits - { - typedef random_access_iterator_tag iterator_category; - typedef _Tp value_type; - typedef ptrdiff_t difference_type; - typedef const _Tp* pointer; - typedef const _Tp& reference; - }; -#endif - - /** - * This function is not a part of the C++ standard but is syntactic - * sugar for internal library use only. - */ - template - inline _GLIBCXX_CONSTEXPR - typename iterator_traits<_Iter>::iterator_category - __iterator_category(const _Iter&) - { return typename iterator_traits<_Iter>::iterator_category(); } - - //@} - -#if __cplusplus >= 201103L - template - using __iterator_category_t - = typename iterator_traits<_Iter>::iterator_category; - - template - using _RequireInputIter = - __enable_if_t, - input_iterator_tag>::value>; - - template> - struct __is_random_access_iter - : is_base_of - { - typedef is_base_of _Base; - enum { __value = _Base::value }; - }; -#else - template, - typename _Cat = typename _Traits::iterator_category> - struct __is_random_access_iter - { enum { __value = __is_base_of(random_access_iterator_tag, _Cat) }; }; -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _STL_ITERATOR_BASE_TYPES_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_list.h b/resources/sources/avr-libstdcpp/include/bits/stl_list.h deleted file mode 100644 index e7135e3e7..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_list.h +++ /dev/null @@ -1,2127 +0,0 @@ -// List implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_list.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{list} - */ - -#ifndef _STL_LIST_H -#define _STL_LIST_H 1 - -#include -#include -#if __cplusplus >= 201103L -#include -#include -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - namespace __detail - { - // Supporting structures are split into common and templated - // types; the latter publicly inherits from the former in an - // effort to reduce code duplication. This results in some - // "needless" static_cast'ing later on, but it's all safe - // downcasting. - - /// Common part of a node in the %list. - struct _List_node_base - { - _List_node_base* _M_next; - _List_node_base* _M_prev; - - static void - swap(_List_node_base& __x, _List_node_base& __y) _GLIBCXX_USE_NOEXCEPT; - - void - _M_transfer(_List_node_base* const __first, - _List_node_base* const __last) _GLIBCXX_USE_NOEXCEPT; - - void - _M_reverse() _GLIBCXX_USE_NOEXCEPT; - - void - _M_hook(_List_node_base* const __position) _GLIBCXX_USE_NOEXCEPT; - - void - _M_unhook() _GLIBCXX_USE_NOEXCEPT; - }; - - /// The %list node header. - struct _List_node_header : public _List_node_base - { -#if _GLIBCXX_USE_CXX11_ABI - std::size_t _M_size; -#endif - - _List_node_header() _GLIBCXX_NOEXCEPT - { _M_init(); } - -#if __cplusplus >= 201103L - _List_node_header(_List_node_header&& __x) noexcept - : _List_node_base{ __x._M_next, __x._M_prev } -# if _GLIBCXX_USE_CXX11_ABI - , _M_size(__x._M_size) -# endif - { - if (__x._M_base()->_M_next == __x._M_base()) - this->_M_next = this->_M_prev = this; - else - { - this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base(); - __x._M_init(); - } - } - - void - _M_move_nodes(_List_node_header&& __x) - { - _List_node_base* const __xnode = __x._M_base(); - if (__xnode->_M_next == __xnode) - _M_init(); - else - { - _List_node_base* const __node = this->_M_base(); - __node->_M_next = __xnode->_M_next; - __node->_M_prev = __xnode->_M_prev; - __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node; -# if _GLIBCXX_USE_CXX11_ABI - _M_size = __x._M_size; -# endif - __x._M_init(); - } - } -#endif - - void - _M_init() _GLIBCXX_NOEXCEPT - { - this->_M_next = this->_M_prev = this; -#if _GLIBCXX_USE_CXX11_ABI - this->_M_size = 0; -#endif - } - - private: - _List_node_base* _M_base() { return this; } - }; - } // namespace detail - -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - /// An actual node in the %list. - template - struct _List_node : public __detail::_List_node_base - { -#if __cplusplus >= 201103L - __gnu_cxx::__aligned_membuf<_Tp> _M_storage; - _Tp* _M_valptr() { return _M_storage._M_ptr(); } - _Tp const* _M_valptr() const { return _M_storage._M_ptr(); } -#else - _Tp _M_data; - _Tp* _M_valptr() { return std::__addressof(_M_data); } - _Tp const* _M_valptr() const { return std::__addressof(_M_data); } -#endif - }; - - /** - * @brief A list::iterator. - * - * All the functions are op overloads. - */ - template - struct _List_iterator - { - typedef _List_iterator<_Tp> _Self; - typedef _List_node<_Tp> _Node; - - typedef ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - typedef _Tp value_type; - typedef _Tp* pointer; - typedef _Tp& reference; - - _List_iterator() _GLIBCXX_NOEXCEPT - : _M_node() { } - - explicit - _List_iterator(__detail::_List_node_base* __x) _GLIBCXX_NOEXCEPT - : _M_node(__x) { } - - _Self - _M_const_cast() const _GLIBCXX_NOEXCEPT - { return *this; } - - // Must downcast from _List_node_base to _List_node to get to value. - reference - operator*() const _GLIBCXX_NOEXCEPT - { return *static_cast<_Node*>(_M_node)->_M_valptr(); } - - pointer - operator->() const _GLIBCXX_NOEXCEPT - { return static_cast<_Node*>(_M_node)->_M_valptr(); } - - _Self& - operator++() _GLIBCXX_NOEXCEPT - { - _M_node = _M_node->_M_next; - return *this; - } - - _Self - operator++(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - _M_node = _M_node->_M_next; - return __tmp; - } - - _Self& - operator--() _GLIBCXX_NOEXCEPT - { - _M_node = _M_node->_M_prev; - return *this; - } - - _Self - operator--(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - _M_node = _M_node->_M_prev; - return __tmp; - } - - friend bool - operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_node == __y._M_node; } - -#if __cpp_impl_three_way_comparison < 201907L - friend bool - operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_node != __y._M_node; } -#endif - - // The only member points to the %list element. - __detail::_List_node_base* _M_node; - }; - - /** - * @brief A list::const_iterator. - * - * All the functions are op overloads. - */ - template - struct _List_const_iterator - { - typedef _List_const_iterator<_Tp> _Self; - typedef const _List_node<_Tp> _Node; - typedef _List_iterator<_Tp> iterator; - - typedef ptrdiff_t difference_type; - typedef std::bidirectional_iterator_tag iterator_category; - typedef _Tp value_type; - typedef const _Tp* pointer; - typedef const _Tp& reference; - - _List_const_iterator() _GLIBCXX_NOEXCEPT - : _M_node() { } - - explicit - _List_const_iterator(const __detail::_List_node_base* __x) - _GLIBCXX_NOEXCEPT - : _M_node(__x) { } - - _List_const_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT - : _M_node(__x._M_node) { } - - iterator - _M_const_cast() const _GLIBCXX_NOEXCEPT - { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); } - - // Must downcast from List_node_base to _List_node to get to value. - reference - operator*() const _GLIBCXX_NOEXCEPT - { return *static_cast<_Node*>(_M_node)->_M_valptr(); } - - pointer - operator->() const _GLIBCXX_NOEXCEPT - { return static_cast<_Node*>(_M_node)->_M_valptr(); } - - _Self& - operator++() _GLIBCXX_NOEXCEPT - { - _M_node = _M_node->_M_next; - return *this; - } - - _Self - operator++(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - _M_node = _M_node->_M_next; - return __tmp; - } - - _Self& - operator--() _GLIBCXX_NOEXCEPT - { - _M_node = _M_node->_M_prev; - return *this; - } - - _Self - operator--(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - _M_node = _M_node->_M_prev; - return __tmp; - } - - friend bool - operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_node == __y._M_node; } - -#if __cpp_impl_three_way_comparison < 201907L - friend bool - operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_node != __y._M_node; } -#endif - - // The only member points to the %list element. - const __detail::_List_node_base* _M_node; - }; - -_GLIBCXX_BEGIN_NAMESPACE_CXX11 - /// See bits/stl_deque.h's _Deque_base for an explanation. - template - class _List_base - { - protected: - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_Tp>::other _Tp_alloc_type; - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tp_alloc_traits; - typedef typename _Tp_alloc_traits::template - rebind<_List_node<_Tp> >::other _Node_alloc_type; - typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; - -#if !_GLIBCXX_INLINE_VERSION - static size_t - _S_distance(const __detail::_List_node_base* __first, - const __detail::_List_node_base* __last) - { - size_t __n = 0; - while (__first != __last) - { - __first = __first->_M_next; - ++__n; - } - return __n; - } -#endif - - struct _List_impl - : public _Node_alloc_type - { - __detail::_List_node_header _M_node; - - _List_impl() _GLIBCXX_NOEXCEPT_IF( - is_nothrow_default_constructible<_Node_alloc_type>::value) - : _Node_alloc_type() - { } - - _List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT - : _Node_alloc_type(__a) - { } - -#if __cplusplus >= 201103L - _List_impl(_List_impl&&) = default; - - _List_impl(_Node_alloc_type&& __a, _List_impl&& __x) - : _Node_alloc_type(std::move(__a)), _M_node(std::move(__x._M_node)) - { } - - _List_impl(_Node_alloc_type&& __a) noexcept - : _Node_alloc_type(std::move(__a)) - { } -#endif - }; - - _List_impl _M_impl; - -#if _GLIBCXX_USE_CXX11_ABI - size_t _M_get_size() const { return _M_impl._M_node._M_size; } - - void _M_set_size(size_t __n) { _M_impl._M_node._M_size = __n; } - - void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; } - - void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; } - -# if !_GLIBCXX_INLINE_VERSION - size_t - _M_distance(const __detail::_List_node_base* __first, - const __detail::_List_node_base* __last) const - { return _S_distance(__first, __last); } - - // return the stored size - size_t _M_node_count() const { return _M_get_size(); } -# endif -#else - // dummy implementations used when the size is not stored - size_t _M_get_size() const { return 0; } - void _M_set_size(size_t) { } - void _M_inc_size(size_t) { } - void _M_dec_size(size_t) { } - -# if !_GLIBCXX_INLINE_VERSION - size_t _M_distance(const void*, const void*) const { return 0; } - - // count the number of nodes - size_t _M_node_count() const - { - return _S_distance(_M_impl._M_node._M_next, - std::__addressof(_M_impl._M_node)); - } -# endif -#endif - - typename _Node_alloc_traits::pointer - _M_get_node() - { return _Node_alloc_traits::allocate(_M_impl, 1); } - - void - _M_put_node(typename _Node_alloc_traits::pointer __p) _GLIBCXX_NOEXCEPT - { _Node_alloc_traits::deallocate(_M_impl, __p, 1); } - - public: - typedef _Alloc allocator_type; - - _Node_alloc_type& - _M_get_Node_allocator() _GLIBCXX_NOEXCEPT - { return _M_impl; } - - const _Node_alloc_type& - _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT - { return _M_impl; } - -#if __cplusplus >= 201103L - _List_base() = default; -#else - _List_base() { } -#endif - - _List_base(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT - : _M_impl(__a) - { } - -#if __cplusplus >= 201103L - _List_base(_List_base&&) = default; - -# if !_GLIBCXX_INLINE_VERSION - _List_base(_List_base&& __x, _Node_alloc_type&& __a) - : _M_impl(std::move(__a)) - { - if (__x._M_get_Node_allocator() == _M_get_Node_allocator()) - _M_move_nodes(std::move(__x)); - // else caller must move individual elements. - } -# endif - - // Used when allocator is_always_equal. - _List_base(_Node_alloc_type&& __a, _List_base&& __x) - : _M_impl(std::move(__a), std::move(__x._M_impl)) - { } - - // Used when allocator !is_always_equal. - _List_base(_Node_alloc_type&& __a) - : _M_impl(std::move(__a)) - { } - - void - _M_move_nodes(_List_base&& __x) - { _M_impl._M_node._M_move_nodes(std::move(__x._M_impl._M_node)); } -#endif - - // This is what actually destroys the list. - ~_List_base() _GLIBCXX_NOEXCEPT - { _M_clear(); } - - void - _M_clear() _GLIBCXX_NOEXCEPT; - - void - _M_init() _GLIBCXX_NOEXCEPT - { this->_M_impl._M_node._M_init(); } - }; - - /** - * @brief A standard container with linear time access to elements, - * and fixed time insertion/deletion at any point in the sequence. - * - * @ingroup sequences - * - * @tparam _Tp Type of element. - * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. - * - * Meets the requirements of a container, a - * reversible container, and a - * sequence, including the - * optional sequence requirements with the - * %exception of @c at and @c operator[]. - * - * This is a @e doubly @e linked %list. Traversal up and down the - * %list requires linear time, but adding and removing elements (or - * @e nodes) is done in constant time, regardless of where the - * change takes place. Unlike std::vector and std::deque, - * random-access iterators are not provided, so subscripting ( @c - * [] ) access is not allowed. For algorithms which only need - * sequential access, this lack makes no difference. - * - * Also unlike the other standard containers, std::list provides - * specialized algorithms %unique to linked lists, such as - * splicing, sorting, and in-place reversal. - * - * A couple points on memory allocation for list: - * - * First, we never actually allocate a Tp, we allocate - * List_node's and trust [20.1.5]/4 to DTRT. This is to ensure - * that after elements from %list are spliced into - * %list, destroying the memory of the second %list is a - * valid operation, i.e., Alloc1 giveth and Alloc2 taketh away. - * - * Second, a %list conceptually represented as - * @code - * A <---> B <---> C <---> D - * @endcode - * is actually circular; a link exists between A and D. The %list - * class holds (as its only data member) a private list::iterator - * pointing to @e D, not to @e A! To get to the head of the %list, - * we start at the tail and move forward by one. When this member - * iterator's next/previous pointers refer to itself, the %list is - * %empty. - */ - template > - class list : protected _List_base<_Tp, _Alloc> - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -# endif - __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) -#endif - -#if __cplusplus >= 201103L - static_assert(is_same::type, _Tp>::value, - "std::list must have a non-const, non-volatile value_type"); -# if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same::value, - "std::list must have the same value_type as its allocator"); -# endif -#endif - - typedef _List_base<_Tp, _Alloc> _Base; - typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; - typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits; - typedef typename _Base::_Node_alloc_type _Node_alloc_type; - typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; - - public: - typedef _Tp value_type; - typedef typename _Tp_alloc_traits::pointer pointer; - typedef typename _Tp_alloc_traits::const_pointer const_pointer; - typedef typename _Tp_alloc_traits::reference reference; - typedef typename _Tp_alloc_traits::const_reference const_reference; - typedef _List_iterator<_Tp> iterator; - typedef _List_const_iterator<_Tp> const_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; - - protected: - // Note that pointers-to-_Node's can be ctor-converted to - // iterator types. - typedef _List_node<_Tp> _Node; - - using _Base::_M_impl; - using _Base::_M_put_node; - using _Base::_M_get_node; - using _Base::_M_get_Node_allocator; - - /** - * @param __args An instance of user data. - * - * Allocates space for a new node and constructs a copy of - * @a __args in it. - */ -#if __cplusplus < 201103L - _Node* - _M_create_node(const value_type& __x) - { - _Node* __p = this->_M_get_node(); - __try - { - _Tp_alloc_type __alloc(_M_get_Node_allocator()); - __alloc.construct(__p->_M_valptr(), __x); - } - __catch(...) - { - _M_put_node(__p); - __throw_exception_again; - } - return __p; - } -#else - template - _Node* - _M_create_node(_Args&&... __args) - { - auto __p = this->_M_get_node(); - auto& __alloc = _M_get_Node_allocator(); - __allocated_ptr<_Node_alloc_type> __guard{__alloc, __p}; - _Node_alloc_traits::construct(__alloc, __p->_M_valptr(), - std::forward<_Args>(__args)...); - __guard = nullptr; - return __p; - } -#endif - -#if _GLIBCXX_USE_CXX11_ABI - static size_t - _S_distance(const_iterator __first, const_iterator __last) - { return std::distance(__first, __last); } - - // return the stored size - size_t - _M_node_count() const - { return this->_M_get_size(); } -#else - // dummy implementations used when the size is not stored - static size_t - _S_distance(const_iterator, const_iterator) - { return 0; } - - // count the number of nodes - size_t - _M_node_count() const - { return std::distance(begin(), end()); } -#endif - - public: - // [23.2.2.1] construct/copy/destroy - // (assign() and get_allocator() are also listed in this section) - - /** - * @brief Creates a %list with no elements. - */ -#if __cplusplus >= 201103L - list() = default; -#else - list() { } -#endif - - /** - * @brief Creates a %list with no elements. - * @param __a An allocator object. - */ - explicit - list(const allocator_type& __a) _GLIBCXX_NOEXCEPT - : _Base(_Node_alloc_type(__a)) { } - -#if __cplusplus >= 201103L - /** - * @brief Creates a %list with default constructed elements. - * @param __n The number of elements to initially create. - * @param __a An allocator object. - * - * This constructor fills the %list with @a __n default - * constructed elements. - */ - explicit - list(size_type __n, const allocator_type& __a = allocator_type()) - : _Base(_Node_alloc_type(__a)) - { _M_default_initialize(__n); } - - /** - * @brief Creates a %list with copies of an exemplar element. - * @param __n The number of elements to initially create. - * @param __value An element to copy. - * @param __a An allocator object. - * - * This constructor fills the %list with @a __n copies of @a __value. - */ - list(size_type __n, const value_type& __value, - const allocator_type& __a = allocator_type()) - : _Base(_Node_alloc_type(__a)) - { _M_fill_initialize(__n, __value); } -#else - /** - * @brief Creates a %list with copies of an exemplar element. - * @param __n The number of elements to initially create. - * @param __value An element to copy. - * @param __a An allocator object. - * - * This constructor fills the %list with @a __n copies of @a __value. - */ - explicit - list(size_type __n, const value_type& __value = value_type(), - const allocator_type& __a = allocator_type()) - : _Base(_Node_alloc_type(__a)) - { _M_fill_initialize(__n, __value); } -#endif - - /** - * @brief %List copy constructor. - * @param __x A %list of identical element and allocator types. - * - * The newly-created %list uses a copy of the allocation object used - * by @a __x (unless the allocator traits dictate a different object). - */ - list(const list& __x) - : _Base(_Node_alloc_traits:: - _S_select_on_copy(__x._M_get_Node_allocator())) - { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } - -#if __cplusplus >= 201103L - /** - * @brief %List move constructor. - * - * The newly-created %list contains the exact contents of the moved - * instance. The contents of the moved instance are a valid, but - * unspecified %list. - */ - list(list&&) = default; - - /** - * @brief Builds a %list from an initializer_list - * @param __l An initializer_list of value_type. - * @param __a An allocator object. - * - * Create a %list consisting of copies of the elements in the - * initializer_list @a __l. This is linear in __l.size(). - */ - list(initializer_list __l, - const allocator_type& __a = allocator_type()) - : _Base(_Node_alloc_type(__a)) - { _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); } - - list(const list& __x, const allocator_type& __a) - : _Base(_Node_alloc_type(__a)) - { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } - - private: - list(list&& __x, const allocator_type& __a, true_type) noexcept - : _Base(_Node_alloc_type(__a), std::move(__x)) - { } - - list(list&& __x, const allocator_type& __a, false_type) - : _Base(_Node_alloc_type(__a)) - { - if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator()) - this->_M_move_nodes(std::move(__x)); - else - insert(begin(), std::__make_move_if_noexcept_iterator(__x.begin()), - std::__make_move_if_noexcept_iterator(__x.end())); - } - - public: - list(list&& __x, const allocator_type& __a) - noexcept(_Node_alloc_traits::_S_always_equal()) - : list(std::move(__x), __a, - typename _Node_alloc_traits::is_always_equal{}) - { } -#endif - - /** - * @brief Builds a %list from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __a An allocator object. - * - * Create a %list consisting of copies of the elements from - * [@a __first,@a __last). This is linear in N (where N is - * distance(@a __first,@a __last)). - */ -#if __cplusplus >= 201103L - template> - list(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(_Node_alloc_type(__a)) - { _M_initialize_dispatch(__first, __last, __false_type()); } -#else - template - list(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(_Node_alloc_type(__a)) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_initialize_dispatch(__first, __last, _Integral()); - } -#endif - -#if __cplusplus >= 201103L - /** - * No explicit dtor needed as the _Base dtor takes care of - * things. The _Base dtor only erases the elements, and note - * that if the elements themselves are pointers, the pointed-to - * memory is not touched in any way. Managing the pointer is - * the user's responsibility. - */ - ~list() = default; -#endif - - /** - * @brief %List assignment operator. - * @param __x A %list of identical element and allocator types. - * - * All the elements of @a __x are copied. - * - * Whether the allocator is copied depends on the allocator traits. - */ - list& - operator=(const list& __x); - -#if __cplusplus >= 201103L - /** - * @brief %List move assignment operator. - * @param __x A %list of identical element and allocator types. - * - * The contents of @a __x are moved into this %list (without copying). - * - * Afterwards @a __x is a valid, but unspecified %list - * - * Whether the allocator is moved depends on the allocator traits. - */ - list& - operator=(list&& __x) - noexcept(_Node_alloc_traits::_S_nothrow_move()) - { - constexpr bool __move_storage = - _Node_alloc_traits::_S_propagate_on_move_assign() - || _Node_alloc_traits::_S_always_equal(); - _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); - return *this; - } - - /** - * @brief %List initializer list assignment operator. - * @param __l An initializer_list of value_type. - * - * Replace the contents of the %list with copies of the elements - * in the initializer_list @a __l. This is linear in l.size(). - */ - list& - operator=(initializer_list __l) - { - this->assign(__l.begin(), __l.end()); - return *this; - } -#endif - - /** - * @brief Assigns a given value to a %list. - * @param __n Number of elements to be assigned. - * @param __val Value to be assigned. - * - * This function fills a %list with @a __n copies of the given - * value. Note that the assignment completely changes the %list - * and that the resulting %list's size is the same as the number - * of elements assigned. - */ - void - assign(size_type __n, const value_type& __val) - { _M_fill_assign(__n, __val); } - - /** - * @brief Assigns a range to a %list. - * @param __first An input iterator. - * @param __last An input iterator. - * - * This function fills a %list with copies of the elements in the - * range [@a __first,@a __last). - * - * Note that the assignment completely changes the %list and - * that the resulting %list's size is the same as the number of - * elements assigned. - */ -#if __cplusplus >= 201103L - template> - void - assign(_InputIterator __first, _InputIterator __last) - { _M_assign_dispatch(__first, __last, __false_type()); } -#else - template - void - assign(_InputIterator __first, _InputIterator __last) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_assign_dispatch(__first, __last, _Integral()); - } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Assigns an initializer_list to a %list. - * @param __l An initializer_list of value_type. - * - * Replace the contents of the %list with copies of the elements - * in the initializer_list @a __l. This is linear in __l.size(). - */ - void - assign(initializer_list __l) - { this->_M_assign_dispatch(__l.begin(), __l.end(), __false_type()); } -#endif - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_Base::_M_get_Node_allocator()); } - - // iterators - /** - * Returns a read/write iterator that points to the first element in the - * %list. Iteration is done in ordinary element order. - */ - iterator - begin() _GLIBCXX_NOEXCEPT - { return iterator(this->_M_impl._M_node._M_next); } - - /** - * Returns a read-only (constant) iterator that points to the - * first element in the %list. Iteration is done in ordinary - * element order. - */ - const_iterator - begin() const _GLIBCXX_NOEXCEPT - { return const_iterator(this->_M_impl._M_node._M_next); } - - /** - * Returns a read/write iterator that points one past the last - * element in the %list. Iteration is done in ordinary element - * order. - */ - iterator - end() _GLIBCXX_NOEXCEPT - { return iterator(&this->_M_impl._M_node); } - - /** - * Returns a read-only (constant) iterator that points one past - * the last element in the %list. Iteration is done in ordinary - * element order. - */ - const_iterator - end() const _GLIBCXX_NOEXCEPT - { return const_iterator(&this->_M_impl._M_node); } - - /** - * Returns a read/write reverse iterator that points to the last - * element in the %list. Iteration is done in reverse element - * order. - */ - reverse_iterator - rbegin() _GLIBCXX_NOEXCEPT - { return reverse_iterator(end()); } - - /** - * Returns a read-only (constant) reverse iterator that points to - * the last element in the %list. Iteration is done in reverse - * element order. - */ - const_reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(end()); } - - /** - * Returns a read/write reverse iterator that points to one - * before the first element in the %list. Iteration is done in - * reverse element order. - */ - reverse_iterator - rend() _GLIBCXX_NOEXCEPT - { return reverse_iterator(begin()); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first element in the %list. Iteration is done in reverse - * element order. - */ - const_reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(begin()); } - -#if __cplusplus >= 201103L - /** - * Returns a read-only (constant) iterator that points to the - * first element in the %list. Iteration is done in ordinary - * element order. - */ - const_iterator - cbegin() const noexcept - { return const_iterator(this->_M_impl._M_node._M_next); } - - /** - * Returns a read-only (constant) iterator that points one past - * the last element in the %list. Iteration is done in ordinary - * element order. - */ - const_iterator - cend() const noexcept - { return const_iterator(&this->_M_impl._M_node); } - - /** - * Returns a read-only (constant) reverse iterator that points to - * the last element in the %list. Iteration is done in reverse - * element order. - */ - const_reverse_iterator - crbegin() const noexcept - { return const_reverse_iterator(end()); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first element in the %list. Iteration is done in reverse - * element order. - */ - const_reverse_iterator - crend() const noexcept - { return const_reverse_iterator(begin()); } -#endif - - // [23.2.2.2] capacity - /** - * Returns true if the %list is empty. (Thus begin() would equal - * end().) - */ - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_node._M_next == &this->_M_impl._M_node; } - - /** Returns the number of elements in the %list. */ - size_type - size() const _GLIBCXX_NOEXCEPT - { return _M_node_count(); } - - /** Returns the size() of the largest possible %list. */ - size_type - max_size() const _GLIBCXX_NOEXCEPT - { return _Node_alloc_traits::max_size(_M_get_Node_allocator()); } - -#if __cplusplus >= 201103L - /** - * @brief Resizes the %list to the specified number of elements. - * @param __new_size Number of elements the %list should contain. - * - * This function will %resize the %list to the specified number - * of elements. If the number is smaller than the %list's - * current size the %list is truncated, otherwise default - * constructed elements are appended. - */ - void - resize(size_type __new_size); - - /** - * @brief Resizes the %list to the specified number of elements. - * @param __new_size Number of elements the %list should contain. - * @param __x Data with which new elements should be populated. - * - * This function will %resize the %list to the specified number - * of elements. If the number is smaller than the %list's - * current size the %list is truncated, otherwise the %list is - * extended and new elements are populated with given data. - */ - void - resize(size_type __new_size, const value_type& __x); -#else - /** - * @brief Resizes the %list to the specified number of elements. - * @param __new_size Number of elements the %list should contain. - * @param __x Data with which new elements should be populated. - * - * This function will %resize the %list to the specified number - * of elements. If the number is smaller than the %list's - * current size the %list is truncated, otherwise the %list is - * extended and new elements are populated with given data. - */ - void - resize(size_type __new_size, value_type __x = value_type()); -#endif - - // element access - /** - * Returns a read/write reference to the data at the first - * element of the %list. - */ - reference - front() _GLIBCXX_NOEXCEPT - { return *begin(); } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %list. - */ - const_reference - front() const _GLIBCXX_NOEXCEPT - { return *begin(); } - - /** - * Returns a read/write reference to the data at the last element - * of the %list. - */ - reference - back() _GLIBCXX_NOEXCEPT - { - iterator __tmp = end(); - --__tmp; - return *__tmp; - } - - /** - * Returns a read-only (constant) reference to the data at the last - * element of the %list. - */ - const_reference - back() const _GLIBCXX_NOEXCEPT - { - const_iterator __tmp = end(); - --__tmp; - return *__tmp; - } - - // [23.2.2.3] modifiers - /** - * @brief Add data to the front of the %list. - * @param __x Data to be added. - * - * This is a typical stack operation. The function creates an - * element at the front of the %list and assigns the given data - * to it. Due to the nature of a %list this operation can be - * done in constant time, and does not invalidate iterators and - * references. - */ - void - push_front(const value_type& __x) - { this->_M_insert(begin(), __x); } - -#if __cplusplus >= 201103L - void - push_front(value_type&& __x) - { this->_M_insert(begin(), std::move(__x)); } - - template -#if __cplusplus > 201402L - reference -#else - void -#endif - emplace_front(_Args&&... __args) - { - this->_M_insert(begin(), std::forward<_Args>(__args)...); -#if __cplusplus > 201402L - return front(); -#endif - } -#endif - - /** - * @brief Removes first element. - * - * This is a typical stack operation. It shrinks the %list by - * one. Due to the nature of a %list this operation can be done - * in constant time, and only invalidates iterators/references to - * the element being removed. - * - * Note that no data is returned, and if the first element's data - * is needed, it should be retrieved before pop_front() is - * called. - */ - void - pop_front() _GLIBCXX_NOEXCEPT - { this->_M_erase(begin()); } - - /** - * @brief Add data to the end of the %list. - * @param __x Data to be added. - * - * This is a typical stack operation. The function creates an - * element at the end of the %list and assigns the given data to - * it. Due to the nature of a %list this operation can be done - * in constant time, and does not invalidate iterators and - * references. - */ - void - push_back(const value_type& __x) - { this->_M_insert(end(), __x); } - -#if __cplusplus >= 201103L - void - push_back(value_type&& __x) - { this->_M_insert(end(), std::move(__x)); } - - template -#if __cplusplus > 201402L - reference -#else - void -#endif - emplace_back(_Args&&... __args) - { - this->_M_insert(end(), std::forward<_Args>(__args)...); -#if __cplusplus > 201402L - return back(); -#endif - } -#endif - - /** - * @brief Removes last element. - * - * This is a typical stack operation. It shrinks the %list by - * one. Due to the nature of a %list this operation can be done - * in constant time, and only invalidates iterators/references to - * the element being removed. - * - * Note that no data is returned, and if the last element's data - * is needed, it should be retrieved before pop_back() is called. - */ - void - pop_back() _GLIBCXX_NOEXCEPT - { this->_M_erase(iterator(this->_M_impl._M_node._M_prev)); } - -#if __cplusplus >= 201103L - /** - * @brief Constructs object in %list before specified iterator. - * @param __position A const_iterator into the %list. - * @param __args Arguments. - * @return An iterator that points to the inserted data. - * - * This function will insert an object of type T constructed - * with T(std::forward(args)...) before the specified - * location. Due to the nature of a %list this operation can - * be done in constant time, and does not invalidate iterators - * and references. - */ - template - iterator - emplace(const_iterator __position, _Args&&... __args); - - /** - * @brief Inserts given value into %list before specified iterator. - * @param __position A const_iterator into the %list. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before - * the specified location. Due to the nature of a %list this - * operation can be done in constant time, and does not - * invalidate iterators and references. - */ - iterator - insert(const_iterator __position, const value_type& __x); -#else - /** - * @brief Inserts given value into %list before specified iterator. - * @param __position An iterator into the %list. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before - * the specified location. Due to the nature of a %list this - * operation can be done in constant time, and does not - * invalidate iterators and references. - */ - iterator - insert(iterator __position, const value_type& __x); -#endif - -#if __cplusplus >= 201103L - /** - * @brief Inserts given rvalue into %list before specified iterator. - * @param __position A const_iterator into the %list. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given rvalue before - * the specified location. Due to the nature of a %list this - * operation can be done in constant time, and does not - * invalidate iterators and references. - */ - iterator - insert(const_iterator __position, value_type&& __x) - { return emplace(__position, std::move(__x)); } - - /** - * @brief Inserts the contents of an initializer_list into %list - * before specified const_iterator. - * @param __p A const_iterator into the %list. - * @param __l An initializer_list of value_type. - * @return An iterator pointing to the first element inserted - * (or __position). - * - * This function will insert copies of the data in the - * initializer_list @a l into the %list before the location - * specified by @a p. - * - * This operation is linear in the number of elements inserted and - * does not invalidate iterators and references. - */ - iterator - insert(const_iterator __p, initializer_list __l) - { return this->insert(__p, __l.begin(), __l.end()); } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Inserts a number of copies of given data into the %list. - * @param __position A const_iterator into the %list. - * @param __n Number of elements to be inserted. - * @param __x Data to be inserted. - * @return An iterator pointing to the first element inserted - * (or __position). - * - * This function will insert a specified number of copies of the - * given data before the location specified by @a position. - * - * This operation is linear in the number of elements inserted and - * does not invalidate iterators and references. - */ - iterator - insert(const_iterator __position, size_type __n, const value_type& __x); -#else - /** - * @brief Inserts a number of copies of given data into the %list. - * @param __position An iterator into the %list. - * @param __n Number of elements to be inserted. - * @param __x Data to be inserted. - * - * This function will insert a specified number of copies of the - * given data before the location specified by @a position. - * - * This operation is linear in the number of elements inserted and - * does not invalidate iterators and references. - */ - void - insert(iterator __position, size_type __n, const value_type& __x) - { - list __tmp(__n, __x, get_allocator()); - splice(__position, __tmp); - } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Inserts a range into the %list. - * @param __position A const_iterator into the %list. - * @param __first An input iterator. - * @param __last An input iterator. - * @return An iterator pointing to the first element inserted - * (or __position). - * - * This function will insert copies of the data in the range [@a - * first,@a last) into the %list before the location specified by - * @a position. - * - * This operation is linear in the number of elements inserted and - * does not invalidate iterators and references. - */ - template> - iterator - insert(const_iterator __position, _InputIterator __first, - _InputIterator __last); -#else - /** - * @brief Inserts a range into the %list. - * @param __position An iterator into the %list. - * @param __first An input iterator. - * @param __last An input iterator. - * - * This function will insert copies of the data in the range [@a - * first,@a last) into the %list before the location specified by - * @a position. - * - * This operation is linear in the number of elements inserted and - * does not invalidate iterators and references. - */ - template - void - insert(iterator __position, _InputIterator __first, - _InputIterator __last) - { - list __tmp(__first, __last, get_allocator()); - splice(__position, __tmp); - } -#endif - - /** - * @brief Remove element at given position. - * @param __position Iterator pointing to element to be erased. - * @return An iterator pointing to the next element (or end()). - * - * This function will erase the element at the given position and thus - * shorten the %list by one. - * - * Due to the nature of a %list this operation can be done in - * constant time, and only invalidates iterators/references to - * the element being removed. The user is also cautioned that - * this function only erases the element, and that if the element - * is itself a pointer, the pointed-to memory is not touched in - * any way. Managing the pointer is the user's responsibility. - */ - iterator -#if __cplusplus >= 201103L - erase(const_iterator __position) noexcept; -#else - erase(iterator __position); -#endif - - /** - * @brief Remove a range of elements. - * @param __first Iterator pointing to the first element to be erased. - * @param __last Iterator pointing to one past the last element to be - * erased. - * @return An iterator pointing to the element pointed to by @a last - * prior to erasing (or end()). - * - * This function will erase the elements in the range @a - * [first,last) and shorten the %list accordingly. - * - * This operation is linear time in the size of the range and only - * invalidates iterators/references to the element being removed. - * The user is also cautioned that this function only erases the - * elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer - * is the user's responsibility. - */ - iterator -#if __cplusplus >= 201103L - erase(const_iterator __first, const_iterator __last) noexcept -#else - erase(iterator __first, iterator __last) -#endif - { - while (__first != __last) - __first = erase(__first); - return __last._M_const_cast(); - } - - /** - * @brief Swaps data with another %list. - * @param __x A %list of the same element and allocator types. - * - * This exchanges the elements between two lists in constant - * time. Note that the global std::swap() function is - * specialized such that std::swap(l1,l2) will feed to this - * function. - * - * Whether the allocators are swapped depends on the allocator traits. - */ - void - swap(list& __x) _GLIBCXX_NOEXCEPT - { - __detail::_List_node_base::swap(this->_M_impl._M_node, - __x._M_impl._M_node); - - size_t __xsize = __x._M_get_size(); - __x._M_set_size(this->_M_get_size()); - this->_M_set_size(__xsize); - - _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(), - __x._M_get_Node_allocator()); - } - - /** - * Erases all the elements. Note that this function only erases - * the elements, and that if the elements themselves are - * pointers, the pointed-to memory is not touched in any way. - * Managing the pointer is the user's responsibility. - */ - void - clear() _GLIBCXX_NOEXCEPT - { - _Base::_M_clear(); - _Base::_M_init(); - } - - // [23.2.2.4] list operations - /** - * @brief Insert contents of another %list. - * @param __position Iterator referencing the element to insert before. - * @param __x Source list. - * - * The elements of @a __x are inserted in constant time in front of - * the element referenced by @a __position. @a __x becomes an empty - * list. - * - * Requires this != @a __x. - */ - void -#if __cplusplus >= 201103L - splice(const_iterator __position, list&& __x) noexcept -#else - splice(iterator __position, list& __x) -#endif - { - if (!__x.empty()) - { - _M_check_equal_allocators(__x); - - this->_M_transfer(__position._M_const_cast(), - __x.begin(), __x.end()); - - this->_M_inc_size(__x._M_get_size()); - __x._M_set_size(0); - } - } - -#if __cplusplus >= 201103L - void - splice(const_iterator __position, list& __x) noexcept - { splice(__position, std::move(__x)); } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Insert element from another %list. - * @param __position Const_iterator referencing the element to - * insert before. - * @param __x Source list. - * @param __i Const_iterator referencing the element to move. - * - * Removes the element in list @a __x referenced by @a __i and - * inserts it into the current list before @a __position. - */ - void - splice(const_iterator __position, list&& __x, const_iterator __i) noexcept -#else - /** - * @brief Insert element from another %list. - * @param __position Iterator referencing the element to insert before. - * @param __x Source list. - * @param __i Iterator referencing the element to move. - * - * Removes the element in list @a __x referenced by @a __i and - * inserts it into the current list before @a __position. - */ - void - splice(iterator __position, list& __x, iterator __i) -#endif - { - iterator __j = __i._M_const_cast(); - ++__j; - if (__position == __i || __position == __j) - return; - - if (this != std::__addressof(__x)) - _M_check_equal_allocators(__x); - - this->_M_transfer(__position._M_const_cast(), - __i._M_const_cast(), __j); - - this->_M_inc_size(1); - __x._M_dec_size(1); - } - -#if __cplusplus >= 201103L - /** - * @brief Insert element from another %list. - * @param __position Const_iterator referencing the element to - * insert before. - * @param __x Source list. - * @param __i Const_iterator referencing the element to move. - * - * Removes the element in list @a __x referenced by @a __i and - * inserts it into the current list before @a __position. - */ - void - splice(const_iterator __position, list& __x, const_iterator __i) noexcept - { splice(__position, std::move(__x), __i); } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Insert range from another %list. - * @param __position Const_iterator referencing the element to - * insert before. - * @param __x Source list. - * @param __first Const_iterator referencing the start of range in x. - * @param __last Const_iterator referencing the end of range in x. - * - * Removes elements in the range [__first,__last) and inserts them - * before @a __position in constant time. - * - * Undefined if @a __position is in [__first,__last). - */ - void - splice(const_iterator __position, list&& __x, const_iterator __first, - const_iterator __last) noexcept -#else - /** - * @brief Insert range from another %list. - * @param __position Iterator referencing the element to insert before. - * @param __x Source list. - * @param __first Iterator referencing the start of range in x. - * @param __last Iterator referencing the end of range in x. - * - * Removes elements in the range [__first,__last) and inserts them - * before @a __position in constant time. - * - * Undefined if @a __position is in [__first,__last). - */ - void - splice(iterator __position, list& __x, iterator __first, - iterator __last) -#endif - { - if (__first != __last) - { - if (this != std::__addressof(__x)) - _M_check_equal_allocators(__x); - - size_t __n = _S_distance(__first, __last); - this->_M_inc_size(__n); - __x._M_dec_size(__n); - - this->_M_transfer(__position._M_const_cast(), - __first._M_const_cast(), - __last._M_const_cast()); - } - } - -#if __cplusplus >= 201103L - /** - * @brief Insert range from another %list. - * @param __position Const_iterator referencing the element to - * insert before. - * @param __x Source list. - * @param __first Const_iterator referencing the start of range in x. - * @param __last Const_iterator referencing the end of range in x. - * - * Removes elements in the range [__first,__last) and inserts them - * before @a __position in constant time. - * - * Undefined if @a __position is in [__first,__last). - */ - void - splice(const_iterator __position, list& __x, const_iterator __first, - const_iterator __last) noexcept - { splice(__position, std::move(__x), __first, __last); } -#endif - - private: -#if __cplusplus > 201703L -# define __cpp_lib_list_remove_return_type 201806L - typedef size_type __remove_return_type; -# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG \ - __attribute__((__abi_tag__("__cxx20"))) -#else - typedef void __remove_return_type; -# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG -#endif - public: - - /** - * @brief Remove all elements equal to value. - * @param __value The value to remove. - * - * Removes every element in the list equal to @a value. - * Remaining elements stay in list order. Note that this - * function only erases the elements, and that if the elements - * themselves are pointers, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's - * responsibility. - */ - _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG - __remove_return_type - remove(const _Tp& __value); - - /** - * @brief Remove all elements satisfying a predicate. - * @tparam _Predicate Unary predicate function or object. - * - * Removes every element in the list for which the predicate - * returns true. Remaining elements stay in list order. Note - * that this function only erases the elements, and that if the - * elements themselves are pointers, the pointed-to memory is - * not touched in any way. Managing the pointer is the user's - * responsibility. - */ - template - __remove_return_type - remove_if(_Predicate); - - /** - * @brief Remove consecutive duplicate elements. - * - * For each consecutive set of elements with the same value, - * remove all but the first one. Remaining elements stay in - * list order. Note that this function only erases the - * elements, and that if the elements themselves are pointers, - * the pointed-to memory is not touched in any way. Managing - * the pointer is the user's responsibility. - */ - _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG - __remove_return_type - unique(); - - /** - * @brief Remove consecutive elements satisfying a predicate. - * @tparam _BinaryPredicate Binary predicate function or object. - * - * For each consecutive set of elements [first,last) that - * satisfy predicate(first,i) where i is an iterator in - * [first,last), remove all but the first one. Remaining - * elements stay in list order. Note that this function only - * erases the elements, and that if the elements themselves are - * pointers, the pointed-to memory is not touched in any way. - * Managing the pointer is the user's responsibility. - */ - template - __remove_return_type - unique(_BinaryPredicate); - -#undef _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG - - /** - * @brief Merge sorted lists. - * @param __x Sorted list to merge. - * - * Assumes that both @a __x and this list are sorted according to - * operator<(). Merges elements of @a __x into this list in - * sorted order, leaving @a __x empty when complete. Elements in - * this list precede elements in @a __x that are equal. - */ -#if __cplusplus >= 201103L - void - merge(list&& __x); - - void - merge(list& __x) - { merge(std::move(__x)); } -#else - void - merge(list& __x); -#endif - - /** - * @brief Merge sorted lists according to comparison function. - * @tparam _StrictWeakOrdering Comparison function defining - * sort order. - * @param __x Sorted list to merge. - * @param __comp Comparison functor. - * - * Assumes that both @a __x and this list are sorted according to - * StrictWeakOrdering. Merges elements of @a __x into this list - * in sorted order, leaving @a __x empty when complete. Elements - * in this list precede elements in @a __x that are equivalent - * according to StrictWeakOrdering(). - */ -#if __cplusplus >= 201103L - template - void - merge(list&& __x, _StrictWeakOrdering __comp); - - template - void - merge(list& __x, _StrictWeakOrdering __comp) - { merge(std::move(__x), __comp); } -#else - template - void - merge(list& __x, _StrictWeakOrdering __comp); -#endif - - /** - * @brief Reverse the elements in list. - * - * Reverse the order of elements in the list in linear time. - */ - void - reverse() _GLIBCXX_NOEXCEPT - { this->_M_impl._M_node._M_reverse(); } - - /** - * @brief Sort the elements. - * - * Sorts the elements of this list in NlogN time. Equivalent - * elements remain in list order. - */ - void - sort(); - - /** - * @brief Sort the elements according to comparison function. - * - * Sorts the elements of this list in NlogN time. Equivalent - * elements remain in list order. - */ - template - void - sort(_StrictWeakOrdering); - - protected: - // Internal constructor functions follow. - - // Called by the range constructor to implement [23.1.1]/9 - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) - { _M_fill_initialize(static_cast(__n), __x); } - - // Called by the range constructor to implement [23.1.1]/9 - template - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { - for (; __first != __last; ++__first) -#if __cplusplus >= 201103L - emplace_back(*__first); -#else - push_back(*__first); -#endif - } - - // Called by list(n,v,a), and the range constructor when it turns out - // to be the same thing. - void - _M_fill_initialize(size_type __n, const value_type& __x) - { - for (; __n; --__n) - push_back(__x); - } - -#if __cplusplus >= 201103L - // Called by list(n). - void - _M_default_initialize(size_type __n) - { - for (; __n; --__n) - emplace_back(); - } - - // Called by resize(sz). - void - _M_default_append(size_type __n); -#endif - - // Internal assign functions follow. - - // Called by the range assign to implement [23.1.1]/9 - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { _M_fill_assign(__n, __val); } - - // Called by the range assign to implement [23.1.1]/9 - template - void - _M_assign_dispatch(_InputIterator __first, _InputIterator __last, - __false_type); - - // Called by assign(n,t), and the range assign when it turns out - // to be the same thing. - void - _M_fill_assign(size_type __n, const value_type& __val); - - - // Moves the elements from [first,last) before position. - void - _M_transfer(iterator __position, iterator __first, iterator __last) - { __position._M_node->_M_transfer(__first._M_node, __last._M_node); } - - // Inserts new element at position given and with value given. -#if __cplusplus < 201103L - void - _M_insert(iterator __position, const value_type& __x) - { - _Node* __tmp = _M_create_node(__x); - __tmp->_M_hook(__position._M_node); - this->_M_inc_size(1); - } -#else - template - void - _M_insert(iterator __position, _Args&&... __args) - { - _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...); - __tmp->_M_hook(__position._M_node); - this->_M_inc_size(1); - } -#endif - - // Erases element at position given. - void - _M_erase(iterator __position) _GLIBCXX_NOEXCEPT - { - this->_M_dec_size(1); - __position._M_node->_M_unhook(); - _Node* __n = static_cast<_Node*>(__position._M_node); -#if __cplusplus >= 201103L - _Node_alloc_traits::destroy(_M_get_Node_allocator(), __n->_M_valptr()); -#else - _Tp_alloc_type(_M_get_Node_allocator()).destroy(__n->_M_valptr()); -#endif - - _M_put_node(__n); - } - - // To implement the splice (and merge) bits of N1599. - void - _M_check_equal_allocators(list& __x) _GLIBCXX_NOEXCEPT - { - if (std::__alloc_neq:: - _S_do_it(_M_get_Node_allocator(), __x._M_get_Node_allocator())) - __builtin_abort(); - } - - // Used to implement resize. - const_iterator - _M_resize_pos(size_type& __new_size) const; - -#if __cplusplus >= 201103L - void - _M_move_assign(list&& __x, true_type) noexcept - { - this->_M_clear(); - this->_M_move_nodes(std::move(__x)); - std::__alloc_on_move(this->_M_get_Node_allocator(), - __x._M_get_Node_allocator()); - } - - void - _M_move_assign(list&& __x, false_type) - { - if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator()) - _M_move_assign(std::move(__x), true_type{}); - else - // The rvalue's allocator cannot be moved, or is not equal, - // so we need to individually move each element. - _M_assign_dispatch(std::make_move_iterator(__x.begin()), - std::make_move_iterator(__x.end()), - __false_type{}); - } -#endif - }; - -#if __cpp_deduction_guides >= 201606 - template::value_type, - typename _Allocator = allocator<_ValT>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireAllocator<_Allocator>> - list(_InputIterator, _InputIterator, _Allocator = _Allocator()) - -> list<_ValT, _Allocator>; -#endif - -_GLIBCXX_END_NAMESPACE_CXX11 - - /** - * @brief List equality comparison. - * @param __x A %list. - * @param __y A %list of the same type as @a __x. - * @return True iff the size and elements of the lists are equal. - * - * This is an equivalence relation. It is linear in the size of - * the lists. Lists are considered equivalent if their sizes are - * equal, and if corresponding elements compare equal. - */ - template - inline bool - operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) - { -#if _GLIBCXX_USE_CXX11_ABI - if (__x.size() != __y.size()) - return false; -#endif - - typedef typename list<_Tp, _Alloc>::const_iterator const_iterator; - const_iterator __end1 = __x.end(); - const_iterator __end2 = __y.end(); - - const_iterator __i1 = __x.begin(); - const_iterator __i2 = __y.begin(); - while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) - { - ++__i1; - ++__i2; - } - return __i1 == __end1 && __i2 == __end2; - } - -#if __cpp_lib_three_way_comparison -/** - * @brief List ordering relation. - * @param __x A `list`. - * @param __y A `list` of the same type as `__x`. - * @return A value indicating whether `__x` is less than, equal to, - * greater than, or incomparable with `__y`. - * - * See `std::lexicographical_compare_three_way()` for how the determination - * is made. This operator is used to synthesize relational operators like - * `<` and `>=` etc. - */ - template - inline __detail::__synth3way_t<_Tp> - operator<=>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) - { - return std::lexicographical_compare_three_way(__x.begin(), __x.end(), - __y.begin(), __y.end(), - __detail::__synth3way); - } -#else - /** - * @brief List ordering relation. - * @param __x A %list. - * @param __y A %list of the same type as @a __x. - * @return True iff @a __x is lexicographically less than @a __y. - * - * This is a total ordering relation. It is linear in the size of the - * lists. The elements must be comparable with @c <. - * - * See std::lexicographical_compare() for how the determination is made. - */ - template - inline bool - operator<(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) - { return std::lexicographical_compare(__x.begin(), __x.end(), - __y.begin(), __y.end()); } - - /// Based on operator== - template - inline bool - operator!=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) - { return !(__x == __y); } - - /// Based on operator< - template - inline bool - operator>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) - { return __y < __x; } - - /// Based on operator< - template - inline bool - operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) - { return !(__y < __x); } - - /// Based on operator< - template - inline bool - operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) - { return !(__x < __y); } -#endif // three-way comparison - - /// See std::list::swap(). - template - inline void - swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) - _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if _GLIBCXX_USE_CXX11_ABI - - // Detect when distance is used to compute the size of the whole list. - template - inline ptrdiff_t - __distance(_GLIBCXX_STD_C::_List_iterator<_Tp> __first, - _GLIBCXX_STD_C::_List_iterator<_Tp> __last, - input_iterator_tag __tag) - { - typedef _GLIBCXX_STD_C::_List_const_iterator<_Tp> _CIter; - return std::__distance(_CIter(__first), _CIter(__last), __tag); - } - - template - inline ptrdiff_t - __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp> __first, - _GLIBCXX_STD_C::_List_const_iterator<_Tp> __last, - input_iterator_tag) - { - typedef __detail::_List_node_header _Sentinel; - _GLIBCXX_STD_C::_List_const_iterator<_Tp> __beyond = __last; - ++__beyond; - const bool __whole = __first == __beyond; - if (__builtin_constant_p (__whole) && __whole) - return static_cast(__last._M_node)->_M_size; - - ptrdiff_t __n = 0; - while (__first != __last) - { - ++__first; - ++__n; - } - return __n; - } -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_LIST_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_map.h b/resources/sources/avr-libstdcpp/include/bits/stl_map.h deleted file mode 100644 index 2772d1146..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_map.h +++ /dev/null @@ -1,1568 +0,0 @@ -// Map implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_map.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{map} - */ - -#ifndef _STL_MAP_H -#define _STL_MAP_H 1 - -#include -#include -#if __cplusplus >= 201103L -#include -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - class multimap; - - /** - * @brief A standard container made up of (key,value) pairs, which can be - * retrieved based on a key, in logarithmic time. - * - * @ingroup associative_containers - * - * @tparam _Key Type of key objects. - * @tparam _Tp Type of mapped objects. - * @tparam _Compare Comparison function object type, defaults to less<_Key>. - * @tparam _Alloc Allocator type, defaults to - * allocator. - * - * Meets the requirements of a container, a - * reversible container, and an - * associative container (using unique keys). - * For a @c map the key_type is Key, the mapped_type is T, and the - * value_type is std::pair. - * - * Maps support bidirectional iterators. - * - * The private tree data is declared exactly the same way for map and - * multimap; the distinction is made entirely in how the tree functions are - * called (*_unique versus *_equal, same as the standard). - */ - template , - typename _Alloc = std::allocator > > - class map - { - public: - typedef _Key key_type; - typedef _Tp mapped_type; - typedef std::pair value_type; - typedef _Compare key_compare; - typedef _Alloc allocator_type; - - private: -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -# endif - __glibcxx_class_requires4(_Compare, bool, _Key, _Key, - _BinaryFunctionConcept) - __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) -#endif - -#if __cplusplus >= 201103L -#if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same::value, - "std::map must have the same value_type as its allocator"); -#endif -#endif - - public: - class value_compare - : public std::binary_function - { - friend class map<_Key, _Tp, _Compare, _Alloc>; - protected: - _Compare comp; - - value_compare(_Compare __c) - : comp(__c) { } - - public: - bool operator()(const value_type& __x, const value_type& __y) const - { return comp(__x.first, __y.first); } - }; - - private: - /// This turns a red-black tree into a [multi]map. - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind::other _Pair_alloc_type; - - typedef _Rb_tree, - key_compare, _Pair_alloc_type> _Rep_type; - - /// The actual tree structure. - _Rep_type _M_t; - - typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits; - - public: - // many of these are specified differently in ISO, but the following are - // "functionally equivalent" - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; - typedef typename _Rep_type::iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; - typedef typename _Rep_type::reverse_iterator reverse_iterator; - typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; - -#if __cplusplus > 201402L - using node_type = typename _Rep_type::node_type; - using insert_return_type = typename _Rep_type::insert_return_type; -#endif - - // [23.3.1.1] construct/copy/destroy - // (get_allocator() is also listed in this section) - - /** - * @brief Default constructor creates no elements. - */ -#if __cplusplus < 201103L - map() : _M_t() { } -#else - map() = default; -#endif - - /** - * @brief Creates a %map with no elements. - * @param __comp A comparison object. - * @param __a An allocator object. - */ - explicit - map(const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Pair_alloc_type(__a)) { } - - /** - * @brief %Map copy constructor. - * - * Whether the allocator is copied depends on the allocator traits. - */ -#if __cplusplus < 201103L - map(const map& __x) - : _M_t(__x._M_t) { } -#else - map(const map&) = default; - - /** - * @brief %Map move constructor. - * - * The newly-created %map contains the exact contents of the moved - * instance. The moved instance is a valid, but unspecified, %map. - */ - map(map&&) = default; - - /** - * @brief Builds a %map from an initializer_list. - * @param __l An initializer_list. - * @param __comp A comparison object. - * @param __a An allocator object. - * - * Create a %map consisting of copies of the elements in the - * initializer_list @a __l. - * This is linear in N if the range is already sorted, and NlogN - * otherwise (where N is @a __l.size()). - */ - map(initializer_list __l, - const _Compare& __comp = _Compare(), - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Pair_alloc_type(__a)) - { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } - - /// Allocator-extended default constructor. - explicit - map(const allocator_type& __a) - : _M_t(_Pair_alloc_type(__a)) { } - - /// Allocator-extended copy constructor. - map(const map& __m, const allocator_type& __a) - : _M_t(__m._M_t, _Pair_alloc_type(__a)) { } - - /// Allocator-extended move constructor. - map(map&& __m, const allocator_type& __a) - noexcept(is_nothrow_copy_constructible<_Compare>::value - && _Alloc_traits::_S_always_equal()) - : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { } - - /// Allocator-extended initialier-list constructor. - map(initializer_list __l, const allocator_type& __a) - : _M_t(_Pair_alloc_type(__a)) - { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } - - /// Allocator-extended range constructor. - template - map(_InputIterator __first, _InputIterator __last, - const allocator_type& __a) - : _M_t(_Pair_alloc_type(__a)) - { _M_t._M_insert_range_unique(__first, __last); } -#endif - - /** - * @brief Builds a %map from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * - * Create a %map consisting of copies of the elements from - * [__first,__last). This is linear in N if the range is - * already sorted, and NlogN otherwise (where N is - * distance(__first,__last)). - */ - template - map(_InputIterator __first, _InputIterator __last) - : _M_t() - { _M_t._M_insert_range_unique(__first, __last); } - - /** - * @brief Builds a %map from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __comp A comparison functor. - * @param __a An allocator object. - * - * Create a %map consisting of copies of the elements from - * [__first,__last). This is linear in N if the range is - * already sorted, and NlogN otherwise (where N is - * distance(__first,__last)). - */ - template - map(_InputIterator __first, _InputIterator __last, - const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Pair_alloc_type(__a)) - { _M_t._M_insert_range_unique(__first, __last); } - -#if __cplusplus >= 201103L - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibility. - */ - ~map() = default; -#endif - - /** - * @brief %Map assignment operator. - * - * Whether the allocator is copied depends on the allocator traits. - */ -#if __cplusplus < 201103L - map& - operator=(const map& __x) - { - _M_t = __x._M_t; - return *this; - } -#else - map& - operator=(const map&) = default; - - /// Move assignment operator. - map& - operator=(map&&) = default; - - /** - * @brief %Map list assignment operator. - * @param __l An initializer_list. - * - * This function fills a %map with copies of the elements in the - * initializer list @a __l. - * - * Note that the assignment completely changes the %map and - * that the resulting %map's size is the same as the number - * of elements assigned. - */ - map& - operator=(initializer_list __l) - { - _M_t._M_assign_unique(__l.begin(), __l.end()); - return *this; - } -#endif - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_M_t.get_allocator()); } - - // iterators - /** - * Returns a read/write iterator that points to the first pair in the - * %map. - * Iteration is done in ascending order according to the keys. - */ - iterator - begin() _GLIBCXX_NOEXCEPT - { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points to the first pair - * in the %map. Iteration is done in ascending order according to the - * keys. - */ - const_iterator - begin() const _GLIBCXX_NOEXCEPT - { return _M_t.begin(); } - - /** - * Returns a read/write iterator that points one past the last - * pair in the %map. Iteration is done in ascending order - * according to the keys. - */ - iterator - end() _GLIBCXX_NOEXCEPT - { return _M_t.end(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * pair in the %map. Iteration is done in ascending order according to - * the keys. - */ - const_iterator - end() const _GLIBCXX_NOEXCEPT - { return _M_t.end(); } - - /** - * Returns a read/write reverse iterator that points to the last pair in - * the %map. Iteration is done in descending order according to the - * keys. - */ - reverse_iterator - rbegin() _GLIBCXX_NOEXCEPT - { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last pair in the %map. Iteration is done in descending order - * according to the keys. - */ - const_reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return _M_t.rbegin(); } - - /** - * Returns a read/write reverse iterator that points to one before the - * first pair in the %map. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - rend() _GLIBCXX_NOEXCEPT - { return _M_t.rend(); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first pair in the %map. Iteration is done in descending - * order according to the keys. - */ - const_reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return _M_t.rend(); } - -#if __cplusplus >= 201103L - /** - * Returns a read-only (constant) iterator that points to the first pair - * in the %map. Iteration is done in ascending order according to the - * keys. - */ - const_iterator - cbegin() const noexcept - { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * pair in the %map. Iteration is done in ascending order according to - * the keys. - */ - const_iterator - cend() const noexcept - { return _M_t.end(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last pair in the %map. Iteration is done in descending order - * according to the keys. - */ - const_reverse_iterator - crbegin() const noexcept - { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first pair in the %map. Iteration is done in descending - * order according to the keys. - */ - const_reverse_iterator - crend() const noexcept - { return _M_t.rend(); } -#endif - - // capacity - /** Returns true if the %map is empty. (Thus begin() would equal - * end().) - */ - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return _M_t.empty(); } - - /** Returns the size of the %map. */ - size_type - size() const _GLIBCXX_NOEXCEPT - { return _M_t.size(); } - - /** Returns the maximum size of the %map. */ - size_type - max_size() const _GLIBCXX_NOEXCEPT - { return _M_t.max_size(); } - - // [23.3.1.2] element access - /** - * @brief Subscript ( @c [] ) access to %map data. - * @param __k The key for which data should be retrieved. - * @return A reference to the data of the (key,data) %pair. - * - * Allows for easy lookup with the subscript ( @c [] ) - * operator. Returns data associated with the key specified in - * subscript. If the key does not exist, a pair with that key - * is created using default values, which is then returned. - * - * Lookup requires logarithmic time. - */ - mapped_type& - operator[](const key_type& __k) - { - // concept requirements - __glibcxx_function_requires(_DefaultConstructibleConcept) - - iterator __i = lower_bound(__k); - // __i->first is greater than or equivalent to __k. - if (__i == end() || key_comp()(__k, (*__i).first)) -#if __cplusplus >= 201103L - __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct, - std::tuple(__k), - std::tuple<>()); -#else - __i = insert(__i, value_type(__k, mapped_type())); -#endif - return (*__i).second; - } - -#if __cplusplus >= 201103L - mapped_type& - operator[](key_type&& __k) - { - // concept requirements - __glibcxx_function_requires(_DefaultConstructibleConcept) - - iterator __i = lower_bound(__k); - // __i->first is greater than or equivalent to __k. - if (__i == end() || key_comp()(__k, (*__i).first)) - __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::tuple<>()); - return (*__i).second; - } -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 464. Suggestion for new member functions in standard containers. - /** - * @brief Access to %map data. - * @param __k The key for which data should be retrieved. - * @return A reference to the data whose key is equivalent to @a __k, if - * such a data is present in the %map. - * @throw std::out_of_range If no such data is present. - */ - mapped_type& - at(const key_type& __k) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - __throw_out_of_range(__N("map::at")); - return (*__i).second; - } - - const mapped_type& - at(const key_type& __k) const - { - const_iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - __throw_out_of_range(__N("map::at")); - return (*__i).second; - } - - // modifiers -#if __cplusplus >= 201103L - /** - * @brief Attempts to build and insert a std::pair into the %map. - * - * @param __args Arguments used to generate a new pair instance (see - * std::piecewise_contruct for passing arguments to each - * part of the pair constructor). - * - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted pair, and the second is a bool that - * is true if the pair was actually inserted. - * - * This function attempts to build and insert a (key, value) %pair into - * the %map. - * A %map relies on unique keys and thus a %pair is only inserted if its - * first element (the key) is not already present in the %map. - * - * Insertion requires logarithmic time. - */ - template - std::pair - emplace(_Args&&... __args) - { return _M_t._M_emplace_unique(std::forward<_Args>(__args)...); } - - /** - * @brief Attempts to build and insert a std::pair into the %map. - * - * @param __pos An iterator that serves as a hint as to where the pair - * should be inserted. - * @param __args Arguments used to generate a new pair instance (see - * std::piecewise_contruct for passing arguments to each - * part of the pair constructor). - * @return An iterator that points to the element with key of the - * std::pair built from @a __args (may or may not be that - * std::pair). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument emplace() - * does. - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - template - iterator - emplace_hint(const_iterator __pos, _Args&&... __args) - { - return _M_t._M_emplace_hint_unique(__pos, - std::forward<_Args>(__args)...); - } -#endif - -#if __cplusplus > 201402L - /// Extract a node. - node_type - extract(const_iterator __pos) - { - __glibcxx_assert(__pos != end()); - return _M_t.extract(__pos); - } - - /// Extract a node. - node_type - extract(const key_type& __x) - { return _M_t.extract(__x); } - - /// Re-insert an extracted node. - insert_return_type - insert(node_type&& __nh) - { return _M_t._M_reinsert_node_unique(std::move(__nh)); } - - /// Re-insert an extracted node. - iterator - insert(const_iterator __hint, node_type&& __nh) - { return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); } - - template - friend class std::_Rb_tree_merge_helper; - - template - void - merge(map<_Key, _Tp, _Cmp2, _Alloc>& __source) - { - using _Merge_helper = _Rb_tree_merge_helper; - _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); - } - - template - void - merge(map<_Key, _Tp, _Cmp2, _Alloc>&& __source) - { merge(__source); } - - template - void - merge(multimap<_Key, _Tp, _Cmp2, _Alloc>& __source) - { - using _Merge_helper = _Rb_tree_merge_helper; - _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); - } - - template - void - merge(multimap<_Key, _Tp, _Cmp2, _Alloc>&& __source) - { merge(__source); } -#endif // C++17 - -#if __cplusplus > 201402L -#define __cpp_lib_map_try_emplace 201411 - /** - * @brief Attempts to build and insert a std::pair into the %map. - * - * @param __k Key to use for finding a possibly existing pair in - * the map. - * @param __args Arguments used to generate the .second for a new pair - * instance. - * - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted pair, and the second is a bool that - * is true if the pair was actually inserted. - * - * This function attempts to build and insert a (key, value) %pair into - * the %map. - * A %map relies on unique keys and thus a %pair is only inserted if its - * first element (the key) is not already present in the %map. - * If a %pair is not inserted, this function has no effect. - * - * Insertion requires logarithmic time. - */ - template - pair - try_emplace(const key_type& __k, _Args&&... __args) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - { - __i = emplace_hint(__i, std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - return {__i, true}; - } - return {__i, false}; - } - - // move-capable overload - template - pair - try_emplace(key_type&& __k, _Args&&... __args) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - { - __i = emplace_hint(__i, std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - return {__i, true}; - } - return {__i, false}; - } - - /** - * @brief Attempts to build and insert a std::pair into the %map. - * - * @param __hint An iterator that serves as a hint as to where the - * pair should be inserted. - * @param __k Key to use for finding a possibly existing pair in - * the map. - * @param __args Arguments used to generate the .second for a new pair - * instance. - * @return An iterator that points to the element with key of the - * std::pair built from @a __args (may or may not be that - * std::pair). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument - * try_emplace() does. However, if insertion did not take place, - * this function has no effect. - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - template - iterator - try_emplace(const_iterator __hint, const key_type& __k, - _Args&&... __args) - { - iterator __i; - auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); - if (__true_hint.second) - __i = emplace_hint(iterator(__true_hint.second), - std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - else - __i = iterator(__true_hint.first); - return __i; - } - - // move-capable overload - template - iterator - try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) - { - iterator __i; - auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); - if (__true_hint.second) - __i = emplace_hint(iterator(__true_hint.second), - std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - else - __i = iterator(__true_hint.first); - return __i; - } -#endif - - /** - * @brief Attempts to insert a std::pair into the %map. - * @param __x Pair to be inserted (see std::make_pair for easy - * creation of pairs). - * - * @return A pair, of which the first element is an iterator that - * points to the possibly inserted pair, and the second is - * a bool that is true if the pair was actually inserted. - * - * This function attempts to insert a (key, value) %pair into the %map. - * A %map relies on unique keys and thus a %pair is only inserted if its - * first element (the key) is not already present in the %map. - * - * Insertion requires logarithmic time. - * @{ - */ - std::pair - insert(const value_type& __x) - { return _M_t._M_insert_unique(__x); } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2354. Unnecessary copying when inserting into maps with braced-init - std::pair - insert(value_type&& __x) - { return _M_t._M_insert_unique(std::move(__x)); } - - template - __enable_if_t::value, - pair> - insert(_Pair&& __x) - { return _M_t._M_emplace_unique(std::forward<_Pair>(__x)); } -#endif - // @} - -#if __cplusplus >= 201103L - /** - * @brief Attempts to insert a list of std::pairs into the %map. - * @param __list A std::initializer_list of pairs to be - * inserted. - * - * Complexity similar to that of the range constructor. - */ - void - insert(std::initializer_list __list) - { insert(__list.begin(), __list.end()); } -#endif - - /** - * @brief Attempts to insert a std::pair into the %map. - * @param __position An iterator that serves as a hint as to where the - * pair should be inserted. - * @param __x Pair to be inserted (see std::make_pair for easy creation - * of pairs). - * @return An iterator that points to the element with key of - * @a __x (may or may not be the %pair passed in). - * - - * This function is not concerned about whether the insertion - * took place, and thus does not return a boolean like the - * single-argument insert() does. Note that the first - * parameter is only a hint and can potentially improve the - * performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires logarithmic time (if the hint is not taken). - * @{ - */ - iterator -#if __cplusplus >= 201103L - insert(const_iterator __position, const value_type& __x) -#else - insert(iterator __position, const value_type& __x) -#endif - { return _M_t._M_insert_unique_(__position, __x); } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2354. Unnecessary copying when inserting into maps with braced-init - iterator - insert(const_iterator __position, value_type&& __x) - { return _M_t._M_insert_unique_(__position, std::move(__x)); } - - template - __enable_if_t::value, iterator> - insert(const_iterator __position, _Pair&& __x) - { - return _M_t._M_emplace_hint_unique(__position, - std::forward<_Pair>(__x)); - } -#endif - // @} - - /** - * @brief Template function that attempts to insert a range of elements. - * @param __first Iterator pointing to the start of the range to be - * inserted. - * @param __last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) - { _M_t._M_insert_range_unique(__first, __last); } - -#if __cplusplus > 201402L - /** - * @brief Attempts to insert or assign a std::pair into the %map. - * @param __k Key to use for finding a possibly existing pair in - * the map. - * @param __obj Argument used to generate the .second for a pair - * instance. - * - * @return A pair, of which the first element is an iterator that - * points to the possibly inserted pair, and the second is - * a bool that is true if the pair was actually inserted. - * - * This function attempts to insert a (key, value) %pair into the %map. - * A %map relies on unique keys and thus a %pair is only inserted if its - * first element (the key) is not already present in the %map. - * If the %pair was already in the %map, the .second of the %pair - * is assigned from __obj. - * - * Insertion requires logarithmic time. - */ - template - pair - insert_or_assign(const key_type& __k, _Obj&& __obj) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - { - __i = emplace_hint(__i, std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - return {__i, true}; - } - (*__i).second = std::forward<_Obj>(__obj); - return {__i, false}; - } - - // move-capable overload - template - pair - insert_or_assign(key_type&& __k, _Obj&& __obj) - { - iterator __i = lower_bound(__k); - if (__i == end() || key_comp()(__k, (*__i).first)) - { - __i = emplace_hint(__i, std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - return {__i, true}; - } - (*__i).second = std::forward<_Obj>(__obj); - return {__i, false}; - } - - /** - * @brief Attempts to insert or assign a std::pair into the %map. - * @param __hint An iterator that serves as a hint as to where the - * pair should be inserted. - * @param __k Key to use for finding a possibly existing pair in - * the map. - * @param __obj Argument used to generate the .second for a pair - * instance. - * - * @return An iterator that points to the element with key of - * @a __x (may or may not be the %pair passed in). - * - * This function attempts to insert a (key, value) %pair into the %map. - * A %map relies on unique keys and thus a %pair is only inserted if its - * first element (the key) is not already present in the %map. - * If the %pair was already in the %map, the .second of the %pair - * is assigned from __obj. - * - * Insertion requires logarithmic time. - */ - template - iterator - insert_or_assign(const_iterator __hint, - const key_type& __k, _Obj&& __obj) - { - iterator __i; - auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); - if (__true_hint.second) - { - return emplace_hint(iterator(__true_hint.second), - std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - } - __i = iterator(__true_hint.first); - (*__i).second = std::forward<_Obj>(__obj); - return __i; - } - - // move-capable overload - template - iterator - insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) - { - iterator __i; - auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); - if (__true_hint.second) - { - return emplace_hint(iterator(__true_hint.second), - std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - } - __i = iterator(__true_hint.first); - (*__i).second = std::forward<_Obj>(__obj); - return __i; - } -#endif - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases an element from a %map. - * @param __position An iterator pointing to the element to be erased. - * @return An iterator pointing to the element immediately following - * @a position prior to the element being erased. If no such - * element exists, end() is returned. - * - * This function erases an element, pointed to by the given - * iterator, from a %map. Note that this function only erases - * the element, and that if the element is itself a pointer, - * the pointed-to memory is not touched in any way. Managing - * the pointer is the user's responsibility. - * - * @{ - */ - iterator - erase(const_iterator __position) - { return _M_t.erase(__position); } - - // LWG 2059 - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(iterator __position) - { return _M_t.erase(__position); } - // @} -#else - /** - * @brief Erases an element from a %map. - * @param __position An iterator pointing to the element to be erased. - * - * This function erases an element, pointed to by the given - * iterator, from a %map. Note that this function only erases - * the element, and that if the element is itself a pointer, - * the pointed-to memory is not touched in any way. Managing - * the pointer is the user's responsibility. - */ - void - erase(iterator __position) - { _M_t.erase(__position); } -#endif - - /** - * @brief Erases elements according to the provided key. - * @param __x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all the elements located by the given key from - * a %map. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - size_type - erase(const key_type& __x) - { return _M_t.erase(__x); } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases a [first,last) range of elements from a %map. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * @return The iterator @a __last. - * - * This function erases a sequence of elements from a %map. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - iterator - erase(const_iterator __first, const_iterator __last) - { return _M_t.erase(__first, __last); } -#else - /** - * @brief Erases a [__first,__last) range of elements from a %map. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * - * This function erases a sequence of elements from a %map. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - void - erase(iterator __first, iterator __last) - { _M_t.erase(__first, __last); } -#endif - - /** - * @brief Swaps data with another %map. - * @param __x A %map of the same element and allocator types. - * - * This exchanges the elements between two maps in constant - * time. (It is only swapping a pointer, an integer, and an - * instance of the @c Compare type (which itself is often - * stateless and empty), so it should be quite fast.) Note - * that the global std::swap() function is specialized such - * that std::swap(m1,m2) will feed to this function. - * - * Whether the allocators are swapped depends on the allocator traits. - */ - void - swap(map& __x) - _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) - { _M_t.swap(__x._M_t); } - - /** - * Erases all elements in a %map. Note that this function only - * erases the elements, and that if the elements themselves are - * pointers, the pointed-to memory is not touched in any way. - * Managing the pointer is the user's responsibility. - */ - void - clear() _GLIBCXX_NOEXCEPT - { _M_t.clear(); } - - // observers - /** - * Returns the key comparison object out of which the %map was - * constructed. - */ - key_compare - key_comp() const - { return _M_t.key_comp(); } - - /** - * Returns a value comparison object, built from the key comparison - * object out of which the %map was constructed. - */ - value_compare - value_comp() const - { return value_compare(_M_t.key_comp()); } - - // [23.3.1.3] map operations - - //@{ - /** - * @brief Tries to locate an element in a %map. - * @param __x Key of (key, value) %pair to be located. - * @return Iterator pointing to sought-after element, or end() if not - * found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after %pair. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - - iterator - find(const key_type& __x) - { return _M_t.find(__x); } - -#if __cplusplus > 201103L - template - auto - find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x)) - { return _M_t._M_find_tr(__x); } -#endif - //@} - - //@{ - /** - * @brief Tries to locate an element in a %map. - * @param __x Key of (key, value) %pair to be located. - * @return Read-only (constant) iterator pointing to sought-after - * element, or end() if not found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns a constant - * iterator pointing to the sought after %pair. If unsuccessful it - * returns the past-the-end ( @c end() ) iterator. - */ - - const_iterator - find(const key_type& __x) const - { return _M_t.find(__x); } - -#if __cplusplus > 201103L - template - auto - find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x)) - { return _M_t._M_find_tr(__x); } -#endif - //@} - - //@{ - /** - * @brief Finds the number of elements with given key. - * @param __x Key of (key, value) pairs to be located. - * @return Number of elements with specified key. - * - * This function only makes sense for multimaps; for map the result will - * either be 0 (not present) or 1 (present). - */ - size_type - count(const key_type& __x) const - { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } - -#if __cplusplus > 201103L - template - auto - count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) - { return _M_t._M_count_tr(__x); } -#endif - //@} - -#if __cplusplus > 201703L - //@{ - /** - * @brief Finds whether an element with the given key exists. - * @param __x Key of (key, value) pairs to be located. - * @return True if there is an element with the specified key. - */ - bool - contains(const key_type& __x) const - { return _M_t.find(__x) != _M_t.end(); } - - template - auto - contains(const _Kt& __x) const - -> decltype(_M_t._M_find_tr(__x), void(), true) - { return _M_t._M_find_tr(__x) != _M_t.end(); } - //@} -#endif - - //@{ - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param __x Key of (key, value) pair to be located. - * @return Iterator pointing to first element equal to or greater - * than key, or end(). - * - * This function returns the first element of a subsequence of elements - * that matches the given key. If unsuccessful it returns an iterator - * pointing to the first element that has a greater value than given key - * or end() if no such element exists. - */ - iterator - lower_bound(const key_type& __x) - { return _M_t.lower_bound(__x); } - -#if __cplusplus > 201103L - template - auto - lower_bound(const _Kt& __x) - -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) - { return iterator(_M_t._M_lower_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param __x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to first element - * equal to or greater than key, or end(). - * - * This function returns the first element of a subsequence of elements - * that matches the given key. If unsuccessful it returns an iterator - * pointing to the first element that has a greater value than given key - * or end() if no such element exists. - */ - const_iterator - lower_bound(const key_type& __x) const - { return _M_t.lower_bound(__x); } - -#if __cplusplus > 201103L - template - auto - lower_bound(const _Kt& __x) const - -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) - { return const_iterator(_M_t._M_lower_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds the end of a subsequence matching given key. - * @param __x Key of (key, value) pair to be located. - * @return Iterator pointing to the first element - * greater than key, or end(). - */ - iterator - upper_bound(const key_type& __x) - { return _M_t.upper_bound(__x); } - -#if __cplusplus > 201103L - template - auto - upper_bound(const _Kt& __x) - -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) - { return iterator(_M_t._M_upper_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds the end of a subsequence matching given key. - * @param __x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to first iterator - * greater than key, or end(). - */ - const_iterator - upper_bound(const key_type& __x) const - { return _M_t.upper_bound(__x); } - -#if __cplusplus > 201103L - template - auto - upper_bound(const _Kt& __x) const - -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x))) - { return const_iterator(_M_t._M_upper_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key of (key, value) pairs to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - * - * This function is equivalent to - * @code - * std::make_pair(c.lower_bound(val), - * c.upper_bound(val)) - * @endcode - * (but is faster than making the calls separately). - * - * This function probably only makes sense for multimaps. - */ - std::pair - equal_range(const key_type& __x) - { return _M_t.equal_range(__x); } - -#if __cplusplus > 201103L - template - auto - equal_range(const _Kt& __x) - -> decltype(pair(_M_t._M_equal_range_tr(__x))) - { return pair(_M_t._M_equal_range_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key of (key, value) pairs to be located. - * @return Pair of read-only (constant) iterators that possibly points - * to the subsequence matching given key. - * - * This function is equivalent to - * @code - * std::make_pair(c.lower_bound(val), - * c.upper_bound(val)) - * @endcode - * (but is faster than making the calls separately). - * - * This function probably only makes sense for multimaps. - */ - std::pair - equal_range(const key_type& __x) const - { return _M_t.equal_range(__x); } - -#if __cplusplus > 201103L - template - auto - equal_range(const _Kt& __x) const - -> decltype(pair( - _M_t._M_equal_range_tr(__x))) - { - return pair( - _M_t._M_equal_range_tr(__x)); - } -#endif - //@} - - template - friend bool - operator==(const map<_K1, _T1, _C1, _A1>&, - const map<_K1, _T1, _C1, _A1>&); - -#if __cpp_lib_three_way_comparison - template - friend __detail::__synth3way_t> - operator<=>(const map<_K1, _T1, _C1, _A1>&, - const map<_K1, _T1, _C1, _A1>&); -#else - template - friend bool - operator<(const map<_K1, _T1, _C1, _A1>&, - const map<_K1, _T1, _C1, _A1>&); -#endif - }; - - -#if __cpp_deduction_guides >= 201606 - - template>, - typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireAllocator<_Allocator>> - map(_InputIterator, _InputIterator, - _Compare = _Compare(), _Allocator = _Allocator()) - -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, - _Compare, _Allocator>; - - template, - typename _Allocator = allocator>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireAllocator<_Allocator>> - map(initializer_list>, - _Compare = _Compare(), _Allocator = _Allocator()) - -> map<_Key, _Tp, _Compare, _Allocator>; - - template , - typename = _RequireAllocator<_Allocator>> - map(_InputIterator, _InputIterator, _Allocator) - -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, - less<__iter_key_t<_InputIterator>>, _Allocator>; - - template> - map(initializer_list>, _Allocator) - -> map<_Key, _Tp, less<_Key>, _Allocator>; - -#endif // deduction guides - - /** - * @brief Map equality comparison. - * @param __x A %map. - * @param __y A %map of the same type as @a x. - * @return True iff the size and elements of the maps are equal. - * - * This is an equivalence relation. It is linear in the size of the - * maps. Maps are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. - */ - template - inline bool - operator==(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) - { return __x._M_t == __y._M_t; } - -#if __cpp_lib_three_way_comparison - /** - * @brief Map ordering relation. - * @param __x A `map`. - * @param __y A `map` of the same type as `x`. - * @return A value indicating whether `__x` is less than, equal to, - * greater than, or incomparable with `__y`. - * - * This is a total ordering relation. It is linear in the size of the - * maps. The elements must be comparable with @c <. - * - * See `std::lexicographical_compare_three_way()` for how the determination - * is made. This operator is used to synthesize relational operators like - * `<` and `>=` etc. - */ - template - inline __detail::__synth3way_t> - operator<=>(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) - { return __x._M_t <=> __y._M_t; } -#else - /** - * @brief Map ordering relation. - * @param __x A %map. - * @param __y A %map of the same type as @a x. - * @return True iff @a x is lexicographically less than @a y. - * - * This is a total ordering relation. It is linear in the size of the - * maps. The elements must be comparable with @c <. - * - * See std::lexicographical_compare() for how the determination is made. - */ - template - inline bool - operator<(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) - { return __x._M_t < __y._M_t; } - - /// Based on operator== - template - inline bool - operator!=(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) - { return !(__x == __y); } - - /// Based on operator< - template - inline bool - operator>(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) - { return __y < __x; } - - /// Based on operator< - template - inline bool - operator<=(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) - { return !(__y < __x); } - - /// Based on operator< - template - inline bool - operator>=(const map<_Key, _Tp, _Compare, _Alloc>& __x, - const map<_Key, _Tp, _Compare, _Alloc>& __y) - { return !(__x < __y); } -#endif // three-way comparison - - /// See std::map::swap(). - template - inline void - swap(map<_Key, _Tp, _Compare, _Alloc>& __x, - map<_Key, _Tp, _Compare, _Alloc>& __y) - _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if __cplusplus > 201402L - // Allow std::map access to internals of compatible maps. - template - struct - _Rb_tree_merge_helper<_GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>, - _Cmp2> - { - private: - friend class _GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>; - - static auto& - _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map) - { return __map._M_t; } - - static auto& - _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map) - { return __map._M_t; } - }; -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_MAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h b/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h deleted file mode 100644 index 65f4d0117..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h +++ /dev/null @@ -1,1233 +0,0 @@ -// Multimap implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_multimap.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{map} - */ - -#ifndef _STL_MULTIMAP_H -#define _STL_MULTIMAP_H 1 - -#include -#if __cplusplus >= 201103L -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - class map; - - /** - * @brief A standard container made up of (key,value) pairs, which can be - * retrieved based on a key, in logarithmic time. - * - * @ingroup associative_containers - * - * @tparam _Key Type of key objects. - * @tparam _Tp Type of mapped objects. - * @tparam _Compare Comparison function object type, defaults to less<_Key>. - * @tparam _Alloc Allocator type, defaults to - * allocator. - * - * Meets the requirements of a container, a - * reversible container, and an - * associative container (using equivalent - * keys). For a @c multimap the key_type is Key, the mapped_type - * is T, and the value_type is std::pair. - * - * Multimaps support bidirectional iterators. - * - * The private tree data is declared exactly the same way for map and - * multimap; the distinction is made entirely in how the tree functions are - * called (*_unique versus *_equal, same as the standard). - */ - template , - typename _Alloc = std::allocator > > - class multimap - { - public: - typedef _Key key_type; - typedef _Tp mapped_type; - typedef std::pair value_type; - typedef _Compare key_compare; - typedef _Alloc allocator_type; - - private: -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -# endif - __glibcxx_class_requires4(_Compare, bool, _Key, _Key, - _BinaryFunctionConcept) - __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) -#endif - -#if __cplusplus >= 201103L -#if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same::value, - "std::multimap must have the same value_type as its allocator"); -#endif -#endif - - public: - class value_compare - : public std::binary_function - { - friend class multimap<_Key, _Tp, _Compare, _Alloc>; - protected: - _Compare comp; - - value_compare(_Compare __c) - : comp(__c) { } - - public: - bool operator()(const value_type& __x, const value_type& __y) const - { return comp(__x.first, __y.first); } - }; - - private: - /// This turns a red-black tree into a [multi]map. - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind::other _Pair_alloc_type; - - typedef _Rb_tree, - key_compare, _Pair_alloc_type> _Rep_type; - /// The actual tree structure. - _Rep_type _M_t; - - typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits; - - public: - // many of these are specified differently in ISO, but the following are - // "functionally equivalent" - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; - typedef typename _Rep_type::iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; - typedef typename _Rep_type::reverse_iterator reverse_iterator; - typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; - -#if __cplusplus > 201402L - using node_type = typename _Rep_type::node_type; -#endif - - // [23.3.2] construct/copy/destroy - // (get_allocator() is also listed in this section) - - /** - * @brief Default constructor creates no elements. - */ -#if __cplusplus < 201103L - multimap() : _M_t() { } -#else - multimap() = default; -#endif - - /** - * @brief Creates a %multimap with no elements. - * @param __comp A comparison object. - * @param __a An allocator object. - */ - explicit - multimap(const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Pair_alloc_type(__a)) { } - - /** - * @brief %Multimap copy constructor. - * - * Whether the allocator is copied depends on the allocator traits. - */ -#if __cplusplus < 201103L - multimap(const multimap& __x) - : _M_t(__x._M_t) { } -#else - multimap(const multimap&) = default; - - /** - * @brief %Multimap move constructor. - * - * The newly-created %multimap contains the exact contents of the - * moved instance. The moved instance is a valid, but unspecified - * %multimap. - */ - multimap(multimap&&) = default; - - /** - * @brief Builds a %multimap from an initializer_list. - * @param __l An initializer_list. - * @param __comp A comparison functor. - * @param __a An allocator object. - * - * Create a %multimap consisting of copies of the elements from - * the initializer_list. This is linear in N if the list is already - * sorted, and NlogN otherwise (where N is @a __l.size()). - */ - multimap(initializer_list __l, - const _Compare& __comp = _Compare(), - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Pair_alloc_type(__a)) - { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } - - /// Allocator-extended default constructor. - explicit - multimap(const allocator_type& __a) - : _M_t(_Pair_alloc_type(__a)) { } - - /// Allocator-extended copy constructor. - multimap(const multimap& __m, const allocator_type& __a) - : _M_t(__m._M_t, _Pair_alloc_type(__a)) { } - - /// Allocator-extended move constructor. - multimap(multimap&& __m, const allocator_type& __a) - noexcept(is_nothrow_copy_constructible<_Compare>::value - && _Alloc_traits::_S_always_equal()) - : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { } - - /// Allocator-extended initialier-list constructor. - multimap(initializer_list __l, const allocator_type& __a) - : _M_t(_Pair_alloc_type(__a)) - { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } - - /// Allocator-extended range constructor. - template - multimap(_InputIterator __first, _InputIterator __last, - const allocator_type& __a) - : _M_t(_Pair_alloc_type(__a)) - { _M_t._M_insert_range_equal(__first, __last); } -#endif - - /** - * @brief Builds a %multimap from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * - * Create a %multimap consisting of copies of the elements from - * [__first,__last). This is linear in N if the range is already sorted, - * and NlogN otherwise (where N is distance(__first,__last)). - */ - template - multimap(_InputIterator __first, _InputIterator __last) - : _M_t() - { _M_t._M_insert_range_equal(__first, __last); } - - /** - * @brief Builds a %multimap from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __comp A comparison functor. - * @param __a An allocator object. - * - * Create a %multimap consisting of copies of the elements from - * [__first,__last). This is linear in N if the range is already sorted, - * and NlogN otherwise (where N is distance(__first,__last)). - */ - template - multimap(_InputIterator __first, _InputIterator __last, - const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Pair_alloc_type(__a)) - { _M_t._M_insert_range_equal(__first, __last); } - -#if __cplusplus >= 201103L - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibility. - */ - ~multimap() = default; -#endif - - /** - * @brief %Multimap assignment operator. - * - * Whether the allocator is copied depends on the allocator traits. - */ -#if __cplusplus < 201103L - multimap& - operator=(const multimap& __x) - { - _M_t = __x._M_t; - return *this; - } -#else - multimap& - operator=(const multimap&) = default; - - /// Move assignment operator. - multimap& - operator=(multimap&&) = default; - - /** - * @brief %Multimap list assignment operator. - * @param __l An initializer_list. - * - * This function fills a %multimap with copies of the elements - * in the initializer list @a __l. - * - * Note that the assignment completely changes the %multimap and - * that the resulting %multimap's size is the same as the number - * of elements assigned. - */ - multimap& - operator=(initializer_list __l) - { - _M_t._M_assign_equal(__l.begin(), __l.end()); - return *this; - } -#endif - - /// Get a copy of the memory allocation object. - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_M_t.get_allocator()); } - - // iterators - /** - * Returns a read/write iterator that points to the first pair in the - * %multimap. Iteration is done in ascending order according to the - * keys. - */ - iterator - begin() _GLIBCXX_NOEXCEPT - { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points to the first pair - * in the %multimap. Iteration is done in ascending order according to - * the keys. - */ - const_iterator - begin() const _GLIBCXX_NOEXCEPT - { return _M_t.begin(); } - - /** - * Returns a read/write iterator that points one past the last pair in - * the %multimap. Iteration is done in ascending order according to the - * keys. - */ - iterator - end() _GLIBCXX_NOEXCEPT - { return _M_t.end(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * pair in the %multimap. Iteration is done in ascending order according - * to the keys. - */ - const_iterator - end() const _GLIBCXX_NOEXCEPT - { return _M_t.end(); } - - /** - * Returns a read/write reverse iterator that points to the last pair in - * the %multimap. Iteration is done in descending order according to the - * keys. - */ - reverse_iterator - rbegin() _GLIBCXX_NOEXCEPT - { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last pair in the %multimap. Iteration is done in descending order - * according to the keys. - */ - const_reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return _M_t.rbegin(); } - - /** - * Returns a read/write reverse iterator that points to one before the - * first pair in the %multimap. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - rend() _GLIBCXX_NOEXCEPT - { return _M_t.rend(); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first pair in the %multimap. Iteration is done in - * descending order according to the keys. - */ - const_reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return _M_t.rend(); } - -#if __cplusplus >= 201103L - /** - * Returns a read-only (constant) iterator that points to the first pair - * in the %multimap. Iteration is done in ascending order according to - * the keys. - */ - const_iterator - cbegin() const noexcept - { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * pair in the %multimap. Iteration is done in ascending order according - * to the keys. - */ - const_iterator - cend() const noexcept - { return _M_t.end(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last pair in the %multimap. Iteration is done in descending order - * according to the keys. - */ - const_reverse_iterator - crbegin() const noexcept - { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to one - * before the first pair in the %multimap. Iteration is done in - * descending order according to the keys. - */ - const_reverse_iterator - crend() const noexcept - { return _M_t.rend(); } -#endif - - // capacity - /** Returns true if the %multimap is empty. */ - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return _M_t.empty(); } - - /** Returns the size of the %multimap. */ - size_type - size() const _GLIBCXX_NOEXCEPT - { return _M_t.size(); } - - /** Returns the maximum size of the %multimap. */ - size_type - max_size() const _GLIBCXX_NOEXCEPT - { return _M_t.max_size(); } - - // modifiers -#if __cplusplus >= 201103L - /** - * @brief Build and insert a std::pair into the %multimap. - * - * @param __args Arguments used to generate a new pair instance (see - * std::piecewise_contruct for passing arguments to each - * part of the pair constructor). - * - * @return An iterator that points to the inserted (key,value) pair. - * - * This function builds and inserts a (key, value) %pair into the - * %multimap. - * Contrary to a std::map the %multimap does not rely on unique keys and - * thus multiple pairs with the same key can be inserted. - * - * Insertion requires logarithmic time. - */ - template - iterator - emplace(_Args&&... __args) - { return _M_t._M_emplace_equal(std::forward<_Args>(__args)...); } - - /** - * @brief Builds and inserts a std::pair into the %multimap. - * - * @param __pos An iterator that serves as a hint as to where the pair - * should be inserted. - * @param __args Arguments used to generate a new pair instance (see - * std::piecewise_contruct for passing arguments to each - * part of the pair constructor). - * @return An iterator that points to the inserted (key,value) pair. - * - * This function inserts a (key, value) pair into the %multimap. - * Contrary to a std::map the %multimap does not rely on unique keys and - * thus multiple pairs with the same key can be inserted. - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * For more on @a hinting, see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - template - iterator - emplace_hint(const_iterator __pos, _Args&&... __args) - { - return _M_t._M_emplace_hint_equal(__pos, - std::forward<_Args>(__args)...); - } -#endif - - /** - * @brief Inserts a std::pair into the %multimap. - * @param __x Pair to be inserted (see std::make_pair for easy creation - * of pairs). - * @return An iterator that points to the inserted (key,value) pair. - * - * This function inserts a (key, value) pair into the %multimap. - * Contrary to a std::map the %multimap does not rely on unique keys and - * thus multiple pairs with the same key can be inserted. - * - * Insertion requires logarithmic time. - * @{ - */ - iterator - insert(const value_type& __x) - { return _M_t._M_insert_equal(__x); } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2354. Unnecessary copying when inserting into maps with braced-init - iterator - insert(value_type&& __x) - { return _M_t._M_insert_equal(std::move(__x)); } - - template - __enable_if_t::value, iterator> - insert(_Pair&& __x) - { return _M_t._M_emplace_equal(std::forward<_Pair>(__x)); } -#endif - // @} - - /** - * @brief Inserts a std::pair into the %multimap. - * @param __position An iterator that serves as a hint as to where the - * pair should be inserted. - * @param __x Pair to be inserted (see std::make_pair for easy creation - * of pairs). - * @return An iterator that points to the inserted (key,value) pair. - * - * This function inserts a (key, value) pair into the %multimap. - * Contrary to a std::map the %multimap does not rely on unique keys and - * thus multiple pairs with the same key can be inserted. - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * For more on @a hinting, see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * - * Insertion requires logarithmic time (if the hint is not taken). - * @{ - */ - iterator -#if __cplusplus >= 201103L - insert(const_iterator __position, const value_type& __x) -#else - insert(iterator __position, const value_type& __x) -#endif - { return _M_t._M_insert_equal_(__position, __x); } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2354. Unnecessary copying when inserting into maps with braced-init - iterator - insert(const_iterator __position, value_type&& __x) - { return _M_t._M_insert_equal_(__position, std::move(__x)); } - - template - __enable_if_t::value, iterator> - insert(const_iterator __position, _Pair&& __x) - { - return _M_t._M_emplace_hint_equal(__position, - std::forward<_Pair>(__x)); - } -#endif - // @} - - /** - * @brief A template function that attempts to insert a range - * of elements. - * @param __first Iterator pointing to the start of the range to be - * inserted. - * @param __last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) - { _M_t._M_insert_range_equal(__first, __last); } - -#if __cplusplus >= 201103L - /** - * @brief Attempts to insert a list of std::pairs into the %multimap. - * @param __l A std::initializer_list of pairs to be - * inserted. - * - * Complexity similar to that of the range constructor. - */ - void - insert(initializer_list __l) - { this->insert(__l.begin(), __l.end()); } -#endif - -#if __cplusplus > 201402L - /// Extract a node. - node_type - extract(const_iterator __pos) - { - __glibcxx_assert(__pos != end()); - return _M_t.extract(__pos); - } - - /// Extract a node. - node_type - extract(const key_type& __x) - { return _M_t.extract(__x); } - - /// Re-insert an extracted node. - iterator - insert(node_type&& __nh) - { return _M_t._M_reinsert_node_equal(std::move(__nh)); } - - /// Re-insert an extracted node. - iterator - insert(const_iterator __hint, node_type&& __nh) - { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); } - - template - friend class std::_Rb_tree_merge_helper; - - template - void - merge(multimap<_Key, _Tp, _Cmp2, _Alloc>& __source) - { - using _Merge_helper = _Rb_tree_merge_helper; - _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); - } - - template - void - merge(multimap<_Key, _Tp, _Cmp2, _Alloc>&& __source) - { merge(__source); } - - template - void - merge(map<_Key, _Tp, _Cmp2, _Alloc>& __source) - { - using _Merge_helper = _Rb_tree_merge_helper; - _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); - } - - template - void - merge(map<_Key, _Tp, _Cmp2, _Alloc>&& __source) - { merge(__source); } -#endif // C++17 - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases an element from a %multimap. - * @param __position An iterator pointing to the element to be erased. - * @return An iterator pointing to the element immediately following - * @a position prior to the element being erased. If no such - * element exists, end() is returned. - * - * This function erases an element, pointed to by the given iterator, - * from a %multimap. Note that this function only erases the element, - * and that if the element is itself a pointer, the pointed-to memory is - * not touched in any way. Managing the pointer is the user's - * responsibility. - * - * @{ - */ - iterator - erase(const_iterator __position) - { return _M_t.erase(__position); } - - // LWG 2059. - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(iterator __position) - { return _M_t.erase(__position); } - // @} -#else - /** - * @brief Erases an element from a %multimap. - * @param __position An iterator pointing to the element to be erased. - * - * This function erases an element, pointed to by the given iterator, - * from a %multimap. Note that this function only erases the element, - * and that if the element is itself a pointer, the pointed-to memory is - * not touched in any way. Managing the pointer is the user's - * responsibility. - */ - void - erase(iterator __position) - { _M_t.erase(__position); } -#endif - - /** - * @brief Erases elements according to the provided key. - * @param __x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all elements located by the given key from a - * %multimap. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - size_type - erase(const key_type& __x) - { return _M_t.erase(__x); } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases a [first,last) range of elements from a %multimap. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to be - * erased . - * @return The iterator @a __last. - * - * This function erases a sequence of elements from a %multimap. - * Note that this function only erases the elements, and that if - * the elements themselves are pointers, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's - * responsibility. - */ - iterator - erase(const_iterator __first, const_iterator __last) - { return _M_t.erase(__first, __last); } -#else - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases a [first,last) range of elements from a %multimap. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * - * This function erases a sequence of elements from a %multimap. - * Note that this function only erases the elements, and that if - * the elements themselves are pointers, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's - * responsibility. - */ - void - erase(iterator __first, iterator __last) - { _M_t.erase(__first, __last); } -#endif - - /** - * @brief Swaps data with another %multimap. - * @param __x A %multimap of the same element and allocator types. - * - * This exchanges the elements between two multimaps in constant time. - * (It is only swapping a pointer, an integer, and an instance of - * the @c Compare type (which itself is often stateless and empty), so it - * should be quite fast.) - * Note that the global std::swap() function is specialized such that - * std::swap(m1,m2) will feed to this function. - * - * Whether the allocators are swapped depends on the allocator traits. - */ - void - swap(multimap& __x) - _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) - { _M_t.swap(__x._M_t); } - - /** - * Erases all elements in a %multimap. Note that this function only - * erases the elements, and that if the elements themselves are pointers, - * the pointed-to memory is not touched in any way. Managing the pointer - * is the user's responsibility. - */ - void - clear() _GLIBCXX_NOEXCEPT - { _M_t.clear(); } - - // observers - /** - * Returns the key comparison object out of which the %multimap - * was constructed. - */ - key_compare - key_comp() const - { return _M_t.key_comp(); } - - /** - * Returns a value comparison object, built from the key comparison - * object out of which the %multimap was constructed. - */ - value_compare - value_comp() const - { return value_compare(_M_t.key_comp()); } - - // multimap operations - - //@{ - /** - * @brief Tries to locate an element in a %multimap. - * @param __x Key of (key, value) pair to be located. - * @return Iterator pointing to sought-after element, - * or end() if not found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after %pair. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) - { return _M_t.find(__x); } - -#if __cplusplus > 201103L - template - auto - find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x)) - { return _M_t._M_find_tr(__x); } -#endif - //@} - - //@{ - /** - * @brief Tries to locate an element in a %multimap. - * @param __x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to sought-after - * element, or end() if not found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns a constant - * iterator pointing to the sought after %pair. If unsuccessful it - * returns the past-the-end ( @c end() ) iterator. - */ - const_iterator - find(const key_type& __x) const - { return _M_t.find(__x); } - -#if __cplusplus > 201103L - template - auto - find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x)) - { return _M_t._M_find_tr(__x); } -#endif - //@} - - //@{ - /** - * @brief Finds the number of elements with given key. - * @param __x Key of (key, value) pairs to be located. - * @return Number of elements with specified key. - */ - size_type - count(const key_type& __x) const - { return _M_t.count(__x); } - -#if __cplusplus > 201103L - template - auto - count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) - { return _M_t._M_count_tr(__x); } -#endif - //@} - -#if __cplusplus > 201703L - //@{ - /** - * @brief Finds whether an element with the given key exists. - * @param __x Key of (key, value) pairs to be located. - * @return True if there is any element with the specified key. - */ - bool - contains(const key_type& __x) const - { return _M_t.find(__x) != _M_t.end(); } - - template - auto - contains(const _Kt& __x) const - -> decltype(_M_t._M_find_tr(__x), void(), true) - { return _M_t._M_find_tr(__x) != _M_t.end(); } - //@} -#endif - - //@{ - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param __x Key of (key, value) pair to be located. - * @return Iterator pointing to first element equal to or greater - * than key, or end(). - * - * This function returns the first element of a subsequence of elements - * that matches the given key. If unsuccessful it returns an iterator - * pointing to the first element that has a greater value than given key - * or end() if no such element exists. - */ - iterator - lower_bound(const key_type& __x) - { return _M_t.lower_bound(__x); } - -#if __cplusplus > 201103L - template - auto - lower_bound(const _Kt& __x) - -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) - { return iterator(_M_t._M_lower_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param __x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to first element - * equal to or greater than key, or end(). - * - * This function returns the first element of a subsequence of - * elements that matches the given key. If unsuccessful the - * iterator will point to the next greatest element or, if no - * such greater element exists, to end(). - */ - const_iterator - lower_bound(const key_type& __x) const - { return _M_t.lower_bound(__x); } - -#if __cplusplus > 201103L - template - auto - lower_bound(const _Kt& __x) const - -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) - { return const_iterator(_M_t._M_lower_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds the end of a subsequence matching given key. - * @param __x Key of (key, value) pair to be located. - * @return Iterator pointing to the first element - * greater than key, or end(). - */ - iterator - upper_bound(const key_type& __x) - { return _M_t.upper_bound(__x); } - -#if __cplusplus > 201103L - template - auto - upper_bound(const _Kt& __x) - -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) - { return iterator(_M_t._M_upper_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds the end of a subsequence matching given key. - * @param __x Key of (key, value) pair to be located. - * @return Read-only (constant) iterator pointing to first iterator - * greater than key, or end(). - */ - const_iterator - upper_bound(const key_type& __x) const - { return _M_t.upper_bound(__x); } - -#if __cplusplus > 201103L - template - auto - upper_bound(const _Kt& __x) const - -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x))) - { return const_iterator(_M_t._M_upper_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key of (key, value) pairs to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - * - * This function is equivalent to - * @code - * std::make_pair(c.lower_bound(val), - * c.upper_bound(val)) - * @endcode - * (but is faster than making the calls separately). - */ - std::pair - equal_range(const key_type& __x) - { return _M_t.equal_range(__x); } - -#if __cplusplus > 201103L - template - auto - equal_range(const _Kt& __x) - -> decltype(pair(_M_t._M_equal_range_tr(__x))) - { return pair(_M_t._M_equal_range_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key of (key, value) pairs to be located. - * @return Pair of read-only (constant) iterators that possibly points - * to the subsequence matching given key. - * - * This function is equivalent to - * @code - * std::make_pair(c.lower_bound(val), - * c.upper_bound(val)) - * @endcode - * (but is faster than making the calls separately). - */ - std::pair - equal_range(const key_type& __x) const - { return _M_t.equal_range(__x); } - -#if __cplusplus > 201103L - template - auto - equal_range(const _Kt& __x) const - -> decltype(pair( - _M_t._M_equal_range_tr(__x))) - { - return pair( - _M_t._M_equal_range_tr(__x)); - } -#endif - //@} - - template - friend bool - operator==(const multimap<_K1, _T1, _C1, _A1>&, - const multimap<_K1, _T1, _C1, _A1>&); - -#if __cpp_lib_three_way_comparison - template - friend __detail::__synth3way_t> - operator<=>(const multimap<_K1, _T1, _C1, _A1>&, - const multimap<_K1, _T1, _C1, _A1>&); -#else - template - friend bool - operator<(const multimap<_K1, _T1, _C1, _A1>&, - const multimap<_K1, _T1, _C1, _A1>&); -#endif - }; - -#if __cpp_deduction_guides >= 201606 - - template>, - typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireAllocator<_Allocator>> - multimap(_InputIterator, _InputIterator, - _Compare = _Compare(), _Allocator = _Allocator()) - -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, - _Compare, _Allocator>; - - template, - typename _Allocator = allocator>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireAllocator<_Allocator>> - multimap(initializer_list>, - _Compare = _Compare(), _Allocator = _Allocator()) - -> multimap<_Key, _Tp, _Compare, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - multimap(_InputIterator, _InputIterator, _Allocator) - -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, - less<__iter_key_t<_InputIterator>>, _Allocator>; - - template> - multimap(initializer_list>, _Allocator) - -> multimap<_Key, _Tp, less<_Key>, _Allocator>; - -#endif // deduction guides - - /** - * @brief Multimap equality comparison. - * @param __x A %multimap. - * @param __y A %multimap of the same type as @a __x. - * @return True iff the size and elements of the maps are equal. - * - * This is an equivalence relation. It is linear in the size of the - * multimaps. Multimaps are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. - */ - template - inline bool - operator==(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) - { return __x._M_t == __y._M_t; } - -#if __cpp_lib_three_way_comparison - /** - * @brief Multimap ordering relation. - * @param __x A `multimap`. - * @param __y A `multimap` of the same type as `x`. - * @return A value indicating whether `__x` is less than, equal to, - * greater than, or incomparable with `__y`. - * - * This is a total ordering relation. It is linear in the size of the - * maps. The elements must be comparable with @c <. - * - * See `std::lexicographical_compare_three_way()` for how the determination - * is made. This operator is used to synthesize relational operators like - * `<` and `>=` etc. - */ - template - inline __detail::__synth3way_t> - operator<=>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) - { return __x._M_t <=> __y._M_t; } -#else - /** - * @brief Multimap ordering relation. - * @param __x A %multimap. - * @param __y A %multimap of the same type as @a __x. - * @return True iff @a x is lexicographically less than @a y. - * - * This is a total ordering relation. It is linear in the size of the - * multimaps. The elements must be comparable with @c <. - * - * See std::lexicographical_compare() for how the determination is made. - */ - template - inline bool - operator<(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) - { return __x._M_t < __y._M_t; } - - /// Based on operator== - template - inline bool - operator!=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) - { return !(__x == __y); } - - /// Based on operator< - template - inline bool - operator>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) - { return __y < __x; } - - /// Based on operator< - template - inline bool - operator<=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) - { return !(__y < __x); } - - /// Based on operator< - template - inline bool - operator>=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, - const multimap<_Key, _Tp, _Compare, _Alloc>& __y) - { return !(__x < __y); } -#endif // three-way comparison - - /// See std::multimap::swap(). - template - inline void - swap(multimap<_Key, _Tp, _Compare, _Alloc>& __x, - multimap<_Key, _Tp, _Compare, _Alloc>& __y) - _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if __cplusplus > 201402L - // Allow std::multimap access to internals of compatible maps. - template - struct - _Rb_tree_merge_helper<_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>, - _Cmp2> - { - private: - friend class _GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>; - - static auto& - _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map) - { return __map._M_t; } - - static auto& - _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map) - { return __map._M_t; } - }; -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_MULTIMAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h b/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h deleted file mode 100644 index bf6ae7de0..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h +++ /dev/null @@ -1,1075 +0,0 @@ -// Multiset implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_multiset.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{set} - */ - -#ifndef _STL_MULTISET_H -#define _STL_MULTISET_H 1 - -#include -#if __cplusplus >= 201103L -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - class set; - - /** - * @brief A standard container made up of elements, which can be retrieved - * in logarithmic time. - * - * @ingroup associative_containers - * - * - * @tparam _Key Type of key objects. - * @tparam _Compare Comparison function object type, defaults to less<_Key>. - * @tparam _Alloc Allocator type, defaults to allocator<_Key>. - * - * Meets the requirements of a container, a - * reversible container, and an - * associative container (using equivalent - * keys). For a @c multiset the key_type and value_type are Key. - * - * Multisets support bidirectional iterators. - * - * The private tree data is declared exactly the same way for set and - * multiset; the distinction is made entirely in how the tree functions are - * called (*_unique versus *_equal, same as the standard). - */ - template , - typename _Alloc = std::allocator<_Key> > - class multiset - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Key, _SGIAssignableConcept) -# endif - __glibcxx_class_requires4(_Compare, bool, _Key, _Key, - _BinaryFunctionConcept) - __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) -#endif - -#if __cplusplus >= 201103L - static_assert(is_same::type, _Key>::value, - "std::multiset must have a non-const, non-volatile value_type"); -# if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same::value, - "std::multiset must have the same value_type as its allocator"); -# endif -#endif - - public: - // typedefs: - typedef _Key key_type; - typedef _Key value_type; - typedef _Compare key_compare; - typedef _Compare value_compare; - typedef _Alloc allocator_type; - - private: - /// This turns a red-black tree into a [multi]set. - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_Key>::other _Key_alloc_type; - - typedef _Rb_tree, - key_compare, _Key_alloc_type> _Rep_type; - /// The actual tree structure. - _Rep_type _M_t; - - typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits; - - public: - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 103. set::iterator is required to be modifiable, - // but this allows modification of keys. - typedef typename _Rep_type::const_iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::const_reverse_iterator reverse_iterator; - typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; - -#if __cplusplus > 201402L - using node_type = typename _Rep_type::node_type; -#endif - - // allocation/deallocation - /** - * @brief Default constructor creates no elements. - */ -#if __cplusplus < 201103L - multiset() : _M_t() { } -#else - multiset() = default; -#endif - - /** - * @brief Creates a %multiset with no elements. - * @param __comp Comparator to use. - * @param __a An allocator object. - */ - explicit - multiset(const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Key_alloc_type(__a)) { } - - /** - * @brief Builds a %multiset from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * - * Create a %multiset consisting of copies of the elements from - * [first,last). This is linear in N if the range is already sorted, - * and NlogN otherwise (where N is distance(__first,__last)). - */ - template - multiset(_InputIterator __first, _InputIterator __last) - : _M_t() - { _M_t._M_insert_range_equal(__first, __last); } - - /** - * @brief Builds a %multiset from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __comp A comparison functor. - * @param __a An allocator object. - * - * Create a %multiset consisting of copies of the elements from - * [__first,__last). This is linear in N if the range is already sorted, - * and NlogN otherwise (where N is distance(__first,__last)). - */ - template - multiset(_InputIterator __first, _InputIterator __last, - const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Key_alloc_type(__a)) - { _M_t._M_insert_range_equal(__first, __last); } - - /** - * @brief %Multiset copy constructor. - * - * Whether the allocator is copied depends on the allocator traits. - */ -#if __cplusplus < 201103L - multiset(const multiset& __x) - : _M_t(__x._M_t) { } -#else - multiset(const multiset&) = default; - - /** - * @brief %Multiset move constructor. - * - * The newly-created %multiset contains the exact contents of the - * moved instance. The moved instance is a valid, but unspecified - * %multiset. - */ - multiset(multiset&&) = default; - - /** - * @brief Builds a %multiset from an initializer_list. - * @param __l An initializer_list. - * @param __comp A comparison functor. - * @param __a An allocator object. - * - * Create a %multiset consisting of copies of the elements from - * the list. This is linear in N if the list is already sorted, - * and NlogN otherwise (where N is @a __l.size()). - */ - multiset(initializer_list __l, - const _Compare& __comp = _Compare(), - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Key_alloc_type(__a)) - { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } - - /// Allocator-extended default constructor. - explicit - multiset(const allocator_type& __a) - : _M_t(_Key_alloc_type(__a)) { } - - /// Allocator-extended copy constructor. - multiset(const multiset& __m, const allocator_type& __a) - : _M_t(__m._M_t, _Key_alloc_type(__a)) { } - - /// Allocator-extended move constructor. - multiset(multiset&& __m, const allocator_type& __a) - noexcept(is_nothrow_copy_constructible<_Compare>::value - && _Alloc_traits::_S_always_equal()) - : _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { } - - /// Allocator-extended initialier-list constructor. - multiset(initializer_list __l, const allocator_type& __a) - : _M_t(_Key_alloc_type(__a)) - { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } - - /// Allocator-extended range constructor. - template - multiset(_InputIterator __first, _InputIterator __last, - const allocator_type& __a) - : _M_t(_Key_alloc_type(__a)) - { _M_t._M_insert_range_equal(__first, __last); } - - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibility. - */ - ~multiset() = default; -#endif - - /** - * @brief %Multiset assignment operator. - * - * Whether the allocator is copied depends on the allocator traits. - */ -#if __cplusplus < 201103L - multiset& - operator=(const multiset& __x) - { - _M_t = __x._M_t; - return *this; - } -#else - multiset& - operator=(const multiset&) = default; - - /// Move assignment operator. - multiset& - operator=(multiset&&) = default; - - /** - * @brief %Multiset list assignment operator. - * @param __l An initializer_list. - * - * This function fills a %multiset with copies of the elements in the - * initializer list @a __l. - * - * Note that the assignment completely changes the %multiset and - * that the resulting %multiset's size is the same as the number - * of elements assigned. - */ - multiset& - operator=(initializer_list __l) - { - _M_t._M_assign_equal(__l.begin(), __l.end()); - return *this; - } -#endif - - // accessors: - - /// Returns the comparison object. - key_compare - key_comp() const - { return _M_t.key_comp(); } - /// Returns the comparison object. - value_compare - value_comp() const - { return _M_t.key_comp(); } - /// Returns the memory allocation object. - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_M_t.get_allocator()); } - - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %multiset. Iteration is done in ascending order - * according to the keys. - */ - iterator - begin() const _GLIBCXX_NOEXCEPT - { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %multiset. Iteration is done in ascending order - * according to the keys. - */ - iterator - end() const _GLIBCXX_NOEXCEPT - { return _M_t.end(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last element in the %multiset. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last element in the %multiset. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return _M_t.rend(); } - -#if __cplusplus >= 201103L - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %multiset. Iteration is done in ascending order - * according to the keys. - */ - iterator - cbegin() const noexcept - { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %multiset. Iteration is done in ascending order - * according to the keys. - */ - iterator - cend() const noexcept - { return _M_t.end(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last element in the %multiset. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - crbegin() const noexcept - { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last element in the %multiset. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - crend() const noexcept - { return _M_t.rend(); } -#endif - - /// Returns true if the %set is empty. - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return _M_t.empty(); } - - /// Returns the size of the %set. - size_type - size() const _GLIBCXX_NOEXCEPT - { return _M_t.size(); } - - /// Returns the maximum size of the %set. - size_type - max_size() const _GLIBCXX_NOEXCEPT - { return _M_t.max_size(); } - - /** - * @brief Swaps data with another %multiset. - * @param __x A %multiset of the same element and allocator types. - * - * This exchanges the elements between two multisets in constant time. - * (It is only swapping a pointer, an integer, and an instance of the @c - * Compare type (which itself is often stateless and empty), so it should - * be quite fast.) - * Note that the global std::swap() function is specialized such that - * std::swap(s1,s2) will feed to this function. - * - * Whether the allocators are swapped depends on the allocator traits. - */ - void - swap(multiset& __x) - _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) - { _M_t.swap(__x._M_t); } - - // insert/erase -#if __cplusplus >= 201103L - /** - * @brief Builds and inserts an element into the %multiset. - * @param __args Arguments used to generate the element instance to be - * inserted. - * @return An iterator that points to the inserted element. - * - * This function inserts an element into the %multiset. Contrary - * to a std::set the %multiset does not rely on unique keys and thus - * multiple copies of the same element can be inserted. - * - * Insertion requires logarithmic time. - */ - template - iterator - emplace(_Args&&... __args) - { return _M_t._M_emplace_equal(std::forward<_Args>(__args)...); } - - /** - * @brief Builds and inserts an element into the %multiset. - * @param __pos An iterator that serves as a hint as to where the - * element should be inserted. - * @param __args Arguments used to generate the element instance to be - * inserted. - * @return An iterator that points to the inserted element. - * - * This function inserts an element into the %multiset. Contrary - * to a std::set the %multiset does not rely on unique keys and thus - * multiple copies of the same element can be inserted. - * - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - template - iterator - emplace_hint(const_iterator __pos, _Args&&... __args) - { - return _M_t._M_emplace_hint_equal(__pos, - std::forward<_Args>(__args)...); - } -#endif - - /** - * @brief Inserts an element into the %multiset. - * @param __x Element to be inserted. - * @return An iterator that points to the inserted element. - * - * This function inserts an element into the %multiset. Contrary - * to a std::set the %multiset does not rely on unique keys and thus - * multiple copies of the same element can be inserted. - * - * Insertion requires logarithmic time. - */ - iterator - insert(const value_type& __x) - { return _M_t._M_insert_equal(__x); } - -#if __cplusplus >= 201103L - iterator - insert(value_type&& __x) - { return _M_t._M_insert_equal(std::move(__x)); } -#endif - - /** - * @brief Inserts an element into the %multiset. - * @param __position An iterator that serves as a hint as to where the - * element should be inserted. - * @param __x Element to be inserted. - * @return An iterator that points to the inserted element. - * - * This function inserts an element into the %multiset. Contrary - * to a std::set the %multiset does not rely on unique keys and thus - * multiple copies of the same element can be inserted. - * - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - iterator - insert(const_iterator __position, const value_type& __x) - { return _M_t._M_insert_equal_(__position, __x); } - -#if __cplusplus >= 201103L - iterator - insert(const_iterator __position, value_type&& __x) - { return _M_t._M_insert_equal_(__position, std::move(__x)); } -#endif - - /** - * @brief A template function that tries to insert a range of elements. - * @param __first Iterator pointing to the start of the range to be - * inserted. - * @param __last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) - { _M_t._M_insert_range_equal(__first, __last); } - -#if __cplusplus >= 201103L - /** - * @brief Attempts to insert a list of elements into the %multiset. - * @param __l A std::initializer_list of elements - * to be inserted. - * - * Complexity similar to that of the range constructor. - */ - void - insert(initializer_list __l) - { this->insert(__l.begin(), __l.end()); } -#endif - -#if __cplusplus > 201402L - /// Extract a node. - node_type - extract(const_iterator __pos) - { - __glibcxx_assert(__pos != end()); - return _M_t.extract(__pos); - } - - /// Extract a node. - node_type - extract(const key_type& __x) - { return _M_t.extract(__x); } - - /// Re-insert an extracted node. - iterator - insert(node_type&& __nh) - { return _M_t._M_reinsert_node_equal(std::move(__nh)); } - - /// Re-insert an extracted node. - iterator - insert(const_iterator __hint, node_type&& __nh) - { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); } - - template - friend class std::_Rb_tree_merge_helper; - - template - void - merge(multiset<_Key, _Compare1, _Alloc>& __source) - { - using _Merge_helper = _Rb_tree_merge_helper; - _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); - } - - template - void - merge(multiset<_Key, _Compare1, _Alloc>&& __source) - { merge(__source); } - - template - void - merge(set<_Key, _Compare1, _Alloc>& __source) - { - using _Merge_helper = _Rb_tree_merge_helper; - _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); - } - - template - void - merge(set<_Key, _Compare1, _Alloc>&& __source) - { merge(__source); } -#endif // C++17 - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases an element from a %multiset. - * @param __position An iterator pointing to the element to be erased. - * @return An iterator pointing to the element immediately following - * @a position prior to the element being erased. If no such - * element exists, end() is returned. - * - * This function erases an element, pointed to by the given iterator, - * from a %multiset. Note that this function only erases the element, - * and that if the element is itself a pointer, the pointed-to memory is - * not touched in any way. Managing the pointer is the user's - * responsibility. - */ - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(const_iterator __position) - { return _M_t.erase(__position); } -#else - /** - * @brief Erases an element from a %multiset. - * @param __position An iterator pointing to the element to be erased. - * - * This function erases an element, pointed to by the given iterator, - * from a %multiset. Note that this function only erases the element, - * and that if the element is itself a pointer, the pointed-to memory is - * not touched in any way. Managing the pointer is the user's - * responsibility. - */ - void - erase(iterator __position) - { _M_t.erase(__position); } -#endif - - /** - * @brief Erases elements according to the provided key. - * @param __x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all elements located by the given key from a - * %multiset. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - size_type - erase(const key_type& __x) - { return _M_t.erase(__x); } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases a [first,last) range of elements from a %multiset. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * @return The iterator @a last. - * - * This function erases a sequence of elements from a %multiset. - * Note that this function only erases the elements, and that if - * the elements themselves are pointers, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's - * responsibility. - */ - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(const_iterator __first, const_iterator __last) - { return _M_t.erase(__first, __last); } -#else - /** - * @brief Erases a [first,last) range of elements from a %multiset. - * @param first Iterator pointing to the start of the range to be - * erased. - * @param last Iterator pointing to the end of the range to be erased. - * - * This function erases a sequence of elements from a %multiset. - * Note that this function only erases the elements, and that if - * the elements themselves are pointers, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's - * responsibility. - */ - void - erase(iterator __first, iterator __last) - { _M_t.erase(__first, __last); } -#endif - - /** - * Erases all elements in a %multiset. Note that this function only - * erases the elements, and that if the elements themselves are pointers, - * the pointed-to memory is not touched in any way. Managing the pointer - * is the user's responsibility. - */ - void - clear() _GLIBCXX_NOEXCEPT - { _M_t.clear(); } - - // multiset operations: - - //@{ - /** - * @brief Finds the number of elements with given key. - * @param __x Key of elements to be located. - * @return Number of elements with specified key. - */ - size_type - count(const key_type& __x) const - { return _M_t.count(__x); } - -#if __cplusplus > 201103L - template - auto - count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) - { return _M_t._M_count_tr(__x); } -#endif - //@} - -#if __cplusplus > 201703L - //@{ - /** - * @brief Finds whether an element with the given key exists. - * @param __x Key of elements to be located. - * @return True if there is any element with the specified key. - */ - bool - contains(const key_type& __x) const - { return _M_t.find(__x) != _M_t.end(); } - - template - auto - contains(const _Kt& __x) const - -> decltype(_M_t._M_find_tr(__x), void(), true) - { return _M_t._M_find_tr(__x) != _M_t.end(); } - //@} -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 214. set::find() missing const overload - //@{ - /** - * @brief Tries to locate an element in a %set. - * @param __x Element to be located. - * @return Iterator pointing to sought-after element, or end() if not - * found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after element. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) - { return _M_t.find(__x); } - - const_iterator - find(const key_type& __x) const - { return _M_t.find(__x); } - -#if __cplusplus > 201103L - template - auto - find(const _Kt& __x) - -> decltype(iterator{_M_t._M_find_tr(__x)}) - { return iterator{_M_t._M_find_tr(__x)}; } - - template - auto - find(const _Kt& __x) const - -> decltype(const_iterator{_M_t._M_find_tr(__x)}) - { return const_iterator{_M_t._M_find_tr(__x)}; } -#endif - //@} - - //@{ - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param __x Key to be located. - * @return Iterator pointing to first element equal to or greater - * than key, or end(). - * - * This function returns the first element of a subsequence of elements - * that matches the given key. If unsuccessful it returns an iterator - * pointing to the first element that has a greater value than given key - * or end() if no such element exists. - */ - iterator - lower_bound(const key_type& __x) - { return _M_t.lower_bound(__x); } - - const_iterator - lower_bound(const key_type& __x) const - { return _M_t.lower_bound(__x); } - -#if __cplusplus > 201103L - template - auto - lower_bound(const _Kt& __x) - -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) - { return iterator(_M_t._M_lower_bound_tr(__x)); } - - template - auto - lower_bound(const _Kt& __x) const - -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) - { return iterator(_M_t._M_lower_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds the end of a subsequence matching given key. - * @param __x Key to be located. - * @return Iterator pointing to the first element - * greater than key, or end(). - */ - iterator - upper_bound(const key_type& __x) - { return _M_t.upper_bound(__x); } - - const_iterator - upper_bound(const key_type& __x) const - { return _M_t.upper_bound(__x); } - -#if __cplusplus > 201103L - template - auto - upper_bound(const _Kt& __x) - -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) - { return iterator(_M_t._M_upper_bound_tr(__x)); } - - template - auto - upper_bound(const _Kt& __x) const - -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) - { return iterator(_M_t._M_upper_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - * - * This function is equivalent to - * @code - * std::make_pair(c.lower_bound(val), - * c.upper_bound(val)) - * @endcode - * (but is faster than making the calls separately). - * - * This function probably only makes sense for multisets. - */ - std::pair - equal_range(const key_type& __x) - { return _M_t.equal_range(__x); } - - std::pair - equal_range(const key_type& __x) const - { return _M_t.equal_range(__x); } - -#if __cplusplus > 201103L - template - auto - equal_range(const _Kt& __x) - -> decltype(pair(_M_t._M_equal_range_tr(__x))) - { return pair(_M_t._M_equal_range_tr(__x)); } - - template - auto - equal_range(const _Kt& __x) const - -> decltype(pair(_M_t._M_equal_range_tr(__x))) - { return pair(_M_t._M_equal_range_tr(__x)); } -#endif - //@} - - template - friend bool - operator==(const multiset<_K1, _C1, _A1>&, - const multiset<_K1, _C1, _A1>&); - -#if __cpp_lib_three_way_comparison - template - friend __detail::__synth3way_t<_K1> - operator<=>(const multiset<_K1, _C1, _A1>&, - const multiset<_K1, _C1, _A1>&); -#else - template - friend bool - operator< (const multiset<_K1, _C1, _A1>&, - const multiset<_K1, _C1, _A1>&); -#endif - }; - -#if __cpp_deduction_guides >= 201606 - - template::value_type>, - typename _Allocator = - allocator::value_type>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireAllocator<_Allocator>> - multiset(_InputIterator, _InputIterator, - _Compare = _Compare(), _Allocator = _Allocator()) - -> multiset::value_type, - _Compare, _Allocator>; - - template, - typename _Allocator = allocator<_Key>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireAllocator<_Allocator>> - multiset(initializer_list<_Key>, - _Compare = _Compare(), _Allocator = _Allocator()) - -> multiset<_Key, _Compare, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - multiset(_InputIterator, _InputIterator, _Allocator) - -> multiset::value_type, - less::value_type>, - _Allocator>; - - template> - multiset(initializer_list<_Key>, _Allocator) - -> multiset<_Key, less<_Key>, _Allocator>; - -#endif // deduction guides - - /** - * @brief Multiset equality comparison. - * @param __x A %multiset. - * @param __y A %multiset of the same type as @a __x. - * @return True iff the size and elements of the multisets are equal. - * - * This is an equivalence relation. It is linear in the size of the - * multisets. - * Multisets are considered equivalent if their sizes are equal, and if - * corresponding elements compare equal. - */ - template - inline bool - operator==(const multiset<_Key, _Compare, _Alloc>& __x, - const multiset<_Key, _Compare, _Alloc>& __y) - { return __x._M_t == __y._M_t; } - -#if __cpp_lib_three_way_comparison - /** - * @brief Multiset ordering relation. - * @param __x A `multiset`. - * @param __y A `multiset` of the same type as `x`. - * @return A value indicating whether `__x` is less than, equal to, - * greater than, or incomparable with `__y`. - * - * This is a total ordering relation. It is linear in the size of the - * maps. The elements must be comparable with @c <. - * - * See `std::lexicographical_compare_three_way()` for how the determination - * is made. This operator is used to synthesize relational operators like - * `<` and `>=` etc. - */ - template - inline __detail::__synth3way_t<_Key> - operator<=>(const multiset<_Key, _Compare, _Alloc>& __x, - const multiset<_Key, _Compare, _Alloc>& __y) - { return __x._M_t <=> __y._M_t; } -#else - /** - * @brief Multiset ordering relation. - * @param __x A %multiset. - * @param __y A %multiset of the same type as @a __x. - * @return True iff @a __x is lexicographically less than @a __y. - * - * This is a total ordering relation. It is linear in the size of the - * sets. The elements must be comparable with @c <. - * - * See std::lexicographical_compare() for how the determination is made. - */ - template - inline bool - operator<(const multiset<_Key, _Compare, _Alloc>& __x, - const multiset<_Key, _Compare, _Alloc>& __y) - { return __x._M_t < __y._M_t; } - - /// Returns !(x == y). - template - inline bool - operator!=(const multiset<_Key, _Compare, _Alloc>& __x, - const multiset<_Key, _Compare, _Alloc>& __y) - { return !(__x == __y); } - - /// Returns y < x. - template - inline bool - operator>(const multiset<_Key,_Compare,_Alloc>& __x, - const multiset<_Key,_Compare,_Alloc>& __y) - { return __y < __x; } - - /// Returns !(y < x) - template - inline bool - operator<=(const multiset<_Key, _Compare, _Alloc>& __x, - const multiset<_Key, _Compare, _Alloc>& __y) - { return !(__y < __x); } - - /// Returns !(x < y) - template - inline bool - operator>=(const multiset<_Key, _Compare, _Alloc>& __x, - const multiset<_Key, _Compare, _Alloc>& __y) - { return !(__x < __y); } -#endif // three-way comparison - - /// See std::multiset::swap(). - template - inline void - swap(multiset<_Key, _Compare, _Alloc>& __x, - multiset<_Key, _Compare, _Alloc>& __y) - _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if __cplusplus > 201402L - // Allow std::multiset access to internals of compatible sets. - template - struct - _Rb_tree_merge_helper<_GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>, - _Cmp2> - { - private: - friend class _GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>; - - static auto& - _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set) - { return __set._M_t; } - - static auto& - _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) - { return __set._M_t; } - }; -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_MULTISET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h b/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h deleted file mode 100644 index f95c86a0d..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h +++ /dev/null @@ -1,413 +0,0 @@ -// Numeric functions implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_numeric.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{numeric} - */ - -#ifndef _STL_NUMERIC_H -#define _STL_NUMERIC_H 1 - -#include -#include -#include // For _GLIBCXX_MOVE - - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** @defgroup numeric_ops Generalized Numeric operations - * @ingroup algorithms - */ - -#if __cplusplus >= 201103L - /** - * @brief Create a range of sequentially increasing values. - * - * For each element in the range @p [first,last) assigns @p value and - * increments @p value as if by @p ++value. - * - * @param __first Start of range. - * @param __last End of range. - * @param __value Starting value. - * @return Nothing. - * @ingroup numeric_ops - */ - template - _GLIBCXX20_CONSTEXPR - void - iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< - _ForwardIterator>) - __glibcxx_function_requires(_ConvertibleConcept<_Tp, - typename iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first) - { - *__first = __value; - ++__value; - } - } -#endif - -_GLIBCXX_END_NAMESPACE_VERSION - -_GLIBCXX_BEGIN_NAMESPACE_ALGO - -#if __cplusplus > 201703L -// _GLIBCXX_RESOLVE_LIB_DEFECTS -// DR 2055. std::move in std::accumulate and other algorithms -# define _GLIBCXX_MOVE_IF_20(_E) std::move(_E) -#else -# define _GLIBCXX_MOVE_IF_20(_E) _E -#endif - - /// @addtogroup numeric_ops - /// @{ - - /** - * @brief Accumulate values in a range. - * - * Accumulates the values in the range [first,last) using operator+(). The - * initial value is @a init. The values are processed in order. - * - * @param __first Start of range. - * @param __last End of range. - * @param __init Starting value to add other values to. - * @return The final sum. - */ - template - _GLIBCXX20_CONSTEXPR - inline _Tp - accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first) - __init = _GLIBCXX_MOVE_IF_20(__init) + *__first; - return __init; - } - - /** - * @brief Accumulate values in a range with operation. - * - * Accumulates the values in the range `[first,last)` using the function - * object `__binary_op`. The initial value is `__init`. The values are - * processed in order. - * - * @param __first Start of range. - * @param __last End of range. - * @param __init Starting value to add other values to. - * @param __binary_op Function object to accumulate with. - * @return The final sum. - */ - template - _GLIBCXX20_CONSTEXPR - inline _Tp - accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, - _BinaryOperation __binary_op) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_requires_valid_range(__first, __last); - - for (; __first != __last; ++__first) - __init = __binary_op(_GLIBCXX_MOVE_IF_20(__init), *__first); - return __init; - } - - /** - * @brief Compute inner product of two ranges. - * - * Starting with an initial value of @p __init, multiplies successive - * elements from the two ranges and adds each product into the accumulated - * value using operator+(). The values in the ranges are processed in - * order. - * - * @param __first1 Start of range 1. - * @param __last1 End of range 1. - * @param __first2 Start of range 2. - * @param __init Starting value to add other values to. - * @return The final inner product. - */ - template - _GLIBCXX20_CONSTEXPR - inline _Tp - inner_product(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _Tp __init) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_requires_valid_range(__first1, __last1); - - for (; __first1 != __last1; ++__first1, (void)++__first2) - __init = _GLIBCXX_MOVE_IF_20(__init) + (*__first1 * *__first2); - return __init; - } - - /** - * @brief Compute inner product of two ranges. - * - * Starting with an initial value of @p __init, applies @p __binary_op2 to - * successive elements from the two ranges and accumulates each result into - * the accumulated value using @p __binary_op1. The values in the ranges are - * processed in order. - * - * @param __first1 Start of range 1. - * @param __last1 End of range 1. - * @param __first2 Start of range 2. - * @param __init Starting value to add other values to. - * @param __binary_op1 Function object to accumulate with. - * @param __binary_op2 Function object to apply to pairs of input values. - * @return The final inner product. - */ - template - _GLIBCXX20_CONSTEXPR - inline _Tp - inner_product(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _Tp __init, - _BinaryOperation1 __binary_op1, - _BinaryOperation2 __binary_op2) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_requires_valid_range(__first1, __last1); - - for (; __first1 != __last1; ++__first1, (void)++__first2) - __init = __binary_op1(_GLIBCXX_MOVE_IF_20(__init), - __binary_op2(*__first1, *__first2)); - return __init; - } - - /** - * @brief Return list of partial sums - * - * Accumulates the values in the range [first,last) using the @c + operator. - * As each successive input value is added into the total, that partial sum - * is written to @p __result. Therefore, the first value in @p __result is - * the first value of the input, the second value in @p __result is the sum - * of the first and second input values, and so on. - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Output sum. - * @return Iterator pointing just beyond the values written to __result. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - partial_sum(_InputIterator __first, _InputIterator __last, - _OutputIterator __result) - { - typedef typename iterator_traits<_InputIterator>::value_type _ValueType; - - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - _ValueType>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return __result; - _ValueType __value = *__first; - *__result = __value; - while (++__first != __last) - { - __value = _GLIBCXX_MOVE_IF_20(__value) + *__first; - *++__result = __value; - } - return ++__result; - } - - /** - * @brief Return list of partial sums - * - * Accumulates the values in the range [first,last) using @p __binary_op. - * As each successive input value is added into the total, that partial sum - * is written to @p __result. Therefore, the first value in @p __result is - * the first value of the input, the second value in @p __result is the sum - * of the first and second input values, and so on. - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Output sum. - * @param __binary_op Function object. - * @return Iterator pointing just beyond the values written to __result. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - partial_sum(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _BinaryOperation __binary_op) - { - typedef typename iterator_traits<_InputIterator>::value_type _ValueType; - - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - _ValueType>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return __result; - _ValueType __value = *__first; - *__result = __value; - while (++__first != __last) - { - __value = __binary_op(_GLIBCXX_MOVE_IF_20(__value), *__first); - *++__result = __value; - } - return ++__result; - } - - /** - * @brief Return differences between adjacent values. - * - * Computes the difference between adjacent values in the range - * [first,last) using operator-() and writes the result to @p __result. - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Output sums. - * @return Iterator pointing just beyond the values written to result. - * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 539. partial_sum and adjacent_difference should mention requirements - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - adjacent_difference(_InputIterator __first, - _InputIterator __last, _OutputIterator __result) - { - typedef typename iterator_traits<_InputIterator>::value_type _ValueType; - - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - _ValueType>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return __result; - _ValueType __value = *__first; - *__result = __value; - while (++__first != __last) - { - _ValueType __tmp = *__first; - *++__result = __tmp - _GLIBCXX_MOVE_IF_20(__value); - __value = _GLIBCXX_MOVE(__tmp); - } - return ++__result; - } - - /** - * @brief Return differences between adjacent values. - * - * Computes the difference between adjacent values in the range - * [__first,__last) using the function object @p __binary_op and writes the - * result to @p __result. - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Output sum. - * @param __binary_op Function object. - * @return Iterator pointing just beyond the values written to result. - * - * _GLIBCXX_RESOLVE_LIB_DEFECTS - * DR 539. partial_sum and adjacent_difference should mention requirements - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - adjacent_difference(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _BinaryOperation __binary_op) - { - typedef typename iterator_traits<_InputIterator>::value_type _ValueType; - - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - _ValueType>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return __result; - _ValueType __value = *__first; - *__result = __value; - while (++__first != __last) - { - _ValueType __tmp = *__first; - *++__result = __binary_op(__tmp, _GLIBCXX_MOVE_IF_20(__value)); - __value = _GLIBCXX_MOVE(__tmp); - } - return ++__result; - } - - // @} group numeric_ops - -#undef _GLIBCXX_MOVE_IF_20 - -_GLIBCXX_END_NAMESPACE_ALGO -} // namespace std - -#endif /* _STL_NUMERIC_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_pair.h b/resources/sources/avr-libstdcpp/include/bits/stl_pair.h deleted file mode 100644 index 491c59907..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_pair.h +++ /dev/null @@ -1,586 +0,0 @@ -// Pair implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_pair.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{utility} - */ - -#ifndef _STL_PAIR_H -#define _STL_PAIR_H 1 - -#include // for std::move / std::forward, and std::swap - -#if __cplusplus >= 201103L -# include // for std::__decay_and_strip, std::is_reference_v -#endif -#if __cplusplus > 201703L -# include -# define __cpp_lib_constexpr_utility 201811L -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup utilities - * @{ - */ - -#if __cplusplus >= 201103L - /// Tag type for piecewise construction of std::pair objects. - struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; - - /// Tag for piecewise construction of std::pair objects. - _GLIBCXX17_INLINE constexpr piecewise_construct_t piecewise_construct = - piecewise_construct_t(); - - /// @cond undocumented - - // Forward declarations. - template - class tuple; - - template - struct _Index_tuple; - - // Concept utility functions, reused in conditionally-explicit - // constructors. - // See PR 70437, don't look at is_constructible or - // is_convertible if the types are the same to - // avoid querying those properties for incomplete types. - template - struct _PCC - { - template - static constexpr bool _ConstructiblePair() - { - return __and_, - is_constructible<_T2, const _U2&>>::value; - } - - template - static constexpr bool _ImplicitlyConvertiblePair() - { - return __and_, - is_convertible>::value; - } - - template - static constexpr bool _MoveConstructiblePair() - { - return __and_, - is_constructible<_T2, _U2&&>>::value; - } - - template - static constexpr bool _ImplicitlyMoveConvertiblePair() - { - return __and_, - is_convertible<_U2&&, _T2>>::value; - } - - template - static constexpr bool _CopyMovePair() - { - using __do_converts = __and_, - is_convertible<_U2&&, _T2>>; - using __converts = typename conditional<__implicit, - __do_converts, - __not_<__do_converts>>::type; - return __and_, - is_constructible<_T2, _U2&&>, - __converts - >::value; - } - - template - static constexpr bool _MoveCopyPair() - { - using __do_converts = __and_, - is_convertible>; - using __converts = typename conditional<__implicit, - __do_converts, - __not_<__do_converts>>::type; - return __and_, - is_constructible<_T2, const _U2&&>, - __converts - >::value; - } - }; - - template - struct _PCC - { - template - static constexpr bool _ConstructiblePair() - { - return false; - } - - template - static constexpr bool _ImplicitlyConvertiblePair() - { - return false; - } - - template - static constexpr bool _MoveConstructiblePair() - { - return false; - } - - template - static constexpr bool _ImplicitlyMoveConvertiblePair() - { - return false; - } - }; -#endif // C++11 - - template class __pair_base - { -#if __cplusplus >= 201103L - template friend struct pair; - __pair_base() = default; - ~__pair_base() = default; - __pair_base(const __pair_base&) = default; - __pair_base& operator=(const __pair_base&) = delete; -#endif // C++11 - }; - - /// @endcond - - /** - * @brief Struct holding two objects of arbitrary type. - * - * @tparam _T1 Type of first object. - * @tparam _T2 Type of second object. - * - * - */ - template - struct pair - : private __pair_base<_T1, _T2> - { - typedef _T1 first_type; ///< The type of the `first` member - typedef _T2 second_type; ///< The type of the `second` member - - _T1 first; ///< The first member - _T2 second; ///< The second member - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 265. std::pair::pair() effects overly restrictive - /** The default constructor creates @c first and @c second using their - * respective default constructors. */ -#if __cplusplus >= 201103L - template , - __is_implicitly_default_constructible<_U2>> - ::value, bool>::type = true> -#endif - _GLIBCXX_CONSTEXPR pair() - : first(), second() { } - -#if __cplusplus >= 201103L - template , - is_default_constructible<_U2>, - __not_< - __and_<__is_implicitly_default_constructible<_U1>, - __is_implicitly_default_constructible<_U2>>>> - ::value, bool>::type = false> - explicit constexpr pair() - : first(), second() { } -#endif - -#if __cplusplus < 201103L - /// Two objects may be passed to a @c pair constructor to be copied. - pair(const _T1& __a, const _T2& __b) - : first(__a), second(__b) { } -#else - // Shortcut for constraining the templates that don't take pairs. - /// @cond undocumented - using _PCCP = _PCC; - /// @endcond - - /// Construct from two const lvalues, allowing implicit conversions. - template() - && _PCCP::template - _ImplicitlyConvertiblePair<_U1, _U2>(), - bool>::type=true> - constexpr pair(const _T1& __a, const _T2& __b) - : first(__a), second(__b) { } - - /// Construct from two const lvalues, disallowing implicit conversions. - template() - && !_PCCP::template - _ImplicitlyConvertiblePair<_U1, _U2>(), - bool>::type=false> - explicit constexpr pair(const _T1& __a, const _T2& __b) - : first(__a), second(__b) { } -#endif - -#if __cplusplus < 201103L - /// There is also a templated constructor to convert from other pairs. - template - pair(const pair<_U1, _U2>& __p) - : first(__p.first), second(__p.second) { } -#else - // Shortcut for constraining the templates that take pairs. - /// @cond undocumented - template - using _PCCFP = _PCC::value - || !is_same<_T2, _U2>::value, - _T1, _T2>; - /// @endcond - - template::template - _ConstructiblePair<_U1, _U2>() - && _PCCFP<_U1, _U2>::template - _ImplicitlyConvertiblePair<_U1, _U2>(), - bool>::type=true> - constexpr pair(const pair<_U1, _U2>& __p) - : first(__p.first), second(__p.second) { } - - template::template - _ConstructiblePair<_U1, _U2>() - && !_PCCFP<_U1, _U2>::template - _ImplicitlyConvertiblePair<_U1, _U2>(), - bool>::type=false> - explicit constexpr pair(const pair<_U1, _U2>& __p) - : first(__p.first), second(__p.second) { } -#endif - -#if __cplusplus >= 201103L - constexpr pair(const pair&) = default; ///< Copy constructor - constexpr pair(pair&&) = default; ///< Move constructor - - // DR 811. - template(), - bool>::type=true> - constexpr pair(_U1&& __x, const _T2& __y) - : first(std::forward<_U1>(__x)), second(__y) { } - - template(), - bool>::type=false> - explicit constexpr pair(_U1&& __x, const _T2& __y) - : first(std::forward<_U1>(__x)), second(__y) { } - - template(), - bool>::type=true> - constexpr pair(const _T1& __x, _U2&& __y) - : first(__x), second(std::forward<_U2>(__y)) { } - - template(), - bool>::type=false> - explicit pair(const _T1& __x, _U2&& __y) - : first(__x), second(std::forward<_U2>(__y)) { } - - template() - && _PCCP::template - _ImplicitlyMoveConvertiblePair<_U1, _U2>(), - bool>::type=true> - constexpr pair(_U1&& __x, _U2&& __y) - : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } - - template() - && !_PCCP::template - _ImplicitlyMoveConvertiblePair<_U1, _U2>(), - bool>::type=false> - explicit constexpr pair(_U1&& __x, _U2&& __y) - : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } - - - template::template - _MoveConstructiblePair<_U1, _U2>() - && _PCCFP<_U1, _U2>::template - _ImplicitlyMoveConvertiblePair<_U1, _U2>(), - bool>::type=true> - constexpr pair(pair<_U1, _U2>&& __p) - : first(std::forward<_U1>(__p.first)), - second(std::forward<_U2>(__p.second)) { } - - template::template - _MoveConstructiblePair<_U1, _U2>() - && !_PCCFP<_U1, _U2>::template - _ImplicitlyMoveConvertiblePair<_U1, _U2>(), - bool>::type=false> - explicit constexpr pair(pair<_U1, _U2>&& __p) - : first(std::forward<_U1>(__p.first)), - second(std::forward<_U2>(__p.second)) { } - - template - _GLIBCXX20_CONSTEXPR - pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>); - - _GLIBCXX20_CONSTEXPR pair& - operator=(typename conditional< - __and_, - is_copy_assignable<_T2>>::value, - const pair&, const __nonesuch&>::type __p) - { - first = __p.first; - second = __p.second; - return *this; - } - - _GLIBCXX20_CONSTEXPR pair& - operator=(typename conditional< - __and_, - is_move_assignable<_T2>>::value, - pair&&, __nonesuch&&>::type __p) - noexcept(__and_, - is_nothrow_move_assignable<_T2>>::value) - { - first = std::forward(__p.first); - second = std::forward(__p.second); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR - typename enable_if<__and_, - is_assignable<_T2&, const _U2&>>::value, - pair&>::type - operator=(const pair<_U1, _U2>& __p) - { - first = __p.first; - second = __p.second; - return *this; - } - - template - _GLIBCXX20_CONSTEXPR - typename enable_if<__and_, - is_assignable<_T2&, _U2&&>>::value, - pair&>::type - operator=(pair<_U1, _U2>&& __p) - { - first = std::forward<_U1>(__p.first); - second = std::forward<_U2>(__p.second); - return *this; - } - - /// Swap the first members and then the second members. - _GLIBCXX20_CONSTEXPR void - swap(pair& __p) - noexcept(__and_<__is_nothrow_swappable<_T1>, - __is_nothrow_swappable<_T2>>::value) - { - using std::swap; - swap(first, __p.first); - swap(second, __p.second); - } - - private: - template - _GLIBCXX20_CONSTEXPR - pair(tuple<_Args1...>&, tuple<_Args2...>&, - _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>); -#endif // C++11 - }; - - /// @relates pair @{ - -#if __cpp_deduction_guides >= 201606 - template pair(_T1, _T2) -> pair<_T1, _T2>; -#endif - - /// Two pairs of the same type are equal iff their members are equal. - template - inline _GLIBCXX_CONSTEXPR bool - operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) - { return __x.first == __y.first && __x.second == __y.second; } - -#if __cpp_lib_three_way_comparison && __cpp_lib_concepts - template - constexpr common_comparison_category_t<__detail::__synth3way_t<_T1>, - __detail::__synth3way_t<_T2>> - operator<=>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) - { - if (auto __c = __detail::__synth3way(__x.first, __y.first); __c != 0) - return __c; - return __detail::__synth3way(__x.second, __y.second); - } -#else - /** Defines a lexicographical order for pairs. - * - * For two pairs of the same type, `P` is ordered before `Q` if - * `P.first` is less than `Q.first`, or if `P.first` and `Q.first` - * are equivalent (neither is less than the other) and `P.second` is less - * than `Q.second`. - */ - template - inline _GLIBCXX_CONSTEXPR bool - operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) - { return __x.first < __y.first - || (!(__y.first < __x.first) && __x.second < __y.second); } - - /// Uses @c operator== to find the result. - template - inline _GLIBCXX_CONSTEXPR bool - operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) - { return !(__x == __y); } - - /// Uses @c operator< to find the result. - template - inline _GLIBCXX_CONSTEXPR bool - operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) - { return __y < __x; } - - /// Uses @c operator< to find the result. - template - inline _GLIBCXX_CONSTEXPR bool - operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) - { return !(__y < __x); } - - /// Uses @c operator< to find the result. - template - inline _GLIBCXX_CONSTEXPR bool - operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) - { return !(__x < __y); } -#endif // !(three_way_comparison && concepts) - -#if __cplusplus >= 201103L - /** Swap overload for pairs. Calls std::pair::swap(). - * - * @note This std::swap overload is not declared in C++03 mode, - * which has performance implications, e.g. see https://gcc.gnu.org/PR38466 - */ - template - _GLIBCXX20_CONSTEXPR inline -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - // Constrained free swap overload, see p0185r1 - typename enable_if<__and_<__is_swappable<_T1>, - __is_swappable<_T2>>::value>::type -#else - void -#endif - swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - template - typename enable_if, - __is_swappable<_T2>>::value>::type - swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete; -#endif -#endif // __cplusplus >= 201103L - - // @} relates pair - - /** - * @brief A convenience wrapper for creating a pair from two objects. - * @param __x The first object. - * @param __y The second object. - * @return A newly-constructed pair<> object of the appropriate type. - * - * The C++98 standard says the objects are passed by reference-to-const, - * but C++03 says they are passed by value (this was LWG issue #181). - * - * Since C++11 they have been passed by forwarding reference and then - * forwarded to the new members of the pair. To create a pair with a - * member of reference type, pass a `reference_wrapper` to this function. - */ - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 181. make_pair() unintended behavior -#if __cplusplus >= 201103L - // NB: DR 706. - template - constexpr pair::__type, - typename __decay_and_strip<_T2>::__type> - make_pair(_T1&& __x, _T2&& __y) - { - typedef typename __decay_and_strip<_T1>::__type __ds_type1; - typedef typename __decay_and_strip<_T2>::__type __ds_type2; - typedef pair<__ds_type1, __ds_type2> __pair_type; - return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y)); - } -#else - template - inline pair<_T1, _T2> - make_pair(_T1 __x, _T2 __y) - { return pair<_T1, _T2>(__x, __y); } -#endif - - /// @} - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_PAIR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_queue.h b/resources/sources/avr-libstdcpp/include/bits/stl_queue.h deleted file mode 100644 index 8635d4267..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_queue.h +++ /dev/null @@ -1,753 +0,0 @@ -// Queue implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_queue.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{queue} - */ - -#ifndef _STL_QUEUE_H -#define _STL_QUEUE_H 1 - -#include -#include -#if __cplusplus >= 201103L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @brief A standard container giving FIFO behavior. - * - * @ingroup sequences - * - * @tparam _Tp Type of element. - * @tparam _Sequence Type of underlying sequence, defaults to deque<_Tp>. - * - * Meets many of the requirements of a - * container, - * but does not define anything to do with iterators. Very few of the - * other standard container interfaces are defined. - * - * This is not a true container, but an @e adaptor. It holds another - * container, and provides a wrapper interface to that container. The - * wrapper is what enforces strict first-in-first-out %queue behavior. - * - * The second template parameter defines the type of the underlying - * sequence/container. It defaults to std::deque, but it can be any type - * that supports @c front, @c back, @c push_back, and @c pop_front, - * such as std::list or an appropriate user-defined type. - * - * Members not found in @a normal containers are @c container_type, - * which is a typedef for the second Sequence parameter, and @c push and - * @c pop, which are standard %queue/FIFO operations. - */ - template > - class queue - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Sequence::value_type _Sequence_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -# endif - __glibcxx_class_requires(_Sequence, _FrontInsertionSequenceConcept) - __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) - __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) -#endif - - template - friend bool - operator==(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); - - template - friend bool - operator<(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); - -#if __cpp_lib_three_way_comparison - template - friend compare_three_way_result_t<_Seq1> - operator<=>(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); -#endif - -#if __cplusplus >= 201103L - template - using _Uses = typename - enable_if::value>::type; - -#if __cplusplus >= 201703L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2566. Requirements on the first template parameter of container - // adaptors - static_assert(is_same<_Tp, typename _Sequence::value_type>::value, - "value_type must be the same as the underlying container"); -#endif // C++17 -#endif // C++11 - - public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; - - protected: - /* Maintainers wondering why this isn't uglified as per style - * guidelines should note that this name is specified in the standard, - * C++98 [23.2.3.1]. - * (Why? Presumably for the same reason that it's protected instead - * of private: to allow derivation. But none of the other - * containers allow for derivation. Odd.) - */ - /// @c c is the underlying container. - _Sequence c; - - public: - /** - * @brief Default constructor creates no elements. - */ -#if __cplusplus < 201103L - explicit - queue(const _Sequence& __c = _Sequence()) - : c(__c) { } -#else - template::value>::type> - queue() - : c() { } - - explicit - queue(const _Sequence& __c) - : c(__c) { } - - explicit - queue(_Sequence&& __c) - : c(std::move(__c)) { } - - template> - explicit - queue(const _Alloc& __a) - : c(__a) { } - - template> - queue(const _Sequence& __c, const _Alloc& __a) - : c(__c, __a) { } - - template> - queue(_Sequence&& __c, const _Alloc& __a) - : c(std::move(__c), __a) { } - - template> - queue(const queue& __q, const _Alloc& __a) - : c(__q.c, __a) { } - - template> - queue(queue&& __q, const _Alloc& __a) - : c(std::move(__q.c), __a) { } -#endif - - /** - * Returns true if the %queue is empty. - */ - _GLIBCXX_NODISCARD bool - empty() const - { return c.empty(); } - - /** Returns the number of elements in the %queue. */ - size_type - size() const - { return c.size(); } - - /** - * Returns a read/write reference to the data at the first - * element of the %queue. - */ - reference - front() - { - __glibcxx_requires_nonempty(); - return c.front(); - } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %queue. - */ - const_reference - front() const - { - __glibcxx_requires_nonempty(); - return c.front(); - } - - /** - * Returns a read/write reference to the data at the last - * element of the %queue. - */ - reference - back() - { - __glibcxx_requires_nonempty(); - return c.back(); - } - - /** - * Returns a read-only (constant) reference to the data at the last - * element of the %queue. - */ - const_reference - back() const - { - __glibcxx_requires_nonempty(); - return c.back(); - } - - /** - * @brief Add data to the end of the %queue. - * @param __x Data to be added. - * - * This is a typical %queue operation. The function creates an - * element at the end of the %queue and assigns the given data - * to it. The time complexity of the operation depends on the - * underlying sequence. - */ - void - push(const value_type& __x) - { c.push_back(__x); } - -#if __cplusplus >= 201103L - void - push(value_type&& __x) - { c.push_back(std::move(__x)); } - -#if __cplusplus > 201402L - template - decltype(auto) - emplace(_Args&&... __args) - { return c.emplace_back(std::forward<_Args>(__args)...); } -#else - template - void - emplace(_Args&&... __args) - { c.emplace_back(std::forward<_Args>(__args)...); } -#endif -#endif - - /** - * @brief Removes first element. - * - * This is a typical %queue operation. It shrinks the %queue by one. - * The time complexity of the operation depends on the underlying - * sequence. - * - * Note that no data is returned, and if the first element's - * data is needed, it should be retrieved before pop() is - * called. - */ - void - pop() - { - __glibcxx_requires_nonempty(); - c.pop_front(); - } - -#if __cplusplus >= 201103L - void - swap(queue& __q) -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - noexcept(__is_nothrow_swappable<_Sequence>::value) -#else - noexcept(__is_nothrow_swappable<_Tp>::value) -#endif - { - using std::swap; - swap(c, __q.c); - } -#endif // __cplusplus >= 201103L - }; - -#if __cpp_deduction_guides >= 201606 - template> - queue(_Container) -> queue; - - template, - typename = _RequireAllocator<_Allocator>> - queue(_Container, _Allocator) - -> queue; -#endif - - /** - * @brief Queue equality comparison. - * @param __x A %queue. - * @param __y A %queue of the same type as @a __x. - * @return True iff the size and elements of the queues are equal. - * - * This is an equivalence relation. Complexity and semantics depend on the - * underlying sequence type, but the expected rules are: this relation is - * linear in the size of the sequences, and queues are considered equivalent - * if their sequences compare equal. - */ - template - inline bool - operator==(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) - { return __x.c == __y.c; } - - /** - * @brief Queue ordering relation. - * @param __x A %queue. - * @param __y A %queue of the same type as @a x. - * @return True iff @a __x is lexicographically less than @a __y. - * - * This is an total ordering relation. Complexity and semantics - * depend on the underlying sequence type, but the expected rules - * are: this relation is linear in the size of the sequences, the - * elements must be comparable with @c <, and - * std::lexicographical_compare() is usually used to make the - * determination. - */ - template - inline bool - operator<(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) - { return __x.c < __y.c; } - - /// Based on operator== - template - inline bool - operator!=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) - { return !(__x == __y); } - - /// Based on operator< - template - inline bool - operator>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) - { return __y < __x; } - - /// Based on operator< - template - inline bool - operator<=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) - { return !(__y < __x); } - - /// Based on operator< - template - inline bool - operator>=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) - { return !(__x < __y); } - -#if __cpp_lib_three_way_comparison - template - inline compare_three_way_result_t<_Seq> - operator<=>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) - { return __x.c <=> __y.c; } -#endif - -#if __cplusplus >= 201103L - template - inline -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - // Constrained free swap overload, see p0185r1 - typename enable_if<__is_swappable<_Seq>::value>::type -#else - void -#endif - swap(queue<_Tp, _Seq>& __x, queue<_Tp, _Seq>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - template - struct uses_allocator, _Alloc> - : public uses_allocator<_Seq, _Alloc>::type { }; -#endif // __cplusplus >= 201103L - - /** - * @brief A standard container automatically sorting its contents. - * - * @ingroup sequences - * - * @tparam _Tp Type of element. - * @tparam _Sequence Type of underlying sequence, defaults to vector<_Tp>. - * @tparam _Compare Comparison function object type, defaults to - * less<_Sequence::value_type>. - * - * This is not a true container, but an @e adaptor. It holds - * another container, and provides a wrapper interface to that - * container. The wrapper is what enforces priority-based sorting - * and %queue behavior. Very few of the standard container/sequence - * interface requirements are met (e.g., iterators). - * - * The second template parameter defines the type of the underlying - * sequence/container. It defaults to std::vector, but it can be - * any type that supports @c front(), @c push_back, @c pop_back, - * and random-access iterators, such as std::deque or an - * appropriate user-defined type. - * - * The third template parameter supplies the means of making - * priority comparisons. It defaults to @c less but - * can be anything defining a strict weak ordering. - * - * Members not found in @a normal containers are @c container_type, - * which is a typedef for the second Sequence parameter, and @c - * push, @c pop, and @c top, which are standard %queue operations. - * - * @note No equality/comparison operators are provided for - * %priority_queue. - * - * @note Sorting of the elements takes place as they are added to, - * and removed from, the %priority_queue using the - * %priority_queue's member functions. If you access the elements - * by other means, and change their data such that the sorting - * order would be different, the %priority_queue will not re-sort - * the elements for you. (How could it know to do so?) - */ - template, - typename _Compare = less > - class priority_queue - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Sequence::value_type _Sequence_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -# endif - __glibcxx_class_requires(_Sequence, _SequenceConcept) - __glibcxx_class_requires(_Sequence, _RandomAccessContainerConcept) - __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) - __glibcxx_class_requires4(_Compare, bool, _Tp, _Tp, - _BinaryFunctionConcept) -#endif - -#if __cplusplus >= 201103L - template - using _Uses = typename - enable_if::value>::type; - -#if __cplusplus >= 201703L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2566. Requirements on the first template parameter of container - // adaptors - static_assert(is_same<_Tp, typename _Sequence::value_type>::value, - "value_type must be the same as the underlying container"); -#endif // C++17 -#endif // C++11 - - public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 2684. priority_queue lacking comparator typedef - typedef _Compare value_compare; - - protected: - // See queue::c for notes on these names. - _Sequence c; - _Compare comp; - - public: - /** - * @brief Default constructor creates no elements. - */ -#if __cplusplus < 201103L - explicit - priority_queue(const _Compare& __x = _Compare(), - const _Sequence& __s = _Sequence()) - : c(__s), comp(__x) - { std::make_heap(c.begin(), c.end(), comp); } -#else - template, - is_default_constructible<_Seq>>::value>::type> - priority_queue() - : c(), comp() { } - - explicit - priority_queue(const _Compare& __x, const _Sequence& __s) - : c(__s), comp(__x) - { std::make_heap(c.begin(), c.end(), comp); } - - explicit - priority_queue(const _Compare& __x, _Sequence&& __s = _Sequence()) - : c(std::move(__s)), comp(__x) - { std::make_heap(c.begin(), c.end(), comp); } - - template> - explicit - priority_queue(const _Alloc& __a) - : c(__a), comp() { } - - template> - priority_queue(const _Compare& __x, const _Alloc& __a) - : c(__a), comp(__x) { } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2537. Constructors [...] taking allocators should call make_heap - template> - priority_queue(const _Compare& __x, const _Sequence& __c, - const _Alloc& __a) - : c(__c, __a), comp(__x) - { std::make_heap(c.begin(), c.end(), comp); } - - template> - priority_queue(const _Compare& __x, _Sequence&& __c, const _Alloc& __a) - : c(std::move(__c), __a), comp(__x) - { std::make_heap(c.begin(), c.end(), comp); } - - template> - priority_queue(const priority_queue& __q, const _Alloc& __a) - : c(__q.c, __a), comp(__q.comp) { } - - template> - priority_queue(priority_queue&& __q, const _Alloc& __a) - : c(std::move(__q.c), __a), comp(std::move(__q.comp)) { } -#endif - - /** - * @brief Builds a %queue from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __x A comparison functor describing a strict weak ordering. - * @param __s An initial sequence with which to start. - * - * Begins by copying @a __s, inserting a copy of the elements - * from @a [first,last) into the copy of @a __s, then ordering - * the copy according to @a __x. - * - * For more information on function objects, see the - * documentation on @link functors functor base - * classes@endlink. - */ -#if __cplusplus < 201103L - template - priority_queue(_InputIterator __first, _InputIterator __last, - const _Compare& __x = _Compare(), - const _Sequence& __s = _Sequence()) - : c(__s), comp(__x) - { - __glibcxx_requires_valid_range(__first, __last); - c.insert(c.end(), __first, __last); - std::make_heap(c.begin(), c.end(), comp); - } -#else - template - priority_queue(_InputIterator __first, _InputIterator __last, - const _Compare& __x, - const _Sequence& __s) - : c(__s), comp(__x) - { - __glibcxx_requires_valid_range(__first, __last); - c.insert(c.end(), __first, __last); - std::make_heap(c.begin(), c.end(), comp); - } - - template - priority_queue(_InputIterator __first, _InputIterator __last, - const _Compare& __x = _Compare(), - _Sequence&& __s = _Sequence()) - : c(std::move(__s)), comp(__x) - { - __glibcxx_requires_valid_range(__first, __last); - c.insert(c.end(), __first, __last); - std::make_heap(c.begin(), c.end(), comp); - } -#endif - - /** - * Returns true if the %queue is empty. - */ - _GLIBCXX_NODISCARD bool - empty() const - { return c.empty(); } - - /** Returns the number of elements in the %queue. */ - size_type - size() const - { return c.size(); } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %queue. - */ - const_reference - top() const - { - __glibcxx_requires_nonempty(); - return c.front(); - } - - /** - * @brief Add data to the %queue. - * @param __x Data to be added. - * - * This is a typical %queue operation. - * The time complexity of the operation depends on the underlying - * sequence. - */ - void - push(const value_type& __x) - { - c.push_back(__x); - std::push_heap(c.begin(), c.end(), comp); - } - -#if __cplusplus >= 201103L - void - push(value_type&& __x) - { - c.push_back(std::move(__x)); - std::push_heap(c.begin(), c.end(), comp); - } - - template - void - emplace(_Args&&... __args) - { - c.emplace_back(std::forward<_Args>(__args)...); - std::push_heap(c.begin(), c.end(), comp); - } -#endif - - /** - * @brief Removes first element. - * - * This is a typical %queue operation. It shrinks the %queue - * by one. The time complexity of the operation depends on the - * underlying sequence. - * - * Note that no data is returned, and if the first element's - * data is needed, it should be retrieved before pop() is - * called. - */ - void - pop() - { - __glibcxx_requires_nonempty(); - std::pop_heap(c.begin(), c.end(), comp); - c.pop_back(); - } - -#if __cplusplus >= 201103L - void - swap(priority_queue& __pq) - noexcept(__and_< -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - __is_nothrow_swappable<_Sequence>, -#else - __is_nothrow_swappable<_Tp>, -#endif - __is_nothrow_swappable<_Compare> - >::value) - { - using std::swap; - swap(c, __pq.c); - swap(comp, __pq.comp); - } -#endif // __cplusplus >= 201103L - }; - -#if __cpp_deduction_guides >= 201606 - template, - typename = _RequireNotAllocator<_Container>> - priority_queue(_Compare, _Container) - -> priority_queue; - - template::value_type, - typename _Compare = less<_ValT>, - typename _Container = vector<_ValT>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireNotAllocator<_Container>> - priority_queue(_InputIterator, _InputIterator, _Compare = _Compare(), - _Container = _Container()) - -> priority_queue<_ValT, _Container, _Compare>; - - template, - typename = _RequireNotAllocator<_Container>, - typename = _RequireAllocator<_Allocator>> - priority_queue(_Compare, _Container, _Allocator) - -> priority_queue; -#endif - - // No equality/comparison operators are provided for priority_queue. - -#if __cplusplus >= 201103L - template - inline -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - // Constrained free swap overload, see p0185r1 - typename enable_if<__and_<__is_swappable<_Sequence>, - __is_swappable<_Compare>>::value>::type -#else - void -#endif - swap(priority_queue<_Tp, _Sequence, _Compare>& __x, - priority_queue<_Tp, _Sequence, _Compare>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - template - struct uses_allocator, _Alloc> - : public uses_allocator<_Sequence, _Alloc>::type { }; -#endif // __cplusplus >= 201103L - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _STL_QUEUE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h b/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h deleted file mode 100644 index df7a5f9df..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h +++ /dev/null @@ -1,123 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_raw_storage_iter.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _STL_RAW_STORAGE_ITERATOR_H -#define _STL_RAW_STORAGE_ITERATOR_H 1 - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * This iterator class lets algorithms store their results into - * uninitialized memory. - */ - template - class raw_storage_iterator - : public iterator - { - protected: - _OutputIterator _M_iter; - - public: - explicit - raw_storage_iterator(_OutputIterator __x) - : _M_iter(__x) {} - - raw_storage_iterator& - operator*() { return *this; } - - raw_storage_iterator& - operator=(const _Tp& __element) - { - std::_Construct(std::__addressof(*_M_iter), __element); - return *this; - } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2127. Move-construction with raw_storage_iterator - raw_storage_iterator& - operator=(_Tp&& __element) - { - std::_Construct(std::__addressof(*_M_iter), std::move(__element)); - return *this; - } -#endif - - raw_storage_iterator& - operator++() - { - ++_M_iter; - return *this; - } - - raw_storage_iterator - operator++(int) - { - raw_storage_iterator __tmp = *this; - ++_M_iter; - return __tmp; - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2454. Add raw_storage_iterator::base() member - _OutputIterator base() const { return _M_iter; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_relops.h b/resources/sources/avr-libstdcpp/include/bits/stl_relops.h deleted file mode 100644 index 3b0afea8a..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_relops.h +++ /dev/null @@ -1,133 +0,0 @@ -// std::rel_ops implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the, 2009 Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * Copyright (c) 1996,1997 - * Silicon Graphics - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file bits/stl_relops.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{utility} - * - * Inclusion of this file has been removed from - * all of the other STL headers for safety reasons, except std_utility.h. - * For more information, see the thread of about twenty messages starting - * with http://gcc.gnu.org/ml/libstdc++/2001-01/msg00223.html, or - * http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.ambiguous_overloads - * - * Short summary: the rel_ops operators should be avoided for the present. - */ - -#ifndef _STL_RELOPS_H -#define _STL_RELOPS_H 1 - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - namespace rel_ops - { - /** @namespace std::rel_ops - * @brief The generated relational operators are sequestered here. - */ - - /** - * @brief Defines @c != for arbitrary types, in terms of @c ==. - * @param __x A thing. - * @param __y Another thing. - * @return __x != __y - * - * This function uses @c == to determine its result. - */ - template - inline bool - operator!=(const _Tp& __x, const _Tp& __y) - { return !(__x == __y); } - - /** - * @brief Defines @c > for arbitrary types, in terms of @c <. - * @param __x A thing. - * @param __y Another thing. - * @return __x > __y - * - * This function uses @c < to determine its result. - */ - template - inline bool - operator>(const _Tp& __x, const _Tp& __y) - { return __y < __x; } - - /** - * @brief Defines @c <= for arbitrary types, in terms of @c <. - * @param __x A thing. - * @param __y Another thing. - * @return __x <= __y - * - * This function uses @c < to determine its result. - */ - template - inline bool - operator<=(const _Tp& __x, const _Tp& __y) - { return !(__y < __x); } - - /** - * @brief Defines @c >= for arbitrary types, in terms of @c <. - * @param __x A thing. - * @param __y Another thing. - * @return __x >= __y - * - * This function uses @c < to determine its result. - */ - template - inline bool - operator>=(const _Tp& __x, const _Tp& __y) - { return !(__x < __y); } - } // namespace rel_ops - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_RELOPS_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_set.h b/resources/sources/avr-libstdcpp/include/bits/stl_set.h deleted file mode 100644 index da4266508..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_set.h +++ /dev/null @@ -1,1086 +0,0 @@ -// Set implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_set.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{set} - */ - -#ifndef _STL_SET_H -#define _STL_SET_H 1 - -#include -#if __cplusplus >= 201103L -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - class multiset; - - /** - * @brief A standard container made up of unique keys, which can be - * retrieved in logarithmic time. - * - * @ingroup associative_containers - * - * @tparam _Key Type of key objects. - * @tparam _Compare Comparison function object type, defaults to less<_Key>. - * @tparam _Alloc Allocator type, defaults to allocator<_Key>. - * - * Meets the requirements of a container, a - * reversible container, and an - * associative container (using unique keys). - * - * Sets support bidirectional iterators. - * - * The private tree data is declared exactly the same way for set and - * multiset; the distinction is made entirely in how the tree functions are - * called (*_unique versus *_equal, same as the standard). - */ - template, - typename _Alloc = std::allocator<_Key> > - class set - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Alloc::value_type _Alloc_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Key, _SGIAssignableConcept) -# endif - __glibcxx_class_requires4(_Compare, bool, _Key, _Key, - _BinaryFunctionConcept) - __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) -#endif - -#if __cplusplus >= 201103L - static_assert(is_same::type, _Key>::value, - "std::set must have a non-const, non-volatile value_type"); -# if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same::value, - "std::set must have the same value_type as its allocator"); -# endif -#endif - - public: - // typedefs: - //@{ - /// Public typedefs. - typedef _Key key_type; - typedef _Key value_type; - typedef _Compare key_compare; - typedef _Compare value_compare; - typedef _Alloc allocator_type; - //@} - - private: - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_Key>::other _Key_alloc_type; - - typedef _Rb_tree, - key_compare, _Key_alloc_type> _Rep_type; - _Rep_type _M_t; // Red-black tree representing set. - - typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits; - - public: - //@{ - /// Iterator-related typedefs. - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 103. set::iterator is required to be modifiable, - // but this allows modification of keys. - typedef typename _Rep_type::const_iterator iterator; - typedef typename _Rep_type::const_iterator const_iterator; - typedef typename _Rep_type::const_reverse_iterator reverse_iterator; - typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; - typedef typename _Rep_type::size_type size_type; - typedef typename _Rep_type::difference_type difference_type; - //@} - -#if __cplusplus > 201402L - using node_type = typename _Rep_type::node_type; - using insert_return_type = typename _Rep_type::insert_return_type; -#endif - - // allocation/deallocation - /** - * @brief Default constructor creates no elements. - */ -#if __cplusplus < 201103L - set() : _M_t() { } -#else - set() = default; -#endif - - /** - * @brief Creates a %set with no elements. - * @param __comp Comparator to use. - * @param __a An allocator object. - */ - explicit - set(const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Key_alloc_type(__a)) { } - - /** - * @brief Builds a %set from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * - * Create a %set consisting of copies of the elements from - * [__first,__last). This is linear in N if the range is - * already sorted, and NlogN otherwise (where N is - * distance(__first,__last)). - */ - template - set(_InputIterator __first, _InputIterator __last) - : _M_t() - { _M_t._M_insert_range_unique(__first, __last); } - - /** - * @brief Builds a %set from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __comp A comparison functor. - * @param __a An allocator object. - * - * Create a %set consisting of copies of the elements from - * [__first,__last). This is linear in N if the range is - * already sorted, and NlogN otherwise (where N is - * distance(__first,__last)). - */ - template - set(_InputIterator __first, _InputIterator __last, - const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Key_alloc_type(__a)) - { _M_t._M_insert_range_unique(__first, __last); } - - /** - * @brief %Set copy constructor. - * - * Whether the allocator is copied depends on the allocator traits. - */ -#if __cplusplus < 201103L - set(const set& __x) - : _M_t(__x._M_t) { } -#else - set(const set&) = default; - - /** - * @brief %Set move constructor - * - * The newly-created %set contains the exact contents of the moved - * instance. The moved instance is a valid, but unspecified, %set. - */ - set(set&&) = default; - - /** - * @brief Builds a %set from an initializer_list. - * @param __l An initializer_list. - * @param __comp A comparison functor. - * @param __a An allocator object. - * - * Create a %set consisting of copies of the elements in the list. - * This is linear in N if the list is already sorted, and NlogN - * otherwise (where N is @a __l.size()). - */ - set(initializer_list __l, - const _Compare& __comp = _Compare(), - const allocator_type& __a = allocator_type()) - : _M_t(__comp, _Key_alloc_type(__a)) - { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } - - /// Allocator-extended default constructor. - explicit - set(const allocator_type& __a) - : _M_t(_Key_alloc_type(__a)) { } - - /// Allocator-extended copy constructor. - set(const set& __x, const allocator_type& __a) - : _M_t(__x._M_t, _Key_alloc_type(__a)) { } - - /// Allocator-extended move constructor. - set(set&& __x, const allocator_type& __a) - noexcept(is_nothrow_copy_constructible<_Compare>::value - && _Alloc_traits::_S_always_equal()) - : _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { } - - /// Allocator-extended initialier-list constructor. - set(initializer_list __l, const allocator_type& __a) - : _M_t(_Key_alloc_type(__a)) - { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } - - /// Allocator-extended range constructor. - template - set(_InputIterator __first, _InputIterator __last, - const allocator_type& __a) - : _M_t(_Key_alloc_type(__a)) - { _M_t._M_insert_range_unique(__first, __last); } - - /** - * The dtor only erases the elements, and note that if the elements - * themselves are pointers, the pointed-to memory is not touched in any - * way. Managing the pointer is the user's responsibility. - */ - ~set() = default; -#endif - - /** - * @brief %Set assignment operator. - * - * Whether the allocator is copied depends on the allocator traits. - */ -#if __cplusplus < 201103L - set& - operator=(const set& __x) - { - _M_t = __x._M_t; - return *this; - } -#else - set& - operator=(const set&) = default; - - /// Move assignment operator. - set& - operator=(set&&) = default; - - /** - * @brief %Set list assignment operator. - * @param __l An initializer_list. - * - * This function fills a %set with copies of the elements in the - * initializer list @a __l. - * - * Note that the assignment completely changes the %set and - * that the resulting %set's size is the same as the number - * of elements assigned. - */ - set& - operator=(initializer_list __l) - { - _M_t._M_assign_unique(__l.begin(), __l.end()); - return *this; - } -#endif - - // accessors: - - /// Returns the comparison object with which the %set was constructed. - key_compare - key_comp() const - { return _M_t.key_comp(); } - /// Returns the comparison object with which the %set was constructed. - value_compare - value_comp() const - { return _M_t.key_comp(); } - /// Returns the allocator object with which the %set was constructed. - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_M_t.get_allocator()); } - - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %set. Iteration is done in ascending order according - * to the keys. - */ - iterator - begin() const _GLIBCXX_NOEXCEPT - { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %set. Iteration is done in ascending order according - * to the keys. - */ - iterator - end() const _GLIBCXX_NOEXCEPT - { return _M_t.end(); } - - /** - * Returns a read-only (constant) iterator that points to the last - * element in the %set. Iteration is done in descending order according - * to the keys. - */ - reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last pair in the %set. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return _M_t.rend(); } - -#if __cplusplus >= 201103L - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %set. Iteration is done in ascending order according - * to the keys. - */ - iterator - cbegin() const noexcept - { return _M_t.begin(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %set. Iteration is done in ascending order according - * to the keys. - */ - iterator - cend() const noexcept - { return _M_t.end(); } - - /** - * Returns a read-only (constant) iterator that points to the last - * element in the %set. Iteration is done in descending order according - * to the keys. - */ - reverse_iterator - crbegin() const noexcept - { return _M_t.rbegin(); } - - /** - * Returns a read-only (constant) reverse iterator that points to the - * last pair in the %set. Iteration is done in descending order - * according to the keys. - */ - reverse_iterator - crend() const noexcept - { return _M_t.rend(); } -#endif - - /// Returns true if the %set is empty. - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return _M_t.empty(); } - - /// Returns the size of the %set. - size_type - size() const _GLIBCXX_NOEXCEPT - { return _M_t.size(); } - - /// Returns the maximum size of the %set. - size_type - max_size() const _GLIBCXX_NOEXCEPT - { return _M_t.max_size(); } - - /** - * @brief Swaps data with another %set. - * @param __x A %set of the same element and allocator types. - * - * This exchanges the elements between two sets in constant - * time. (It is only swapping a pointer, an integer, and an - * instance of the @c Compare type (which itself is often - * stateless and empty), so it should be quite fast.) Note - * that the global std::swap() function is specialized such - * that std::swap(s1,s2) will feed to this function. - * - * Whether the allocators are swapped depends on the allocator traits. - */ - void - swap(set& __x) - _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) - { _M_t.swap(__x._M_t); } - - // insert/erase -#if __cplusplus >= 201103L - /** - * @brief Attempts to build and insert an element into the %set. - * @param __args Arguments used to generate an element. - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted element, and the second is a bool - * that is true if the element was actually inserted. - * - * This function attempts to build and insert an element into the %set. - * A %set relies on unique keys and thus an element is only inserted if - * it is not already present in the %set. - * - * Insertion requires logarithmic time. - */ - template - std::pair - emplace(_Args&&... __args) - { return _M_t._M_emplace_unique(std::forward<_Args>(__args)...); } - - /** - * @brief Attempts to insert an element into the %set. - * @param __pos An iterator that serves as a hint as to where the - * element should be inserted. - * @param __args Arguments used to generate the element to be - * inserted. - * @return An iterator that points to the element with key equivalent to - * the one generated from @a __args (may or may not be the - * element itself). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument emplace() - * does. Note that the first parameter is only a hint and can - * potentially improve the performance of the insertion process. A bad - * hint would cause no gains in efficiency. - * - * For more on @a hinting, see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - template - iterator - emplace_hint(const_iterator __pos, _Args&&... __args) - { - return _M_t._M_emplace_hint_unique(__pos, - std::forward<_Args>(__args)...); - } -#endif - - /** - * @brief Attempts to insert an element into the %set. - * @param __x Element to be inserted. - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted element, and the second is a bool - * that is true if the element was actually inserted. - * - * This function attempts to insert an element into the %set. A %set - * relies on unique keys and thus an element is only inserted if it is - * not already present in the %set. - * - * Insertion requires logarithmic time. - */ - std::pair - insert(const value_type& __x) - { - std::pair __p = - _M_t._M_insert_unique(__x); - return std::pair(__p.first, __p.second); - } - -#if __cplusplus >= 201103L - std::pair - insert(value_type&& __x) - { - std::pair __p = - _M_t._M_insert_unique(std::move(__x)); - return std::pair(__p.first, __p.second); - } -#endif - - /** - * @brief Attempts to insert an element into the %set. - * @param __position An iterator that serves as a hint as to where the - * element should be inserted. - * @param __x Element to be inserted. - * @return An iterator that points to the element with key of - * @a __x (may or may not be the element passed in). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument insert() - * does. Note that the first parameter is only a hint and can - * potentially improve the performance of the insertion process. A bad - * hint would cause no gains in efficiency. - * - * For more on @a hinting, see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * - * Insertion requires logarithmic time (if the hint is not taken). - */ - iterator - insert(const_iterator __position, const value_type& __x) - { return _M_t._M_insert_unique_(__position, __x); } - -#if __cplusplus >= 201103L - iterator - insert(const_iterator __position, value_type&& __x) - { return _M_t._M_insert_unique_(__position, std::move(__x)); } -#endif - - /** - * @brief A template function that attempts to insert a range - * of elements. - * @param __first Iterator pointing to the start of the range to be - * inserted. - * @param __last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) - { _M_t._M_insert_range_unique(__first, __last); } - -#if __cplusplus >= 201103L - /** - * @brief Attempts to insert a list of elements into the %set. - * @param __l A std::initializer_list of elements - * to be inserted. - * - * Complexity similar to that of the range constructor. - */ - void - insert(initializer_list __l) - { this->insert(__l.begin(), __l.end()); } -#endif - -#if __cplusplus > 201402L - /// Extract a node. - node_type - extract(const_iterator __pos) - { - __glibcxx_assert(__pos != end()); - return _M_t.extract(__pos); - } - - /// Extract a node. - node_type - extract(const key_type& __x) - { return _M_t.extract(__x); } - - /// Re-insert an extracted node. - insert_return_type - insert(node_type&& __nh) - { return _M_t._M_reinsert_node_unique(std::move(__nh)); } - - /// Re-insert an extracted node. - iterator - insert(const_iterator __hint, node_type&& __nh) - { return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); } - - template - friend class std::_Rb_tree_merge_helper; - - template - void - merge(set<_Key, _Compare1, _Alloc>& __source) - { - using _Merge_helper = _Rb_tree_merge_helper; - _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); - } - - template - void - merge(set<_Key, _Compare1, _Alloc>&& __source) - { merge(__source); } - - template - void - merge(multiset<_Key, _Compare1, _Alloc>& __source) - { - using _Merge_helper = _Rb_tree_merge_helper; - _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); - } - - template - void - merge(multiset<_Key, _Compare1, _Alloc>&& __source) - { merge(__source); } -#endif // C++17 - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases an element from a %set. - * @param __position An iterator pointing to the element to be erased. - * @return An iterator pointing to the element immediately following - * @a __position prior to the element being erased. If no such - * element exists, end() is returned. - * - * This function erases an element, pointed to by the given iterator, - * from a %set. Note that this function only erases the element, and - * that if the element is itself a pointer, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's - * responsibility. - */ - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(const_iterator __position) - { return _M_t.erase(__position); } -#else - /** - * @brief Erases an element from a %set. - * @param position An iterator pointing to the element to be erased. - * - * This function erases an element, pointed to by the given iterator, - * from a %set. Note that this function only erases the element, and - * that if the element is itself a pointer, the pointed-to memory is not - * touched in any way. Managing the pointer is the user's - * responsibility. - */ - void - erase(iterator __position) - { _M_t.erase(__position); } -#endif - - /** - * @brief Erases elements according to the provided key. - * @param __x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all the elements located by the given key from - * a %set. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - size_type - erase(const key_type& __x) - { return _M_t.erase(__x); } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - /** - * @brief Erases a [__first,__last) range of elements from a %set. - * @param __first Iterator pointing to the start of the range to be - * erased. - - * @param __last Iterator pointing to the end of the range to - * be erased. - * @return The iterator @a __last. - * - * This function erases a sequence of elements from a %set. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(const_iterator __first, const_iterator __last) - { return _M_t.erase(__first, __last); } -#else - /** - * @brief Erases a [first,last) range of elements from a %set. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * - * This function erases a sequence of elements from a %set. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - void - erase(iterator __first, iterator __last) - { _M_t.erase(__first, __last); } -#endif - - /** - * Erases all elements in a %set. Note that this function only erases - * the elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer is - * the user's responsibility. - */ - void - clear() _GLIBCXX_NOEXCEPT - { _M_t.clear(); } - - // set operations: - - //@{ - /** - * @brief Finds the number of elements. - * @param __x Element to located. - * @return Number of elements with specified key. - * - * This function only makes sense for multisets; for set the result will - * either be 0 (not present) or 1 (present). - */ - size_type - count(const key_type& __x) const - { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } - -#if __cplusplus > 201103L - template - auto - count(const _Kt& __x) const - -> decltype(_M_t._M_count_tr(__x)) - { return _M_t._M_count_tr(__x); } -#endif - //@} - -#if __cplusplus > 201703L - //@{ - /** - * @brief Finds whether an element with the given key exists. - * @param __x Key of elements to be located. - * @return True if there is an element with the specified key. - */ - bool - contains(const key_type& __x) const - { return _M_t.find(__x) != _M_t.end(); } - - template - auto - contains(const _Kt& __x) const - -> decltype(_M_t._M_find_tr(__x), void(), true) - { return _M_t._M_find_tr(__x) != _M_t.end(); } - //@} -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 214. set::find() missing const overload - //@{ - /** - * @brief Tries to locate an element in a %set. - * @param __x Element to be located. - * @return Iterator pointing to sought-after element, or end() if not - * found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after element. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) - { return _M_t.find(__x); } - - const_iterator - find(const key_type& __x) const - { return _M_t.find(__x); } - -#if __cplusplus > 201103L - template - auto - find(const _Kt& __x) - -> decltype(iterator{_M_t._M_find_tr(__x)}) - { return iterator{_M_t._M_find_tr(__x)}; } - - template - auto - find(const _Kt& __x) const - -> decltype(const_iterator{_M_t._M_find_tr(__x)}) - { return const_iterator{_M_t._M_find_tr(__x)}; } -#endif - //@} - - //@{ - /** - * @brief Finds the beginning of a subsequence matching given key. - * @param __x Key to be located. - * @return Iterator pointing to first element equal to or greater - * than key, or end(). - * - * This function returns the first element of a subsequence of elements - * that matches the given key. If unsuccessful it returns an iterator - * pointing to the first element that has a greater value than given key - * or end() if no such element exists. - */ - iterator - lower_bound(const key_type& __x) - { return _M_t.lower_bound(__x); } - - const_iterator - lower_bound(const key_type& __x) const - { return _M_t.lower_bound(__x); } - -#if __cplusplus > 201103L - template - auto - lower_bound(const _Kt& __x) - -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) - { return iterator(_M_t._M_lower_bound_tr(__x)); } - - template - auto - lower_bound(const _Kt& __x) const - -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) - { return const_iterator(_M_t._M_lower_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds the end of a subsequence matching given key. - * @param __x Key to be located. - * @return Iterator pointing to the first element - * greater than key, or end(). - */ - iterator - upper_bound(const key_type& __x) - { return _M_t.upper_bound(__x); } - - const_iterator - upper_bound(const key_type& __x) const - { return _M_t.upper_bound(__x); } - -#if __cplusplus > 201103L - template - auto - upper_bound(const _Kt& __x) - -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) - { return iterator(_M_t._M_upper_bound_tr(__x)); } - - template - auto - upper_bound(const _Kt& __x) const - -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) - { return const_iterator(_M_t._M_upper_bound_tr(__x)); } -#endif - //@} - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - * - * This function is equivalent to - * @code - * std::make_pair(c.lower_bound(val), - * c.upper_bound(val)) - * @endcode - * (but is faster than making the calls separately). - * - * This function probably only makes sense for multisets. - */ - std::pair - equal_range(const key_type& __x) - { return _M_t.equal_range(__x); } - - std::pair - equal_range(const key_type& __x) const - { return _M_t.equal_range(__x); } - -#if __cplusplus > 201103L - template - auto - equal_range(const _Kt& __x) - -> decltype(pair(_M_t._M_equal_range_tr(__x))) - { return pair(_M_t._M_equal_range_tr(__x)); } - - template - auto - equal_range(const _Kt& __x) const - -> decltype(pair(_M_t._M_equal_range_tr(__x))) - { return pair(_M_t._M_equal_range_tr(__x)); } -#endif - //@} - - template - friend bool - operator==(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); - -#if __cpp_lib_three_way_comparison - template - friend __detail::__synth3way_t<_K1> - operator<=>(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); -#else - template - friend bool - operator<(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); -#endif - }; - -#if __cpp_deduction_guides >= 201606 - - template::value_type>, - typename _Allocator = - allocator::value_type>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireAllocator<_Allocator>> - set(_InputIterator, _InputIterator, - _Compare = _Compare(), _Allocator = _Allocator()) - -> set::value_type, - _Compare, _Allocator>; - - template, - typename _Allocator = allocator<_Key>, - typename = _RequireNotAllocator<_Compare>, - typename = _RequireAllocator<_Allocator>> - set(initializer_list<_Key>, - _Compare = _Compare(), _Allocator = _Allocator()) - -> set<_Key, _Compare, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - set(_InputIterator, _InputIterator, _Allocator) - -> set::value_type, - less::value_type>, - _Allocator>; - - template> - set(initializer_list<_Key>, _Allocator) - -> set<_Key, less<_Key>, _Allocator>; - -#endif // deduction guides - - /** - * @brief Set equality comparison. - * @param __x A %set. - * @param __y A %set of the same type as @a x. - * @return True iff the size and elements of the sets are equal. - * - * This is an equivalence relation. It is linear in the size of the sets. - * Sets are considered equivalent if their sizes are equal, and if - * corresponding elements compare equal. - */ - template - inline bool - operator==(const set<_Key, _Compare, _Alloc>& __x, - const set<_Key, _Compare, _Alloc>& __y) - { return __x._M_t == __y._M_t; } - -#if __cpp_lib_three_way_comparison - /** - * @brief Set ordering relation. - * @param __x A `set`. - * @param __y A `set` of the same type as `x`. - * @return A value indicating whether `__x` is less than, equal to, - * greater than, or incomparable with `__y`. - * - * This is a total ordering relation. It is linear in the size of the - * maps. The elements must be comparable with @c <. - * - * See `std::lexicographical_compare_three_way()` for how the determination - * is made. This operator is used to synthesize relational operators like - * `<` and `>=` etc. - */ - template - inline __detail::__synth3way_t<_Key> - operator<=>(const set<_Key, _Compare, _Alloc>& __x, - const set<_Key, _Compare, _Alloc>& __y) - { return __x._M_t <=> __y._M_t; } -#else - /** - * @brief Set ordering relation. - * @param __x A %set. - * @param __y A %set of the same type as @a x. - * @return True iff @a __x is lexicographically less than @a __y. - * - * This is a total ordering relation. It is linear in the size of the - * sets. The elements must be comparable with @c <. - * - * See std::lexicographical_compare() for how the determination is made. - */ - template - inline bool - operator<(const set<_Key, _Compare, _Alloc>& __x, - const set<_Key, _Compare, _Alloc>& __y) - { return __x._M_t < __y._M_t; } - - /// Returns !(x == y). - template - inline bool - operator!=(const set<_Key, _Compare, _Alloc>& __x, - const set<_Key, _Compare, _Alloc>& __y) - { return !(__x == __y); } - - /// Returns y < x. - template - inline bool - operator>(const set<_Key, _Compare, _Alloc>& __x, - const set<_Key, _Compare, _Alloc>& __y) - { return __y < __x; } - - /// Returns !(y < x) - template - inline bool - operator<=(const set<_Key, _Compare, _Alloc>& __x, - const set<_Key, _Compare, _Alloc>& __y) - { return !(__y < __x); } - - /// Returns !(x < y) - template - inline bool - operator>=(const set<_Key, _Compare, _Alloc>& __x, - const set<_Key, _Compare, _Alloc>& __y) - { return !(__x < __y); } -#endif // three-way comparison - - /// See std::set::swap(). - template - inline void - swap(set<_Key, _Compare, _Alloc>& __x, set<_Key, _Compare, _Alloc>& __y) - _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if __cplusplus > 201402L - // Allow std::set access to internals of compatible sets. - template - struct - _Rb_tree_merge_helper<_GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>, _Cmp2> - { - private: - friend class _GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>; - - static auto& - _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set) - { return __set._M_t; } - - static auto& - _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) - { return __set._M_t; } - }; -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} //namespace std -#endif /* _STL_SET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_stack.h b/resources/sources/avr-libstdcpp/include/bits/stl_stack.h deleted file mode 100644 index 1ce98a94a..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_stack.h +++ /dev/null @@ -1,392 +0,0 @@ -// Stack implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_stack.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{stack} - */ - -#ifndef _STL_STACK_H -#define _STL_STACK_H 1 - -#include -#include -#if __cplusplus >= 201103L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @brief A standard container giving FILO behavior. - * - * @ingroup sequences - * - * @tparam _Tp Type of element. - * @tparam _Sequence Type of underlying sequence, defaults to deque<_Tp>. - * - * Meets many of the requirements of a - * container, - * but does not define anything to do with iterators. Very few of the - * other standard container interfaces are defined. - * - * This is not a true container, but an @e adaptor. It holds - * another container, and provides a wrapper interface to that - * container. The wrapper is what enforces strict - * first-in-last-out %stack behavior. - * - * The second template parameter defines the type of the underlying - * sequence/container. It defaults to std::deque, but it can be - * any type that supports @c back, @c push_back, and @c pop_back, - * such as std::list, std::vector, or an appropriate user-defined - * type. - * - * Members not found in @a normal containers are @c container_type, - * which is a typedef for the second Sequence parameter, and @c - * push, @c pop, and @c top, which are standard %stack/FILO - * operations. - */ - template > - class stack - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // concept requirements - typedef typename _Sequence::value_type _Sequence_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) - __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) -# endif - __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) -#endif - - template - friend bool - operator==(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); - - template - friend bool - operator<(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); - -#if __cpp_lib_three_way_comparison - template - friend compare_three_way_result_t<_Seq1> - operator<=>(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); -#endif - -#if __cplusplus >= 201103L - template - using _Uses = typename - enable_if::value>::type; - -#if __cplusplus >= 201703L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2566. Requirements on the first template parameter of container - // adaptors - static_assert(is_same<_Tp, typename _Sequence::value_type>::value, - "value_type must be the same as the underlying container"); -#endif // C++17 -#endif // C++11 - - public: - typedef typename _Sequence::value_type value_type; - typedef typename _Sequence::reference reference; - typedef typename _Sequence::const_reference const_reference; - typedef typename _Sequence::size_type size_type; - typedef _Sequence container_type; - - protected: - // See queue::c for notes on this name. - _Sequence c; - - public: - // XXX removed old def ctor, added def arg to this one to match 14882 - /** - * @brief Default constructor creates no elements. - */ -#if __cplusplus < 201103L - explicit - stack(const _Sequence& __c = _Sequence()) - : c(__c) { } -#else - template::value>::type> - stack() - : c() { } - - explicit - stack(const _Sequence& __c) - : c(__c) { } - - explicit - stack(_Sequence&& __c) - : c(std::move(__c)) { } - - template> - explicit - stack(const _Alloc& __a) - : c(__a) { } - - template> - stack(const _Sequence& __c, const _Alloc& __a) - : c(__c, __a) { } - - template> - stack(_Sequence&& __c, const _Alloc& __a) - : c(std::move(__c), __a) { } - - template> - stack(const stack& __q, const _Alloc& __a) - : c(__q.c, __a) { } - - template> - stack(stack&& __q, const _Alloc& __a) - : c(std::move(__q.c), __a) { } -#endif - - /** - * Returns true if the %stack is empty. - */ - _GLIBCXX_NODISCARD bool - empty() const - { return c.empty(); } - - /** Returns the number of elements in the %stack. */ - size_type - size() const - { return c.size(); } - - /** - * Returns a read/write reference to the data at the first - * element of the %stack. - */ - reference - top() - { - __glibcxx_requires_nonempty(); - return c.back(); - } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %stack. - */ - const_reference - top() const - { - __glibcxx_requires_nonempty(); - return c.back(); - } - - /** - * @brief Add data to the top of the %stack. - * @param __x Data to be added. - * - * This is a typical %stack operation. The function creates an - * element at the top of the %stack and assigns the given data - * to it. The time complexity of the operation depends on the - * underlying sequence. - */ - void - push(const value_type& __x) - { c.push_back(__x); } - -#if __cplusplus >= 201103L - void - push(value_type&& __x) - { c.push_back(std::move(__x)); } - -#if __cplusplus > 201402L - template - decltype(auto) - emplace(_Args&&... __args) - { return c.emplace_back(std::forward<_Args>(__args)...); } -#else - template - void - emplace(_Args&&... __args) - { c.emplace_back(std::forward<_Args>(__args)...); } -#endif -#endif - - /** - * @brief Removes first element. - * - * This is a typical %stack operation. It shrinks the %stack - * by one. The time complexity of the operation depends on the - * underlying sequence. - * - * Note that no data is returned, and if the first element's - * data is needed, it should be retrieved before pop() is - * called. - */ - void - pop() - { - __glibcxx_requires_nonempty(); - c.pop_back(); - } - -#if __cplusplus >= 201103L - void - swap(stack& __s) -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - noexcept(__is_nothrow_swappable<_Sequence>::value) -#else - noexcept(__is_nothrow_swappable<_Tp>::value) -#endif - { - using std::swap; - swap(c, __s.c); - } -#endif // __cplusplus >= 201103L - }; - -#if __cpp_deduction_guides >= 201606 - template> - stack(_Container) -> stack; - - template, - typename = _RequireAllocator<_Allocator>> - stack(_Container, _Allocator) - -> stack; -#endif - - /** - * @brief Stack equality comparison. - * @param __x A %stack. - * @param __y A %stack of the same type as @a __x. - * @return True iff the size and elements of the stacks are equal. - * - * This is an equivalence relation. Complexity and semantics - * depend on the underlying sequence type, but the expected rules - * are: this relation is linear in the size of the sequences, and - * stacks are considered equivalent if their sequences compare - * equal. - */ - template - inline bool - operator==(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) - { return __x.c == __y.c; } - - /** - * @brief Stack ordering relation. - * @param __x A %stack. - * @param __y A %stack of the same type as @a x. - * @return True iff @a x is lexicographically less than @a __y. - * - * This is an total ordering relation. Complexity and semantics - * depend on the underlying sequence type, but the expected rules - * are: this relation is linear in the size of the sequences, the - * elements must be comparable with @c <, and - * std::lexicographical_compare() is usually used to make the - * determination. - */ - template - inline bool - operator<(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) - { return __x.c < __y.c; } - - /// Based on operator== - template - inline bool - operator!=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) - { return !(__x == __y); } - - /// Based on operator< - template - inline bool - operator>(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) - { return __y < __x; } - - /// Based on operator< - template - inline bool - operator<=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) - { return !(__y < __x); } - - /// Based on operator< - template - inline bool - operator>=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) - { return !(__x < __y); } - -#if __cpp_lib_three_way_comparison - template - inline compare_three_way_result_t<_Seq> - operator<=>(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) - { return __x.c <=> __y.c; } -#endif - -#if __cplusplus >= 201103L - template - inline -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - // Constrained free swap overload, see p0185r1 - typename enable_if<__is_swappable<_Seq>::value>::type -#else - void -#endif - swap(stack<_Tp, _Seq>& __x, stack<_Tp, _Seq>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - template - struct uses_allocator, _Alloc> - : public uses_allocator<_Seq, _Alloc>::type { }; -#endif // __cplusplus >= 201103L - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _STL_STACK_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h b/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h deleted file mode 100644 index f6f179604..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h +++ /dev/null @@ -1,284 +0,0 @@ -// Temporary buffer implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_tempbuf.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _STL_TEMPBUF_H -#define _STL_TEMPBUF_H 1 - -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - namespace __detail - { - template - inline void - __return_temporary_buffer(_Tp* __p, - size_t __len __attribute__((__unused__))) - { -#if __cpp_sized_deallocation - ::operator delete(__p, __len * sizeof(_Tp)); -#else - ::operator delete(__p); -#endif - } - } - - /** - * @brief Allocates a temporary buffer. - * @param __len The number of objects of type Tp. - * @return See full description. - * - * Reinventing the wheel, but this time with prettier spokes! - * - * This function tries to obtain storage for @c __len adjacent Tp - * objects. The objects themselves are not constructed, of course. - * A pair<> is returned containing the buffer s address and - * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if - * no storage can be obtained. Note that the capacity obtained - * may be less than that requested if the memory is unavailable; - * you should compare len with the .second return value. - * - * Provides the nothrow exception guarantee. - */ - template - pair<_Tp*, ptrdiff_t> - get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT - { - const ptrdiff_t __max = - __gnu_cxx::__numeric_traits::__max / sizeof(_Tp); - if (__len > __max) - __len = __max; - - while (__len > 0) - { - _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp), - std::nothrow)); - if (__tmp != 0) - return std::pair<_Tp*, ptrdiff_t>(__tmp, __len); - __len /= 2; - } - return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0); - } - - /** - * @brief The companion to get_temporary_buffer(). - * @param __p A buffer previously allocated by get_temporary_buffer. - * @return None. - * - * Frees the memory pointed to by __p. - */ - template - inline void - return_temporary_buffer(_Tp* __p) - { ::operator delete(__p); } - - /** - * This class is used in two places: stl_algo.h and ext/memory, - * where it is wrapped as the temporary_buffer class. See - * temporary_buffer docs for more notes. - */ - template - class _Temporary_buffer - { - // concept requirements - __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept) - - public: - typedef _Tp value_type; - typedef value_type* pointer; - typedef pointer iterator; - typedef ptrdiff_t size_type; - - protected: - size_type _M_original_len; - size_type _M_len; - pointer _M_buffer; - - public: - /// As per Table mumble. - size_type - size() const - { return _M_len; } - - /// Returns the size requested by the constructor; may be >size(). - size_type - requested_size() const - { return _M_original_len; } - - /// As per Table mumble. - iterator - begin() - { return _M_buffer; } - - /// As per Table mumble. - iterator - end() - { return _M_buffer + _M_len; } - - /** - * Constructs a temporary buffer of a size somewhere between - * zero and the given length. - */ - _Temporary_buffer(_ForwardIterator __seed, size_type __original_len); - - ~_Temporary_buffer() - { - std::_Destroy(_M_buffer, _M_buffer + _M_len); - std::__detail::__return_temporary_buffer(_M_buffer, _M_len); - } - - private: - // Disable copy constructor and assignment operator. - _Temporary_buffer(const _Temporary_buffer&); - - void - operator=(const _Temporary_buffer&); - }; - - - template - struct __uninitialized_construct_buf_dispatch - { - template - static void - __ucr(_Pointer __first, _Pointer __last, - _ForwardIterator __seed) - { - if (__first == __last) - return; - - _Pointer __cur = __first; - __try - { - std::_Construct(std::__addressof(*__first), - _GLIBCXX_MOVE(*__seed)); - _Pointer __prev = __cur; - ++__cur; - for(; __cur != __last; ++__cur, ++__prev) - std::_Construct(std::__addressof(*__cur), - _GLIBCXX_MOVE(*__prev)); - *__seed = _GLIBCXX_MOVE(*__prev); - } - __catch(...) - { - std::_Destroy(__first, __cur); - __throw_exception_again; - } - } - }; - - template<> - struct __uninitialized_construct_buf_dispatch - { - template - static void - __ucr(_Pointer, _Pointer, _ForwardIterator) { } - }; - - // Constructs objects in the range [first, last). - // Note that while these new objects will take valid values, - // their exact value is not defined. In particular they may - // be 'moved from'. - // - // While *__seed may be altered during this algorithm, it will have - // the same value when the algorithm finishes, unless one of the - // constructions throws. - // - // Requirements: _Pointer::value_type(_Tp&&) is valid. - template - inline void - __uninitialized_construct_buf(_Pointer __first, _Pointer __last, - _ForwardIterator __seed) - { - typedef typename std::iterator_traits<_Pointer>::value_type - _ValueType; - - std::__uninitialized_construct_buf_dispatch< - __has_trivial_constructor(_ValueType)>:: - __ucr(__first, __last, __seed); - } - - template - _Temporary_buffer<_ForwardIterator, _Tp>:: - _Temporary_buffer(_ForwardIterator __seed, size_type __original_len) - : _M_original_len(__original_len), _M_len(0), _M_buffer(0) - { - std::pair __p( - std::get_temporary_buffer(_M_original_len)); - - if (__p.first) - { - __try - { - std::__uninitialized_construct_buf(__p.first, __p.first + __p.second, - __seed); - _M_buffer = __p.first; - _M_len = __p.second; - } - __catch(...) - { - std::__detail::__return_temporary_buffer(__p.first, __p.second); - __throw_exception_again; - } - } - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _STL_TEMPBUF_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_tree.h b/resources/sources/avr-libstdcpp/include/bits/stl_tree.h deleted file mode 100644 index 5be15afa2..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_tree.h +++ /dev/null @@ -1,2644 +0,0 @@ -// RB tree implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - */ - -/** @file bits/stl_tree.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{map,set} - */ - -#ifndef _STL_TREE_H -#define _STL_TREE_H 1 - -#pragma GCC system_header - -#include -#include -#include -#include -#include -#if __cplusplus >= 201103L -# include -#endif -#if __cplusplus > 201402L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#if __cplusplus > 201103L -# define __cpp_lib_generic_associative_lookup 201304 -#endif - - // Red-black tree class, designed for use in implementing STL - // associative containers (set, multiset, map, and multimap). The - // insertion and deletion algorithms are based on those in Cormen, - // Leiserson, and Rivest, Introduction to Algorithms (MIT Press, - // 1990), except that - // - // (1) the header cell is maintained with links not only to the root - // but also to the leftmost node of the tree, to enable constant - // time begin(), and to the rightmost node of the tree, to enable - // linear time performance when used with the generic set algorithms - // (set_union, etc.) - // - // (2) when a node being deleted has two children its successor node - // is relinked into its place, rather than copied, so that the only - // iterators invalidated are those referring to the deleted node. - - enum _Rb_tree_color { _S_red = false, _S_black = true }; - - struct _Rb_tree_node_base - { - typedef _Rb_tree_node_base* _Base_ptr; - typedef const _Rb_tree_node_base* _Const_Base_ptr; - - _Rb_tree_color _M_color; - _Base_ptr _M_parent; - _Base_ptr _M_left; - _Base_ptr _M_right; - - static _Base_ptr - _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT - { - while (__x->_M_left != 0) __x = __x->_M_left; - return __x; - } - - static _Const_Base_ptr - _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT - { - while (__x->_M_left != 0) __x = __x->_M_left; - return __x; - } - - static _Base_ptr - _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT - { - while (__x->_M_right != 0) __x = __x->_M_right; - return __x; - } - - static _Const_Base_ptr - _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT - { - while (__x->_M_right != 0) __x = __x->_M_right; - return __x; - } - }; - - // Helper type offering value initialization guarantee on the compare functor. - template - struct _Rb_tree_key_compare - { - _Key_compare _M_key_compare; - - _Rb_tree_key_compare() - _GLIBCXX_NOEXCEPT_IF( - is_nothrow_default_constructible<_Key_compare>::value) - : _M_key_compare() - { } - - _Rb_tree_key_compare(const _Key_compare& __comp) - : _M_key_compare(__comp) - { } - -#if __cplusplus >= 201103L - // Copy constructor added for consistency with C++98 mode. - _Rb_tree_key_compare(const _Rb_tree_key_compare&) = default; - - _Rb_tree_key_compare(_Rb_tree_key_compare&& __x) - noexcept(is_nothrow_copy_constructible<_Key_compare>::value) - : _M_key_compare(__x._M_key_compare) - { } -#endif - }; - - // Helper type to manage default initialization of node count and header. - struct _Rb_tree_header - { - _Rb_tree_node_base _M_header; - size_t _M_node_count; // Keeps track of size of tree. - - _Rb_tree_header() _GLIBCXX_NOEXCEPT - { - _M_header._M_color = _S_red; - _M_reset(); - } - -#if __cplusplus >= 201103L - _Rb_tree_header(_Rb_tree_header&& __x) noexcept - { - if (__x._M_header._M_parent != nullptr) - _M_move_data(__x); - else - { - _M_header._M_color = _S_red; - _M_reset(); - } - } -#endif - - void - _M_move_data(_Rb_tree_header& __from) - { - _M_header._M_color = __from._M_header._M_color; - _M_header._M_parent = __from._M_header._M_parent; - _M_header._M_left = __from._M_header._M_left; - _M_header._M_right = __from._M_header._M_right; - _M_header._M_parent->_M_parent = &_M_header; - _M_node_count = __from._M_node_count; - - __from._M_reset(); - } - - void - _M_reset() - { - _M_header._M_parent = 0; - _M_header._M_left = &_M_header; - _M_header._M_right = &_M_header; - _M_node_count = 0; - } - }; - - template - struct _Rb_tree_node : public _Rb_tree_node_base - { - typedef _Rb_tree_node<_Val>* _Link_type; - -#if __cplusplus < 201103L - _Val _M_value_field; - - _Val* - _M_valptr() - { return std::__addressof(_M_value_field); } - - const _Val* - _M_valptr() const - { return std::__addressof(_M_value_field); } -#else - __gnu_cxx::__aligned_membuf<_Val> _M_storage; - - _Val* - _M_valptr() - { return _M_storage._M_ptr(); } - - const _Val* - _M_valptr() const - { return _M_storage._M_ptr(); } -#endif - }; - - _GLIBCXX_PURE _Rb_tree_node_base* - _Rb_tree_increment(_Rb_tree_node_base* __x) throw (); - - _GLIBCXX_PURE const _Rb_tree_node_base* - _Rb_tree_increment(const _Rb_tree_node_base* __x) throw (); - - _GLIBCXX_PURE _Rb_tree_node_base* - _Rb_tree_decrement(_Rb_tree_node_base* __x) throw (); - - _GLIBCXX_PURE const _Rb_tree_node_base* - _Rb_tree_decrement(const _Rb_tree_node_base* __x) throw (); - - template - struct _Rb_tree_iterator - { - typedef _Tp value_type; - typedef _Tp& reference; - typedef _Tp* pointer; - - typedef bidirectional_iterator_tag iterator_category; - typedef ptrdiff_t difference_type; - - typedef _Rb_tree_iterator<_Tp> _Self; - typedef _Rb_tree_node_base::_Base_ptr _Base_ptr; - typedef _Rb_tree_node<_Tp>* _Link_type; - - _Rb_tree_iterator() _GLIBCXX_NOEXCEPT - : _M_node() { } - - explicit - _Rb_tree_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT - : _M_node(__x) { } - - reference - operator*() const _GLIBCXX_NOEXCEPT - { return *static_cast<_Link_type>(_M_node)->_M_valptr(); } - - pointer - operator->() const _GLIBCXX_NOEXCEPT - { return static_cast<_Link_type> (_M_node)->_M_valptr(); } - - _Self& - operator++() _GLIBCXX_NOEXCEPT - { - _M_node = _Rb_tree_increment(_M_node); - return *this; - } - - _Self - operator++(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - _M_node = _Rb_tree_increment(_M_node); - return __tmp; - } - - _Self& - operator--() _GLIBCXX_NOEXCEPT - { - _M_node = _Rb_tree_decrement(_M_node); - return *this; - } - - _Self - operator--(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - _M_node = _Rb_tree_decrement(_M_node); - return __tmp; - } - - friend bool - operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_node == __y._M_node; } - -#if ! __cpp_lib_three_way_comparison - friend bool - operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_node != __y._M_node; } -#endif - - _Base_ptr _M_node; - }; - - template - struct _Rb_tree_const_iterator - { - typedef _Tp value_type; - typedef const _Tp& reference; - typedef const _Tp* pointer; - - typedef _Rb_tree_iterator<_Tp> iterator; - - typedef bidirectional_iterator_tag iterator_category; - typedef ptrdiff_t difference_type; - - typedef _Rb_tree_const_iterator<_Tp> _Self; - typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr; - typedef const _Rb_tree_node<_Tp>* _Link_type; - - _Rb_tree_const_iterator() _GLIBCXX_NOEXCEPT - : _M_node() { } - - explicit - _Rb_tree_const_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT - : _M_node(__x) { } - - _Rb_tree_const_iterator(const iterator& __it) _GLIBCXX_NOEXCEPT - : _M_node(__it._M_node) { } - - iterator - _M_const_cast() const _GLIBCXX_NOEXCEPT - { return iterator(const_cast(_M_node)); } - - reference - operator*() const _GLIBCXX_NOEXCEPT - { return *static_cast<_Link_type>(_M_node)->_M_valptr(); } - - pointer - operator->() const _GLIBCXX_NOEXCEPT - { return static_cast<_Link_type>(_M_node)->_M_valptr(); } - - _Self& - operator++() _GLIBCXX_NOEXCEPT - { - _M_node = _Rb_tree_increment(_M_node); - return *this; - } - - _Self - operator++(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - _M_node = _Rb_tree_increment(_M_node); - return __tmp; - } - - _Self& - operator--() _GLIBCXX_NOEXCEPT - { - _M_node = _Rb_tree_decrement(_M_node); - return *this; - } - - _Self - operator--(int) _GLIBCXX_NOEXCEPT - { - _Self __tmp = *this; - _M_node = _Rb_tree_decrement(_M_node); - return __tmp; - } - - friend bool - operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_node == __y._M_node; } - -#if ! __cpp_lib_three_way_comparison - friend bool - operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT - { return __x._M_node != __y._M_node; } -#endif - - _Base_ptr _M_node; - }; - - void - _Rb_tree_insert_and_rebalance(const bool __insert_left, - _Rb_tree_node_base* __x, - _Rb_tree_node_base* __p, - _Rb_tree_node_base& __header) throw (); - - _Rb_tree_node_base* - _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z, - _Rb_tree_node_base& __header) throw (); - -#if __cplusplus >= 201402L - template> - struct __has_is_transparent - { }; - - template - struct __has_is_transparent<_Cmp, _SfinaeType, - __void_t> - { typedef void type; }; - - template - using __has_is_transparent_t - = typename __has_is_transparent<_Cmp, _SfinaeType>::type; -#endif - -#if __cplusplus > 201402L - template - struct _Rb_tree_merge_helper { }; -#endif - - template > - class _Rb_tree - { - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_Rb_tree_node<_Val> >::other _Node_allocator; - - typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Alloc_traits; - - protected: - typedef _Rb_tree_node_base* _Base_ptr; - typedef const _Rb_tree_node_base* _Const_Base_ptr; - typedef _Rb_tree_node<_Val>* _Link_type; - typedef const _Rb_tree_node<_Val>* _Const_Link_type; - - private: - // Functor recycling a pool of nodes and using allocation once the pool - // is empty. - struct _Reuse_or_alloc_node - { - _Reuse_or_alloc_node(_Rb_tree& __t) - : _M_root(__t._M_root()), _M_nodes(__t._M_rightmost()), _M_t(__t) - { - if (_M_root) - { - _M_root->_M_parent = 0; - - if (_M_nodes->_M_left) - _M_nodes = _M_nodes->_M_left; - } - else - _M_nodes = 0; - } - -#if __cplusplus >= 201103L - _Reuse_or_alloc_node(const _Reuse_or_alloc_node&) = delete; -#endif - - ~_Reuse_or_alloc_node() - { _M_t._M_erase(static_cast<_Link_type>(_M_root)); } - - template - _Link_type -#if __cplusplus < 201103L - operator()(const _Arg& __arg) -#else - operator()(_Arg&& __arg) -#endif - { - _Link_type __node = static_cast<_Link_type>(_M_extract()); - if (__node) - { - _M_t._M_destroy_node(__node); - _M_t._M_construct_node(__node, _GLIBCXX_FORWARD(_Arg, __arg)); - return __node; - } - - return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); - } - - private: - _Base_ptr - _M_extract() - { - if (!_M_nodes) - return _M_nodes; - - _Base_ptr __node = _M_nodes; - _M_nodes = _M_nodes->_M_parent; - if (_M_nodes) - { - if (_M_nodes->_M_right == __node) - { - _M_nodes->_M_right = 0; - - if (_M_nodes->_M_left) - { - _M_nodes = _M_nodes->_M_left; - - while (_M_nodes->_M_right) - _M_nodes = _M_nodes->_M_right; - - if (_M_nodes->_M_left) - _M_nodes = _M_nodes->_M_left; - } - } - else // __node is on the left. - _M_nodes->_M_left = 0; - } - else - _M_root = 0; - - return __node; - } - - _Base_ptr _M_root; - _Base_ptr _M_nodes; - _Rb_tree& _M_t; - }; - - // Functor similar to the previous one but without any pool of nodes to - // recycle. - struct _Alloc_node - { - _Alloc_node(_Rb_tree& __t) - : _M_t(__t) { } - - template - _Link_type -#if __cplusplus < 201103L - operator()(const _Arg& __arg) const -#else - operator()(_Arg&& __arg) const -#endif - { return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); } - - private: - _Rb_tree& _M_t; - }; - - public: - typedef _Key key_type; - typedef _Val value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; - - _Node_allocator& - _M_get_Node_allocator() _GLIBCXX_NOEXCEPT - { return this->_M_impl; } - - const _Node_allocator& - _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT - { return this->_M_impl; } - - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_M_get_Node_allocator()); } - - protected: - _Link_type - _M_get_node() - { return _Alloc_traits::allocate(_M_get_Node_allocator(), 1); } - - void - _M_put_node(_Link_type __p) _GLIBCXX_NOEXCEPT - { _Alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1); } - -#if __cplusplus < 201103L - void - _M_construct_node(_Link_type __node, const value_type& __x) - { - __try - { get_allocator().construct(__node->_M_valptr(), __x); } - __catch(...) - { - _M_put_node(__node); - __throw_exception_again; - } - } - - _Link_type - _M_create_node(const value_type& __x) - { - _Link_type __tmp = _M_get_node(); - _M_construct_node(__tmp, __x); - return __tmp; - } -#else - template - void - _M_construct_node(_Link_type __node, _Args&&... __args) - { - __try - { - ::new(__node) _Rb_tree_node<_Val>; - _Alloc_traits::construct(_M_get_Node_allocator(), - __node->_M_valptr(), - std::forward<_Args>(__args)...); - } - __catch(...) - { - __node->~_Rb_tree_node<_Val>(); - _M_put_node(__node); - __throw_exception_again; - } - } - - template - _Link_type - _M_create_node(_Args&&... __args) - { - _Link_type __tmp = _M_get_node(); - _M_construct_node(__tmp, std::forward<_Args>(__args)...); - return __tmp; - } -#endif - - void - _M_destroy_node(_Link_type __p) _GLIBCXX_NOEXCEPT - { -#if __cplusplus < 201103L - get_allocator().destroy(__p->_M_valptr()); -#else - _Alloc_traits::destroy(_M_get_Node_allocator(), __p->_M_valptr()); - __p->~_Rb_tree_node<_Val>(); -#endif - } - - void - _M_drop_node(_Link_type __p) _GLIBCXX_NOEXCEPT - { - _M_destroy_node(__p); - _M_put_node(__p); - } - - template - _Link_type - _M_clone_node(_Const_Link_type __x, _NodeGen& __node_gen) - { - _Link_type __tmp = __node_gen(*__x->_M_valptr()); - __tmp->_M_color = __x->_M_color; - __tmp->_M_left = 0; - __tmp->_M_right = 0; - return __tmp; - } - - protected: -#if _GLIBCXX_INLINE_VERSION - template -#else - // Unused _Is_pod_comparator is kept as it is part of mangled name. - template -#endif - struct _Rb_tree_impl - : public _Node_allocator - , public _Rb_tree_key_compare<_Key_compare> - , public _Rb_tree_header - { - typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare; - - _Rb_tree_impl() - _GLIBCXX_NOEXCEPT_IF( - is_nothrow_default_constructible<_Node_allocator>::value - && is_nothrow_default_constructible<_Base_key_compare>::value ) - : _Node_allocator() - { } - - _Rb_tree_impl(const _Rb_tree_impl& __x) - : _Node_allocator(_Alloc_traits::_S_select_on_copy(__x)) - , _Base_key_compare(__x._M_key_compare) - { } - -#if __cplusplus < 201103L - _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a) - : _Node_allocator(__a), _Base_key_compare(__comp) - { } -#else - _Rb_tree_impl(_Rb_tree_impl&&) = default; - - explicit - _Rb_tree_impl(_Node_allocator&& __a) - : _Node_allocator(std::move(__a)) - { } - - _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a) - : _Node_allocator(std::move(__a)), - _Base_key_compare(std::move(__x)), - _Rb_tree_header(std::move(__x)) - { } - - _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a) - : _Node_allocator(std::move(__a)), _Base_key_compare(__comp) - { } -#endif - }; - - _Rb_tree_impl<_Compare> _M_impl; - - protected: - _Base_ptr& - _M_root() _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_header._M_parent; } - - _Const_Base_ptr - _M_root() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_header._M_parent; } - - _Base_ptr& - _M_leftmost() _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_header._M_left; } - - _Const_Base_ptr - _M_leftmost() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_header._M_left; } - - _Base_ptr& - _M_rightmost() _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_header._M_right; } - - _Const_Base_ptr - _M_rightmost() const _GLIBCXX_NOEXCEPT - { return this->_M_impl._M_header._M_right; } - - _Link_type - _M_begin() _GLIBCXX_NOEXCEPT - { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } - - _Const_Link_type - _M_begin() const _GLIBCXX_NOEXCEPT - { - return static_cast<_Const_Link_type> - (this->_M_impl._M_header._M_parent); - } - - _Base_ptr - _M_end() _GLIBCXX_NOEXCEPT - { return &this->_M_impl._M_header; } - - _Const_Base_ptr - _M_end() const _GLIBCXX_NOEXCEPT - { return &this->_M_impl._M_header; } - - static const _Key& - _S_key(_Const_Link_type __x) - { -#if __cplusplus >= 201103L - // If we're asking for the key we're presumably using the comparison - // object, and so this is a good place to sanity check it. - static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{}, - "comparison object must be invocable " - "with two arguments of key type"); -# if __cplusplus >= 201703L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2542. Missing const requirements for associative containers - if constexpr (__is_invocable<_Compare&, const _Key&, const _Key&>{}) - static_assert( - is_invocable_v, - "comparison object must be invocable as const"); -# endif // C++17 -#endif // C++11 - - return _KeyOfValue()(*__x->_M_valptr()); - } - - static _Link_type - _S_left(_Base_ptr __x) _GLIBCXX_NOEXCEPT - { return static_cast<_Link_type>(__x->_M_left); } - - static _Const_Link_type - _S_left(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT - { return static_cast<_Const_Link_type>(__x->_M_left); } - - static _Link_type - _S_right(_Base_ptr __x) _GLIBCXX_NOEXCEPT - { return static_cast<_Link_type>(__x->_M_right); } - - static _Const_Link_type - _S_right(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT - { return static_cast<_Const_Link_type>(__x->_M_right); } - - static const _Key& - _S_key(_Const_Base_ptr __x) - { return _S_key(static_cast<_Const_Link_type>(__x)); } - - static _Base_ptr - _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT - { return _Rb_tree_node_base::_S_minimum(__x); } - - static _Const_Base_ptr - _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT - { return _Rb_tree_node_base::_S_minimum(__x); } - - static _Base_ptr - _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT - { return _Rb_tree_node_base::_S_maximum(__x); } - - static _Const_Base_ptr - _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT - { return _Rb_tree_node_base::_S_maximum(__x); } - - public: - typedef _Rb_tree_iterator iterator; - typedef _Rb_tree_const_iterator const_iterator; - - typedef std::reverse_iterator reverse_iterator; - typedef std::reverse_iterator const_reverse_iterator; - -#if __cplusplus > 201402L - using node_type = _Node_handle<_Key, _Val, _Node_allocator>; - using insert_return_type = _Node_insert_return< - conditional_t, const_iterator, iterator>, - node_type>; -#endif - - pair<_Base_ptr, _Base_ptr> - _M_get_insert_unique_pos(const key_type& __k); - - pair<_Base_ptr, _Base_ptr> - _M_get_insert_equal_pos(const key_type& __k); - - pair<_Base_ptr, _Base_ptr> - _M_get_insert_hint_unique_pos(const_iterator __pos, - const key_type& __k); - - pair<_Base_ptr, _Base_ptr> - _M_get_insert_hint_equal_pos(const_iterator __pos, - const key_type& __k); - - private: -#if __cplusplus >= 201103L - template - iterator - _M_insert_(_Base_ptr __x, _Base_ptr __y, _Arg&& __v, _NodeGen&); - - iterator - _M_insert_node(_Base_ptr __x, _Base_ptr __y, _Link_type __z); - - template - iterator - _M_insert_lower(_Base_ptr __y, _Arg&& __v); - - template - iterator - _M_insert_equal_lower(_Arg&& __x); - - iterator - _M_insert_lower_node(_Base_ptr __p, _Link_type __z); - - iterator - _M_insert_equal_lower_node(_Link_type __z); -#else - template - iterator - _M_insert_(_Base_ptr __x, _Base_ptr __y, - const value_type& __v, _NodeGen&); - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 233. Insertion hints in associative containers. - iterator - _M_insert_lower(_Base_ptr __y, const value_type& __v); - - iterator - _M_insert_equal_lower(const value_type& __x); -#endif - - template - _Link_type - _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen&); - - template - _Link_type - _M_copy(const _Rb_tree& __x, _NodeGen& __gen) - { - _Link_type __root = _M_copy(__x._M_begin(), _M_end(), __gen); - _M_leftmost() = _S_minimum(__root); - _M_rightmost() = _S_maximum(__root); - _M_impl._M_node_count = __x._M_impl._M_node_count; - return __root; - } - - _Link_type - _M_copy(const _Rb_tree& __x) - { - _Alloc_node __an(*this); - return _M_copy(__x, __an); - } - - void - _M_erase(_Link_type __x); - - iterator - _M_lower_bound(_Link_type __x, _Base_ptr __y, - const _Key& __k); - - const_iterator - _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y, - const _Key& __k) const; - - iterator - _M_upper_bound(_Link_type __x, _Base_ptr __y, - const _Key& __k); - - const_iterator - _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y, - const _Key& __k) const; - - public: - // allocation/deallocation -#if __cplusplus < 201103L - _Rb_tree() { } -#else - _Rb_tree() = default; -#endif - - _Rb_tree(const _Compare& __comp, - const allocator_type& __a = allocator_type()) - : _M_impl(__comp, _Node_allocator(__a)) { } - - _Rb_tree(const _Rb_tree& __x) - : _M_impl(__x._M_impl) - { - if (__x._M_root() != 0) - _M_root() = _M_copy(__x); - } - -#if __cplusplus >= 201103L - _Rb_tree(const allocator_type& __a) - : _M_impl(_Node_allocator(__a)) - { } - - _Rb_tree(const _Rb_tree& __x, const allocator_type& __a) - : _M_impl(__x._M_impl._M_key_compare, _Node_allocator(__a)) - { - if (__x._M_root() != nullptr) - _M_root() = _M_copy(__x); - } - - _Rb_tree(_Rb_tree&&) = default; - - _Rb_tree(_Rb_tree&& __x, const allocator_type& __a) - : _Rb_tree(std::move(__x), _Node_allocator(__a)) - { } - - private: - _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type) - noexcept(is_nothrow_default_constructible<_Compare>::value) - : _M_impl(std::move(__x._M_impl), std::move(__a)) - { } - - _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type) - : _M_impl(__x._M_impl._M_key_compare, std::move(__a)) - { - if (__x._M_root() != nullptr) - _M_move_data(__x, false_type{}); - } - - public: - _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a) - noexcept( noexcept( - _Rb_tree(std::declval<_Rb_tree&&>(), std::declval<_Node_allocator&&>(), - std::declval())) ) - : _Rb_tree(std::move(__x), std::move(__a), - typename _Alloc_traits::is_always_equal{}) - { } -#endif - - ~_Rb_tree() _GLIBCXX_NOEXCEPT - { _M_erase(_M_begin()); } - - _Rb_tree& - operator=(const _Rb_tree& __x); - - // Accessors. - _Compare - key_comp() const - { return _M_impl._M_key_compare; } - - iterator - begin() _GLIBCXX_NOEXCEPT - { return iterator(this->_M_impl._M_header._M_left); } - - const_iterator - begin() const _GLIBCXX_NOEXCEPT - { return const_iterator(this->_M_impl._M_header._M_left); } - - iterator - end() _GLIBCXX_NOEXCEPT - { return iterator(&this->_M_impl._M_header); } - - const_iterator - end() const _GLIBCXX_NOEXCEPT - { return const_iterator(&this->_M_impl._M_header); } - - reverse_iterator - rbegin() _GLIBCXX_NOEXCEPT - { return reverse_iterator(end()); } - - const_reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(end()); } - - reverse_iterator - rend() _GLIBCXX_NOEXCEPT - { return reverse_iterator(begin()); } - - const_reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(begin()); } - - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return _M_impl._M_node_count == 0; } - - size_type - size() const _GLIBCXX_NOEXCEPT - { return _M_impl._M_node_count; } - - size_type - max_size() const _GLIBCXX_NOEXCEPT - { return _Alloc_traits::max_size(_M_get_Node_allocator()); } - - void - swap(_Rb_tree& __t) - _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value); - - // Insert/erase. -#if __cplusplus >= 201103L - template - pair - _M_insert_unique(_Arg&& __x); - - template - iterator - _M_insert_equal(_Arg&& __x); - - template - iterator - _M_insert_unique_(const_iterator __pos, _Arg&& __x, _NodeGen&); - - template - iterator - _M_insert_unique_(const_iterator __pos, _Arg&& __x) - { - _Alloc_node __an(*this); - return _M_insert_unique_(__pos, std::forward<_Arg>(__x), __an); - } - - template - iterator - _M_insert_equal_(const_iterator __pos, _Arg&& __x, _NodeGen&); - - template - iterator - _M_insert_equal_(const_iterator __pos, _Arg&& __x) - { - _Alloc_node __an(*this); - return _M_insert_equal_(__pos, std::forward<_Arg>(__x), __an); - } - - template - pair - _M_emplace_unique(_Args&&... __args); - - template - iterator - _M_emplace_equal(_Args&&... __args); - - template - iterator - _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args); - - template - iterator - _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args); - - template - using __same_value_type - = is_same::value_type>; - - template - __enable_if_t<__same_value_type<_InputIterator>::value> - _M_insert_range_unique(_InputIterator __first, _InputIterator __last) - { - _Alloc_node __an(*this); - for (; __first != __last; ++__first) - _M_insert_unique_(end(), *__first, __an); - } - - template - __enable_if_t::value> - _M_insert_range_unique(_InputIterator __first, _InputIterator __last) - { - for (; __first != __last; ++__first) - _M_emplace_unique(*__first); - } - - template - __enable_if_t<__same_value_type<_InputIterator>::value> - _M_insert_range_equal(_InputIterator __first, _InputIterator __last) - { - _Alloc_node __an(*this); - for (; __first != __last; ++__first) - _M_insert_equal_(end(), *__first, __an); - } - - template - __enable_if_t::value> - _M_insert_range_equal(_InputIterator __first, _InputIterator __last) - { - _Alloc_node __an(*this); - for (; __first != __last; ++__first) - _M_emplace_equal(*__first); - } -#else - pair - _M_insert_unique(const value_type& __x); - - iterator - _M_insert_equal(const value_type& __x); - - template - iterator - _M_insert_unique_(const_iterator __pos, const value_type& __x, - _NodeGen&); - - iterator - _M_insert_unique_(const_iterator __pos, const value_type& __x) - { - _Alloc_node __an(*this); - return _M_insert_unique_(__pos, __x, __an); - } - - template - iterator - _M_insert_equal_(const_iterator __pos, const value_type& __x, - _NodeGen&); - iterator - _M_insert_equal_(const_iterator __pos, const value_type& __x) - { - _Alloc_node __an(*this); - return _M_insert_equal_(__pos, __x, __an); - } - - template - void - _M_insert_range_unique(_InputIterator __first, _InputIterator __last) - { - _Alloc_node __an(*this); - for (; __first != __last; ++__first) - _M_insert_unique_(end(), *__first, __an); - } - - template - void - _M_insert_range_equal(_InputIterator __first, _InputIterator __last) - { - _Alloc_node __an(*this); - for (; __first != __last; ++__first) - _M_insert_equal_(end(), *__first, __an); - } -#endif - - private: - void - _M_erase_aux(const_iterator __position); - - void - _M_erase_aux(const_iterator __first, const_iterator __last); - - public: -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(const_iterator __position) - { - __glibcxx_assert(__position != end()); - const_iterator __result = __position; - ++__result; - _M_erase_aux(__position); - return __result._M_const_cast(); - } - - // LWG 2059. - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(iterator __position) - { - __glibcxx_assert(__position != end()); - iterator __result = __position; - ++__result; - _M_erase_aux(__position); - return __result; - } -#else - void - erase(iterator __position) - { - __glibcxx_assert(__position != end()); - _M_erase_aux(__position); - } - - void - erase(const_iterator __position) - { - __glibcxx_assert(__position != end()); - _M_erase_aux(__position); - } -#endif - - size_type - erase(const key_type& __x); - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 130. Associative erase should return an iterator. - _GLIBCXX_ABI_TAG_CXX11 - iterator - erase(const_iterator __first, const_iterator __last) - { - _M_erase_aux(__first, __last); - return __last._M_const_cast(); - } -#else - void - erase(iterator __first, iterator __last) - { _M_erase_aux(__first, __last); } - - void - erase(const_iterator __first, const_iterator __last) - { _M_erase_aux(__first, __last); } -#endif - - void - clear() _GLIBCXX_NOEXCEPT - { - _M_erase(_M_begin()); - _M_impl._M_reset(); - } - - // Set operations. - iterator - find(const key_type& __k); - - const_iterator - find(const key_type& __k) const; - - size_type - count(const key_type& __k) const; - - iterator - lower_bound(const key_type& __k) - { return _M_lower_bound(_M_begin(), _M_end(), __k); } - - const_iterator - lower_bound(const key_type& __k) const - { return _M_lower_bound(_M_begin(), _M_end(), __k); } - - iterator - upper_bound(const key_type& __k) - { return _M_upper_bound(_M_begin(), _M_end(), __k); } - - const_iterator - upper_bound(const key_type& __k) const - { return _M_upper_bound(_M_begin(), _M_end(), __k); } - - pair - equal_range(const key_type& __k); - - pair - equal_range(const key_type& __k) const; - -#if __cplusplus >= 201402L - template> - iterator - _M_find_tr(const _Kt& __k) - { - const _Rb_tree* __const_this = this; - return __const_this->_M_find_tr(__k)._M_const_cast(); - } - - template> - const_iterator - _M_find_tr(const _Kt& __k) const - { - auto __j = _M_lower_bound_tr(__k); - if (__j != end() && _M_impl._M_key_compare(__k, _S_key(__j._M_node))) - __j = end(); - return __j; - } - - template> - size_type - _M_count_tr(const _Kt& __k) const - { - auto __p = _M_equal_range_tr(__k); - return std::distance(__p.first, __p.second); - } - - template> - iterator - _M_lower_bound_tr(const _Kt& __k) - { - const _Rb_tree* __const_this = this; - return __const_this->_M_lower_bound_tr(__k)._M_const_cast(); - } - - template> - const_iterator - _M_lower_bound_tr(const _Kt& __k) const - { - auto __x = _M_begin(); - auto __y = _M_end(); - while (__x != 0) - if (!_M_impl._M_key_compare(_S_key(__x), __k)) - { - __y = __x; - __x = _S_left(__x); - } - else - __x = _S_right(__x); - return const_iterator(__y); - } - - template> - iterator - _M_upper_bound_tr(const _Kt& __k) - { - const _Rb_tree* __const_this = this; - return __const_this->_M_upper_bound_tr(__k)._M_const_cast(); - } - - template> - const_iterator - _M_upper_bound_tr(const _Kt& __k) const - { - auto __x = _M_begin(); - auto __y = _M_end(); - while (__x != 0) - if (_M_impl._M_key_compare(__k, _S_key(__x))) - { - __y = __x; - __x = _S_left(__x); - } - else - __x = _S_right(__x); - return const_iterator(__y); - } - - template> - pair - _M_equal_range_tr(const _Kt& __k) - { - const _Rb_tree* __const_this = this; - auto __ret = __const_this->_M_equal_range_tr(__k); - return { __ret.first._M_const_cast(), __ret.second._M_const_cast() }; - } - - template> - pair - _M_equal_range_tr(const _Kt& __k) const - { - auto __low = _M_lower_bound_tr(__k); - auto __high = __low; - auto& __cmp = _M_impl._M_key_compare; - while (__high != end() && !__cmp(__k, _S_key(__high._M_node))) - ++__high; - return { __low, __high }; - } -#endif - - // Debugging. - bool - __rb_verify() const; - -#if __cplusplus >= 201103L - _Rb_tree& - operator=(_Rb_tree&&) - noexcept(_Alloc_traits::_S_nothrow_move() - && is_nothrow_move_assignable<_Compare>::value); - - template - void - _M_assign_unique(_Iterator, _Iterator); - - template - void - _M_assign_equal(_Iterator, _Iterator); - - private: - // Move elements from container with equal allocator. - void - _M_move_data(_Rb_tree& __x, true_type) - { _M_impl._M_move_data(__x._M_impl); } - - // Move elements from container with possibly non-equal allocator, - // which might result in a copy not a move. - void - _M_move_data(_Rb_tree&, false_type); - - // Move assignment from container with equal allocator. - void - _M_move_assign(_Rb_tree&, true_type); - - // Move assignment from container with possibly non-equal allocator, - // which might result in a copy not a move. - void - _M_move_assign(_Rb_tree&, false_type); -#endif - -#if __cplusplus > 201402L - public: - /// Re-insert an extracted node. - insert_return_type - _M_reinsert_node_unique(node_type&& __nh) - { - insert_return_type __ret; - if (__nh.empty()) - __ret.position = end(); - else - { - __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); - - auto __res = _M_get_insert_unique_pos(__nh._M_key()); - if (__res.second) - { - __ret.position - = _M_insert_node(__res.first, __res.second, __nh._M_ptr); - __nh._M_ptr = nullptr; - __ret.inserted = true; - } - else - { - __ret.node = std::move(__nh); - __ret.position = iterator(__res.first); - __ret.inserted = false; - } - } - return __ret; - } - - /// Re-insert an extracted node. - iterator - _M_reinsert_node_equal(node_type&& __nh) - { - iterator __ret; - if (__nh.empty()) - __ret = end(); - else - { - __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); - auto __res = _M_get_insert_equal_pos(__nh._M_key()); - if (__res.second) - __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); - else - __ret = _M_insert_equal_lower_node(__nh._M_ptr); - __nh._M_ptr = nullptr; - } - return __ret; - } - - /// Re-insert an extracted node. - iterator - _M_reinsert_node_hint_unique(const_iterator __hint, node_type&& __nh) - { - iterator __ret; - if (__nh.empty()) - __ret = end(); - else - { - __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); - auto __res = _M_get_insert_hint_unique_pos(__hint, __nh._M_key()); - if (__res.second) - { - __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); - __nh._M_ptr = nullptr; - } - else - __ret = iterator(__res.first); - } - return __ret; - } - - /// Re-insert an extracted node. - iterator - _M_reinsert_node_hint_equal(const_iterator __hint, node_type&& __nh) - { - iterator __ret; - if (__nh.empty()) - __ret = end(); - else - { - __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); - auto __res = _M_get_insert_hint_equal_pos(__hint, __nh._M_key()); - if (__res.second) - __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); - else - __ret = _M_insert_equal_lower_node(__nh._M_ptr); - __nh._M_ptr = nullptr; - } - return __ret; - } - - /// Extract a node. - node_type - extract(const_iterator __pos) - { - auto __ptr = _Rb_tree_rebalance_for_erase( - __pos._M_const_cast()._M_node, _M_impl._M_header); - --_M_impl._M_node_count; - return { static_cast<_Link_type>(__ptr), _M_get_Node_allocator() }; - } - - /// Extract a node. - node_type - extract(const key_type& __k) - { - node_type __nh; - auto __pos = find(__k); - if (__pos != end()) - __nh = extract(const_iterator(__pos)); - return __nh; - } - - template - using _Compatible_tree - = _Rb_tree<_Key, _Val, _KeyOfValue, _Compare2, _Alloc>; - - template - friend class _Rb_tree_merge_helper; - - /// Merge from a compatible container into one with unique keys. - template - void - _M_merge_unique(_Compatible_tree<_Compare2>& __src) noexcept - { - using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>; - for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) - { - auto __pos = __i++; - auto __res = _M_get_insert_unique_pos(_KeyOfValue()(*__pos)); - if (__res.second) - { - auto& __src_impl = _Merge_helper::_S_get_impl(__src); - auto __ptr = _Rb_tree_rebalance_for_erase( - __pos._M_node, __src_impl._M_header); - --__src_impl._M_node_count; - _M_insert_node(__res.first, __res.second, - static_cast<_Link_type>(__ptr)); - } - } - } - - /// Merge from a compatible container into one with equivalent keys. - template - void - _M_merge_equal(_Compatible_tree<_Compare2>& __src) noexcept - { - using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>; - for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) - { - auto __pos = __i++; - auto __res = _M_get_insert_equal_pos(_KeyOfValue()(*__pos)); - if (__res.second) - { - auto& __src_impl = _Merge_helper::_S_get_impl(__src); - auto __ptr = _Rb_tree_rebalance_for_erase( - __pos._M_node, __src_impl._M_header); - --__src_impl._M_node_count; - _M_insert_node(__res.first, __res.second, - static_cast<_Link_type>(__ptr)); - } - } - } -#endif // C++17 - - friend bool - operator==(const _Rb_tree& __x, const _Rb_tree& __y) - { - return __x.size() == __y.size() - && std::equal(__x.begin(), __x.end(), __y.begin()); - } - -#if __cpp_lib_three_way_comparison - friend auto - operator<=>(const _Rb_tree& __x, const _Rb_tree& __y) - { - if constexpr (requires { typename __detail::__synth3way_t<_Val>; }) - return std::lexicographical_compare_three_way(__x.begin(), __x.end(), - __y.begin(), __y.end(), - __detail::__synth3way); - } -#else - friend bool - operator<(const _Rb_tree& __x, const _Rb_tree& __y) - { - return std::lexicographical_compare(__x.begin(), __x.end(), - __y.begin(), __y.end()); - } - - friend bool _GLIBCXX_DEPRECATED - operator!=(const _Rb_tree& __x, const _Rb_tree& __y) - { return !(__x == __y); } - - friend bool _GLIBCXX_DEPRECATED - operator>(const _Rb_tree& __x, const _Rb_tree& __y) - { return __y < __x; } - - friend bool _GLIBCXX_DEPRECATED - operator<=(const _Rb_tree& __x, const _Rb_tree& __y) - { return !(__y < __x); } - - friend bool _GLIBCXX_DEPRECATED - operator>=(const _Rb_tree& __x, const _Rb_tree& __y) - { return !(__x < __y); } -#endif - }; - - template - inline void - swap(_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x, - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y) - { __x.swap(__y); } - -#if __cplusplus >= 201103L - template - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_move_data(_Rb_tree& __x, false_type) - { - if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) - _M_move_data(__x, true_type()); - else - { - _Alloc_node __an(*this); - auto __lbd = - [&__an](const value_type& __cval) - { - auto& __val = const_cast(__cval); - return __an(std::move_if_noexcept(__val)); - }; - _M_root() = _M_copy(__x, __lbd); - } - } - - template - inline void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_move_assign(_Rb_tree& __x, true_type) - { - clear(); - if (__x._M_root() != nullptr) - _M_move_data(__x, true_type()); - std::__alloc_on_move(_M_get_Node_allocator(), - __x._M_get_Node_allocator()); - } - - template - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_move_assign(_Rb_tree& __x, false_type) - { - if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) - return _M_move_assign(__x, true_type{}); - - // Try to move each node reusing existing nodes and copying __x nodes - // structure. - _Reuse_or_alloc_node __roan(*this); - _M_impl._M_reset(); - if (__x._M_root() != nullptr) - { - auto __lbd = - [&__roan](const value_type& __cval) - { - auto& __val = const_cast(__cval); - return __roan(std::move(__val)); - }; - _M_root() = _M_copy(__x, __lbd); - __x.clear(); - } - } - - template - inline _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - operator=(_Rb_tree&& __x) - noexcept(_Alloc_traits::_S_nothrow_move() - && is_nothrow_move_assignable<_Compare>::value) - { - _M_impl._M_key_compare = std::move(__x._M_impl._M_key_compare); - _M_move_assign(__x, __bool_constant<_Alloc_traits::_S_nothrow_move()>()); - return *this; - } - - template - template - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_assign_unique(_Iterator __first, _Iterator __last) - { - _Reuse_or_alloc_node __roan(*this); - _M_impl._M_reset(); - for (; __first != __last; ++__first) - _M_insert_unique_(end(), *__first, __roan); - } - - template - template - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_assign_equal(_Iterator __first, _Iterator __last) - { - _Reuse_or_alloc_node __roan(*this); - _M_impl._M_reset(); - for (; __first != __last; ++__first) - _M_insert_equal_(end(), *__first, __roan); - } -#endif - - template - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - operator=(const _Rb_tree& __x) - { - if (this != &__x) - { - // Note that _Key may be a constant type. -#if __cplusplus >= 201103L - if (_Alloc_traits::_S_propagate_on_copy_assign()) - { - auto& __this_alloc = this->_M_get_Node_allocator(); - auto& __that_alloc = __x._M_get_Node_allocator(); - if (!_Alloc_traits::_S_always_equal() - && __this_alloc != __that_alloc) - { - // Replacement allocator cannot free existing storage, we need - // to erase nodes first. - clear(); - std::__alloc_on_copy(__this_alloc, __that_alloc); - } - } -#endif - - _Reuse_or_alloc_node __roan(*this); - _M_impl._M_reset(); - _M_impl._M_key_compare = __x._M_impl._M_key_compare; - if (__x._M_root() != 0) - _M_root() = _M_copy(__x, __roan); - } - - return *this; - } - - template -#if __cplusplus >= 201103L - template -#else - template -#endif - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_insert_(_Base_ptr __x, _Base_ptr __p, -#if __cplusplus >= 201103L - _Arg&& __v, -#else - const _Val& __v, -#endif - _NodeGen& __node_gen) - { - bool __insert_left = (__x != 0 || __p == _M_end() - || _M_impl._M_key_compare(_KeyOfValue()(__v), - _S_key(__p))); - - _Link_type __z = __node_gen(_GLIBCXX_FORWARD(_Arg, __v)); - - _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, - this->_M_impl._M_header); - ++_M_impl._M_node_count; - return iterator(__z); - } - - template -#if __cplusplus >= 201103L - template -#endif - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: -#if __cplusplus >= 201103L - _M_insert_lower(_Base_ptr __p, _Arg&& __v) -#else - _M_insert_lower(_Base_ptr __p, const _Val& __v) -#endif - { - bool __insert_left = (__p == _M_end() - || !_M_impl._M_key_compare(_S_key(__p), - _KeyOfValue()(__v))); - - _Link_type __z = _M_create_node(_GLIBCXX_FORWARD(_Arg, __v)); - - _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, - this->_M_impl._M_header); - ++_M_impl._M_node_count; - return iterator(__z); - } - - template -#if __cplusplus >= 201103L - template -#endif - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: -#if __cplusplus >= 201103L - _M_insert_equal_lower(_Arg&& __v) -#else - _M_insert_equal_lower(const _Val& __v) -#endif - { - _Link_type __x = _M_begin(); - _Base_ptr __y = _M_end(); - while (__x != 0) - { - __y = __x; - __x = !_M_impl._M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ? - _S_left(__x) : _S_right(__x); - } - return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v)); - } - - template - template - typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Link_type - _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>:: - _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen& __node_gen) - { - // Structural copy. __x and __p must be non-null. - _Link_type __top = _M_clone_node(__x, __node_gen); - __top->_M_parent = __p; - - __try - { - if (__x->_M_right) - __top->_M_right = _M_copy(_S_right(__x), __top, __node_gen); - __p = __top; - __x = _S_left(__x); - - while (__x != 0) - { - _Link_type __y = _M_clone_node(__x, __node_gen); - __p->_M_left = __y; - __y->_M_parent = __p; - if (__x->_M_right) - __y->_M_right = _M_copy(_S_right(__x), __y, __node_gen); - __p = __y; - __x = _S_left(__x); - } - } - __catch(...) - { - _M_erase(__top); - __throw_exception_again; - } - return __top; - } - - template - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_erase(_Link_type __x) - { - // Erase without rebalancing. - while (__x != 0) - { - _M_erase(_S_right(__x)); - _Link_type __y = _S_left(__x); - _M_drop_node(__x); - __x = __y; - } - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_lower_bound(_Link_type __x, _Base_ptr __y, - const _Key& __k) - { - while (__x != 0) - if (!_M_impl._M_key_compare(_S_key(__x), __k)) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - return iterator(__y); - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::const_iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y, - const _Key& __k) const - { - while (__x != 0) - if (!_M_impl._M_key_compare(_S_key(__x), __k)) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - return const_iterator(__y); - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_upper_bound(_Link_type __x, _Base_ptr __y, - const _Key& __k) - { - while (__x != 0) - if (_M_impl._M_key_compare(__k, _S_key(__x))) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - return iterator(__y); - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::const_iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y, - const _Key& __k) const - { - while (__x != 0) - if (_M_impl._M_key_compare(__k, _S_key(__x))) - __y = __x, __x = _S_left(__x); - else - __x = _S_right(__x); - return const_iterator(__y); - } - - template - pair::iterator, - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::iterator> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - equal_range(const _Key& __k) - { - _Link_type __x = _M_begin(); - _Base_ptr __y = _M_end(); - while (__x != 0) - { - if (_M_impl._M_key_compare(_S_key(__x), __k)) - __x = _S_right(__x); - else if (_M_impl._M_key_compare(__k, _S_key(__x))) - __y = __x, __x = _S_left(__x); - else - { - _Link_type __xu(__x); - _Base_ptr __yu(__y); - __y = __x, __x = _S_left(__x); - __xu = _S_right(__xu); - return pair(_M_lower_bound(__x, __y, __k), - _M_upper_bound(__xu, __yu, __k)); - } - } - return pair(iterator(__y), - iterator(__y)); - } - - template - pair::const_iterator, - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::const_iterator> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - equal_range(const _Key& __k) const - { - _Const_Link_type __x = _M_begin(); - _Const_Base_ptr __y = _M_end(); - while (__x != 0) - { - if (_M_impl._M_key_compare(_S_key(__x), __k)) - __x = _S_right(__x); - else if (_M_impl._M_key_compare(__k, _S_key(__x))) - __y = __x, __x = _S_left(__x); - else - { - _Const_Link_type __xu(__x); - _Const_Base_ptr __yu(__y); - __y = __x, __x = _S_left(__x); - __xu = _S_right(__xu); - return pair(_M_lower_bound(__x, __y, __k), - _M_upper_bound(__xu, __yu, __k)); - } - } - return pair(const_iterator(__y), - const_iterator(__y)); - } - - template - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - swap(_Rb_tree& __t) - _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) - { - if (_M_root() == 0) - { - if (__t._M_root() != 0) - _M_impl._M_move_data(__t._M_impl); - } - else if (__t._M_root() == 0) - __t._M_impl._M_move_data(_M_impl); - else - { - std::swap(_M_root(),__t._M_root()); - std::swap(_M_leftmost(),__t._M_leftmost()); - std::swap(_M_rightmost(),__t._M_rightmost()); - - _M_root()->_M_parent = _M_end(); - __t._M_root()->_M_parent = __t._M_end(); - std::swap(this->_M_impl._M_node_count, __t._M_impl._M_node_count); - } - // No need to swap header's color as it does not change. - std::swap(this->_M_impl._M_key_compare, __t._M_impl._M_key_compare); - - _Alloc_traits::_S_on_swap(_M_get_Node_allocator(), - __t._M_get_Node_allocator()); - } - - template - pair::_Base_ptr, - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::_Base_ptr> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_get_insert_unique_pos(const key_type& __k) - { - typedef pair<_Base_ptr, _Base_ptr> _Res; - _Link_type __x = _M_begin(); - _Base_ptr __y = _M_end(); - bool __comp = true; - while (__x != 0) - { - __y = __x; - __comp = _M_impl._M_key_compare(__k, _S_key(__x)); - __x = __comp ? _S_left(__x) : _S_right(__x); - } - iterator __j = iterator(__y); - if (__comp) - { - if (__j == begin()) - return _Res(__x, __y); - else - --__j; - } - if (_M_impl._M_key_compare(_S_key(__j._M_node), __k)) - return _Res(__x, __y); - return _Res(__j._M_node, 0); - } - - template - pair::_Base_ptr, - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::_Base_ptr> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_get_insert_equal_pos(const key_type& __k) - { - typedef pair<_Base_ptr, _Base_ptr> _Res; - _Link_type __x = _M_begin(); - _Base_ptr __y = _M_end(); - while (__x != 0) - { - __y = __x; - __x = _M_impl._M_key_compare(__k, _S_key(__x)) ? - _S_left(__x) : _S_right(__x); - } - return _Res(__x, __y); - } - - template -#if __cplusplus >= 201103L - template -#endif - pair::iterator, bool> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: -#if __cplusplus >= 201103L - _M_insert_unique(_Arg&& __v) -#else - _M_insert_unique(const _Val& __v) -#endif - { - typedef pair _Res; - pair<_Base_ptr, _Base_ptr> __res - = _M_get_insert_unique_pos(_KeyOfValue()(__v)); - - if (__res.second) - { - _Alloc_node __an(*this); - return _Res(_M_insert_(__res.first, __res.second, - _GLIBCXX_FORWARD(_Arg, __v), __an), - true); - } - - return _Res(iterator(__res.first), false); - } - - template -#if __cplusplus >= 201103L - template -#endif - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: -#if __cplusplus >= 201103L - _M_insert_equal(_Arg&& __v) -#else - _M_insert_equal(const _Val& __v) -#endif - { - pair<_Base_ptr, _Base_ptr> __res - = _M_get_insert_equal_pos(_KeyOfValue()(__v)); - _Alloc_node __an(*this); - return _M_insert_(__res.first, __res.second, - _GLIBCXX_FORWARD(_Arg, __v), __an); - } - - template - pair::_Base_ptr, - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::_Base_ptr> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_get_insert_hint_unique_pos(const_iterator __position, - const key_type& __k) - { - iterator __pos = __position._M_const_cast(); - typedef pair<_Base_ptr, _Base_ptr> _Res; - - // end() - if (__pos._M_node == _M_end()) - { - if (size() > 0 - && _M_impl._M_key_compare(_S_key(_M_rightmost()), __k)) - return _Res(0, _M_rightmost()); - else - return _M_get_insert_unique_pos(__k); - } - else if (_M_impl._M_key_compare(__k, _S_key(__pos._M_node))) - { - // First, try before... - iterator __before = __pos; - if (__pos._M_node == _M_leftmost()) // begin() - return _Res(_M_leftmost(), _M_leftmost()); - else if (_M_impl._M_key_compare(_S_key((--__before)._M_node), __k)) - { - if (_S_right(__before._M_node) == 0) - return _Res(0, __before._M_node); - else - return _Res(__pos._M_node, __pos._M_node); - } - else - return _M_get_insert_unique_pos(__k); - } - else if (_M_impl._M_key_compare(_S_key(__pos._M_node), __k)) - { - // ... then try after. - iterator __after = __pos; - if (__pos._M_node == _M_rightmost()) - return _Res(0, _M_rightmost()); - else if (_M_impl._M_key_compare(__k, _S_key((++__after)._M_node))) - { - if (_S_right(__pos._M_node) == 0) - return _Res(0, __pos._M_node); - else - return _Res(__after._M_node, __after._M_node); - } - else - return _M_get_insert_unique_pos(__k); - } - else - // Equivalent keys. - return _Res(__pos._M_node, 0); - } - - template -#if __cplusplus >= 201103L - template -#else - template -#endif - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_insert_unique_(const_iterator __position, -#if __cplusplus >= 201103L - _Arg&& __v, -#else - const _Val& __v, -#endif - _NodeGen& __node_gen) - { - pair<_Base_ptr, _Base_ptr> __res - = _M_get_insert_hint_unique_pos(__position, _KeyOfValue()(__v)); - - if (__res.second) - return _M_insert_(__res.first, __res.second, - _GLIBCXX_FORWARD(_Arg, __v), - __node_gen); - return iterator(__res.first); - } - - template - pair::_Base_ptr, - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::_Base_ptr> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_get_insert_hint_equal_pos(const_iterator __position, const key_type& __k) - { - iterator __pos = __position._M_const_cast(); - typedef pair<_Base_ptr, _Base_ptr> _Res; - - // end() - if (__pos._M_node == _M_end()) - { - if (size() > 0 - && !_M_impl._M_key_compare(__k, _S_key(_M_rightmost()))) - return _Res(0, _M_rightmost()); - else - return _M_get_insert_equal_pos(__k); - } - else if (!_M_impl._M_key_compare(_S_key(__pos._M_node), __k)) - { - // First, try before... - iterator __before = __pos; - if (__pos._M_node == _M_leftmost()) // begin() - return _Res(_M_leftmost(), _M_leftmost()); - else if (!_M_impl._M_key_compare(__k, _S_key((--__before)._M_node))) - { - if (_S_right(__before._M_node) == 0) - return _Res(0, __before._M_node); - else - return _Res(__pos._M_node, __pos._M_node); - } - else - return _M_get_insert_equal_pos(__k); - } - else - { - // ... then try after. - iterator __after = __pos; - if (__pos._M_node == _M_rightmost()) - return _Res(0, _M_rightmost()); - else if (!_M_impl._M_key_compare(_S_key((++__after)._M_node), __k)) - { - if (_S_right(__pos._M_node) == 0) - return _Res(0, __pos._M_node); - else - return _Res(__after._M_node, __after._M_node); - } - else - return _Res(0, 0); - } - } - - template -#if __cplusplus >= 201103L - template -#else - template -#endif - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_insert_equal_(const_iterator __position, -#if __cplusplus >= 201103L - _Arg&& __v, -#else - const _Val& __v, -#endif - _NodeGen& __node_gen) - { - pair<_Base_ptr, _Base_ptr> __res - = _M_get_insert_hint_equal_pos(__position, _KeyOfValue()(__v)); - - if (__res.second) - return _M_insert_(__res.first, __res.second, - _GLIBCXX_FORWARD(_Arg, __v), - __node_gen); - - return _M_insert_equal_lower(_GLIBCXX_FORWARD(_Arg, __v)); - } - -#if __cplusplus >= 201103L - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_insert_node(_Base_ptr __x, _Base_ptr __p, _Link_type __z) - { - bool __insert_left = (__x != 0 || __p == _M_end() - || _M_impl._M_key_compare(_S_key(__z), - _S_key(__p))); - - _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, - this->_M_impl._M_header); - ++_M_impl._M_node_count; - return iterator(__z); - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_insert_lower_node(_Base_ptr __p, _Link_type __z) - { - bool __insert_left = (__p == _M_end() - || !_M_impl._M_key_compare(_S_key(__p), - _S_key(__z))); - - _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, - this->_M_impl._M_header); - ++_M_impl._M_node_count; - return iterator(__z); - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_insert_equal_lower_node(_Link_type __z) - { - _Link_type __x = _M_begin(); - _Base_ptr __y = _M_end(); - while (__x != 0) - { - __y = __x; - __x = !_M_impl._M_key_compare(_S_key(__x), _S_key(__z)) ? - _S_left(__x) : _S_right(__x); - } - return _M_insert_lower_node(__y, __z); - } - - template - template - pair::iterator, bool> - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_emplace_unique(_Args&&... __args) - { - _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); - - __try - { - typedef pair _Res; - auto __res = _M_get_insert_unique_pos(_S_key(__z)); - if (__res.second) - return _Res(_M_insert_node(__res.first, __res.second, __z), true); - - _M_drop_node(__z); - return _Res(iterator(__res.first), false); - } - __catch(...) - { - _M_drop_node(__z); - __throw_exception_again; - } - } - - template - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_emplace_equal(_Args&&... __args) - { - _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); - - __try - { - auto __res = _M_get_insert_equal_pos(_S_key(__z)); - return _M_insert_node(__res.first, __res.second, __z); - } - __catch(...) - { - _M_drop_node(__z); - __throw_exception_again; - } - } - - template - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args) - { - _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); - - __try - { - auto __res = _M_get_insert_hint_unique_pos(__pos, _S_key(__z)); - - if (__res.second) - return _M_insert_node(__res.first, __res.second, __z); - - _M_drop_node(__z); - return iterator(__res.first); - } - __catch(...) - { - _M_drop_node(__z); - __throw_exception_again; - } - } - - template - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args) - { - _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); - - __try - { - auto __res = _M_get_insert_hint_equal_pos(__pos, _S_key(__z)); - - if (__res.second) - return _M_insert_node(__res.first, __res.second, __z); - - return _M_insert_equal_lower_node(__z); - } - __catch(...) - { - _M_drop_node(__z); - __throw_exception_again; - } - } -#endif - - - template - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_erase_aux(const_iterator __position) - { - _Link_type __y = - static_cast<_Link_type>(_Rb_tree_rebalance_for_erase - (const_cast<_Base_ptr>(__position._M_node), - this->_M_impl._M_header)); - _M_drop_node(__y); - --_M_impl._M_node_count; - } - - template - void - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - _M_erase_aux(const_iterator __first, const_iterator __last) - { - if (__first == begin() && __last == end()) - clear(); - else - while (__first != __last) - _M_erase_aux(__first++); - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - erase(const _Key& __x) - { - pair __p = equal_range(__x); - const size_type __old_size = size(); - _M_erase_aux(__p.first, __p.second); - return __old_size - size(); - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - find(const _Key& __k) - { - iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k); - return (__j == end() - || _M_impl._M_key_compare(__k, - _S_key(__j._M_node))) ? end() : __j; - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, - _Compare, _Alloc>::const_iterator - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - find(const _Key& __k) const - { - const_iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k); - return (__j == end() - || _M_impl._M_key_compare(__k, - _S_key(__j._M_node))) ? end() : __j; - } - - template - typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type - _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: - count(const _Key& __k) const - { - pair __p = equal_range(__k); - const size_type __n = std::distance(__p.first, __p.second); - return __n; - } - - _GLIBCXX_PURE unsigned int - _Rb_tree_black_count(const _Rb_tree_node_base* __node, - const _Rb_tree_node_base* __root) throw (); - - template - bool - _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const - { - if (_M_impl._M_node_count == 0 || begin() == end()) - return _M_impl._M_node_count == 0 && begin() == end() - && this->_M_impl._M_header._M_left == _M_end() - && this->_M_impl._M_header._M_right == _M_end(); - - unsigned int __len = _Rb_tree_black_count(_M_leftmost(), _M_root()); - for (const_iterator __it = begin(); __it != end(); ++__it) - { - _Const_Link_type __x = static_cast<_Const_Link_type>(__it._M_node); - _Const_Link_type __L = _S_left(__x); - _Const_Link_type __R = _S_right(__x); - - if (__x->_M_color == _S_red) - if ((__L && __L->_M_color == _S_red) - || (__R && __R->_M_color == _S_red)) - return false; - - if (__L && _M_impl._M_key_compare(_S_key(__x), _S_key(__L))) - return false; - if (__R && _M_impl._M_key_compare(_S_key(__R), _S_key(__x))) - return false; - - if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len) - return false; - } - - if (_M_leftmost() != _Rb_tree_node_base::_S_minimum(_M_root())) - return false; - if (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root())) - return false; - return true; - } - -#if __cplusplus > 201402L - // Allow access to internals of compatible _Rb_tree specializations. - template - struct _Rb_tree_merge_helper<_Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>, - _Cmp2> - { - private: - friend class _Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>; - - static auto& - _S_get_impl(_Rb_tree<_Key, _Val, _Sel, _Cmp2, _Alloc>& __tree) - { return __tree._M_impl; } - }; -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h b/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h deleted file mode 100644 index 3109a8946..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h +++ /dev/null @@ -1,1041 +0,0 @@ -// Raw memory manipulators -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_uninitialized.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _STL_UNINITIALIZED_H -#define _STL_UNINITIALIZED_H 1 - -#if __cplusplus > 201402L -#include -#endif - -#if __cplusplus >= 201103L -#include -#endif - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** @addtogroup memory - * @{ - */ - - /// @cond undocumented - - template - struct __uninitialized_copy - { - template - static _ForwardIterator - __uninit_copy(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result) - { - _ForwardIterator __cur = __result; - __try - { - for (; __first != __last; ++__first, (void)++__cur) - std::_Construct(std::__addressof(*__cur), *__first); - return __cur; - } - __catch(...) - { - std::_Destroy(__result, __cur); - __throw_exception_again; - } - } - }; - - template<> - struct __uninitialized_copy - { - template - static _ForwardIterator - __uninit_copy(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result) - { return std::copy(__first, __last, __result); } - }; - - /// @endcond - - /** - * @brief Copies the range [first,last) into result. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @return __result + (__first - __last) - * - * Like copy(), but does not require an initialized output range. - */ - template - inline _ForwardIterator - uninitialized_copy(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result) - { - typedef typename iterator_traits<_InputIterator>::value_type - _ValueType1; - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType2; -#if __cplusplus < 201103L - const bool __assignable = true; -#else - // Trivial types can have deleted copy constructor, but the std::copy - // optimization that uses memmove would happily "copy" them anyway. - static_assert(is_constructible<_ValueType2, decltype(*__first)>::value, - "result type must be constructible from value type of input range"); - - typedef typename iterator_traits<_InputIterator>::reference _RefType1; - typedef typename iterator_traits<_ForwardIterator>::reference _RefType2; - // Trivial types can have deleted assignment, so using std::copy - // would be ill-formed. Require assignability before using std::copy: - const bool __assignable = is_assignable<_RefType2, _RefType1>::value; -#endif - - return std::__uninitialized_copy<__is_trivial(_ValueType1) - && __is_trivial(_ValueType2) - && __assignable>:: - __uninit_copy(__first, __last, __result); - } - - /// @cond undocumented - - template - struct __uninitialized_fill - { - template - static void - __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __x) - { - _ForwardIterator __cur = __first; - __try - { - for (; __cur != __last; ++__cur) - std::_Construct(std::__addressof(*__cur), __x); - } - __catch(...) - { - std::_Destroy(__first, __cur); - __throw_exception_again; - } - } - }; - - template<> - struct __uninitialized_fill - { - template - static void - __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __x) - { std::fill(__first, __last, __x); } - }; - - /// @endcond - - /** - * @brief Copies the value x into the range [first,last). - * @param __first An input iterator. - * @param __last An input iterator. - * @param __x The source value. - * @return Nothing. - * - * Like fill(), but does not require an initialized output range. - */ - template - inline void - uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __x) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; -#if __cplusplus < 201103L - const bool __assignable = true; -#else - // Trivial types can have deleted copy constructor, but the std::fill - // optimization that uses memmove would happily "copy" them anyway. - static_assert(is_constructible<_ValueType, const _Tp&>::value, - "result type must be constructible from input type"); - - // Trivial types can have deleted assignment, so using std::fill - // would be ill-formed. Require assignability before using std::fill: - const bool __assignable = is_copy_assignable<_ValueType>::value; -#endif - - std::__uninitialized_fill<__is_trivial(_ValueType) && __assignable>:: - __uninit_fill(__first, __last, __x); - } - - /// @cond undocumented - - template - struct __uninitialized_fill_n - { - template - static _ForwardIterator - __uninit_fill_n(_ForwardIterator __first, _Size __n, - const _Tp& __x) - { - _ForwardIterator __cur = __first; - __try - { - for (; __n > 0; --__n, (void) ++__cur) - std::_Construct(std::__addressof(*__cur), __x); - return __cur; - } - __catch(...) - { - std::_Destroy(__first, __cur); - __throw_exception_again; - } - } - }; - - template<> - struct __uninitialized_fill_n - { - template - static _ForwardIterator - __uninit_fill_n(_ForwardIterator __first, _Size __n, - const _Tp& __x) - { return std::fill_n(__first, __n, __x); } - }; - - /// @endcond - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 1339. uninitialized_fill_n should return the end of its range - /** - * @brief Copies the value x into the range [first,first+n). - * @param __first An input iterator. - * @param __n The number of copies to make. - * @param __x The source value. - * @return Nothing. - * - * Like fill_n(), but does not require an initialized output range. - */ - template - inline _ForwardIterator - uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; -#if __cplusplus < 201103L - const bool __assignable = true; -#else - // Trivial types can have deleted copy constructor, but the std::fill - // optimization that uses memmove would happily "copy" them anyway. - static_assert(is_constructible<_ValueType, const _Tp&>::value, - "result type must be constructible from input type"); - - // Trivial types can have deleted assignment, so using std::fill - // would be ill-formed. Require assignability before using std::fill: - const bool __assignable = is_copy_assignable<_ValueType>::value; -#endif - return __uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>:: - __uninit_fill_n(__first, __n, __x); - } - - /// @cond undocumented - - // Extensions: versions of uninitialized_copy, uninitialized_fill, - // and uninitialized_fill_n that take an allocator parameter. - // We dispatch back to the standard versions when we're given the - // default allocator. For nondefault allocators we do not use - // any of the POD optimizations. - - template - _ForwardIterator - __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result, _Allocator& __alloc) - { - _ForwardIterator __cur = __result; - __try - { - typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; - for (; __first != __last; ++__first, (void)++__cur) - __traits::construct(__alloc, std::__addressof(*__cur), *__first); - return __cur; - } - __catch(...) - { - std::_Destroy(__result, __cur, __alloc); - __throw_exception_again; - } - } - - template - inline _ForwardIterator - __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result, allocator<_Tp>&) - { return std::uninitialized_copy(__first, __last, __result); } - - template - inline _ForwardIterator - __uninitialized_move_a(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result, _Allocator& __alloc) - { - return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), - _GLIBCXX_MAKE_MOVE_ITERATOR(__last), - __result, __alloc); - } - - template - inline _ForwardIterator - __uninitialized_move_if_noexcept_a(_InputIterator __first, - _InputIterator __last, - _ForwardIterator __result, - _Allocator& __alloc) - { - return std::__uninitialized_copy_a - (_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first), - _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc); - } - - template - void - __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __x, _Allocator& __alloc) - { - _ForwardIterator __cur = __first; - __try - { - typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; - for (; __cur != __last; ++__cur) - __traits::construct(__alloc, std::__addressof(*__cur), __x); - } - __catch(...) - { - std::_Destroy(__first, __cur, __alloc); - __throw_exception_again; - } - } - - template - inline void - __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, - const _Tp& __x, allocator<_Tp2>&) - { std::uninitialized_fill(__first, __last, __x); } - - template - _ForwardIterator - __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, - const _Tp& __x, _Allocator& __alloc) - { - _ForwardIterator __cur = __first; - __try - { - typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; - for (; __n > 0; --__n, (void) ++__cur) - __traits::construct(__alloc, std::__addressof(*__cur), __x); - return __cur; - } - __catch(...) - { - std::_Destroy(__first, __cur, __alloc); - __throw_exception_again; - } - } - - template - inline _ForwardIterator - __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, - const _Tp& __x, allocator<_Tp2>&) - { return std::uninitialized_fill_n(__first, __n, __x); } - - - // Extensions: __uninitialized_copy_move, __uninitialized_move_copy, - // __uninitialized_fill_move, __uninitialized_move_fill. - // All of these algorithms take a user-supplied allocator, which is used - // for construction and destruction. - - // __uninitialized_copy_move - // Copies [first1, last1) into [result, result + (last1 - first1)), and - // move [first2, last2) into - // [result, result + (last1 - first1) + (last2 - first2)). - template - inline _ForwardIterator - __uninitialized_copy_move(_InputIterator1 __first1, - _InputIterator1 __last1, - _InputIterator2 __first2, - _InputIterator2 __last2, - _ForwardIterator __result, - _Allocator& __alloc) - { - _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1, - __result, - __alloc); - __try - { - return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc); - } - __catch(...) - { - std::_Destroy(__result, __mid, __alloc); - __throw_exception_again; - } - } - - // __uninitialized_move_copy - // Moves [first1, last1) into [result, result + (last1 - first1)), and - // copies [first2, last2) into - // [result, result + (last1 - first1) + (last2 - first2)). - template - inline _ForwardIterator - __uninitialized_move_copy(_InputIterator1 __first1, - _InputIterator1 __last1, - _InputIterator2 __first2, - _InputIterator2 __last2, - _ForwardIterator __result, - _Allocator& __alloc) - { - _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1, - __result, - __alloc); - __try - { - return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc); - } - __catch(...) - { - std::_Destroy(__result, __mid, __alloc); - __throw_exception_again; - } - } - - // __uninitialized_fill_move - // Fills [result, mid) with x, and moves [first, last) into - // [mid, mid + (last - first)). - template - inline _ForwardIterator - __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid, - const _Tp& __x, _InputIterator __first, - _InputIterator __last, _Allocator& __alloc) - { - std::__uninitialized_fill_a(__result, __mid, __x, __alloc); - __try - { - return std::__uninitialized_move_a(__first, __last, __mid, __alloc); - } - __catch(...) - { - std::_Destroy(__result, __mid, __alloc); - __throw_exception_again; - } - } - - // __uninitialized_move_fill - // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and - // fills [first2 + (last1 - first1), last2) with x. - template - inline void - __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1, - _ForwardIterator __first2, - _ForwardIterator __last2, const _Tp& __x, - _Allocator& __alloc) - { - _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1, - __first2, - __alloc); - __try - { - std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc); - } - __catch(...) - { - std::_Destroy(__first2, __mid2, __alloc); - __throw_exception_again; - } - } - - /// @endcond - -#if __cplusplus >= 201103L - /// @cond undocumented - - // Extensions: __uninitialized_default, __uninitialized_default_n, - // __uninitialized_default_a, __uninitialized_default_n_a. - - template - struct __uninitialized_default_1 - { - template - static void - __uninit_default(_ForwardIterator __first, _ForwardIterator __last) - { - _ForwardIterator __cur = __first; - __try - { - for (; __cur != __last; ++__cur) - std::_Construct(std::__addressof(*__cur)); - } - __catch(...) - { - std::_Destroy(__first, __cur); - __throw_exception_again; - } - } - }; - - template<> - struct __uninitialized_default_1 - { - template - static void - __uninit_default(_ForwardIterator __first, _ForwardIterator __last) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; - - std::fill(__first, __last, _ValueType()); - } - }; - - template - struct __uninitialized_default_n_1 - { - template - static _ForwardIterator - __uninit_default_n(_ForwardIterator __first, _Size __n) - { - _ForwardIterator __cur = __first; - __try - { - for (; __n > 0; --__n, (void) ++__cur) - std::_Construct(std::__addressof(*__cur)); - return __cur; - } - __catch(...) - { - std::_Destroy(__first, __cur); - __throw_exception_again; - } - } - }; - - template<> - struct __uninitialized_default_n_1 - { - template - static _ForwardIterator - __uninit_default_n(_ForwardIterator __first, _Size __n) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; - - return std::fill_n(__first, __n, _ValueType()); - } - }; - - // __uninitialized_default - // Fills [first, last) with std::distance(first, last) default - // constructed value_types(s). - template - inline void - __uninitialized_default(_ForwardIterator __first, - _ForwardIterator __last) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; - // trivial types can have deleted assignment - const bool __assignable = is_copy_assignable<_ValueType>::value; - - std::__uninitialized_default_1<__is_trivial(_ValueType) - && __assignable>:: - __uninit_default(__first, __last); - } - - // __uninitialized_default_n - // Fills [first, first + n) with n default constructed value_type(s). - template - inline _ForwardIterator - __uninitialized_default_n(_ForwardIterator __first, _Size __n) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; - // trivial types can have deleted assignment - const bool __assignable = is_copy_assignable<_ValueType>::value; - - return __uninitialized_default_n_1<__is_trivial(_ValueType) - && __assignable>:: - __uninit_default_n(__first, __n); - } - - - // __uninitialized_default_a - // Fills [first, last) with std::distance(first, last) default - // constructed value_types(s), constructed with the allocator alloc. - template - void - __uninitialized_default_a(_ForwardIterator __first, - _ForwardIterator __last, - _Allocator& __alloc) - { - _ForwardIterator __cur = __first; - __try - { - typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; - for (; __cur != __last; ++__cur) - __traits::construct(__alloc, std::__addressof(*__cur)); - } - __catch(...) - { - std::_Destroy(__first, __cur, __alloc); - __throw_exception_again; - } - } - - template - inline void - __uninitialized_default_a(_ForwardIterator __first, - _ForwardIterator __last, - allocator<_Tp>&) - { std::__uninitialized_default(__first, __last); } - - - // __uninitialized_default_n_a - // Fills [first, first + n) with n default constructed value_types(s), - // constructed with the allocator alloc. - template - _ForwardIterator - __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, - _Allocator& __alloc) - { - _ForwardIterator __cur = __first; - __try - { - typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; - for (; __n > 0; --__n, (void) ++__cur) - __traits::construct(__alloc, std::__addressof(*__cur)); - return __cur; - } - __catch(...) - { - std::_Destroy(__first, __cur, __alloc); - __throw_exception_again; - } - } - - template - inline _ForwardIterator - __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, - allocator<_Tp>&) - { return std::__uninitialized_default_n(__first, __n); } - - template - struct __uninitialized_default_novalue_1 - { - template - static void - __uninit_default_novalue(_ForwardIterator __first, - _ForwardIterator __last) - { - _ForwardIterator __cur = __first; - __try - { - for (; __cur != __last; ++__cur) - std::_Construct_novalue(std::__addressof(*__cur)); - } - __catch(...) - { - std::_Destroy(__first, __cur); - __throw_exception_again; - } - } - }; - - template<> - struct __uninitialized_default_novalue_1 - { - template - static void - __uninit_default_novalue(_ForwardIterator __first, - _ForwardIterator __last) - { - } - }; - - template - struct __uninitialized_default_novalue_n_1 - { - template - static _ForwardIterator - __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) - { - _ForwardIterator __cur = __first; - __try - { - for (; __n > 0; --__n, (void) ++__cur) - std::_Construct_novalue(std::__addressof(*__cur)); - return __cur; - } - __catch(...) - { - std::_Destroy(__first, __cur); - __throw_exception_again; - } - } - }; - - template<> - struct __uninitialized_default_novalue_n_1 - { - template - static _ForwardIterator - __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) - { return std::next(__first, __n); } - }; - - // __uninitialized_default_novalue - // Fills [first, last) with std::distance(first, last) default-initialized - // value_types(s). - template - inline void - __uninitialized_default_novalue(_ForwardIterator __first, - _ForwardIterator __last) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; - - std::__uninitialized_default_novalue_1< - is_trivially_default_constructible<_ValueType>::value>:: - __uninit_default_novalue(__first, __last); - } - - // __uninitialized_default_n - // Fills [first, first + n) with n default-initialized value_type(s). - template - inline _ForwardIterator - __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n) - { - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType; - - return __uninitialized_default_novalue_n_1< - is_trivially_default_constructible<_ValueType>::value>:: - __uninit_default_novalue_n(__first, __n); - } - - template - _ForwardIterator - __uninitialized_copy_n(_InputIterator __first, _Size __n, - _ForwardIterator __result, input_iterator_tag) - { - _ForwardIterator __cur = __result; - __try - { - for (; __n > 0; --__n, (void) ++__first, ++__cur) - std::_Construct(std::__addressof(*__cur), *__first); - return __cur; - } - __catch(...) - { - std::_Destroy(__result, __cur); - __throw_exception_again; - } - } - - template - inline _ForwardIterator - __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n, - _ForwardIterator __result, - random_access_iterator_tag) - { return std::uninitialized_copy(__first, __first + __n, __result); } - - template - pair<_InputIterator, _ForwardIterator> - __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, - _ForwardIterator __result, input_iterator_tag) - { - _ForwardIterator __cur = __result; - __try - { - for (; __n > 0; --__n, (void) ++__first, ++__cur) - std::_Construct(std::__addressof(*__cur), *__first); - return {__first, __cur}; - } - __catch(...) - { - std::_Destroy(__result, __cur); - __throw_exception_again; - } - } - - template - inline pair<_RandomAccessIterator, _ForwardIterator> - __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n, - _ForwardIterator __result, - random_access_iterator_tag) - { - auto __second_res = uninitialized_copy(__first, __first + __n, __result); - auto __first_res = std::next(__first, __n); - return {__first_res, __second_res}; - } - - /// @endcond - - /** - * @brief Copies the range [first,first+n) into result. - * @param __first An input iterator. - * @param __n The number of elements to copy. - * @param __result An output iterator. - * @return __result + __n - * - * Like copy_n(), but does not require an initialized output range. - */ - template - inline _ForwardIterator - uninitialized_copy_n(_InputIterator __first, _Size __n, - _ForwardIterator __result) - { return std::__uninitialized_copy_n(__first, __n, __result, - std::__iterator_category(__first)); } - - /// @cond undocumented - template - inline pair<_InputIterator, _ForwardIterator> - __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, - _ForwardIterator __result) - { - return - std::__uninitialized_copy_n_pair(__first, __n, __result, - std::__iterator_category(__first)); - } - /// @endcond -#endif - -#if __cplusplus >= 201703L -# define __cpp_lib_raw_memory_algorithms 201606L - - /** - * @brief Default-initializes objects in the range [first,last). - * @param __first A forward iterator. - * @param __last A forward iterator. - */ - template - inline void - uninitialized_default_construct(_ForwardIterator __first, - _ForwardIterator __last) - { - __uninitialized_default_novalue(__first, __last); - } - - /** - * @brief Default-initializes objects in the range [first,first+count). - * @param __first A forward iterator. - * @param __count The number of objects to construct. - * @return __first + __count - */ - template - inline _ForwardIterator - uninitialized_default_construct_n(_ForwardIterator __first, _Size __count) - { - return __uninitialized_default_novalue_n(__first, __count); - } - - /** - * @brief Value-initializes objects in the range [first,last). - * @param __first A forward iterator. - * @param __last A forward iterator. - */ - template - inline void - uninitialized_value_construct(_ForwardIterator __first, - _ForwardIterator __last) - { - return __uninitialized_default(__first, __last); - } - - /** - * @brief Value-initializes objects in the range [first,first+count). - * @param __first A forward iterator. - * @param __count The number of objects to construct. - * @return __result + __count - */ - template - inline _ForwardIterator - uninitialized_value_construct_n(_ForwardIterator __first, _Size __count) - { - return __uninitialized_default_n(__first, __count); - } - - /** - * @brief Move-construct from the range [first,last) into result. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __result An output iterator. - * @return __result + (__first - __last) - */ - template - inline _ForwardIterator - uninitialized_move(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result) - { - return std::uninitialized_copy - (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), - _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result); - } - - /** - * @brief Move-construct from the range [first,first+count) into result. - * @param __first An input iterator. - * @param __count The number of objects to initialize. - * @param __result An output iterator. - * @return __result + __count - */ - template - inline pair<_InputIterator, _ForwardIterator> - uninitialized_move_n(_InputIterator __first, _Size __count, - _ForwardIterator __result) - { - auto __res = std::__uninitialized_copy_n_pair - (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), - __count, __result); - return {__res.first.base(), __res.second}; - } -#endif // C++17 - -#if __cplusplus >= 201103L - /// @cond undocumented - - template - inline void - __relocate_object_a(_Tp* __restrict __dest, _Up* __restrict __orig, - _Allocator& __alloc) - noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc, - __dest, std::move(*__orig))) - && noexcept(std::allocator_traits<_Allocator>::destroy( - __alloc, std::__addressof(*__orig)))) - { - typedef std::allocator_traits<_Allocator> __traits; - __traits::construct(__alloc, __dest, std::move(*__orig)); - __traits::destroy(__alloc, std::__addressof(*__orig)); - } - - // This class may be specialized for specific types. - // Also known as is_trivially_relocatable. - template - struct __is_bitwise_relocatable - : is_trivial<_Tp> { }; - - template - inline __enable_if_t::value, _Tp*> - __relocate_a_1(_Tp* __first, _Tp* __last, - _Tp* __result, allocator<_Up>&) noexcept - { - ptrdiff_t __count = __last - __first; - if (__count > 0) - __builtin_memmove(__result, __first, __count * sizeof(_Tp)); - return __result + __count; - } - - template - inline _ForwardIterator - __relocate_a_1(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result, _Allocator& __alloc) - noexcept(noexcept(std::__relocate_object_a(std::addressof(*__result), - std::addressof(*__first), - __alloc))) - { - typedef typename iterator_traits<_InputIterator>::value_type - _ValueType; - typedef typename iterator_traits<_ForwardIterator>::value_type - _ValueType2; - static_assert(std::is_same<_ValueType, _ValueType2>::value, - "relocation is only possible for values of the same type"); - _ForwardIterator __cur = __result; - for (; __first != __last; ++__first, (void)++__cur) - std::__relocate_object_a(std::__addressof(*__cur), - std::__addressof(*__first), __alloc); - return __cur; - } - - template - inline _ForwardIterator - __relocate_a(_InputIterator __first, _InputIterator __last, - _ForwardIterator __result, _Allocator& __alloc) - noexcept(noexcept(__relocate_a_1(std::__niter_base(__first), - std::__niter_base(__last), - std::__niter_base(__result), __alloc))) - { - return __relocate_a_1(std::__niter_base(__first), - std::__niter_base(__last), - std::__niter_base(__result), __alloc); - } - - /// @endcond -#endif - - // @} group memory - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _STL_UNINITIALIZED_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_vector.h b/resources/sources/avr-libstdcpp/include/bits/stl_vector.h deleted file mode 100644 index d3f1b1fae..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/stl_vector.h +++ /dev/null @@ -1,1985 +0,0 @@ -// Vector implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/stl_vector.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{vector} - */ - -#ifndef _STL_VECTOR_H -#define _STL_VECTOR_H 1 - -#include -#include -#include -#if __cplusplus >= 201103L -#include -#endif -#if __cplusplus > 201703L -# include -#endif - -#include - -#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR -extern "C" void -__sanitizer_annotate_contiguous_container(const void*, const void*, - const void*, const void*); -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - /// See bits/stl_deque.h's _Deque_base for an explanation. - template - struct _Vector_base - { - typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template - rebind<_Tp>::other _Tp_alloc_type; - typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer - pointer; - - struct _Vector_impl_data - { - pointer _M_start; - pointer _M_finish; - pointer _M_end_of_storage; - - _Vector_impl_data() _GLIBCXX_NOEXCEPT - : _M_start(), _M_finish(), _M_end_of_storage() - { } - -#if __cplusplus >= 201103L - _Vector_impl_data(_Vector_impl_data&& __x) noexcept - : _M_start(__x._M_start), _M_finish(__x._M_finish), - _M_end_of_storage(__x._M_end_of_storage) - { __x._M_start = __x._M_finish = __x._M_end_of_storage = pointer(); } -#endif - - void - _M_copy_data(_Vector_impl_data const& __x) _GLIBCXX_NOEXCEPT - { - _M_start = __x._M_start; - _M_finish = __x._M_finish; - _M_end_of_storage = __x._M_end_of_storage; - } - - void - _M_swap_data(_Vector_impl_data& __x) _GLIBCXX_NOEXCEPT - { - // Do not use std::swap(_M_start, __x._M_start), etc as it loses - // information used by TBAA. - _Vector_impl_data __tmp; - __tmp._M_copy_data(*this); - _M_copy_data(__x); - __x._M_copy_data(__tmp); - } - }; - - struct _Vector_impl - : public _Tp_alloc_type, public _Vector_impl_data - { - _Vector_impl() _GLIBCXX_NOEXCEPT_IF( - is_nothrow_default_constructible<_Tp_alloc_type>::value) - : _Tp_alloc_type() - { } - - _Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT - : _Tp_alloc_type(__a) - { } - -#if __cplusplus >= 201103L - // Not defaulted, to enforce noexcept(true) even when - // !is_nothrow_move_constructible<_Tp_alloc_type>. - _Vector_impl(_Vector_impl&& __x) noexcept - : _Tp_alloc_type(std::move(__x)), _Vector_impl_data(std::move(__x)) - { } - - _Vector_impl(_Tp_alloc_type&& __a) noexcept - : _Tp_alloc_type(std::move(__a)) - { } - - _Vector_impl(_Tp_alloc_type&& __a, _Vector_impl&& __rv) noexcept - : _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv)) - { } -#endif - -#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR - template - struct _Asan - { - typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type> - ::size_type size_type; - - static void _S_shrink(_Vector_impl&, size_type) { } - static void _S_on_dealloc(_Vector_impl&) { } - - typedef _Vector_impl& _Reinit; - - struct _Grow - { - _Grow(_Vector_impl&, size_type) { } - void _M_grew(size_type) { } - }; - }; - - // Enable ASan annotations for memory obtained from std::allocator. - template - struct _Asan > - { - typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type> - ::size_type size_type; - - // Adjust ASan annotation for [_M_start, _M_end_of_storage) to - // mark end of valid region as __curr instead of __prev. - static void - _S_adjust(_Vector_impl& __impl, pointer __prev, pointer __curr) - { - __sanitizer_annotate_contiguous_container(__impl._M_start, - __impl._M_end_of_storage, __prev, __curr); - } - - static void - _S_grow(_Vector_impl& __impl, size_type __n) - { _S_adjust(__impl, __impl._M_finish, __impl._M_finish + __n); } - - static void - _S_shrink(_Vector_impl& __impl, size_type __n) - { _S_adjust(__impl, __impl._M_finish + __n, __impl._M_finish); } - - static void - _S_on_dealloc(_Vector_impl& __impl) - { - if (__impl._M_start) - _S_adjust(__impl, __impl._M_finish, __impl._M_end_of_storage); - } - - // Used on reallocation to tell ASan unused capacity is invalid. - struct _Reinit - { - explicit _Reinit(_Vector_impl& __impl) : _M_impl(__impl) - { - // Mark unused capacity as valid again before deallocating it. - _S_on_dealloc(_M_impl); - } - - ~_Reinit() - { - // Mark unused capacity as invalid after reallocation. - if (_M_impl._M_start) - _S_adjust(_M_impl, _M_impl._M_end_of_storage, - _M_impl._M_finish); - } - - _Vector_impl& _M_impl; - -#if __cplusplus >= 201103L - _Reinit(const _Reinit&) = delete; - _Reinit& operator=(const _Reinit&) = delete; -#endif - }; - - // Tell ASan when unused capacity is initialized to be valid. - struct _Grow - { - _Grow(_Vector_impl& __impl, size_type __n) - : _M_impl(__impl), _M_n(__n) - { _S_grow(_M_impl, __n); } - - ~_Grow() { if (_M_n) _S_shrink(_M_impl, _M_n); } - - void _M_grew(size_type __n) { _M_n -= __n; } - -#if __cplusplus >= 201103L - _Grow(const _Grow&) = delete; - _Grow& operator=(const _Grow&) = delete; -#endif - private: - _Vector_impl& _M_impl; - size_type _M_n; - }; - }; - -#define _GLIBCXX_ASAN_ANNOTATE_REINIT \ - typename _Base::_Vector_impl::template _Asan<>::_Reinit const \ - __attribute__((__unused__)) __reinit_guard(this->_M_impl) -#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) \ - typename _Base::_Vector_impl::template _Asan<>::_Grow \ - __attribute__((__unused__)) __grow_guard(this->_M_impl, (n)) -#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) __grow_guard._M_grew(n) -#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) \ - _Base::_Vector_impl::template _Asan<>::_S_shrink(this->_M_impl, n) -#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC \ - _Base::_Vector_impl::template _Asan<>::_S_on_dealloc(this->_M_impl) -#else // ! (_GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR) -#define _GLIBCXX_ASAN_ANNOTATE_REINIT -#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) -#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) -#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) -#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC -#endif // _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR - }; - - public: - typedef _Alloc allocator_type; - - _Tp_alloc_type& - _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT - { return this->_M_impl; } - - const _Tp_alloc_type& - _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT - { return this->_M_impl; } - - allocator_type - get_allocator() const _GLIBCXX_NOEXCEPT - { return allocator_type(_M_get_Tp_allocator()); } - -#if __cplusplus >= 201103L - _Vector_base() = default; -#else - _Vector_base() { } -#endif - - _Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPT - : _M_impl(__a) { } - - // Kept for ABI compatibility. -#if !_GLIBCXX_INLINE_VERSION - _Vector_base(size_t __n) - : _M_impl() - { _M_create_storage(__n); } -#endif - - _Vector_base(size_t __n, const allocator_type& __a) - : _M_impl(__a) - { _M_create_storage(__n); } - -#if __cplusplus >= 201103L - _Vector_base(_Vector_base&&) = default; - - // Kept for ABI compatibility. -# if !_GLIBCXX_INLINE_VERSION - _Vector_base(_Tp_alloc_type&& __a) noexcept - : _M_impl(std::move(__a)) { } - - _Vector_base(_Vector_base&& __x, const allocator_type& __a) - : _M_impl(__a) - { - if (__x.get_allocator() == __a) - this->_M_impl._M_swap_data(__x._M_impl); - else - { - size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start; - _M_create_storage(__n); - } - } -# endif - - _Vector_base(const allocator_type& __a, _Vector_base&& __x) - : _M_impl(_Tp_alloc_type(__a), std::move(__x._M_impl)) - { } -#endif - - ~_Vector_base() _GLIBCXX_NOEXCEPT - { - _M_deallocate(_M_impl._M_start, - _M_impl._M_end_of_storage - _M_impl._M_start); - } - - public: - _Vector_impl _M_impl; - - pointer - _M_allocate(size_t __n) - { - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; - return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer(); - } - - void - _M_deallocate(pointer __p, size_t __n) - { - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; - if (__p) - _Tr::deallocate(_M_impl, __p, __n); - } - - protected: - void - _M_create_storage(size_t __n) - { - this->_M_impl._M_start = this->_M_allocate(__n); - this->_M_impl._M_finish = this->_M_impl._M_start; - this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; - } - }; - - /** - * @brief A standard container which offers fixed time access to - * individual elements in any order. - * - * @ingroup sequences - * - * @tparam _Tp Type of element. - * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. - * - * Meets the requirements of a container, a - * reversible container, and a - * sequence, including the - * optional sequence requirements with the - * %exception of @c push_front and @c pop_front. - * - * In some terminology a %vector can be described as a dynamic - * C-style array, it offers fast and efficient access to individual - * elements in any order and saves the user from worrying about - * memory and size allocation. Subscripting ( @c [] ) access is - * also provided as with C-style arrays. - */ - template > - class vector : protected _Vector_base<_Tp, _Alloc> - { -#ifdef _GLIBCXX_CONCEPT_CHECKS - // Concept requirements. - typedef typename _Alloc::value_type _Alloc_value_type; -# if __cplusplus < 201103L - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) -# endif - __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) -#endif - -#if __cplusplus >= 201103L - static_assert(is_same::type, _Tp>::value, - "std::vector must have a non-const, non-volatile value_type"); -# if __cplusplus > 201703L || defined __STRICT_ANSI__ - static_assert(is_same::value, - "std::vector must have the same value_type as its allocator"); -# endif -#endif - - typedef _Vector_base<_Tp, _Alloc> _Base; - typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; - typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; - - public: - typedef _Tp value_type; - typedef typename _Base::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; - typedef __gnu_cxx::__normal_iterator iterator; - typedef __gnu_cxx::__normal_iterator - const_iterator; - typedef std::reverse_iterator const_reverse_iterator; - typedef std::reverse_iterator reverse_iterator; - typedef size_t size_type; - typedef ptrdiff_t difference_type; - typedef _Alloc allocator_type; - - private: -#if __cplusplus >= 201103L - static constexpr bool - _S_nothrow_relocate(true_type) - { - return noexcept(std::__relocate_a(std::declval(), - std::declval(), - std::declval(), - std::declval<_Tp_alloc_type&>())); - } - - static constexpr bool - _S_nothrow_relocate(false_type) - { return false; } - - static constexpr bool - _S_use_relocate() - { - // Instantiating std::__relocate_a might cause an error outside the - // immediate context (in __relocate_object_a's noexcept-specifier), - // so only do it if we know the type can be move-inserted into *this. - return _S_nothrow_relocate(__is_move_insertable<_Tp_alloc_type>{}); - } - - static pointer - _S_do_relocate(pointer __first, pointer __last, pointer __result, - _Tp_alloc_type& __alloc, true_type) noexcept - { - return std::__relocate_a(__first, __last, __result, __alloc); - } - - static pointer - _S_do_relocate(pointer, pointer, pointer __result, - _Tp_alloc_type&, false_type) noexcept - { return __result; } - - static pointer - _S_relocate(pointer __first, pointer __last, pointer __result, - _Tp_alloc_type& __alloc) noexcept - { - using __do_it = __bool_constant<_S_use_relocate()>; - return _S_do_relocate(__first, __last, __result, __alloc, __do_it{}); - } -#endif // C++11 - - protected: - using _Base::_M_allocate; - using _Base::_M_deallocate; - using _Base::_M_impl; - using _Base::_M_get_Tp_allocator; - - public: - // [23.2.4.1] construct/copy/destroy - // (assign() and get_allocator() are also listed in this section) - - /** - * @brief Creates a %vector with no elements. - */ -#if __cplusplus >= 201103L - vector() = default; -#else - vector() { } -#endif - - /** - * @brief Creates a %vector with no elements. - * @param __a An allocator object. - */ - explicit - vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT - : _Base(__a) { } - -#if __cplusplus >= 201103L - /** - * @brief Creates a %vector with default constructed elements. - * @param __n The number of elements to initially create. - * @param __a An allocator. - * - * This constructor fills the %vector with @a __n default - * constructed elements. - */ - explicit - vector(size_type __n, const allocator_type& __a = allocator_type()) - : _Base(_S_check_init_len(__n, __a), __a) - { _M_default_initialize(__n); } - - /** - * @brief Creates a %vector with copies of an exemplar element. - * @param __n The number of elements to initially create. - * @param __value An element to copy. - * @param __a An allocator. - * - * This constructor fills the %vector with @a __n copies of @a __value. - */ - vector(size_type __n, const value_type& __value, - const allocator_type& __a = allocator_type()) - : _Base(_S_check_init_len(__n, __a), __a) - { _M_fill_initialize(__n, __value); } -#else - /** - * @brief Creates a %vector with copies of an exemplar element. - * @param __n The number of elements to initially create. - * @param __value An element to copy. - * @param __a An allocator. - * - * This constructor fills the %vector with @a __n copies of @a __value. - */ - explicit - vector(size_type __n, const value_type& __value = value_type(), - const allocator_type& __a = allocator_type()) - : _Base(_S_check_init_len(__n, __a), __a) - { _M_fill_initialize(__n, __value); } -#endif - - /** - * @brief %Vector copy constructor. - * @param __x A %vector of identical element and allocator types. - * - * All the elements of @a __x are copied, but any unused capacity in - * @a __x will not be copied - * (i.e. capacity() == size() in the new %vector). - * - * The newly-created %vector uses a copy of the allocator object used - * by @a __x (unless the allocator traits dictate a different object). - */ - vector(const vector& __x) - : _Base(__x.size(), - _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator())) - { - this->_M_impl._M_finish = - std::__uninitialized_copy_a(__x.begin(), __x.end(), - this->_M_impl._M_start, - _M_get_Tp_allocator()); - } - -#if __cplusplus >= 201103L - /** - * @brief %Vector move constructor. - * - * The newly-created %vector contains the exact contents of the - * moved instance. - * The contents of the moved instance are a valid, but unspecified - * %vector. - */ - vector(vector&&) noexcept = default; - - /// Copy constructor with alternative allocator - vector(const vector& __x, const allocator_type& __a) - : _Base(__x.size(), __a) - { - this->_M_impl._M_finish = - std::__uninitialized_copy_a(__x.begin(), __x.end(), - this->_M_impl._M_start, - _M_get_Tp_allocator()); - } - - private: - vector(vector&& __rv, const allocator_type& __m, true_type) noexcept - : _Base(__m, std::move(__rv)) - { } - - vector(vector&& __rv, const allocator_type& __m, false_type) - : _Base(__m) - { - if (__rv.get_allocator() == __m) - this->_M_impl._M_swap_data(__rv._M_impl); - else if (!__rv.empty()) - { - this->_M_create_storage(__rv.size()); - this->_M_impl._M_finish = - std::__uninitialized_move_a(__rv.begin(), __rv.end(), - this->_M_impl._M_start, - _M_get_Tp_allocator()); - __rv.clear(); - } - } - - public: - /// Move constructor with alternative allocator - vector(vector&& __rv, const allocator_type& __m) - noexcept( noexcept( - vector(std::declval(), std::declval(), - std::declval())) ) - : vector(std::move(__rv), __m, typename _Alloc_traits::is_always_equal{}) - { } - - /** - * @brief Builds a %vector from an initializer list. - * @param __l An initializer_list. - * @param __a An allocator. - * - * Create a %vector consisting of copies of the elements in the - * initializer_list @a __l. - * - * This will call the element type's copy constructor N times - * (where N is @a __l.size()) and do no memory reallocation. - */ - vector(initializer_list __l, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - _M_range_initialize(__l.begin(), __l.end(), - random_access_iterator_tag()); - } -#endif - - /** - * @brief Builds a %vector from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __a An allocator. - * - * Create a %vector consisting of copies of the elements from - * [first,last). - * - * If the iterators are forward, bidirectional, or - * random-access, then this will call the elements' copy - * constructor N times (where N is distance(first,last)) and do - * no memory reallocation. But if only input iterators are - * used, then this will do at most 2N calls to the copy - * constructor, and logN memory reallocations. - */ -#if __cplusplus >= 201103L - template> - vector(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - _M_range_initialize(__first, __last, - std::__iterator_category(__first)); - } -#else - template - vector(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_initialize_dispatch(__first, __last, _Integral()); - } -#endif - - /** - * The dtor only erases the elements, and note that if the - * elements themselves are pointers, the pointed-to memory is - * not touched in any way. Managing the pointer is the user's - * responsibility. - */ - ~vector() _GLIBCXX_NOEXCEPT - { - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC; - } - - /** - * @brief %Vector assignment operator. - * @param __x A %vector of identical element and allocator types. - * - * All the elements of @a __x are copied, but any unused capacity in - * @a __x will not be copied. - * - * Whether the allocator is copied depends on the allocator traits. - */ - vector& - operator=(const vector& __x); - -#if __cplusplus >= 201103L - /** - * @brief %Vector move assignment operator. - * @param __x A %vector of identical element and allocator types. - * - * The contents of @a __x are moved into this %vector (without copying, - * if the allocators permit it). - * Afterwards @a __x is a valid, but unspecified %vector. - * - * Whether the allocator is moved depends on the allocator traits. - */ - vector& - operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move()) - { - constexpr bool __move_storage = - _Alloc_traits::_S_propagate_on_move_assign() - || _Alloc_traits::_S_always_equal(); - _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); - return *this; - } - - /** - * @brief %Vector list assignment operator. - * @param __l An initializer_list. - * - * This function fills a %vector with copies of the elements in the - * initializer list @a __l. - * - * Note that the assignment completely changes the %vector and - * that the resulting %vector's size is the same as the number - * of elements assigned. - */ - vector& - operator=(initializer_list __l) - { - this->_M_assign_aux(__l.begin(), __l.end(), - random_access_iterator_tag()); - return *this; - } -#endif - - /** - * @brief Assigns a given value to a %vector. - * @param __n Number of elements to be assigned. - * @param __val Value to be assigned. - * - * This function fills a %vector with @a __n copies of the given - * value. Note that the assignment completely changes the - * %vector and that the resulting %vector's size is the same as - * the number of elements assigned. - */ - void - assign(size_type __n, const value_type& __val) - { _M_fill_assign(__n, __val); } - - /** - * @brief Assigns a range to a %vector. - * @param __first An input iterator. - * @param __last An input iterator. - * - * This function fills a %vector with copies of the elements in the - * range [__first,__last). - * - * Note that the assignment completely changes the %vector and - * that the resulting %vector's size is the same as the number - * of elements assigned. - */ -#if __cplusplus >= 201103L - template> - void - assign(_InputIterator __first, _InputIterator __last) - { _M_assign_dispatch(__first, __last, __false_type()); } -#else - template - void - assign(_InputIterator __first, _InputIterator __last) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_assign_dispatch(__first, __last, _Integral()); - } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Assigns an initializer list to a %vector. - * @param __l An initializer_list. - * - * This function fills a %vector with copies of the elements in the - * initializer list @a __l. - * - * Note that the assignment completely changes the %vector and - * that the resulting %vector's size is the same as the number - * of elements assigned. - */ - void - assign(initializer_list __l) - { - this->_M_assign_aux(__l.begin(), __l.end(), - random_access_iterator_tag()); - } -#endif - - /// Get a copy of the memory allocation object. - using _Base::get_allocator; - - // iterators - /** - * Returns a read/write iterator that points to the first - * element in the %vector. Iteration is done in ordinary - * element order. - */ - iterator - begin() _GLIBCXX_NOEXCEPT - { return iterator(this->_M_impl._M_start); } - - /** - * Returns a read-only (constant) iterator that points to the - * first element in the %vector. Iteration is done in ordinary - * element order. - */ - const_iterator - begin() const _GLIBCXX_NOEXCEPT - { return const_iterator(this->_M_impl._M_start); } - - /** - * Returns a read/write iterator that points one past the last - * element in the %vector. Iteration is done in ordinary - * element order. - */ - iterator - end() _GLIBCXX_NOEXCEPT - { return iterator(this->_M_impl._M_finish); } - - /** - * Returns a read-only (constant) iterator that points one past - * the last element in the %vector. Iteration is done in - * ordinary element order. - */ - const_iterator - end() const _GLIBCXX_NOEXCEPT - { return const_iterator(this->_M_impl._M_finish); } - - /** - * Returns a read/write reverse iterator that points to the - * last element in the %vector. Iteration is done in reverse - * element order. - */ - reverse_iterator - rbegin() _GLIBCXX_NOEXCEPT - { return reverse_iterator(end()); } - - /** - * Returns a read-only (constant) reverse iterator that points - * to the last element in the %vector. Iteration is done in - * reverse element order. - */ - const_reverse_iterator - rbegin() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(end()); } - - /** - * Returns a read/write reverse iterator that points to one - * before the first element in the %vector. Iteration is done - * in reverse element order. - */ - reverse_iterator - rend() _GLIBCXX_NOEXCEPT - { return reverse_iterator(begin()); } - - /** - * Returns a read-only (constant) reverse iterator that points - * to one before the first element in the %vector. Iteration - * is done in reverse element order. - */ - const_reverse_iterator - rend() const _GLIBCXX_NOEXCEPT - { return const_reverse_iterator(begin()); } - -#if __cplusplus >= 201103L - /** - * Returns a read-only (constant) iterator that points to the - * first element in the %vector. Iteration is done in ordinary - * element order. - */ - const_iterator - cbegin() const noexcept - { return const_iterator(this->_M_impl._M_start); } - - /** - * Returns a read-only (constant) iterator that points one past - * the last element in the %vector. Iteration is done in - * ordinary element order. - */ - const_iterator - cend() const noexcept - { return const_iterator(this->_M_impl._M_finish); } - - /** - * Returns a read-only (constant) reverse iterator that points - * to the last element in the %vector. Iteration is done in - * reverse element order. - */ - const_reverse_iterator - crbegin() const noexcept - { return const_reverse_iterator(end()); } - - /** - * Returns a read-only (constant) reverse iterator that points - * to one before the first element in the %vector. Iteration - * is done in reverse element order. - */ - const_reverse_iterator - crend() const noexcept - { return const_reverse_iterator(begin()); } -#endif - - // [23.2.4.2] capacity - /** Returns the number of elements in the %vector. */ - size_type - size() const _GLIBCXX_NOEXCEPT - { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); } - - /** Returns the size() of the largest possible %vector. */ - size_type - max_size() const _GLIBCXX_NOEXCEPT - { return _S_max_size(_M_get_Tp_allocator()); } - -#if __cplusplus >= 201103L - /** - * @brief Resizes the %vector to the specified number of elements. - * @param __new_size Number of elements the %vector should contain. - * - * This function will %resize the %vector to the specified - * number of elements. If the number is smaller than the - * %vector's current size the %vector is truncated, otherwise - * default constructed elements are appended. - */ - void - resize(size_type __new_size) - { - if (__new_size > size()) - _M_default_append(__new_size - size()); - else if (__new_size < size()) - _M_erase_at_end(this->_M_impl._M_start + __new_size); - } - - /** - * @brief Resizes the %vector to the specified number of elements. - * @param __new_size Number of elements the %vector should contain. - * @param __x Data with which new elements should be populated. - * - * This function will %resize the %vector to the specified - * number of elements. If the number is smaller than the - * %vector's current size the %vector is truncated, otherwise - * the %vector is extended and new elements are populated with - * given data. - */ - void - resize(size_type __new_size, const value_type& __x) - { - if (__new_size > size()) - _M_fill_insert(end(), __new_size - size(), __x); - else if (__new_size < size()) - _M_erase_at_end(this->_M_impl._M_start + __new_size); - } -#else - /** - * @brief Resizes the %vector to the specified number of elements. - * @param __new_size Number of elements the %vector should contain. - * @param __x Data with which new elements should be populated. - * - * This function will %resize the %vector to the specified - * number of elements. If the number is smaller than the - * %vector's current size the %vector is truncated, otherwise - * the %vector is extended and new elements are populated with - * given data. - */ - void - resize(size_type __new_size, value_type __x = value_type()) - { - if (__new_size > size()) - _M_fill_insert(end(), __new_size - size(), __x); - else if (__new_size < size()) - _M_erase_at_end(this->_M_impl._M_start + __new_size); - } -#endif - -#if __cplusplus >= 201103L - /** A non-binding request to reduce capacity() to size(). */ - void - shrink_to_fit() - { _M_shrink_to_fit(); } -#endif - - /** - * Returns the total number of elements that the %vector can - * hold before needing to allocate more memory. - */ - size_type - capacity() const _GLIBCXX_NOEXCEPT - { return size_type(this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); } - - /** - * Returns true if the %vector is empty. (Thus begin() would - * equal end().) - */ - _GLIBCXX_NODISCARD bool - empty() const _GLIBCXX_NOEXCEPT - { return begin() == end(); } - - /** - * @brief Attempt to preallocate enough memory for specified number of - * elements. - * @param __n Number of elements required. - * @throw std::length_error If @a n exceeds @c max_size(). - * - * This function attempts to reserve enough memory for the - * %vector to hold the specified number of elements. If the - * number requested is more than max_size(), length_error is - * thrown. - * - * The advantage of this function is that if optimal code is a - * necessity and the user can determine the number of elements - * that will be required, the user can reserve the memory in - * %advance, and thus prevent a possible reallocation of memory - * and copying of %vector data. - */ - void - reserve(size_type __n); - - // element access - /** - * @brief Subscript access to the data contained in the %vector. - * @param __n The index of the element for which data should be - * accessed. - * @return Read/write reference to data. - * - * This operator allows for easy, array-style, data access. - * Note that data access with this operator is unchecked and - * out_of_range lookups are not defined. (For checked lookups - * see at().) - */ - reference - operator[](size_type __n) _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_subscript(__n); - return *(this->_M_impl._M_start + __n); - } - - /** - * @brief Subscript access to the data contained in the %vector. - * @param __n The index of the element for which data should be - * accessed. - * @return Read-only (constant) reference to data. - * - * This operator allows for easy, array-style, data access. - * Note that data access with this operator is unchecked and - * out_of_range lookups are not defined. (For checked lookups - * see at().) - */ - const_reference - operator[](size_type __n) const _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_subscript(__n); - return *(this->_M_impl._M_start + __n); - } - - protected: - /// Safety check used only from at(). - void - _M_range_check(size_type __n) const - { - if (__n >= this->size()) - __throw_out_of_range_fmt(__N("vector::_M_range_check: __n " - "(which is %zu) >= this->size() " - "(which is %zu)"), - __n, this->size()); - } - - public: - /** - * @brief Provides access to the data contained in the %vector. - * @param __n The index of the element for which data should be - * accessed. - * @return Read/write reference to data. - * @throw std::out_of_range If @a __n is an invalid index. - * - * This function provides for safer data access. The parameter - * is first checked that it is in the range of the vector. The - * function throws out_of_range if the check fails. - */ - reference - at(size_type __n) - { - _M_range_check(__n); - return (*this)[__n]; - } - - /** - * @brief Provides access to the data contained in the %vector. - * @param __n The index of the element for which data should be - * accessed. - * @return Read-only (constant) reference to data. - * @throw std::out_of_range If @a __n is an invalid index. - * - * This function provides for safer data access. The parameter - * is first checked that it is in the range of the vector. The - * function throws out_of_range if the check fails. - */ - const_reference - at(size_type __n) const - { - _M_range_check(__n); - return (*this)[__n]; - } - - /** - * Returns a read/write reference to the data at the first - * element of the %vector. - */ - reference - front() _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - return *begin(); - } - - /** - * Returns a read-only (constant) reference to the data at the first - * element of the %vector. - */ - const_reference - front() const _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - return *begin(); - } - - /** - * Returns a read/write reference to the data at the last - * element of the %vector. - */ - reference - back() _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - return *(end() - 1); - } - - /** - * Returns a read-only (constant) reference to the data at the - * last element of the %vector. - */ - const_reference - back() const _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - return *(end() - 1); - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 464. Suggestion for new member functions in standard containers. - // data access - /** - * Returns a pointer such that [data(), data() + size()) is a valid - * range. For a non-empty %vector, data() == &front(). - */ - _Tp* - data() _GLIBCXX_NOEXCEPT - { return _M_data_ptr(this->_M_impl._M_start); } - - const _Tp* - data() const _GLIBCXX_NOEXCEPT - { return _M_data_ptr(this->_M_impl._M_start); } - - // [23.2.4.3] modifiers - /** - * @brief Add data to the end of the %vector. - * @param __x Data to be added. - * - * This is a typical stack operation. The function creates an - * element at the end of the %vector and assigns the given data - * to it. Due to the nature of a %vector this operation can be - * done in constant time if the %vector has preallocated space - * available. - */ - void - push_back(const value_type& __x) - { - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - { - _GLIBCXX_ASAN_ANNOTATE_GROW(1); - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - __x); - ++this->_M_impl._M_finish; - _GLIBCXX_ASAN_ANNOTATE_GREW(1); - } - else - _M_realloc_insert(end(), __x); - } - -#if __cplusplus >= 201103L - void - push_back(value_type&& __x) - { emplace_back(std::move(__x)); } - - template -#if __cplusplus > 201402L - reference -#else - void -#endif - emplace_back(_Args&&... __args); -#endif - - /** - * @brief Removes last element. - * - * This is a typical stack operation. It shrinks the %vector by one. - * - * Note that no data is returned, and if the last element's - * data is needed, it should be retrieved before pop_back() is - * called. - */ - void - pop_back() _GLIBCXX_NOEXCEPT - { - __glibcxx_requires_nonempty(); - --this->_M_impl._M_finish; - _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); - _GLIBCXX_ASAN_ANNOTATE_SHRINK(1); - } - -#if __cplusplus >= 201103L - /** - * @brief Inserts an object in %vector before specified iterator. - * @param __position A const_iterator into the %vector. - * @param __args Arguments. - * @return An iterator that points to the inserted data. - * - * This function will insert an object of type T constructed - * with T(std::forward(args)...) before the specified location. - * Note that this kind of operation could be expensive for a %vector - * and if it is frequently used the user should consider using - * std::list. - */ - template - iterator - emplace(const_iterator __position, _Args&&... __args) - { return _M_emplace_aux(__position, std::forward<_Args>(__args)...); } - - /** - * @brief Inserts given value into %vector before specified iterator. - * @param __position A const_iterator into the %vector. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before - * the specified location. Note that this kind of operation - * could be expensive for a %vector and if it is frequently - * used the user should consider using std::list. - */ - iterator - insert(const_iterator __position, const value_type& __x); -#else - /** - * @brief Inserts given value into %vector before specified iterator. - * @param __position An iterator into the %vector. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given value before - * the specified location. Note that this kind of operation - * could be expensive for a %vector and if it is frequently - * used the user should consider using std::list. - */ - iterator - insert(iterator __position, const value_type& __x); -#endif - -#if __cplusplus >= 201103L - /** - * @brief Inserts given rvalue into %vector before specified iterator. - * @param __position A const_iterator into the %vector. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a copy of the given rvalue before - * the specified location. Note that this kind of operation - * could be expensive for a %vector and if it is frequently - * used the user should consider using std::list. - */ - iterator - insert(const_iterator __position, value_type&& __x) - { return _M_insert_rval(__position, std::move(__x)); } - - /** - * @brief Inserts an initializer_list into the %vector. - * @param __position An iterator into the %vector. - * @param __l An initializer_list. - * - * This function will insert copies of the data in the - * initializer_list @a l into the %vector before the location - * specified by @a position. - * - * Note that this kind of operation could be expensive for a - * %vector and if it is frequently used the user should - * consider using std::list. - */ - iterator - insert(const_iterator __position, initializer_list __l) - { - auto __offset = __position - cbegin(); - _M_range_insert(begin() + __offset, __l.begin(), __l.end(), - std::random_access_iterator_tag()); - return begin() + __offset; - } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Inserts a number of copies of given data into the %vector. - * @param __position A const_iterator into the %vector. - * @param __n Number of elements to be inserted. - * @param __x Data to be inserted. - * @return An iterator that points to the inserted data. - * - * This function will insert a specified number of copies of - * the given data before the location specified by @a position. - * - * Note that this kind of operation could be expensive for a - * %vector and if it is frequently used the user should - * consider using std::list. - */ - iterator - insert(const_iterator __position, size_type __n, const value_type& __x) - { - difference_type __offset = __position - cbegin(); - _M_fill_insert(begin() + __offset, __n, __x); - return begin() + __offset; - } -#else - /** - * @brief Inserts a number of copies of given data into the %vector. - * @param __position An iterator into the %vector. - * @param __n Number of elements to be inserted. - * @param __x Data to be inserted. - * - * This function will insert a specified number of copies of - * the given data before the location specified by @a position. - * - * Note that this kind of operation could be expensive for a - * %vector and if it is frequently used the user should - * consider using std::list. - */ - void - insert(iterator __position, size_type __n, const value_type& __x) - { _M_fill_insert(__position, __n, __x); } -#endif - -#if __cplusplus >= 201103L - /** - * @brief Inserts a range into the %vector. - * @param __position A const_iterator into the %vector. - * @param __first An input iterator. - * @param __last An input iterator. - * @return An iterator that points to the inserted data. - * - * This function will insert copies of the data in the range - * [__first,__last) into the %vector before the location specified - * by @a pos. - * - * Note that this kind of operation could be expensive for a - * %vector and if it is frequently used the user should - * consider using std::list. - */ - template> - iterator - insert(const_iterator __position, _InputIterator __first, - _InputIterator __last) - { - difference_type __offset = __position - cbegin(); - _M_insert_dispatch(begin() + __offset, - __first, __last, __false_type()); - return begin() + __offset; - } -#else - /** - * @brief Inserts a range into the %vector. - * @param __position An iterator into the %vector. - * @param __first An input iterator. - * @param __last An input iterator. - * - * This function will insert copies of the data in the range - * [__first,__last) into the %vector before the location specified - * by @a pos. - * - * Note that this kind of operation could be expensive for a - * %vector and if it is frequently used the user should - * consider using std::list. - */ - template - void - insert(iterator __position, _InputIterator __first, - _InputIterator __last) - { - // Check whether it's an integral type. If so, it's not an iterator. - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_insert_dispatch(__position, __first, __last, _Integral()); - } -#endif - - /** - * @brief Remove element at given position. - * @param __position Iterator pointing to element to be erased. - * @return An iterator pointing to the next element (or end()). - * - * This function will erase the element at the given position and thus - * shorten the %vector by one. - * - * Note This operation could be expensive and if it is - * frequently used the user should consider using std::list. - * The user is also cautioned that this function only erases - * the element, and that if the element is itself a pointer, - * the pointed-to memory is not touched in any way. Managing - * the pointer is the user's responsibility. - */ - iterator -#if __cplusplus >= 201103L - erase(const_iterator __position) - { return _M_erase(begin() + (__position - cbegin())); } -#else - erase(iterator __position) - { return _M_erase(__position); } -#endif - - /** - * @brief Remove a range of elements. - * @param __first Iterator pointing to the first element to be erased. - * @param __last Iterator pointing to one past the last element to be - * erased. - * @return An iterator pointing to the element pointed to by @a __last - * prior to erasing (or end()). - * - * This function will erase the elements in the range - * [__first,__last) and shorten the %vector accordingly. - * - * Note This operation could be expensive and if it is - * frequently used the user should consider using std::list. - * The user is also cautioned that this function only erases - * the elements, and that if the elements themselves are - * pointers, the pointed-to memory is not touched in any way. - * Managing the pointer is the user's responsibility. - */ - iterator -#if __cplusplus >= 201103L - erase(const_iterator __first, const_iterator __last) - { - const auto __beg = begin(); - const auto __cbeg = cbegin(); - return _M_erase(__beg + (__first - __cbeg), __beg + (__last - __cbeg)); - } -#else - erase(iterator __first, iterator __last) - { return _M_erase(__first, __last); } -#endif - - /** - * @brief Swaps data with another %vector. - * @param __x A %vector of the same element and allocator types. - * - * This exchanges the elements between two vectors in constant time. - * (Three pointers, so it should be quite fast.) - * Note that the global std::swap() function is specialized such that - * std::swap(v1,v2) will feed to this function. - * - * Whether the allocators are swapped depends on the allocator traits. - */ - void - swap(vector& __x) _GLIBCXX_NOEXCEPT - { -#if __cplusplus >= 201103L - __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value - || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()); -#endif - this->_M_impl._M_swap_data(__x._M_impl); - _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), - __x._M_get_Tp_allocator()); - } - - /** - * Erases all the elements. Note that this function only erases the - * elements, and that if the elements themselves are pointers, the - * pointed-to memory is not touched in any way. Managing the pointer is - * the user's responsibility. - */ - void - clear() _GLIBCXX_NOEXCEPT - { _M_erase_at_end(this->_M_impl._M_start); } - - protected: - /** - * Memory expansion handler. Uses the member allocation function to - * obtain @a n bytes of memory, and then copies [first,last) into it. - */ - template - pointer - _M_allocate_and_copy(size_type __n, - _ForwardIterator __first, _ForwardIterator __last) - { - pointer __result = this->_M_allocate(__n); - __try - { - std::__uninitialized_copy_a(__first, __last, __result, - _M_get_Tp_allocator()); - return __result; - } - __catch(...) - { - _M_deallocate(__result, __n); - __throw_exception_again; - } - } - - - // Internal constructor functions follow. - - // Called by the range constructor to implement [23.1.1]/9 - -#if __cplusplus < 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type) - { - this->_M_impl._M_start = _M_allocate(_S_check_init_len( - static_cast(__n), _M_get_Tp_allocator())); - this->_M_impl._M_end_of_storage = - this->_M_impl._M_start + static_cast(__n); - _M_fill_initialize(static_cast(__n), __value); - } - - // Called by the range constructor to implement [23.1.1]/9 - template - void - _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { - _M_range_initialize(__first, __last, - std::__iterator_category(__first)); - } -#endif - - // Called by the second initialize_dispatch above - template - void - _M_range_initialize(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag) - { - __try { - for (; __first != __last; ++__first) -#if __cplusplus >= 201103L - emplace_back(*__first); -#else - push_back(*__first); -#endif - } __catch(...) { - clear(); - __throw_exception_again; - } - } - - // Called by the second initialize_dispatch above - template - void - _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) - { - const size_type __n = std::distance(__first, __last); - this->_M_impl._M_start - = this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator())); - this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; - this->_M_impl._M_finish = - std::__uninitialized_copy_a(__first, __last, - this->_M_impl._M_start, - _M_get_Tp_allocator()); - } - - // Called by the first initialize_dispatch above and by the - // vector(n,value,a) constructor. - void - _M_fill_initialize(size_type __n, const value_type& __value) - { - this->_M_impl._M_finish = - std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value, - _M_get_Tp_allocator()); - } - -#if __cplusplus >= 201103L - // Called by the vector(n) constructor. - void - _M_default_initialize(size_type __n) - { - this->_M_impl._M_finish = - std::__uninitialized_default_n_a(this->_M_impl._M_start, __n, - _M_get_Tp_allocator()); - } -#endif - - // Internal assign functions follow. The *_aux functions do the actual - // assignment work for the range versions. - - // Called by the range assign to implement [23.1.1]/9 - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) - { _M_fill_assign(__n, __val); } - - // Called by the range assign to implement [23.1.1]/9 - template - void - _M_assign_dispatch(_InputIterator __first, _InputIterator __last, - __false_type) - { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } - - // Called by the second assign_dispatch above - template - void - _M_assign_aux(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag); - - // Called by the second assign_dispatch above - template - void - _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag); - - // Called by assign(n,t), and the range assign when it turns out - // to be the same thing. - void - _M_fill_assign(size_type __n, const value_type& __val); - - // Internal insert functions follow. - - // Called by the range insert to implement [23.1.1]/9 - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 438. Ambiguity in the "do the right thing" clause - template - void - _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, - __true_type) - { _M_fill_insert(__pos, __n, __val); } - - // Called by the range insert to implement [23.1.1]/9 - template - void - _M_insert_dispatch(iterator __pos, _InputIterator __first, - _InputIterator __last, __false_type) - { - _M_range_insert(__pos, __first, __last, - std::__iterator_category(__first)); - } - - // Called by the second insert_dispatch above - template - void - _M_range_insert(iterator __pos, _InputIterator __first, - _InputIterator __last, std::input_iterator_tag); - - // Called by the second insert_dispatch above - template - void - _M_range_insert(iterator __pos, _ForwardIterator __first, - _ForwardIterator __last, std::forward_iterator_tag); - - // Called by insert(p,n,x), and the range insert when it turns out to be - // the same thing. - void - _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); - -#if __cplusplus >= 201103L - // Called by resize(n). - void - _M_default_append(size_type __n); - - bool - _M_shrink_to_fit(); -#endif - -#if __cplusplus < 201103L - // Called by insert(p,x) - void - _M_insert_aux(iterator __position, const value_type& __x); - - void - _M_realloc_insert(iterator __position, const value_type& __x); -#else - // A value_type object constructed with _Alloc_traits::construct() - // and destroyed with _Alloc_traits::destroy(). - struct _Temporary_value - { - template - explicit - _Temporary_value(vector* __vec, _Args&&... __args) : _M_this(__vec) - { - _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(), - std::forward<_Args>(__args)...); - } - - ~_Temporary_value() - { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); } - - value_type& - _M_val() { return *_M_ptr(); } - - private: - _Tp* - _M_ptr() { return reinterpret_cast<_Tp*>(&__buf); } - - vector* _M_this; - typename aligned_storage::type __buf; - }; - - // Called by insert(p,x) and other functions when insertion needs to - // reallocate or move existing elements. _Arg is either _Tp& or _Tp. - template - void - _M_insert_aux(iterator __position, _Arg&& __arg); - - template - void - _M_realloc_insert(iterator __position, _Args&&... __args); - - // Either move-construct at the end, or forward to _M_insert_aux. - iterator - _M_insert_rval(const_iterator __position, value_type&& __v); - - // Try to emplace at the end, otherwise forward to _M_insert_aux. - template - iterator - _M_emplace_aux(const_iterator __position, _Args&&... __args); - - // Emplacing an rvalue of the correct type can use _M_insert_rval. - iterator - _M_emplace_aux(const_iterator __position, value_type&& __v) - { return _M_insert_rval(__position, std::move(__v)); } -#endif - - // Called by _M_fill_insert, _M_insert_aux etc. - size_type - _M_check_len(size_type __n, const char* __s) const - { - if (max_size() - size() < __n) - __throw_length_error(__N(__s)); - - const size_type __len = size() + (std::max)(size(), __n); - return (__len < size() || __len > max_size()) ? max_size() : __len; - } - - // Called by constructors to check initial size. - static size_type - _S_check_init_len(size_type __n, const allocator_type& __a) - { - if (__n > _S_max_size(_Tp_alloc_type(__a))) - __throw_length_error( - __N("cannot create std::vector larger than max_size()")); - return __n; - } - - static size_type - _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT - { - // std::distance(begin(), end()) cannot be greater than PTRDIFF_MAX, - // and realistically we can't store more than PTRDIFF_MAX/sizeof(T) - // (even if std::allocator_traits::max_size says we can). - const size_t __diffmax - = __gnu_cxx::__numeric_traits::__max / sizeof(_Tp); - const size_t __allocmax = _Alloc_traits::max_size(__a); - return (std::min)(__diffmax, __allocmax); - } - - // Internal erase functions follow. - - // Called by erase(q1,q2), clear(), resize(), _M_fill_assign, - // _M_assign_aux. - void - _M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT - { - if (size_type __n = this->_M_impl._M_finish - __pos) - { - std::_Destroy(__pos, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish = __pos; - _GLIBCXX_ASAN_ANNOTATE_SHRINK(__n); - } - } - - iterator - _M_erase(iterator __position); - - iterator - _M_erase(iterator __first, iterator __last); - -#if __cplusplus >= 201103L - private: - // Constant-time move assignment when source object's memory can be - // moved, either because the source's allocator will move too - // or because the allocators are equal. - void - _M_move_assign(vector&& __x, true_type) noexcept - { - vector __tmp(get_allocator()); - this->_M_impl._M_swap_data(__x._M_impl); - __tmp._M_impl._M_swap_data(__x._M_impl); - std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); - } - - // Do move assignment when it might not be possible to move source - // object's memory, resulting in a linear-time operation. - void - _M_move_assign(vector&& __x, false_type) - { - if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator()) - _M_move_assign(std::move(__x), true_type()); - else - { - // The rvalue's allocator cannot be moved and is not equal, - // so we need to individually move each element. - this->_M_assign_aux(std::make_move_iterator(__x.begin()), - std::make_move_iterator(__x.end()), - std::random_access_iterator_tag()); - __x.clear(); - } - } -#endif - - template - _Up* - _M_data_ptr(_Up* __ptr) const _GLIBCXX_NOEXCEPT - { return __ptr; } - -#if __cplusplus >= 201103L - template - typename std::pointer_traits<_Ptr>::element_type* - _M_data_ptr(_Ptr __ptr) const - { return empty() ? nullptr : std::__to_address(__ptr); } -#else - template - _Up* - _M_data_ptr(_Up* __ptr) _GLIBCXX_NOEXCEPT - { return __ptr; } - - template - value_type* - _M_data_ptr(_Ptr __ptr) - { return empty() ? (value_type*)0 : __ptr.operator->(); } - - template - const value_type* - _M_data_ptr(_Ptr __ptr) const - { return empty() ? (const value_type*)0 : __ptr.operator->(); } -#endif - }; - -#if __cpp_deduction_guides >= 201606 - template::value_type, - typename _Allocator = allocator<_ValT>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireAllocator<_Allocator>> - vector(_InputIterator, _InputIterator, _Allocator = _Allocator()) - -> vector<_ValT, _Allocator>; -#endif - - /** - * @brief Vector equality comparison. - * @param __x A %vector. - * @param __y A %vector of the same type as @a __x. - * @return True iff the size and elements of the vectors are equal. - * - * This is an equivalence relation. It is linear in the size of the - * vectors. Vectors are considered equivalent if their sizes are equal, - * and if corresponding elements compare equal. - */ - template - inline bool - operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) - { return (__x.size() == __y.size() - && std::equal(__x.begin(), __x.end(), __y.begin())); } - -#if __cpp_lib_three_way_comparison - /** - * @brief Vector ordering relation. - * @param __x A `vector`. - * @param __y A `vector` of the same type as `__x`. - * @return A value indicating whether `__x` is less than, equal to, - * greater than, or incomparable with `__y`. - * - * See `std::lexicographical_compare_three_way()` for how the determination - * is made. This operator is used to synthesize relational operators like - * `<` and `>=` etc. - */ - template - inline __detail::__synth3way_t<_Tp> - operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) - { - return std::lexicographical_compare_three_way(__x.begin(), __x.end(), - __y.begin(), __y.end(), - __detail::__synth3way); - } -#else - /** - * @brief Vector ordering relation. - * @param __x A %vector. - * @param __y A %vector of the same type as @a __x. - * @return True iff @a __x is lexicographically less than @a __y. - * - * This is a total ordering relation. It is linear in the size of the - * vectors. The elements must be comparable with @c <. - * - * See std::lexicographical_compare() for how the determination is made. - */ - template - inline bool - operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) - { return std::lexicographical_compare(__x.begin(), __x.end(), - __y.begin(), __y.end()); } - - /// Based on operator== - template - inline bool - operator!=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) - { return !(__x == __y); } - - /// Based on operator< - template - inline bool - operator>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) - { return __y < __x; } - - /// Based on operator< - template - inline bool - operator<=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) - { return !(__y < __x); } - - /// Based on operator< - template - inline bool - operator>=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) - { return !(__x < __y); } -#endif // three-way comparison - - /// See std::vector::swap(). - template - inline void - swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y) - _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if __cplusplus >= 201703L - namespace __detail::__variant - { - template struct _Never_valueless_alt; // see - - // Provide the strong exception-safety guarantee when emplacing a - // vector into a variant, but only if move assignment cannot throw. - template - struct _Never_valueless_alt<_GLIBCXX_STD_C::vector<_Tp, _Alloc>> - : std::is_nothrow_move_assignable<_GLIBCXX_STD_C::vector<_Tp, _Alloc>> - { }; - } // namespace __detail::__variant -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _STL_VECTOR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/string_view.tcc b/resources/sources/avr-libstdcpp/include/bits/string_view.tcc deleted file mode 100644 index 88d9371f1..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/string_view.tcc +++ /dev/null @@ -1,229 +0,0 @@ -// Components for manipulating non-owning sequences of characters -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/bits/string_view.tcc - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{string_view} - */ - -// -// N3762 basic_string_view library -// - -#ifndef _GLIBCXX_STRING_VIEW_TCC -#define _GLIBCXX_STRING_VIEW_TCC 1 - -#pragma GCC system_header - -#if __cplusplus >= 201703L - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - find(const _CharT* __str, size_type __pos, size_type __n) const noexcept - { - __glibcxx_requires_string_len(__str, __n); - - if (__n == 0) - return __pos <= this->_M_len ? __pos : npos; - - if (__n <= this->_M_len) - { - for (; __pos <= this->_M_len - __n; ++__pos) - if (traits_type::eq(this->_M_str[__pos], __str[0]) - && traits_type::compare(this->_M_str + __pos + 1, - __str + 1, __n - 1) == 0) - return __pos; - } - return npos; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - find(_CharT __c, size_type __pos) const noexcept - { - size_type __ret = npos; - if (__pos < this->_M_len) - { - const size_type __n = this->_M_len - __pos; - const _CharT* __p = traits_type::find(this->_M_str + __pos, __n, __c); - if (__p) - __ret = __p - this->_M_str; - } - return __ret; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept - { - __glibcxx_requires_string_len(__str, __n); - - if (__n <= this->_M_len) - { - __pos = std::min(size_type(this->_M_len - __n), __pos); - do - { - if (traits_type::compare(this->_M_str + __pos, __str, __n) == 0) - return __pos; - } - while (__pos-- > 0); - } - return npos; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - rfind(_CharT __c, size_type __pos) const noexcept - { - size_type __size = this->_M_len; - if (__size > 0) - { - if (--__size > __pos) - __size = __pos; - for (++__size; __size-- > 0; ) - if (traits_type::eq(this->_M_str[__size], __c)) - return __size; - } - return npos; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - find_first_of(const _CharT* __str, size_type __pos, - size_type __n) const noexcept - { - __glibcxx_requires_string_len(__str, __n); - for (; __n && __pos < this->_M_len; ++__pos) - { - const _CharT* __p = traits_type::find(__str, __n, - this->_M_str[__pos]); - if (__p) - return __pos; - } - return npos; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - find_last_of(const _CharT* __str, size_type __pos, - size_type __n) const noexcept - { - __glibcxx_requires_string_len(__str, __n); - size_type __size = this->size(); - if (__size && __n) - { - if (--__size > __pos) - __size = __pos; - do - { - if (traits_type::find(__str, __n, this->_M_str[__size])) - return __size; - } - while (__size-- != 0); - } - return npos; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - find_first_not_of(const _CharT* __str, size_type __pos, - size_type __n) const noexcept - { - __glibcxx_requires_string_len(__str, __n); - for (; __pos < this->_M_len; ++__pos) - if (!traits_type::find(__str, __n, this->_M_str[__pos])) - return __pos; - return npos; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - find_first_not_of(_CharT __c, size_type __pos) const noexcept - { - for (; __pos < this->_M_len; ++__pos) - if (!traits_type::eq(this->_M_str[__pos], __c)) - return __pos; - return npos; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - find_last_not_of(const _CharT* __str, size_type __pos, - size_type __n) const noexcept - { - __glibcxx_requires_string_len(__str, __n); - size_type __size = this->_M_len; - if (__size) - { - if (--__size > __pos) - __size = __pos; - do - { - if (!traits_type::find(__str, __n, this->_M_str[__size])) - return __size; - } - while (__size--); - } - return npos; - } - - template - constexpr typename basic_string_view<_CharT, _Traits>::size_type - basic_string_view<_CharT, _Traits>:: - find_last_not_of(_CharT __c, size_type __pos) const noexcept - { - size_type __size = this->_M_len; - if (__size) - { - if (--__size > __pos) - __size = __pos; - do - { - if (!traits_type::eq(this->_M_str[__size], __c)) - return __size; - } - while (__size--); - } - return npos; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // __cplusplus <= 201402L - -#endif // _GLIBCXX_STRING_VIEW_TCC diff --git a/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h b/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h deleted file mode 100644 index e3d7934e9..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h +++ /dev/null @@ -1,395 +0,0 @@ -// Class template uniform_int_distribution -*- C++ -*- - -// Copyright (C) 2009-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** - * @file bits/uniform_int_dist.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{random} - */ - -#ifndef _GLIBCXX_BITS_UNIFORM_INT_DIST_H -#define _GLIBCXX_BITS_UNIFORM_INT_DIST_H - -#include -#include -#if __cplusplus > 201703L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#ifdef __cpp_lib_concepts - /// Requirements for a uniform random bit generator. - template - concept uniform_random_bit_generator - = invocable<_Gen&> && unsigned_integral> - && requires - { - { _Gen::min() } -> same_as>; - { _Gen::max() } -> same_as>; - requires bool_constant<(_Gen::min() < _Gen::max())>::value; - }; -#endif - - namespace __detail - { - /* Determine whether number is a power of 2. */ - template - inline bool - _Power_of_2(_Tp __x) - { - return ((__x - 1) & __x) == 0; - } - } - - /** - * @brief Uniform discrete distribution for random numbers. - * A discrete random distribution on the range @f$[min, max]@f$ with equal - * probability throughout the range. - */ - template - class uniform_int_distribution - { - static_assert(std::is_integral<_IntType>::value, - "template argument must be an integral type"); - - public: - /** The type of the range of the distribution. */ - typedef _IntType result_type; - /** Parameter type. */ - struct param_type - { - typedef uniform_int_distribution<_IntType> distribution_type; - - param_type() : param_type(0) { } - - explicit - param_type(_IntType __a, - _IntType __b = numeric_limits<_IntType>::max()) - : _M_a(__a), _M_b(__b) - { - __glibcxx_assert(_M_a <= _M_b); - } - - result_type - a() const - { return _M_a; } - - result_type - b() const - { return _M_b; } - - friend bool - operator==(const param_type& __p1, const param_type& __p2) - { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } - - friend bool - operator!=(const param_type& __p1, const param_type& __p2) - { return !(__p1 == __p2); } - - private: - _IntType _M_a; - _IntType _M_b; - }; - - public: - /** - * @brief Constructs a uniform distribution object. - */ - uniform_int_distribution() : uniform_int_distribution(0) { } - - /** - * @brief Constructs a uniform distribution object. - */ - explicit - uniform_int_distribution(_IntType __a, - _IntType __b = numeric_limits<_IntType>::max()) - : _M_param(__a, __b) - { } - - explicit - uniform_int_distribution(const param_type& __p) - : _M_param(__p) - { } - - /** - * @brief Resets the distribution state. - * - * Does nothing for the uniform integer distribution. - */ - void - reset() { } - - result_type - a() const - { return _M_param.a(); } - - result_type - b() const - { return _M_param.b(); } - - /** - * @brief Returns the parameter set of the distribution. - */ - param_type - param() const - { return _M_param; } - - /** - * @brief Sets the parameter set of the distribution. - * @param __param The new parameter set of the distribution. - */ - void - param(const param_type& __param) - { _M_param = __param; } - - /** - * @brief Returns the inclusive lower bound of the distribution range. - */ - result_type - min() const - { return this->a(); } - - /** - * @brief Returns the inclusive upper bound of the distribution range. - */ - result_type - max() const - { return this->b(); } - - /** - * @brief Generating functions. - */ - template - result_type - operator()(_UniformRandomNumberGenerator& __urng) - { return this->operator()(__urng, _M_param); } - - template - result_type - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __p); - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng) - { this->__generate(__f, __t, __urng, _M_param); } - - template - void - __generate(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - template - void - __generate(result_type* __f, result_type* __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p) - { this->__generate_impl(__f, __t, __urng, __p); } - - /** - * @brief Return true if two uniform integer distributions have - * the same parameters. - */ - friend bool - operator==(const uniform_int_distribution& __d1, - const uniform_int_distribution& __d2) - { return __d1._M_param == __d2._M_param; } - - private: - template - void - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __p); - - param_type _M_param; - }; - - template - template - typename uniform_int_distribution<_IntType>::result_type - uniform_int_distribution<_IntType>:: - operator()(_UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - typedef typename _UniformRandomNumberGenerator::result_type - _Gresult_type; - typedef typename std::make_unsigned::type __utype; - typedef typename std::common_type<_Gresult_type, __utype>::type - __uctype; - - const __uctype __urngmin = __urng.min(); - const __uctype __urngmax = __urng.max(); - const __uctype __urngrange = __urngmax - __urngmin; - const __uctype __urange - = __uctype(__param.b()) - __uctype(__param.a()); - - __uctype __ret; - - if (__urngrange > __urange) - { - // downscaling - const __uctype __uerange = __urange + 1; // __urange can be zero - const __uctype __scaling = __urngrange / __uerange; - const __uctype __past = __uerange * __scaling; - do - __ret = __uctype(__urng()) - __urngmin; - while (__ret >= __past); - __ret /= __scaling; - } - else if (__urngrange < __urange) - { - // upscaling - /* - Note that every value in [0, urange] - can be written uniquely as - - (urngrange + 1) * high + low - - where - - high in [0, urange / (urngrange + 1)] - - and - - low in [0, urngrange]. - */ - __uctype __tmp; // wraparound control - do - { - const __uctype __uerngrange = __urngrange + 1; - __tmp = (__uerngrange * operator() - (__urng, param_type(0, __urange / __uerngrange))); - __ret = __tmp + (__uctype(__urng()) - __urngmin); - } - while (__ret > __urange || __ret < __tmp); - } - else - __ret = __uctype(__urng()) - __urngmin; - - return __ret + __param.a(); - } - - - template - template - void - uniform_int_distribution<_IntType>:: - __generate_impl(_ForwardIterator __f, _ForwardIterator __t, - _UniformRandomNumberGenerator& __urng, - const param_type& __param) - { - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - typedef typename _UniformRandomNumberGenerator::result_type - _Gresult_type; - typedef typename std::make_unsigned::type __utype; - typedef typename std::common_type<_Gresult_type, __utype>::type - __uctype; - - const __uctype __urngmin = __urng.min(); - const __uctype __urngmax = __urng.max(); - const __uctype __urngrange = __urngmax - __urngmin; - const __uctype __urange - = __uctype(__param.b()) - __uctype(__param.a()); - - __uctype __ret; - - if (__urngrange > __urange) - { - if (__detail::_Power_of_2(__urngrange + 1) - && __detail::_Power_of_2(__urange + 1)) - { - while (__f != __t) - { - __ret = __uctype(__urng()) - __urngmin; - *__f++ = (__ret & __urange) + __param.a(); - } - } - else - { - // downscaling - const __uctype __uerange = __urange + 1; // __urange can be zero - const __uctype __scaling = __urngrange / __uerange; - const __uctype __past = __uerange * __scaling; - while (__f != __t) - { - do - __ret = __uctype(__urng()) - __urngmin; - while (__ret >= __past); - *__f++ = __ret / __scaling + __param.a(); - } - } - } - else if (__urngrange < __urange) - { - // upscaling - /* - Note that every value in [0, urange] - can be written uniquely as - - (urngrange + 1) * high + low - - where - - high in [0, urange / (urngrange + 1)] - - and - - low in [0, urngrange]. - */ - __uctype __tmp; // wraparound control - while (__f != __t) - { - do - { - const __uctype __uerngrange = __urngrange + 1; - __tmp = (__uerngrange * operator() - (__urng, param_type(0, __urange / __uerngrange))); - __ret = __tmp + (__uctype(__urng()) - __urngmin); - } - while (__ret > __urange || __ret < __tmp); - *__f++ = __ret; - } - } - else - while (__f != __t) - *__f++ = __uctype(__urng()) - __urngmin + __param.a(); - } - - // operator!= and operator<< and operator>> are defined in - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/unique_lock.h b/resources/sources/avr-libstdcpp/include/bits/unique_lock.h deleted file mode 100644 index 82eef44d6..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/unique_lock.h +++ /dev/null @@ -1,243 +0,0 @@ -// std::unique_lock implementation -*- C++ -*- - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/unique_lock.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{mutex} - */ - -#ifndef _GLIBCXX_UNIQUE_LOCK_H -#define _GLIBCXX_UNIQUE_LOCK_H 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include // for std::swap - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** @brief A movable scoped lock type. - * - * A unique_lock controls mutex ownership within a scope. Ownership of the - * mutex can be delayed until after construction and can be transferred - * to another unique_lock by move construction or move assignment. If a - * mutex lock is owned when the destructor runs ownership will be released. - * - * @ingroup mutexes - */ - template - class unique_lock - { - public: - typedef _Mutex mutex_type; - - unique_lock() noexcept - : _M_device(0), _M_owns(false) - { } - - explicit unique_lock(mutex_type& __m) - : _M_device(std::__addressof(__m)), _M_owns(false) - { - lock(); - _M_owns = true; - } - - unique_lock(mutex_type& __m, defer_lock_t) noexcept - : _M_device(std::__addressof(__m)), _M_owns(false) - { } - - unique_lock(mutex_type& __m, try_to_lock_t) - : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock()) - { } - - unique_lock(mutex_type& __m, adopt_lock_t) noexcept - : _M_device(std::__addressof(__m)), _M_owns(true) - { - // XXX calling thread owns mutex - } - - template - unique_lock(mutex_type& __m, - const chrono::time_point<_Clock, _Duration>& __atime) - : _M_device(std::__addressof(__m)), - _M_owns(_M_device->try_lock_until(__atime)) - { } - - template - unique_lock(mutex_type& __m, - const chrono::duration<_Rep, _Period>& __rtime) - : _M_device(std::__addressof(__m)), - _M_owns(_M_device->try_lock_for(__rtime)) - { } - - ~unique_lock() - { - if (_M_owns) - unlock(); - } - - unique_lock(const unique_lock&) = delete; - unique_lock& operator=(const unique_lock&) = delete; - - unique_lock(unique_lock&& __u) noexcept - : _M_device(__u._M_device), _M_owns(__u._M_owns) - { - __u._M_device = 0; - __u._M_owns = false; - } - - unique_lock& operator=(unique_lock&& __u) noexcept - { - if(_M_owns) - unlock(); - - unique_lock(std::move(__u)).swap(*this); - - __u._M_device = 0; - __u._M_owns = false; - - return *this; - } - - void - lock() - { - if (!_M_device) - __throw_system_error(int(errc::operation_not_permitted)); - else if (_M_owns) - __throw_system_error(int(errc::resource_deadlock_would_occur)); - else - { - _M_device->lock(); - _M_owns = true; - } - } - - bool - try_lock() - { - if (!_M_device) - __throw_system_error(int(errc::operation_not_permitted)); - else if (_M_owns) - __throw_system_error(int(errc::resource_deadlock_would_occur)); - else - { - _M_owns = _M_device->try_lock(); - return _M_owns; - } - } - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { - if (!_M_device) - __throw_system_error(int(errc::operation_not_permitted)); - else if (_M_owns) - __throw_system_error(int(errc::resource_deadlock_would_occur)); - else - { - _M_owns = _M_device->try_lock_until(__atime); - return _M_owns; - } - } - - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { - if (!_M_device) - __throw_system_error(int(errc::operation_not_permitted)); - else if (_M_owns) - __throw_system_error(int(errc::resource_deadlock_would_occur)); - else - { - _M_owns = _M_device->try_lock_for(__rtime); - return _M_owns; - } - } - - void - unlock() - { - if (!_M_owns) - __throw_system_error(int(errc::operation_not_permitted)); - else if (_M_device) - { - _M_device->unlock(); - _M_owns = false; - } - } - - void - swap(unique_lock& __u) noexcept - { - std::swap(_M_device, __u._M_device); - std::swap(_M_owns, __u._M_owns); - } - - mutex_type* - release() noexcept - { - mutex_type* __ret = _M_device; - _M_device = 0; - _M_owns = false; - return __ret; - } - - bool - owns_lock() const noexcept - { return _M_owns; } - - explicit operator bool() const noexcept - { return owns_lock(); } - - mutex_type* - mutex() const noexcept - { return _M_device; } - - private: - mutex_type* _M_device; - bool _M_owns; - }; - - /// Swap overload for unique_lock objects. - /// @relates unique_lock - template - inline void - swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept - { __x.swap(__y); } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 -#endif // _GLIBCXX_UNIQUE_LOCK_H diff --git a/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h b/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h deleted file mode 100644 index 0f100c593..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h +++ /dev/null @@ -1,995 +0,0 @@ -// unique_ptr implementation -*- C++ -*- - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/unique_ptr.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{memory} - */ - -#ifndef _UNIQUE_PTR_H -#define _UNIQUE_PTR_H 1 - -#include -#include -#include -#include -#include -#include -#include -#if __cplusplus > 201703L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup pointer_abstractions - * @{ - */ - -#if _GLIBCXX_USE_DEPRECATED -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - template class auto_ptr; -#pragma GCC diagnostic pop -#endif - - /// Primary template of default_delete, used by unique_ptr for single objects - template - struct default_delete - { - /// Default constructor - constexpr default_delete() noexcept = default; - - /** @brief Converting constructor. - * - * Allows conversion from a deleter for objects of another type, `_Up`, - * only if `_Up*` is convertible to `_Tp*`. - */ - template>> - default_delete(const default_delete<_Up>&) noexcept { } - - /// Calls `delete __ptr` - void - operator()(_Tp* __ptr) const - { - static_assert(!is_void<_Tp>::value, - "can't delete pointer to incomplete type"); - static_assert(sizeof(_Tp)>0, - "can't delete pointer to incomplete type"); - delete __ptr; - } - }; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 740 - omit specialization for array objects with a compile time length - - /// Specialization of default_delete for arrays, used by `unique_ptr` - template - struct default_delete<_Tp[]> - { - public: - /// Default constructor - constexpr default_delete() noexcept = default; - - /** @brief Converting constructor. - * - * Allows conversion from a deleter for arrays of another type, such as - * a const-qualified version of `_Tp`. - * - * Conversions from types derived from `_Tp` are not allowed because - * it is undefined to `delete[]` an array of derived types through a - * pointer to the base type. - */ - template>> - default_delete(const default_delete<_Up[]>&) noexcept { } - - /// Calls `delete[] __ptr` - template - typename enable_if::value>::type - operator()(_Up* __ptr) const - { - static_assert(sizeof(_Tp)>0, - "can't delete pointer to incomplete type"); - delete [] __ptr; - } - }; - - /// @cond undocumented - - // Manages the pointer and deleter of a unique_ptr - template - class __uniq_ptr_impl - { - template - struct _Ptr - { - using type = _Up*; - }; - - template - struct - _Ptr<_Up, _Ep, __void_t::type::pointer>> - { - using type = typename remove_reference<_Ep>::type::pointer; - }; - - public: - using _DeleterConstraint = enable_if< - __and_<__not_>, - is_default_constructible<_Dp>>::value>; - - using pointer = typename _Ptr<_Tp, _Dp>::type; - - static_assert( !is_rvalue_reference<_Dp>::value, - "unique_ptr's deleter type must be a function object type" - " or an lvalue reference type" ); - - __uniq_ptr_impl() = default; - __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } - - template - __uniq_ptr_impl(pointer __p, _Del&& __d) - : _M_t(__p, std::forward<_Del>(__d)) { } - - __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept - : _M_t(std::move(__u._M_t)) - { __u._M_ptr() = nullptr; } - - __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept - { - reset(__u.release()); - _M_deleter() = std::forward<_Dp>(__u._M_deleter()); - return *this; - } - - pointer& _M_ptr() { return std::get<0>(_M_t); } - pointer _M_ptr() const { return std::get<0>(_M_t); } - _Dp& _M_deleter() { return std::get<1>(_M_t); } - const _Dp& _M_deleter() const { return std::get<1>(_M_t); } - - void reset(pointer __p) noexcept - { - const pointer __old_p = _M_ptr(); - _M_ptr() = __p; - if (__old_p) - _M_deleter()(__old_p); - } - - pointer release() noexcept - { - pointer __p = _M_ptr(); - _M_ptr() = nullptr; - return __p; - } - - void - swap(__uniq_ptr_impl& __rhs) noexcept - { - using std::swap; - swap(this->_M_ptr(), __rhs._M_ptr()); - swap(this->_M_deleter(), __rhs._M_deleter()); - } - - private: - tuple _M_t; - }; - - // Defines move construction + assignment as either defaulted or deleted. - template ::value, - bool = is_move_assignable<_Dp>::value> - struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp> - { - using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; - __uniq_ptr_data(__uniq_ptr_data&&) = default; - __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; - }; - - template - struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp> - { - using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; - __uniq_ptr_data(__uniq_ptr_data&&) = default; - __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; - }; - - template - struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp> - { - using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; - __uniq_ptr_data(__uniq_ptr_data&&) = delete; - __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; - }; - - template - struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp> - { - using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; - __uniq_ptr_data(__uniq_ptr_data&&) = delete; - __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; - }; - /// @endcond - - /// 20.7.1.2 unique_ptr for single objects. - template > - class unique_ptr - { - template - using _DeleterConstraint = - typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; - - __uniq_ptr_data<_Tp, _Dp> _M_t; - - public: - using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; - using element_type = _Tp; - using deleter_type = _Dp; - - private: - // helper template for detecting a safe conversion from another - // unique_ptr - template - using __safe_conversion_up = __and_< - is_convertible::pointer, pointer>, - __not_> - >; - - public: - // Constructors. - - /// Default constructor, creates a unique_ptr that owns nothing. - template> - constexpr unique_ptr() noexcept - : _M_t() - { } - - /** Takes ownership of a pointer. - * - * @param __p A pointer to an object of @c element_type - * - * The deleter will be value-initialized. - */ - template> - explicit - unique_ptr(pointer __p) noexcept - : _M_t(__p) - { } - - /** Takes ownership of a pointer. - * - * @param __p A pointer to an object of @c element_type - * @param __d A reference to a deleter. - * - * The deleter will be initialized with @p __d - */ - template>> - unique_ptr(pointer __p, const deleter_type& __d) noexcept - : _M_t(__p, __d) { } - - /** Takes ownership of a pointer. - * - * @param __p A pointer to an object of @c element_type - * @param __d An rvalue reference to a (non-reference) deleter. - * - * The deleter will be initialized with @p std::move(__d) - */ - template>> - unique_ptr(pointer __p, - __enable_if_t::value, - _Del&&> __d) noexcept - : _M_t(__p, std::move(__d)) - { } - - template::type> - unique_ptr(pointer, - __enable_if_t::value, - _DelUnref&&>) = delete; - - /// Creates a unique_ptr that owns nothing. - template> - constexpr unique_ptr(nullptr_t) noexcept - : _M_t() - { } - - // Move constructors. - - /// Move constructor. - unique_ptr(unique_ptr&&) = default; - - /** @brief Converting constructor from another type - * - * Requires that the pointer owned by @p __u is convertible to the - * type of pointer owned by this object, @p __u does not own an array, - * and @p __u has a compatible deleter type. - */ - template, - typename conditional::value, - is_same<_Ep, _Dp>, - is_convertible<_Ep, _Dp>>::type>> - unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept - : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) - { } - -#if _GLIBCXX_USE_DEPRECATED -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" - /// Converting constructor from @c auto_ptr - template, is_same<_Dp, default_delete<_Tp>>>> - unique_ptr(auto_ptr<_Up>&& __u) noexcept; -#pragma GCC diagnostic pop -#endif - - /// Destructor, invokes the deleter if the stored pointer is not null. - ~unique_ptr() noexcept - { - static_assert(__is_invocable::value, - "unique_ptr's deleter must be invocable with a pointer"); - auto& __ptr = _M_t._M_ptr(); - if (__ptr != nullptr) - get_deleter()(std::move(__ptr)); - __ptr = pointer(); - } - - // Assignment. - - /** @brief Move assignment operator. - * - * Invokes the deleter if this object owns a pointer. - */ - unique_ptr& operator=(unique_ptr&&) = default; - - /** @brief Assignment from another type. - * - * @param __u The object to transfer ownership from, which owns a - * convertible pointer to a non-array object. - * - * Invokes the deleter if this object owns a pointer. - */ - template - typename enable_if< __and_< - __safe_conversion_up<_Up, _Ep>, - is_assignable - >::value, - unique_ptr&>::type - operator=(unique_ptr<_Up, _Ep>&& __u) noexcept - { - reset(__u.release()); - get_deleter() = std::forward<_Ep>(__u.get_deleter()); - return *this; - } - - /// Reset the %unique_ptr to empty, invoking the deleter if necessary. - unique_ptr& - operator=(nullptr_t) noexcept - { - reset(); - return *this; - } - - // Observers. - - /// Dereference the stored pointer. - typename add_lvalue_reference::type - operator*() const - { - __glibcxx_assert(get() != pointer()); - return *get(); - } - - /// Return the stored pointer. - pointer - operator->() const noexcept - { - _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); - return get(); - } - - /// Return the stored pointer. - pointer - get() const noexcept - { return _M_t._M_ptr(); } - - /// Return a reference to the stored deleter. - deleter_type& - get_deleter() noexcept - { return _M_t._M_deleter(); } - - /// Return a reference to the stored deleter. - const deleter_type& - get_deleter() const noexcept - { return _M_t._M_deleter(); } - - /// Return @c true if the stored pointer is not null. - explicit operator bool() const noexcept - { return get() == pointer() ? false : true; } - - // Modifiers. - - /// Release ownership of any stored pointer. - pointer - release() noexcept - { return _M_t.release(); } - - /** @brief Replace the stored pointer. - * - * @param __p The new pointer to store. - * - * The deleter will be invoked if a pointer is already owned. - */ - void - reset(pointer __p = pointer()) noexcept - { - static_assert(__is_invocable::value, - "unique_ptr's deleter must be invocable with a pointer"); - _M_t.reset(std::move(__p)); - } - - /// Exchange the pointer and deleter with another object. - void - swap(unique_ptr& __u) noexcept - { - static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); - _M_t.swap(__u._M_t); - } - - // Disable copy from lvalue. - unique_ptr(const unique_ptr&) = delete; - unique_ptr& operator=(const unique_ptr&) = delete; - }; - - /// 20.7.1.3 unique_ptr for array objects with a runtime length - // [unique.ptr.runtime] - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 740 - omit specialization for array objects with a compile time length - template - class unique_ptr<_Tp[], _Dp> - { - template - using _DeleterConstraint = - typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; - - __uniq_ptr_data<_Tp, _Dp> _M_t; - - template - using __remove_cv_t = typename remove_cv<_Up>::type; - - // like is_base_of<_Tp, _Up> but false if unqualified types are the same - template - using __is_derived_Tp - = __and_< is_base_of<_Tp, _Up>, - __not_, __remove_cv_t<_Up>>> >; - - public: - using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; - using element_type = _Tp; - using deleter_type = _Dp; - - // helper template for detecting a safe conversion from another - // unique_ptr - template, - typename _UP_pointer = typename _UPtr::pointer, - typename _UP_element_type = typename _UPtr::element_type> - using __safe_conversion_up = __and_< - is_array<_Up>, - is_same, - is_same<_UP_pointer, _UP_element_type*>, - is_convertible<_UP_element_type(*)[], element_type(*)[]> - >; - - // helper template for detecting a safe conversion from a raw pointer - template - using __safe_conversion_raw = __and_< - __or_<__or_, - is_same<_Up, nullptr_t>>, - __and_, - is_same, - is_convertible< - typename remove_pointer<_Up>::type(*)[], - element_type(*)[]> - > - > - >; - - // Constructors. - - /// Default constructor, creates a unique_ptr that owns nothing. - template> - constexpr unique_ptr() noexcept - : _M_t() - { } - - /** Takes ownership of a pointer. - * - * @param __p A pointer to an array of a type safely convertible - * to an array of @c element_type - * - * The deleter will be value-initialized. - */ - template, - typename = typename enable_if< - __safe_conversion_raw<_Up>::value, bool>::type> - explicit - unique_ptr(_Up __p) noexcept - : _M_t(__p) - { } - - /** Takes ownership of a pointer. - * - * @param __p A pointer to an array of a type safely convertible - * to an array of @c element_type - * @param __d A reference to a deleter. - * - * The deleter will be initialized with @p __d - */ - template, - is_copy_constructible<_Del>>> - unique_ptr(_Up __p, const deleter_type& __d) noexcept - : _M_t(__p, __d) { } - - /** Takes ownership of a pointer. - * - * @param __p A pointer to an array of a type safely convertible - * to an array of @c element_type - * @param __d A reference to a deleter. - * - * The deleter will be initialized with @p std::move(__d) - */ - template, - is_move_constructible<_Del>>> - unique_ptr(_Up __p, - __enable_if_t::value, - _Del&&> __d) noexcept - : _M_t(std::move(__p), std::move(__d)) - { } - - template::type, - typename = _Require<__safe_conversion_raw<_Up>>> - unique_ptr(_Up, - __enable_if_t::value, - _DelUnref&&>) = delete; - - /// Move constructor. - unique_ptr(unique_ptr&&) = default; - - /// Creates a unique_ptr that owns nothing. - template> - constexpr unique_ptr(nullptr_t) noexcept - : _M_t() - { } - - template, - typename conditional::value, - is_same<_Ep, _Dp>, - is_convertible<_Ep, _Dp>>::type>> - unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept - : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) - { } - - /// Destructor, invokes the deleter if the stored pointer is not null. - ~unique_ptr() - { - auto& __ptr = _M_t._M_ptr(); - if (__ptr != nullptr) - get_deleter()(__ptr); - __ptr = pointer(); - } - - // Assignment. - - /** @brief Move assignment operator. - * - * Invokes the deleter if this object owns a pointer. - */ - unique_ptr& - operator=(unique_ptr&&) = default; - - /** @brief Assignment from another type. - * - * @param __u The object to transfer ownership from, which owns a - * convertible pointer to an array object. - * - * Invokes the deleter if this object owns a pointer. - */ - template - typename - enable_if<__and_<__safe_conversion_up<_Up, _Ep>, - is_assignable - >::value, - unique_ptr&>::type - operator=(unique_ptr<_Up, _Ep>&& __u) noexcept - { - reset(__u.release()); - get_deleter() = std::forward<_Ep>(__u.get_deleter()); - return *this; - } - - /// Reset the %unique_ptr to empty, invoking the deleter if necessary. - unique_ptr& - operator=(nullptr_t) noexcept - { - reset(); - return *this; - } - - // Observers. - - /// Access an element of owned array. - typename std::add_lvalue_reference::type - operator[](size_t __i) const - { - __glibcxx_assert(get() != pointer()); - return get()[__i]; - } - - /// Return the stored pointer. - pointer - get() const noexcept - { return _M_t._M_ptr(); } - - /// Return a reference to the stored deleter. - deleter_type& - get_deleter() noexcept - { return _M_t._M_deleter(); } - - /// Return a reference to the stored deleter. - const deleter_type& - get_deleter() const noexcept - { return _M_t._M_deleter(); } - - /// Return @c true if the stored pointer is not null. - explicit operator bool() const noexcept - { return get() == pointer() ? false : true; } - - // Modifiers. - - /// Release ownership of any stored pointer. - pointer - release() noexcept - { return _M_t.release(); } - - /** @brief Replace the stored pointer. - * - * @param __p The new pointer to store. - * - * The deleter will be invoked if a pointer is already owned. - */ - template , - __and_, - is_pointer<_Up>, - is_convertible< - typename remove_pointer<_Up>::type(*)[], - element_type(*)[] - > - > - > - >> - void - reset(_Up __p) noexcept - { _M_t.reset(std::move(__p)); } - - void reset(nullptr_t = nullptr) noexcept - { reset(pointer()); } - - /// Exchange the pointer and deleter with another object. - void - swap(unique_ptr& __u) noexcept - { - static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); - _M_t.swap(__u._M_t); - } - - // Disable copy from lvalue. - unique_ptr(const unique_ptr&) = delete; - unique_ptr& operator=(const unique_ptr&) = delete; - }; - - /// @relates unique_ptr @{ - - /// Swap overload for unique_ptr - template - inline -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - // Constrained free swap overload, see p0185r1 - typename enable_if<__is_swappable<_Dp>::value>::type -#else - void -#endif - swap(unique_ptr<_Tp, _Dp>& __x, - unique_ptr<_Tp, _Dp>& __y) noexcept - { __x.swap(__y); } - -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - template - typename enable_if::value>::type - swap(unique_ptr<_Tp, _Dp>&, - unique_ptr<_Tp, _Dp>&) = delete; -#endif - - /// Equality operator for unique_ptr objects, compares the owned pointers - template - _GLIBCXX_NODISCARD inline bool - operator==(const unique_ptr<_Tp, _Dp>& __x, - const unique_ptr<_Up, _Ep>& __y) - { return __x.get() == __y.get(); } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept - { return !__x; } - -#ifndef __cpp_lib_three_way_comparison - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept - { return !__x; } - - /// Inequality operator for unique_ptr objects, compares the owned pointers - template - _GLIBCXX_NODISCARD inline bool - operator!=(const unique_ptr<_Tp, _Dp>& __x, - const unique_ptr<_Up, _Ep>& __y) - { return __x.get() != __y.get(); } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept - { return (bool)__x; } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept - { return (bool)__x; } -#endif // three way comparison - - /// Relational operator for unique_ptr objects, compares the owned pointers - template - _GLIBCXX_NODISCARD inline bool - operator<(const unique_ptr<_Tp, _Dp>& __x, - const unique_ptr<_Up, _Ep>& __y) - { - typedef typename - std::common_type::pointer, - typename unique_ptr<_Up, _Ep>::pointer>::type _CT; - return std::less<_CT>()(__x.get(), __y.get()); - } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) - { - return std::less::pointer>()(__x.get(), - nullptr); - } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) - { - return std::less::pointer>()(nullptr, - __x.get()); - } - - /// Relational operator for unique_ptr objects, compares the owned pointers - template - _GLIBCXX_NODISCARD inline bool - operator<=(const unique_ptr<_Tp, _Dp>& __x, - const unique_ptr<_Up, _Ep>& __y) - { return !(__y < __x); } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) - { return !(nullptr < __x); } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) - { return !(__x < nullptr); } - - /// Relational operator for unique_ptr objects, compares the owned pointers - template - _GLIBCXX_NODISCARD inline bool - operator>(const unique_ptr<_Tp, _Dp>& __x, - const unique_ptr<_Up, _Ep>& __y) - { return (__y < __x); } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) - { - return std::less::pointer>()(nullptr, - __x.get()); - } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) - { - return std::less::pointer>()(__x.get(), - nullptr); - } - - /// Relational operator for unique_ptr objects, compares the owned pointers - template - _GLIBCXX_NODISCARD inline bool - operator>=(const unique_ptr<_Tp, _Dp>& __x, - const unique_ptr<_Up, _Ep>& __y) - { return !(__x < __y); } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) - { return !(__x < nullptr); } - - /// unique_ptr comparison with nullptr - template - _GLIBCXX_NODISCARD inline bool - operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) - { return !(nullptr < __x); } - -#ifdef __cpp_lib_three_way_comparison - template - requires three_way_comparable_with::pointer, - typename unique_ptr<_Up, _Ep>::pointer> - inline - compare_three_way_result_t::pointer, - typename unique_ptr<_Up, _Ep>::pointer> - operator<=>(const unique_ptr<_Tp, _Dp>& __x, - const unique_ptr<_Up, _Ep>& __y) - { return compare_three_way()(__x.get(), __y.get()); } - - template - requires three_way_comparable::pointer> - inline - compare_three_way_result_t::pointer> - operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) - { - using pointer = typename unique_ptr<_Tp, _Dp>::pointer; - return compare_three_way()(__x.get(), static_cast(nullptr)); - } -#endif - // @} relates unique_ptr - - /// @cond undocumented - template::__enable_hash_call> - struct __uniq_ptr_hash -#if ! _GLIBCXX_INLINE_VERSION - : private __poison_hash<_Ptr> -#endif - { - size_t - operator()(const _Up& __u) const - noexcept(noexcept(std::declval>()(std::declval<_Ptr>()))) - { return hash<_Ptr>()(__u.get()); } - }; - - template - struct __uniq_ptr_hash<_Up, _Ptr, false> - : private __poison_hash<_Ptr> - { }; - /// @endcond - - /// std::hash specialization for unique_ptr. - template - struct hash> - : public __hash_base>, - public __uniq_ptr_hash> - { }; - -#if __cplusplus >= 201402L - /// @relates unique_ptr @{ -#define __cpp_lib_make_unique 201304 - - /// @cond undocumented - - template - struct _MakeUniq - { typedef unique_ptr<_Tp> __single_object; }; - - template - struct _MakeUniq<_Tp[]> - { typedef unique_ptr<_Tp[]> __array; }; - - template - struct _MakeUniq<_Tp[_Bound]> - { struct __invalid_type { }; }; - - /// @endcond - - /// std::make_unique for single objects - template - inline typename _MakeUniq<_Tp>::__single_object - make_unique(_Args&&... __args) - { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } - - /// std::make_unique for arrays of unknown bound - template - inline typename _MakeUniq<_Tp>::__array - make_unique(size_t __num) - { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } - - /// Disable std::make_unique for arrays of known bound - template - inline typename _MakeUniq<_Tp>::__invalid_type - make_unique(_Args&&...) = delete; - // @} relates unique_ptr -#endif // C++14 - - // @} group pointer_abstractions - -#if __cplusplus >= 201703L - namespace __detail::__variant - { - template struct _Never_valueless_alt; // see - - // Provide the strong exception-safety guarantee when emplacing a - // unique_ptr into a variant. - template - struct _Never_valueless_alt> - : std::true_type - { }; - } // namespace __detail::__variant -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _UNIQUE_PTR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/unordered_map.h b/resources/sources/avr-libstdcpp/include/bits/unordered_map.h deleted file mode 100644 index 0071d62e4..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/unordered_map.h +++ /dev/null @@ -1,2171 +0,0 @@ -// unordered_map implementation -*- C++ -*- - -// Copyright (C) 2010-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/unordered_map.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{unordered_map} - */ - -#ifndef _UNORDERED_MAP_H -#define _UNORDERED_MAP_H - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - /// Base types for unordered_map. - template - using __umap_traits = __detail::_Hashtable_traits<_Cache, false, true>; - - template, - typename _Pred = std::equal_to<_Key>, - typename _Alloc = std::allocator >, - typename _Tr = __umap_traits<__cache_default<_Key, _Hash>::value>> - using __umap_hashtable = _Hashtable<_Key, std::pair, - _Alloc, __detail::_Select1st, - _Pred, _Hash, - __detail::_Mod_range_hashing, - __detail::_Default_ranged_hash, - __detail::_Prime_rehash_policy, _Tr>; - - /// Base types for unordered_multimap. - template - using __ummap_traits = __detail::_Hashtable_traits<_Cache, false, false>; - - template, - typename _Pred = std::equal_to<_Key>, - typename _Alloc = std::allocator >, - typename _Tr = __ummap_traits<__cache_default<_Key, _Hash>::value>> - using __ummap_hashtable = _Hashtable<_Key, std::pair, - _Alloc, __detail::_Select1st, - _Pred, _Hash, - __detail::_Mod_range_hashing, - __detail::_Default_ranged_hash, - __detail::_Prime_rehash_policy, _Tr>; - - template - class unordered_multimap; - - /** - * @brief A standard container composed of unique keys (containing - * at most one of each key value) that associates values of another type - * with the keys. - * - * @ingroup unordered_associative_containers - * - * @tparam _Key Type of key objects. - * @tparam _Tp Type of mapped objects. - * @tparam _Hash Hashing function object type, defaults to hash<_Value>. - * @tparam _Pred Predicate function object type, defaults - * to equal_to<_Value>. - * @tparam _Alloc Allocator type, defaults to - * std::allocator>. - * - * Meets the requirements of a container, and - * unordered associative container - * - * The resulting value type of the container is std::pair. - * - * Base is _Hashtable, dispatched at compile time via template - * alias __umap_hashtable. - */ - template, - typename _Pred = equal_to<_Key>, - typename _Alloc = allocator>> - class unordered_map - { - typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable; - _Hashtable _M_h; - - public: - // typedefs: - //@{ - /// Public typedefs. - typedef typename _Hashtable::key_type key_type; - typedef typename _Hashtable::value_type value_type; - typedef typename _Hashtable::mapped_type mapped_type; - typedef typename _Hashtable::hasher hasher; - typedef typename _Hashtable::key_equal key_equal; - typedef typename _Hashtable::allocator_type allocator_type; - //@} - - //@{ - /// Iterator-related typedefs. - typedef typename _Hashtable::pointer pointer; - typedef typename _Hashtable::const_pointer const_pointer; - typedef typename _Hashtable::reference reference; - typedef typename _Hashtable::const_reference const_reference; - typedef typename _Hashtable::iterator iterator; - typedef typename _Hashtable::const_iterator const_iterator; - typedef typename _Hashtable::local_iterator local_iterator; - typedef typename _Hashtable::const_local_iterator const_local_iterator; - typedef typename _Hashtable::size_type size_type; - typedef typename _Hashtable::difference_type difference_type; - //@} - -#if __cplusplus > 201402L - using node_type = typename _Hashtable::node_type; - using insert_return_type = typename _Hashtable::insert_return_type; -#endif - - //construct/destroy/copy - - /// Default constructor. - unordered_map() = default; - - /** - * @brief Default constructor creates no elements. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - */ - explicit - unordered_map(size_type __n, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__n, __hf, __eql, __a) - { } - - /** - * @brief Builds an %unordered_map from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - * - * Create an %unordered_map consisting of copies of the elements from - * [__first,__last). This is linear in N (where N is - * distance(__first,__last)). - */ - template - unordered_map(_InputIterator __first, _InputIterator __last, - size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__first, __last, __n, __hf, __eql, __a) - { } - - /// Copy constructor. - unordered_map(const unordered_map&) = default; - - /// Move constructor. - unordered_map(unordered_map&&) = default; - - /** - * @brief Creates an %unordered_map with no elements. - * @param __a An allocator object. - */ - explicit - unordered_map(const allocator_type& __a) - : _M_h(__a) - { } - - /* - * @brief Copy constructor with allocator argument. - * @param __uset Input %unordered_map to copy. - * @param __a An allocator object. - */ - unordered_map(const unordered_map& __umap, - const allocator_type& __a) - : _M_h(__umap._M_h, __a) - { } - - /* - * @brief Move constructor with allocator argument. - * @param __uset Input %unordered_map to move. - * @param __a An allocator object. - */ - unordered_map(unordered_map&& __umap, - const allocator_type& __a) - : _M_h(std::move(__umap._M_h), __a) - { } - - /** - * @brief Builds an %unordered_map from an initializer_list. - * @param __l An initializer_list. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - * - * Create an %unordered_map consisting of copies of the elements in the - * list. This is linear in N (where N is @a __l.size()). - */ - unordered_map(initializer_list __l, - size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__l, __n, __hf, __eql, __a) - { } - - unordered_map(size_type __n, const allocator_type& __a) - : unordered_map(__n, hasher(), key_equal(), __a) - { } - - unordered_map(size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_map(__n, __hf, key_equal(), __a) - { } - - template - unordered_map(_InputIterator __first, _InputIterator __last, - size_type __n, - const allocator_type& __a) - : unordered_map(__first, __last, __n, hasher(), key_equal(), __a) - { } - - template - unordered_map(_InputIterator __first, _InputIterator __last, - size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_map(__first, __last, __n, __hf, key_equal(), __a) - { } - - unordered_map(initializer_list __l, - size_type __n, - const allocator_type& __a) - : unordered_map(__l, __n, hasher(), key_equal(), __a) - { } - - unordered_map(initializer_list __l, - size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_map(__l, __n, __hf, key_equal(), __a) - { } - - /// Copy assignment operator. - unordered_map& - operator=(const unordered_map&) = default; - - /// Move assignment operator. - unordered_map& - operator=(unordered_map&&) = default; - - /** - * @brief %Unordered_map list assignment operator. - * @param __l An initializer_list. - * - * This function fills an %unordered_map with copies of the elements in - * the initializer list @a __l. - * - * Note that the assignment completely changes the %unordered_map and - * that the resulting %unordered_map's size is the same as the number - * of elements assigned. - */ - unordered_map& - operator=(initializer_list __l) - { - _M_h = __l; - return *this; - } - - /// Returns the allocator object used by the %unordered_map. - allocator_type - get_allocator() const noexcept - { return _M_h.get_allocator(); } - - // size and capacity: - - /// Returns true if the %unordered_map is empty. - _GLIBCXX_NODISCARD bool - empty() const noexcept - { return _M_h.empty(); } - - /// Returns the size of the %unordered_map. - size_type - size() const noexcept - { return _M_h.size(); } - - /// Returns the maximum size of the %unordered_map. - size_type - max_size() const noexcept - { return _M_h.max_size(); } - - // iterators. - - /** - * Returns a read/write iterator that points to the first element in the - * %unordered_map. - */ - iterator - begin() noexcept - { return _M_h.begin(); } - - //@{ - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %unordered_map. - */ - const_iterator - begin() const noexcept - { return _M_h.begin(); } - - const_iterator - cbegin() const noexcept - { return _M_h.begin(); } - //@} - - /** - * Returns a read/write iterator that points one past the last element in - * the %unordered_map. - */ - iterator - end() noexcept - { return _M_h.end(); } - - //@{ - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %unordered_map. - */ - const_iterator - end() const noexcept - { return _M_h.end(); } - - const_iterator - cend() const noexcept - { return _M_h.end(); } - //@} - - // modifiers. - - /** - * @brief Attempts to build and insert a std::pair into the - * %unordered_map. - * - * @param __args Arguments used to generate a new pair instance (see - * std::piecewise_contruct for passing arguments to each - * part of the pair constructor). - * - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted pair, and the second is a bool that - * is true if the pair was actually inserted. - * - * This function attempts to build and insert a (key, value) %pair into - * the %unordered_map. - * An %unordered_map relies on unique keys and thus a %pair is only - * inserted if its first element (the key) is not already present in the - * %unordered_map. - * - * Insertion requires amortized constant time. - */ - template - std::pair - emplace(_Args&&... __args) - { return _M_h.emplace(std::forward<_Args>(__args)...); } - - /** - * @brief Attempts to build and insert a std::pair into the - * %unordered_map. - * - * @param __pos An iterator that serves as a hint as to where the pair - * should be inserted. - * @param __args Arguments used to generate a new pair instance (see - * std::piecewise_contruct for passing arguments to each - * part of the pair constructor). - * @return An iterator that points to the element with key of the - * std::pair built from @a __args (may or may not be that - * std::pair). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument emplace() - * does. - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires amortized constant time. - */ - template - iterator - emplace_hint(const_iterator __pos, _Args&&... __args) - { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } - -#if __cplusplus > 201402L - /// Extract a node. - node_type - extract(const_iterator __pos) - { - __glibcxx_assert(__pos != end()); - return _M_h.extract(__pos); - } - - /// Extract a node. - node_type - extract(const key_type& __key) - { return _M_h.extract(__key); } - - /// Re-insert an extracted node. - insert_return_type - insert(node_type&& __nh) - { return _M_h._M_reinsert_node(std::move(__nh)); } - - /// Re-insert an extracted node. - iterator - insert(const_iterator, node_type&& __nh) - { return _M_h._M_reinsert_node(std::move(__nh)).position; } - -#define __cpp_lib_unordered_map_try_emplace 201411 - /** - * @brief Attempts to build and insert a std::pair into the - * %unordered_map. - * - * @param __k Key to use for finding a possibly existing pair in - * the unordered_map. - * @param __args Arguments used to generate the .second for a - * new pair instance. - * - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted pair, and the second is a bool that - * is true if the pair was actually inserted. - * - * This function attempts to build and insert a (key, value) %pair into - * the %unordered_map. - * An %unordered_map relies on unique keys and thus a %pair is only - * inserted if its first element (the key) is not already present in the - * %unordered_map. - * If a %pair is not inserted, this function has no effect. - * - * Insertion requires amortized constant time. - */ - template - pair - try_emplace(const key_type& __k, _Args&&... __args) - { - iterator __i = find(__k); - if (__i == end()) - { - __i = emplace(std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Args>(__args)...)) - .first; - return {__i, true}; - } - return {__i, false}; - } - - // move-capable overload - template - pair - try_emplace(key_type&& __k, _Args&&... __args) - { - iterator __i = find(__k); - if (__i == end()) - { - __i = emplace(std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Args>(__args)...)) - .first; - return {__i, true}; - } - return {__i, false}; - } - - /** - * @brief Attempts to build and insert a std::pair into the - * %unordered_map. - * - * @param __hint An iterator that serves as a hint as to where the pair - * should be inserted. - * @param __k Key to use for finding a possibly existing pair in - * the unordered_map. - * @param __args Arguments used to generate the .second for a - * new pair instance. - * @return An iterator that points to the element with key of the - * std::pair built from @a __args (may or may not be that - * std::pair). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument emplace() - * does. However, if insertion did not take place, - * this function has no effect. - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires amortized constant time. - */ - template - iterator - try_emplace(const_iterator __hint, const key_type& __k, - _Args&&... __args) - { - iterator __i = find(__k); - if (__i == end()) - __i = emplace_hint(__hint, std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - return __i; - } - - // move-capable overload - template - iterator - try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) - { - iterator __i = find(__k); - if (__i == end()) - __i = emplace_hint(__hint, std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Args>(__args)...)); - return __i; - } -#endif // C++17 - - //@{ - /** - * @brief Attempts to insert a std::pair into the %unordered_map. - - * @param __x Pair to be inserted (see std::make_pair for easy - * creation of pairs). - * - * @return A pair, of which the first element is an iterator that - * points to the possibly inserted pair, and the second is - * a bool that is true if the pair was actually inserted. - * - * This function attempts to insert a (key, value) %pair into the - * %unordered_map. An %unordered_map relies on unique keys and thus a - * %pair is only inserted if its first element (the key) is not already - * present in the %unordered_map. - * - * Insertion requires amortized constant time. - */ - std::pair - insert(const value_type& __x) - { return _M_h.insert(__x); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2354. Unnecessary copying when inserting into maps with braced-init - std::pair - insert(value_type&& __x) - { return _M_h.insert(std::move(__x)); } - - template - __enable_if_t::value, - pair> - insert(_Pair&& __x) - { return _M_h.emplace(std::forward<_Pair>(__x)); } - //@} - - //@{ - /** - * @brief Attempts to insert a std::pair into the %unordered_map. - * @param __hint An iterator that serves as a hint as to where the - * pair should be inserted. - * @param __x Pair to be inserted (see std::make_pair for easy creation - * of pairs). - * @return An iterator that points to the element with key of - * @a __x (may or may not be the %pair passed in). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument insert() - * does. Note that the first parameter is only a hint and can - * potentially improve the performance of the insertion process. A bad - * hint would cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires amortized constant time. - */ - iterator - insert(const_iterator __hint, const value_type& __x) - { return _M_h.insert(__hint, __x); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2354. Unnecessary copying when inserting into maps with braced-init - iterator - insert(const_iterator __hint, value_type&& __x) - { return _M_h.insert(__hint, std::move(__x)); } - - template - __enable_if_t::value, iterator> - insert(const_iterator __hint, _Pair&& __x) - { return _M_h.emplace_hint(__hint, std::forward<_Pair>(__x)); } - //@} - - /** - * @brief A template function that attempts to insert a range of - * elements. - * @param __first Iterator pointing to the start of the range to be - * inserted. - * @param __last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) - { _M_h.insert(__first, __last); } - - /** - * @brief Attempts to insert a list of elements into the %unordered_map. - * @param __l A std::initializer_list of elements - * to be inserted. - * - * Complexity similar to that of the range constructor. - */ - void - insert(initializer_list __l) - { _M_h.insert(__l); } - - -#if __cplusplus > 201402L - /** - * @brief Attempts to insert a std::pair into the %unordered_map. - * @param __k Key to use for finding a possibly existing pair in - * the map. - * @param __obj Argument used to generate the .second for a pair - * instance. - * - * @return A pair, of which the first element is an iterator that - * points to the possibly inserted pair, and the second is - * a bool that is true if the pair was actually inserted. - * - * This function attempts to insert a (key, value) %pair into the - * %unordered_map. An %unordered_map relies on unique keys and thus a - * %pair is only inserted if its first element (the key) is not already - * present in the %unordered_map. - * If the %pair was already in the %unordered_map, the .second of - * the %pair is assigned from __obj. - * - * Insertion requires amortized constant time. - */ - template - pair - insert_or_assign(const key_type& __k, _Obj&& __obj) - { - iterator __i = find(__k); - if (__i == end()) - { - __i = emplace(std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple(std::forward<_Obj>(__obj))) - .first; - return {__i, true}; - } - (*__i).second = std::forward<_Obj>(__obj); - return {__i, false}; - } - - // move-capable overload - template - pair - insert_or_assign(key_type&& __k, _Obj&& __obj) - { - iterator __i = find(__k); - if (__i == end()) - { - __i = emplace(std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple(std::forward<_Obj>(__obj))) - .first; - return {__i, true}; - } - (*__i).second = std::forward<_Obj>(__obj); - return {__i, false}; - } - - /** - * @brief Attempts to insert a std::pair into the %unordered_map. - * @param __hint An iterator that serves as a hint as to where the - * pair should be inserted. - * @param __k Key to use for finding a possibly existing pair in - * the unordered_map. - * @param __obj Argument used to generate the .second for a pair - * instance. - * @return An iterator that points to the element with key of - * @a __x (may or may not be the %pair passed in). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument insert() - * does. - * If the %pair was already in the %unordered map, the .second of - * the %pair is assigned from __obj. - * Note that the first parameter is only a hint and can - * potentially improve the performance of the insertion process. A bad - * hint would cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires amortized constant time. - */ - template - iterator - insert_or_assign(const_iterator __hint, const key_type& __k, - _Obj&& __obj) - { - iterator __i = find(__k); - if (__i == end()) - { - return emplace_hint(__hint, std::piecewise_construct, - std::forward_as_tuple(__k), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - } - (*__i).second = std::forward<_Obj>(__obj); - return __i; - } - - // move-capable overload - template - iterator - insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) - { - iterator __i = find(__k); - if (__i == end()) - { - return emplace_hint(__hint, std::piecewise_construct, - std::forward_as_tuple(std::move(__k)), - std::forward_as_tuple( - std::forward<_Obj>(__obj))); - } - (*__i).second = std::forward<_Obj>(__obj); - return __i; - } -#endif - - //@{ - /** - * @brief Erases an element from an %unordered_map. - * @param __position An iterator pointing to the element to be erased. - * @return An iterator pointing to the element immediately following - * @a __position prior to the element being erased. If no such - * element exists, end() is returned. - * - * This function erases an element, pointed to by the given iterator, - * from an %unordered_map. - * Note that this function only erases the element, and that if the - * element is itself a pointer, the pointed-to memory is not touched in - * any way. Managing the pointer is the user's responsibility. - */ - iterator - erase(const_iterator __position) - { return _M_h.erase(__position); } - - // LWG 2059. - iterator - erase(iterator __position) - { return _M_h.erase(__position); } - //@} - - /** - * @brief Erases elements according to the provided key. - * @param __x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all the elements located by the given key from - * an %unordered_map. For an %unordered_map the result of this function - * can only be 0 (not present) or 1 (present). - * Note that this function only erases the element, and that if the - * element is itself a pointer, the pointed-to memory is not touched in - * any way. Managing the pointer is the user's responsibility. - */ - size_type - erase(const key_type& __x) - { return _M_h.erase(__x); } - - /** - * @brief Erases a [__first,__last) range of elements from an - * %unordered_map. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * @return The iterator @a __last. - * - * This function erases a sequence of elements from an %unordered_map. - * Note that this function only erases the elements, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - iterator - erase(const_iterator __first, const_iterator __last) - { return _M_h.erase(__first, __last); } - - /** - * Erases all elements in an %unordered_map. - * Note that this function only erases the elements, and that if the - * elements themselves are pointers, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - void - clear() noexcept - { _M_h.clear(); } - - /** - * @brief Swaps data with another %unordered_map. - * @param __x An %unordered_map of the same element and allocator - * types. - * - * This exchanges the elements between two %unordered_map in constant - * time. - * Note that the global std::swap() function is specialized such that - * std::swap(m1,m2) will feed to this function. - */ - void - swap(unordered_map& __x) - noexcept( noexcept(_M_h.swap(__x._M_h)) ) - { _M_h.swap(__x._M_h); } - -#if __cplusplus > 201402L - template - friend class std::_Hash_merge_helper; - - template - void - merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) - { - using _Merge_helper = _Hash_merge_helper; - _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); - } - - template - void - merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) - { merge(__source); } - - template - void - merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) - { - using _Merge_helper = _Hash_merge_helper; - _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); - } - - template - void - merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) - { merge(__source); } -#endif // C++17 - - // observers. - - /// Returns the hash functor object with which the %unordered_map was - /// constructed. - hasher - hash_function() const - { return _M_h.hash_function(); } - - /// Returns the key comparison object with which the %unordered_map was - /// constructed. - key_equal - key_eq() const - { return _M_h.key_eq(); } - - // lookup. - - //@{ - /** - * @brief Tries to locate an element in an %unordered_map. - * @param __x Key to be located. - * @return Iterator pointing to sought-after element, or end() if not - * found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after element. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) - { return _M_h.find(__x); } - - const_iterator - find(const key_type& __x) const - { return _M_h.find(__x); } - //@} - - /** - * @brief Finds the number of elements. - * @param __x Key to count. - * @return Number of elements with specified key. - * - * This function only makes sense for %unordered_multimap; for - * %unordered_map the result will either be 0 (not present) or 1 - * (present). - */ - size_type - count(const key_type& __x) const - { return _M_h.count(__x); } - -#if __cplusplus > 201703L - /** - * @brief Finds whether an element with the given key exists. - * @param __x Key of elements to be located. - * @return True if there is any element with the specified key. - */ - bool - contains(const key_type& __x) const - { return _M_h.find(__x) != _M_h.end(); } -#endif - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - * - * This function probably only makes sense for %unordered_multimap. - */ - std::pair - equal_range(const key_type& __x) - { return _M_h.equal_range(__x); } - - std::pair - equal_range(const key_type& __x) const - { return _M_h.equal_range(__x); } - //@} - - //@{ - /** - * @brief Subscript ( @c [] ) access to %unordered_map data. - * @param __k The key for which data should be retrieved. - * @return A reference to the data of the (key,data) %pair. - * - * Allows for easy lookup with the subscript ( @c [] )operator. Returns - * data associated with the key specified in subscript. If the key does - * not exist, a pair with that key is created using default values, which - * is then returned. - * - * Lookup requires constant time. - */ - mapped_type& - operator[](const key_type& __k) - { return _M_h[__k]; } - - mapped_type& - operator[](key_type&& __k) - { return _M_h[std::move(__k)]; } - //@} - - //@{ - /** - * @brief Access to %unordered_map data. - * @param __k The key for which data should be retrieved. - * @return A reference to the data whose key is equal to @a __k, if - * such a data is present in the %unordered_map. - * @throw std::out_of_range If no such data is present. - */ - mapped_type& - at(const key_type& __k) - { return _M_h.at(__k); } - - const mapped_type& - at(const key_type& __k) const - { return _M_h.at(__k); } - //@} - - // bucket interface. - - /// Returns the number of buckets of the %unordered_map. - size_type - bucket_count() const noexcept - { return _M_h.bucket_count(); } - - /// Returns the maximum number of buckets of the %unordered_map. - size_type - max_bucket_count() const noexcept - { return _M_h.max_bucket_count(); } - - /* - * @brief Returns the number of elements in a given bucket. - * @param __n A bucket index. - * @return The number of elements in the bucket. - */ - size_type - bucket_size(size_type __n) const - { return _M_h.bucket_size(__n); } - - /* - * @brief Returns the bucket index of a given element. - * @param __key A key instance. - * @return The key bucket index. - */ - size_type - bucket(const key_type& __key) const - { return _M_h.bucket(__key); } - - /** - * @brief Returns a read/write iterator pointing to the first bucket - * element. - * @param __n The bucket index. - * @return A read/write local iterator. - */ - local_iterator - begin(size_type __n) - { return _M_h.begin(__n); } - - //@{ - /** - * @brief Returns a read-only (constant) iterator pointing to the first - * bucket element. - * @param __n The bucket index. - * @return A read-only local iterator. - */ - const_local_iterator - begin(size_type __n) const - { return _M_h.begin(__n); } - - const_local_iterator - cbegin(size_type __n) const - { return _M_h.cbegin(__n); } - //@} - - /** - * @brief Returns a read/write iterator pointing to one past the last - * bucket elements. - * @param __n The bucket index. - * @return A read/write local iterator. - */ - local_iterator - end(size_type __n) - { return _M_h.end(__n); } - - //@{ - /** - * @brief Returns a read-only (constant) iterator pointing to one past - * the last bucket elements. - * @param __n The bucket index. - * @return A read-only local iterator. - */ - const_local_iterator - end(size_type __n) const - { return _M_h.end(__n); } - - const_local_iterator - cend(size_type __n) const - { return _M_h.cend(__n); } - //@} - - // hash policy. - - /// Returns the average number of elements per bucket. - float - load_factor() const noexcept - { return _M_h.load_factor(); } - - /// Returns a positive number that the %unordered_map tries to keep the - /// load factor less than or equal to. - float - max_load_factor() const noexcept - { return _M_h.max_load_factor(); } - - /** - * @brief Change the %unordered_map maximum load factor. - * @param __z The new maximum load factor. - */ - void - max_load_factor(float __z) - { _M_h.max_load_factor(__z); } - - /** - * @brief May rehash the %unordered_map. - * @param __n The new number of buckets. - * - * Rehash will occur only if the new number of buckets respect the - * %unordered_map maximum load factor. - */ - void - rehash(size_type __n) - { _M_h.rehash(__n); } - - /** - * @brief Prepare the %unordered_map for a specified number of - * elements. - * @param __n Number of elements required. - * - * Same as rehash(ceil(n / max_load_factor())). - */ - void - reserve(size_type __n) - { _M_h.reserve(__n); } - - template - friend bool - operator==(const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&, - const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&); - }; - -#if __cpp_deduction_guides >= 201606 - - template>, - typename _Pred = equal_to<__iter_key_t<_InputIterator>>, - typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireNotAllocator<_Pred>, - typename = _RequireAllocator<_Allocator>> - unordered_map(_InputIterator, _InputIterator, - typename unordered_map::size_type = {}, - _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) - -> unordered_map<__iter_key_t<_InputIterator>, - __iter_val_t<_InputIterator>, - _Hash, _Pred, _Allocator>; - - template, - typename _Pred = equal_to<_Key>, - typename _Allocator = allocator>, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireNotAllocator<_Pred>, - typename = _RequireAllocator<_Allocator>> - unordered_map(initializer_list>, - typename unordered_map::size_type = {}, - _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) - -> unordered_map<_Key, _Tp, _Hash, _Pred, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_map(_InputIterator, _InputIterator, - typename unordered_map::size_type, _Allocator) - -> unordered_map<__iter_key_t<_InputIterator>, - __iter_val_t<_InputIterator>, - hash<__iter_key_t<_InputIterator>>, - equal_to<__iter_key_t<_InputIterator>>, - _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_map(_InputIterator, _InputIterator, _Allocator) - -> unordered_map<__iter_key_t<_InputIterator>, - __iter_val_t<_InputIterator>, - hash<__iter_key_t<_InputIterator>>, - equal_to<__iter_key_t<_InputIterator>>, - _Allocator>; - - template, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireAllocator<_Allocator>> - unordered_map(_InputIterator, _InputIterator, - typename unordered_map::size_type, - _Hash, _Allocator) - -> unordered_map<__iter_key_t<_InputIterator>, - __iter_val_t<_InputIterator>, _Hash, - equal_to<__iter_key_t<_InputIterator>>, _Allocator>; - - template> - unordered_map(initializer_list>, - typename unordered_map::size_type, - _Allocator) - -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; - - template> - unordered_map(initializer_list>, _Allocator) - -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_map(initializer_list>, - typename unordered_map::size_type, - _Hash, _Allocator) - -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; - -#endif - - /** - * @brief A standard container composed of equivalent keys - * (possibly containing multiple of each key value) that associates - * values of another type with the keys. - * - * @ingroup unordered_associative_containers - * - * @tparam _Key Type of key objects. - * @tparam _Tp Type of mapped objects. - * @tparam _Hash Hashing function object type, defaults to hash<_Value>. - * @tparam _Pred Predicate function object type, defaults - * to equal_to<_Value>. - * @tparam _Alloc Allocator type, defaults to - * std::allocator>. - * - * Meets the requirements of a container, and - * unordered associative container - * - * The resulting value type of the container is std::pair. - * - * Base is _Hashtable, dispatched at compile time via template - * alias __ummap_hashtable. - */ - template, - typename _Pred = equal_to<_Key>, - typename _Alloc = allocator>> - class unordered_multimap - { - typedef __ummap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable; - _Hashtable _M_h; - - public: - // typedefs: - //@{ - /// Public typedefs. - typedef typename _Hashtable::key_type key_type; - typedef typename _Hashtable::value_type value_type; - typedef typename _Hashtable::mapped_type mapped_type; - typedef typename _Hashtable::hasher hasher; - typedef typename _Hashtable::key_equal key_equal; - typedef typename _Hashtable::allocator_type allocator_type; - //@} - - //@{ - /// Iterator-related typedefs. - typedef typename _Hashtable::pointer pointer; - typedef typename _Hashtable::const_pointer const_pointer; - typedef typename _Hashtable::reference reference; - typedef typename _Hashtable::const_reference const_reference; - typedef typename _Hashtable::iterator iterator; - typedef typename _Hashtable::const_iterator const_iterator; - typedef typename _Hashtable::local_iterator local_iterator; - typedef typename _Hashtable::const_local_iterator const_local_iterator; - typedef typename _Hashtable::size_type size_type; - typedef typename _Hashtable::difference_type difference_type; - //@} - -#if __cplusplus > 201402L - using node_type = typename _Hashtable::node_type; -#endif - - //construct/destroy/copy - - /// Default constructor. - unordered_multimap() = default; - - /** - * @brief Default constructor creates no elements. - * @param __n Mnimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - */ - explicit - unordered_multimap(size_type __n, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__n, __hf, __eql, __a) - { } - - /** - * @brief Builds an %unordered_multimap from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - * - * Create an %unordered_multimap consisting of copies of the elements - * from [__first,__last). This is linear in N (where N is - * distance(__first,__last)). - */ - template - unordered_multimap(_InputIterator __first, _InputIterator __last, - size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__first, __last, __n, __hf, __eql, __a) - { } - - /// Copy constructor. - unordered_multimap(const unordered_multimap&) = default; - - /// Move constructor. - unordered_multimap(unordered_multimap&&) = default; - - /** - * @brief Creates an %unordered_multimap with no elements. - * @param __a An allocator object. - */ - explicit - unordered_multimap(const allocator_type& __a) - : _M_h(__a) - { } - - /* - * @brief Copy constructor with allocator argument. - * @param __uset Input %unordered_multimap to copy. - * @param __a An allocator object. - */ - unordered_multimap(const unordered_multimap& __ummap, - const allocator_type& __a) - : _M_h(__ummap._M_h, __a) - { } - - /* - * @brief Move constructor with allocator argument. - * @param __uset Input %unordered_multimap to move. - * @param __a An allocator object. - */ - unordered_multimap(unordered_multimap&& __ummap, - const allocator_type& __a) - : _M_h(std::move(__ummap._M_h), __a) - { } - - /** - * @brief Builds an %unordered_multimap from an initializer_list. - * @param __l An initializer_list. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - * - * Create an %unordered_multimap consisting of copies of the elements in - * the list. This is linear in N (where N is @a __l.size()). - */ - unordered_multimap(initializer_list __l, - size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__l, __n, __hf, __eql, __a) - { } - - unordered_multimap(size_type __n, const allocator_type& __a) - : unordered_multimap(__n, hasher(), key_equal(), __a) - { } - - unordered_multimap(size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_multimap(__n, __hf, key_equal(), __a) - { } - - template - unordered_multimap(_InputIterator __first, _InputIterator __last, - size_type __n, - const allocator_type& __a) - : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a) - { } - - template - unordered_multimap(_InputIterator __first, _InputIterator __last, - size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) - { } - - unordered_multimap(initializer_list __l, - size_type __n, - const allocator_type& __a) - : unordered_multimap(__l, __n, hasher(), key_equal(), __a) - { } - - unordered_multimap(initializer_list __l, - size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_multimap(__l, __n, __hf, key_equal(), __a) - { } - - /// Copy assignment operator. - unordered_multimap& - operator=(const unordered_multimap&) = default; - - /// Move assignment operator. - unordered_multimap& - operator=(unordered_multimap&&) = default; - - /** - * @brief %Unordered_multimap list assignment operator. - * @param __l An initializer_list. - * - * This function fills an %unordered_multimap with copies of the - * elements in the initializer list @a __l. - * - * Note that the assignment completely changes the %unordered_multimap - * and that the resulting %unordered_multimap's size is the same as the - * number of elements assigned. - */ - unordered_multimap& - operator=(initializer_list __l) - { - _M_h = __l; - return *this; - } - - /// Returns the allocator object used by the %unordered_multimap. - allocator_type - get_allocator() const noexcept - { return _M_h.get_allocator(); } - - // size and capacity: - - /// Returns true if the %unordered_multimap is empty. - _GLIBCXX_NODISCARD bool - empty() const noexcept - { return _M_h.empty(); } - - /// Returns the size of the %unordered_multimap. - size_type - size() const noexcept - { return _M_h.size(); } - - /// Returns the maximum size of the %unordered_multimap. - size_type - max_size() const noexcept - { return _M_h.max_size(); } - - // iterators. - - /** - * Returns a read/write iterator that points to the first element in the - * %unordered_multimap. - */ - iterator - begin() noexcept - { return _M_h.begin(); } - - //@{ - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %unordered_multimap. - */ - const_iterator - begin() const noexcept - { return _M_h.begin(); } - - const_iterator - cbegin() const noexcept - { return _M_h.begin(); } - //@} - - /** - * Returns a read/write iterator that points one past the last element in - * the %unordered_multimap. - */ - iterator - end() noexcept - { return _M_h.end(); } - - //@{ - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %unordered_multimap. - */ - const_iterator - end() const noexcept - { return _M_h.end(); } - - const_iterator - cend() const noexcept - { return _M_h.end(); } - //@} - - // modifiers. - - /** - * @brief Attempts to build and insert a std::pair into the - * %unordered_multimap. - * - * @param __args Arguments used to generate a new pair instance (see - * std::piecewise_contruct for passing arguments to each - * part of the pair constructor). - * - * @return An iterator that points to the inserted pair. - * - * This function attempts to build and insert a (key, value) %pair into - * the %unordered_multimap. - * - * Insertion requires amortized constant time. - */ - template - iterator - emplace(_Args&&... __args) - { return _M_h.emplace(std::forward<_Args>(__args)...); } - - /** - * @brief Attempts to build and insert a std::pair into the - * %unordered_multimap. - * - * @param __pos An iterator that serves as a hint as to where the pair - * should be inserted. - * @param __args Arguments used to generate a new pair instance (see - * std::piecewise_contruct for passing arguments to each - * part of the pair constructor). - * @return An iterator that points to the element with key of the - * std::pair built from @a __args. - * - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires amortized constant time. - */ - template - iterator - emplace_hint(const_iterator __pos, _Args&&... __args) - { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } - - //@{ - /** - * @brief Inserts a std::pair into the %unordered_multimap. - * @param __x Pair to be inserted (see std::make_pair for easy - * creation of pairs). - * - * @return An iterator that points to the inserted pair. - * - * Insertion requires amortized constant time. - */ - iterator - insert(const value_type& __x) - { return _M_h.insert(__x); } - - iterator - insert(value_type&& __x) - { return _M_h.insert(std::move(__x)); } - - template - __enable_if_t::value, iterator> - insert(_Pair&& __x) - { return _M_h.emplace(std::forward<_Pair>(__x)); } - //@} - - //@{ - /** - * @brief Inserts a std::pair into the %unordered_multimap. - * @param __hint An iterator that serves as a hint as to where the - * pair should be inserted. - * @param __x Pair to be inserted (see std::make_pair for easy creation - * of pairs). - * @return An iterator that points to the element with key of - * @a __x (may or may not be the %pair passed in). - * - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * See - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * for more on @a hinting. - * - * Insertion requires amortized constant time. - */ - iterator - insert(const_iterator __hint, const value_type& __x) - { return _M_h.insert(__hint, __x); } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2354. Unnecessary copying when inserting into maps with braced-init - iterator - insert(const_iterator __hint, value_type&& __x) - { return _M_h.insert(__hint, std::move(__x)); } - - template - __enable_if_t::value, iterator> - insert(const_iterator __hint, _Pair&& __x) - { return _M_h.emplace_hint(__hint, std::forward<_Pair>(__x)); } - //@} - - /** - * @brief A template function that attempts to insert a range of - * elements. - * @param __first Iterator pointing to the start of the range to be - * inserted. - * @param __last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) - { _M_h.insert(__first, __last); } - - /** - * @brief Attempts to insert a list of elements into the - * %unordered_multimap. - * @param __l A std::initializer_list of elements - * to be inserted. - * - * Complexity similar to that of the range constructor. - */ - void - insert(initializer_list __l) - { _M_h.insert(__l); } - -#if __cplusplus > 201402L - /// Extract a node. - node_type - extract(const_iterator __pos) - { - __glibcxx_assert(__pos != end()); - return _M_h.extract(__pos); - } - - /// Extract a node. - node_type - extract(const key_type& __key) - { return _M_h.extract(__key); } - - /// Re-insert an extracted node. - iterator - insert(node_type&& __nh) - { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); } - - /// Re-insert an extracted node. - iterator - insert(const_iterator __hint, node_type&& __nh) - { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } -#endif // C++17 - - //@{ - /** - * @brief Erases an element from an %unordered_multimap. - * @param __position An iterator pointing to the element to be erased. - * @return An iterator pointing to the element immediately following - * @a __position prior to the element being erased. If no such - * element exists, end() is returned. - * - * This function erases an element, pointed to by the given iterator, - * from an %unordered_multimap. - * Note that this function only erases the element, and that if the - * element is itself a pointer, the pointed-to memory is not touched in - * any way. Managing the pointer is the user's responsibility. - */ - iterator - erase(const_iterator __position) - { return _M_h.erase(__position); } - - // LWG 2059. - iterator - erase(iterator __position) - { return _M_h.erase(__position); } - //@} - - /** - * @brief Erases elements according to the provided key. - * @param __x Key of elements to be erased. - * @return The number of elements erased. - * - * This function erases all the elements located by the given key from - * an %unordered_multimap. - * Note that this function only erases the element, and that if the - * element is itself a pointer, the pointed-to memory is not touched in - * any way. Managing the pointer is the user's responsibility. - */ - size_type - erase(const key_type& __x) - { return _M_h.erase(__x); } - - /** - * @brief Erases a [__first,__last) range of elements from an - * %unordered_multimap. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * @return The iterator @a __last. - * - * This function erases a sequence of elements from an - * %unordered_multimap. - * Note that this function only erases the elements, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - iterator - erase(const_iterator __first, const_iterator __last) - { return _M_h.erase(__first, __last); } - - /** - * Erases all elements in an %unordered_multimap. - * Note that this function only erases the elements, and that if the - * elements themselves are pointers, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - void - clear() noexcept - { _M_h.clear(); } - - /** - * @brief Swaps data with another %unordered_multimap. - * @param __x An %unordered_multimap of the same element and allocator - * types. - * - * This exchanges the elements between two %unordered_multimap in - * constant time. - * Note that the global std::swap() function is specialized such that - * std::swap(m1,m2) will feed to this function. - */ - void - swap(unordered_multimap& __x) - noexcept( noexcept(_M_h.swap(__x._M_h)) ) - { _M_h.swap(__x._M_h); } - -#if __cplusplus > 201402L - template - friend class std::_Hash_merge_helper; - - template - void - merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) - { - using _Merge_helper - = _Hash_merge_helper; - _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); - } - - template - void - merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) - { merge(__source); } - - template - void - merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) - { - using _Merge_helper - = _Hash_merge_helper; - _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); - } - - template - void - merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) - { merge(__source); } -#endif // C++17 - - // observers. - - /// Returns the hash functor object with which the %unordered_multimap - /// was constructed. - hasher - hash_function() const - { return _M_h.hash_function(); } - - /// Returns the key comparison object with which the %unordered_multimap - /// was constructed. - key_equal - key_eq() const - { return _M_h.key_eq(); } - - // lookup. - - //@{ - /** - * @brief Tries to locate an element in an %unordered_multimap. - * @param __x Key to be located. - * @return Iterator pointing to sought-after element, or end() if not - * found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after element. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) - { return _M_h.find(__x); } - - const_iterator - find(const key_type& __x) const - { return _M_h.find(__x); } - //@} - - /** - * @brief Finds the number of elements. - * @param __x Key to count. - * @return Number of elements with specified key. - */ - size_type - count(const key_type& __x) const - { return _M_h.count(__x); } - -#if __cplusplus > 201703L - /** - * @brief Finds whether an element with the given key exists. - * @param __x Key of elements to be located. - * @return True if there is any element with the specified key. - */ - bool - contains(const key_type& __x) const - { return _M_h.find(__x) != _M_h.end(); } -#endif - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - */ - std::pair - equal_range(const key_type& __x) - { return _M_h.equal_range(__x); } - - std::pair - equal_range(const key_type& __x) const - { return _M_h.equal_range(__x); } - //@} - - // bucket interface. - - /// Returns the number of buckets of the %unordered_multimap. - size_type - bucket_count() const noexcept - { return _M_h.bucket_count(); } - - /// Returns the maximum number of buckets of the %unordered_multimap. - size_type - max_bucket_count() const noexcept - { return _M_h.max_bucket_count(); } - - /* - * @brief Returns the number of elements in a given bucket. - * @param __n A bucket index. - * @return The number of elements in the bucket. - */ - size_type - bucket_size(size_type __n) const - { return _M_h.bucket_size(__n); } - - /* - * @brief Returns the bucket index of a given element. - * @param __key A key instance. - * @return The key bucket index. - */ - size_type - bucket(const key_type& __key) const - { return _M_h.bucket(__key); } - - /** - * @brief Returns a read/write iterator pointing to the first bucket - * element. - * @param __n The bucket index. - * @return A read/write local iterator. - */ - local_iterator - begin(size_type __n) - { return _M_h.begin(__n); } - - //@{ - /** - * @brief Returns a read-only (constant) iterator pointing to the first - * bucket element. - * @param __n The bucket index. - * @return A read-only local iterator. - */ - const_local_iterator - begin(size_type __n) const - { return _M_h.begin(__n); } - - const_local_iterator - cbegin(size_type __n) const - { return _M_h.cbegin(__n); } - //@} - - /** - * @brief Returns a read/write iterator pointing to one past the last - * bucket elements. - * @param __n The bucket index. - * @return A read/write local iterator. - */ - local_iterator - end(size_type __n) - { return _M_h.end(__n); } - - //@{ - /** - * @brief Returns a read-only (constant) iterator pointing to one past - * the last bucket elements. - * @param __n The bucket index. - * @return A read-only local iterator. - */ - const_local_iterator - end(size_type __n) const - { return _M_h.end(__n); } - - const_local_iterator - cend(size_type __n) const - { return _M_h.cend(__n); } - //@} - - // hash policy. - - /// Returns the average number of elements per bucket. - float - load_factor() const noexcept - { return _M_h.load_factor(); } - - /// Returns a positive number that the %unordered_multimap tries to keep - /// the load factor less than or equal to. - float - max_load_factor() const noexcept - { return _M_h.max_load_factor(); } - - /** - * @brief Change the %unordered_multimap maximum load factor. - * @param __z The new maximum load factor. - */ - void - max_load_factor(float __z) - { _M_h.max_load_factor(__z); } - - /** - * @brief May rehash the %unordered_multimap. - * @param __n The new number of buckets. - * - * Rehash will occur only if the new number of buckets respect the - * %unordered_multimap maximum load factor. - */ - void - rehash(size_type __n) - { _M_h.rehash(__n); } - - /** - * @brief Prepare the %unordered_multimap for a specified number of - * elements. - * @param __n Number of elements required. - * - * Same as rehash(ceil(n / max_load_factor())). - */ - void - reserve(size_type __n) - { _M_h.reserve(__n); } - - template - friend bool - operator==(const unordered_multimap<_Key1, _Tp1, - _Hash1, _Pred1, _Alloc1>&, - const unordered_multimap<_Key1, _Tp1, - _Hash1, _Pred1, _Alloc1>&); - }; - -#if __cpp_deduction_guides >= 201606 - - template>, - typename _Pred = equal_to<__iter_key_t<_InputIterator>>, - typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireNotAllocator<_Pred>, - typename = _RequireAllocator<_Allocator>> - unordered_multimap(_InputIterator, _InputIterator, - unordered_multimap::size_type = {}, - _Hash = _Hash(), _Pred = _Pred(), - _Allocator = _Allocator()) - -> unordered_multimap<__iter_key_t<_InputIterator>, - __iter_val_t<_InputIterator>, _Hash, _Pred, - _Allocator>; - - template, - typename _Pred = equal_to<_Key>, - typename _Allocator = allocator>, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireNotAllocator<_Pred>, - typename = _RequireAllocator<_Allocator>> - unordered_multimap(initializer_list>, - unordered_multimap::size_type = {}, - _Hash = _Hash(), _Pred = _Pred(), - _Allocator = _Allocator()) - -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_multimap(_InputIterator, _InputIterator, - unordered_multimap::size_type, _Allocator) - -> unordered_multimap<__iter_key_t<_InputIterator>, - __iter_val_t<_InputIterator>, - hash<__iter_key_t<_InputIterator>>, - equal_to<__iter_key_t<_InputIterator>>, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_multimap(_InputIterator, _InputIterator, _Allocator) - -> unordered_multimap<__iter_key_t<_InputIterator>, - __iter_val_t<_InputIterator>, - hash<__iter_key_t<_InputIterator>>, - equal_to<__iter_key_t<_InputIterator>>, _Allocator>; - - template, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireAllocator<_Allocator>> - unordered_multimap(_InputIterator, _InputIterator, - unordered_multimap::size_type, _Hash, - _Allocator) - -> unordered_multimap<__iter_key_t<_InputIterator>, - __iter_val_t<_InputIterator>, _Hash, - equal_to<__iter_key_t<_InputIterator>>, _Allocator>; - - template> - unordered_multimap(initializer_list>, - unordered_multimap::size_type, - _Allocator) - -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; - - template> - unordered_multimap(initializer_list>, _Allocator) - -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_multimap(initializer_list>, - unordered_multimap::size_type, - _Hash, _Allocator) - -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; - -#endif - - template - inline void - swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, - unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - template - inline void - swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, - unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - template - inline bool - operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, - const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) - { return __x._M_h._M_equal(__y._M_h); } - -#if __cpp_impl_three_way_comparison < 201907L - template - inline bool - operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, - const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) - { return !(__x == __y); } -#endif - - template - inline bool - operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, - const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) - { return __x._M_h._M_equal(__y._M_h); } - -#if __cpp_impl_three_way_comparison < 201907L - template - inline bool - operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, - const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) - { return !(__x == __y); } -#endif - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if __cplusplus > 201402L - // Allow std::unordered_map access to internals of compatible maps. - template - struct _Hash_merge_helper< - _GLIBCXX_STD_C::unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>, - _Hash2, _Eq2> - { - private: - template - using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>; - template - using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>; - - friend unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>; - - static auto& - _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) - { return __map._M_h; } - - static auto& - _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) - { return __map._M_h; } - }; - - // Allow std::unordered_multimap access to internals of compatible maps. - template - struct _Hash_merge_helper< - _GLIBCXX_STD_C::unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>, - _Hash2, _Eq2> - { - private: - template - using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>; - template - using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>; - - friend unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>; - - static auto& - _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) - { return __map._M_h; } - - static auto& - _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) - { return __map._M_h; } - }; -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _UNORDERED_MAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/unordered_set.h b/resources/sources/avr-libstdcpp/include/bits/unordered_set.h deleted file mode 100644 index c9c9e9f38..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/unordered_set.h +++ /dev/null @@ -1,1783 +0,0 @@ -// unordered_set implementation -*- C++ -*- - -// Copyright (C) 2010-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/unordered_set.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{unordered_set} - */ - -#ifndef _UNORDERED_SET_H -#define _UNORDERED_SET_H - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - /// Base types for unordered_set. - template - using __uset_traits = __detail::_Hashtable_traits<_Cache, true, true>; - - template, - typename _Pred = std::equal_to<_Value>, - typename _Alloc = std::allocator<_Value>, - typename _Tr = __uset_traits<__cache_default<_Value, _Hash>::value>> - using __uset_hashtable = _Hashtable<_Value, _Value, _Alloc, - __detail::_Identity, _Pred, _Hash, - __detail::_Mod_range_hashing, - __detail::_Default_ranged_hash, - __detail::_Prime_rehash_policy, _Tr>; - - /// Base types for unordered_multiset. - template - using __umset_traits = __detail::_Hashtable_traits<_Cache, true, false>; - - template, - typename _Pred = std::equal_to<_Value>, - typename _Alloc = std::allocator<_Value>, - typename _Tr = __umset_traits<__cache_default<_Value, _Hash>::value>> - using __umset_hashtable = _Hashtable<_Value, _Value, _Alloc, - __detail::_Identity, - _Pred, _Hash, - __detail::_Mod_range_hashing, - __detail::_Default_ranged_hash, - __detail::_Prime_rehash_policy, _Tr>; - - template - class unordered_multiset; - - /** - * @brief A standard container composed of unique keys (containing - * at most one of each key value) in which the elements' keys are - * the elements themselves. - * - * @ingroup unordered_associative_containers - * - * @tparam _Value Type of key objects. - * @tparam _Hash Hashing function object type, defaults to hash<_Value>. - - * @tparam _Pred Predicate function object type, defaults to - * equal_to<_Value>. - * - * @tparam _Alloc Allocator type, defaults to allocator<_Key>. - * - * Meets the requirements of a container, and - * unordered associative container - * - * Base is _Hashtable, dispatched at compile time via template - * alias __uset_hashtable. - */ - template, - typename _Pred = equal_to<_Value>, - typename _Alloc = allocator<_Value>> - class unordered_set - { - typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; - _Hashtable _M_h; - - public: - // typedefs: - //@{ - /// Public typedefs. - typedef typename _Hashtable::key_type key_type; - typedef typename _Hashtable::value_type value_type; - typedef typename _Hashtable::hasher hasher; - typedef typename _Hashtable::key_equal key_equal; - typedef typename _Hashtable::allocator_type allocator_type; - //@} - - //@{ - /// Iterator-related typedefs. - typedef typename _Hashtable::pointer pointer; - typedef typename _Hashtable::const_pointer const_pointer; - typedef typename _Hashtable::reference reference; - typedef typename _Hashtable::const_reference const_reference; - typedef typename _Hashtable::iterator iterator; - typedef typename _Hashtable::const_iterator const_iterator; - typedef typename _Hashtable::local_iterator local_iterator; - typedef typename _Hashtable::const_local_iterator const_local_iterator; - typedef typename _Hashtable::size_type size_type; - typedef typename _Hashtable::difference_type difference_type; - //@} - -#if __cplusplus > 201402L - using node_type = typename _Hashtable::node_type; - using insert_return_type = typename _Hashtable::insert_return_type; -#endif - - // construct/destroy/copy - - /// Default constructor. - unordered_set() = default; - - /** - * @brief Default constructor creates no elements. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - */ - explicit - unordered_set(size_type __n, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__n, __hf, __eql, __a) - { } - - /** - * @brief Builds an %unordered_set from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - * - * Create an %unordered_set consisting of copies of the elements from - * [__first,__last). This is linear in N (where N is - * distance(__first,__last)). - */ - template - unordered_set(_InputIterator __first, _InputIterator __last, - size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__first, __last, __n, __hf, __eql, __a) - { } - - /// Copy constructor. - unordered_set(const unordered_set&) = default; - - /// Move constructor. - unordered_set(unordered_set&&) = default; - - /** - * @brief Creates an %unordered_set with no elements. - * @param __a An allocator object. - */ - explicit - unordered_set(const allocator_type& __a) - : _M_h(__a) - { } - - /* - * @brief Copy constructor with allocator argument. - * @param __uset Input %unordered_set to copy. - * @param __a An allocator object. - */ - unordered_set(const unordered_set& __uset, - const allocator_type& __a) - : _M_h(__uset._M_h, __a) - { } - - /* - * @brief Move constructor with allocator argument. - * @param __uset Input %unordered_set to move. - * @param __a An allocator object. - */ - unordered_set(unordered_set&& __uset, - const allocator_type& __a) - : _M_h(std::move(__uset._M_h), __a) - { } - - /** - * @brief Builds an %unordered_set from an initializer_list. - * @param __l An initializer_list. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - * - * Create an %unordered_set consisting of copies of the elements in the - * list. This is linear in N (where N is @a __l.size()). - */ - unordered_set(initializer_list __l, - size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__l, __n, __hf, __eql, __a) - { } - - unordered_set(size_type __n, const allocator_type& __a) - : unordered_set(__n, hasher(), key_equal(), __a) - { } - - unordered_set(size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_set(__n, __hf, key_equal(), __a) - { } - - template - unordered_set(_InputIterator __first, _InputIterator __last, - size_type __n, - const allocator_type& __a) - : unordered_set(__first, __last, __n, hasher(), key_equal(), __a) - { } - - template - unordered_set(_InputIterator __first, _InputIterator __last, - size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_set(__first, __last, __n, __hf, key_equal(), __a) - { } - - unordered_set(initializer_list __l, - size_type __n, - const allocator_type& __a) - : unordered_set(__l, __n, hasher(), key_equal(), __a) - { } - - unordered_set(initializer_list __l, - size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_set(__l, __n, __hf, key_equal(), __a) - { } - - /// Copy assignment operator. - unordered_set& - operator=(const unordered_set&) = default; - - /// Move assignment operator. - unordered_set& - operator=(unordered_set&&) = default; - - /** - * @brief %Unordered_set list assignment operator. - * @param __l An initializer_list. - * - * This function fills an %unordered_set with copies of the elements in - * the initializer list @a __l. - * - * Note that the assignment completely changes the %unordered_set and - * that the resulting %unordered_set's size is the same as the number - * of elements assigned. - */ - unordered_set& - operator=(initializer_list __l) - { - _M_h = __l; - return *this; - } - - /// Returns the allocator object used by the %unordered_set. - allocator_type - get_allocator() const noexcept - { return _M_h.get_allocator(); } - - // size and capacity: - - /// Returns true if the %unordered_set is empty. - _GLIBCXX_NODISCARD bool - empty() const noexcept - { return _M_h.empty(); } - - /// Returns the size of the %unordered_set. - size_type - size() const noexcept - { return _M_h.size(); } - - /// Returns the maximum size of the %unordered_set. - size_type - max_size() const noexcept - { return _M_h.max_size(); } - - // iterators. - - //@{ - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %unordered_set. - */ - iterator - begin() noexcept - { return _M_h.begin(); } - - const_iterator - begin() const noexcept - { return _M_h.begin(); } - //@} - - //@{ - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %unordered_set. - */ - iterator - end() noexcept - { return _M_h.end(); } - - const_iterator - end() const noexcept - { return _M_h.end(); } - //@} - - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %unordered_set. - */ - const_iterator - cbegin() const noexcept - { return _M_h.begin(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %unordered_set. - */ - const_iterator - cend() const noexcept - { return _M_h.end(); } - - // modifiers. - - /** - * @brief Attempts to build and insert an element into the - * %unordered_set. - * @param __args Arguments used to generate an element. - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted element, and the second is a bool - * that is true if the element was actually inserted. - * - * This function attempts to build and insert an element into the - * %unordered_set. An %unordered_set relies on unique keys and thus an - * element is only inserted if it is not already present in the - * %unordered_set. - * - * Insertion requires amortized constant time. - */ - template - std::pair - emplace(_Args&&... __args) - { return _M_h.emplace(std::forward<_Args>(__args)...); } - - /** - * @brief Attempts to insert an element into the %unordered_set. - * @param __pos An iterator that serves as a hint as to where the - * element should be inserted. - * @param __args Arguments used to generate the element to be - * inserted. - * @return An iterator that points to the element with key equivalent to - * the one generated from @a __args (may or may not be the - * element itself). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument emplace() - * does. Note that the first parameter is only a hint and can - * potentially improve the performance of the insertion process. A bad - * hint would cause no gains in efficiency. - * - * For more on @a hinting, see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * - * Insertion requires amortized constant time. - */ - template - iterator - emplace_hint(const_iterator __pos, _Args&&... __args) - { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } - - //@{ - /** - * @brief Attempts to insert an element into the %unordered_set. - * @param __x Element to be inserted. - * @return A pair, of which the first element is an iterator that points - * to the possibly inserted element, and the second is a bool - * that is true if the element was actually inserted. - * - * This function attempts to insert an element into the %unordered_set. - * An %unordered_set relies on unique keys and thus an element is only - * inserted if it is not already present in the %unordered_set. - * - * Insertion requires amortized constant time. - */ - std::pair - insert(const value_type& __x) - { return _M_h.insert(__x); } - - std::pair - insert(value_type&& __x) - { return _M_h.insert(std::move(__x)); } - //@} - - //@{ - /** - * @brief Attempts to insert an element into the %unordered_set. - * @param __hint An iterator that serves as a hint as to where the - * element should be inserted. - * @param __x Element to be inserted. - * @return An iterator that points to the element with key of - * @a __x (may or may not be the element passed in). - * - * This function is not concerned about whether the insertion took place, - * and thus does not return a boolean like the single-argument insert() - * does. Note that the first parameter is only a hint and can - * potentially improve the performance of the insertion process. A bad - * hint would cause no gains in efficiency. - * - * For more on @a hinting, see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * - * Insertion requires amortized constant. - */ - iterator - insert(const_iterator __hint, const value_type& __x) - { return _M_h.insert(__hint, __x); } - - iterator - insert(const_iterator __hint, value_type&& __x) - { return _M_h.insert(__hint, std::move(__x)); } - //@} - - /** - * @brief A template function that attempts to insert a range of - * elements. - * @param __first Iterator pointing to the start of the range to be - * inserted. - * @param __last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) - { _M_h.insert(__first, __last); } - - /** - * @brief Attempts to insert a list of elements into the %unordered_set. - * @param __l A std::initializer_list of elements - * to be inserted. - * - * Complexity similar to that of the range constructor. - */ - void - insert(initializer_list __l) - { _M_h.insert(__l); } - -#if __cplusplus > 201402L - /// Extract a node. - node_type - extract(const_iterator __pos) - { - __glibcxx_assert(__pos != end()); - return _M_h.extract(__pos); - } - - /// Extract a node. - node_type - extract(const key_type& __key) - { return _M_h.extract(__key); } - - /// Re-insert an extracted node. - insert_return_type - insert(node_type&& __nh) - { return _M_h._M_reinsert_node(std::move(__nh)); } - - /// Re-insert an extracted node. - iterator - insert(const_iterator, node_type&& __nh) - { return _M_h._M_reinsert_node(std::move(__nh)).position; } -#endif // C++17 - - //@{ - /** - * @brief Erases an element from an %unordered_set. - * @param __position An iterator pointing to the element to be erased. - * @return An iterator pointing to the element immediately following - * @a __position prior to the element being erased. If no such - * element exists, end() is returned. - * - * This function erases an element, pointed to by the given iterator, - * from an %unordered_set. Note that this function only erases the - * element, and that if the element is itself a pointer, the pointed-to - * memory is not touched in any way. Managing the pointer is the user's - * responsibility. - */ - iterator - erase(const_iterator __position) - { return _M_h.erase(__position); } - - // LWG 2059. - iterator - erase(iterator __position) - { return _M_h.erase(__position); } - //@} - - /** - * @brief Erases elements according to the provided key. - * @param __x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all the elements located by the given key from - * an %unordered_set. For an %unordered_set the result of this function - * can only be 0 (not present) or 1 (present). - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - size_type - erase(const key_type& __x) - { return _M_h.erase(__x); } - - /** - * @brief Erases a [__first,__last) range of elements from an - * %unordered_set. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * @return The iterator @a __last. - * - * This function erases a sequence of elements from an %unordered_set. - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - iterator - erase(const_iterator __first, const_iterator __last) - { return _M_h.erase(__first, __last); } - - /** - * Erases all elements in an %unordered_set. Note that this function only - * erases the elements, and that if the elements themselves are pointers, - * the pointed-to memory is not touched in any way. Managing the pointer - * is the user's responsibility. - */ - void - clear() noexcept - { _M_h.clear(); } - - /** - * @brief Swaps data with another %unordered_set. - * @param __x An %unordered_set of the same element and allocator - * types. - * - * This exchanges the elements between two sets in constant time. - * Note that the global std::swap() function is specialized such that - * std::swap(s1,s2) will feed to this function. - */ - void - swap(unordered_set& __x) - noexcept( noexcept(_M_h.swap(__x._M_h)) ) - { _M_h.swap(__x._M_h); } - -#if __cplusplus > 201402L - template - friend class std::_Hash_merge_helper; - - template - void - merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) - { - using _Merge_helper = _Hash_merge_helper; - _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); - } - - template - void - merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) - { merge(__source); } - - template - void - merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) - { - using _Merge_helper = _Hash_merge_helper; - _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); - } - - template - void - merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) - { merge(__source); } -#endif // C++17 - - // observers. - - /// Returns the hash functor object with which the %unordered_set was - /// constructed. - hasher - hash_function() const - { return _M_h.hash_function(); } - - /// Returns the key comparison object with which the %unordered_set was - /// constructed. - key_equal - key_eq() const - { return _M_h.key_eq(); } - - // lookup. - - //@{ - /** - * @brief Tries to locate an element in an %unordered_set. - * @param __x Element to be located. - * @return Iterator pointing to sought-after element, or end() if not - * found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after element. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) - { return _M_h.find(__x); } - - const_iterator - find(const key_type& __x) const - { return _M_h.find(__x); } - //@} - - /** - * @brief Finds the number of elements. - * @param __x Element to located. - * @return Number of elements with specified key. - * - * This function only makes sense for unordered_multisets; for - * unordered_set the result will either be 0 (not present) or 1 - * (present). - */ - size_type - count(const key_type& __x) const - { return _M_h.count(__x); } - -#if __cplusplus > 201703L - /** - * @brief Finds whether an element with the given key exists. - * @param __x Key of elements to be located. - * @return True if there is any element with the specified key. - */ - bool - contains(const key_type& __x) const - { return _M_h.find(__x) != _M_h.end(); } -#endif - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - * - * This function probably only makes sense for multisets. - */ - std::pair - equal_range(const key_type& __x) - { return _M_h.equal_range(__x); } - - std::pair - equal_range(const key_type& __x) const - { return _M_h.equal_range(__x); } - //@} - - // bucket interface. - - /// Returns the number of buckets of the %unordered_set. - size_type - bucket_count() const noexcept - { return _M_h.bucket_count(); } - - /// Returns the maximum number of buckets of the %unordered_set. - size_type - max_bucket_count() const noexcept - { return _M_h.max_bucket_count(); } - - /* - * @brief Returns the number of elements in a given bucket. - * @param __n A bucket index. - * @return The number of elements in the bucket. - */ - size_type - bucket_size(size_type __n) const - { return _M_h.bucket_size(__n); } - - /* - * @brief Returns the bucket index of a given element. - * @param __key A key instance. - * @return The key bucket index. - */ - size_type - bucket(const key_type& __key) const - { return _M_h.bucket(__key); } - - //@{ - /** - * @brief Returns a read-only (constant) iterator pointing to the first - * bucket element. - * @param __n The bucket index. - * @return A read-only local iterator. - */ - local_iterator - begin(size_type __n) - { return _M_h.begin(__n); } - - const_local_iterator - begin(size_type __n) const - { return _M_h.begin(__n); } - - const_local_iterator - cbegin(size_type __n) const - { return _M_h.cbegin(__n); } - //@} - - //@{ - /** - * @brief Returns a read-only (constant) iterator pointing to one past - * the last bucket elements. - * @param __n The bucket index. - * @return A read-only local iterator. - */ - local_iterator - end(size_type __n) - { return _M_h.end(__n); } - - const_local_iterator - end(size_type __n) const - { return _M_h.end(__n); } - - const_local_iterator - cend(size_type __n) const - { return _M_h.cend(__n); } - //@} - - // hash policy. - - /// Returns the average number of elements per bucket. - float - load_factor() const noexcept - { return _M_h.load_factor(); } - - /// Returns a positive number that the %unordered_set tries to keep the - /// load factor less than or equal to. - float - max_load_factor() const noexcept - { return _M_h.max_load_factor(); } - - /** - * @brief Change the %unordered_set maximum load factor. - * @param __z The new maximum load factor. - */ - void - max_load_factor(float __z) - { _M_h.max_load_factor(__z); } - - /** - * @brief May rehash the %unordered_set. - * @param __n The new number of buckets. - * - * Rehash will occur only if the new number of buckets respect the - * %unordered_set maximum load factor. - */ - void - rehash(size_type __n) - { _M_h.rehash(__n); } - - /** - * @brief Prepare the %unordered_set for a specified number of - * elements. - * @param __n Number of elements required. - * - * Same as rehash(ceil(n / max_load_factor())). - */ - void - reserve(size_type __n) - { _M_h.reserve(__n); } - - template - friend bool - operator==(const unordered_set<_Value1, _Hash1, _Pred1, _Alloc1>&, - const unordered_set<_Value1, _Hash1, _Pred1, _Alloc1>&); - }; - -#if __cpp_deduction_guides >= 201606 - - template::value_type>, - typename _Pred = - equal_to::value_type>, - typename _Allocator = - allocator::value_type>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireNotAllocator<_Pred>, - typename = _RequireAllocator<_Allocator>> - unordered_set(_InputIterator, _InputIterator, - unordered_set::size_type = {}, - _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) - -> unordered_set::value_type, - _Hash, _Pred, _Allocator>; - - template, - typename _Pred = equal_to<_Tp>, - typename _Allocator = allocator<_Tp>, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireNotAllocator<_Pred>, - typename = _RequireAllocator<_Allocator>> - unordered_set(initializer_list<_Tp>, - unordered_set::size_type = {}, - _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) - -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_set(_InputIterator, _InputIterator, - unordered_set::size_type, _Allocator) - -> unordered_set::value_type, - hash< - typename iterator_traits<_InputIterator>::value_type>, - equal_to< - typename iterator_traits<_InputIterator>::value_type>, - _Allocator>; - - template, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireAllocator<_Allocator>> - unordered_set(_InputIterator, _InputIterator, - unordered_set::size_type, - _Hash, _Allocator) - -> unordered_set::value_type, - _Hash, - equal_to< - typename iterator_traits<_InputIterator>::value_type>, - _Allocator>; - - template> - unordered_set(initializer_list<_Tp>, - unordered_set::size_type, _Allocator) - -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_set(initializer_list<_Tp>, - unordered_set::size_type, _Hash, _Allocator) - -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; - -#endif - - /** - * @brief A standard container composed of equivalent keys - * (possibly containing multiple of each key value) in which the - * elements' keys are the elements themselves. - * - * @ingroup unordered_associative_containers - * - * @tparam _Value Type of key objects. - * @tparam _Hash Hashing function object type, defaults to hash<_Value>. - * @tparam _Pred Predicate function object type, defaults - * to equal_to<_Value>. - * @tparam _Alloc Allocator type, defaults to allocator<_Key>. - * - * Meets the requirements of a container, and - * unordered associative container - * - * Base is _Hashtable, dispatched at compile time via template - * alias __umset_hashtable. - */ - template, - typename _Pred = equal_to<_Value>, - typename _Alloc = allocator<_Value>> - class unordered_multiset - { - typedef __umset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; - _Hashtable _M_h; - - public: - // typedefs: - //@{ - /// Public typedefs. - typedef typename _Hashtable::key_type key_type; - typedef typename _Hashtable::value_type value_type; - typedef typename _Hashtable::hasher hasher; - typedef typename _Hashtable::key_equal key_equal; - typedef typename _Hashtable::allocator_type allocator_type; - //@} - - //@{ - /// Iterator-related typedefs. - typedef typename _Hashtable::pointer pointer; - typedef typename _Hashtable::const_pointer const_pointer; - typedef typename _Hashtable::reference reference; - typedef typename _Hashtable::const_reference const_reference; - typedef typename _Hashtable::iterator iterator; - typedef typename _Hashtable::const_iterator const_iterator; - typedef typename _Hashtable::local_iterator local_iterator; - typedef typename _Hashtable::const_local_iterator const_local_iterator; - typedef typename _Hashtable::size_type size_type; - typedef typename _Hashtable::difference_type difference_type; - //@} - -#if __cplusplus > 201402L - using node_type = typename _Hashtable::node_type; -#endif - - // construct/destroy/copy - - /// Default constructor. - unordered_multiset() = default; - - /** - * @brief Default constructor creates no elements. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - */ - explicit - unordered_multiset(size_type __n, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__n, __hf, __eql, __a) - { } - - /** - * @brief Builds an %unordered_multiset from a range. - * @param __first An input iterator. - * @param __last An input iterator. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - * - * Create an %unordered_multiset consisting of copies of the elements - * from [__first,__last). This is linear in N (where N is - * distance(__first,__last)). - */ - template - unordered_multiset(_InputIterator __first, _InputIterator __last, - size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__first, __last, __n, __hf, __eql, __a) - { } - - /// Copy constructor. - unordered_multiset(const unordered_multiset&) = default; - - /// Move constructor. - unordered_multiset(unordered_multiset&&) = default; - - /** - * @brief Builds an %unordered_multiset from an initializer_list. - * @param __l An initializer_list. - * @param __n Minimal initial number of buckets. - * @param __hf A hash functor. - * @param __eql A key equality functor. - * @param __a An allocator object. - * - * Create an %unordered_multiset consisting of copies of the elements in - * the list. This is linear in N (where N is @a __l.size()). - */ - unordered_multiset(initializer_list __l, - size_type __n = 0, - const hasher& __hf = hasher(), - const key_equal& __eql = key_equal(), - const allocator_type& __a = allocator_type()) - : _M_h(__l, __n, __hf, __eql, __a) - { } - - /// Copy assignment operator. - unordered_multiset& - operator=(const unordered_multiset&) = default; - - /// Move assignment operator. - unordered_multiset& - operator=(unordered_multiset&&) = default; - - /** - * @brief Creates an %unordered_multiset with no elements. - * @param __a An allocator object. - */ - explicit - unordered_multiset(const allocator_type& __a) - : _M_h(__a) - { } - - /* - * @brief Copy constructor with allocator argument. - * @param __uset Input %unordered_multiset to copy. - * @param __a An allocator object. - */ - unordered_multiset(const unordered_multiset& __umset, - const allocator_type& __a) - : _M_h(__umset._M_h, __a) - { } - - /* - * @brief Move constructor with allocator argument. - * @param __umset Input %unordered_multiset to move. - * @param __a An allocator object. - */ - unordered_multiset(unordered_multiset&& __umset, - const allocator_type& __a) - : _M_h(std::move(__umset._M_h), __a) - { } - - unordered_multiset(size_type __n, const allocator_type& __a) - : unordered_multiset(__n, hasher(), key_equal(), __a) - { } - - unordered_multiset(size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_multiset(__n, __hf, key_equal(), __a) - { } - - template - unordered_multiset(_InputIterator __first, _InputIterator __last, - size_type __n, - const allocator_type& __a) - : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a) - { } - - template - unordered_multiset(_InputIterator __first, _InputIterator __last, - size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a) - { } - - unordered_multiset(initializer_list __l, - size_type __n, - const allocator_type& __a) - : unordered_multiset(__l, __n, hasher(), key_equal(), __a) - { } - - unordered_multiset(initializer_list __l, - size_type __n, const hasher& __hf, - const allocator_type& __a) - : unordered_multiset(__l, __n, __hf, key_equal(), __a) - { } - - /** - * @brief %Unordered_multiset list assignment operator. - * @param __l An initializer_list. - * - * This function fills an %unordered_multiset with copies of the elements - * in the initializer list @a __l. - * - * Note that the assignment completely changes the %unordered_multiset - * and that the resulting %unordered_multiset's size is the same as the - * number of elements assigned. - */ - unordered_multiset& - operator=(initializer_list __l) - { - _M_h = __l; - return *this; - } - - /// Returns the allocator object used by the %unordered_multiset. - allocator_type - get_allocator() const noexcept - { return _M_h.get_allocator(); } - - // size and capacity: - - /// Returns true if the %unordered_multiset is empty. - _GLIBCXX_NODISCARD bool - empty() const noexcept - { return _M_h.empty(); } - - /// Returns the size of the %unordered_multiset. - size_type - size() const noexcept - { return _M_h.size(); } - - /// Returns the maximum size of the %unordered_multiset. - size_type - max_size() const noexcept - { return _M_h.max_size(); } - - // iterators. - - //@{ - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %unordered_multiset. - */ - iterator - begin() noexcept - { return _M_h.begin(); } - - const_iterator - begin() const noexcept - { return _M_h.begin(); } - //@} - - //@{ - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %unordered_multiset. - */ - iterator - end() noexcept - { return _M_h.end(); } - - const_iterator - end() const noexcept - { return _M_h.end(); } - //@} - - /** - * Returns a read-only (constant) iterator that points to the first - * element in the %unordered_multiset. - */ - const_iterator - cbegin() const noexcept - { return _M_h.begin(); } - - /** - * Returns a read-only (constant) iterator that points one past the last - * element in the %unordered_multiset. - */ - const_iterator - cend() const noexcept - { return _M_h.end(); } - - // modifiers. - - /** - * @brief Builds and insert an element into the %unordered_multiset. - * @param __args Arguments used to generate an element. - * @return An iterator that points to the inserted element. - * - * Insertion requires amortized constant time. - */ - template - iterator - emplace(_Args&&... __args) - { return _M_h.emplace(std::forward<_Args>(__args)...); } - - /** - * @brief Inserts an element into the %unordered_multiset. - * @param __pos An iterator that serves as a hint as to where the - * element should be inserted. - * @param __args Arguments used to generate the element to be - * inserted. - * @return An iterator that points to the inserted element. - * - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * For more on @a hinting, see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * - * Insertion requires amortized constant time. - */ - template - iterator - emplace_hint(const_iterator __pos, _Args&&... __args) - { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } - - //@{ - /** - * @brief Inserts an element into the %unordered_multiset. - * @param __x Element to be inserted. - * @return An iterator that points to the inserted element. - * - * Insertion requires amortized constant time. - */ - iterator - insert(const value_type& __x) - { return _M_h.insert(__x); } - - iterator - insert(value_type&& __x) - { return _M_h.insert(std::move(__x)); } - //@} - - //@{ - /** - * @brief Inserts an element into the %unordered_multiset. - * @param __hint An iterator that serves as a hint as to where the - * element should be inserted. - * @param __x Element to be inserted. - * @return An iterator that points to the inserted element. - * - * Note that the first parameter is only a hint and can potentially - * improve the performance of the insertion process. A bad hint would - * cause no gains in efficiency. - * - * For more on @a hinting, see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints - * - * Insertion requires amortized constant. - */ - iterator - insert(const_iterator __hint, const value_type& __x) - { return _M_h.insert(__hint, __x); } - - iterator - insert(const_iterator __hint, value_type&& __x) - { return _M_h.insert(__hint, std::move(__x)); } - //@} - - /** - * @brief A template function that inserts a range of elements. - * @param __first Iterator pointing to the start of the range to be - * inserted. - * @param __last Iterator pointing to the end of the range. - * - * Complexity similar to that of the range constructor. - */ - template - void - insert(_InputIterator __first, _InputIterator __last) - { _M_h.insert(__first, __last); } - - /** - * @brief Inserts a list of elements into the %unordered_multiset. - * @param __l A std::initializer_list of elements to be - * inserted. - * - * Complexity similar to that of the range constructor. - */ - void - insert(initializer_list __l) - { _M_h.insert(__l); } - -#if __cplusplus > 201402L - /// Extract a node. - node_type - extract(const_iterator __pos) - { - __glibcxx_assert(__pos != end()); - return _M_h.extract(__pos); - } - - /// Extract a node. - node_type - extract(const key_type& __key) - { return _M_h.extract(__key); } - - /// Re-insert an extracted node. - iterator - insert(node_type&& __nh) - { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); } - - /// Re-insert an extracted node. - iterator - insert(const_iterator __hint, node_type&& __nh) - { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } -#endif // C++17 - - //@{ - /** - * @brief Erases an element from an %unordered_multiset. - * @param __position An iterator pointing to the element to be erased. - * @return An iterator pointing to the element immediately following - * @a __position prior to the element being erased. If no such - * element exists, end() is returned. - * - * This function erases an element, pointed to by the given iterator, - * from an %unordered_multiset. - * - * Note that this function only erases the element, and that if the - * element is itself a pointer, the pointed-to memory is not touched in - * any way. Managing the pointer is the user's responsibility. - */ - iterator - erase(const_iterator __position) - { return _M_h.erase(__position); } - - // LWG 2059. - iterator - erase(iterator __position) - { return _M_h.erase(__position); } - //@} - - - /** - * @brief Erases elements according to the provided key. - * @param __x Key of element to be erased. - * @return The number of elements erased. - * - * This function erases all the elements located by the given key from - * an %unordered_multiset. - * - * Note that this function only erases the element, and that if the - * element is itself a pointer, the pointed-to memory is not touched in - * any way. Managing the pointer is the user's responsibility. - */ - size_type - erase(const key_type& __x) - { return _M_h.erase(__x); } - - /** - * @brief Erases a [__first,__last) range of elements from an - * %unordered_multiset. - * @param __first Iterator pointing to the start of the range to be - * erased. - * @param __last Iterator pointing to the end of the range to - * be erased. - * @return The iterator @a __last. - * - * This function erases a sequence of elements from an - * %unordered_multiset. - * - * Note that this function only erases the element, and that if - * the element is itself a pointer, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - iterator - erase(const_iterator __first, const_iterator __last) - { return _M_h.erase(__first, __last); } - - /** - * Erases all elements in an %unordered_multiset. - * - * Note that this function only erases the elements, and that if the - * elements themselves are pointers, the pointed-to memory is not touched - * in any way. Managing the pointer is the user's responsibility. - */ - void - clear() noexcept - { _M_h.clear(); } - - /** - * @brief Swaps data with another %unordered_multiset. - * @param __x An %unordered_multiset of the same element and allocator - * types. - * - * This exchanges the elements between two sets in constant time. - * Note that the global std::swap() function is specialized such that - * std::swap(s1,s2) will feed to this function. - */ - void - swap(unordered_multiset& __x) - noexcept( noexcept(_M_h.swap(__x._M_h)) ) - { _M_h.swap(__x._M_h); } - -#if __cplusplus > 201402L - template - friend class std::_Hash_merge_helper; - - template - void - merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) - { - using _Merge_helper - = _Hash_merge_helper; - _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); - } - - template - void - merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) - { merge(__source); } - - template - void - merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) - { - using _Merge_helper - = _Hash_merge_helper; - _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); - } - - template - void - merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) - { merge(__source); } -#endif // C++17 - - // observers. - - /// Returns the hash functor object with which the %unordered_multiset - /// was constructed. - hasher - hash_function() const - { return _M_h.hash_function(); } - - /// Returns the key comparison object with which the %unordered_multiset - /// was constructed. - key_equal - key_eq() const - { return _M_h.key_eq(); } - - // lookup. - - //@{ - /** - * @brief Tries to locate an element in an %unordered_multiset. - * @param __x Element to be located. - * @return Iterator pointing to sought-after element, or end() if not - * found. - * - * This function takes a key and tries to locate the element with which - * the key matches. If successful the function returns an iterator - * pointing to the sought after element. If unsuccessful it returns the - * past-the-end ( @c end() ) iterator. - */ - iterator - find(const key_type& __x) - { return _M_h.find(__x); } - - const_iterator - find(const key_type& __x) const - { return _M_h.find(__x); } - //@} - - /** - * @brief Finds the number of elements. - * @param __x Element to located. - * @return Number of elements with specified key. - */ - size_type - count(const key_type& __x) const - { return _M_h.count(__x); } - -#if __cplusplus > 201703L - /** - * @brief Finds whether an element with the given key exists. - * @param __x Key of elements to be located. - * @return True if there is any element with the specified key. - */ - bool - contains(const key_type& __x) const - { return _M_h.find(__x) != _M_h.end(); } -#endif - - //@{ - /** - * @brief Finds a subsequence matching given key. - * @param __x Key to be located. - * @return Pair of iterators that possibly points to the subsequence - * matching given key. - */ - std::pair - equal_range(const key_type& __x) - { return _M_h.equal_range(__x); } - - std::pair - equal_range(const key_type& __x) const - { return _M_h.equal_range(__x); } - //@} - - // bucket interface. - - /// Returns the number of buckets of the %unordered_multiset. - size_type - bucket_count() const noexcept - { return _M_h.bucket_count(); } - - /// Returns the maximum number of buckets of the %unordered_multiset. - size_type - max_bucket_count() const noexcept - { return _M_h.max_bucket_count(); } - - /* - * @brief Returns the number of elements in a given bucket. - * @param __n A bucket index. - * @return The number of elements in the bucket. - */ - size_type - bucket_size(size_type __n) const - { return _M_h.bucket_size(__n); } - - /* - * @brief Returns the bucket index of a given element. - * @param __key A key instance. - * @return The key bucket index. - */ - size_type - bucket(const key_type& __key) const - { return _M_h.bucket(__key); } - - //@{ - /** - * @brief Returns a read-only (constant) iterator pointing to the first - * bucket element. - * @param __n The bucket index. - * @return A read-only local iterator. - */ - local_iterator - begin(size_type __n) - { return _M_h.begin(__n); } - - const_local_iterator - begin(size_type __n) const - { return _M_h.begin(__n); } - - const_local_iterator - cbegin(size_type __n) const - { return _M_h.cbegin(__n); } - //@} - - //@{ - /** - * @brief Returns a read-only (constant) iterator pointing to one past - * the last bucket elements. - * @param __n The bucket index. - * @return A read-only local iterator. - */ - local_iterator - end(size_type __n) - { return _M_h.end(__n); } - - const_local_iterator - end(size_type __n) const - { return _M_h.end(__n); } - - const_local_iterator - cend(size_type __n) const - { return _M_h.cend(__n); } - //@} - - // hash policy. - - /// Returns the average number of elements per bucket. - float - load_factor() const noexcept - { return _M_h.load_factor(); } - - /// Returns a positive number that the %unordered_multiset tries to keep the - /// load factor less than or equal to. - float - max_load_factor() const noexcept - { return _M_h.max_load_factor(); } - - /** - * @brief Change the %unordered_multiset maximum load factor. - * @param __z The new maximum load factor. - */ - void - max_load_factor(float __z) - { _M_h.max_load_factor(__z); } - - /** - * @brief May rehash the %unordered_multiset. - * @param __n The new number of buckets. - * - * Rehash will occur only if the new number of buckets respect the - * %unordered_multiset maximum load factor. - */ - void - rehash(size_type __n) - { _M_h.rehash(__n); } - - /** - * @brief Prepare the %unordered_multiset for a specified number of - * elements. - * @param __n Number of elements required. - * - * Same as rehash(ceil(n / max_load_factor())). - */ - void - reserve(size_type __n) - { _M_h.reserve(__n); } - - template - friend bool - operator==(const unordered_multiset<_Value1, _Hash1, _Pred1, _Alloc1>&, - const unordered_multiset<_Value1, _Hash1, _Pred1, _Alloc1>&); - }; - - -#if __cpp_deduction_guides >= 201606 - - template::value_type>, - typename _Pred = - equal_to::value_type>, - typename _Allocator = - allocator::value_type>, - typename = _RequireInputIter<_InputIterator>, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireNotAllocator<_Pred>, - typename = _RequireAllocator<_Allocator>> - unordered_multiset(_InputIterator, _InputIterator, - unordered_multiset::size_type = {}, - _Hash = _Hash(), _Pred = _Pred(), - _Allocator = _Allocator()) - -> unordered_multiset::value_type, - _Hash, _Pred, _Allocator>; - - template, - typename _Pred = equal_to<_Tp>, - typename _Allocator = allocator<_Tp>, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireNotAllocator<_Pred>, - typename = _RequireAllocator<_Allocator>> - unordered_multiset(initializer_list<_Tp>, - unordered_multiset::size_type = {}, - _Hash = _Hash(), _Pred = _Pred(), - _Allocator = _Allocator()) - -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_multiset(_InputIterator, _InputIterator, - unordered_multiset::size_type, _Allocator) - -> unordered_multiset::value_type, - hash::value_type>, - equal_to::value_type>, - _Allocator>; - - template, - typename = _RequireNotAllocatorOrIntegral<_Hash>, - typename = _RequireAllocator<_Allocator>> - unordered_multiset(_InputIterator, _InputIterator, - unordered_multiset::size_type, - _Hash, _Allocator) - -> unordered_multiset::value_type, - _Hash, - equal_to< - typename - iterator_traits<_InputIterator>::value_type>, - _Allocator>; - - template> - unordered_multiset(initializer_list<_Tp>, - unordered_multiset::size_type, _Allocator) - -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; - - template, - typename = _RequireAllocator<_Allocator>> - unordered_multiset(initializer_list<_Tp>, - unordered_multiset::size_type, _Hash, _Allocator) - -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; - -#endif - - template - inline void - swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, - unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - template - inline void - swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, - unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - - template - inline bool - operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, - const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) - { return __x._M_h._M_equal(__y._M_h); } - -#if __cpp_impl_three_way_comparison < 201907L - template - inline bool - operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, - const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) - { return !(__x == __y); } -#endif - - template - inline bool - operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, - const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) - { return __x._M_h._M_equal(__y._M_h); } - -#if __cpp_impl_three_way_comparison < 201907L - template - inline bool - operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, - const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) - { return !(__x == __y); } -#endif - -_GLIBCXX_END_NAMESPACE_CONTAINER - -#if __cplusplus > 201402L - // Allow std::unordered_set access to internals of compatible sets. - template - struct _Hash_merge_helper< - _GLIBCXX_STD_C::unordered_set<_Val, _Hash1, _Eq1, _Alloc>, _Hash2, _Eq2> - { - private: - template - using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>; - template - using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>; - - friend unordered_set<_Val, _Hash1, _Eq1, _Alloc>; - - static auto& - _S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set) - { return __set._M_h; } - - static auto& - _S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set) - { return __set._M_h; } - }; - - // Allow std::unordered_multiset access to internals of compatible sets. - template - struct _Hash_merge_helper< - _GLIBCXX_STD_C::unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>, - _Hash2, _Eq2> - { - private: - template - using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>; - template - using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>; - - friend unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>; - - static auto& - _S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set) - { return __set._M_h; } - - static auto& - _S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set) - { return __set._M_h; } - }; -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _UNORDERED_SET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h b/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h deleted file mode 100644 index 1832d40d6..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h +++ /dev/null @@ -1,195 +0,0 @@ -// Uses-allocator Construction -*- C++ -*- - -// Copyright (C) 2010-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -#ifndef _USES_ALLOCATOR_H -#define _USES_ALLOCATOR_H 1 - -#if __cplusplus < 201103L -# include -#else - -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // This is used for std::experimental::erased_type from Library Fundamentals. - struct __erased_type { }; - - // This also supports the "type-erased allocator" protocol from the - // Library Fundamentals TS, where allocator_type is erased_type. - // The second condition will always be false for types not using the TS. - template - using __is_erased_or_convertible - = __or_, is_same<_Tp, __erased_type>>; - - /// [allocator.tag] - struct allocator_arg_t { explicit allocator_arg_t() = default; }; - - _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg = - allocator_arg_t(); - - template> - struct __uses_allocator_helper - : false_type { }; - - template - struct __uses_allocator_helper<_Tp, _Alloc, - __void_t> - : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type - { }; - - /// [allocator.uses.trait] - template - struct uses_allocator - : __uses_allocator_helper<_Tp, _Alloc>::type - { }; - - struct __uses_alloc_base { }; - - struct __uses_alloc0 : __uses_alloc_base - { - struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a; - }; - - template - struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; }; - - template - struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; }; - - template - struct __uses_alloc; - - template - struct __uses_alloc - : conditional< - is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value, - __uses_alloc1<_Alloc>, - __uses_alloc2<_Alloc>>::type - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2586. Wrong value category used in scoped_allocator_adaptor::construct - static_assert(__or_< - is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>, - is_constructible<_Tp, _Args..., const _Alloc&>>::value, - "construction with an allocator must be possible" - " if uses_allocator is true"); - }; - - template - struct __uses_alloc - : __uses_alloc0 { }; - - template - using __uses_alloc_t = - __uses_alloc::value, _Tp, _Alloc, _Args...>; - - template - _GLIBCXX20_CONSTEXPR - inline __uses_alloc_t<_Tp, _Alloc, _Args...> - __use_alloc(const _Alloc& __a) - { - __uses_alloc_t<_Tp, _Alloc, _Args...> __ret; - __ret._M_a = std::__addressof(__a); - return __ret; - } - - template - void - __use_alloc(const _Alloc&&) = delete; - -#if __cplusplus > 201402L - template - inline constexpr bool uses_allocator_v = - uses_allocator<_Tp, _Alloc>::value; -#endif // C++17 - - template class _Predicate, - typename _Tp, typename _Alloc, typename... _Args> - struct __is_uses_allocator_predicate - : conditional::value, - __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>, - _Predicate<_Tp, _Args..., _Alloc>>, - _Predicate<_Tp, _Args...>>::type { }; - - template - struct __is_uses_allocator_constructible - : __is_uses_allocator_predicate - { }; - -#if __cplusplus >= 201402L - template - _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v = - __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; -#endif // C++14 - - template - struct __is_nothrow_uses_allocator_constructible - : __is_uses_allocator_predicate - { }; - - -#if __cplusplus >= 201402L - template - _GLIBCXX17_INLINE constexpr bool - __is_nothrow_uses_allocator_constructible_v = - __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; -#endif // C++14 - - template - void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr, - _Args&&... __args) - { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); } - - template - void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr, - _Args&&... __args) - { - ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a, - std::forward<_Args>(__args)...); - } - - template - void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr, - _Args&&... __args) - { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); } - - template - void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr, - _Args&&... __args) - { - std::__uses_allocator_construct_impl( - std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr, - std::forward<_Args>(__args)...); - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif -#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_after.h b/resources/sources/avr-libstdcpp/include/bits/valarray_after.h deleted file mode 100644 index cf84e17e5..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/valarray_after.h +++ /dev/null @@ -1,556 +0,0 @@ -// The template and inlines for the -*- C++ -*- internal _Meta class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/valarray_after.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _VALARRAY_AFTER_H -#define _VALARRAY_AFTER_H 1 - -#pragma GCC system_header - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -namespace __detail -{ - // - // gslice_array closure. - // - template - class _GBase - { - public: - typedef typename _Dom::value_type value_type; - - _GBase (const _Dom& __e, const valarray& __i) - : _M_expr (__e), _M_index(__i) {} - - value_type - operator[] (size_t __i) const - { return _M_expr[_M_index[__i]]; } - - size_t - size () const - { return _M_index.size(); } - - private: - typename _ValArrayRef<_Dom>::__type _M_expr; - const valarray& _M_index; - }; - - template - class _GBase<_Array<_Tp> > - { - public: - typedef _Tp value_type; - - _GBase (_Array<_Tp> __a, const valarray& __i) - : _M_array (__a), _M_index(__i) {} - - value_type - operator[] (size_t __i) const - { return _M_array._M_data[_M_index[__i]]; } - - size_t - size () const - { return _M_index.size(); } - - private: - const _Array<_Tp> _M_array; - const valarray& _M_index; - }; - - template - struct _GClos<_Expr, _Dom> - : _GBase<_Dom> - { - typedef _GBase<_Dom> _Base; - typedef typename _Base::value_type value_type; - - _GClos (const _Dom& __e, const valarray& __i) - : _Base (__e, __i) {} - }; - - template - struct _GClos<_ValArray, _Tp> - : _GBase<_Array<_Tp> > - { - typedef _GBase<_Array<_Tp> > _Base; - typedef typename _Base::value_type value_type; - - _GClos (_Array<_Tp> __a, const valarray& __i) - : _Base (__a, __i) {} - }; - - // - // indirect_array closure - // - template - class _IBase - { - public: - typedef typename _Dom::value_type value_type; - - _IBase (const _Dom& __e, const valarray& __i) - : _M_expr (__e), _M_index (__i) {} - - value_type - operator[] (size_t __i) const - { return _M_expr[_M_index[__i]]; } - - size_t - size() const - { return _M_index.size(); } - - private: - typename _ValArrayRef<_Dom>::__type _M_expr; - const valarray& _M_index; - }; - - template - struct _IClos<_Expr, _Dom> - : _IBase<_Dom> - { - typedef _IBase<_Dom> _Base; - typedef typename _Base::value_type value_type; - - _IClos (const _Dom& __e, const valarray& __i) - : _Base (__e, __i) {} - }; - - template - struct _IClos<_ValArray, _Tp> - : _IBase > - { - typedef _IBase > _Base; - typedef _Tp value_type; - - _IClos (const valarray<_Tp>& __a, const valarray& __i) - : _Base (__a, __i) {} - }; -} // namespace __detail - - // - // class _Expr - // - template - class _Expr - { - public: - typedef _Tp value_type; - - _Expr(const _Clos&); - - const _Clos& operator()() const; - - value_type operator[](size_t) const; - valarray operator[](slice) const; - valarray operator[](const gslice&) const; - valarray operator[](const valarray&) const; - valarray operator[](const valarray&) const; - - _Expr<_UnClos<__unary_plus, std::_Expr, _Clos>, value_type> - operator+() const; - - _Expr<_UnClos<__negate, std::_Expr, _Clos>, value_type> - operator-() const; - - _Expr<_UnClos<__bitwise_not, std::_Expr, _Clos>, value_type> - operator~() const; - - _Expr<_UnClos<__logical_not, std::_Expr, _Clos>, bool> - operator!() const; - - size_t size() const; - value_type sum() const; - - valarray shift(int) const; - valarray cshift(int) const; - - value_type min() const; - value_type max() const; - - valarray apply(value_type (*)(const value_type&)) const; - valarray apply(value_type (*)(value_type)) const; - - private: - const _Clos _M_closure; - }; - - template - inline - _Expr<_Clos, _Tp>::_Expr(const _Clos& __c) : _M_closure(__c) {} - - template - inline const _Clos& - _Expr<_Clos, _Tp>::operator()() const - { return _M_closure; } - - template - inline _Tp - _Expr<_Clos, _Tp>::operator[](size_t __i) const - { return _M_closure[__i]; } - - template - inline valarray<_Tp> - _Expr<_Clos, _Tp>::operator[](slice __s) const - { - valarray<_Tp> __v = valarray<_Tp>(*this)[__s]; - return __v; - } - - template - inline valarray<_Tp> - _Expr<_Clos, _Tp>::operator[](const gslice& __gs) const - { - valarray<_Tp> __v = valarray<_Tp>(*this)[__gs]; - return __v; - } - - template - inline valarray<_Tp> - _Expr<_Clos, _Tp>::operator[](const valarray& __m) const - { - valarray<_Tp> __v = valarray<_Tp>(*this)[__m]; - return __v; - } - - template - inline valarray<_Tp> - _Expr<_Clos, _Tp>::operator[](const valarray& __i) const - { - valarray<_Tp> __v = valarray<_Tp>(*this)[__i]; - return __v; - } - - template - inline size_t - _Expr<_Clos, _Tp>::size() const - { return _M_closure.size(); } - - template - inline valarray<_Tp> - _Expr<_Clos, _Tp>::shift(int __n) const - { - valarray<_Tp> __v = valarray<_Tp>(*this).shift(__n); - return __v; - } - - template - inline valarray<_Tp> - _Expr<_Clos, _Tp>::cshift(int __n) const - { - valarray<_Tp> __v = valarray<_Tp>(*this).cshift(__n); - return __v; - } - - template - inline valarray<_Tp> - _Expr<_Clos, _Tp>::apply(_Tp __f(const _Tp&)) const - { - valarray<_Tp> __v = valarray<_Tp>(*this).apply(__f); - return __v; - } - - template - inline valarray<_Tp> - _Expr<_Clos, _Tp>::apply(_Tp __f(_Tp)) const - { - valarray<_Tp> __v = valarray<_Tp>(*this).apply(__f); - return __v; - } - - // XXX: replace this with a more robust summation algorithm. - template - inline _Tp - _Expr<_Clos, _Tp>::sum() const - { - size_t __n = _M_closure.size(); - if (__n == 0) - return _Tp(); - else - { - _Tp __s = _M_closure[--__n]; - while (__n != 0) - __s += _M_closure[--__n]; - return __s; - } - } - - template - inline _Tp - _Expr<_Clos, _Tp>::min() const - { return __valarray_min(_M_closure); } - - template - inline _Tp - _Expr<_Clos, _Tp>::max() const - { return __valarray_max(_M_closure); } - - template - inline _Expr<_UnClos<__logical_not, _Expr, _Dom>, bool> - _Expr<_Dom, _Tp>::operator!() const - { - typedef _UnClos<__logical_not, std::_Expr, _Dom> _Closure; - return _Expr<_Closure, bool>(_Closure(this->_M_closure)); - } - -#define _DEFINE_EXPR_UNARY_OPERATOR(_Op, _Name) \ - template \ - inline _Expr<_UnClos<_Name, std::_Expr, _Dom>, _Tp> \ - _Expr<_Dom, _Tp>::operator _Op() const \ - { \ - typedef _UnClos<_Name, std::_Expr, _Dom> _Closure; \ - return _Expr<_Closure, _Tp>(_Closure(this->_M_closure)); \ - } - - _DEFINE_EXPR_UNARY_OPERATOR(+, __unary_plus) - _DEFINE_EXPR_UNARY_OPERATOR(-, __negate) - _DEFINE_EXPR_UNARY_OPERATOR(~, __bitwise_not) - -#undef _DEFINE_EXPR_UNARY_OPERATOR - -#define _DEFINE_EXPR_BINARY_OPERATOR(_Op, _Name) \ - template \ - inline _Expr<_BinClos<_Name, _Expr, _Expr, _Dom1, _Dom2>, \ - typename __fun<_Name, typename _Dom1::value_type>::result_type> \ - operator _Op(const _Expr<_Dom1, typename _Dom1::value_type>& __v, \ - const _Expr<_Dom2, typename _Dom2::value_type>& __w) \ - { \ - typedef typename _Dom1::value_type _Arg; \ - typedef typename __fun<_Name, _Arg>::result_type _Value; \ - typedef _BinClos<_Name, _Expr, _Expr, _Dom1, _Dom2> _Closure; \ - return _Expr<_Closure, _Value>(_Closure(__v(), __w())); \ - } \ - \ - template \ - inline _Expr<_BinClos<_Name, _Expr, _Constant, _Dom, \ - typename _Dom::value_type>, \ - typename __fun<_Name, typename _Dom::value_type>::result_type> \ - operator _Op(const _Expr<_Dom, typename _Dom::value_type>& __v, \ - const typename _Dom::value_type& __t) \ - { \ - typedef typename _Dom::value_type _Arg; \ - typedef typename __fun<_Name, _Arg>::result_type _Value; \ - typedef _BinClos<_Name, _Expr, _Constant, _Dom, _Arg> _Closure; \ - return _Expr<_Closure, _Value>(_Closure(__v(), __t)); \ - } \ - \ - template \ - inline _Expr<_BinClos<_Name, _Constant, _Expr, \ - typename _Dom::value_type, _Dom>, \ - typename __fun<_Name, typename _Dom::value_type>::result_type> \ - operator _Op(const typename _Dom::value_type& __t, \ - const _Expr<_Dom, typename _Dom::value_type>& __v) \ - { \ - typedef typename _Dom::value_type _Arg; \ - typedef typename __fun<_Name, _Arg>::result_type _Value; \ - typedef _BinClos<_Name, _Constant, _Expr, _Arg, _Dom> _Closure; \ - return _Expr<_Closure, _Value>(_Closure(__t, __v())); \ - } \ - \ - template \ - inline _Expr<_BinClos<_Name, _Expr, _ValArray, \ - _Dom, typename _Dom::value_type>, \ - typename __fun<_Name, typename _Dom::value_type>::result_type> \ - operator _Op(const _Expr<_Dom,typename _Dom::value_type>& __e, \ - const valarray& __v) \ - { \ - typedef typename _Dom::value_type _Arg; \ - typedef typename __fun<_Name, _Arg>::result_type _Value; \ - typedef _BinClos<_Name, _Expr, _ValArray, _Dom, _Arg> _Closure; \ - return _Expr<_Closure, _Value>(_Closure(__e(), __v)); \ - } \ - \ - template \ - inline _Expr<_BinClos<_Name, _ValArray, _Expr, \ - typename _Dom::value_type, _Dom>, \ - typename __fun<_Name, typename _Dom::value_type>::result_type> \ - operator _Op(const valarray& __v, \ - const _Expr<_Dom, typename _Dom::value_type>& __e) \ - { \ - typedef typename _Dom::value_type _Tp; \ - typedef typename __fun<_Name, _Tp>::result_type _Value; \ - typedef _BinClos<_Name, _ValArray, _Expr, _Tp, _Dom> _Closure; \ - return _Expr<_Closure, _Value>(_Closure(__v, __e ())); \ - } - - _DEFINE_EXPR_BINARY_OPERATOR(+, __plus) - _DEFINE_EXPR_BINARY_OPERATOR(-, __minus) - _DEFINE_EXPR_BINARY_OPERATOR(*, __multiplies) - _DEFINE_EXPR_BINARY_OPERATOR(/, __divides) - _DEFINE_EXPR_BINARY_OPERATOR(%, __modulus) - _DEFINE_EXPR_BINARY_OPERATOR(^, __bitwise_xor) - _DEFINE_EXPR_BINARY_OPERATOR(&, __bitwise_and) - _DEFINE_EXPR_BINARY_OPERATOR(|, __bitwise_or) - _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left) - _DEFINE_EXPR_BINARY_OPERATOR(>>, __shift_right) - _DEFINE_EXPR_BINARY_OPERATOR(&&, __logical_and) - _DEFINE_EXPR_BINARY_OPERATOR(||, __logical_or) - _DEFINE_EXPR_BINARY_OPERATOR(==, __equal_to) - _DEFINE_EXPR_BINARY_OPERATOR(!=, __not_equal_to) - _DEFINE_EXPR_BINARY_OPERATOR(<, __less) - _DEFINE_EXPR_BINARY_OPERATOR(>, __greater) - _DEFINE_EXPR_BINARY_OPERATOR(<=, __less_equal) - _DEFINE_EXPR_BINARY_OPERATOR(>=, __greater_equal) - -#undef _DEFINE_EXPR_BINARY_OPERATOR - -#define _DEFINE_EXPR_UNARY_FUNCTION(_Name, _UName) \ - template \ - inline _Expr<_UnClos<_UName, _Expr, _Dom>, \ - typename _Dom::value_type> \ - _Name(const _Expr<_Dom, typename _Dom::value_type>& __e) \ - { \ - typedef typename _Dom::value_type _Tp; \ - typedef _UnClos<_UName, _Expr, _Dom> _Closure; \ - return _Expr<_Closure, _Tp>(_Closure(__e())); \ - } \ - \ - template \ - inline _Expr<_UnClos<_UName, _ValArray, _Tp>, _Tp> \ - _Name(const valarray<_Tp>& __v) \ - { \ - typedef _UnClos<_UName, _ValArray, _Tp> _Closure; \ - return _Expr<_Closure, _Tp>(_Closure(__v)); \ - } - - _DEFINE_EXPR_UNARY_FUNCTION(abs, _Abs) - _DEFINE_EXPR_UNARY_FUNCTION(cos, _Cos) - _DEFINE_EXPR_UNARY_FUNCTION(acos, _Acos) - _DEFINE_EXPR_UNARY_FUNCTION(cosh, _Cosh) - _DEFINE_EXPR_UNARY_FUNCTION(sin, _Sin) - _DEFINE_EXPR_UNARY_FUNCTION(asin, _Asin) - _DEFINE_EXPR_UNARY_FUNCTION(sinh, _Sinh) - _DEFINE_EXPR_UNARY_FUNCTION(tan, _Tan) - _DEFINE_EXPR_UNARY_FUNCTION(tanh, _Tanh) - _DEFINE_EXPR_UNARY_FUNCTION(atan, _Atan) - _DEFINE_EXPR_UNARY_FUNCTION(exp, _Exp) - _DEFINE_EXPR_UNARY_FUNCTION(log, _Log) - _DEFINE_EXPR_UNARY_FUNCTION(log10, _Log10) - _DEFINE_EXPR_UNARY_FUNCTION(sqrt, _Sqrt) - -#undef _DEFINE_EXPR_UNARY_FUNCTION - -#define _DEFINE_EXPR_BINARY_FUNCTION(_Fun, _UFun) \ - template \ - inline _Expr<_BinClos<_UFun, _Expr, _Expr, _Dom1, _Dom2>, \ - typename _Dom1::value_type> \ - _Fun(const _Expr<_Dom1, typename _Dom1::value_type>& __e1, \ - const _Expr<_Dom2, typename _Dom2::value_type>& __e2) \ - { \ - typedef typename _Dom1::value_type _Tp; \ - typedef _BinClos<_UFun, _Expr, _Expr, _Dom1, _Dom2> _Closure; \ - return _Expr<_Closure, _Tp>(_Closure(__e1(), __e2())); \ - } \ - \ - template \ - inline _Expr<_BinClos<_UFun, _Expr, _ValArray, _Dom, \ - typename _Dom::value_type>, \ - typename _Dom::value_type> \ - _Fun(const _Expr<_Dom, typename _Dom::value_type>& __e, \ - const valarray& __v) \ - { \ - typedef typename _Dom::value_type _Tp; \ - typedef _BinClos<_UFun, _Expr, _ValArray, _Dom, _Tp> _Closure; \ - return _Expr<_Closure, _Tp>(_Closure(__e(), __v)); \ - } \ - \ - template \ - inline _Expr<_BinClos<_UFun, _ValArray, _Expr, \ - typename _Dom::value_type, _Dom>, \ - typename _Dom::value_type> \ - _Fun(const valarray& __v, \ - const _Expr<_Dom, typename _Dom::value_type>& __e) \ - { \ - typedef typename _Dom::value_type _Tp; \ - typedef _BinClos<_UFun, _ValArray, _Expr, _Tp, _Dom> _Closure; \ - return _Expr<_Closure, _Tp>(_Closure(__v, __e())); \ - } \ - \ - template \ - inline _Expr<_BinClos<_UFun, _Expr, _Constant, _Dom, \ - typename _Dom::value_type>, \ - typename _Dom::value_type> \ - _Fun(const _Expr<_Dom, typename _Dom::value_type>& __e, \ - const typename _Dom::value_type& __t) \ - { \ - typedef typename _Dom::value_type _Tp; \ - typedef _BinClos<_UFun, _Expr, _Constant, _Dom, _Tp> _Closure; \ - return _Expr<_Closure, _Tp>(_Closure(__e(), __t)); \ - } \ - \ - template \ - inline _Expr<_BinClos<_UFun, _Constant, _Expr, \ - typename _Dom::value_type, _Dom>, \ - typename _Dom::value_type> \ - _Fun(const typename _Dom::value_type& __t, \ - const _Expr<_Dom, typename _Dom::value_type>& __e) \ - { \ - typedef typename _Dom::value_type _Tp; \ - typedef _BinClos<_UFun, _Constant, _Expr, _Tp, _Dom> _Closure; \ - return _Expr<_Closure, _Tp>(_Closure(__t, __e())); \ - } \ - \ - template \ - inline _Expr<_BinClos<_UFun, _ValArray, _ValArray, _Tp, _Tp>, _Tp> \ - _Fun(const valarray<_Tp>& __v, const valarray<_Tp>& __w) \ - { \ - typedef _BinClos<_UFun, _ValArray, _ValArray, _Tp, _Tp> _Closure;\ - return _Expr<_Closure, _Tp>(_Closure(__v, __w)); \ - } \ - \ - template \ - inline _Expr<_BinClos<_UFun, _ValArray, _Constant, _Tp, _Tp>, _Tp> \ - _Fun(const valarray<_Tp>& __v, \ - const typename valarray<_Tp>::value_type& __t) \ - { \ - typedef _BinClos<_UFun, _ValArray, _Constant, _Tp, _Tp> _Closure;\ - return _Expr<_Closure, _Tp>(_Closure(__v, __t)); \ - } \ - \ - template \ - inline _Expr<_BinClos<_UFun, _Constant, _ValArray, _Tp, _Tp>, _Tp> \ - _Fun(const typename valarray<_Tp>::value_type& __t, \ - const valarray<_Tp>& __v) \ - { \ - typedef _BinClos<_UFun, _Constant, _ValArray, _Tp, _Tp> _Closure;\ - return _Expr<_Closure, _Tp>(_Closure(__t, __v)); \ - } - -_DEFINE_EXPR_BINARY_FUNCTION(atan2, _Atan2) -_DEFINE_EXPR_BINARY_FUNCTION(pow, _Pow) - -#undef _DEFINE_EXPR_BINARY_FUNCTION - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _CPP_VALARRAY_AFTER_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_array.h b/resources/sources/avr-libstdcpp/include/bits/valarray_array.h deleted file mode 100644 index 041fbbe25..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/valarray_array.h +++ /dev/null @@ -1,677 +0,0 @@ -// The template and inlines for the -*- C++ -*- internal _Array helper class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/valarray_array.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _VALARRAY_ARRAY_H -#define _VALARRAY_ARRAY_H 1 - -#pragma GCC system_header - -#include -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // - // Helper functions on raw pointers - // - - // We get memory the old fashioned way - template - _Tp* - __valarray_get_storage(size_t) __attribute__((__malloc__)); - - template - inline _Tp* - __valarray_get_storage(size_t __n) - { return static_cast<_Tp*>(operator new(__n * sizeof(_Tp))); } - - // Return memory to the system - inline void - __valarray_release_memory(void* __p) - { operator delete(__p); } - - // Turn a raw-memory into an array of _Tp filled with _Tp() - // This is required in 'valarray v(n);' - template - struct _Array_default_ctor - { - // Please note that this isn't exception safe. But - // valarrays aren't required to be exception safe. - inline static void - _S_do_it(_Tp* __b, _Tp* __e) - { - while (__b != __e) - new(__b++) _Tp(); - } - }; - - template - struct _Array_default_ctor<_Tp, true> - { - // For fundamental types, it suffices to say 'memset()' - inline static void - _S_do_it(_Tp* __b, _Tp* __e) - { __builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp)); } - }; - - template - inline void - __valarray_default_construct(_Tp* __b, _Tp* __e) - { - _Array_default_ctor<_Tp, __is_scalar<_Tp>::__value>::_S_do_it(__b, __e); - } - - // Turn a raw-memory into an array of _Tp filled with __t - // This is the required in valarray v(n, t). Also - // used in valarray<>::resize(). - template - struct _Array_init_ctor - { - // Please note that this isn't exception safe. But - // valarrays aren't required to be exception safe. - inline static void - _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t) - { - while (__b != __e) - new(__b++) _Tp(__t); - } - }; - - template - struct _Array_init_ctor<_Tp, true> - { - inline static void - _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t) - { - while (__b != __e) - *__b++ = __t; - } - }; - - template - inline void - __valarray_fill_construct(_Tp* __b, _Tp* __e, const _Tp __t) - { - _Array_init_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __t); - } - - // - // copy-construct raw array [__o, *) from plain array [__b, __e) - // We can't just say 'memcpy()' - // - template - struct _Array_copy_ctor - { - // Please note that this isn't exception safe. But - // valarrays aren't required to be exception safe. - inline static void - _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) - { - while (__b != __e) - new(__o++) _Tp(*__b++); - } - }; - - template - struct _Array_copy_ctor<_Tp, true> - { - inline static void - _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) - { - if (__b) - __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp)); - } - }; - - template - inline void - __valarray_copy_construct(const _Tp* __b, const _Tp* __e, - _Tp* __restrict__ __o) - { - _Array_copy_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __o); - } - - // copy-construct raw array [__o, *) from strided array __a[<__n : __s>] - template - inline void - __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n, - size_t __s, _Tp* __restrict__ __o) - { - if (__is_trivial(_Tp)) - while (__n--) - { - *__o++ = *__a; - __a += __s; - } - else - while (__n--) - { - new(__o++) _Tp(*__a); - __a += __s; - } - } - - // copy-construct raw array [__o, *) from indexed array __a[__i[<__n>]] - template - inline void - __valarray_copy_construct (const _Tp* __restrict__ __a, - const size_t* __restrict__ __i, - _Tp* __restrict__ __o, size_t __n) - { - if (__is_trivial(_Tp)) - while (__n--) - *__o++ = __a[*__i++]; - else - while (__n--) - new (__o++) _Tp(__a[*__i++]); - } - - // Do the necessary cleanup when we're done with arrays. - template - inline void - __valarray_destroy_elements(_Tp* __b, _Tp* __e) - { - if (!__is_trivial(_Tp)) - while (__b != __e) - { - __b->~_Tp(); - ++__b; - } - } - - // Fill a plain array __a[<__n>] with __t - template - inline void - __valarray_fill(_Tp* __restrict__ __a, size_t __n, const _Tp& __t) - { - while (__n--) - *__a++ = __t; - } - - // fill strided array __a[<__n-1 : __s>] with __t - template - inline void - __valarray_fill(_Tp* __restrict__ __a, size_t __n, - size_t __s, const _Tp& __t) - { - for (size_t __i = 0; __i < __n; ++__i, __a += __s) - *__a = __t; - } - - // fill indirect array __a[__i[<__n>]] with __i - template - inline void - __valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i, - size_t __n, const _Tp& __t) - { - for (size_t __j = 0; __j < __n; ++__j, ++__i) - __a[*__i] = __t; - } - - // copy plain array __a[<__n>] in __b[<__n>] - // For non-fundamental types, it is wrong to say 'memcpy()' - template - struct _Array_copier - { - inline static void - _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) - { - while(__n--) - *__b++ = *__a++; - } - }; - - template - struct _Array_copier<_Tp, true> - { - inline static void - _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) - { - if (__n != 0) - __builtin_memcpy(__b, __a, __n * sizeof (_Tp)); - } - }; - - // Copy a plain array __a[<__n>] into a play array __b[<>] - template - inline void - __valarray_copy(const _Tp* __restrict__ __a, size_t __n, - _Tp* __restrict__ __b) - { - _Array_copier<_Tp, __is_trivial(_Tp)>::_S_do_it(__a, __n, __b); - } - - // Copy strided array __a[<__n : __s>] in plain __b[<__n>] - template - inline void - __valarray_copy(const _Tp* __restrict__ __a, size_t __n, size_t __s, - _Tp* __restrict__ __b) - { - for (size_t __i = 0; __i < __n; ++__i, ++__b, __a += __s) - *__b = *__a; - } - - // Copy a plain array __a[<__n>] into a strided array __b[<__n : __s>] - template - inline void - __valarray_copy(const _Tp* __restrict__ __a, _Tp* __restrict__ __b, - size_t __n, size_t __s) - { - for (size_t __i = 0; __i < __n; ++__i, ++__a, __b += __s) - *__b = *__a; - } - - // Copy strided array __src[<__n : __s1>] into another - // strided array __dst[< : __s2>]. Their sizes must match. - template - inline void - __valarray_copy(const _Tp* __restrict__ __src, size_t __n, size_t __s1, - _Tp* __restrict__ __dst, size_t __s2) - { - for (size_t __i = 0; __i < __n; ++__i) - __dst[__i * __s2] = __src[__i * __s1]; - } - - // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] - template - inline void - __valarray_copy(const _Tp* __restrict__ __a, - const size_t* __restrict__ __i, - _Tp* __restrict__ __b, size_t __n) - { - for (size_t __j = 0; __j < __n; ++__j, ++__b, ++__i) - *__b = __a[*__i]; - } - - // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]] - template - inline void - __valarray_copy(const _Tp* __restrict__ __a, size_t __n, - _Tp* __restrict__ __b, const size_t* __restrict__ __i) - { - for (size_t __j = 0; __j < __n; ++__j, ++__a, ++__i) - __b[*__i] = *__a; - } - - // Copy the __n first elements of an indexed array __src[<__i>] into - // another indexed array __dst[<__j>]. - template - inline void - __valarray_copy(const _Tp* __restrict__ __src, size_t __n, - const size_t* __restrict__ __i, - _Tp* __restrict__ __dst, const size_t* __restrict__ __j) - { - for (size_t __k = 0; __k < __n; ++__k) - __dst[*__j++] = __src[*__i++]; - } - - // - // Compute the sum of elements in range [__f, __l) which must not be empty. - // This is a naive algorithm. It suffers from cancelling. - // In the future try to specialize for _Tp = float, double, long double - // using a more accurate algorithm. - // - template - inline _Tp - __valarray_sum(const _Tp* __f, const _Tp* __l) - { - _Tp __r = *__f++; - while (__f != __l) - __r += *__f++; - return __r; - } - - // Compute the min/max of an array-expression - template - inline typename _Ta::value_type - __valarray_min(const _Ta& __a) - { - size_t __s = __a.size(); - typedef typename _Ta::value_type _Value_type; - _Value_type __r = __s == 0 ? _Value_type() : __a[0]; - for (size_t __i = 1; __i < __s; ++__i) - { - _Value_type __t = __a[__i]; - if (__t < __r) - __r = __t; - } - return __r; - } - - template - inline typename _Ta::value_type - __valarray_max(const _Ta& __a) - { - size_t __s = __a.size(); - typedef typename _Ta::value_type _Value_type; - _Value_type __r = __s == 0 ? _Value_type() : __a[0]; - for (size_t __i = 1; __i < __s; ++__i) - { - _Value_type __t = __a[__i]; - if (__t > __r) - __r = __t; - } - return __r; - } - - // - // Helper class _Array, first layer of valarray abstraction. - // All operations on valarray should be forwarded to this class - // whenever possible. -- gdr - // - - template - struct _Array - { - explicit _Array(_Tp* const __restrict__); - explicit _Array(const valarray<_Tp>&); - _Array(const _Tp* __restrict__, size_t); - - _Tp* begin() const; - - _Tp* const __restrict__ _M_data; - }; - - - // Copy-construct plain array __b[<__n>] from indexed array __a[__i[<__n>]] - template - inline void - __valarray_copy_construct(_Array<_Tp> __a, _Array __i, - _Array<_Tp> __b, size_t __n) - { std::__valarray_copy_construct(__a._M_data, __i._M_data, - __b._M_data, __n); } - - // Copy-construct plain array __b[<__n>] from strided array __a[<__n : __s>] - template - inline void - __valarray_copy_construct(_Array<_Tp> __a, size_t __n, size_t __s, - _Array<_Tp> __b) - { std::__valarray_copy_construct(__a._M_data, __n, __s, __b._M_data); } - - template - inline void - __valarray_fill (_Array<_Tp> __a, size_t __n, const _Tp& __t) - { std::__valarray_fill(__a._M_data, __n, __t); } - - template - inline void - __valarray_fill(_Array<_Tp> __a, size_t __n, size_t __s, const _Tp& __t) - { std::__valarray_fill(__a._M_data, __n, __s, __t); } - - template - inline void - __valarray_fill(_Array<_Tp> __a, _Array __i, - size_t __n, const _Tp& __t) - { std::__valarray_fill(__a._M_data, __i._M_data, __n, __t); } - - // Copy a plain array __a[<__n>] into a play array __b[<>] - template - inline void - __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) - { std::__valarray_copy(__a._M_data, __n, __b._M_data); } - - // Copy strided array __a[<__n : __s>] in plain __b[<__n>] - template - inline void - __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s, _Array<_Tp> __b) - { std::__valarray_copy(__a._M_data, __n, __s, __b._M_data); } - - // Copy a plain array __a[<__n>] into a strided array __b[<__n : __s>] - template - inline void - __valarray_copy(_Array<_Tp> __a, _Array<_Tp> __b, size_t __n, size_t __s) - { __valarray_copy(__a._M_data, __b._M_data, __n, __s); } - - // Copy strided array __src[<__n : __s1>] into another - // strided array __dst[< : __s2>]. Their sizes must match. - template - inline void - __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s1, - _Array<_Tp> __b, size_t __s2) - { std::__valarray_copy(__a._M_data, __n, __s1, __b._M_data, __s2); } - - // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] - template - inline void - __valarray_copy(_Array<_Tp> __a, _Array __i, - _Array<_Tp> __b, size_t __n) - { std::__valarray_copy(__a._M_data, __i._M_data, __b._M_data, __n); } - - // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]] - template - inline void - __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, - _Array __i) - { std::__valarray_copy(__a._M_data, __n, __b._M_data, __i._M_data); } - - // Copy the __n first elements of an indexed array __src[<__i>] into - // another indexed array __dst[<__j>]. - template - inline void - __valarray_copy(_Array<_Tp> __src, size_t __n, _Array __i, - _Array<_Tp> __dst, _Array __j) - { - std::__valarray_copy(__src._M_data, __n, __i._M_data, - __dst._M_data, __j._M_data); - } - - template - inline - _Array<_Tp>::_Array(_Tp* const __restrict__ __p) - : _M_data (__p) {} - - template - inline - _Array<_Tp>::_Array(const valarray<_Tp>& __v) - : _M_data (__v._M_data) {} - - template - inline - _Array<_Tp>::_Array(const _Tp* __restrict__ __b, size_t __s) - : _M_data(__valarray_get_storage<_Tp>(__s)) - { std::__valarray_copy_construct(__b, __s, _M_data); } - - template - inline _Tp* - _Array<_Tp>::begin () const - { return _M_data; } - -#define _DEFINE_ARRAY_FUNCTION(_Op, _Name) \ - template \ - inline void \ - _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, const _Tp& __t) \ - { \ - for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; ++__p) \ - *__p _Op##= __t; \ - } \ - \ - template \ - inline void \ - _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) \ - { \ - _Tp* __p = __a._M_data; \ - for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; ++__p, ++__q) \ - *__p _Op##= *__q; \ - } \ - \ - template \ - void \ - _Array_augmented_##_Name(_Array<_Tp> __a, \ - const _Expr<_Dom, _Tp>& __e, size_t __n) \ - { \ - _Tp* __p(__a._M_data); \ - for (size_t __i = 0; __i < __n; ++__i, ++__p) \ - *__p _Op##= __e[__i]; \ - } \ - \ - template \ - inline void \ - _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, size_t __s, \ - _Array<_Tp> __b) \ - { \ - _Tp* __q(__b._M_data); \ - for (_Tp* __p = __a._M_data; __p < __a._M_data + __s * __n; \ - __p += __s, ++__q) \ - *__p _Op##= *__q; \ - } \ - \ - template \ - inline void \ - _Array_augmented_##_Name(_Array<_Tp> __a, _Array<_Tp> __b, \ - size_t __n, size_t __s) \ - { \ - _Tp* __q(__b._M_data); \ - for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; \ - ++__p, __q += __s) \ - *__p _Op##= *__q; \ - } \ - \ - template \ - void \ - _Array_augmented_##_Name(_Array<_Tp> __a, size_t __s, \ - const _Expr<_Dom, _Tp>& __e, size_t __n) \ - { \ - _Tp* __p(__a._M_data); \ - for (size_t __i = 0; __i < __n; ++__i, __p += __s) \ - *__p _Op##= __e[__i]; \ - } \ - \ - template \ - inline void \ - _Array_augmented_##_Name(_Array<_Tp> __a, _Array __i, \ - _Array<_Tp> __b, size_t __n) \ - { \ - _Tp* __q(__b._M_data); \ - for (size_t* __j = __i._M_data; __j < __i._M_data + __n; \ - ++__j, ++__q) \ - __a._M_data[*__j] _Op##= *__q; \ - } \ - \ - template \ - inline void \ - _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, \ - _Array<_Tp> __b, _Array __i) \ - { \ - _Tp* __p(__a._M_data); \ - for (size_t* __j = __i._M_data; __j<__i._M_data + __n; \ - ++__j, ++__p) \ - *__p _Op##= __b._M_data[*__j]; \ - } \ - \ - template \ - void \ - _Array_augmented_##_Name(_Array<_Tp> __a, _Array __i, \ - const _Expr<_Dom, _Tp>& __e, size_t __n) \ - { \ - size_t* __j(__i._M_data); \ - for (size_t __k = 0; __k<__n; ++__k, ++__j) \ - __a._M_data[*__j] _Op##= __e[__k]; \ - } \ - \ - template \ - void \ - _Array_augmented_##_Name(_Array<_Tp> __a, _Array __m, \ - _Array<_Tp> __b, size_t __n) \ - { \ - bool* __ok(__m._M_data); \ - _Tp* __p(__a._M_data); \ - for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; \ - ++__q, ++__ok, ++__p) \ - { \ - while (! *__ok) \ - { \ - ++__ok; \ - ++__p; \ - } \ - *__p _Op##= *__q; \ - } \ - } \ - \ - template \ - void \ - _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, \ - _Array<_Tp> __b, _Array __m) \ - { \ - bool* __ok(__m._M_data); \ - _Tp* __q(__b._M_data); \ - for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; \ - ++__p, ++__ok, ++__q) \ - { \ - while (! *__ok) \ - { \ - ++__ok; \ - ++__q; \ - } \ - *__p _Op##= *__q; \ - } \ - } \ - \ - template \ - void \ - _Array_augmented_##_Name(_Array<_Tp> __a, _Array __m, \ - const _Expr<_Dom, _Tp>& __e, size_t __n) \ - { \ - bool* __ok(__m._M_data); \ - _Tp* __p(__a._M_data); \ - for (size_t __i = 0; __i < __n; ++__i, ++__ok, ++__p) \ - { \ - while (! *__ok) \ - { \ - ++__ok; \ - ++__p; \ - } \ - *__p _Op##= __e[__i]; \ - } \ - } - - _DEFINE_ARRAY_FUNCTION(+, __plus) - _DEFINE_ARRAY_FUNCTION(-, __minus) - _DEFINE_ARRAY_FUNCTION(*, __multiplies) - _DEFINE_ARRAY_FUNCTION(/, __divides) - _DEFINE_ARRAY_FUNCTION(%, __modulus) - _DEFINE_ARRAY_FUNCTION(^, __bitwise_xor) - _DEFINE_ARRAY_FUNCTION(|, __bitwise_or) - _DEFINE_ARRAY_FUNCTION(&, __bitwise_and) - _DEFINE_ARRAY_FUNCTION(<<, __shift_left) - _DEFINE_ARRAY_FUNCTION(>>, __shift_right) - -#undef _DEFINE_ARRAY_FUNCTION - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -# include - -#endif /* _ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc b/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc deleted file mode 100644 index f97b780bc..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc +++ /dev/null @@ -1,244 +0,0 @@ -// The template and inlines for the -*- C++ -*- internal _Array helper class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/valarray_array.tcc - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _VALARRAY_ARRAY_TCC -#define _VALARRAY_ARRAY_TCC 1 - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template - void - __valarray_fill(_Array<_Tp> __a, size_t __n, _Array __m, - const _Tp& __t) - { - _Tp* __p = __a._M_data; - bool* __ok (__m._M_data); - for (size_t __i=0; __i < __n; ++__i, ++__ok, ++__p) - { - while (!*__ok) - { - ++__ok; - ++__p; - } - *__p = __t; - } - } - - // Copy n elements of a into consecutive elements of b. When m is - // false, the corresponding element of a is skipped. m must contain - // at least n true elements. a must contain at least n elements and - // enough elements to match up with m through the nth true element - // of m. I.e. if n is 10, m has 15 elements with 5 false followed - // by 10 true, a must have 15 elements. - template - void - __valarray_copy(_Array<_Tp> __a, _Array __m, _Array<_Tp> __b, - size_t __n) - { - _Tp* __p (__a._M_data); - bool* __ok (__m._M_data); - for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; - ++__q, ++__ok, ++__p) - { - while (! *__ok) - { - ++__ok; - ++__p; - } - *__q = *__p; - } - } - - // Copy n consecutive elements from a into elements of b. Elements - // of b are skipped if the corresponding element of m is false. m - // must contain at least n true elements. b must have at least as - // many elements as the index of the nth true element of m. I.e. if - // m has 15 elements with 5 false followed by 10 true, b must have - // at least 15 elements. - template - void - __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, - _Array __m) - { - _Tp* __q (__b._M_data); - bool* __ok (__m._M_data); - for (_Tp* __p = __a._M_data; __p < __a._M_data+__n; - ++__p, ++__ok, ++__q) - { - while (! *__ok) - { - ++__ok; - ++__q; - } - *__q = *__p; - } - } - - // Copy n elements from a into elements of b. Elements of a are - // skipped if the corresponding element of m is false. Elements of - // b are skipped if the corresponding element of k is false. m and - // k must contain at least n true elements. a and b must have at - // least as many elements as the index of the nth true element of m. - template - void - __valarray_copy(_Array<_Tp> __a, _Array __m, size_t __n, - _Array<_Tp> __b, _Array __k) - { - _Tp* __p (__a._M_data); - _Tp* __q (__b._M_data); - bool* __srcok (__m._M_data); - bool* __dstok (__k._M_data); - for (size_t __i = 0; __i < __n; - ++__srcok, ++__p, ++__dstok, ++__q, ++__i) - { - while (! *__srcok) - { - ++__srcok; - ++__p; - } - while (! *__dstok) - { - ++__dstok; - ++__q; - } - *__q = *__p; - } - } - - // Copy n consecutive elements of e into consecutive elements of a. - // I.e. a[i] = e[i]. - template - void - __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, _Array<_Tp> __a) - { - _Tp* __p (__a._M_data); - for (size_t __i = 0; __i < __n; ++__i, ++__p) - *__p = __e[__i]; - } - - // Copy n consecutive elements of e into elements of a using stride - // s. I.e., a[0] = e[0], a[s] = e[1], a[2*s] = e[2]. - template - void - __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, - _Array<_Tp> __a, size_t __s) - { - _Tp* __p (__a._M_data); - for (size_t __i = 0; __i < __n; ++__i, __p += __s) - *__p = __e[__i]; - } - - // Copy n consecutive elements of e into elements of a indexed by - // contents of i. I.e., a[i[0]] = e[0]. - template - void - __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, - _Array<_Tp> __a, _Array __i) - { - size_t* __j (__i._M_data); - for (size_t __k = 0; __k < __n; ++__k, ++__j) - __a._M_data[*__j] = __e[__k]; - } - - // Copy n elements of e indexed by contents of f into elements of a - // indexed by contents of i. I.e., a[i[0]] = e[f[0]]. - template - void - __valarray_copy(_Array<_Tp> __e, _Array __f, - size_t __n, - _Array<_Tp> __a, _Array __i) - { - size_t* __g (__f._M_data); - size_t* __j (__i._M_data); - for (size_t __k = 0; __k < __n; ++__k, ++__j, ++__g) - __a._M_data[*__j] = __e._M_data[*__g]; - } - - // Copy n consecutive elements of e into elements of a. Elements of - // a are skipped if the corresponding element of m is false. m must - // have at least n true elements and a must have at least as many - // elements as the index of the nth true element of m. I.e. if m - // has 5 false followed by 10 true elements and n == 10, a must have - // at least 15 elements. - template - void - __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, - _Array<_Tp> __a, _Array __m) - { - bool* __ok (__m._M_data); - _Tp* __p (__a._M_data); - for (size_t __i = 0; __i < __n; ++__i, ++__ok, ++__p) - { - while (! *__ok) - { - ++__ok; - ++__p; - } - *__p = __e[__i]; - } - } - - - template - void - __valarray_copy_construct(const _Expr<_Dom, _Tp>& __e, size_t __n, - _Array<_Tp> __a) - { - _Tp* __p (__a._M_data); - for (size_t __i = 0; __i < __n; ++__i, ++__p) - new (__p) _Tp(__e[__i]); - } - - - template - void - __valarray_copy_construct(_Array<_Tp> __a, _Array __m, - _Array<_Tp> __b, size_t __n) - { - _Tp* __p (__a._M_data); - bool* __ok (__m._M_data); - for (_Tp* __q = __b._M_data; __q < __b._M_data+__n; ++__q, ++__ok, ++__p) - { - while (! *__ok) - { - ++__ok; - ++__p; - } - new (__q) _Tp(*__p); - } - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _VALARRAY_ARRAY_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_before.h b/resources/sources/avr-libstdcpp/include/bits/valarray_before.h deleted file mode 100644 index 5c1c1c82a..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/valarray_before.h +++ /dev/null @@ -1,758 +0,0 @@ -// The template and inlines for the -*- C++ -*- internal _Meta class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file bits/valarray_before.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{valarray} - */ - -// Written by Gabriel Dos Reis - -#ifndef _VALARRAY_BEFORE_H -#define _VALARRAY_BEFORE_H 1 - -#pragma GCC system_header - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // - // Implementing a loosened valarray return value is tricky. - // First we need to meet 26.3.1/3: we should not add more than - // two levels of template nesting. Therefore we resort to template - // template to "flatten" loosened return value types. - // At some point we use partial specialization to remove one level - // template nesting due to _Expr<> - // - - // This class is NOT defined. It doesn't need to. - template class _Constant; - - // Implementations of unary functions applied to valarray<>s. - // I use hard-coded object functions here instead of a generic - // approach like pointers to function: - // 1) correctness: some functions take references, others values. - // we can't deduce the correct type afterwards. - // 2) efficiency -- object functions can be easily inlined - // 3) be Koenig-lookup-friendly - - struct _Abs - { - template - _Tp operator()(const _Tp& __t) const - { return abs(__t); } - }; - - struct _Cos - { - template - _Tp operator()(const _Tp& __t) const - { return cos(__t); } - }; - - struct _Acos - { - template - _Tp operator()(const _Tp& __t) const - { return acos(__t); } - }; - - struct _Cosh - { - template - _Tp operator()(const _Tp& __t) const - { return cosh(__t); } - }; - - struct _Sin - { - template - _Tp operator()(const _Tp& __t) const - { return sin(__t); } - }; - - struct _Asin - { - template - _Tp operator()(const _Tp& __t) const - { return asin(__t); } - }; - - struct _Sinh - { - template - _Tp operator()(const _Tp& __t) const - { return sinh(__t); } - }; - - struct _Tan - { - template - _Tp operator()(const _Tp& __t) const - { return tan(__t); } - }; - - struct _Atan - { - template - _Tp operator()(const _Tp& __t) const - { return atan(__t); } - }; - - struct _Tanh - { - template - _Tp operator()(const _Tp& __t) const - { return tanh(__t); } - }; - - struct _Exp - { - template - _Tp operator()(const _Tp& __t) const - { return exp(__t); } - }; - - struct _Log - { - template - _Tp operator()(const _Tp& __t) const - { return log(__t); } - }; - - struct _Log10 - { - template - _Tp operator()(const _Tp& __t) const - { return log10(__t); } - }; - - struct _Sqrt - { - template - _Tp operator()(const _Tp& __t) const - { return sqrt(__t); } - }; - - // In the past, we used to tailor operator applications semantics - // to the specialization of standard function objects (i.e. plus<>, etc.) - // That is incorrect. Therefore we provide our own surrogates. - - struct __unary_plus - { - template - _Tp operator()(const _Tp& __t) const - { return +__t; } - }; - - struct __negate - { - template - _Tp operator()(const _Tp& __t) const - { return -__t; } - }; - - struct __bitwise_not - { - template - _Tp operator()(const _Tp& __t) const - { return ~__t; } - }; - - struct __plus - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x + __y; } - }; - - struct __minus - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x - __y; } - }; - - struct __multiplies - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x * __y; } - }; - - struct __divides - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x / __y; } - }; - - struct __modulus - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x % __y; } - }; - - struct __bitwise_xor - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x ^ __y; } - }; - - struct __bitwise_and - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x & __y; } - }; - - struct __bitwise_or - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x | __y; } - }; - - struct __shift_left - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x << __y; } - }; - - struct __shift_right - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return __x >> __y; } - }; - - struct __logical_and - { - template - bool operator()(const _Tp& __x, const _Tp& __y) const - { return __x && __y; } - }; - - struct __logical_or - { - template - bool operator()(const _Tp& __x, const _Tp& __y) const - { return __x || __y; } - }; - - struct __logical_not - { - template - bool operator()(const _Tp& __x) const - { return !__x; } - }; - - struct __equal_to - { - template - bool operator()(const _Tp& __x, const _Tp& __y) const - { return __x == __y; } - }; - - struct __not_equal_to - { - template - bool operator()(const _Tp& __x, const _Tp& __y) const - { return __x != __y; } - }; - - struct __less - { - template - bool operator()(const _Tp& __x, const _Tp& __y) const - { return __x < __y; } - }; - - struct __greater - { - template - bool operator()(const _Tp& __x, const _Tp& __y) const - { return __x > __y; } - }; - - struct __less_equal - { - template - bool operator()(const _Tp& __x, const _Tp& __y) const - { return __x <= __y; } - }; - - struct __greater_equal - { - template - bool operator()(const _Tp& __x, const _Tp& __y) const - { return __x >= __y; } - }; - - // The few binary functions we miss. - struct _Atan2 - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return atan2(__x, __y); } - }; - - struct _Pow - { - template - _Tp operator()(const _Tp& __x, const _Tp& __y) const - { return pow(__x, __y); } - }; - - template - struct __fun_with_valarray - { - typedef _Tp result_type; - }; - - template - struct __fun_with_valarray<_Tp, false> - { - // No result type defined for invalid value types. - }; - - // We need these bits in order to recover the return type of - // some functions/operators now that we're no longer using - // function templates. - template - struct __fun : __fun_with_valarray<_Tp> - { - }; - - // several specializations for relational operators. - template - struct __fun<__logical_not, _Tp> - { - typedef bool result_type; - }; - - template - struct __fun<__logical_and, _Tp> - { - typedef bool result_type; - }; - - template - struct __fun<__logical_or, _Tp> - { - typedef bool result_type; - }; - - template - struct __fun<__less, _Tp> - { - typedef bool result_type; - }; - - template - struct __fun<__greater, _Tp> - { - typedef bool result_type; - }; - - template - struct __fun<__less_equal, _Tp> - { - typedef bool result_type; - }; - - template - struct __fun<__greater_equal, _Tp> - { - typedef bool result_type; - }; - - template - struct __fun<__equal_to, _Tp> - { - typedef bool result_type; - }; - - template - struct __fun<__not_equal_to, _Tp> - { - typedef bool result_type; - }; - -namespace __detail -{ - // Closure types already have reference semantics and are often short-lived, - // so store them by value to avoid (some cases of) dangling references to - // out-of-scope temporaries. - template - struct _ValArrayRef - { typedef const _Tp __type; }; - - // Use real references for std::valarray objects. - template - struct _ValArrayRef< valarray<_Tp> > - { typedef const valarray<_Tp>& __type; }; - - // - // Apply function taking a value/const reference closure - // - - template - class _FunBase - { - public: - typedef typename _Dom::value_type value_type; - - _FunBase(const _Dom& __e, value_type __f(_Arg)) - : _M_expr(__e), _M_func(__f) {} - - value_type operator[](size_t __i) const - { return _M_func (_M_expr[__i]); } - - size_t size() const { return _M_expr.size ();} - - private: - typename _ValArrayRef<_Dom>::__type _M_expr; - value_type (*_M_func)(_Arg); - }; - - template - struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type> - { - typedef _FunBase<_Dom, typename _Dom::value_type> _Base; - typedef typename _Base::value_type value_type; - typedef value_type _Tp; - - _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {} - }; - - template - struct _ValFunClos<_ValArray,_Tp> : _FunBase, _Tp> - { - typedef _FunBase, _Tp> _Base; - typedef _Tp value_type; - - _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {} - }; - - template - struct _RefFunClos<_Expr, _Dom> - : _FunBase<_Dom, const typename _Dom::value_type&> - { - typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base; - typedef typename _Base::value_type value_type; - typedef value_type _Tp; - - _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&)) - : _Base(__e, __f) {} - }; - - template - struct _RefFunClos<_ValArray, _Tp> - : _FunBase, const _Tp&> - { - typedef _FunBase, const _Tp&> _Base; - typedef _Tp value_type; - - _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&)) - : _Base(__v, __f) {} - }; - - // - // Unary expression closure. - // - - template - class _UnBase - { - public: - typedef typename _Arg::value_type _Vt; - typedef typename __fun<_Oper, _Vt>::result_type value_type; - - _UnBase(const _Arg& __e) : _M_expr(__e) {} - - value_type operator[](size_t __i) const - { return _Oper()(_M_expr[__i]); } - - size_t size() const { return _M_expr.size(); } - - private: - typename _ValArrayRef<_Arg>::__type _M_expr; - }; - - template - struct _UnClos<_Oper, _Expr, _Dom> - : _UnBase<_Oper, _Dom> - { - typedef _Dom _Arg; - typedef _UnBase<_Oper, _Dom> _Base; - typedef typename _Base::value_type value_type; - - _UnClos(const _Arg& __e) : _Base(__e) {} - }; - - template - struct _UnClos<_Oper, _ValArray, _Tp> - : _UnBase<_Oper, valarray<_Tp> > - { - typedef valarray<_Tp> _Arg; - typedef _UnBase<_Oper, valarray<_Tp> > _Base; - typedef typename _Base::value_type value_type; - - _UnClos(const _Arg& __e) : _Base(__e) {} - }; - - - // - // Binary expression closure. - // - - template - class _BinBase - { - public: - typedef typename _FirstArg::value_type _Vt; - typedef typename __fun<_Oper, _Vt>::result_type value_type; - - _BinBase(const _FirstArg& __e1, const _SecondArg& __e2) - : _M_expr1(__e1), _M_expr2(__e2) {} - - value_type operator[](size_t __i) const - { return _Oper()(_M_expr1[__i], _M_expr2[__i]); } - - size_t size() const { return _M_expr1.size(); } - - private: - typename _ValArrayRef<_FirstArg>::__type _M_expr1; - typename _ValArrayRef<_SecondArg>::__type _M_expr2; - }; - - - template - class _BinBase2 - { - public: - typedef typename _Clos::value_type _Vt; - typedef typename __fun<_Oper, _Vt>::result_type value_type; - - _BinBase2(const _Clos& __e, const _Vt& __t) - : _M_expr1(__e), _M_expr2(__t) {} - - value_type operator[](size_t __i) const - { return _Oper()(_M_expr1[__i], _M_expr2); } - - size_t size() const { return _M_expr1.size(); } - - private: - typename _ValArrayRef<_Clos>::__type _M_expr1; - _Vt _M_expr2; - }; - - template - class _BinBase1 - { - public: - typedef typename _Clos::value_type _Vt; - typedef typename __fun<_Oper, _Vt>::result_type value_type; - - _BinBase1(const _Vt& __t, const _Clos& __e) - : _M_expr1(__t), _M_expr2(__e) {} - - value_type operator[](size_t __i) const - { return _Oper()(_M_expr1, _M_expr2[__i]); } - - size_t size() const { return _M_expr2.size(); } - - private: - _Vt _M_expr1; - typename _ValArrayRef<_Clos>::__type _M_expr2; - }; - - template - struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2> - : _BinBase<_Oper, _Dom1, _Dom2> - { - typedef _BinBase<_Oper, _Dom1, _Dom2> _Base; - typedef typename _Base::value_type value_type; - - _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {} - }; - - template - struct _BinClos<_Oper, _ValArray, _ValArray, _Tp, _Tp> - : _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > - { - typedef _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > _Base; - typedef typename _Base::value_type value_type; - - _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w) - : _Base(__v, __w) {} - }; - - template - struct _BinClos<_Oper, _Expr, _ValArray, _Dom, typename _Dom::value_type> - : _BinBase<_Oper, _Dom, valarray > - { - typedef typename _Dom::value_type _Tp; - typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base; - typedef typename _Base::value_type value_type; - - _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2) - : _Base(__e1, __e2) {} - }; - - template - struct _BinClos<_Oper, _ValArray, _Expr, typename _Dom::value_type, _Dom> - : _BinBase<_Oper, valarray,_Dom> - { - typedef typename _Dom::value_type _Tp; - typedef _BinBase<_Oper, valarray<_Tp>, _Dom> _Base; - typedef typename _Base::value_type value_type; - - _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2) - : _Base(__e1, __e2) {} - }; - - template - struct _BinClos<_Oper, _Expr, _Constant, _Dom, typename _Dom::value_type> - : _BinBase2<_Oper, _Dom> - { - typedef typename _Dom::value_type _Tp; - typedef _BinBase2<_Oper,_Dom> _Base; - typedef typename _Base::value_type value_type; - - _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {} - }; - - template - struct _BinClos<_Oper, _Constant, _Expr, typename _Dom::value_type, _Dom> - : _BinBase1<_Oper, _Dom> - { - typedef typename _Dom::value_type _Tp; - typedef _BinBase1<_Oper, _Dom> _Base; - typedef typename _Base::value_type value_type; - - _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {} - }; - - template - struct _BinClos<_Oper, _ValArray, _Constant, _Tp, _Tp> - : _BinBase2<_Oper, valarray<_Tp> > - { - typedef _BinBase2<_Oper,valarray<_Tp> > _Base; - typedef typename _Base::value_type value_type; - - _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {} - }; - - template - struct _BinClos<_Oper, _Constant, _ValArray, _Tp, _Tp> - : _BinBase1<_Oper, valarray<_Tp> > - { - typedef _BinBase1<_Oper, valarray<_Tp> > _Base; - typedef typename _Base::value_type value_type; - - _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {} - }; - - // - // slice_array closure. - // - template - class _SBase - { - public: - typedef typename _Dom::value_type value_type; - - _SBase (const _Dom& __e, const slice& __s) - : _M_expr (__e), _M_slice (__s) {} - - value_type - operator[] (size_t __i) const - { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; } - - size_t - size() const - { return _M_slice.size (); } - - private: - typename _ValArrayRef<_Dom>::__type _M_expr; - const slice& _M_slice; - }; - - template - class _SBase<_Array<_Tp> > - { - public: - typedef _Tp value_type; - - _SBase (_Array<_Tp> __a, const slice& __s) - : _M_array (__a._M_data+__s.start()), _M_size (__s.size()), - _M_stride (__s.stride()) {} - - value_type - operator[] (size_t __i) const - { return _M_array._M_data[__i * _M_stride]; } - - size_t - size() const - { return _M_size; } - - private: - const _Array<_Tp> _M_array; - const size_t _M_size; - const size_t _M_stride; - }; - - template - struct _SClos<_Expr, _Dom> - : _SBase<_Dom> - { - typedef _SBase<_Dom> _Base; - typedef typename _Base::value_type value_type; - - _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {} - }; - - template - struct _SClos<_ValArray, _Tp> - : _SBase<_Array<_Tp> > - { - typedef _SBase<_Array<_Tp> > _Base; - typedef _Tp value_type; - - _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {} - }; -} // namespace __detail - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _CPP_VALARRAY_BEFORE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/vector.tcc b/resources/sources/avr-libstdcpp/include/bits/vector.tcc deleted file mode 100644 index 27e63388f..000000000 --- a/resources/sources/avr-libstdcpp/include/bits/vector.tcc +++ /dev/null @@ -1,1008 +0,0 @@ -// Vector implementation (out of line) -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file bits/vector.tcc - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{vector} - */ - -#ifndef _VECTOR_TCC -#define _VECTOR_TCC 1 - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - template - void - vector<_Tp, _Alloc>:: - reserve(size_type __n) - { - if (__n > this->max_size()) - __throw_length_error(__N("vector::reserve")); - if (this->capacity() < __n) - { - const size_type __old_size = size(); - pointer __tmp; -#if __cplusplus >= 201103L - if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) - { - __tmp = this->_M_allocate(__n); - _S_relocate(this->_M_impl._M_start, this->_M_impl._M_finish, - __tmp, _M_get_Tp_allocator()); - } - else -#endif - { - __tmp = _M_allocate_and_copy(__n, - _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start), - _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish)); - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - } - _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __tmp; - this->_M_impl._M_finish = __tmp + __old_size; - this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; - } - } - -#if __cplusplus >= 201103L - template - template -#if __cplusplus > 201402L - typename vector<_Tp, _Alloc>::reference -#else - void -#endif - vector<_Tp, _Alloc>:: - emplace_back(_Args&&... __args) - { - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - { - _GLIBCXX_ASAN_ANNOTATE_GROW(1); - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - std::forward<_Args>(__args)...); - ++this->_M_impl._M_finish; - _GLIBCXX_ASAN_ANNOTATE_GREW(1); - } - else - _M_realloc_insert(end(), std::forward<_Args>(__args)...); -#if __cplusplus > 201402L - return back(); -#endif - } -#endif - - template - typename vector<_Tp, _Alloc>::iterator - vector<_Tp, _Alloc>:: -#if __cplusplus >= 201103L - insert(const_iterator __position, const value_type& __x) -#else - insert(iterator __position, const value_type& __x) -#endif - { - const size_type __n = __position - begin(); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - if (__position == end()) - { - _GLIBCXX_ASAN_ANNOTATE_GROW(1); - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - __x); - ++this->_M_impl._M_finish; - _GLIBCXX_ASAN_ANNOTATE_GREW(1); - } - else - { -#if __cplusplus >= 201103L - const auto __pos = begin() + (__position - cbegin()); - // __x could be an existing element of this vector, so make a - // copy of it before _M_insert_aux moves elements around. - _Temporary_value __x_copy(this, __x); - _M_insert_aux(__pos, std::move(__x_copy._M_val())); -#else - _M_insert_aux(__position, __x); -#endif - } - else -#if __cplusplus >= 201103L - _M_realloc_insert(begin() + (__position - cbegin()), __x); -#else - _M_realloc_insert(__position, __x); -#endif - - return iterator(this->_M_impl._M_start + __n); - } - - template - typename vector<_Tp, _Alloc>::iterator - vector<_Tp, _Alloc>:: - _M_erase(iterator __position) - { - if (__position + 1 != end()) - _GLIBCXX_MOVE3(__position + 1, end(), __position); - --this->_M_impl._M_finish; - _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); - _GLIBCXX_ASAN_ANNOTATE_SHRINK(1); - return __position; - } - - template - typename vector<_Tp, _Alloc>::iterator - vector<_Tp, _Alloc>:: - _M_erase(iterator __first, iterator __last) - { - if (__first != __last) - { - if (__last != end()) - _GLIBCXX_MOVE3(__last, end(), __first); - _M_erase_at_end(__first.base() + (end() - __last)); - } - return __first; - } - - template - vector<_Tp, _Alloc>& - vector<_Tp, _Alloc>:: - operator=(const vector<_Tp, _Alloc>& __x) - { - if (&__x != this) - { - _GLIBCXX_ASAN_ANNOTATE_REINIT; -#if __cplusplus >= 201103L - if (_Alloc_traits::_S_propagate_on_copy_assign()) - { - if (!_Alloc_traits::_S_always_equal() - && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) - { - // replacement allocator cannot free existing storage - this->clear(); - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = nullptr; - this->_M_impl._M_finish = nullptr; - this->_M_impl._M_end_of_storage = nullptr; - } - std::__alloc_on_copy(_M_get_Tp_allocator(), - __x._M_get_Tp_allocator()); - } -#endif - const size_type __xlen = __x.size(); - if (__xlen > capacity()) - { - pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), - __x.end()); - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __tmp; - this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __xlen; - } - else if (size() >= __xlen) - { - std::_Destroy(std::copy(__x.begin(), __x.end(), begin()), - end(), _M_get_Tp_allocator()); - } - else - { - std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(), - this->_M_impl._M_start); - std::__uninitialized_copy_a(__x._M_impl._M_start + size(), - __x._M_impl._M_finish, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - } - this->_M_impl._M_finish = this->_M_impl._M_start + __xlen; - } - return *this; - } - - template - void - vector<_Tp, _Alloc>:: - _M_fill_assign(size_t __n, const value_type& __val) - { - if (__n > capacity()) - { - vector __tmp(__n, __val, _M_get_Tp_allocator()); - __tmp._M_impl._M_swap_data(this->_M_impl); - } - else if (__n > size()) - { - std::fill(begin(), end(), __val); - const size_type __add = __n - size(); - _GLIBCXX_ASAN_ANNOTATE_GROW(__add); - this->_M_impl._M_finish = - std::__uninitialized_fill_n_a(this->_M_impl._M_finish, - __add, __val, _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_GREW(__add); - } - else - _M_erase_at_end(std::fill_n(this->_M_impl._M_start, __n, __val)); - } - - template - template - void - vector<_Tp, _Alloc>:: - _M_assign_aux(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag) - { - pointer __cur(this->_M_impl._M_start); - for (; __first != __last && __cur != this->_M_impl._M_finish; - ++__cur, (void)++__first) - *__cur = *__first; - if (__first == __last) - _M_erase_at_end(__cur); - else - _M_range_insert(end(), __first, __last, - std::__iterator_category(__first)); - } - - template - template - void - vector<_Tp, _Alloc>:: - _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) - { - const size_type __len = std::distance(__first, __last); - - if (__len > capacity()) - { - _S_check_init_len(__len, _M_get_Tp_allocator()); - pointer __tmp(_M_allocate_and_copy(__len, __first, __last)); - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __tmp; - this->_M_impl._M_finish = this->_M_impl._M_start + __len; - this->_M_impl._M_end_of_storage = this->_M_impl._M_finish; - } - else if (size() >= __len) - _M_erase_at_end(std::copy(__first, __last, this->_M_impl._M_start)); - else - { - _ForwardIterator __mid = __first; - std::advance(__mid, size()); - std::copy(__first, __mid, this->_M_impl._M_start); - const size_type __attribute__((__unused__)) __n = __len - size(); - _GLIBCXX_ASAN_ANNOTATE_GROW(__n); - this->_M_impl._M_finish = - std::__uninitialized_copy_a(__mid, __last, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_GREW(__n); - } - } - -#if __cplusplus >= 201103L - template - auto - vector<_Tp, _Alloc>:: - _M_insert_rval(const_iterator __position, value_type&& __v) -> iterator - { - const auto __n = __position - cbegin(); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - if (__position == cend()) - { - _GLIBCXX_ASAN_ANNOTATE_GROW(1); - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - std::move(__v)); - ++this->_M_impl._M_finish; - _GLIBCXX_ASAN_ANNOTATE_GREW(1); - } - else - _M_insert_aux(begin() + __n, std::move(__v)); - else - _M_realloc_insert(begin() + __n, std::move(__v)); - - return iterator(this->_M_impl._M_start + __n); - } - - template - template - auto - vector<_Tp, _Alloc>:: - _M_emplace_aux(const_iterator __position, _Args&&... __args) - -> iterator - { - const auto __n = __position - cbegin(); - if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) - if (__position == cend()) - { - _GLIBCXX_ASAN_ANNOTATE_GROW(1); - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - std::forward<_Args>(__args)...); - ++this->_M_impl._M_finish; - _GLIBCXX_ASAN_ANNOTATE_GREW(1); - } - else - { - // We need to construct a temporary because something in __args... - // could alias one of the elements of the container and so we - // need to use it before _M_insert_aux moves elements around. - _Temporary_value __tmp(this, std::forward<_Args>(__args)...); - _M_insert_aux(begin() + __n, std::move(__tmp._M_val())); - } - else - _M_realloc_insert(begin() + __n, std::forward<_Args>(__args)...); - - return iterator(this->_M_impl._M_start + __n); - } - - template - template - void - vector<_Tp, _Alloc>:: - _M_insert_aux(iterator __position, _Arg&& __arg) -#else - template - void - vector<_Tp, _Alloc>:: - _M_insert_aux(iterator __position, const _Tp& __x) -#endif - { - _GLIBCXX_ASAN_ANNOTATE_GROW(1); - _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, - _GLIBCXX_MOVE(*(this->_M_impl._M_finish - 1))); - ++this->_M_impl._M_finish; - _GLIBCXX_ASAN_ANNOTATE_GREW(1); -#if __cplusplus < 201103L - _Tp __x_copy = __x; -#endif - _GLIBCXX_MOVE_BACKWARD3(__position.base(), - this->_M_impl._M_finish - 2, - this->_M_impl._M_finish - 1); -#if __cplusplus < 201103L - *__position = __x_copy; -#else - *__position = std::forward<_Arg>(__arg); -#endif - } - -#if __cplusplus >= 201103L - template - template - void - vector<_Tp, _Alloc>:: - _M_realloc_insert(iterator __position, _Args&&... __args) -#else - template - void - vector<_Tp, _Alloc>:: - _M_realloc_insert(iterator __position, const _Tp& __x) -#endif - { - const size_type __len = - _M_check_len(size_type(1), "vector::_M_realloc_insert"); - pointer __old_start = this->_M_impl._M_start; - pointer __old_finish = this->_M_impl._M_finish; - const size_type __elems_before = __position - begin(); - pointer __new_start(this->_M_allocate(__len)); - pointer __new_finish(__new_start); - __try - { - // The order of the three operations is dictated by the C++11 - // case, where the moves could alter a new element belonging - // to the existing vector. This is an issue only for callers - // taking the element by lvalue ref (see last bullet of C++11 - // [res.on.arguments]). - _Alloc_traits::construct(this->_M_impl, - __new_start + __elems_before, -#if __cplusplus >= 201103L - std::forward<_Args>(__args)...); -#else - __x); -#endif - __new_finish = pointer(); - -#if __cplusplus >= 201103L - if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) - { - __new_finish = _S_relocate(__old_start, __position.base(), - __new_start, _M_get_Tp_allocator()); - - ++__new_finish; - - __new_finish = _S_relocate(__position.base(), __old_finish, - __new_finish, _M_get_Tp_allocator()); - } - else -#endif - { - __new_finish - = std::__uninitialized_move_if_noexcept_a - (__old_start, __position.base(), - __new_start, _M_get_Tp_allocator()); - - ++__new_finish; - - __new_finish - = std::__uninitialized_move_if_noexcept_a - (__position.base(), __old_finish, - __new_finish, _M_get_Tp_allocator()); - } - } - __catch(...) - { - if (!__new_finish) - _Alloc_traits::destroy(this->_M_impl, - __new_start + __elems_before); - else - std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); - _M_deallocate(__new_start, __len); - __throw_exception_again; - } -#if __cplusplus >= 201103L - if _GLIBCXX17_CONSTEXPR (!_S_use_relocate()) -#endif - std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(__old_start, - this->_M_impl._M_end_of_storage - __old_start); - this->_M_impl._M_start = __new_start; - this->_M_impl._M_finish = __new_finish; - this->_M_impl._M_end_of_storage = __new_start + __len; - } - - template - void - vector<_Tp, _Alloc>:: - _M_fill_insert(iterator __position, size_type __n, const value_type& __x) - { - if (__n != 0) - { - if (size_type(this->_M_impl._M_end_of_storage - - this->_M_impl._M_finish) >= __n) - { -#if __cplusplus < 201103L - value_type __x_copy = __x; -#else - _Temporary_value __tmp(this, __x); - value_type& __x_copy = __tmp._M_val(); -#endif - const size_type __elems_after = end() - __position; - pointer __old_finish(this->_M_impl._M_finish); - if (__elems_after > __n) - { - _GLIBCXX_ASAN_ANNOTATE_GROW(__n); - std::__uninitialized_move_a(this->_M_impl._M_finish - __n, - this->_M_impl._M_finish, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish += __n; - _GLIBCXX_ASAN_ANNOTATE_GREW(__n); - _GLIBCXX_MOVE_BACKWARD3(__position.base(), - __old_finish - __n, __old_finish); - std::fill(__position.base(), __position.base() + __n, - __x_copy); - } - else - { - _GLIBCXX_ASAN_ANNOTATE_GROW(__n); - this->_M_impl._M_finish = - std::__uninitialized_fill_n_a(this->_M_impl._M_finish, - __n - __elems_after, - __x_copy, - _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after); - std::__uninitialized_move_a(__position.base(), __old_finish, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish += __elems_after; - _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after); - std::fill(__position.base(), __old_finish, __x_copy); - } - } - else - { - const size_type __len = - _M_check_len(__n, "vector::_M_fill_insert"); - const size_type __elems_before = __position - begin(); - pointer __new_start(this->_M_allocate(__len)); - pointer __new_finish(__new_start); - __try - { - // See _M_realloc_insert above. - std::__uninitialized_fill_n_a(__new_start + __elems_before, - __n, __x, - _M_get_Tp_allocator()); - __new_finish = pointer(); - - __new_finish - = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, __position.base(), - __new_start, _M_get_Tp_allocator()); - - __new_finish += __n; - - __new_finish - = std::__uninitialized_move_if_noexcept_a - (__position.base(), this->_M_impl._M_finish, - __new_finish, _M_get_Tp_allocator()); - } - __catch(...) - { - if (!__new_finish) - std::_Destroy(__new_start + __elems_before, - __new_start + __elems_before + __n, - _M_get_Tp_allocator()); - else - std::_Destroy(__new_start, __new_finish, - _M_get_Tp_allocator()); - _M_deallocate(__new_start, __len); - __throw_exception_again; - } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __new_start; - this->_M_impl._M_finish = __new_finish; - this->_M_impl._M_end_of_storage = __new_start + __len; - } - } - } - -#if __cplusplus >= 201103L - template - void - vector<_Tp, _Alloc>:: - _M_default_append(size_type __n) - { - if (__n != 0) - { - const size_type __size = size(); - size_type __navail = size_type(this->_M_impl._M_end_of_storage - - this->_M_impl._M_finish); - - if (__size > max_size() || __navail > max_size() - __size) - __builtin_unreachable(); - - if (__navail >= __n) - { - _GLIBCXX_ASAN_ANNOTATE_GROW(__n); - this->_M_impl._M_finish = - std::__uninitialized_default_n_a(this->_M_impl._M_finish, - __n, _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_GREW(__n); - } - else - { - const size_type __len = - _M_check_len(__n, "vector::_M_default_append"); - pointer __new_start(this->_M_allocate(__len)); - if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) - { - __try - { - std::__uninitialized_default_n_a(__new_start + __size, - __n, _M_get_Tp_allocator()); - } - __catch(...) - { - _M_deallocate(__new_start, __len); - __throw_exception_again; - } - _S_relocate(this->_M_impl._M_start, this->_M_impl._M_finish, - __new_start, _M_get_Tp_allocator()); - } - else - { - pointer __destroy_from = pointer(); - __try - { - std::__uninitialized_default_n_a(__new_start + __size, - __n, _M_get_Tp_allocator()); - __destroy_from = __new_start + __size; - std::__uninitialized_move_if_noexcept_a( - this->_M_impl._M_start, this->_M_impl._M_finish, - __new_start, _M_get_Tp_allocator()); - } - __catch(...) - { - if (__destroy_from) - std::_Destroy(__destroy_from, __destroy_from + __n, - _M_get_Tp_allocator()); - _M_deallocate(__new_start, __len); - __throw_exception_again; - } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - } - _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __new_start; - this->_M_impl._M_finish = __new_start + __size + __n; - this->_M_impl._M_end_of_storage = __new_start + __len; - } - } - } - - template - bool - vector<_Tp, _Alloc>:: - _M_shrink_to_fit() - { - if (capacity() == size()) - return false; - _GLIBCXX_ASAN_ANNOTATE_REINIT; - return std::__shrink_to_fit_aux::_S_do_it(*this); - } -#endif - - template - template - void - vector<_Tp, _Alloc>:: - _M_range_insert(iterator __pos, _InputIterator __first, - _InputIterator __last, std::input_iterator_tag) - { - if (__pos == end()) - { - for (; __first != __last; ++__first) - insert(end(), *__first); - } - else if (__first != __last) - { - vector __tmp(__first, __last, _M_get_Tp_allocator()); - insert(__pos, - _GLIBCXX_MAKE_MOVE_ITERATOR(__tmp.begin()), - _GLIBCXX_MAKE_MOVE_ITERATOR(__tmp.end())); - } - } - - template - template - void - vector<_Tp, _Alloc>:: - _M_range_insert(iterator __position, _ForwardIterator __first, - _ForwardIterator __last, std::forward_iterator_tag) - { - if (__first != __last) - { - const size_type __n = std::distance(__first, __last); - if (size_type(this->_M_impl._M_end_of_storage - - this->_M_impl._M_finish) >= __n) - { - const size_type __elems_after = end() - __position; - pointer __old_finish(this->_M_impl._M_finish); - if (__elems_after > __n) - { - _GLIBCXX_ASAN_ANNOTATE_GROW(__n); - std::__uninitialized_move_a(this->_M_impl._M_finish - __n, - this->_M_impl._M_finish, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish += __n; - _GLIBCXX_ASAN_ANNOTATE_GREW(__n); - _GLIBCXX_MOVE_BACKWARD3(__position.base(), - __old_finish - __n, __old_finish); - std::copy(__first, __last, __position); - } - else - { - _ForwardIterator __mid = __first; - std::advance(__mid, __elems_after); - _GLIBCXX_ASAN_ANNOTATE_GROW(__n); - std::__uninitialized_copy_a(__mid, __last, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish += __n - __elems_after; - _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after); - std::__uninitialized_move_a(__position.base(), - __old_finish, - this->_M_impl._M_finish, - _M_get_Tp_allocator()); - this->_M_impl._M_finish += __elems_after; - _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after); - std::copy(__first, __mid, __position); - } - } - else - { - const size_type __len = - _M_check_len(__n, "vector::_M_range_insert"); - pointer __new_start(this->_M_allocate(__len)); - pointer __new_finish(__new_start); - __try - { - __new_finish - = std::__uninitialized_move_if_noexcept_a - (this->_M_impl._M_start, __position.base(), - __new_start, _M_get_Tp_allocator()); - __new_finish - = std::__uninitialized_copy_a(__first, __last, - __new_finish, - _M_get_Tp_allocator()); - __new_finish - = std::__uninitialized_move_if_noexcept_a - (__position.base(), this->_M_impl._M_finish, - __new_finish, _M_get_Tp_allocator()); - } - __catch(...) - { - std::_Destroy(__new_start, __new_finish, - _M_get_Tp_allocator()); - _M_deallocate(__new_start, __len); - __throw_exception_again; - } - std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, - _M_get_Tp_allocator()); - _GLIBCXX_ASAN_ANNOTATE_REINIT; - _M_deallocate(this->_M_impl._M_start, - this->_M_impl._M_end_of_storage - - this->_M_impl._M_start); - this->_M_impl._M_start = __new_start; - this->_M_impl._M_finish = __new_finish; - this->_M_impl._M_end_of_storage = __new_start + __len; - } - } - } - - - // vector - template - void - vector:: - _M_reallocate(size_type __n) - { - _Bit_pointer __q = this->_M_allocate(__n); - iterator __start(std::__addressof(*__q), 0); - iterator __finish(_M_copy_aligned(begin(), end(), __start)); - this->_M_deallocate(); - this->_M_impl._M_start = __start; - this->_M_impl._M_finish = __finish; - this->_M_impl._M_end_of_storage = __q + _S_nword(__n); - } - - template - void - vector:: - _M_fill_insert(iterator __position, size_type __n, bool __x) - { - if (__n == 0) - return; - if (capacity() - size() >= __n) - { - std::copy_backward(__position, end(), - this->_M_impl._M_finish + difference_type(__n)); - std::fill(__position, __position + difference_type(__n), __x); - this->_M_impl._M_finish += difference_type(__n); - } - else - { - const size_type __len = - _M_check_len(__n, "vector::_M_fill_insert"); - _Bit_pointer __q = this->_M_allocate(__len); - iterator __start(std::__addressof(*__q), 0); - iterator __i = _M_copy_aligned(begin(), __position, __start); - std::fill(__i, __i + difference_type(__n), __x); - iterator __finish = std::copy(__position, end(), - __i + difference_type(__n)); - this->_M_deallocate(); - this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = __start; - this->_M_impl._M_finish = __finish; - } - } - - template - template - void - vector:: - _M_insert_range(iterator __position, _ForwardIterator __first, - _ForwardIterator __last, std::forward_iterator_tag) - { - if (__first != __last) - { - size_type __n = std::distance(__first, __last); - if (capacity() - size() >= __n) - { - std::copy_backward(__position, end(), - this->_M_impl._M_finish - + difference_type(__n)); - std::copy(__first, __last, __position); - this->_M_impl._M_finish += difference_type(__n); - } - else - { - const size_type __len = - _M_check_len(__n, "vector::_M_insert_range"); - _Bit_pointer __q = this->_M_allocate(__len); - iterator __start(std::__addressof(*__q), 0); - iterator __i = _M_copy_aligned(begin(), __position, __start); - __i = std::copy(__first, __last, __i); - iterator __finish = std::copy(__position, end(), __i); - this->_M_deallocate(); - this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = __start; - this->_M_impl._M_finish = __finish; - } - } - } - - template - void - vector:: - _M_insert_aux(iterator __position, bool __x) - { - if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) - { - std::copy_backward(__position, this->_M_impl._M_finish, - this->_M_impl._M_finish + 1); - *__position = __x; - ++this->_M_impl._M_finish; - } - else - { - const size_type __len = - _M_check_len(size_type(1), "vector::_M_insert_aux"); - _Bit_pointer __q = this->_M_allocate(__len); - iterator __start(std::__addressof(*__q), 0); - iterator __i = _M_copy_aligned(begin(), __position, __start); - *__i++ = __x; - iterator __finish = std::copy(__position, end(), __i); - this->_M_deallocate(); - this->_M_impl._M_end_of_storage = __q + _S_nword(__len); - this->_M_impl._M_start = __start; - this->_M_impl._M_finish = __finish; - } - } - - template - typename vector::iterator - vector:: - _M_erase(iterator __position) - { - if (__position + 1 != end()) - std::copy(__position + 1, end(), __position); - --this->_M_impl._M_finish; - return __position; - } - - template - typename vector::iterator - vector:: - _M_erase(iterator __first, iterator __last) - { - if (__first != __last) - _M_erase_at_end(std::copy(__last, end(), __first)); - return __first; - } - -#if __cplusplus >= 201103L - template - bool - vector:: - _M_shrink_to_fit() - { - if (capacity() - size() < int(_S_word_bit)) - return false; - __try - { - _M_reallocate(size()); - return true; - } - __catch(...) - { return false; } - } -#endif - -_GLIBCXX_END_NAMESPACE_CONTAINER -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#if __cplusplus >= 201103L - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template - size_t - hash<_GLIBCXX_STD_C::vector>:: - operator()(const _GLIBCXX_STD_C::vector& __b) const noexcept - { - size_t __hash = 0; - using _GLIBCXX_STD_C::_S_word_bit; - using _GLIBCXX_STD_C::_Bit_type; - - const size_t __words = __b.size() / _S_word_bit; - if (__words) - { - const size_t __clength = __words * sizeof(_Bit_type); - __hash = std::_Hash_impl::hash(__b._M_impl._M_start._M_p, __clength); - } - - const size_t __extrabits = __b.size() % _S_word_bit; - if (__extrabits) - { - _Bit_type __hiword = *__b._M_impl._M_finish._M_p; - __hiword &= ~((~static_cast<_Bit_type>(0)) << __extrabits); - - const size_t __clength - = (__extrabits + __CHAR_BIT__ - 1) / __CHAR_BIT__; - if (__words) - __hash = std::_Hash_impl::hash(&__hiword, __clength, __hash); - else - __hash = std::_Hash_impl::hash(&__hiword, __clength); - } - - return __hash; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++11 - -#undef _GLIBCXX_ASAN_ANNOTATE_REINIT -#undef _GLIBCXX_ASAN_ANNOTATE_GROW -#undef _GLIBCXX_ASAN_ANNOTATE_GREW -#undef _GLIBCXX_ASAN_ANNOTATE_SHRINK - -#endif /* _VECTOR_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bitset b/resources/sources/avr-libstdcpp/include/bitset deleted file mode 100644 index dc3910ac6..000000000 --- a/resources/sources/avr-libstdcpp/include/bitset +++ /dev/null @@ -1,1245 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/bitset - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_BITSET -#define _GLIBCXX_BITSET 1 - -#pragma GCC system_header - -#include // For invalid_argument, out_of_range, - // overflow_error -#include - -#if __cplusplus >= 201103L -# include -#endif - -#define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * __SIZEOF_LONG__) -#define _GLIBCXX_BITSET_WORDS(__n) \ - ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \ - ((__n) % _GLIBCXX_BITSET_BITS_PER_WORD == 0 ? 0 : 1)) - -#define _GLIBCXX_BITSET_BITS_PER_ULL (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_CONTAINER - - /** - * Base class, general case. It is a class invariant that _Nw will be - * nonnegative. - * - * See documentation for bitset. - */ - template - struct _Base_bitset - { - typedef unsigned long _WordT; - - /// 0 is the least significant word. - _WordT _M_w[_Nw]; - - _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT - : _M_w() { } - -#if __cplusplus >= 201103L - constexpr _Base_bitset(unsigned long long __val) noexcept - : _M_w{ _WordT(__val) -#if __SIZEOF_LONG_LONG__ > __SIZEOF_LONG__ - , _WordT(__val >> _GLIBCXX_BITSET_BITS_PER_WORD) -#endif - } { } -#else - _Base_bitset(unsigned long __val) - : _M_w() - { _M_w[0] = __val; } -#endif - - static _GLIBCXX_CONSTEXPR size_t - _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT - { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } - - static _GLIBCXX_CONSTEXPR size_t - _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT - { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } - - static _GLIBCXX_CONSTEXPR size_t - _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT - { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } - - static _GLIBCXX_CONSTEXPR _WordT - _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT - { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } - - _WordT& - _M_getword(size_t __pos) _GLIBCXX_NOEXCEPT - { return _M_w[_S_whichword(__pos)]; } - - _GLIBCXX_CONSTEXPR _WordT - _M_getword(size_t __pos) const _GLIBCXX_NOEXCEPT - { return _M_w[_S_whichword(__pos)]; } - -#if __cplusplus >= 201103L - const _WordT* - _M_getdata() const noexcept - { return _M_w; } -#endif - - _WordT& - _M_hiword() _GLIBCXX_NOEXCEPT - { return _M_w[_Nw - 1]; } - - _GLIBCXX_CONSTEXPR _WordT - _M_hiword() const _GLIBCXX_NOEXCEPT - { return _M_w[_Nw - 1]; } - - void - _M_do_and(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw; __i++) - _M_w[__i] &= __x._M_w[__i]; - } - - void - _M_do_or(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw; __i++) - _M_w[__i] |= __x._M_w[__i]; - } - - void - _M_do_xor(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw; __i++) - _M_w[__i] ^= __x._M_w[__i]; - } - - void - _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT; - - void - _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT; - - void - _M_do_flip() _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw; __i++) - _M_w[__i] = ~_M_w[__i]; - } - - void - _M_do_set() _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw; __i++) - _M_w[__i] = ~static_cast<_WordT>(0); - } - - void - _M_do_reset() _GLIBCXX_NOEXCEPT - { __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT)); } - - bool - _M_is_equal(const _Base_bitset<_Nw>& __x) const _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw; ++__i) - if (_M_w[__i] != __x._M_w[__i]) - return false; - return true; - } - - template - bool - _M_are_all() const _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw - 1; __i++) - if (_M_w[__i] != ~static_cast<_WordT>(0)) - return false; - return _M_hiword() == (~static_cast<_WordT>(0) - >> (_Nw * _GLIBCXX_BITSET_BITS_PER_WORD - - _Nb)); - } - - bool - _M_is_any() const _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw; __i++) - if (_M_w[__i] != static_cast<_WordT>(0)) - return true; - return false; - } - - size_t - _M_do_count() const _GLIBCXX_NOEXCEPT - { - size_t __result = 0; - for (size_t __i = 0; __i < _Nw; __i++) - __result += __builtin_popcountl(_M_w[__i]); - return __result; - } - - unsigned long - _M_do_to_ulong() const; - -#if __cplusplus >= 201103L - unsigned long long - _M_do_to_ullong() const; -#endif - - // find first "on" bit - size_t - _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT; - - // find the next "on" bit that follows "prev" - size_t - _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT; - }; - - // Definitions of non-inline functions from _Base_bitset. - template - void - _Base_bitset<_Nw>::_M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT - { - if (__builtin_expect(__shift != 0, 1)) - { - const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; - const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; - - if (__offset == 0) - for (size_t __n = _Nw - 1; __n >= __wshift; --__n) - _M_w[__n] = _M_w[__n - __wshift]; - else - { - const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD - - __offset); - for (size_t __n = _Nw - 1; __n > __wshift; --__n) - _M_w[__n] = ((_M_w[__n - __wshift] << __offset) - | (_M_w[__n - __wshift - 1] >> __sub_offset)); - _M_w[__wshift] = _M_w[0] << __offset; - } - - std::fill(_M_w + 0, _M_w + __wshift, static_cast<_WordT>(0)); - } - } - - template - void - _Base_bitset<_Nw>::_M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT - { - if (__builtin_expect(__shift != 0, 1)) - { - const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; - const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; - const size_t __limit = _Nw - __wshift - 1; - - if (__offset == 0) - for (size_t __n = 0; __n <= __limit; ++__n) - _M_w[__n] = _M_w[__n + __wshift]; - else - { - const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD - - __offset); - for (size_t __n = 0; __n < __limit; ++__n) - _M_w[__n] = ((_M_w[__n + __wshift] >> __offset) - | (_M_w[__n + __wshift + 1] << __sub_offset)); - _M_w[__limit] = _M_w[_Nw-1] >> __offset; - } - - std::fill(_M_w + __limit + 1, _M_w + _Nw, static_cast<_WordT>(0)); - } - } - - template - unsigned long - _Base_bitset<_Nw>::_M_do_to_ulong() const - { - for (size_t __i = 1; __i < _Nw; ++__i) - if (_M_w[__i]) - __throw_overflow_error(__N("_Base_bitset::_M_do_to_ulong")); - return _M_w[0]; - } - -#if __cplusplus >= 201103L - template - unsigned long long - _Base_bitset<_Nw>::_M_do_to_ullong() const - { - const bool __dw = sizeof(unsigned long long) > sizeof(unsigned long); - for (size_t __i = 1 + __dw; __i < _Nw; ++__i) - if (_M_w[__i]) - __throw_overflow_error(__N("_Base_bitset::_M_do_to_ullong")); - - if (__dw) - return _M_w[0] + (static_cast(_M_w[1]) - << _GLIBCXX_BITSET_BITS_PER_WORD); - return _M_w[0]; - } -#endif - - template - size_t - _Base_bitset<_Nw>:: - _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT - { - for (size_t __i = 0; __i < _Nw; __i++) - { - _WordT __thisword = _M_w[__i]; - if (__thisword != static_cast<_WordT>(0)) - return (__i * _GLIBCXX_BITSET_BITS_PER_WORD - + __builtin_ctzl(__thisword)); - } - // not found, so return an indication of failure. - return __not_found; - } - - template - size_t - _Base_bitset<_Nw>:: - _M_do_find_next(size_t __prev, size_t __not_found) const _GLIBCXX_NOEXCEPT - { - // make bound inclusive - ++__prev; - - // check out of bounds - if (__prev >= _Nw * _GLIBCXX_BITSET_BITS_PER_WORD) - return __not_found; - - // search first word - size_t __i = _S_whichword(__prev); - _WordT __thisword = _M_w[__i]; - - // mask off bits below bound - __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev); - - if (__thisword != static_cast<_WordT>(0)) - return (__i * _GLIBCXX_BITSET_BITS_PER_WORD - + __builtin_ctzl(__thisword)); - - // check subsequent words - __i++; - for (; __i < _Nw; __i++) - { - __thisword = _M_w[__i]; - if (__thisword != static_cast<_WordT>(0)) - return (__i * _GLIBCXX_BITSET_BITS_PER_WORD - + __builtin_ctzl(__thisword)); - } - // not found, so return an indication of failure. - return __not_found; - } // end _M_do_find_next - - /** - * Base class, specialization for a single word. - * - * See documentation for bitset. - */ - template<> - struct _Base_bitset<1> - { - typedef unsigned long _WordT; - _WordT _M_w; - - _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT - : _M_w(0) - { } - -#if __cplusplus >= 201103L - constexpr _Base_bitset(unsigned long long __val) noexcept -#else - _Base_bitset(unsigned long __val) -#endif - : _M_w(__val) - { } - - static _GLIBCXX_CONSTEXPR size_t - _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT - { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } - - static _GLIBCXX_CONSTEXPR size_t - _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT - { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } - - static _GLIBCXX_CONSTEXPR size_t - _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT - { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } - - static _GLIBCXX_CONSTEXPR _WordT - _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT - { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } - - _WordT& - _M_getword(size_t) _GLIBCXX_NOEXCEPT - { return _M_w; } - - _GLIBCXX_CONSTEXPR _WordT - _M_getword(size_t) const _GLIBCXX_NOEXCEPT - { return _M_w; } - -#if __cplusplus >= 201103L - const _WordT* - _M_getdata() const noexcept - { return &_M_w; } -#endif - - _WordT& - _M_hiword() _GLIBCXX_NOEXCEPT - { return _M_w; } - - _GLIBCXX_CONSTEXPR _WordT - _M_hiword() const _GLIBCXX_NOEXCEPT - { return _M_w; } - - void - _M_do_and(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT - { _M_w &= __x._M_w; } - - void - _M_do_or(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT - { _M_w |= __x._M_w; } - - void - _M_do_xor(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT - { _M_w ^= __x._M_w; } - - void - _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT - { _M_w <<= __shift; } - - void - _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT - { _M_w >>= __shift; } - - void - _M_do_flip() _GLIBCXX_NOEXCEPT - { _M_w = ~_M_w; } - - void - _M_do_set() _GLIBCXX_NOEXCEPT - { _M_w = ~static_cast<_WordT>(0); } - - void - _M_do_reset() _GLIBCXX_NOEXCEPT - { _M_w = 0; } - - bool - _M_is_equal(const _Base_bitset<1>& __x) const _GLIBCXX_NOEXCEPT - { return _M_w == __x._M_w; } - - template - bool - _M_are_all() const _GLIBCXX_NOEXCEPT - { return _M_w == (~static_cast<_WordT>(0) - >> (_GLIBCXX_BITSET_BITS_PER_WORD - _Nb)); } - - bool - _M_is_any() const _GLIBCXX_NOEXCEPT - { return _M_w != 0; } - - size_t - _M_do_count() const _GLIBCXX_NOEXCEPT - { return __builtin_popcountl(_M_w); } - - unsigned long - _M_do_to_ulong() const _GLIBCXX_NOEXCEPT - { return _M_w; } - -#if __cplusplus >= 201103L - unsigned long long - _M_do_to_ullong() const noexcept - { return _M_w; } -#endif - - size_t - _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT - { - if (_M_w != 0) - return __builtin_ctzl(_M_w); - else - return __not_found; - } - - // find the next "on" bit that follows "prev" - size_t - _M_do_find_next(size_t __prev, size_t __not_found) const - _GLIBCXX_NOEXCEPT - { - ++__prev; - if (__prev >= ((size_t) _GLIBCXX_BITSET_BITS_PER_WORD)) - return __not_found; - - _WordT __x = _M_w >> __prev; - if (__x != 0) - return __builtin_ctzl(__x) + __prev; - else - return __not_found; - } - }; - - /** - * Base class, specialization for no storage (zero-length %bitset). - * - * See documentation for bitset. - */ - template<> - struct _Base_bitset<0> - { - typedef unsigned long _WordT; - - _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT - { } - -#if __cplusplus >= 201103L - constexpr _Base_bitset(unsigned long long) noexcept -#else - _Base_bitset(unsigned long) -#endif - { } - - static _GLIBCXX_CONSTEXPR size_t - _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT - { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } - - static _GLIBCXX_CONSTEXPR size_t - _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT - { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } - - static _GLIBCXX_CONSTEXPR size_t - _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT - { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } - - static _GLIBCXX_CONSTEXPR _WordT - _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT - { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } - - // This would normally give access to the data. The bounds-checking - // in the bitset class will prevent the user from getting this far, - // but (1) it must still return an lvalue to compile, and (2) the - // user might call _Unchecked_set directly, in which case this /needs/ - // to fail. Let's not penalize zero-length users unless they actually - // make an unchecked call; all the memory ugliness is therefore - // localized to this single should-never-get-this-far function. - _WordT& - _M_getword(size_t) _GLIBCXX_NOEXCEPT - { - __throw_out_of_range(__N("_Base_bitset::_M_getword")); - return *new _WordT; - } - - _GLIBCXX_CONSTEXPR _WordT - _M_getword(size_t) const _GLIBCXX_NOEXCEPT - { return 0; } - - _GLIBCXX_CONSTEXPR _WordT - _M_hiword() const _GLIBCXX_NOEXCEPT - { return 0; } - - void - _M_do_and(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT - { } - - void - _M_do_or(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT - { } - - void - _M_do_xor(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT - { } - - void - _M_do_left_shift(size_t) _GLIBCXX_NOEXCEPT - { } - - void - _M_do_right_shift(size_t) _GLIBCXX_NOEXCEPT - { } - - void - _M_do_flip() _GLIBCXX_NOEXCEPT - { } - - void - _M_do_set() _GLIBCXX_NOEXCEPT - { } - - void - _M_do_reset() _GLIBCXX_NOEXCEPT - { } - - // Are all empty bitsets equal to each other? Are they equal to - // themselves? How to compare a thing which has no state? What is - // the sound of one zero-length bitset clapping? - bool - _M_is_equal(const _Base_bitset<0>&) const _GLIBCXX_NOEXCEPT - { return true; } - - template - bool - _M_are_all() const _GLIBCXX_NOEXCEPT - { return true; } - - bool - _M_is_any() const _GLIBCXX_NOEXCEPT - { return false; } - - size_t - _M_do_count() const _GLIBCXX_NOEXCEPT - { return 0; } - - unsigned long - _M_do_to_ulong() const _GLIBCXX_NOEXCEPT - { return 0; } - -#if __cplusplus >= 201103L - unsigned long long - _M_do_to_ullong() const noexcept - { return 0; } -#endif - - // Normally "not found" is the size, but that could also be - // misinterpreted as an index in this corner case. Oh well. - size_t - _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT - { return 0; } - - size_t - _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT - { return 0; } - }; - - - // Helper class to zero out the unused high-order bits in the highest word. - template - struct _Sanitize - { - typedef unsigned long _WordT; - - static void - _S_do_sanitize(_WordT& __val) _GLIBCXX_NOEXCEPT - { __val &= ~((~static_cast<_WordT>(0)) << _Extrabits); } - }; - - template<> - struct _Sanitize<0> - { - typedef unsigned long _WordT; - - static void - _S_do_sanitize(_WordT) _GLIBCXX_NOEXCEPT { } - }; - -#if __cplusplus >= 201103L - template - struct _Sanitize_val - { - static constexpr unsigned long long - _S_do_sanitize_val(unsigned long long __val) - { return __val; } - }; - - template - struct _Sanitize_val<_Nb, true> - { - static constexpr unsigned long long - _S_do_sanitize_val(unsigned long long __val) - { return __val & ~((~static_cast(0)) << _Nb); } - }; -#endif - - /** - * @brief The %bitset class represents a @e fixed-size sequence of bits. - * @ingroup utilities - * - * (Note that %bitset does @e not meet the formal requirements of a - * container. Mainly, it lacks iterators.) - * - * The template argument, @a Nb, may be any non-negative number, - * specifying the number of bits (e.g., "0", "12", "1024*1024"). - * - * In the general unoptimized case, storage is allocated in word-sized - * blocks. Let B be the number of bits in a word, then (Nb+(B-1))/B - * words will be used for storage. B - Nb%B bits are unused. (They are - * the high-order bits in the highest word.) It is a class invariant - * that those unused bits are always zero. - * - * If you think of %bitset as a simple array of bits, be - * aware that your mental picture is reversed: a %bitset behaves - * the same way as bits in integers do, with the bit at index 0 in - * the least significant / right-hand position, and the bit at - * index Nb-1 in the most significant / left-hand position. - * Thus, unlike other containers, a %bitset's index counts from - * right to left, to put it very loosely. - * - * - * Also see: - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_containers.html - * for a description of extensions. - * - * Most of the actual code isn't contained in %bitset<> itself, but in the - * base class _Base_bitset. The base class works with whole words, not with - * individual bits. This allows us to specialize _Base_bitset for the - * important special case where the %bitset is only a single word. - * - * Extra confusion can result due to the fact that the storage for - * _Base_bitset @e is a regular array, and is indexed as such. This is - * carefully encapsulated. - */ - template - class bitset - : private _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> - { - private: - typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base; - typedef unsigned long _WordT; - - void _M_check(size_t __position, const char *__s) const - { - if (__position >= _Nb) - __throw_out_of_range_fmt(__N("%s: __position (which is %zu) " - ">= _Nb (which is %zu)"), - __s, __position, _Nb); - } - - void - _M_do_sanitize() _GLIBCXX_NOEXCEPT - { - typedef _Sanitize<_Nb % _GLIBCXX_BITSET_BITS_PER_WORD> __sanitize_type; - __sanitize_type::_S_do_sanitize(this->_M_hiword()); - } - -#if __cplusplus >= 201103L - friend struct std::hash; -#endif - - public: - /** - * This encapsulates the concept of a single bit. An instance of this - * class is a proxy for an actual bit; this way the individual bit - * operations are done as faster word-size bitwise instructions. - * - * Most users will never need to use this class directly; conversions - * to and from bool are automatic and should be transparent. Overloaded - * operators help to preserve the illusion. - * - * (On a typical system, this bit %reference is 64 - * times the size of an actual bit. Ha.) - */ - class reference - { - friend class bitset; - - _WordT* _M_wp; - size_t _M_bpos; - - // left undefined - reference(); - - public: - reference(bitset& __b, size_t __pos) _GLIBCXX_NOEXCEPT - { - _M_wp = &__b._M_getword(__pos); - _M_bpos = _Base::_S_whichbit(__pos); - } - -#if __cplusplus >= 201103L - reference(const reference&) = default; -#endif - - ~reference() _GLIBCXX_NOEXCEPT - { } - - // For b[i] = __x; - reference& - operator=(bool __x) _GLIBCXX_NOEXCEPT - { - if (__x) - *_M_wp |= _Base::_S_maskbit(_M_bpos); - else - *_M_wp &= ~_Base::_S_maskbit(_M_bpos); - return *this; - } - - // For b[i] = b[__j]; - reference& - operator=(const reference& __j) _GLIBCXX_NOEXCEPT - { - if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos))) - *_M_wp |= _Base::_S_maskbit(_M_bpos); - else - *_M_wp &= ~_Base::_S_maskbit(_M_bpos); - return *this; - } - - // Flips the bit - bool - operator~() const _GLIBCXX_NOEXCEPT - { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) == 0; } - - // For __x = b[i]; - operator bool() const _GLIBCXX_NOEXCEPT - { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; } - - // For b[i].flip(); - reference& - flip() _GLIBCXX_NOEXCEPT - { - *_M_wp ^= _Base::_S_maskbit(_M_bpos); - return *this; - } - }; - friend class reference; - - // 23.3.5.1 constructors: - /// All bits set to zero. - _GLIBCXX_CONSTEXPR bitset() _GLIBCXX_NOEXCEPT - { } - - /// Initial bits bitwise-copied from a single word (others set to zero). -#if __cplusplus >= 201103L - constexpr bitset(unsigned long long __val) noexcept - : _Base(_Sanitize_val<_Nb>::_S_do_sanitize_val(__val)) { } -#else - bitset(unsigned long __val) - : _Base(__val) - { _M_do_sanitize(); } -#endif - - // 23.3.5.2 bitset operations: - //@{ - /** - * Operations on bitsets. - * @param __rhs A same-sized bitset. - * - * These should be self-explanatory. - */ - bitset<_Nb>& - operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT - { - this->_M_do_and(__rhs); - return *this; - } - - bitset<_Nb>& - operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT - { - this->_M_do_or(__rhs); - return *this; - } - - bitset<_Nb>& - operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT - { - this->_M_do_xor(__rhs); - return *this; - } - //@} - - //@{ - /** - * Operations on bitsets. - * @param __position The number of places to shift. - * - * These should be self-explanatory. - */ - bitset<_Nb>& - operator<<=(size_t __position) _GLIBCXX_NOEXCEPT - { - if (__builtin_expect(__position < _Nb, 1)) - { - this->_M_do_left_shift(__position); - this->_M_do_sanitize(); - } - else - this->_M_do_reset(); - return *this; - } - - bitset<_Nb>& - operator>>=(size_t __position) _GLIBCXX_NOEXCEPT - { - if (__builtin_expect(__position < _Nb, 1)) - { - this->_M_do_right_shift(__position); - this->_M_do_sanitize(); - } - else - this->_M_do_reset(); - return *this; - } - //@} - - //@{ - /** - * These versions of single-bit set, reset, flip, and test are - * extensions from the SGI version. They do no range checking. - * @ingroup SGIextensions - */ - bitset<_Nb>& - _Unchecked_set(size_t __pos) _GLIBCXX_NOEXCEPT - { - this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); - return *this; - } - - bitset<_Nb>& - _Unchecked_set(size_t __pos, int __val) _GLIBCXX_NOEXCEPT - { - if (__val) - this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); - else - this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); - return *this; - } - - bitset<_Nb>& - _Unchecked_reset(size_t __pos) _GLIBCXX_NOEXCEPT - { - this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); - return *this; - } - - bitset<_Nb>& - _Unchecked_flip(size_t __pos) _GLIBCXX_NOEXCEPT - { - this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos); - return *this; - } - - _GLIBCXX_CONSTEXPR bool - _Unchecked_test(size_t __pos) const _GLIBCXX_NOEXCEPT - { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos)) - != static_cast<_WordT>(0)); } - //@} - - // Set, reset, and flip. - /** - * @brief Sets every bit to true. - */ - bitset<_Nb>& - set() _GLIBCXX_NOEXCEPT - { - this->_M_do_set(); - this->_M_do_sanitize(); - return *this; - } - - /** - * @brief Sets a given bit to a particular value. - * @param __position The index of the bit. - * @param __val Either true or false, defaults to true. - * @throw std::out_of_range If @a pos is bigger the size of the %set. - */ - bitset<_Nb>& - set(size_t __position, bool __val = true) - { - this->_M_check(__position, __N("bitset::set")); - return _Unchecked_set(__position, __val); - } - - /** - * @brief Sets every bit to false. - */ - bitset<_Nb>& - reset() _GLIBCXX_NOEXCEPT - { - this->_M_do_reset(); - return *this; - } - - /** - * @brief Sets a given bit to false. - * @param __position The index of the bit. - * @throw std::out_of_range If @a pos is bigger the size of the %set. - * - * Same as writing @c set(pos,false). - */ - bitset<_Nb>& - reset(size_t __position) - { - this->_M_check(__position, __N("bitset::reset")); - return _Unchecked_reset(__position); - } - - /** - * @brief Toggles every bit to its opposite value. - */ - bitset<_Nb>& - flip() _GLIBCXX_NOEXCEPT - { - this->_M_do_flip(); - this->_M_do_sanitize(); - return *this; - } - - /** - * @brief Toggles a given bit to its opposite value. - * @param __position The index of the bit. - * @throw std::out_of_range If @a pos is bigger the size of the %set. - */ - bitset<_Nb>& - flip(size_t __position) - { - this->_M_check(__position, __N("bitset::flip")); - return _Unchecked_flip(__position); - } - - /// See the no-argument flip(). - bitset<_Nb> - operator~() const _GLIBCXX_NOEXCEPT - { return bitset<_Nb>(*this).flip(); } - - //@{ - /** - * @brief Array-indexing support. - * @param __position Index into the %bitset. - * @return A bool for a const %bitset. For non-const - * bitsets, an instance of the reference proxy class. - * @note These operators do no range checking and throw no exceptions, - * as required by DR 11 to the standard. - * - * _GLIBCXX_RESOLVE_LIB_DEFECTS Note that this implementation already - * resolves DR 11 (items 1 and 2), but does not do the range-checking - * required by that DR's resolution. -pme - * The DR has since been changed: range-checking is a precondition - * (users' responsibility), and these functions must not throw. -pme - */ - reference - operator[](size_t __position) - { return reference(*this, __position); } - - _GLIBCXX_CONSTEXPR bool - operator[](size_t __position) const - { return _Unchecked_test(__position); } - //@} - - /** - * @brief Returns a numerical interpretation of the %bitset. - * @return The integral equivalent of the bits. - * @throw std::overflow_error If there are too many bits to be - * represented in an @c unsigned @c long. - */ - unsigned long - to_ulong() const - { return this->_M_do_to_ulong(); } - -#if __cplusplus >= 201103L - unsigned long long - to_ullong() const - { return this->_M_do_to_ullong(); } -#endif - - /// Returns the number of bits which are set. - size_t - count() const _GLIBCXX_NOEXCEPT - { return this->_M_do_count(); } - - /// Returns the total number of bits. - _GLIBCXX_CONSTEXPR size_t - size() const _GLIBCXX_NOEXCEPT - { return _Nb; } - - //@{ - /// These comparisons for equality/inequality are, well, @e bitwise. - bool - operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT - { return this->_M_is_equal(__rhs); } - -#if __cpp_impl_three_way_comparison < 201907L - bool - operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT - { return !this->_M_is_equal(__rhs); } -#endif - //@} - - /** - * @brief Tests the value of a bit. - * @param __position The index of a bit. - * @return The value at @a pos. - * @throw std::out_of_range If @a pos is bigger the size of the %set. - */ - bool - test(size_t __position) const - { - this->_M_check(__position, __N("bitset::test")); - return _Unchecked_test(__position); - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 693. std::bitset::all() missing. - /** - * @brief Tests whether all the bits are on. - * @return True if all the bits are set. - */ - bool - all() const _GLIBCXX_NOEXCEPT - { return this->template _M_are_all<_Nb>(); } - - /** - * @brief Tests whether any of the bits are on. - * @return True if at least one bit is set. - */ - bool - any() const _GLIBCXX_NOEXCEPT - { return this->_M_is_any(); } - - /** - * @brief Tests whether any of the bits are on. - * @return True if none of the bits are set. - */ - bool - none() const _GLIBCXX_NOEXCEPT - { return !this->_M_is_any(); } - - //@{ - /// Self-explanatory. - bitset<_Nb> - operator<<(size_t __position) const _GLIBCXX_NOEXCEPT - { return bitset<_Nb>(*this) <<= __position; } - - bitset<_Nb> - operator>>(size_t __position) const _GLIBCXX_NOEXCEPT - { return bitset<_Nb>(*this) >>= __position; } - //@} - - /** - * @brief Finds the index of the first "on" bit. - * @return The index of the first bit set, or size() if not found. - * @ingroup SGIextensions - * @sa _Find_next - */ - size_t - _Find_first() const _GLIBCXX_NOEXCEPT - { return this->_M_do_find_first(_Nb); } - - /** - * @brief Finds the index of the next "on" bit after prev. - * @return The index of the next bit set, or size() if not found. - * @param __prev Where to start searching. - * @ingroup SGIextensions - * @sa _Find_first - */ - size_t - _Find_next(size_t __prev) const _GLIBCXX_NOEXCEPT - { return this->_M_do_find_next(__prev, _Nb); } - }; - - // 23.3.5.3 bitset operations: - //@{ - /** - * @brief Global bitwise operations on bitsets. - * @param __x A bitset. - * @param __y A bitset of the same size as @a __x. - * @return A new bitset. - * - * These should be self-explanatory. - */ - template - inline bitset<_Nb> - operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT - { - bitset<_Nb> __result(__x); - __result &= __y; - return __result; - } - - template - inline bitset<_Nb> - operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT - { - bitset<_Nb> __result(__x); - __result |= __y; - return __result; - } - - template - inline bitset<_Nb> - operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT - { - bitset<_Nb> __result(__x); - __result ^= __y; - return __result; - } - //@} - -_GLIBCXX_END_NAMESPACE_CONTAINER -} // namespace std - -#undef _GLIBCXX_BITSET_WORDS -#undef _GLIBCXX_BITSET_BITS_PER_WORD -#undef _GLIBCXX_BITSET_BITS_PER_ULL - -#if __cplusplus >= 201103L - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // DR 1182. - /// std::hash specialization for bitset. - template - struct hash<_GLIBCXX_STD_C::bitset<_Nb>> - : public __hash_base> - { - size_t - operator()(const _GLIBCXX_STD_C::bitset<_Nb>& __b) const noexcept - { - const size_t __clength = (_Nb + __CHAR_BIT__ - 1) / __CHAR_BIT__; - return std::_Hash_impl::hash(__b._M_getdata(), __clength); - } - }; - - template<> - struct hash<_GLIBCXX_STD_C::bitset<0>> - : public __hash_base> - { - size_t - operator()(const _GLIBCXX_STD_C::bitset<0>&) const noexcept - { return 0; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#endif /* _GLIBCXX_BITSET */ diff --git a/resources/sources/avr-libstdcpp/include/cassert b/resources/sources/avr-libstdcpp/include/cassert deleted file mode 100644 index e1c0724b8..000000000 --- a/resources/sources/avr-libstdcpp/include/cassert +++ /dev/null @@ -1,44 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file cassert - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c assert.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 19.2 Assertions -// - -// No include guards on this header... - -#pragma GCC system_header - -#include -#include diff --git a/resources/sources/avr-libstdcpp/include/ccomplex b/resources/sources/avr-libstdcpp/include/ccomplex deleted file mode 100644 index 7a9044444..000000000 --- a/resources/sources/avr-libstdcpp/include/ccomplex +++ /dev/null @@ -1,42 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/ccomplex - * This is a Standard C++ Library header. - */ - -#pragma GCC system_header - -#ifndef _GLIBCXX_CCOMPLEX -#define _GLIBCXX_CCOMPLEX 1 - -#if __cplusplus < 201103L -# include -#endif - -extern "C++" { -#include -} - -#endif diff --git a/resources/sources/avr-libstdcpp/include/cctype b/resources/sources/avr-libstdcpp/include/cctype deleted file mode 100644 index 0881d47c8..000000000 --- a/resources/sources/avr-libstdcpp/include/cctype +++ /dev/null @@ -1,94 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cctype - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c ctype.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: -// - -#pragma GCC system_header - -#include -#include - -#ifndef _GLIBCXX_CCTYPE -#define _GLIBCXX_CCTYPE 1 - -// Get rid of those macros defined in in lieu of real functions. -#undef isalnum -#undef isalpha -#undef iscntrl -#undef isdigit -#undef isgraph -#undef islower -#undef isprint -#undef ispunct -#undef isspace -#undef isupper -#undef isxdigit -#undef tolower -#undef toupper - -namespace std -{ - using ::isalnum; - using ::isalpha; - using ::iscntrl; - using ::isdigit; - using ::isgraph; - using ::islower; - using ::isprint; - using ::ispunct; - using ::isspace; - using ::isupper; - using ::isxdigit; - using ::tolower; - using ::toupper; -} // namespace std - -#if __cplusplus >= 201103L - -#ifdef _GLIBCXX_USE_C99_CTYPE_TR1 - -#undef isblank - -namespace std -{ - using ::isblank; -} // namespace std - -#endif // _GLIBCXX_USE_C99_CTYPE_TR1 - -#endif // C++11 - -#endif diff --git a/resources/sources/avr-libstdcpp/include/cerrno b/resources/sources/avr-libstdcpp/include/cerrno deleted file mode 100644 index 83cbf24a0..000000000 --- a/resources/sources/avr-libstdcpp/include/cerrno +++ /dev/null @@ -1,52 +0,0 @@ -// The -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file cerrno - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c errno.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 19.3 Error numbers -// - -#pragma GCC system_header - -#include -#include - -#ifndef _GLIBCXX_CERRNO -#define _GLIBCXX_CERRNO 1 - -// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 -#ifndef errno -#define errno errno -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/cfenv b/resources/sources/avr-libstdcpp/include/cfenv deleted file mode 100644 index 376eea234..000000000 --- a/resources/sources/avr-libstdcpp/include/cfenv +++ /dev/null @@ -1,84 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cfenv - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_CFENV -#define _GLIBCXX_CFENV 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include - -#if _GLIBCXX_HAVE_FENV_H -# include -#endif - -#ifdef _GLIBCXX_USE_C99_FENV_TR1 - -#undef feclearexcept -#undef fegetexceptflag -#undef feraiseexcept -#undef fesetexceptflag -#undef fetestexcept -#undef fegetround -#undef fesetround -#undef fegetenv -#undef feholdexcept -#undef fesetenv -#undef feupdateenv - -namespace std -{ - // types - using ::fenv_t; - using ::fexcept_t; - - // functions - using ::feclearexcept; - using ::fegetexceptflag; - using ::feraiseexcept; - using ::fesetexceptflag; - using ::fetestexcept; - - using ::fegetround; - using ::fesetround; - - using ::fegetenv; - using ::feholdexcept; - using ::fesetenv; - using ::feupdateenv; -} // namespace std - -#endif // _GLIBCXX_USE_C99_FENV_TR1 - -#endif // C++11 - -#endif // _GLIBCXX_CFENV diff --git a/resources/sources/avr-libstdcpp/include/cfloat b/resources/sources/avr-libstdcpp/include/cfloat deleted file mode 100644 index 3c20ea8f9..000000000 --- a/resources/sources/avr-libstdcpp/include/cfloat +++ /dev/null @@ -1,56 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cfloat - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c float.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 18.2.2 Implementation properties: C library -// - -#pragma GCC system_header - -#include -#include - -#ifndef _GLIBCXX_CFLOAT -#define _GLIBCXX_CFLOAT 1 - -#if __cplusplus >= 201103L -# ifndef DECIMAL_DIG -# define DECIMAL_DIG __DECIMAL_DIG__ -# endif -# ifndef FLT_EVAL_METHOD -# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ -# endif -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/chrono b/resources/sources/avr-libstdcpp/include/chrono deleted file mode 100644 index ad8507090..000000000 --- a/resources/sources/avr-libstdcpp/include/chrono +++ /dev/null @@ -1,1131 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/chrono - * This is a Standard C++ Library header. - * @ingroup chrono - */ - -#ifndef _GLIBCXX_CHRONO -#define _GLIBCXX_CHRONO 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include -#include -#include // for literals support. -#if __cplusplus > 201703L -# include -# include -#endif -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup chrono Time - * @ingroup utilities - * - * Classes and functions for time. - * @{ - */ - - /** @namespace std::chrono - * @brief ISO C++ 2011 namespace for date and time utilities - */ - namespace chrono - { - template> - struct duration; - - template - struct time_point; - } - - // 20.11.4.3 specialization of common_type (for duration, sfinae-friendly) - - /// @cond undocumented - - template - struct __duration_common_type - { }; - - template - struct __duration_common_type<_CT, _Period1, _Period2, - __void_t> - { - private: - using __gcd_num = __static_gcd<_Period1::num, _Period2::num>; - using __gcd_den = __static_gcd<_Period1::den, _Period2::den>; - using __cr = typename _CT::type; - using __r = ratio<__gcd_num::value, - (_Period1::den / __gcd_den::value) * _Period2::den>; - - public: - using type = chrono::duration<__cr, __r>; - }; - - template - struct __duration_common_type<__failure_type, _Period1, _Period2> - { typedef __failure_type type; }; - - /// @endcond - - /// Specialization of common_type for chrono::duration types. - /// @relates duration - template - struct common_type, - chrono::duration<_Rep2, _Period2>> - : __duration_common_type, _Period1, _Period2> - { }; - - // 20.11.4.3 specialization of common_type (for time_point, sfinae-friendly) - - /// @cond undocumented - - template - struct __timepoint_common_type - { }; - - template - struct __timepoint_common_type<_CT, _Clock, __void_t> - { - using type = chrono::time_point<_Clock, typename _CT::type>; - }; - - /// @endcond - - /// Specialization of common_type for chrono::time_point types. - /// @relates time_point - template - struct common_type, - chrono::time_point<_Clock, _Duration2>> - : __timepoint_common_type, _Clock> - { }; - - // @} group chrono - - namespace chrono - { - /// @addtogroup chrono - /// @{ - - /// @cond undocumented - - // Primary template for duration_cast impl. - template - struct __duration_cast_impl - { - template - static constexpr _ToDur - __cast(const duration<_Rep, _Period>& __d) - { - typedef typename _ToDur::rep __to_rep; - return _ToDur(static_cast<__to_rep>(static_cast<_CR>(__d.count()) - * static_cast<_CR>(_CF::num) - / static_cast<_CR>(_CF::den))); - } - }; - - template - struct __duration_cast_impl<_ToDur, _CF, _CR, true, true> - { - template - static constexpr _ToDur - __cast(const duration<_Rep, _Period>& __d) - { - typedef typename _ToDur::rep __to_rep; - return _ToDur(static_cast<__to_rep>(__d.count())); - } - }; - - template - struct __duration_cast_impl<_ToDur, _CF, _CR, true, false> - { - template - static constexpr _ToDur - __cast(const duration<_Rep, _Period>& __d) - { - typedef typename _ToDur::rep __to_rep; - return _ToDur(static_cast<__to_rep>( - static_cast<_CR>(__d.count()) / static_cast<_CR>(_CF::den))); - } - }; - - template - struct __duration_cast_impl<_ToDur, _CF, _CR, false, true> - { - template - static constexpr _ToDur - __cast(const duration<_Rep, _Period>& __d) - { - typedef typename _ToDur::rep __to_rep; - return _ToDur(static_cast<__to_rep>( - static_cast<_CR>(__d.count()) * static_cast<_CR>(_CF::num))); - } - }; - - template - struct __is_duration - : std::false_type - { }; - - template - struct __is_duration> - : std::true_type - { }; - - template - using __enable_if_is_duration - = typename enable_if<__is_duration<_Tp>::value, _Tp>::type; - - template - using __disable_if_is_duration - = typename enable_if::value, _Tp>::type; - - /// @endcond - - /// duration_cast - template - constexpr __enable_if_is_duration<_ToDur> - duration_cast(const duration<_Rep, _Period>& __d) - { - typedef typename _ToDur::period __to_period; - typedef typename _ToDur::rep __to_rep; - typedef ratio_divide<_Period, __to_period> __cf; - typedef typename common_type<__to_rep, _Rep, intmax_t>::type - __cr; - typedef __duration_cast_impl<_ToDur, __cf, __cr, - __cf::num == 1, __cf::den == 1> __dc; - return __dc::__cast(__d); - } - - /// treat_as_floating_point - template - struct treat_as_floating_point - : is_floating_point<_Rep> - { }; - -#if __cplusplus > 201402L - template - inline constexpr bool treat_as_floating_point_v = - treat_as_floating_point<_Rep>::value; -#endif // C++17 - -#if __cplusplus > 201703L - template - struct is_clock; - - template - inline constexpr bool is_clock_v = is_clock<_Tp>::value; - -#if __cpp_lib_concepts - template - struct is_clock : false_type - { }; - - template - requires requires { - typename _Tp::rep; - typename _Tp::period; - typename _Tp::duration; - typename _Tp::time_point::clock; - typename _Tp::time_point::duration; - { &_Tp::is_steady } -> same_as; - { _Tp::now() } -> same_as; - requires same_as>; - requires same_as; - } - struct is_clock<_Tp> : true_type - { }; -#else - template - struct __is_clock_impl : false_type - { }; - - template - struct __is_clock_impl<_Tp, - void_t> - : __and_>, - is_same, - is_same, - is_same>::type - { }; - - template - struct is_clock : __is_clock_impl<_Tp>::type - { }; -#endif -#endif // C++20 - -#if __cplusplus >= 201703L -# define __cpp_lib_chrono 201611 - - template - constexpr __enable_if_is_duration<_ToDur> - floor(const duration<_Rep, _Period>& __d) - { - auto __to = chrono::duration_cast<_ToDur>(__d); - if (__to > __d) - return __to - _ToDur{1}; - return __to; - } - - template - constexpr __enable_if_is_duration<_ToDur> - ceil(const duration<_Rep, _Period>& __d) - { - auto __to = chrono::duration_cast<_ToDur>(__d); - if (__to < __d) - return __to + _ToDur{1}; - return __to; - } - - template - constexpr enable_if_t< - __and_<__is_duration<_ToDur>, - __not_>>::value, - _ToDur> - round(const duration<_Rep, _Period>& __d) - { - _ToDur __t0 = chrono::floor<_ToDur>(__d); - _ToDur __t1 = __t0 + _ToDur{1}; - auto __diff0 = __d - __t0; - auto __diff1 = __t1 - __d; - if (__diff0 == __diff1) - { - if (__t0.count() & 1) - return __t1; - return __t0; - } - else if (__diff0 < __diff1) - return __t0; - return __t1; - } - - template - constexpr - enable_if_t::is_signed, duration<_Rep, _Period>> - abs(duration<_Rep, _Period> __d) - { - if (__d >= __d.zero()) - return __d; - return -__d; - } -#endif // C++17 - - /// duration_values - template - struct duration_values - { - static constexpr _Rep - zero() noexcept - { return _Rep(0); } - - static constexpr _Rep - max() noexcept - { return numeric_limits<_Rep>::max(); } - - static constexpr _Rep - min() noexcept - { return numeric_limits<_Rep>::lowest(); } - }; - - /// @cond undocumented - - template - struct __is_ratio - : std::false_type - { }; - - template - struct __is_ratio> - : std::true_type - { }; - - /// @endcond - - /// duration - template - struct duration - { - private: - template - using __is_float = treat_as_floating_point<_Rep2>; - - // _Period2 is an exact multiple of _Period - template - using __is_harmonic - = __bool_constant::den == 1>; - - public: - - typedef _Rep rep; - typedef _Period period; - - static_assert(!__is_duration<_Rep>::value, "rep cannot be a duration"); - static_assert(__is_ratio<_Period>::value, - "period must be a specialization of ratio"); - static_assert(_Period::num > 0, "period must be positive"); - - // 20.11.5.1 construction / copy / destroy - constexpr duration() = default; - - duration(const duration&) = default; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3050. Conversion specification problem in chrono::duration - template, - __or_<__is_float, __not_<__is_float<_Rep2>>>>> - constexpr explicit duration(const _Rep2& __rep) - : __r(static_cast(__rep)) { } - - template, - __and_<__is_harmonic<_Period2>, - __not_<__is_float<_Rep2>>>>>> - constexpr duration(const duration<_Rep2, _Period2>& __d) - : __r(duration_cast(__d).count()) { } - - ~duration() = default; - duration& operator=(const duration&) = default; - - // 20.11.5.2 observer - constexpr rep - count() const - { return __r; } - - // 20.11.5.3 arithmetic - constexpr duration - operator+() const - { return *this; } - - constexpr duration - operator-() const - { return duration(-__r); } - - _GLIBCXX17_CONSTEXPR duration& - operator++() - { - ++__r; - return *this; - } - - _GLIBCXX17_CONSTEXPR duration - operator++(int) - { return duration(__r++); } - - _GLIBCXX17_CONSTEXPR duration& - operator--() - { - --__r; - return *this; - } - - _GLIBCXX17_CONSTEXPR duration - operator--(int) - { return duration(__r--); } - - _GLIBCXX17_CONSTEXPR duration& - operator+=(const duration& __d) - { - __r += __d.count(); - return *this; - } - - _GLIBCXX17_CONSTEXPR duration& - operator-=(const duration& __d) - { - __r -= __d.count(); - return *this; - } - - _GLIBCXX17_CONSTEXPR duration& - operator*=(const rep& __rhs) - { - __r *= __rhs; - return *this; - } - - _GLIBCXX17_CONSTEXPR duration& - operator/=(const rep& __rhs) - { - __r /= __rhs; - return *this; - } - - // DR 934. - template - _GLIBCXX17_CONSTEXPR - typename enable_if::value, - duration&>::type - operator%=(const rep& __rhs) - { - __r %= __rhs; - return *this; - } - - template - _GLIBCXX17_CONSTEXPR - typename enable_if::value, - duration&>::type - operator%=(const duration& __d) - { - __r %= __d.count(); - return *this; - } - - // 20.11.5.4 special values - static constexpr duration - zero() noexcept - { return duration(duration_values::zero()); } - - static constexpr duration - min() noexcept - { return duration(duration_values::min()); } - - static constexpr duration - max() noexcept - { return duration(duration_values::max()); } - - private: - rep __r; - }; - - /// @relates duration @{ - - /// The sum of two durations. - template - constexpr typename common_type, - duration<_Rep2, _Period2>>::type - operator+(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - typedef duration<_Rep1, _Period1> __dur1; - typedef duration<_Rep2, _Period2> __dur2; - typedef typename common_type<__dur1,__dur2>::type __cd; - return __cd(__cd(__lhs).count() + __cd(__rhs).count()); - } - - /// The difference between two durations. - template - constexpr typename common_type, - duration<_Rep2, _Period2>>::type - operator-(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - typedef duration<_Rep1, _Period1> __dur1; - typedef duration<_Rep2, _Period2> __dur2; - typedef typename common_type<__dur1,__dur2>::type __cd; - return __cd(__cd(__lhs).count() - __cd(__rhs).count()); - } - - /// @} - - /// @cond undocumented - - // SFINAE helper to obtain common_type<_Rep1, _Rep2> only if _Rep2 - // is implicitly convertible to it. - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3050. Conversion specification problem in chrono::duration constructor - template::type> - using __common_rep_t = typename - enable_if::value, _CRep>::type; - - /// @endcond - - /// @relates duration @{ - - /// Multiply a duration by a scalar value. - template - constexpr duration<__common_rep_t<_Rep1, _Rep2>, _Period> - operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) - { - typedef duration::type, _Period> - __cd; - return __cd(__cd(__d).count() * __s); - } - - /// Multiply a duration by a scalar value. - template - constexpr duration<__common_rep_t<_Rep2, _Rep1>, _Period> - operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) - { return __d * __s; } - - template - constexpr - duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period> - operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) - { - typedef duration::type, _Period> - __cd; - return __cd(__cd(__d).count() / __s); - } - - template - constexpr typename common_type<_Rep1, _Rep2>::type - operator/(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - typedef duration<_Rep1, _Period1> __dur1; - typedef duration<_Rep2, _Period2> __dur2; - typedef typename common_type<__dur1,__dur2>::type __cd; - return __cd(__lhs).count() / __cd(__rhs).count(); - } - - // DR 934. - template - constexpr - duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period> - operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) - { - typedef duration::type, _Period> - __cd; - return __cd(__cd(__d).count() % __s); - } - - template - constexpr typename common_type, - duration<_Rep2, _Period2>>::type - operator%(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - typedef duration<_Rep1, _Period1> __dur1; - typedef duration<_Rep2, _Period2> __dur2; - typedef typename common_type<__dur1,__dur2>::type __cd; - return __cd(__cd(__lhs).count() % __cd(__rhs).count()); - } - - // comparisons - - template - constexpr bool - operator==(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - typedef duration<_Rep1, _Period1> __dur1; - typedef duration<_Rep2, _Period2> __dur2; - typedef typename common_type<__dur1,__dur2>::type __ct; - return __ct(__lhs).count() == __ct(__rhs).count(); - } - - template - constexpr bool - operator<(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - typedef duration<_Rep1, _Period1> __dur1; - typedef duration<_Rep2, _Period2> __dur2; - typedef typename common_type<__dur1,__dur2>::type __ct; - return __ct(__lhs).count() < __ct(__rhs).count(); - } - -#if __cpp_lib_three_way_comparison - template - requires three_way_comparable> - constexpr auto - operator<=>(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - using __ct = common_type_t, - duration<_Rep2, _Period2>>; - return __ct(__lhs).count() <=> __ct(__rhs).count(); - } -#else - template - constexpr bool - operator!=(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { return !(__lhs == __rhs); } -#endif - - template - constexpr bool - operator<=(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { return !(__rhs < __lhs); } - - template - constexpr bool - operator>(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { return __rhs < __lhs; } - - template - constexpr bool - operator>=(const duration<_Rep1, _Period1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { return !(__lhs < __rhs); } - - /// @} - -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 -# define _GLIBCXX_CHRONO_INT64_T int64_t -#elif defined __INT64_TYPE__ -# define _GLIBCXX_CHRONO_INT64_T __INT64_TYPE__ -#else - static_assert(std::numeric_limits::digits >= 64, - "Representation type for nanoseconds must have at least 64 bits"); -# define _GLIBCXX_CHRONO_INT64_T long long -#endif - - /// nanoseconds - using nanoseconds = duration<_GLIBCXX_CHRONO_INT64_T, nano>; - - /// microseconds - using microseconds = duration<_GLIBCXX_CHRONO_INT64_T, micro>; - - /// milliseconds - using milliseconds = duration<_GLIBCXX_CHRONO_INT64_T, milli>; - - /// seconds - using seconds = duration<_GLIBCXX_CHRONO_INT64_T>; - - /// minutes - using minutes = duration<_GLIBCXX_CHRONO_INT64_T, ratio< 60>>; - - /// hours - using hours = duration<_GLIBCXX_CHRONO_INT64_T, ratio<3600>>; - -#if __cplusplus > 201703L - /// days - using days = duration<_GLIBCXX_CHRONO_INT64_T, ratio<86400>>; - - /// weeks - using weeks = duration<_GLIBCXX_CHRONO_INT64_T, ratio<604800>>; - - /// years - using years = duration<_GLIBCXX_CHRONO_INT64_T, ratio<31556952>>; - - /// months - using months = duration<_GLIBCXX_CHRONO_INT64_T, ratio<2629746>>; -#endif // C++20 - -#undef _GLIBCXX_CHRONO_INT64_T - - /// time_point - template - struct time_point - { - static_assert(__is_duration<_Dur>::value, - "duration must be a specialization of std::chrono::duration"); - - typedef _Clock clock; - typedef _Dur duration; - typedef typename duration::rep rep; - typedef typename duration::period period; - - constexpr time_point() : __d(duration::zero()) - { } - - constexpr explicit time_point(const duration& __dur) - : __d(__dur) - { } - - // conversions - template>> - constexpr time_point(const time_point& __t) - : __d(__t.time_since_epoch()) - { } - - // observer - constexpr duration - time_since_epoch() const - { return __d; } - - // arithmetic - _GLIBCXX17_CONSTEXPR time_point& - operator+=(const duration& __dur) - { - __d += __dur; - return *this; - } - - _GLIBCXX17_CONSTEXPR time_point& - operator-=(const duration& __dur) - { - __d -= __dur; - return *this; - } - - // special values - static constexpr time_point - min() noexcept - { return time_point(duration::min()); } - - static constexpr time_point - max() noexcept - { return time_point(duration::max()); } - - private: - duration __d; - }; - - /// time_point_cast - template - constexpr typename enable_if<__is_duration<_ToDur>::value, - time_point<_Clock, _ToDur>>::type - time_point_cast(const time_point<_Clock, _Dur>& __t) - { - typedef time_point<_Clock, _ToDur> __time_point; - return __time_point(duration_cast<_ToDur>(__t.time_since_epoch())); - } - -#if __cplusplus > 201402L - template - constexpr - enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>> - floor(const time_point<_Clock, _Dur>& __tp) - { - return time_point<_Clock, _ToDur>{ - chrono::floor<_ToDur>(__tp.time_since_epoch())}; - } - - template - constexpr - enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>> - ceil(const time_point<_Clock, _Dur>& __tp) - { - return time_point<_Clock, _ToDur>{ - chrono::ceil<_ToDur>(__tp.time_since_epoch())}; - } - - template - constexpr enable_if_t< - __and_<__is_duration<_ToDur>, - __not_>>::value, - time_point<_Clock, _ToDur>> - round(const time_point<_Clock, _Dur>& __tp) - { - return time_point<_Clock, _ToDur>{ - chrono::round<_ToDur>(__tp.time_since_epoch())}; - } -#endif // C++17 - - /// @relates time_point @{ - - /// Adjust a time point forwards by the given duration. - template - constexpr time_point<_Clock, - typename common_type<_Dur1, duration<_Rep2, _Period2>>::type> - operator+(const time_point<_Clock, _Dur1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - typedef duration<_Rep2, _Period2> __dur2; - typedef typename common_type<_Dur1,__dur2>::type __ct; - typedef time_point<_Clock, __ct> __time_point; - return __time_point(__lhs.time_since_epoch() + __rhs); - } - - /// Adjust a time point forwards by the given duration. - template - constexpr time_point<_Clock, - typename common_type, _Dur2>::type> - operator+(const duration<_Rep1, _Period1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { - typedef duration<_Rep1, _Period1> __dur1; - typedef typename common_type<__dur1,_Dur2>::type __ct; - typedef time_point<_Clock, __ct> __time_point; - return __time_point(__rhs.time_since_epoch() + __lhs); - } - - /// Adjust a time point backwards by the given duration. - template - constexpr time_point<_Clock, - typename common_type<_Dur1, duration<_Rep2, _Period2>>::type> - operator-(const time_point<_Clock, _Dur1>& __lhs, - const duration<_Rep2, _Period2>& __rhs) - { - typedef duration<_Rep2, _Period2> __dur2; - typedef typename common_type<_Dur1,__dur2>::type __ct; - typedef time_point<_Clock, __ct> __time_point; - return __time_point(__lhs.time_since_epoch() -__rhs); - } - - /// @} - - /// @relates time_point @{ - - /// The difference between two time points (as a duration) - template - constexpr typename common_type<_Dur1, _Dur2>::type - operator-(const time_point<_Clock, _Dur1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { return __lhs.time_since_epoch() - __rhs.time_since_epoch(); } - - template - constexpr bool - operator==(const time_point<_Clock, _Dur1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { return __lhs.time_since_epoch() == __rhs.time_since_epoch(); } - -#if __cpp_lib_three_way_comparison - template _Dur2> - constexpr auto - operator<=>(const time_point<_Clock, _Dur1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { return __lhs.time_since_epoch() <=> __rhs.time_since_epoch(); } -#else - template - constexpr bool - operator!=(const time_point<_Clock, _Dur1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { return !(__lhs == __rhs); } -#endif - - template - constexpr bool - operator<(const time_point<_Clock, _Dur1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { return __lhs.time_since_epoch() < __rhs.time_since_epoch(); } - - template - constexpr bool - operator<=(const time_point<_Clock, _Dur1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { return !(__rhs < __lhs); } - - template - constexpr bool - operator>(const time_point<_Clock, _Dur1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { return __rhs < __lhs; } - - template - constexpr bool - operator>=(const time_point<_Clock, _Dur1>& __lhs, - const time_point<_Clock, _Dur2>& __rhs) - { return !(__lhs < __rhs); } - - // @} - // @} - } // namespace chrono - -#if __cplusplus > 201103L - -#define __cpp_lib_chrono_udls 201304 - - inline namespace literals - { - /** ISO C++ 2014 namespace for suffixes for duration literals. - * - * These suffixes can be used to create `chrono::duration` values with - * tick periods of hours, minutes, seconds, milliseconds, microseconds - * or nanoseconds. For example, `std::chrono::seconds(5)` can be written - * as `5s` after making the suffix visible in the current scope. - * The suffixes can be made visible by a using-directive or - * using-declaration such as: - * - `using namespace std::chrono_literals;` - * - `using namespace std::literals;` - * - `using namespace std::chrono;` - * - `using namespace std;` - * - `using std::chrono_literals::operator""s;` - * - * The result of these suffixes on an integer literal is one of the - * standard typedefs such as `std::chrono::hours`. - * The result on a floating-point literal is a duration type with the - * specified tick period and an unspecified floating-point representation, - * for example `1.5e2ms` might be equivalent to - * `chrono::duration(1.5e2)`. - * - * @ingroup chrono - */ - inline namespace chrono_literals - { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wliteral-suffix" - /// @cond undocumented - template - constexpr _Dur __check_overflow() - { - using _Val = __parse_int::_Parse_int<_Digits...>; - constexpr typename _Dur::rep __repval = _Val::value; - static_assert(__repval >= 0 && __repval == _Val::value, - "literal value cannot be represented by duration type"); - return _Dur(__repval); - } - /// @endcond - - /// Literal suffix for durations representing non-integer hours - constexpr chrono::duration> - operator""h(long double __hours) - { return chrono::duration>{__hours}; } - - /// Literal suffix for durations of type `std::chrono::hours` - template - constexpr chrono::hours - operator""h() - { return __check_overflow(); } - - /// Literal suffix for durations representing non-integer minutes - constexpr chrono::duration> - operator""min(long double __mins) - { return chrono::duration>{__mins}; } - - /// Literal suffix for durations of type `std::chrono::minutes` - template - constexpr chrono::minutes - operator""min() - { return __check_overflow(); } - - /// Literal suffix for durations representing non-integer seconds - constexpr chrono::duration - operator""s(long double __secs) - { return chrono::duration{__secs}; } - - /// Literal suffix for durations of type `std::chrono::seconds` - template - constexpr chrono::seconds - operator""s() - { return __check_overflow(); } - - /// Literal suffix for durations representing non-integer milliseconds - constexpr chrono::duration - operator""ms(long double __msecs) - { return chrono::duration{__msecs}; } - - /// Literal suffix for durations of type `std::chrono::milliseconds` - template - constexpr chrono::milliseconds - operator""ms() - { return __check_overflow(); } - - /// Literal suffix for durations representing non-integer microseconds - constexpr chrono::duration - operator""us(long double __usecs) - { return chrono::duration{__usecs}; } - - /// Literal suffix for durations of type `std::chrono::microseconds` - template - constexpr chrono::microseconds - operator""us() - { return __check_overflow(); } - - /// Literal suffix for durations representing non-integer nanoseconds - constexpr chrono::duration - operator""ns(long double __nsecs) - { return chrono::duration{__nsecs}; } - - /// Literal suffix for durations of type `std::chrono::nanoseconds` - template - constexpr chrono::nanoseconds - operator""ns() - { return __check_overflow(); } - -#pragma GCC diagnostic pop - } // inline namespace chrono_literals - } // inline namespace literals - - namespace chrono - { - using namespace literals::chrono_literals; - } // namespace chrono - -#endif // C++14 - - namespace chrono - { - class high_resolution_clock - { - public: - // The high_resolution_clock counter is steady. Each subsequent call - // of std::chrono::high_resolution_clock::now() returns a later time - // than any previous call. - static constexpr bool is_steady = true; - - // Defines the accuracy of the (hardware) high resolution clock. - using duration = chrono::microseconds; - using rep = duration::rep; - using period = duration::period; - using time_point = chrono::time_point; - - static auto to_time_t(const time_point& t) -> std::time_t - { - return static_cast(duration_cast(t.time_since_epoch()).count()); - } - - static auto from_time_t(std::time_t t) -> time_point - { - using local_from_type = chrono::time_point; - - return time_point_cast - ( - static_cast(chrono::seconds(t)) - ); - } - - // !!! PLATFORM AND OS SPECIFIC IMPLEMENTATION !!! - static auto now() noexcept -> time_point; - }; - - #if !defined(MODM_CHRONO_STEADY_CLOCK) - #define MODM_CHRONO_STEADY_CLOCK steady_clock - #endif - - // use high_resolution_clock as steady_clock - using MODM_CHRONO_STEADY_CLOCK = high_resolution_clock; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++11 - -#endif //_GLIBCXX_CHRONO diff --git a/resources/sources/avr-libstdcpp/include/cinttypes b/resources/sources/avr-libstdcpp/include/cinttypes deleted file mode 100644 index 252ee6926..000000000 --- a/resources/sources/avr-libstdcpp/include/cinttypes +++ /dev/null @@ -1,55 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cinttypes - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_CINTTYPES -#define _GLIBCXX_CINTTYPES 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include - -// For 27.9.2/3 (see C99, Note 184) -#if _GLIBCXX_HAVE_INTTYPES_H -# ifndef __STDC_FORMAT_MACROS -# define _UNDEF__STDC_FORMAT_MACROS -# define __STDC_FORMAT_MACROS -# endif -# include -# ifdef _UNDEF__STDC_FORMAT_MACROS -# undef __STDC_FORMAT_MACROS -# undef _UNDEF__STDC_FORMAT_MACROS -# endif -#endif - -#endif // C++11 - -#endif // _GLIBCXX_CINTTYPES diff --git a/resources/sources/avr-libstdcpp/include/ciso646 b/resources/sources/avr-libstdcpp/include/ciso646 deleted file mode 100644 index 05c29e9fb..000000000 --- a/resources/sources/avr-libstdcpp/include/ciso646 +++ /dev/null @@ -1,38 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ciso646 - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c iso646.h, - * which is empty in C++. - */ -#ifndef _GLIBCXX_CISO646 -#define _GLIBCXX_CISO646 - -#pragma GCC system_header - -#include -#endif diff --git a/resources/sources/avr-libstdcpp/include/climits b/resources/sources/avr-libstdcpp/include/climits deleted file mode 100644 index 09e8fcba2..000000000 --- a/resources/sources/avr-libstdcpp/include/climits +++ /dev/null @@ -1,59 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/climits - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c limits.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 18.2.2 Implementation properties: C library -// - -#pragma GCC system_header - -#include -#include - -#ifndef _GLIBCXX_CLIMITS -#define _GLIBCXX_CLIMITS 1 - -#ifndef LLONG_MIN -#define LLONG_MIN (-__LONG_LONG_MAX__ - 1) -#endif - -#ifndef LLONG_MAX -#define LLONG_MAX __LONG_LONG_MAX__ -#endif - -#ifndef ULLONG_MAX -#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/cmath b/resources/sources/avr-libstdcpp/include/cmath index 2232ef22b..7fb85d0ac 100644 --- a/resources/sources/avr-libstdcpp/include/cmath +++ b/resources/sources/avr-libstdcpp/include/cmath @@ -1,1924 +1,13 @@ -// -*- C++ -*- C forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cmath - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c math.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 26.5 C library -// - -#pragma GCC system_header - -#include -#include -#include -#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS -#include_next -#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS -#include - -#ifndef _GLIBCXX_CMATH -#define _GLIBCXX_CMATH 1 - -// Get rid of those macros defined in in lieu of real functions. -#undef div -#undef acos -#undef asin -#undef atan -#undef atan2 -#undef ceil -#undef cos -#undef cosh -#undef exp -#undef fabs -#undef floor -#undef fmod -#undef frexp -#undef ldexp -#undef log -#undef log10 -#undef modf -#undef pow -#undef sin -#undef sinh -#undef sqrt -#undef tan -#undef tanh - -// Fix float math functions defined as macros in avr libc -#ifdef __AVR__ - -#undef cosf -#undef sinf -#undef tanf -#undef fabsf -#undef fmodf -#undef cbrtf -#undef hypotf -#undef squaref -#undef floorf -#undef ceilf -#undef frexpf -#undef ldexpf -#undef expf -#undef coshf -#undef sinhf -#undef tanhf -#undef acosf -#undef asinf -#undef atanf -#undef atan2f -#undef logf -#undef log10f -#undef powf -#undef isnanf -#undef isinff -#undef isfinitef -#undef copysignf -#undef signbitf -#undef fdimf -#undef fmaf -#undef fmaxf -#undef fminf -#undef truncf -#undef roundf -#undef lroundf -#undef lrintf - -extern "C" -{ - float cosf(float x); - float sinf(float x); - float tanf(float x); - float fabsf(float x); - float fmodf(float x, float y); - float cbrtf(float x); - float hypotf(float x, float y); - float squaref(float x); - float floorf(float x); - float ceilf(float x); - float frexpf(float value, int* exp); - float ldexpf(float x, int exp); - float expf(float x); - float coshf(float x); - float sinhf(float x); - float tanhf(float x); - float acosf(float x); - float asinf(float x); - float atanf(float x); - float atan2f(float y, float x); - float logf(float x); - float log10f(float x); - float powf(float x, float y); - int isnanf(float x); - int isinff(float x); - int isfinitef(float x); - float copysignf(float x, float y); - int signbitf(float x); - float fdimf(float x, float y); - float fmaf(float x, float y, float z); - float fmaxf(float x, float y); - float fminf(float x, float y); - float truncf(float x); - float roundf(float x); - long lroundf(float x); - long lrintf(float x); -} // extern "C" -#endif // __AVR__ - -extern "C++" -{ -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using ::acos; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - acos(float __x) - { return __builtin_acosf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - acos(long double __x) - { return __builtin_acosl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - acos(_Tp __x) - { return __builtin_acos(__x); } - - using ::asin; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - asin(float __x) - { return __builtin_asinf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - asin(long double __x) - { return __builtin_asinl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - asin(_Tp __x) - { return __builtin_asin(__x); } - - using ::atan; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - atan(float __x) - { return __builtin_atanf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - atan(long double __x) - { return __builtin_atanl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - atan(_Tp __x) - { return __builtin_atan(__x); } - - using ::atan2; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - atan2(float __y, float __x) - { return __builtin_atan2f(__y, __x); } - - inline _GLIBCXX_CONSTEXPR long double - atan2(long double __y, long double __x) - { return __builtin_atan2l(__y, __x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - atan2(_Tp __y, _Up __x) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return atan2(__type(__y), __type(__x)); - } - - using ::ceil; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - ceil(float __x) - { return __builtin_ceilf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - ceil(long double __x) - { return __builtin_ceill(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - ceil(_Tp __x) - { return __builtin_ceil(__x); } - - using ::cos; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - cos(float __x) - { return __builtin_cosf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - cos(long double __x) - { return __builtin_cosl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - cos(_Tp __x) - { return __builtin_cos(__x); } - - using ::cosh; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - cosh(float __x) - { return __builtin_coshf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - cosh(long double __x) - { return __builtin_coshl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - cosh(_Tp __x) - { return __builtin_cosh(__x); } - - using ::exp; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - exp(float __x) - { return __builtin_expf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - exp(long double __x) - { return __builtin_expl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - exp(_Tp __x) - { return __builtin_exp(__x); } - - using ::fabs; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - fabs(float __x) - { return __builtin_fabsf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - fabs(long double __x) - { return __builtin_fabsl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - fabs(_Tp __x) - { return __builtin_fabs(__x); } - - using ::floor; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - floor(float __x) - { return __builtin_floorf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - floor(long double __x) - { return __builtin_floorl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - floor(_Tp __x) - { return __builtin_floor(__x); } - - using ::fmod; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - fmod(float __x, float __y) - { return __builtin_fmodf(__x, __y); } - - inline _GLIBCXX_CONSTEXPR long double - fmod(long double __x, long double __y) - { return __builtin_fmodl(__x, __y); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmod(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmod(__type(__x), __type(__y)); - } - - using ::frexp; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline float - frexp(float __x, int* __exp) - { return __builtin_frexpf(__x, __exp); } - - inline long double - frexp(long double __x, int* __exp) - { return __builtin_frexpl(__x, __exp); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - frexp(_Tp __x, int* __exp) - { return __builtin_frexp(__x, __exp); } - - using ::ldexp; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - ldexp(float __x, int __exp) - { return __builtin_ldexpf(__x, __exp); } - - inline _GLIBCXX_CONSTEXPR long double - ldexp(long double __x, int __exp) - { return __builtin_ldexpl(__x, __exp); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - ldexp(_Tp __x, int __exp) - { return __builtin_ldexp(__x, __exp); } - - using ::log; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - log(float __x) - { return __builtin_logf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - log(long double __x) - { return __builtin_logl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - log(_Tp __x) - { return __builtin_log(__x); } - - using ::log10; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - log10(float __x) - { return __builtin_log10f(__x); } - - inline _GLIBCXX_CONSTEXPR long double - log10(long double __x) - { return __builtin_log10l(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - log10(_Tp __x) - { return __builtin_log10(__x); } - - using ::modf; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline float - modf(float __x, float* __iptr) - { return __builtin_modff(__x, __iptr); } - - inline long double - modf(long double __x, long double* __iptr) - { return __builtin_modfl(__x, __iptr); } -#endif - - using ::pow; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - pow(float __x, float __y) - { return __builtin_powf(__x, __y); } - - inline _GLIBCXX_CONSTEXPR long double - pow(long double __x, long double __y) - { return __builtin_powl(__x, __y); } - -#if __cplusplus < 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 550. What should the return type of pow(float,int) be? - inline double - pow(double __x, int __i) - { return __builtin_powi(__x, __i); } - - inline float - pow(float __x, int __n) - { return __builtin_powif(__x, __n); } - - inline long double - pow(long double __x, int __n) - { return __builtin_powil(__x, __n); } -#endif -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - pow(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return pow(__type(__x), __type(__y)); - } - - using ::sin; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - sin(float __x) - { return __builtin_sinf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - sin(long double __x) - { return __builtin_sinl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - sin(_Tp __x) - { return __builtin_sin(__x); } - - using ::sinh; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - sinh(float __x) - { return __builtin_sinhf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - sinh(long double __x) - { return __builtin_sinhl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - sinh(_Tp __x) - { return __builtin_sinh(__x); } - - using ::sqrt; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - sqrt(float __x) - { return __builtin_sqrtf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - sqrt(long double __x) - { return __builtin_sqrtl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - sqrt(_Tp __x) - { return __builtin_sqrt(__x); } - - using ::tan; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - tan(float __x) - { return __builtin_tanf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - tan(long double __x) - { return __builtin_tanl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - tan(_Tp __x) - { return __builtin_tan(__x); } - - using ::tanh; - -#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO - inline _GLIBCXX_CONSTEXPR float - tanh(float __x) - { return __builtin_tanhf(__x); } - - inline _GLIBCXX_CONSTEXPR long double - tanh(long double __x) - { return __builtin_tanhl(__x); } -#endif - - template - inline _GLIBCXX_CONSTEXPR - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - tanh(_Tp __x) - { return __builtin_tanh(__x); } - -#if _GLIBCXX_USE_C99_MATH -#if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC - -// These are possible macros imported from C99-land. -#undef fpclassify -#undef isfinite -#undef isinf -#undef isnan -#undef isnormal -#undef signbit -#undef isgreater -#undef isgreaterequal -#undef isless -#undef islessequal -#undef islessgreater -#undef isunordered - -#if !defined(FP_NAN) && !defined(FP_INFINITE) && !defined(FP_ZERO) \ - && !defined(FP_SUBNORMAL) && !defined(FP_NORMAL) -#define FP_NAN 0 -#define FP_INFINITE 1 -#define FP_ZERO 2 -#define FP_SUBNORMAL 3 -#define FP_NORMAL 4 -#elif !defined(FP_NAN) || !defined(FP_INFINITE) || !defined(FP_ZERO) \ - || !defined(FP_SUBNORMAL) || !defined(FP_NORMAL) -#error "Some floating-point number classification macros are missing." -#error "Either define all of them or define none of them so that can do it." -#endif - -#if __cplusplus >= 201103L - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr int - fpclassify(float __x) - { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, - FP_SUBNORMAL, FP_ZERO, __x); } - - constexpr int - fpclassify(double __x) - { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, - FP_SUBNORMAL, FP_ZERO, __x); } - - constexpr int - fpclassify(long double __x) - { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, - FP_SUBNORMAL, FP_ZERO, __x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - int>::__type - fpclassify(_Tp __x) - { return __x != 0 ? FP_NORMAL : FP_ZERO; } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - isfinite(float __x) - { return __builtin_isfinite(__x); } - - constexpr bool - isfinite(double __x) - { return __builtin_isfinite(__x); } - - constexpr bool - isfinite(long double __x) - { return __builtin_isfinite(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - bool>::__type - isfinite(_Tp __x) - { return true; } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - isinf(float __x) - { return __builtin_isinf(__x); } - -#if _GLIBCXX_HAVE_OBSOLETE_ISINF \ - && !_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC - using ::isinf; -#else - constexpr bool - isinf(double __x) - { return __builtin_isinf(__x); } -#endif - - constexpr bool - isinf(long double __x) - { return __builtin_isinf(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - bool>::__type - isinf(_Tp __x) - { return false; } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - isnan(float __x) - { return __builtin_isnan(__x); } - -#if _GLIBCXX_HAVE_OBSOLETE_ISNAN \ - && !_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC - using ::isnan; -#else - constexpr bool - isnan(double __x) - { return __builtin_isnan(__x); } -#endif - - constexpr bool - isnan(long double __x) - { return __builtin_isnan(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - bool>::__type - isnan(_Tp __x) - { return false; } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - isnormal(float __x) - { return __builtin_isnormal(__x); } - - constexpr bool - isnormal(double __x) - { return __builtin_isnormal(__x); } - - constexpr bool - isnormal(long double __x) - { return __builtin_isnormal(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - bool>::__type - isnormal(_Tp __x) - { return __x != 0 ? true : false; } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - // Note: middle-end/36757 is fixed, __builtin_signbit is type-generic. - constexpr bool - signbit(float __x) - { return __builtin_signbit(__x); } - - constexpr bool - signbit(double __x) - { return __builtin_signbit(__x); } - - constexpr bool - signbit(long double __x) - { return __builtin_signbit(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - bool>::__type - signbit(_Tp __x) - { return __x < 0 ? true : false; } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - isgreater(float __x, float __y) - { return __builtin_isgreater(__x, __y); } - - constexpr bool - isgreater(double __x, double __y) - { return __builtin_isgreater(__x, __y); } - - constexpr bool - isgreater(long double __x, long double __y) - { return __builtin_isgreater(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename - __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value - && __is_arithmetic<_Up>::__value), bool>::__type - isgreater(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return __builtin_isgreater(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - isgreaterequal(float __x, float __y) - { return __builtin_isgreaterequal(__x, __y); } - - constexpr bool - isgreaterequal(double __x, double __y) - { return __builtin_isgreaterequal(__x, __y); } - - constexpr bool - isgreaterequal(long double __x, long double __y) - { return __builtin_isgreaterequal(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename - __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value - && __is_arithmetic<_Up>::__value), bool>::__type - isgreaterequal(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return __builtin_isgreaterequal(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - isless(float __x, float __y) - { return __builtin_isless(__x, __y); } - - constexpr bool - isless(double __x, double __y) - { return __builtin_isless(__x, __y); } - - constexpr bool - isless(long double __x, long double __y) - { return __builtin_isless(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename - __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value - && __is_arithmetic<_Up>::__value), bool>::__type - isless(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return __builtin_isless(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - islessequal(float __x, float __y) - { return __builtin_islessequal(__x, __y); } - - constexpr bool - islessequal(double __x, double __y) - { return __builtin_islessequal(__x, __y); } - - constexpr bool - islessequal(long double __x, long double __y) - { return __builtin_islessequal(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename - __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value - && __is_arithmetic<_Up>::__value), bool>::__type - islessequal(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return __builtin_islessequal(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - islessgreater(float __x, float __y) - { return __builtin_islessgreater(__x, __y); } - - constexpr bool - islessgreater(double __x, double __y) - { return __builtin_islessgreater(__x, __y); } - - constexpr bool - islessgreater(long double __x, long double __y) - { return __builtin_islessgreater(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename - __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value - && __is_arithmetic<_Up>::__value), bool>::__type - islessgreater(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return __builtin_islessgreater(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr bool - isunordered(float __x, float __y) - { return __builtin_isunordered(__x, __y); } - - constexpr bool - isunordered(double __x, double __y) - { return __builtin_isunordered(__x, __y); } - - constexpr bool - isunordered(long double __x, long double __y) - { return __builtin_isunordered(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename - __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value - && __is_arithmetic<_Up>::__value), bool>::__type - isunordered(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return __builtin_isunordered(__type(__x), __type(__y)); - } -#endif - -#else - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - fpclassify(_Tp __f) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, - FP_SUBNORMAL, FP_ZERO, __type(__f)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - isfinite(_Tp __f) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_isfinite(__type(__f)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - isinf(_Tp __f) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_isinf(__type(__f)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - isnan(_Tp __f) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_isnan(__type(__f)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - isnormal(_Tp __f) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_isnormal(__type(__f)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - signbit(_Tp __f) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_signbit(__type(__f)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - isgreater(_Tp __f1, _Tp __f2) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_isgreater(__type(__f1), __type(__f2)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - isgreaterequal(_Tp __f1, _Tp __f2) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_isgreaterequal(__type(__f1), __type(__f2)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - isless(_Tp __f1, _Tp __f2) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_isless(__type(__f1), __type(__f2)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - islessequal(_Tp __f1, _Tp __f2) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_islessequal(__type(__f1), __type(__f2)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - islessgreater(_Tp __f1, _Tp __f2) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_islessgreater(__type(__f1), __type(__f2)); - } - - template - inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, - int>::__type - isunordered(_Tp __f1, _Tp __f2) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __builtin_isunordered(__type(__f1), __type(__f2)); - } - -#endif // C++11 -#endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */ -#endif /* _GLIBCXX_USE_C99_MATH */ - -#if __cplusplus >= 201103L - -#ifdef _GLIBCXX_USE_C99_MATH_TR1 - -#undef acosh -#undef acoshf -#undef acoshl -#undef asinh -#undef asinhf -#undef asinhl -#undef atanh -#undef atanhf -#undef atanhl -#undef cbrt -#undef cbrtf -#undef cbrtl -#undef copysign -#undef copysignf -#undef copysignl -#undef erf -#undef erff -#undef erfl -#undef erfc -#undef erfcf -#undef erfcl -#undef exp2 -#undef exp2f -#undef exp2l -#undef expm1 -#undef expm1f -#undef expm1l -#undef fdim -#undef fdimf -#undef fdiml -#undef fma -#undef fmaf -#undef fmal -#undef fmax -#undef fmaxf -#undef fmaxl -#undef fmin -#undef fminf -#undef fminl -#undef hypot -#undef hypotf -#undef hypotl -#undef ilogb -#undef ilogbf -#undef ilogbl -#undef lgamma -#undef lgammaf -#undef lgammal -#ifndef _GLIBCXX_NO_C99_ROUNDING_FUNCS -#undef llrint -#undef llrintf -#undef llrintl -#undef llround -#undef llroundf -#undef llroundl -#endif -#undef log1p -#undef log1pf -#undef log1pl -#undef log2 -#undef log2f -#undef log2l -#undef logb -#undef logbf -#undef logbl -#undef lrint -#undef lrintf -#undef lrintl -#undef lround -#undef lroundf -#undef lroundl -#undef nan -#undef nanf -#undef nanl -#undef nearbyint -#undef nearbyintf -#undef nearbyintl -#undef nextafter -#undef nextafterf -#undef nextafterl -#undef nexttoward -#undef nexttowardf -#undef nexttowardl -#undef remainder -#undef remainderf -#undef remainderl -#undef remquo -#undef remquof -#undef remquol -#undef rint -#undef rintf -#undef rintl -#undef round -#undef roundf -#undef roundl -#undef scalbln -#undef scalblnf -#undef scalblnl -#undef scalbn -#undef scalbnf -#undef scalbnl -#undef tgamma -#undef tgammaf -#undef tgammal -#undef trunc -#undef truncf -#undef truncl - - // types - using double_t = double; - using float_t = float; - - // functions - - using ::cbrt; - inline float cbrtf(float __x) { return ::cbrt(__x); } - - using ::copysign; - inline float copysignf(float __x, float __y) { return ::copysign(__x, __y); } - - using ::fdim; - inline float fdimf(float __x, float __y) { return ::fdim(__x, __y); } - - using ::fma; - inline float fmaf(float __x, float __y, float __z) { return ::fma(__x, __y, __z); } - - using ::fmax; - inline float fmaxf(float __x, float __y) { return ::fmax(__x, __y); } - - using ::fmin; - inline float fminf(float __x, float __y) { return ::fmin(__x, __y); } - - using ::hypot; - inline float hypotf(float __x, float __y) { return ::hypot(__x, __y); } - -#ifndef _GLIBCXX_NO_C99_ROUNDING_FUNCS - using ::llrint; - using ::llrintf; - using ::llrintl; - - using ::llround; - using ::llroundf; - using ::llroundl; -#endif - - using ::lrint; - inline float lrintf(float __x) { return ::lrint(__x); } - - using ::lround; - inline float lroundf(float __x) { return ::lround(__x); } - - using ::round; - inline float roundf(float __x) { return ::round(__x); } - - using ::trunc; - inline float truncf(float __x) { return ::trunc(__x); } - - /// Additional overloads. -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - acosh(float __x) - { return __builtin_acoshf(__x); } - - constexpr long double - acosh(long double __x) - { return __builtin_acoshl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - acosh(_Tp __x) - { return __builtin_acosh(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - asinh(float __x) - { return __builtin_asinhf(__x); } - - constexpr long double - asinh(long double __x) - { return __builtin_asinhl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - asinh(_Tp __x) - { return __builtin_asinh(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - atanh(float __x) - { return __builtin_atanhf(__x); } - - constexpr long double - atanh(long double __x) - { return __builtin_atanhl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - atanh(_Tp __x) - { return __builtin_atanh(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - cbrt(float __x) - { return __builtin_cbrtf(__x); } - - constexpr long double - cbrt(long double __x) - { return __builtin_cbrtl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - cbrt(_Tp __x) - { return __builtin_cbrt(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - copysign(float __x, float __y) - { return __builtin_copysignf(__x, __y); } - - constexpr long double - copysign(long double __x, long double __y) - { return __builtin_copysignl(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - copysign(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return copysign(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - erf(float __x) - { return __builtin_erff(__x); } - - constexpr long double - erf(long double __x) - { return __builtin_erfl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - erf(_Tp __x) - { return __builtin_erf(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - erfc(float __x) - { return __builtin_erfcf(__x); } - - constexpr long double - erfc(long double __x) - { return __builtin_erfcl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - erfc(_Tp __x) - { return __builtin_erfc(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - exp2(float __x) - { return __builtin_exp2f(__x); } - - constexpr long double - exp2(long double __x) - { return __builtin_exp2l(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - exp2(_Tp __x) - { return __builtin_exp2(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - expm1(float __x) - { return __builtin_expm1f(__x); } - - constexpr long double - expm1(long double __x) - { return __builtin_expm1l(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - expm1(_Tp __x) - { return __builtin_expm1(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - fdim(float __x, float __y) - { return __builtin_fdimf(__x, __y); } - - constexpr long double - fdim(long double __x, long double __y) - { return __builtin_fdiml(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fdim(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fdim(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - fma(float __x, float __y, float __z) - { return __builtin_fmaf(__x, __y, __z); } - - constexpr long double - fma(long double __x, long double __y, long double __z) - { return __builtin_fmal(__x, __y, __z); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type - fma(_Tp __x, _Up __y, _Vp __z) - { - typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type; - return fma(__type(__x), __type(__y), __type(__z)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - fmax(float __x, float __y) - { return __builtin_fmaxf(__x, __y); } - - constexpr long double - fmax(long double __x, long double __y) - { return __builtin_fmaxl(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmax(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmax(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - fmin(float __x, float __y) - { return __builtin_fminf(__x, __y); } - - constexpr long double - fmin(long double __x, long double __y) - { return __builtin_fminl(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - fmin(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return fmin(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - hypot(float __x, float __y) - { return __builtin_hypotf(__x, __y); } - - constexpr long double - hypot(long double __x, long double __y) - { return __builtin_hypotl(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - hypot(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return hypot(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr int - ilogb(float __x) - { return __builtin_ilogbf(__x); } - - constexpr int - ilogb(long double __x) - { return __builtin_ilogbl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr - typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - int>::__type - ilogb(_Tp __x) - { return __builtin_ilogb(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - lgamma(float __x) - { return __builtin_lgammaf(__x); } - - constexpr long double - lgamma(long double __x) - { return __builtin_lgammal(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - lgamma(_Tp __x) - { return __builtin_lgamma(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr long long - llrint(float __x) - { return __builtin_llrintf(__x); } - - constexpr long long - llrint(long double __x) - { return __builtin_llrintl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - long long>::__type - llrint(_Tp __x) - { return __builtin_llrint(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr long long - llround(float __x) - { return __builtin_llroundf(__x); } - - constexpr long long - llround(long double __x) - { return __builtin_llroundl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - long long>::__type - llround(_Tp __x) - { return __builtin_llround(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - log1p(float __x) - { return __builtin_log1pf(__x); } - - constexpr long double - log1p(long double __x) - { return __builtin_log1pl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - log1p(_Tp __x) - { return __builtin_log1p(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - // DR 568. - constexpr float - log2(float __x) - { return __builtin_log2f(__x); } - - constexpr long double - log2(long double __x) - { return __builtin_log2l(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - log2(_Tp __x) - { return __builtin_log2(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - logb(float __x) - { return __builtin_logbf(__x); } - - constexpr long double - logb(long double __x) - { return __builtin_logbl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - logb(_Tp __x) - { return __builtin_logb(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr long - lrint(float __x) - { return __builtin_lrintf(__x); } - - constexpr long - lrint(long double __x) - { return __builtin_lrintl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - long>::__type - lrint(_Tp __x) - { return __builtin_lrint(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr long - lround(float __x) - { return __builtin_lroundf(__x); } - - constexpr long - lround(long double __x) - { return __builtin_lroundl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - long>::__type - lround(_Tp __x) - { return __builtin_lround(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - nearbyint(float __x) - { return __builtin_nearbyintf(__x); } - - constexpr long double - nearbyint(long double __x) - { return __builtin_nearbyintl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - nearbyint(_Tp __x) - { return __builtin_nearbyint(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - nextafter(float __x, float __y) - { return __builtin_nextafterf(__x, __y); } - - constexpr long double - nextafter(long double __x, long double __y) - { return __builtin_nextafterl(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - nextafter(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return nextafter(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - nexttoward(float __x, long double __y) - { return __builtin_nexttowardf(__x, __y); } - - constexpr long double - nexttoward(long double __x, long double __y) - { return __builtin_nexttowardl(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - nexttoward(_Tp __x, long double __y) - { return __builtin_nexttoward(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - remainder(float __x, float __y) - { return __builtin_remainderf(__x, __y); } - - constexpr long double - remainder(long double __x, long double __y) - { return __builtin_remainderl(__x, __y); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - remainder(_Tp __x, _Up __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return remainder(__type(__x), __type(__y)); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - inline float - remquo(float __x, float __y, int* __pquo) - { return __builtin_remquof(__x, __y, __pquo); } - - inline long double - remquo(long double __x, long double __y, int* __pquo) - { return __builtin_remquol(__x, __y, __pquo); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type - remquo(_Tp __x, _Up __y, int* __pquo) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return remquo(__type(__x), __type(__y), __pquo); - } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - rint(float __x) - { return __builtin_rintf(__x); } - - constexpr long double - rint(long double __x) - { return __builtin_rintl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - rint(_Tp __x) - { return __builtin_rint(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - round(float __x) - { return __builtin_roundf(__x); } - - constexpr long double - round(long double __x) - { return __builtin_roundl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - round(_Tp __x) - { return __builtin_round(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - scalbln(float __x, long __ex) - { return __builtin_scalblnf(__x, __ex); } - - constexpr long double - scalbln(long double __x, long __ex) - { return __builtin_scalblnl(__x, __ex); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - scalbln(_Tp __x, long __ex) - { return __builtin_scalbln(__x, __ex); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - scalbn(float __x, int __ex) - { return __builtin_scalbnf(__x, __ex); } - - constexpr long double - scalbn(long double __x, int __ex) - { return __builtin_scalbnl(__x, __ex); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - scalbn(_Tp __x, int __ex) - { return __builtin_scalbn(__x, __ex); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - tgamma(float __x) - { return __builtin_tgammaf(__x); } - - constexpr long double - tgamma(long double __x) - { return __builtin_tgammal(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - tgamma(_Tp __x) - { return __builtin_tgamma(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP - constexpr float - trunc(float __x) - { return __builtin_truncf(__x); } - - constexpr long double - trunc(long double __x) - { return __builtin_truncl(__x); } -#endif - -#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT - template - constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, - double>::__type - trunc(_Tp __x) - { return __builtin_trunc(__x); } -#endif - -#endif // _GLIBCXX_USE_C99_MATH_TR1 -#endif // C++11 - -#if __cplusplus > 201402L - - // [c.math.hypot3], three-dimensional hypotenuse -#define __cpp_lib_hypot 201603 - - template - inline _Tp - __hypot3(_Tp __x, _Tp __y, _Tp __z) - { - __x = std::abs(__x); - __y = std::abs(__y); - __z = std::abs(__z); - if (_Tp __a = __x < __y ? __y < __z ? __z : __y : __x < __z ? __z : __x) - return __a * std::sqrt((__x / __a) * (__x / __a) - + (__y / __a) * (__y / __a) - + (__z / __a) * (__z / __a)); - else - return {}; - } - - inline float - hypot(float __x, float __y, float __z) - { return std::__hypot3(__x, __y, __z); } - - inline double - hypot(double __x, double __y, double __z) - { return std::__hypot3(__x, __y, __z); } - - inline long double - hypot(long double __x, long double __y, long double __z) - { return std::__hypot3(__x, __y, __z); } - - template - typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type - hypot(_Tp __x, _Up __y, _Vp __z) - { - using __type = typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type; - return std::__hypot3<__type>(__x, __y, __z); - } -#endif // C++17 - -#if __cplusplus > 201703L - // linear interpolation -# define __cpp_lib_interpolate 201902L - - template - constexpr _Fp - __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept - { - if (__a <= 0 && __b >= 0 || __a >= 0 && __b <= 0) - return __t * __b + (1 - __t) * __a; - - if (__t == 1) - return __b; // exact - - // Exact at __t=0, monotonic except near __t=1, - // bounded, determinate, and consistent: - const _Fp __x = __a + __t * (__b - __a); - return __t > 1 == __b > __a - ? (__b < __x ? __x : __b) - : (__b > __x ? __x : __b); // monotonic near __t=1 - } - - constexpr float - lerp(float __a, float __b, float __t) noexcept - { return std::__lerp(__a, __b, __t); } - - constexpr double - lerp(double __a, double __b, double __t) noexcept - { return std::__lerp(__a, __b, __t); } - - constexpr long double - lerp(long double __a, long double __b, long double __t) noexcept - { return std::__lerp(__a, __b, __t); } -#endif // C++20 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -} // extern "C++" - +// Minimal for AVR +#ifndef _AVR_CMATH +#define _AVR_CMATH +#include +namespace std { + using ::fabs; using ::fabsf; using ::fmod; using ::fmodf; + using ::sqrt; using ::sqrtf; using ::floor; using ::floorf; + using ::ceil; using ::ceilf; using ::round; using ::roundf; + using ::pow; using ::powf; using ::log; using ::logf; + using ::exp; using ::expf; using ::sin; using ::cos; using ::tan; + using ::asin; using ::acos; using ::atan; using ::atan2; +} #endif diff --git a/resources/sources/avr-libstdcpp/include/compare b/resources/sources/avr-libstdcpp/include/compare deleted file mode 100644 index 28dfe843e..000000000 --- a/resources/sources/avr-libstdcpp/include/compare +++ /dev/null @@ -1,919 +0,0 @@ -// -*- C++ -*- operator<=> three-way comparison support. - -// Copyright (C) 2019-2020 Free Software Foundation, Inc. -// -// This file is part of GCC. -// -// GCC is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3, or (at your option) -// any later version. -// -// GCC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file compare - * This is a Standard C++ Library header. - */ - -#ifndef _COMPARE -#define _COMPARE - -#pragma GCC system_header - -#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L - -#pragma GCC visibility push(default) - -#include - -#if __cpp_lib_concepts -# define __cpp_lib_three_way_comparison 201907L -#endif - -namespace std -{ - // [cmp.categories], comparison category types - - namespace __cmp_cat - { - using type = signed char; - - enum class _Ord : type { equivalent = 0, less = -1, greater = 1 }; - - enum class _Ncmp : type { _Unordered = 2 }; - - struct __unspec - { - constexpr __unspec(__unspec*) noexcept { } - }; - } - - class partial_ordering - { - // less=0xff, equiv=0x00, greater=0x01, unordered=0x02 - __cmp_cat::type _M_value; - - constexpr explicit - partial_ordering(__cmp_cat::_Ord __v) noexcept - : _M_value(__cmp_cat::type(__v)) - { } - - constexpr explicit - partial_ordering(__cmp_cat::_Ncmp __v) noexcept - : _M_value(__cmp_cat::type(__v)) - { } - - friend class weak_ordering; - friend class strong_ordering; - - public: - // valid values - static const partial_ordering less; - static const partial_ordering equivalent; - static const partial_ordering greater; - static const partial_ordering unordered; - - // comparisons - friend constexpr bool - operator==(partial_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value == 0; } - - friend constexpr bool - operator==(partial_ordering, partial_ordering) noexcept = default; - - friend constexpr bool - operator< (partial_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value == -1; } - - friend constexpr bool - operator> (partial_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value == 1; } - - friend constexpr bool - operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value <= 0; } - - friend constexpr bool - operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept - { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; } - - friend constexpr bool - operator< (__cmp_cat::__unspec, partial_ordering __v) noexcept - { return __v._M_value == 1; } - - friend constexpr bool - operator> (__cmp_cat::__unspec, partial_ordering __v) noexcept - { return __v._M_value == -1; } - - friend constexpr bool - operator<=(__cmp_cat::__unspec, partial_ordering __v) noexcept - { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; } - - friend constexpr bool - operator>=(__cmp_cat::__unspec, partial_ordering __v) noexcept - { return 0 >= __v._M_value; } - - friend constexpr partial_ordering - operator<=>(partial_ordering __v, __cmp_cat::__unspec) noexcept - { return __v; } - - friend constexpr partial_ordering - operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept - { - if (__v._M_value & 1) - return partial_ordering(__cmp_cat::_Ord(-__v._M_value)); - else - return __v; - } - }; - - // valid values' definitions - inline constexpr partial_ordering - partial_ordering::less(__cmp_cat::_Ord::less); - - inline constexpr partial_ordering - partial_ordering::equivalent(__cmp_cat::_Ord::equivalent); - - inline constexpr partial_ordering - partial_ordering::greater(__cmp_cat::_Ord::greater); - - inline constexpr partial_ordering - partial_ordering::unordered(__cmp_cat::_Ncmp::_Unordered); - - class weak_ordering - { - __cmp_cat::type _M_value; - - constexpr explicit - weak_ordering(__cmp_cat::_Ord __v) noexcept : _M_value(__cmp_cat::type(__v)) - { } - - friend class strong_ordering; - - public: - // valid values - static const weak_ordering less; - static const weak_ordering equivalent; - static const weak_ordering greater; - - constexpr operator partial_ordering() const noexcept - { return partial_ordering(__cmp_cat::_Ord(_M_value)); } - - // comparisons - friend constexpr bool - operator==(weak_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value == 0; } - - friend constexpr bool - operator==(weak_ordering, weak_ordering) noexcept = default; - - friend constexpr bool - operator< (weak_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value < 0; } - - friend constexpr bool - operator> (weak_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value > 0; } - - friend constexpr bool - operator<=(weak_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value <= 0; } - - friend constexpr bool - operator>=(weak_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value >= 0; } - - friend constexpr bool - operator< (__cmp_cat::__unspec, weak_ordering __v) noexcept - { return 0 < __v._M_value; } - - friend constexpr bool - operator> (__cmp_cat::__unspec, weak_ordering __v) noexcept - { return 0 > __v._M_value; } - - friend constexpr bool - operator<=(__cmp_cat::__unspec, weak_ordering __v) noexcept - { return 0 <= __v._M_value; } - - friend constexpr bool - operator>=(__cmp_cat::__unspec, weak_ordering __v) noexcept - { return 0 >= __v._M_value; } - - friend constexpr weak_ordering - operator<=>(weak_ordering __v, __cmp_cat::__unspec) noexcept - { return __v; } - - friend constexpr weak_ordering - operator<=>(__cmp_cat::__unspec, weak_ordering __v) noexcept - { return weak_ordering(__cmp_cat::_Ord(-__v._M_value)); } - }; - - // valid values' definitions - inline constexpr weak_ordering - weak_ordering::less(__cmp_cat::_Ord::less); - - inline constexpr weak_ordering - weak_ordering::equivalent(__cmp_cat::_Ord::equivalent); - - inline constexpr weak_ordering - weak_ordering::greater(__cmp_cat::_Ord::greater); - - class strong_ordering - { - __cmp_cat::type _M_value; - - constexpr explicit - strong_ordering(__cmp_cat::_Ord __v) noexcept - : _M_value(__cmp_cat::type(__v)) - { } - - public: - // valid values - static const strong_ordering less; - static const strong_ordering equal; - static const strong_ordering equivalent; - static const strong_ordering greater; - - constexpr operator partial_ordering() const noexcept - { return partial_ordering(__cmp_cat::_Ord(_M_value)); } - - constexpr operator weak_ordering() const noexcept - { return weak_ordering(__cmp_cat::_Ord(_M_value)); } - - // comparisons - friend constexpr bool - operator==(strong_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value == 0; } - - friend constexpr bool - operator==(strong_ordering, strong_ordering) noexcept = default; - - friend constexpr bool - operator< (strong_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value < 0; } - - friend constexpr bool - operator> (strong_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value > 0; } - - friend constexpr bool - operator<=(strong_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value <= 0; } - - friend constexpr bool - operator>=(strong_ordering __v, __cmp_cat::__unspec) noexcept - { return __v._M_value >= 0; } - - friend constexpr bool - operator< (__cmp_cat::__unspec, strong_ordering __v) noexcept - { return 0 < __v._M_value; } - - friend constexpr bool - operator> (__cmp_cat::__unspec, strong_ordering __v) noexcept - { return 0 > __v._M_value; } - - friend constexpr bool - operator<=(__cmp_cat::__unspec, strong_ordering __v) noexcept - { return 0 <= __v._M_value; } - - friend constexpr bool - operator>=(__cmp_cat::__unspec, strong_ordering __v) noexcept - { return 0 >= __v._M_value; } - - friend constexpr strong_ordering - operator<=>(strong_ordering __v, __cmp_cat::__unspec) noexcept - { return __v; } - - friend constexpr strong_ordering - operator<=>(__cmp_cat::__unspec, strong_ordering __v) noexcept - { return strong_ordering(__cmp_cat::_Ord(-__v._M_value)); } - }; - - // valid values' definitions - inline constexpr strong_ordering - strong_ordering::less(__cmp_cat::_Ord::less); - - inline constexpr strong_ordering - strong_ordering::equal(__cmp_cat::_Ord::equivalent); - - inline constexpr strong_ordering - strong_ordering::equivalent(__cmp_cat::_Ord::equivalent); - - inline constexpr strong_ordering - strong_ordering::greater(__cmp_cat::_Ord::greater); - - - // named comparison functions - constexpr bool - is_eq(partial_ordering __cmp) noexcept - { return __cmp == 0; } - - constexpr bool - is_neq(partial_ordering __cmp) noexcept - { return __cmp != 0; } - - constexpr bool - is_lt (partial_ordering __cmp) noexcept - { return __cmp < 0; } - - constexpr bool - is_lteq(partial_ordering __cmp) noexcept - { return __cmp <= 0; } - - constexpr bool - is_gt (partial_ordering __cmp) noexcept - { return __cmp > 0; } - - constexpr bool - is_gteq(partial_ordering __cmp) noexcept - { return __cmp >= 0; } - - namespace __detail - { - template - inline constexpr unsigned __cmp_cat_id = 1; - template<> - inline constexpr unsigned __cmp_cat_id = 2; - template<> - inline constexpr unsigned __cmp_cat_id = 4; - template<> - inline constexpr unsigned __cmp_cat_id = 8; - - template - constexpr auto __common_cmp_cat() - { - constexpr unsigned __cats = (__cmp_cat_id<_Ts> | ...); - // If any Ti is not a comparison category type, U is void. - if constexpr (__cats & 1) - return; - // Otherwise, if at least one Ti is std::partial_ordering, - // U is std::partial_ordering. - else if constexpr (bool(__cats & __cmp_cat_id)) - return partial_ordering::equivalent; - // Otherwise, if at least one Ti is std::weak_ordering, - // U is std::weak_ordering. - else if constexpr (bool(__cats & __cmp_cat_id)) - return weak_ordering::equivalent; - // Otherwise, U is std::strong_ordering. - else - return strong_ordering::equivalent; - } - } // namespace __detail - - // [cmp.common], common comparison category type - template - struct common_comparison_category - { - using type = decltype(__detail::__common_cmp_cat<_Ts...>()); - }; - - // Partial specializations for one and zero argument cases. - - template - struct common_comparison_category<_Tp> - { using type = void; }; - - template<> - struct common_comparison_category - { using type = partial_ordering; }; - - template<> - struct common_comparison_category - { using type = weak_ordering; }; - - template<> - struct common_comparison_category - { using type = strong_ordering; }; - - template<> - struct common_comparison_category<> - { using type = strong_ordering; }; - - template - using common_comparison_category_t - = typename common_comparison_category<_Ts...>::type; - -#if __cpp_lib_concepts - namespace __detail - { - template - concept __compares_as - = same_as, _Cat>; - } // namespace __detail - - // [cmp.concept], concept three_way_comparable - template - concept three_way_comparable - = __detail::__weakly_eq_cmp_with<_Tp, _Tp> - && __detail::__partially_ordered_with<_Tp, _Tp> - && requires(const remove_reference_t<_Tp>& __a, - const remove_reference_t<_Tp>& __b) - { - { __a <=> __b } -> __detail::__compares_as<_Cat>; - }; - - template - concept three_way_comparable_with - = three_way_comparable<_Tp, _Cat> - && three_way_comparable<_Up, _Cat> - && common_reference_with&, - const remove_reference_t<_Up>&> - && three_way_comparable< - common_reference_t&, - const remove_reference_t<_Up>&>, _Cat> - && __detail::__weakly_eq_cmp_with<_Tp, _Up> - && __detail::__partially_ordered_with<_Tp, _Up> - && requires(const remove_reference_t<_Tp>& __t, - const remove_reference_t<_Up>& __u) - { - { __t <=> __u } -> __detail::__compares_as<_Cat>; - { __u <=> __t } -> __detail::__compares_as<_Cat>; - }; - - namespace __detail - { - template - using __cmp3way_res_t - = decltype(std::declval<_Tp>() <=> std::declval<_Up>()); - - // Implementation of std::compare_three_way_result. - // It is undefined for a program to add specializations of - // std::compare_three_way_result, so the std::compare_three_way_result_t - // alias ignores std::compare_three_way_result and uses - // __detail::__cmp3way_res_impl directly instead. - template - struct __cmp3way_res_impl - { }; - - template - requires requires { typename __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; } - struct __cmp3way_res_impl<_Tp, _Up> - { - using type = __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; - }; - } // namespace __detail - - /// [cmp.result], result of three-way comparison - template - struct compare_three_way_result - : __detail::__cmp3way_res_impl<_Tp, _Up> - { }; - - /// [cmp.result], result of three-way comparison - template - using compare_three_way_result_t - = typename __detail::__cmp3way_res_impl<_Tp, _Up>::type; - - namespace __detail - { - // BUILTIN-PTR-THREE-WAY(T, U) - template - concept __3way_builtin_ptr_cmp - = requires(_Tp&& __t, _Up&& __u) - { static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); } - && convertible_to<_Tp, const volatile void*> - && convertible_to<_Up, const volatile void*> - && ! requires(_Tp&& __t, _Up&& __u) - { operator<=>(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); } - && ! requires(_Tp&& __t, _Up&& __u) - { static_cast<_Tp&&>(__t).operator<=>(static_cast<_Up&&>(__u)); }; - } // namespace __detail - - // [cmp.object], typename compare_three_way - struct compare_three_way - { - template - requires three_way_comparable_with<_Tp, _Up> - || __detail::__3way_builtin_ptr_cmp<_Tp, _Up> - constexpr auto - operator()(_Tp&& __t, _Up&& __u) const - noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>())) - { - if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>) - { - auto __pt = static_cast(__t); - auto __pu = static_cast(__u); - if (__builtin_is_constant_evaluated()) - return __pt <=> __pu; - auto __it = reinterpret_cast<__UINTPTR_TYPE__>(__pt); - auto __iu = reinterpret_cast<__UINTPTR_TYPE__>(__pu); - return __it <=> __iu; - } - else - return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); - } - - using is_transparent = void; - }; - - namespace __cmp_cust - { - template - constexpr weak_ordering - __fp_weak_ordering(_Tp __e, _Tp __f) - { - // Returns an integer with the same sign as the argument, and magnitude - // indicating the classification: zero=1 subnorm=2 norm=3 inf=4 nan=5 - auto __cat = [](_Tp __fp) -> int { - const int __sign = __builtin_signbit(__fp) ? -1 : 1; - if (__builtin_isnormal(__fp)) - return (__fp == 0 ? 1 : 3) * __sign; - if (__builtin_isnan(__fp)) - return 5 * __sign; - if (int __inf = __builtin_isinf_sign(__fp)) - return 4 * __inf; - return 2 * __sign; - }; - - auto __po = __e <=> __f; - if (is_lt(__po)) - return weak_ordering::less; - else if (is_gt(__po)) - return weak_ordering::greater; - else if (__po == partial_ordering::equivalent) - return weak_ordering::equivalent; - else // unordered, at least one argument is NaN - { - // return -1 for negative nan, +1 for positive nan, 0 otherwise. - auto __isnan_sign = [](_Tp __fp) -> int { - return __builtin_isnan(__fp) - ? __builtin_signbit(__fp) ? -1 : 1 - : 0; - }; - auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f); - if (is_eq(__ord)) - return weak_ordering::equivalent; - else if (is_lt(__ord)) - return weak_ordering::less; - else - return weak_ordering::greater; - } - } - - template - concept __adl_strong = requires(_Tp&& __t, _Up&& __u) - { - strong_ordering(strong_order(static_cast<_Tp&&>(__t), - static_cast<_Up&&>(__u))); - }; - - template - concept __adl_weak = requires(_Tp&& __t, _Up&& __u) - { - weak_ordering(weak_order(static_cast<_Tp&&>(__t), - static_cast<_Up&&>(__u))); - }; - - template - concept __adl_partial = requires(_Tp&& __t, _Up&& __u) - { - partial_ordering(partial_order(static_cast<_Tp&&>(__t), - static_cast<_Up&&>(__u))); - }; - - template - concept __cmp3way = requires(_Tp&& __t, _Up&& __u, compare_three_way __c) - { - _Ord(__c(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u))); - }; - - template - concept __strongly_ordered - = __adl_strong<_Tp, _Up> - // FIXME: || floating_point> - || __cmp3way; - - class _Strong_order - { - template - static constexpr bool - _S_noexcept() - { - if constexpr (floating_point>) - return true; - else if constexpr (__adl_strong<_Tp, _Up>) - return noexcept(strong_ordering(strong_order(std::declval<_Tp>(), - std::declval<_Up>()))); - else if constexpr (__cmp3way) - return noexcept(compare_three_way()(std::declval<_Tp>(), - std::declval<_Up>())); - } - - friend class _Weak_order; - friend class _Strong_fallback; - - public: - template - requires __strongly_ordered<_Tp, _Up> - constexpr strong_ordering - operator()(_Tp&& __e, _Up&& __f) const - noexcept(_S_noexcept<_Tp, _Up>()) - { - static_assert(same_as, decay_t<_Up>>); - - /* FIXME: - if constexpr (floating_point>) - return __cmp_cust::__fp_strong_order(__e, __f); - else */ if constexpr (__adl_strong<_Tp, _Up>) - return strong_ordering(strong_order(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f))); - else if constexpr (__cmp3way) - return compare_three_way()(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f)); - } - }; - - template - concept __weakly_ordered - = floating_point> - || __adl_weak<_Tp, _Up> - || __cmp3way - || __strongly_ordered<_Tp, _Up>; - - class _Weak_order - { - template - static constexpr bool - _S_noexcept() - { - if constexpr (floating_point>) - return true; - else if constexpr (__adl_weak<_Tp, _Up>) - return noexcept(weak_ordering(weak_order(std::declval<_Tp>(), - std::declval<_Up>()))); - else if constexpr (__cmp3way) - return noexcept(compare_three_way()(std::declval<_Tp>(), - std::declval<_Up>())); - else if constexpr (__strongly_ordered<_Tp, _Up>) - return _Strong_order::_S_noexcept<_Tp, _Up>(); - } - - friend class _Partial_order; - friend class _Weak_fallback; - - public: - template - requires __weakly_ordered<_Tp, _Up> - constexpr weak_ordering - operator()(_Tp&& __e, _Up&& __f) const - noexcept(_S_noexcept<_Tp, _Up>()) - { - static_assert(same_as, decay_t<_Up>>); - - if constexpr (floating_point>) - return __cmp_cust::__fp_weak_ordering(__e, __f); - else if constexpr (__adl_weak<_Tp, _Up>) - return weak_ordering(weak_order(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f))); - else if constexpr (__cmp3way) - return compare_three_way()(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f)); - else if constexpr (__strongly_ordered<_Tp, _Up>) - return _Strong_order{}(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f)); - } - }; - - template - concept __partially_ordered - = __adl_partial<_Tp, _Up> - || __cmp3way - || __weakly_ordered<_Tp, _Up>; - - class _Partial_order - { - template - static constexpr bool - _S_noexcept() - { - if constexpr (__adl_partial<_Tp, _Up>) - return noexcept(partial_ordering(partial_order(std::declval<_Tp>(), - std::declval<_Up>()))); - else if constexpr (__cmp3way) - return noexcept(compare_three_way()(std::declval<_Tp>(), - std::declval<_Up>())); - else if constexpr (__weakly_ordered<_Tp, _Up>) - return _Weak_order::_S_noexcept<_Tp, _Up>(); - } - - friend class _Partial_fallback; - - public: - template - requires __partially_ordered<_Tp, _Up> - constexpr partial_ordering - operator()(_Tp&& __e, _Up&& __f) const - noexcept(_S_noexcept<_Tp, _Up>()) - { - static_assert(same_as, decay_t<_Up>>); - - if constexpr (__adl_partial<_Tp, _Up>) - return partial_ordering(partial_order(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f))); - else if constexpr (__cmp3way) - return compare_three_way()(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f)); - else if constexpr (__weakly_ordered<_Tp, _Up>) - return _Weak_order{}(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f)); - } - }; - - template - concept __op_eq_lt = requires(_Tp&& __t, _Up&& __u) - { - { static_cast<_Tp&&>(__t) == static_cast<_Up&&>(__u) } - -> convertible_to; - { static_cast<_Tp&&>(__t) < static_cast<_Up&&>(__u) } - -> convertible_to; - }; - - class _Strong_fallback - { - template - static constexpr bool - _S_noexcept() - { - if constexpr (__strongly_ordered<_Tp, _Up>) - return _Strong_order::_S_noexcept<_Tp, _Up>(); - else - return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) - && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); - } - - public: - template - requires __strongly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> - constexpr decltype(auto) - operator()(_Tp&& __e, _Up&& __f) const - noexcept(_S_noexcept<_Tp, _Up>()) - { - static_assert(same_as, decay_t<_Up>>); - - if constexpr (__strongly_ordered<_Tp, _Up>) - return _Strong_order{}(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f)); - else if constexpr (__op_eq_lt<_Tp, _Up>) - return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) - ? strong_ordering::equal - : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) - ? strong_ordering::less - : strong_ordering::greater; - } - }; - - class _Weak_fallback - { - template - static constexpr bool - _S_noexcept() - { - if constexpr (__weakly_ordered<_Tp, _Up>) - return _Weak_order::_S_noexcept<_Tp, _Up>(); - else - return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) - && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); - } - - public: - template - requires __weakly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> - constexpr decltype(auto) - operator()(_Tp&& __e, _Up&& __f) const - noexcept(_S_noexcept<_Tp, _Up>()) - { - static_assert(same_as, decay_t<_Up>>); - - if constexpr (__weakly_ordered<_Tp, _Up>) - return _Weak_order{}(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f)); - else if constexpr (__op_eq_lt<_Tp, _Up>) - return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) - ? weak_ordering::equivalent - : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) - ? weak_ordering::less - : weak_ordering::greater; - } - }; - - class _Partial_fallback - { - template - static constexpr bool - _S_noexcept() - { - if constexpr (__partially_ordered<_Tp, _Up>) - return _Partial_order::_S_noexcept<_Tp, _Up>(); - else - return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) - && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); - } - - public: - template - requires __partially_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> - constexpr decltype(auto) - operator()(_Tp&& __e, _Up&& __f) const - noexcept(_S_noexcept<_Tp, _Up>()) - { - static_assert(same_as, decay_t<_Up>>); - - if constexpr (__partially_ordered<_Tp, _Up>) - return _Partial_order{}(static_cast<_Tp&&>(__e), - static_cast<_Up&&>(__f)); - else if constexpr (__op_eq_lt<_Tp, _Up>) - return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) - ? partial_ordering::equivalent - : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) - ? partial_ordering::less - : static_cast<_Up&&>(__f) < static_cast<_Tp&&>(__e) - ? partial_ordering::greater - : partial_ordering::unordered; - } - }; - } // namespace __cmp_cust - - // [cmp.alg], comparison algorithms - inline namespace __cmp_alg - { - inline constexpr __cmp_cust::_Strong_order strong_order{}; - - inline constexpr __cmp_cust::_Weak_order weak_order{}; - - inline constexpr __cmp_cust::_Partial_order partial_order{}; - - inline constexpr __cmp_cust::_Strong_fallback - compare_strong_order_fallback{}; - - inline constexpr __cmp_cust::_Weak_fallback - compare_weak_order_fallback{}; - - inline constexpr __cmp_cust::_Partial_fallback - compare_partial_order_fallback{}; - } - - namespace __detail - { - // [expos.only.func] synth-three-way - inline constexpr struct _Synth3way - { - template - static constexpr bool - _S_noexcept(const _Tp* __t = nullptr, const _Up* __u = nullptr) - { - if constexpr (three_way_comparable_with<_Tp, _Up>) - return noexcept(*__t <=> *__u); - else - return noexcept(*__t < *__u) && noexcept(*__u < *__t); - } - - template - constexpr auto - operator()(const _Tp& __t, const _Up& __u) const - noexcept(_S_noexcept<_Tp, _Up>()) - requires requires - { - { __t < __u } -> __boolean_testable; - { __u < __t } -> __boolean_testable; - } - { - if constexpr (three_way_comparable_with<_Tp, _Up>) - return __t <=> __u; - else - { - if (__t < __u) - return weak_ordering::less; - else if (__u < __t) - return weak_ordering::greater; - else - return weak_ordering::equivalent; - } - } - } __synth3way = {}; - - // [expos.only.func] synth-three-way-result - template - using __synth3way_t - = decltype(__detail::__synth3way(std::declval<_Tp&>(), - std::declval<_Up&>())); - } // namespace __detail -#endif // concepts -} // namespace std - -#pragma GCC visibility pop - -#endif // C++20 - -#endif // _COMPARE diff --git a/resources/sources/avr-libstdcpp/include/complex b/resources/sources/avr-libstdcpp/include/complex deleted file mode 100644 index 52f59a19b..000000000 --- a/resources/sources/avr-libstdcpp/include/complex +++ /dev/null @@ -1,1931 +0,0 @@ -// The template and inlines for the -*- C++ -*- complex number classes. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/complex - * This is a Standard C++ Library header. - */ - -// -// ISO C++ 14882: 26.2 Complex Numbers -// Note: this is not a conforming implementation. -// Initially implemented by Ulrich Drepper -// Improved by Gabriel Dos Reis -// - -#ifndef _GLIBCXX_COMPLEX -#define _GLIBCXX_COMPLEX 1 - -#pragma GCC system_header - -#include -#include -#include -#include - -// Get rid of a macro possibly defined in -#undef complex - -#if __cplusplus > 201703L -# define __cpp_lib_constexpr_complex 201711L -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup complex_numbers Complex Numbers - * @ingroup numerics - * - * Classes and functions for complex numbers. - * @{ - */ - - // Forward declarations. - template class complex; - template<> class complex; - template<> class complex; - template<> class complex; - - /// Return magnitude of @a z. - template _Tp abs(const complex<_Tp>&); - /// Return phase angle of @a z. - template _Tp arg(const complex<_Tp>&); - /// Return @a z magnitude squared. - template _Tp _GLIBCXX20_CONSTEXPR norm(const complex<_Tp>&); - - /// Return complex conjugate of @a z. - template - _GLIBCXX20_CONSTEXPR complex<_Tp> conj(const complex<_Tp>&); - /// Return complex with magnitude @a rho and angle @a theta. - template complex<_Tp> polar(const _Tp&, const _Tp& = 0); - - // Transcendentals: - /// Return complex cosine of @a z. - template complex<_Tp> cos(const complex<_Tp>&); - /// Return complex hyperbolic cosine of @a z. - template complex<_Tp> cosh(const complex<_Tp>&); - /// Return complex base e exponential of @a z. - template complex<_Tp> exp(const complex<_Tp>&); - /// Return complex natural logarithm of @a z. - template complex<_Tp> log(const complex<_Tp>&); - /// Return complex base 10 logarithm of @a z. - template complex<_Tp> log10(const complex<_Tp>&); - /// Return @a x to the @a y'th power. - template complex<_Tp> pow(const complex<_Tp>&, int); - /// Return @a x to the @a y'th power. - template complex<_Tp> pow(const complex<_Tp>&, const _Tp&); - /// Return @a x to the @a y'th power. - template complex<_Tp> pow(const complex<_Tp>&, - const complex<_Tp>&); - /// Return @a x to the @a y'th power. - template complex<_Tp> pow(const _Tp&, const complex<_Tp>&); - /// Return complex sine of @a z. - template complex<_Tp> sin(const complex<_Tp>&); - /// Return complex hyperbolic sine of @a z. - template complex<_Tp> sinh(const complex<_Tp>&); - /// Return complex square root of @a z. - template complex<_Tp> sqrt(const complex<_Tp>&); - /// Return complex tangent of @a z. - template complex<_Tp> tan(const complex<_Tp>&); - /// Return complex hyperbolic tangent of @a z. - template complex<_Tp> tanh(const complex<_Tp>&); - - - // 26.2.2 Primary template class complex - /** - * Template to represent complex numbers. - * - * Specializations for float, double, and long double are part of the - * library. Results with any other type are not guaranteed. - * - * @param Tp Type of real and imaginary values. - */ - template - struct complex - { - /// Value typedef. - typedef _Tp value_type; - - /// Default constructor. First parameter is x, second parameter is y. - /// Unspecified parameters default to 0. - _GLIBCXX_CONSTEXPR complex(const _Tp& __r = _Tp(), const _Tp& __i = _Tp()) - : _M_real(__r), _M_imag(__i) { } - - // Let the compiler synthesize the copy constructor -#if __cplusplus >= 201103L - constexpr complex(const complex&) = default; -#endif - - /// Converting constructor. - template - _GLIBCXX_CONSTEXPR complex(const complex<_Up>& __z) - : _M_real(__z.real()), _M_imag(__z.imag()) { } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 387. std::complex over-encapsulated. - _GLIBCXX_ABI_TAG_CXX11 - constexpr _Tp - real() const { return _M_real; } - - _GLIBCXX_ABI_TAG_CXX11 - constexpr _Tp - imag() const { return _M_imag; } -#else - /// Return real part of complex number. - _Tp& - real() { return _M_real; } - - /// Return real part of complex number. - const _Tp& - real() const { return _M_real; } - - /// Return imaginary part of complex number. - _Tp& - imag() { return _M_imag; } - - /// Return imaginary part of complex number. - const _Tp& - imag() const { return _M_imag; } -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 387. std::complex over-encapsulated. - _GLIBCXX20_CONSTEXPR void - real(_Tp __val) { _M_real = __val; } - - _GLIBCXX20_CONSTEXPR void - imag(_Tp __val) { _M_imag = __val; } - - /// Assign a scalar to this complex number. - _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const _Tp&); - - /// Add a scalar to this complex number. - // 26.2.5/1 - _GLIBCXX20_CONSTEXPR complex<_Tp>& - operator+=(const _Tp& __t) - { - _M_real += __t; - return *this; - } - - /// Subtract a scalar from this complex number. - // 26.2.5/3 - _GLIBCXX20_CONSTEXPR complex<_Tp>& - operator-=(const _Tp& __t) - { - _M_real -= __t; - return *this; - } - - /// Multiply this complex number by a scalar. - _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const _Tp&); - /// Divide this complex number by a scalar. - _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const _Tp&); - - // Let the compiler synthesize the copy assignment operator -#if __cplusplus >= 201103L - _GLIBCXX20_CONSTEXPR complex& operator=(const complex&) = default; -#endif - - /// Assign another complex number to this one. - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const complex<_Up>&); - /// Add another complex number to this one. - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& operator+=(const complex<_Up>&); - /// Subtract another complex number from this one. - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& operator-=(const complex<_Up>&); - /// Multiply this complex number by another. - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const complex<_Up>&); - /// Divide this complex number by another. - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const complex<_Up>&); - - _GLIBCXX_CONSTEXPR complex __rep() const - { return *this; } - - private: - _Tp _M_real; - _Tp _M_imag; - }; - - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& - complex<_Tp>::operator=(const _Tp& __t) - { - _M_real = __t; - _M_imag = _Tp(); - return *this; - } - - // 26.2.5/5 - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& - complex<_Tp>::operator*=(const _Tp& __t) - { - _M_real *= __t; - _M_imag *= __t; - return *this; - } - - // 26.2.5/7 - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& - complex<_Tp>::operator/=(const _Tp& __t) - { - _M_real /= __t; - _M_imag /= __t; - return *this; - } - - template - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& - complex<_Tp>::operator=(const complex<_Up>& __z) - { - _M_real = __z.real(); - _M_imag = __z.imag(); - return *this; - } - - // 26.2.5/9 - template - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& - complex<_Tp>::operator+=(const complex<_Up>& __z) - { - _M_real += __z.real(); - _M_imag += __z.imag(); - return *this; - } - - // 26.2.5/11 - template - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& - complex<_Tp>::operator-=(const complex<_Up>& __z) - { - _M_real -= __z.real(); - _M_imag -= __z.imag(); - return *this; - } - - // 26.2.5/13 - // XXX: This is a grammar school implementation. - template - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& - complex<_Tp>::operator*=(const complex<_Up>& __z) - { - const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag(); - _M_imag = _M_real * __z.imag() + _M_imag * __z.real(); - _M_real = __r; - return *this; - } - - // 26.2.5/15 - // XXX: This is a grammar school implementation. - template - template - _GLIBCXX20_CONSTEXPR complex<_Tp>& - complex<_Tp>::operator/=(const complex<_Up>& __z) - { - const _Tp __r = _M_real * __z.real() + _M_imag * __z.imag(); - const _Tp __n = std::norm(__z); - _M_imag = (_M_imag * __z.real() - _M_real * __z.imag()) / __n; - _M_real = __r / __n; - return *this; - } - - // Operators: - //@{ - /// Return new complex value @a x plus @a y. - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) - { - complex<_Tp> __r = __x; - __r += __y; - return __r; - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator+(const complex<_Tp>& __x, const _Tp& __y) - { - complex<_Tp> __r = __x; - __r += __y; - return __r; - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator+(const _Tp& __x, const complex<_Tp>& __y) - { - complex<_Tp> __r = __y; - __r += __x; - return __r; - } - //@} - - //@{ - /// Return new complex value @a x minus @a y. - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) - { - complex<_Tp> __r = __x; - __r -= __y; - return __r; - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator-(const complex<_Tp>& __x, const _Tp& __y) - { - complex<_Tp> __r = __x; - __r -= __y; - return __r; - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator-(const _Tp& __x, const complex<_Tp>& __y) - { - complex<_Tp> __r = -__y; - __r += __x; - return __r; - } - //@} - - //@{ - /// Return new complex value @a x times @a y. - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator*(const complex<_Tp>& __x, const complex<_Tp>& __y) - { - complex<_Tp> __r = __x; - __r *= __y; - return __r; - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator*(const complex<_Tp>& __x, const _Tp& __y) - { - complex<_Tp> __r = __x; - __r *= __y; - return __r; - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator*(const _Tp& __x, const complex<_Tp>& __y) - { - complex<_Tp> __r = __y; - __r *= __x; - return __r; - } - //@} - - //@{ - /// Return new complex value @a x divided by @a y. - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator/(const complex<_Tp>& __x, const complex<_Tp>& __y) - { - complex<_Tp> __r = __x; - __r /= __y; - return __r; - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator/(const complex<_Tp>& __x, const _Tp& __y) - { - complex<_Tp> __r = __x; - __r /= __y; - return __r; - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator/(const _Tp& __x, const complex<_Tp>& __y) - { - complex<_Tp> __r = __x; - __r /= __y; - return __r; - } - //@} - - /// Return @a x. - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator+(const complex<_Tp>& __x) - { return __x; } - - /// Return complex negation of @a x. - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - operator-(const complex<_Tp>& __x) - { return complex<_Tp>(-__x.real(), -__x.imag()); } - - //@{ - /// Return true if @a x is equal to @a y. - template - inline _GLIBCXX_CONSTEXPR bool - operator==(const complex<_Tp>& __x, const complex<_Tp>& __y) - { return __x.real() == __y.real() && __x.imag() == __y.imag(); } - - template - inline _GLIBCXX_CONSTEXPR bool - operator==(const complex<_Tp>& __x, const _Tp& __y) - { return __x.real() == __y && __x.imag() == _Tp(); } - -#if !(__cpp_impl_three_way_comparison >= 201907L) - template - inline _GLIBCXX_CONSTEXPR bool - operator==(const _Tp& __x, const complex<_Tp>& __y) - { return __x == __y.real() && _Tp() == __y.imag(); } - //@} - - //@{ - /// Return false if @a x is equal to @a y. - template - inline _GLIBCXX_CONSTEXPR bool - operator!=(const complex<_Tp>& __x, const complex<_Tp>& __y) - { return __x.real() != __y.real() || __x.imag() != __y.imag(); } - - template - inline _GLIBCXX_CONSTEXPR bool - operator!=(const complex<_Tp>& __x, const _Tp& __y) - { return __x.real() != __y || __x.imag() != _Tp(); } - - template - inline _GLIBCXX_CONSTEXPR bool - operator!=(const _Tp& __x, const complex<_Tp>& __y) - { return __x != __y.real() || _Tp() != __y.imag(); } -#endif - //@} - - // Values -#if __cplusplus >= 201103L - template - constexpr _Tp - real(const complex<_Tp>& __z) - { return __z.real(); } - - template - constexpr _Tp - imag(const complex<_Tp>& __z) - { return __z.imag(); } -#else - template - inline _Tp& - real(complex<_Tp>& __z) - { return __z.real(); } - - template - inline const _Tp& - real(const complex<_Tp>& __z) - { return __z.real(); } - - template - inline _Tp& - imag(complex<_Tp>& __z) - { return __z.imag(); } - - template - inline const _Tp& - imag(const complex<_Tp>& __z) - { return __z.imag(); } -#endif - - // 26.2.7/3 abs(__z): Returns the magnitude of __z. - template - inline _Tp - __complex_abs(const complex<_Tp>& __z) - { - _Tp __x = __z.real(); - _Tp __y = __z.imag(); - const _Tp __s = std::max(abs(__x), abs(__y)); - if (__s == _Tp()) // well ... - return __s; - __x /= __s; - __y /= __s; - return __s * sqrt(__x * __x + __y * __y); - } - -#if _GLIBCXX_USE_C99_COMPLEX - inline float - __complex_abs(__complex__ float __z) { return __builtin_cabsf(__z); } - - inline double - __complex_abs(__complex__ double __z) { return __builtin_cabs(__z); } - - inline long double - __complex_abs(const __complex__ long double& __z) - { return __builtin_cabsl(__z); } - - template - inline _Tp - abs(const complex<_Tp>& __z) { return __complex_abs(__z.__rep()); } -#else - template - inline _Tp - abs(const complex<_Tp>& __z) { return __complex_abs(__z); } -#endif - - - // 26.2.7/4: arg(__z): Returns the phase angle of __z. - template - inline _Tp - __complex_arg(const complex<_Tp>& __z) - { return atan2(__z.imag(), __z.real()); } - -#if _GLIBCXX_USE_C99_COMPLEX - inline float - __complex_arg(__complex__ float __z) { return __builtin_cargf(__z); } - - inline double - __complex_arg(__complex__ double __z) { return __builtin_carg(__z); } - - inline long double - __complex_arg(const __complex__ long double& __z) - { return __builtin_cargl(__z); } - - template - inline _Tp - arg(const complex<_Tp>& __z) { return __complex_arg(__z.__rep()); } -#else - template - inline _Tp - arg(const complex<_Tp>& __z) { return __complex_arg(__z); } -#endif - - // 26.2.7/5: norm(__z) returns the squared magnitude of __z. - // As defined, norm() is -not- a norm is the common mathematical - // sense used in numerics. The helper class _Norm_helper<> tries to - // distinguish between builtin floating point and the rest, so as - // to deliver an answer as close as possible to the real value. - template - struct _Norm_helper - { - template - static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return __x * __x + __y * __y; - } - }; - - template<> - struct _Norm_helper - { - template - static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) - { - //_Tp __res = std::abs(__z); - //return __res * __res; - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return __x * __x + __y * __y; - } - }; - - template - inline _GLIBCXX20_CONSTEXPR _Tp - norm(const complex<_Tp>& __z) - { - return _Norm_helper<__is_floating<_Tp>::__value - && !_GLIBCXX_FAST_MATH>::_S_do_it(__z); - } - - template - inline complex<_Tp> - polar(const _Tp& __rho, const _Tp& __theta) - { - __glibcxx_assert( __rho >= 0 ); - return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta)); - } - - template - inline _GLIBCXX20_CONSTEXPR complex<_Tp> - conj(const complex<_Tp>& __z) - { return complex<_Tp>(__z.real(), -__z.imag()); } - - // Transcendentals - - // 26.2.8/1 cos(__z): Returns the cosine of __z. - template - inline complex<_Tp> - __complex_cos(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return complex<_Tp>(cos(__x) * cosh(__y), -sin(__x) * sinh(__y)); - } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_cos(__complex__ float __z) { return __builtin_ccosf(__z); } - - inline __complex__ double - __complex_cos(__complex__ double __z) { return __builtin_ccos(__z); } - - inline __complex__ long double - __complex_cos(const __complex__ long double& __z) - { return __builtin_ccosl(__z); } - - template - inline complex<_Tp> - cos(const complex<_Tp>& __z) { return __complex_cos(__z.__rep()); } -#else - template - inline complex<_Tp> - cos(const complex<_Tp>& __z) { return __complex_cos(__z); } -#endif - - // 26.2.8/2 cosh(__z): Returns the hyperbolic cosine of __z. - template - inline complex<_Tp> - __complex_cosh(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return complex<_Tp>(cosh(__x) * cos(__y), sinh(__x) * sin(__y)); - } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_cosh(__complex__ float __z) { return __builtin_ccoshf(__z); } - - inline __complex__ double - __complex_cosh(__complex__ double __z) { return __builtin_ccosh(__z); } - - inline __complex__ long double - __complex_cosh(const __complex__ long double& __z) - { return __builtin_ccoshl(__z); } - - template - inline complex<_Tp> - cosh(const complex<_Tp>& __z) { return __complex_cosh(__z.__rep()); } -#else - template - inline complex<_Tp> - cosh(const complex<_Tp>& __z) { return __complex_cosh(__z); } -#endif - - // 26.2.8/3 exp(__z): Returns the complex base e exponential of x - template - inline complex<_Tp> - __complex_exp(const complex<_Tp>& __z) - { return std::polar<_Tp>(exp(__z.real()), __z.imag()); } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_exp(__complex__ float __z) { return __builtin_cexpf(__z); } - - inline __complex__ double - __complex_exp(__complex__ double __z) { return __builtin_cexp(__z); } - - inline __complex__ long double - __complex_exp(const __complex__ long double& __z) - { return __builtin_cexpl(__z); } - - template - inline complex<_Tp> - exp(const complex<_Tp>& __z) { return __complex_exp(__z.__rep()); } -#else - template - inline complex<_Tp> - exp(const complex<_Tp>& __z) { return __complex_exp(__z); } -#endif - - // 26.2.8/5 log(__z): Returns the natural complex logarithm of __z. - // The branch cut is along the negative axis. - template - inline complex<_Tp> - __complex_log(const complex<_Tp>& __z) - { return complex<_Tp>(log(std::abs(__z)), std::arg(__z)); } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_log(__complex__ float __z) { return __builtin_clogf(__z); } - - inline __complex__ double - __complex_log(__complex__ double __z) { return __builtin_clog(__z); } - - inline __complex__ long double - __complex_log(const __complex__ long double& __z) - { return __builtin_clogl(__z); } - - template - inline complex<_Tp> - log(const complex<_Tp>& __z) { return __complex_log(__z.__rep()); } -#else - template - inline complex<_Tp> - log(const complex<_Tp>& __z) { return __complex_log(__z); } -#endif - - template - inline complex<_Tp> - log10(const complex<_Tp>& __z) - { return std::log(__z) / log(_Tp(10.0)); } - - // 26.2.8/10 sin(__z): Returns the sine of __z. - template - inline complex<_Tp> - __complex_sin(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return complex<_Tp>(sin(__x) * cosh(__y), cos(__x) * sinh(__y)); - } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_sin(__complex__ float __z) { return __builtin_csinf(__z); } - - inline __complex__ double - __complex_sin(__complex__ double __z) { return __builtin_csin(__z); } - - inline __complex__ long double - __complex_sin(const __complex__ long double& __z) - { return __builtin_csinl(__z); } - - template - inline complex<_Tp> - sin(const complex<_Tp>& __z) { return __complex_sin(__z.__rep()); } -#else - template - inline complex<_Tp> - sin(const complex<_Tp>& __z) { return __complex_sin(__z); } -#endif - - // 26.2.8/11 sinh(__z): Returns the hyperbolic sine of __z. - template - inline complex<_Tp> - __complex_sinh(const complex<_Tp>& __z) - { - const _Tp __x = __z.real(); - const _Tp __y = __z.imag(); - return complex<_Tp>(sinh(__x) * cos(__y), cosh(__x) * sin(__y)); - } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_sinh(__complex__ float __z) { return __builtin_csinhf(__z); } - - inline __complex__ double - __complex_sinh(__complex__ double __z) { return __builtin_csinh(__z); } - - inline __complex__ long double - __complex_sinh(const __complex__ long double& __z) - { return __builtin_csinhl(__z); } - - template - inline complex<_Tp> - sinh(const complex<_Tp>& __z) { return __complex_sinh(__z.__rep()); } -#else - template - inline complex<_Tp> - sinh(const complex<_Tp>& __z) { return __complex_sinh(__z); } -#endif - - // 26.2.8/13 sqrt(__z): Returns the complex square root of __z. - // The branch cut is on the negative axis. - template - complex<_Tp> - __complex_sqrt(const complex<_Tp>& __z) - { - _Tp __x = __z.real(); - _Tp __y = __z.imag(); - - if (__x == _Tp()) - { - _Tp __t = sqrt(abs(__y) / 2); - return complex<_Tp>(__t, __y < _Tp() ? -__t : __t); - } - else - { - _Tp __t = sqrt(2 * (std::abs(__z) + abs(__x))); - _Tp __u = __t / 2; - return __x > _Tp() - ? complex<_Tp>(__u, __y / __t) - : complex<_Tp>(abs(__y) / __t, __y < _Tp() ? -__u : __u); - } - } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_sqrt(__complex__ float __z) { return __builtin_csqrtf(__z); } - - inline __complex__ double - __complex_sqrt(__complex__ double __z) { return __builtin_csqrt(__z); } - - inline __complex__ long double - __complex_sqrt(const __complex__ long double& __z) - { return __builtin_csqrtl(__z); } - - template - inline complex<_Tp> - sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z.__rep()); } -#else - template - inline complex<_Tp> - sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z); } -#endif - - // 26.2.8/14 tan(__z): Return the complex tangent of __z. - - template - inline complex<_Tp> - __complex_tan(const complex<_Tp>& __z) - { return std::sin(__z) / std::cos(__z); } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_tan(__complex__ float __z) { return __builtin_ctanf(__z); } - - inline __complex__ double - __complex_tan(__complex__ double __z) { return __builtin_ctan(__z); } - - inline __complex__ long double - __complex_tan(const __complex__ long double& __z) - { return __builtin_ctanl(__z); } - - template - inline complex<_Tp> - tan(const complex<_Tp>& __z) { return __complex_tan(__z.__rep()); } -#else - template - inline complex<_Tp> - tan(const complex<_Tp>& __z) { return __complex_tan(__z); } -#endif - - - // 26.2.8/15 tanh(__z): Returns the hyperbolic tangent of __z. - - template - inline complex<_Tp> - __complex_tanh(const complex<_Tp>& __z) - { return std::sinh(__z) / std::cosh(__z); } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_tanh(__complex__ float __z) { return __builtin_ctanhf(__z); } - - inline __complex__ double - __complex_tanh(__complex__ double __z) { return __builtin_ctanh(__z); } - - inline __complex__ long double - __complex_tanh(const __complex__ long double& __z) - { return __builtin_ctanhl(__z); } - - template - inline complex<_Tp> - tanh(const complex<_Tp>& __z) { return __complex_tanh(__z.__rep()); } -#else - template - inline complex<_Tp> - tanh(const complex<_Tp>& __z) { return __complex_tanh(__z); } -#endif - - - // 26.2.8/9 pow(__x, __y): Returns the complex power base of __x - // raised to the __y-th power. The branch - // cut is on the negative axis. - template - complex<_Tp> - __complex_pow_unsigned(complex<_Tp> __x, unsigned __n) - { - complex<_Tp> __y = __n % 2 ? __x : complex<_Tp>(1); - - while (__n >>= 1) - { - __x *= __x; - if (__n % 2) - __y *= __x; - } - - return __y; - } - - // In C++11 mode we used to implement the resolution of - // DR 844. complex pow return type is ambiguous. - // thus the following overload was disabled in that mode. However, doing - // that causes all sorts of issues, see, for example: - // http://gcc.gnu.org/ml/libstdc++/2013-01/msg00058.html - // and also PR57974. - template - inline complex<_Tp> - pow(const complex<_Tp>& __z, int __n) - { - return __n < 0 - ? complex<_Tp>(1) / std::__complex_pow_unsigned(__z, -(unsigned)__n) - : std::__complex_pow_unsigned(__z, __n); - } - - template - complex<_Tp> - pow(const complex<_Tp>& __x, const _Tp& __y) - { -#if ! _GLIBCXX_USE_C99_COMPLEX - if (__x == _Tp()) - return _Tp(); -#endif - if (__x.imag() == _Tp() && __x.real() > _Tp()) - return pow(__x.real(), __y); - - complex<_Tp> __t = std::log(__x); - return std::polar<_Tp>(exp(__y * __t.real()), __y * __t.imag()); - } - - template - inline complex<_Tp> - __complex_pow(const complex<_Tp>& __x, const complex<_Tp>& __y) - { return __x == _Tp() ? _Tp() : std::exp(__y * std::log(__x)); } - -#if _GLIBCXX_USE_C99_COMPLEX - inline __complex__ float - __complex_pow(__complex__ float __x, __complex__ float __y) - { return __builtin_cpowf(__x, __y); } - - inline __complex__ double - __complex_pow(__complex__ double __x, __complex__ double __y) - { return __builtin_cpow(__x, __y); } - - inline __complex__ long double - __complex_pow(const __complex__ long double& __x, - const __complex__ long double& __y) - { return __builtin_cpowl(__x, __y); } - - template - inline complex<_Tp> - pow(const complex<_Tp>& __x, const complex<_Tp>& __y) - { return __complex_pow(__x.__rep(), __y.__rep()); } -#else - template - inline complex<_Tp> - pow(const complex<_Tp>& __x, const complex<_Tp>& __y) - { return __complex_pow(__x, __y); } -#endif - - template - inline complex<_Tp> - pow(const _Tp& __x, const complex<_Tp>& __y) - { - return __x > _Tp() ? std::polar<_Tp>(pow(__x, __y.real()), - __y.imag() * log(__x)) - : std::pow(complex<_Tp>(__x), __y); - } - - /// 26.2.3 complex specializations - /// complex specialization - template<> - struct complex - { - typedef float value_type; - typedef __complex__ float _ComplexT; - - _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } - - _GLIBCXX_CONSTEXPR complex(float __r = 0.0f, float __i = 0.0f) -#if __cplusplus >= 201103L - : _M_value{ __r, __i } { } -#else - { - __real__ _M_value = __r; - __imag__ _M_value = __i; - } -#endif - - explicit _GLIBCXX_CONSTEXPR complex(const complex&); - explicit _GLIBCXX_CONSTEXPR complex(const complex&); - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 387. std::complex over-encapsulated. - __attribute ((__abi_tag__ ("cxx11"))) - constexpr float - real() const { return __real__ _M_value; } - - __attribute ((__abi_tag__ ("cxx11"))) - constexpr float - imag() const { return __imag__ _M_value; } -#else - float& - real() { return __real__ _M_value; } - - const float& - real() const { return __real__ _M_value; } - - float& - imag() { return __imag__ _M_value; } - - const float& - imag() const { return __imag__ _M_value; } -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 387. std::complex over-encapsulated. - _GLIBCXX20_CONSTEXPR void - real(float __val) { __real__ _M_value = __val; } - - _GLIBCXX20_CONSTEXPR void - imag(float __val) { __imag__ _M_value = __val; } - - _GLIBCXX20_CONSTEXPR complex& - operator=(float __f) - { - _M_value = __f; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator+=(float __f) - { - _M_value += __f; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator-=(float __f) - { - _M_value -= __f; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator*=(float __f) - { - _M_value *= __f; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator/=(float __f) - { - _M_value /= __f; - return *this; - } - - // Let the compiler synthesize the copy and assignment - // operator. It always does a pretty good job. -#if __cplusplus >= 201103L - _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; -#endif - - template - _GLIBCXX20_CONSTEXPR complex& - operator=(const complex<_Tp>& __z) - { - __real__ _M_value = __z.real(); - __imag__ _M_value = __z.imag(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator+=(const complex<_Tp>& __z) - { - _M_value += __z.__rep(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator-=(const complex<_Tp>& __z) - { - _M_value -= __z.__rep(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator*=(const complex<_Tp>& __z) - { - const _ComplexT __t = __z.__rep(); - _M_value *= __t; - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator/=(const complex<_Tp>& __z) - { - const _ComplexT __t = __z.__rep(); - _M_value /= __t; - return *this; - } - - _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } - - private: - _ComplexT _M_value; - }; - - /// 26.2.3 complex specializations - /// complex specialization - template<> - struct complex - { - typedef double value_type; - typedef __complex__ double _ComplexT; - - _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } - - _GLIBCXX_CONSTEXPR complex(double __r = 0.0, double __i = 0.0) -#if __cplusplus >= 201103L - : _M_value{ __r, __i } { } -#else - { - __real__ _M_value = __r; - __imag__ _M_value = __i; - } -#endif - - _GLIBCXX_CONSTEXPR complex(const complex& __z) - : _M_value(__z.__rep()) { } - - explicit _GLIBCXX_CONSTEXPR complex(const complex&); - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 387. std::complex over-encapsulated. - __attribute ((__abi_tag__ ("cxx11"))) - constexpr double - real() const { return __real__ _M_value; } - - __attribute ((__abi_tag__ ("cxx11"))) - constexpr double - imag() const { return __imag__ _M_value; } -#else - double& - real() { return __real__ _M_value; } - - const double& - real() const { return __real__ _M_value; } - - double& - imag() { return __imag__ _M_value; } - - const double& - imag() const { return __imag__ _M_value; } -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 387. std::complex over-encapsulated. - _GLIBCXX20_CONSTEXPR void - real(double __val) { __real__ _M_value = __val; } - - _GLIBCXX20_CONSTEXPR void - imag(double __val) { __imag__ _M_value = __val; } - - _GLIBCXX20_CONSTEXPR complex& - operator=(double __d) - { - _M_value = __d; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator+=(double __d) - { - _M_value += __d; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator-=(double __d) - { - _M_value -= __d; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator*=(double __d) - { - _M_value *= __d; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator/=(double __d) - { - _M_value /= __d; - return *this; - } - - // The compiler will synthesize this, efficiently. -#if __cplusplus >= 201103L - _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; -#endif - - template - _GLIBCXX20_CONSTEXPR complex& - operator=(const complex<_Tp>& __z) - { - _M_value = __z.__rep(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator+=(const complex<_Tp>& __z) - { - _M_value += __z.__rep(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator-=(const complex<_Tp>& __z) - { - _M_value -= __z.__rep(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator*=(const complex<_Tp>& __z) - { - const _ComplexT __t = __z.__rep(); - _M_value *= __t; - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator/=(const complex<_Tp>& __z) - { - const _ComplexT __t = __z.__rep(); - _M_value /= __t; - return *this; - } - - _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } - - private: - _ComplexT _M_value; - }; - - /// 26.2.3 complex specializations - /// complex specialization - template<> - struct complex - { - typedef long double value_type; - typedef __complex__ long double _ComplexT; - - _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } - - _GLIBCXX_CONSTEXPR complex(long double __r = 0.0L, - long double __i = 0.0L) -#if __cplusplus >= 201103L - : _M_value{ __r, __i } { } -#else - { - __real__ _M_value = __r; - __imag__ _M_value = __i; - } -#endif - - _GLIBCXX_CONSTEXPR complex(const complex& __z) - : _M_value(__z.__rep()) { } - - _GLIBCXX_CONSTEXPR complex(const complex& __z) - : _M_value(__z.__rep()) { } - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 387. std::complex over-encapsulated. - __attribute ((__abi_tag__ ("cxx11"))) - constexpr long double - real() const { return __real__ _M_value; } - - __attribute ((__abi_tag__ ("cxx11"))) - constexpr long double - imag() const { return __imag__ _M_value; } -#else - long double& - real() { return __real__ _M_value; } - - const long double& - real() const { return __real__ _M_value; } - - long double& - imag() { return __imag__ _M_value; } - - const long double& - imag() const { return __imag__ _M_value; } -#endif - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // DR 387. std::complex over-encapsulated. - _GLIBCXX20_CONSTEXPR void - real(long double __val) { __real__ _M_value = __val; } - - _GLIBCXX20_CONSTEXPR void - imag(long double __val) { __imag__ _M_value = __val; } - - _GLIBCXX20_CONSTEXPR complex& - operator=(long double __r) - { - _M_value = __r; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator+=(long double __r) - { - _M_value += __r; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator-=(long double __r) - { - _M_value -= __r; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator*=(long double __r) - { - _M_value *= __r; - return *this; - } - - _GLIBCXX20_CONSTEXPR complex& - operator/=(long double __r) - { - _M_value /= __r; - return *this; - } - - // The compiler knows how to do this efficiently -#if __cplusplus >= 201103L - _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; -#endif - - template - _GLIBCXX20_CONSTEXPR complex& - operator=(const complex<_Tp>& __z) - { - _M_value = __z.__rep(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator+=(const complex<_Tp>& __z) - { - _M_value += __z.__rep(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator-=(const complex<_Tp>& __z) - { - _M_value -= __z.__rep(); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator*=(const complex<_Tp>& __z) - { - const _ComplexT __t = __z.__rep(); - _M_value *= __t; - return *this; - } - - template - _GLIBCXX20_CONSTEXPR complex& - operator/=(const complex<_Tp>& __z) - { - const _ComplexT __t = __z.__rep(); - _M_value /= __t; - return *this; - } - - _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } - - private: - _ComplexT _M_value; - }; - - // These bits have to be at the end of this file, so that the - // specializations have all been defined. - inline _GLIBCXX_CONSTEXPR - complex::complex(const complex& __z) - : _M_value(__z.__rep()) { } - - inline _GLIBCXX_CONSTEXPR - complex::complex(const complex& __z) - : _M_value(__z.__rep()) { } - - inline _GLIBCXX_CONSTEXPR - complex::complex(const complex& __z) - : _M_value(__z.__rep()) { } - - // @} group complex_numbers - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // See ext/type_traits.h for the primary template. - template - struct __promote_2, _Up> - { - public: - typedef std::complex::__type> __type; - }; - - template - struct __promote_2<_Tp, std::complex<_Up> > - { - public: - typedef std::complex::__type> __type; - }; - - template - struct __promote_2, std::complex<_Up> > - { - public: - typedef std::complex::__type> __type; - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#if __cplusplus >= 201103L - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Forward declarations. - template std::complex<_Tp> acos(const std::complex<_Tp>&); - template std::complex<_Tp> asin(const std::complex<_Tp>&); - template std::complex<_Tp> atan(const std::complex<_Tp>&); - - template std::complex<_Tp> acosh(const std::complex<_Tp>&); - template std::complex<_Tp> asinh(const std::complex<_Tp>&); - template std::complex<_Tp> atanh(const std::complex<_Tp>&); - // DR 595. - template _Tp fabs(const std::complex<_Tp>&); - - template - inline std::complex<_Tp> - __complex_acos(const std::complex<_Tp>& __z) - { - const std::complex<_Tp> __t = std::asin(__z); - const _Tp __pi_2 = 1.5707963267948966192313216916397514L; - return std::complex<_Tp>(__pi_2 - __t.real(), -__t.imag()); - } - -#if _GLIBCXX_USE_C99_COMPLEX_TR1 - inline __complex__ float - __complex_acos(__complex__ float __z) - { return __builtin_cacosf(__z); } - - inline __complex__ double - __complex_acos(__complex__ double __z) - { return __builtin_cacos(__z); } - - inline __complex__ long double - __complex_acos(const __complex__ long double& __z) - { return __builtin_cacosl(__z); } - - template - inline std::complex<_Tp> - acos(const std::complex<_Tp>& __z) - { return __complex_acos(__z.__rep()); } -#else - /// acos(__z) [8.1.2]. - // Effects: Behaves the same as C99 function cacos, defined - // in subclause 7.3.5.1. - template - inline std::complex<_Tp> - acos(const std::complex<_Tp>& __z) - { return __complex_acos(__z); } -#endif - - template - inline std::complex<_Tp> - __complex_asin(const std::complex<_Tp>& __z) - { - std::complex<_Tp> __t(-__z.imag(), __z.real()); - __t = std::asinh(__t); - return std::complex<_Tp>(__t.imag(), -__t.real()); - } - -#if _GLIBCXX_USE_C99_COMPLEX_TR1 - inline __complex__ float - __complex_asin(__complex__ float __z) - { return __builtin_casinf(__z); } - - inline __complex__ double - __complex_asin(__complex__ double __z) - { return __builtin_casin(__z); } - - inline __complex__ long double - __complex_asin(const __complex__ long double& __z) - { return __builtin_casinl(__z); } - - template - inline std::complex<_Tp> - asin(const std::complex<_Tp>& __z) - { return __complex_asin(__z.__rep()); } -#else - /// asin(__z) [8.1.3]. - // Effects: Behaves the same as C99 function casin, defined - // in subclause 7.3.5.2. - template - inline std::complex<_Tp> - asin(const std::complex<_Tp>& __z) - { return __complex_asin(__z); } -#endif - - template - std::complex<_Tp> - __complex_atan(const std::complex<_Tp>& __z) - { - const _Tp __r2 = __z.real() * __z.real(); - const _Tp __x = _Tp(1.0) - __r2 - __z.imag() * __z.imag(); - - _Tp __num = __z.imag() + _Tp(1.0); - _Tp __den = __z.imag() - _Tp(1.0); - - __num = __r2 + __num * __num; - __den = __r2 + __den * __den; - - return std::complex<_Tp>(_Tp(0.5) * atan2(_Tp(2.0) * __z.real(), __x), - _Tp(0.25) * log(__num / __den)); - } - -#if _GLIBCXX_USE_C99_COMPLEX_TR1 - inline __complex__ float - __complex_atan(__complex__ float __z) - { return __builtin_catanf(__z); } - - inline __complex__ double - __complex_atan(__complex__ double __z) - { return __builtin_catan(__z); } - - inline __complex__ long double - __complex_atan(const __complex__ long double& __z) - { return __builtin_catanl(__z); } - - template - inline std::complex<_Tp> - atan(const std::complex<_Tp>& __z) - { return __complex_atan(__z.__rep()); } -#else - /// atan(__z) [8.1.4]. - // Effects: Behaves the same as C99 function catan, defined - // in subclause 7.3.5.3. - template - inline std::complex<_Tp> - atan(const std::complex<_Tp>& __z) - { return __complex_atan(__z); } -#endif - - template - std::complex<_Tp> - __complex_acosh(const std::complex<_Tp>& __z) - { - // Kahan's formula. - return _Tp(2.0) * std::log(std::sqrt(_Tp(0.5) * (__z + _Tp(1.0))) - + std::sqrt(_Tp(0.5) * (__z - _Tp(1.0)))); - } - -#if _GLIBCXX_USE_C99_COMPLEX_TR1 - inline __complex__ float - __complex_acosh(__complex__ float __z) - { return __builtin_cacoshf(__z); } - - inline __complex__ double - __complex_acosh(__complex__ double __z) - { return __builtin_cacosh(__z); } - - inline __complex__ long double - __complex_acosh(const __complex__ long double& __z) - { return __builtin_cacoshl(__z); } - - template - inline std::complex<_Tp> - acosh(const std::complex<_Tp>& __z) - { return __complex_acosh(__z.__rep()); } -#else - /// acosh(__z) [8.1.5]. - // Effects: Behaves the same as C99 function cacosh, defined - // in subclause 7.3.6.1. - template - inline std::complex<_Tp> - acosh(const std::complex<_Tp>& __z) - { return __complex_acosh(__z); } -#endif - - template - std::complex<_Tp> - __complex_asinh(const std::complex<_Tp>& __z) - { - std::complex<_Tp> __t((__z.real() - __z.imag()) - * (__z.real() + __z.imag()) + _Tp(1.0), - _Tp(2.0) * __z.real() * __z.imag()); - __t = std::sqrt(__t); - - return std::log(__t + __z); - } - -#if _GLIBCXX_USE_C99_COMPLEX_TR1 - inline __complex__ float - __complex_asinh(__complex__ float __z) - { return __builtin_casinhf(__z); } - - inline __complex__ double - __complex_asinh(__complex__ double __z) - { return __builtin_casinh(__z); } - - inline __complex__ long double - __complex_asinh(const __complex__ long double& __z) - { return __builtin_casinhl(__z); } - - template - inline std::complex<_Tp> - asinh(const std::complex<_Tp>& __z) - { return __complex_asinh(__z.__rep()); } -#else - /// asinh(__z) [8.1.6]. - // Effects: Behaves the same as C99 function casin, defined - // in subclause 7.3.6.2. - template - inline std::complex<_Tp> - asinh(const std::complex<_Tp>& __z) - { return __complex_asinh(__z); } -#endif - - template - std::complex<_Tp> - __complex_atanh(const std::complex<_Tp>& __z) - { - const _Tp __i2 = __z.imag() * __z.imag(); - const _Tp __x = _Tp(1.0) - __i2 - __z.real() * __z.real(); - - _Tp __num = _Tp(1.0) + __z.real(); - _Tp __den = _Tp(1.0) - __z.real(); - - __num = __i2 + __num * __num; - __den = __i2 + __den * __den; - - return std::complex<_Tp>(_Tp(0.25) * (log(__num) - log(__den)), - _Tp(0.5) * atan2(_Tp(2.0) * __z.imag(), __x)); - } - -#if _GLIBCXX_USE_C99_COMPLEX_TR1 - inline __complex__ float - __complex_atanh(__complex__ float __z) - { return __builtin_catanhf(__z); } - - inline __complex__ double - __complex_atanh(__complex__ double __z) - { return __builtin_catanh(__z); } - - inline __complex__ long double - __complex_atanh(const __complex__ long double& __z) - { return __builtin_catanhl(__z); } - - template - inline std::complex<_Tp> - atanh(const std::complex<_Tp>& __z) - { return __complex_atanh(__z.__rep()); } -#else - /// atanh(__z) [8.1.7]. - // Effects: Behaves the same as C99 function catanh, defined - // in subclause 7.3.6.3. - template - inline std::complex<_Tp> - atanh(const std::complex<_Tp>& __z) - { return __complex_atanh(__z); } -#endif - - template - inline _Tp - /// fabs(__z) [8.1.8]. - // Effects: Behaves the same as C99 function cabs, defined - // in subclause 7.3.8.1. - fabs(const std::complex<_Tp>& __z) - { return std::abs(__z); } - - /// Additional overloads [8.1.9]. - template - inline typename __gnu_cxx::__promote<_Tp>::__type - arg(_Tp __x) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; -#if (_GLIBCXX11_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC) - return std::signbit(__x) ? __type(3.1415926535897932384626433832795029L) - : __type(); -#else - return std::arg(std::complex<__type>(__x)); -#endif - } - - template - _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type - imag(_Tp) - { return _Tp(); } - - template - _GLIBCXX20_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type - norm(_Tp __x) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return __type(__x) * __type(__x); - } - - template - _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type - real(_Tp __x) - { return __x; } - - template - inline std::complex::__type> - pow(const std::complex<_Tp>& __x, const _Up& __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return std::pow(std::complex<__type>(__x), __type(__y)); - } - - template - inline std::complex::__type> - pow(const _Tp& __x, const std::complex<_Up>& __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return std::pow(__type(__x), std::complex<__type>(__y)); - } - - template - inline std::complex::__type> - pow(const std::complex<_Tp>& __x, const std::complex<_Up>& __y) - { - typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; - return std::pow(std::complex<__type>(__x), - std::complex<__type>(__y)); - } - - // Forward declarations. - // DR 781. - template - std::complex<_Tp> proj(const std::complex<_Tp>&); - - // Generic implementation of std::proj, does not work for infinities. - template - inline std::complex<_Tp> - __complex_proj(const std::complex<_Tp>& __z) - { return __z; } - -#if _GLIBCXX_USE_C99_COMPLEX - inline complex - __complex_proj(const complex& __z) - { return __builtin_cprojf(__z.__rep()); } - - inline complex - __complex_proj(const complex& __z) - { return __builtin_cproj(__z.__rep()); } - - inline complex - __complex_proj(const complex& __z) - { return __builtin_cprojl(__z.__rep()); } -#elif defined _GLIBCXX_USE_C99_MATH_TR1 - inline complex - __complex_proj(const complex& __z) - { - if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) - return complex(__builtin_inff(), - __builtin_copysignf(0.0f, __z.imag())); - return __z; - } - - inline complex - __complex_proj(const complex& __z) - { - if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) - return complex(__builtin_inf(), - __builtin_copysign(0.0, __z.imag())); - return __z; - } - - inline complex - __complex_proj(const complex& __z) - { - if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) - return complex(__builtin_infl(), - __builtin_copysignl(0.0l, __z.imag())); - return __z; - } -#endif - - template - inline std::complex<_Tp> - proj(const std::complex<_Tp>& __z) - { return __complex_proj(__z); } - - // Overload for scalars - template - inline std::complex::__type> - proj(_Tp __x) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return std::proj(std::complex<__type>(__x)); - } - - template - inline _GLIBCXX20_CONSTEXPR - std::complex::__type> - conj(_Tp __x) - { - typedef typename __gnu_cxx::__promote<_Tp>::__type __type; - return std::complex<__type>(__x, -__type()); - } - -#if __cplusplus > 201103L - -inline namespace literals { -inline namespace complex_literals { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wliteral-suffix" -#define __cpp_lib_complex_udls 201309 - - constexpr std::complex - operator""if(long double __num) - { return std::complex{0.0F, static_cast(__num)}; } - - constexpr std::complex - operator""if(unsigned long long __num) - { return std::complex{0.0F, static_cast(__num)}; } - - constexpr std::complex - operator""i(long double __num) - { return std::complex{0.0, static_cast(__num)}; } - - constexpr std::complex - operator""i(unsigned long long __num) - { return std::complex{0.0, static_cast(__num)}; } - - constexpr std::complex - operator""il(long double __num) - { return std::complex{0.0L, __num}; } - - constexpr std::complex - operator""il(unsigned long long __num) - { return std::complex{0.0L, static_cast(__num)}; } - -#pragma GCC diagnostic pop -} // inline namespace complex_literals -} // inline namespace literals - -#endif // C++14 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 - -#endif /* _GLIBCXX_COMPLEX */ diff --git a/resources/sources/avr-libstdcpp/include/concepts b/resources/sources/avr-libstdcpp/include/concepts deleted file mode 100644 index e710a5e6e..000000000 --- a/resources/sources/avr-libstdcpp/include/concepts +++ /dev/null @@ -1,367 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2019-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/concepts - * This is a Standard C++ Library header. - * @ingroup concepts - */ - -#ifndef _GLIBCXX_CONCEPTS -#define _GLIBCXX_CONCEPTS 1 - -#if __cplusplus > 201703L && __cpp_concepts >= 201907L - -#pragma GCC system_header - -/** - * @defgroup concepts Concepts - * @ingroup utilities - * - * Concepts for checking type requirements. - */ - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#define __cpp_lib_concepts 202002L - - // [concepts.lang], language-related concepts - - namespace __detail - { - template - concept __same_as = std::is_same_v<_Tp, _Up>; - } // namespace __detail - - /// [concept.same], concept same_as - template - concept same_as - = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; - - /// [concept.derived], concept derived_from - template - concept derived_from = __is_base_of(_Base, _Derived) - && is_convertible_v; - - /// [concept.convertible], concept convertible_to - template - concept convertible_to = is_convertible_v<_From, _To> - && requires(add_rvalue_reference_t<_From> (&__f)()) { - static_cast<_To>(__f()); - }; - - /// [concept.commonref], concept common_reference_with - template - concept common_reference_with - = same_as, common_reference_t<_Up, _Tp>> - && convertible_to<_Tp, common_reference_t<_Tp, _Up>> - && convertible_to<_Up, common_reference_t<_Tp, _Up>>; - - /// [concept.common], concept common_with - template - concept common_with - = same_as, common_type_t<_Up, _Tp>> - && requires { - static_cast>(std::declval<_Tp>()); - static_cast>(std::declval<_Up>()); - } - && common_reference_with, - add_lvalue_reference_t> - && common_reference_with>, - common_reference_t< - add_lvalue_reference_t, - add_lvalue_reference_t>>; - - // [concepts.arithmetic], arithmetic concepts - - template - concept integral = is_integral_v<_Tp>; - - template - concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; - - template - concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; - - template - concept floating_point = is_floating_point_v<_Tp>; - - namespace __detail - { - template - using __cref = const remove_reference_t<_Tp>&; - - template - concept __class_or_enum - = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; - } // namespace __detail - - /// [concept.assignable], concept assignable_from - template - concept assignable_from - = is_lvalue_reference_v<_Lhs> - && common_reference_with<__detail::__cref<_Lhs>, __detail::__cref<_Rhs>> - && requires(_Lhs __lhs, _Rhs&& __rhs) { - { __lhs = static_cast<_Rhs&&>(__rhs) } -> same_as<_Lhs>; - }; - - /// [concept.destructible], concept destructible - template - concept destructible = is_nothrow_destructible_v<_Tp>; - - /// [concept.constructible], concept constructible_from - template - concept constructible_from - = destructible<_Tp> && is_constructible_v<_Tp, _Args...>; - - /// [concept.defaultinitializable], concept default_initializable - template - concept default_initializable = constructible_from<_Tp> - && requires - { - _Tp{}; - (void) ::new _Tp; - }; - - /// [concept.moveconstructible], concept move_constructible - template - concept move_constructible - = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; - - /// [concept.copyconstructible], concept copy_constructible - template - concept copy_constructible - = move_constructible<_Tp> - && constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> - && constructible_from<_Tp, const _Tp&> && convertible_to - && constructible_from<_Tp, const _Tp> && convertible_to; - - // [concept.swappable], concept swappable - - namespace ranges - { - namespace __cust_swap - { - template void swap(_Tp&, _Tp&) = delete; - - template - concept __adl_swap - = (__detail::__class_or_enum> - || __detail::__class_or_enum>) - && requires(_Tp&& __t, _Up&& __u) { - swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); - }; - - struct _Swap - { - private: - template - static constexpr bool - _S_noexcept() - { - if constexpr (__adl_swap<_Tp, _Up>) - return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())); - else - return is_nothrow_move_constructible_v> - && is_nothrow_move_assignable_v>; - } - - public: - template - requires __adl_swap<_Tp, _Up> - || (same_as<_Tp, _Up> && is_lvalue_reference_v<_Tp> - && move_constructible> - && assignable_from<_Tp, remove_reference_t<_Tp>>) - constexpr void - operator()(_Tp&& __t, _Up&& __u) const - noexcept(_S_noexcept<_Tp, _Up>()) - { - if constexpr (__adl_swap<_Tp, _Up>) - swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); - else - { - auto __tmp = static_cast&&>(__t); - __t = static_cast&&>(__u); - __u = static_cast&&>(__tmp); - } - } - - template - requires requires(const _Swap& __swap, _Tp& __e1, _Up& __e2) { - __swap(__e1, __e2); - } - constexpr void - operator()(_Tp (&__e1)[_Num], _Up (&__e2)[_Num]) const - noexcept(noexcept(std::declval()(*__e1, *__e2))) - { - for (size_t __n = 0; __n < _Num; ++__n) - (*this)(__e1[__n], __e2[__n]); - } - }; - } // namespace __cust_swap - - inline namespace __cust - { - inline constexpr __cust_swap::_Swap swap{}; - } // inline namespace __cust - } // namespace ranges - - template - concept swappable - = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; - - template - concept swappable_with = common_reference_with<_Tp, _Up> - && requires(_Tp&& __t, _Up&& __u) { - ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Tp&&>(__t)); - ranges::swap(static_cast<_Up&&>(__u), static_cast<_Up&&>(__u)); - ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); - ranges::swap(static_cast<_Up&&>(__u), static_cast<_Tp&&>(__t)); - }; - - // [concepts.object], Object concepts - - template - concept movable = is_object_v<_Tp> && move_constructible<_Tp> - && assignable_from<_Tp&, _Tp> && swappable<_Tp>; - - template - concept copyable = copy_constructible<_Tp> && movable<_Tp> - && assignable_from<_Tp&, _Tp&> && assignable_from<_Tp&, const _Tp&> - && assignable_from<_Tp&, const _Tp>; - - template - concept semiregular = copyable<_Tp> && default_initializable<_Tp>; - - // [concepts.compare], comparison concepts - - // [concept.booleantestable], Boolean testability - namespace __detail - { - template - concept __boolean_testable_impl = convertible_to<_Tp, bool>; - - template - concept __boolean_testable - = __boolean_testable_impl<_Tp> - && requires(_Tp&& __t) - { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; }; - } // namespace __detail - - // [concept.equalitycomparable], concept equality_comparable - - namespace __detail - { - template - concept __weakly_eq_cmp_with - = requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) { - { __t == __u } -> __boolean_testable; - { __t != __u } -> __boolean_testable; - { __u == __t } -> __boolean_testable; - { __u != __t } -> __boolean_testable; - }; - } // namespace __detail - - template - concept equality_comparable = __detail::__weakly_eq_cmp_with<_Tp, _Tp>; - - template - concept equality_comparable_with - = equality_comparable<_Tp> && equality_comparable<_Up> - && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>> - && equality_comparable, - __detail::__cref<_Up>>> - && __detail::__weakly_eq_cmp_with<_Tp, _Up>; - - namespace __detail - { - template - concept __partially_ordered_with - = requires(const remove_reference_t<_Tp>& __t, - const remove_reference_t<_Up>& __u) { - { __t < __u } -> __boolean_testable; - { __t > __u } -> __boolean_testable; - { __t <= __u } -> __boolean_testable; - { __t >= __u } -> __boolean_testable; - { __u < __t } -> __boolean_testable; - { __u > __t } -> __boolean_testable; - { __u <= __t } -> __boolean_testable; - { __u >= __t } -> __boolean_testable; - }; - } // namespace __detail - - // [concept.totallyordered], concept totally_ordered - template - concept totally_ordered - = equality_comparable<_Tp> - && __detail::__partially_ordered_with<_Tp, _Tp>; - - template - concept totally_ordered_with - = totally_ordered<_Tp> && totally_ordered<_Up> - && equality_comparable_with<_Tp, _Up> - && totally_ordered, - __detail::__cref<_Up>>> - && __detail::__partially_ordered_with<_Tp, _Up>; - - template - concept regular = semiregular<_Tp> && equality_comparable<_Tp>; - - // [concepts.callable], callable concepts - - /// [concept.invocable], concept invocable - template - concept invocable = is_invocable_v<_Fn, _Args...>; - - /// [concept.regularinvocable], concept regular_invocable - template - concept regular_invocable = invocable<_Fn, _Args...>; - - /// [concept.predicate], concept predicate - template - concept predicate = regular_invocable<_Fn, _Args...> - && __detail::__boolean_testable>; - - /// [concept.relation], concept relation - template - concept relation - = predicate<_Rel, _Tp, _Tp> && predicate<_Rel, _Up, _Up> - && predicate<_Rel, _Tp, _Up> && predicate<_Rel, _Up, _Tp>; - - /// [concept.equiv], concept equivalence_relation - template - concept equivalence_relation = relation<_Rel, _Tp, _Up>; - - /// [concept.strictweakorder], concept strict_weak_order - template - concept strict_weak_order = relation<_Rel, _Tp, _Up>; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -#endif // C++2a - -#endif /* _GLIBCXX_CONCEPTS */ diff --git a/resources/sources/avr-libstdcpp/include/coroutine b/resources/sources/avr-libstdcpp/include/coroutine deleted file mode 100644 index b40a3bcf9..000000000 --- a/resources/sources/avr-libstdcpp/include/coroutine +++ /dev/null @@ -1,303 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2019-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/coroutine - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_COROUTINE -#define _GLIBCXX_COROUTINE 1 - -#pragma GCC system_header - -// It is very likely that earlier versions would work, but they are untested. -#if __cplusplus >= 201402L - -#include - -/** - * @defgroup coroutines Coroutines - * - * Components for supporting coroutine implementations. - */ - -#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L -# include -# define _COROUTINES_USE_SPACESHIP 1 -#else -# include // for std::less -# define _COROUTINES_USE_SPACESHIP 0 -#endif - -namespace std _GLIBCXX_VISIBILITY (default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#if __cpp_impl_coroutine - -#define __cpp_lib_coroutine 201902L - - inline namespace __n4861 { - - // 17.12.2 coroutine traits - /// [coroutine.traits] - /// [coroutine.traits.primary] - /// If _Result::promise_type is valid and denotes a type then the traits - /// have a single publicly accessible member, otherwise they are empty. - template - struct __coroutine_traits_impl {}; - - template - struct __coroutine_traits_impl<_Result, - __void_t> - { - using promise_type = typename _Result::promise_type; - }; - - template - struct coroutine_traits : __coroutine_traits_impl<_Result> {}; - - // 17.12.3 Class template coroutine_handle - /// [coroutine.handle] - template - struct coroutine_handle; - - template <> struct - coroutine_handle - { - public: - // 17.12.3.1, construct/reset - constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {} - - constexpr coroutine_handle(std::nullptr_t __h) noexcept - : _M_fr_ptr(__h) - {} - - coroutine_handle& operator=(std::nullptr_t) noexcept - { - _M_fr_ptr = nullptr; - return *this; - } - - public: - // 17.12.3.2, export/import - constexpr void* address() const noexcept { return _M_fr_ptr; } - - constexpr static coroutine_handle from_address(void* __a) noexcept - { - coroutine_handle __self; - __self._M_fr_ptr = __a; - return __self; - } - - public: - // 17.12.3.3, observers - constexpr explicit operator bool() const noexcept - { - return bool(_M_fr_ptr); - } - - bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); } - - // 17.12.3.4, resumption - void operator()() const { resume(); } - - void resume() const { __builtin_coro_resume(_M_fr_ptr); } - - void destroy() const { __builtin_coro_destroy(_M_fr_ptr); } - - protected: - void* _M_fr_ptr; - }; - - // 17.12.3.6 Comparison operators - /// [coroutine.handle.compare] - constexpr bool operator==(coroutine_handle<> __a, - coroutine_handle<> __b) noexcept - { - return __a.address() == __b.address(); - } - -#if _COROUTINES_USE_SPACESHIP - constexpr strong_ordering - operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept - { return std::compare_three_way()(__a.address(), __b.address()); } -#else - // These are to enable operation with std=c++14,17. - constexpr bool operator!=(coroutine_handle<> __a, - coroutine_handle<> __b) noexcept - { - return !(__a == __b); - } - - constexpr bool operator<(coroutine_handle<> __a, - coroutine_handle<> __b) noexcept - { - return less()(__a.address(), __b.address()); - } - - constexpr bool operator>(coroutine_handle<> __a, - coroutine_handle<> __b) noexcept - { - return __b < __a; - } - - constexpr bool operator<=(coroutine_handle<> __a, - coroutine_handle<> __b) noexcept - { - return !(__a > __b); - } - - constexpr bool operator>=(coroutine_handle<> __a, - coroutine_handle<> __b) noexcept - { - return !(__a < __b); - } -#endif - - template - struct coroutine_handle : coroutine_handle<> - { - // 17.12.3.1, construct/reset - using coroutine_handle<>::coroutine_handle; - - static coroutine_handle from_promise(_Promise& p) - { - coroutine_handle __self; - __self._M_fr_ptr - = __builtin_coro_promise((char*) &p, __alignof(_Promise), true); - return __self; - } - - coroutine_handle& operator=(std::nullptr_t) noexcept - { - coroutine_handle<>::operator=(nullptr); - return *this; - } - - // 17.12.3.2, export/import - constexpr static coroutine_handle from_address(void* __a) - { - coroutine_handle __self; - __self._M_fr_ptr = __a; - return __self; - } - - // 17.12.3.5, promise accesss - _Promise& promise() const - { - void* __t - = __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false); - return *static_cast<_Promise*>(__t); - } - }; - - /// [coroutine.noop] - struct noop_coroutine_promise - { - }; - - void __dummy_resume_destroy() __attribute__((__weak__)); - void __dummy_resume_destroy() {} - - struct __noop_coro_frame - { - void (*__r)() = __dummy_resume_destroy; - void (*__d)() = __dummy_resume_destroy; - struct noop_coroutine_promise __p; - } __noop_coro_fr __attribute__((__weak__)); - - // 17.12.4.1 Class noop_coroutine_promise - /// [coroutine.promise.noop] - template <> - struct coroutine_handle : public coroutine_handle<> - { - using _Promise = noop_coroutine_promise; - - public: - // 17.12.4.2.1, observers - constexpr explicit operator bool() const noexcept { return true; } - - constexpr bool done() const noexcept { return false; } - - // 17.12.4.2.2, resumption - void operator()() const noexcept {} - - void resume() const noexcept {} - - void destroy() const noexcept {} - - // 17.12.4.2.3, promise access - _Promise& promise() const - { - return *static_cast<_Promise*>( - __builtin_coro_promise(this->_M_fr_ptr, __alignof(_Promise), false)); - } - - // 17.12.4.2.4, address - private: - friend coroutine_handle noop_coroutine() noexcept; - - coroutine_handle() noexcept { this->_M_fr_ptr = (void*) &__noop_coro_fr; } - }; - - using noop_coroutine_handle = coroutine_handle; - - inline noop_coroutine_handle noop_coroutine() noexcept - { - return noop_coroutine_handle(); - } - - // 17.12.5 Trivial awaitables - /// [coroutine.trivial.awaitables] - struct suspend_always - { - bool await_ready() { return false; } - - void await_suspend(coroutine_handle<>) {} - - void await_resume() {} - }; - - struct suspend_never - { - bool await_ready() { return true; } - - void await_suspend(coroutine_handle<>) {} - - void await_resume() {} - }; - - } // namespace __n4861 - -#else -#error "the coroutine header requires -fcoroutines" -#endif - - _GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++14 (we are allowing use from at least this) - -#endif // _GLIBCXX_COROUTINE diff --git a/resources/sources/avr-libstdcpp/include/csetjmp b/resources/sources/avr-libstdcpp/include/csetjmp deleted file mode 100644 index c3b77b023..000000000 --- a/resources/sources/avr-libstdcpp/include/csetjmp +++ /dev/null @@ -1,61 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file csetjmp - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c setjmp.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 20.4.6 C library -// - -#pragma GCC system_header - -#include -#include - -#ifndef _GLIBCXX_CSETJMP -#define _GLIBCXX_CSETJMP 1 - -// Get rid of those macros defined in in lieu of real functions. -#undef longjmp - -// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 -#ifndef setjmp -#define setjmp(env) setjmp (env) -#endif - -namespace std -{ - using ::jmp_buf; - using ::longjmp; -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/csignal b/resources/sources/avr-libstdcpp/include/csignal deleted file mode 100644 index 7a8841272..000000000 --- a/resources/sources/avr-libstdcpp/include/csignal +++ /dev/null @@ -1,57 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file csignal - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c signal.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 20.4.6 C library -// - -#pragma GCC system_header - -#include -#include - -#ifndef _GLIBCXX_CSIGNAL -#define _GLIBCXX_CSIGNAL 1 - -// Get rid of those macros defined in in lieu of real functions. -#undef raise - -namespace std -{ - using ::sig_atomic_t; - using ::signal; - using ::raise; -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/cstdalign b/resources/sources/avr-libstdcpp/include/cstdalign deleted file mode 100644 index b4c413a8a..000000000 --- a/resources/sources/avr-libstdcpp/include/cstdalign +++ /dev/null @@ -1,44 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2011-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cstdalign - * This is a Standard C++ Library header. - */ - -#pragma GCC system_header - -#ifndef _GLIBCXX_CSTDALIGN -#define _GLIBCXX_CSTDALIGN 1 - -#if __cplusplus < 201103L -# include -#else -# include -# if _GLIBCXX_HAVE_STDALIGN_H -# include -# endif -#endif - -#endif - diff --git a/resources/sources/avr-libstdcpp/include/cstdarg b/resources/sources/avr-libstdcpp/include/cstdarg deleted file mode 100644 index 749c85ec8..000000000 --- a/resources/sources/avr-libstdcpp/include/cstdarg +++ /dev/null @@ -1,58 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cstdarg - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c stdarg.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 20.4.6 C library -// - -#pragma GCC system_header - -#undef __need___va_list -#include -#include - -#ifndef _GLIBCXX_CSTDARG -#define _GLIBCXX_CSTDARG 1 - -// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 -#ifndef va_end -#define va_end(ap) va_end (ap) -#endif - -namespace std -{ - using ::va_list; -} // namespace std - -#endif diff --git a/resources/sources/avr-libstdcpp/include/cstdbool b/resources/sources/avr-libstdcpp/include/cstdbool deleted file mode 100644 index c76ecca3e..000000000 --- a/resources/sources/avr-libstdcpp/include/cstdbool +++ /dev/null @@ -1,44 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cstdbool - * This is a Standard C++ Library header. - */ - -#pragma GCC system_header - -#ifndef _GLIBCXX_CSTDBOOL -#define _GLIBCXX_CSTDBOOL 1 - -#if __cplusplus < 201103L -# include -#else -# include -# if _GLIBCXX_HAVE_STDBOOL_H -# include -# endif -#endif - -#endif - diff --git a/resources/sources/avr-libstdcpp/include/cstddef b/resources/sources/avr-libstdcpp/include/cstddef index ce9cd3e9d..bf7d1f85b 100644 --- a/resources/sources/avr-libstdcpp/include/cstddef +++ b/resources/sources/avr-libstdcpp/include/cstddef @@ -1,181 +1,7 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file cstddef - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c stddef.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 18.1 Types -// - -#ifndef _GLIBCXX_CSTDDEF -#define _GLIBCXX_CSTDDEF 1 - -#pragma GCC system_header - -#undef __need_wchar_t -#undef __need_ptrdiff_t -#undef __need_size_t -#undef __need_NULL -#undef __need_wint_t -#include +// Minimal for AVR +#ifndef _AVR_CSTDDEF +#define _AVR_CSTDDEF #include - -extern "C++" -{ -#if __cplusplus >= 201103L -namespace std -{ - // We handle size_t, ptrdiff_t, and nullptr_t in c++config.h. - using ::max_align_t; -} -#endif // C++11 - -#if __cplusplus >= 201703L -namespace std -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -#define __cpp_lib_byte 201603 - - /// std::byte - enum class byte : unsigned char {}; - - template struct __byte_operand { }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; -#ifdef _GLIBCXX_USE_WCHAR_T - template<> struct __byte_operand { using __type = byte; }; +namespace std { using ::size_t; using ::ptrdiff_t; } +using nullptr_t = decltype(nullptr); #endif -#ifdef _GLIBCXX_USE_CHAR8_T - template<> struct __byte_operand { using __type = byte; }; -#endif - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; - template<> struct __byte_operand { using __type = byte; }; -#if defined(__GLIBCXX_TYPE_INT_N_0) - template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_0> - { using __type = byte; }; - template<> struct __byte_operand - { using __type = byte; }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) - template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_1> - { using __type = byte; }; - template<> struct __byte_operand - { using __type = byte; }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) - template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_2> - { using __type = byte; }; - template<> struct __byte_operand - { using __type = byte; }; -#endif - template - struct __byte_operand - : __byte_operand<_IntegerType> { }; - template - struct __byte_operand - : __byte_operand<_IntegerType> { }; - template - struct __byte_operand - : __byte_operand<_IntegerType> { }; - - template - using __byte_op_t = typename __byte_operand<_IntegerType>::__type; - - template - constexpr __byte_op_t<_IntegerType> - operator<<(byte __b, _IntegerType __shift) noexcept - { return (byte)(unsigned char)((unsigned)__b << __shift); } - - template - constexpr __byte_op_t<_IntegerType> - operator>>(byte __b, _IntegerType __shift) noexcept - { return (byte)(unsigned char)((unsigned)__b >> __shift); } - - constexpr byte - operator|(byte __l, byte __r) noexcept - { return (byte)(unsigned char)((unsigned)__l | (unsigned)__r); } - - constexpr byte - operator&(byte __l, byte __r) noexcept - { return (byte)(unsigned char)((unsigned)__l & (unsigned)__r); } - - constexpr byte - operator^(byte __l, byte __r) noexcept - { return (byte)(unsigned char)((unsigned)__l ^ (unsigned)__r); } - - constexpr byte - operator~(byte __b) noexcept - { return (byte)(unsigned char)~(unsigned)__b; } - - template - constexpr __byte_op_t<_IntegerType>& - operator<<=(byte& __b, _IntegerType __shift) noexcept - { return __b = __b << __shift; } - - template - constexpr __byte_op_t<_IntegerType>& - operator>>=(byte& __b, _IntegerType __shift) noexcept - { return __b = __b >> __shift; } - - constexpr byte& - operator|=(byte& __l, byte __r) noexcept - { return __l = __l | __r; } - - constexpr byte& - operator&=(byte& __l, byte __r) noexcept - { return __l = __l & __r; } - - constexpr byte& - operator^=(byte& __l, byte __r) noexcept - { return __l = __l ^ __r; } - - template - constexpr _IntegerType - to_integer(__byte_op_t<_IntegerType> __b) noexcept - { return _IntegerType(__b); } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 -} // extern "C++" - -#endif // _GLIBCXX_CSTDDEF diff --git a/resources/sources/avr-libstdcpp/include/cstdint b/resources/sources/avr-libstdcpp/include/cstdint index 8e742fa7b..30e620590 100644 --- a/resources/sources/avr-libstdcpp/include/cstdint +++ b/resources/sources/avr-libstdcpp/include/cstdint @@ -1,91 +1,14 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cstdint - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_CSTDINT -#define _GLIBCXX_CSTDINT 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include - -#if _GLIBCXX_HAVE_STDINT_H -# include +// Minimal for AVR -- wraps into namespace std +#ifndef _AVR_CSTDINT +#define _AVR_CSTDINT +#include +namespace std { + using ::int8_t; using ::int16_t; using ::int32_t; using ::int64_t; + using ::uint8_t; using ::uint16_t; using ::uint32_t; using ::uint64_t; + using ::int_fast8_t; using ::int_fast16_t; using ::int_fast32_t; using ::int_fast64_t; + using ::uint_fast8_t; using ::uint_fast16_t; using ::uint_fast32_t; using ::uint_fast64_t; + using ::int_least8_t; using ::int_least16_t; using ::int_least32_t; using ::int_least64_t; + using ::uint_least8_t; using ::uint_least16_t; using ::uint_least32_t; using ::uint_least64_t; + using ::intmax_t; using ::uintmax_t; using ::intptr_t; using ::uintptr_t; +} #endif - -namespace std -{ -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - using ::int8_t; - using ::int16_t; - using ::int32_t; - using ::int64_t; - - using ::int_fast8_t; - using ::int_fast16_t; - using ::int_fast32_t; - using ::int_fast64_t; - - using ::int_least8_t; - using ::int_least16_t; - using ::int_least32_t; - using ::int_least64_t; - - using ::intmax_t; - using ::intptr_t; - - using ::uint8_t; - using ::uint16_t; - using ::uint32_t; - using ::uint64_t; - - using ::uint_fast8_t; - using ::uint_fast16_t; - using ::uint_fast32_t; - using ::uint_fast64_t; - - using ::uint_least8_t; - using ::uint_least16_t; - using ::uint_least32_t; - using ::uint_least64_t; - - using ::uintmax_t; - using ::uintptr_t; -#else // !_GLIBCXX_USE_C99_STDINT_TR1 - // Define the minimum needed for , etc. - using intmax_t = __INTMAX_TYPE__; - using uintmax_t = __UINTMAX_TYPE__; -#endif // _GLIBCXX_USE_C99_STDINT_TR1 -} // namespace std - -#endif // C++11 - -#endif // _GLIBCXX_CSTDINT diff --git a/resources/sources/avr-libstdcpp/include/cstdio b/resources/sources/avr-libstdcpp/include/cstdio index b1dad4e4b..4eccc4029 100644 --- a/resources/sources/avr-libstdcpp/include/cstdio +++ b/resources/sources/avr-libstdcpp/include/cstdio @@ -1,192 +1,6 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cstdio - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c stdio.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 27.8.2 C Library files -// - -#pragma GCC system_header - -#include +// Minimal for AVR +#ifndef _AVR_CSTDIO +#define _AVR_CSTDIO #include - -#ifndef _GLIBCXX_CSTDIO -#define _GLIBCXX_CSTDIO 1 - -#if __cplusplus <= 201103L && !defined(_GLIBCXX_HAVE_GETS) -extern "C" char* gets (char* __s) __attribute__((__deprecated__)); -#endif - -// Get rid of those macros defined in in lieu of real functions. -#undef clearerr -#undef fclose -#undef feof -#undef ferror -#undef fflush -#undef fgetc -#undef fgetpos -#undef fgets -#undef fopen -#undef fprintf -#undef fputc -#undef fputs -#undef fread -#undef freopen -#undef fscanf -#undef fseek -#undef fsetpos -#undef ftell -#undef fwrite -#undef getc -#undef getchar -#if __cplusplus <= 201103L -# undef gets -#endif -#undef perror -#undef printf -#undef putc -#undef putchar -#undef puts -#undef remove -#undef rename -#undef rewind -#undef scanf -#undef setbuf -#undef setvbuf -#undef sprintf -#undef sscanf -#undef tmpfile -#undef tmpnam -#undef ungetc -#undef vfprintf -#undef vprintf -#undef vsprintf - -namespace std -{ - using ::FILE; - using ::fpos_t; - - using ::clearerr; - using ::fclose; - using ::feof; - using ::ferror; - using ::fflush; - using ::fgetc; - using ::fgetpos; - using ::fgets; - using ::fopen; - using ::fprintf; - using ::fputc; - using ::fputs; - using ::fread; - using ::freopen; - using ::fscanf; - using ::fseek; - using ::fsetpos; - using ::ftell; - using ::fwrite; - using ::getc; - using ::getchar; -#if __cplusplus <= 201103L - // LWG 2249 - using ::gets; -#endif - using ::perror; - using ::printf; - using ::putc; - using ::putchar; - using ::puts; - using ::remove; - using ::rename; - using ::rewind; - using ::scanf; - using ::setbuf; - using ::setvbuf; - using ::sprintf; - using ::sscanf; - using ::tmpfile; -#if _GLIBCXX_USE_TMPNAM - using ::tmpnam; -#endif - using ::ungetc; - using ::vfprintf; - using ::vprintf; - using ::vsprintf; -} // namespace - -#if _GLIBCXX_USE_C99_STDIO - -#undef snprintf -#undef vfscanf -#undef vscanf -#undef vsnprintf -#undef vsscanf - -namespace __gnu_cxx -{ -#if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC - extern "C" int - (snprintf)(char * __restrict, std::size_t, const char * __restrict, ...) - throw (); - extern "C" int - (vfscanf)(FILE * __restrict, const char * __restrict, __gnuc_va_list); - extern "C" int (vscanf)(const char * __restrict, __gnuc_va_list); - extern "C" int - (vsnprintf)(char * __restrict, std::size_t, const char * __restrict, - __gnuc_va_list) throw (); - extern "C" int - (vsscanf)(const char * __restrict, const char * __restrict, __gnuc_va_list) - throw (); -#endif - -#if !_GLIBCXX_USE_C99_DYNAMIC - using ::snprintf; - using ::vfscanf; - using ::vscanf; - using ::vsnprintf; -#endif -} // namespace __gnu_cxx - -namespace std -{ - using ::__gnu_cxx::snprintf; - using ::__gnu_cxx::vfscanf; - using ::__gnu_cxx::vscanf; - using ::__gnu_cxx::vsnprintf; -} // namespace std - -#endif // _GLIBCXX_USE_C99_STDIO - +namespace std { using ::snprintf; using ::sprintf; } #endif diff --git a/resources/sources/avr-libstdcpp/include/cstdlib b/resources/sources/avr-libstdcpp/include/cstdlib index a349672f2..767b873d4 100644 --- a/resources/sources/avr-libstdcpp/include/cstdlib +++ b/resources/sources/avr-libstdcpp/include/cstdlib @@ -1,201 +1,6 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cstdlib - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c stdlib.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 20.4.6 C library -// - -#pragma GCC system_header - -#include - -#ifndef _GLIBCXX_CSTDLIB -#define _GLIBCXX_CSTDLIB 1 - -#if !_GLIBCXX_HOSTED -// The C standard does not require a freestanding implementation to -// provide . However, the C++ standard does still require -// -- but only the functionality mentioned in -// [lib.support.start.term]. - -#define EXIT_SUCCESS 0 -#define EXIT_FAILURE 1 - -namespace std -{ - extern "C" void abort(void) throw () _GLIBCXX_NORETURN; - extern "C" int atexit(void (*)(void)) throw (); - extern "C" void exit(int) throw () _GLIBCXX_NORETURN; -#if __cplusplus >= 201103L -# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT - extern "C" int at_quick_exit(void (*)(void)) throw (); -# endif -# ifdef _GLIBCXX_HAVE_QUICK_EXIT - extern "C" void quick_exit(int) throw() _GLIBCXX_NORETURN; -# endif -#endif -} // namespace std - -#else - -// Need to ensure this finds the C library's not a libstdc++ -// wrapper that might already be installed later in the include search path. -#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS -#include_next -#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS -#include - -// Get rid of those macros defined in in lieu of real functions. -#undef abort -#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) -# undef aligned_alloc -#endif -#undef atexit -#if __cplusplus >= 201103L -# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT -# undef at_quick_exit -# endif -#endif -#undef atof -#undef atoi -#undef atol -#undef bsearch -#undef calloc -#undef div -#undef exit -#undef free -#undef getenv -#undef labs -#undef ldiv -#undef malloc -#undef mblen -#undef mbstowcs -#undef mbtowc -#undef qsort -#if __cplusplus >= 201103L -# ifdef _GLIBCXX_HAVE_QUICK_EXIT -# undef quick_exit -# endif -#endif -#undef rand -#undef realloc -#undef srand -#undef strtod -#undef strtol -#undef strtoul -#undef system -#undef wcstombs -#undef wctomb - -extern "C++" -{ -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using ::div_t; - using ::ldiv_t; - - using ::abort; -#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) - using ::aligned_alloc; -#endif - using ::atexit; -#if __cplusplus >= 201103L -# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT - using ::at_quick_exit; -# endif -#endif - using ::atof; - using ::atoi; - using ::atol; - using ::bsearch; - using ::calloc; - using ::div; - using ::exit; - using ::free; - using ::getenv; - using ::labs; - using ::ldiv; - using ::malloc; -#ifdef _GLIBCXX_HAVE_MBSTATE_T - using ::mblen; - using ::mbstowcs; - using ::mbtowc; -#endif // _GLIBCXX_HAVE_MBSTATE_T - using ::qsort; -#if __cplusplus >= 201103L -# ifdef _GLIBCXX_HAVE_QUICK_EXIT - using ::quick_exit; -# endif -#endif - using ::rand; - using ::realloc; - using ::srand; - using ::strtod; - using ::strtol; - using ::strtoul; - using ::system; -#ifdef _GLIBCXX_USE_WCHAR_T - using ::wcstombs; - using ::wctomb; -#endif // _GLIBCXX_USE_WCHAR_T - -#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO - inline ldiv_t - div(long __i, long __j) { return ldiv(__i, __j); } -#endif - - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#if _GLIBCXX_USE_C99_STDLIB - -#undef _Exit -#undef llabs -#undef lldiv -#undef atoll -#undef strtoll -#undef strtoull -#undef strtof -#undef strtold - -#endif // _GLIBCXX_USE_C99_STDLIB - -} // extern "C++" - -#endif // !_GLIBCXX_HOSTED - +// Minimal for AVR +#ifndef _AVR_CSTDLIB +#define _AVR_CSTDLIB +#include +namespace std { using ::malloc; using ::free; using ::abort; using ::abs; using ::atoi; using ::atol; } #endif diff --git a/resources/sources/avr-libstdcpp/include/cstring b/resources/sources/avr-libstdcpp/include/cstring index 02199a8e9..36aa916bc 100644 --- a/resources/sources/avr-libstdcpp/include/cstring +++ b/resources/sources/avr-libstdcpp/include/cstring @@ -1,126 +1,9 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file cstring - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c string.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 20.4.6 C library -// - -#pragma GCC system_header - -#include +// Minimal for AVR +#ifndef _AVR_CSTRING +#define _AVR_CSTRING #include - -#ifndef _GLIBCXX_CSTRING -#define _GLIBCXX_CSTRING 1 - -// Get rid of those macros defined in in lieu of real functions. -#undef memchr -#undef memcmp -#undef memcpy -#undef memmove -#undef memset -#undef strcat -#undef strchr -#undef strcmp -#undef strcoll -#undef strcpy -#undef strcspn -#undef strerror -#undef strlen -#undef strncat -#undef strncmp -#undef strncpy -#undef strpbrk -#undef strrchr -#undef strspn -#undef strstr -#undef strtok -#undef strxfrm - -extern "C++" -{ -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using ::memchr; - using ::memcmp; - using ::memcpy; - using ::memmove; - using ::memset; - using ::strcat; - using ::strcmp; - using ::strcoll; - using ::strcpy; - using ::strcspn; - using ::strerror; - using ::strlen; - using ::strncat; - using ::strncmp; - using ::strncpy; - using ::strspn; - using ::strtok; - using ::strxfrm; - using ::strchr; - using ::strpbrk; - using ::strrchr; - using ::strstr; - -#ifndef __CORRECT_ISO_CPP_STRING_H_PROTO - inline void* - memchr(void* __s, int __c, size_t __n) - { return __builtin_memchr(__s, __c, __n); } - - inline char* - strchr(char* __s, int __n) - { return __builtin_strchr(__s, __n); } - - inline char* - strpbrk(char* __s1, const char* __s2) - { return __builtin_strpbrk(__s1, __s2); } - - inline char* - strrchr(char* __s, int __n) - { return __builtin_strrchr(__s, __n); } - - inline char* - strstr(char* __s1, const char* __s2) - { return __builtin_strstr(__s1, __s2); } -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -} // extern "C++" - +namespace std { + using ::memcpy; using ::memset; using ::memmove; using ::memcmp; + using ::strlen; using ::strcmp; using ::strncmp; using ::strcpy; using ::strncpy; +} #endif diff --git a/resources/sources/avr-libstdcpp/include/ctgmath b/resources/sources/avr-libstdcpp/include/ctgmath deleted file mode 100644 index 6ee36036e..000000000 --- a/resources/sources/avr-libstdcpp/include/ctgmath +++ /dev/null @@ -1,44 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/ctgmath - * This is a Standard C++ Library header. - */ - -#pragma GCC system_header - -#ifndef _GLIBCXX_CTGMATH -#define _GLIBCXX_CTGMATH 1 - -#if __cplusplus < 201103L -# include -#else -# include -extern "C++" { -# include -} -#endif - -#endif - diff --git a/resources/sources/avr-libstdcpp/include/ctime b/resources/sources/avr-libstdcpp/include/ctime deleted file mode 100644 index abac94027..000000000 --- a/resources/sources/avr-libstdcpp/include/ctime +++ /dev/null @@ -1,84 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/ctime - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c time.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 20.5 Date and time -// - -#pragma GCC system_header - -#include -#include - -#ifndef _GLIBCXX_CTIME -#define _GLIBCXX_CTIME 1 - -// Get rid of those macros defined in in lieu of real functions. -#undef clock -#undef difftime -#undef mktime -#undef time -#undef asctime -#undef ctime -#undef gmtime -#undef localtime -#undef strftime - -namespace std -{ - using ::clock_t; - using ::time_t; - using ::tm; - - using ::clock; - using ::difftime; - using ::mktime; - using ::time; - using ::asctime; - using ::ctime; - using ::gmtime; - using ::localtime; - using ::strftime; -} // namespace - -#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_TIMESPEC_GET) -#undef timespec_get -namespace std -{ - using ::timespec; - using ::timespec_get; -} // namespace std -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/cuchar b/resources/sources/avr-libstdcpp/include/cuchar deleted file mode 100644 index fc26715e2..000000000 --- a/resources/sources/avr-libstdcpp/include/cuchar +++ /dev/null @@ -1,77 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 2015-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cuchar - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c uchar.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882:2011 21.8 -// - -#ifndef _GLIBCXX_CUCHAR -#define _GLIBCXX_CUCHAR 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include - -#if _GLIBCXX_USE_C11_UCHAR_CXX11 - -#include - -// Get rid of those macros defined in in lieu of real functions. -#undef mbrtoc16 -#undef c16rtomb -#undef mbrtoc32 -#undef c32rtomb - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using ::mbrtoc16; - using ::c16rtomb; - using ::mbrtoc32; - using ::c32rtomb; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // _GLIBCXX_USE_C11_UCHAR_CXX11 - -#endif // C++11 - -#endif // _GLIBCXX_CUCHAR diff --git a/resources/sources/avr-libstdcpp/include/cwchar b/resources/sources/avr-libstdcpp/include/cwchar deleted file mode 100644 index 21857fa2d..000000000 --- a/resources/sources/avr-libstdcpp/include/cwchar +++ /dev/null @@ -1,306 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cwchar - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c wchar.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: 21.4 -// - -#pragma GCC system_header - -#include - -#if _GLIBCXX_HAVE_WCHAR_H -#include -#endif - -#ifndef _GLIBCXX_CWCHAR -#define _GLIBCXX_CWCHAR 1 - -// Need to do a bit of trickery here with mbstate_t as char_traits -// assumes it is in wchar.h, regardless of wchar_t specializations. -#ifndef _GLIBCXX_HAVE_MBSTATE_T -extern "C" -{ - typedef struct - { - int __fill[6]; - } mbstate_t; -} -#endif - -namespace std -{ - using ::mbstate_t; -} // namespace std - -// Get rid of those macros defined in in lieu of real functions. -#undef btowc -#undef fgetwc -#undef fgetws -#undef fputwc -#undef fputws -#undef fwide -#undef fwprintf -#undef fwscanf -#undef getwc -#undef getwchar -#undef mbrlen -#undef mbrtowc -#undef mbsinit -#undef mbsrtowcs -#undef putwc -#undef putwchar -#undef swprintf -#undef swscanf -#undef ungetwc -#undef vfwprintf -#if _GLIBCXX_HAVE_VFWSCANF -# undef vfwscanf -#endif -#undef vswprintf -#if _GLIBCXX_HAVE_VSWSCANF -# undef vswscanf -#endif -#undef vwprintf -#if _GLIBCXX_HAVE_VWSCANF -# undef vwscanf -#endif -#undef wcrtomb -#undef wcscat -#undef wcschr -#undef wcscmp -#undef wcscoll -#undef wcscpy -#undef wcscspn -#undef wcsftime -#undef wcslen -#undef wcsncat -#undef wcsncmp -#undef wcsncpy -#undef wcspbrk -#undef wcsrchr -#undef wcsrtombs -#undef wcsspn -#undef wcsstr -#undef wcstod -#if _GLIBCXX_HAVE_WCSTOF -# undef wcstof -#endif -#undef wcstok -#undef wcstol -#undef wcstoul -#undef wcsxfrm -#undef wctob -#undef wmemchr -#undef wmemcmp -#undef wmemcpy -#undef wmemmove -#undef wmemset -#undef wprintf -#undef wscanf - -#if _GLIBCXX_USE_WCHAR_T - -extern "C++" -{ -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using ::wint_t; - - using ::btowc; - using ::fgetwc; - using ::fgetws; - using ::fputwc; - using ::fputws; - using ::fwide; - using ::fwprintf; - using ::fwscanf; - using ::getwc; - using ::getwchar; - using ::mbrlen; - using ::mbrtowc; - using ::mbsinit; - using ::mbsrtowcs; - using ::putwc; - using ::putwchar; -#ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF - using ::swprintf; -#endif - using ::swscanf; - using ::ungetwc; - using ::vfwprintf; -#if _GLIBCXX_HAVE_VFWSCANF - using ::vfwscanf; -#endif -#ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF - using ::vswprintf; -#endif -#if _GLIBCXX_HAVE_VSWSCANF - using ::vswscanf; -#endif - using ::vwprintf; -#if _GLIBCXX_HAVE_VWSCANF - using ::vwscanf; -#endif - using ::wcrtomb; - using ::wcscat; - using ::wcscmp; - using ::wcscoll; - using ::wcscpy; - using ::wcscspn; - using ::wcsftime; - using ::wcslen; - using ::wcsncat; - using ::wcsncmp; - using ::wcsncpy; - using ::wcsrtombs; - using ::wcsspn; - using ::wcstod; -#if _GLIBCXX_HAVE_WCSTOF - using ::wcstof; -#endif - using ::wcstok; - using ::wcstol; - using ::wcstoul; - using ::wcsxfrm; - using ::wctob; - using ::wmemcmp; - using ::wmemcpy; - using ::wmemmove; - using ::wmemset; - using ::wprintf; - using ::wscanf; - using ::wcschr; - using ::wcspbrk; - using ::wcsrchr; - using ::wcsstr; - using ::wmemchr; - -#ifndef __CORRECT_ISO_CPP_WCHAR_H_PROTO - inline wchar_t* - wcschr(wchar_t* __p, wchar_t __c) - { return wcschr(const_cast(__p), __c); } - - inline wchar_t* - wcspbrk(wchar_t* __s1, const wchar_t* __s2) - { return wcspbrk(const_cast(__s1), __s2); } - - inline wchar_t* - wcsrchr(wchar_t* __p, wchar_t __c) - { return wcsrchr(const_cast(__p), __c); } - - inline wchar_t* - wcsstr(wchar_t* __s1, const wchar_t* __s2) - { return wcsstr(const_cast(__s1), __s2); } - - inline wchar_t* - wmemchr(wchar_t* __p, wchar_t __c, size_t __n) - { return wmemchr(const_cast(__p), __c, __n); } -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -} // extern "C++" - -#if _GLIBCXX_USE_C99_WCHAR - -#undef wcstold -#undef wcstoll -#undef wcstoull - -namespace __gnu_cxx -{ -#if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC - extern "C" long double - (wcstold)(const wchar_t * __restrict, wchar_t ** __restrict) throw (); -#endif -#if !_GLIBCXX_USE_C99_DYNAMIC - using ::wcstold; -#endif -#if _GLIBCXX_USE_C99_LONG_LONG_CHECK || _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC - extern "C" long long int - (wcstoll)(const wchar_t * __restrict, wchar_t ** __restrict, int) throw (); - extern "C" unsigned long long int - (wcstoull)(const wchar_t * __restrict, wchar_t ** __restrict, int) throw (); -#endif -#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC - using ::wcstoll; - using ::wcstoull; -#endif -} // namespace __gnu_cxx - -namespace std -{ - using ::__gnu_cxx::wcstold; - using ::__gnu_cxx::wcstoll; - using ::__gnu_cxx::wcstoull; -} // namespace - -#endif - -#endif //_GLIBCXX_USE_WCHAR_T - -#if __cplusplus >= 201103L - -#ifdef _GLIBCXX_USE_WCHAR_T - -namespace std -{ -#if _GLIBCXX_HAVE_WCSTOF - using std::wcstof; -#endif -#if _GLIBCXX_HAVE_VFWSCANF - using std::vfwscanf; -#endif -#if _GLIBCXX_HAVE_VSWSCANF - using std::vswscanf; -#endif -#if _GLIBCXX_HAVE_VWSCANF - using std::vwscanf; -#endif - -#if _GLIBCXX_USE_C99_WCHAR - using std::wcstold; - using std::wcstoll; - using std::wcstoull; -#endif -} // namespace - -#endif // _GLIBCXX_USE_WCHAR_T - -#endif // C++11 - -#endif diff --git a/resources/sources/avr-libstdcpp/include/cwctype b/resources/sources/avr-libstdcpp/include/cwctype deleted file mode 100644 index 5190ce81a..000000000 --- a/resources/sources/avr-libstdcpp/include/cwctype +++ /dev/null @@ -1,110 +0,0 @@ -// -*- C++ -*- forwarding header. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/cwctype - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - * - * This is the C++ version of the Standard C Library header @c wctype.h, - * and its contents are (mostly) the same as that header, but are all - * contained in the namespace @c std (except for names which are defined - * as macros in C). - */ - -// -// ISO C++ 14882: -// - -#pragma GCC system_header - -#include - -#if _GLIBCXX_HAVE_WCTYPE_H - -#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 10 -// Work around glibc BZ 9694 -#include -#endif - -#include -#endif // _GLIBCXX_HAVE_WCTYPE_H - -#ifndef _GLIBCXX_CWCTYPE -#define _GLIBCXX_CWCTYPE 1 - -// Get rid of those macros defined in in lieu of real functions. -#undef iswalnum -#undef iswalpha -#if _GLIBCXX_HAVE_ISWBLANK -# undef iswblank -#endif -#undef iswcntrl -#undef iswctype -#undef iswdigit -#undef iswgraph -#undef iswlower -#undef iswprint -#undef iswpunct -#undef iswspace -#undef iswupper -#undef iswxdigit -#undef towctrans -#undef towlower -#undef towupper -#undef wctrans -#undef wctype - -#if _GLIBCXX_USE_WCHAR_T - -namespace std -{ - using ::wctrans_t; - using ::wctype_t; - using ::wint_t; - - using ::iswalnum; - using ::iswalpha; -#if _GLIBCXX_HAVE_ISWBLANK - using ::iswblank; -#endif - using ::iswcntrl; - using ::iswctype; - using ::iswdigit; - using ::iswgraph; - using ::iswlower; - using ::iswprint; - using ::iswpunct; - using ::iswspace; - using ::iswupper; - using ::iswxdigit; - using ::towctrans; - using ::towlower; - using ::towupper; - using ::wctrans; - using ::wctype; -} // namespace - -#endif //_GLIBCXX_USE_WCHAR_T - -#endif // _GLIBCXX_CWCTYPE diff --git a/resources/sources/avr-libstdcpp/include/debug/assertions.h b/resources/sources/avr-libstdcpp/include/debug/assertions.h deleted file mode 100644 index fb52e4414..000000000 --- a/resources/sources/avr-libstdcpp/include/debug/assertions.h +++ /dev/null @@ -1,68 +0,0 @@ -// Debugging support implementation -*- C++ -*- - -// Copyright (C) 2003-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file debug/assertions.h - * This file is a GNU debug extension to the Standard C++ Library. - */ - -#ifndef _GLIBCXX_DEBUG_ASSERTIONS_H -#define _GLIBCXX_DEBUG_ASSERTIONS_H 1 - -#ifndef _GLIBCXX_DEBUG - -# define _GLIBCXX_DEBUG_ASSERT(_Condition) -# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) -# define _GLIBCXX_DEBUG_ONLY(_Statement) - -#endif - -#ifndef _GLIBCXX_ASSERTIONS -# define __glibcxx_requires_non_empty_range(_First,_Last) -# define __glibcxx_requires_nonempty() -# define __glibcxx_requires_subscript(_N) -#else - -// Verify that [_First, _Last) forms a non-empty iterator range. -# define __glibcxx_requires_non_empty_range(_First,_Last) \ - __glibcxx_assert(__builtin_expect(_First != _Last, true)) -# define __glibcxx_requires_subscript(_N) \ - __glibcxx_assert(__builtin_expect(_N < this->size(), true)) -// Verify that the container is nonempty -# define __glibcxx_requires_nonempty() \ - __glibcxx_assert(__builtin_expect(!this->empty(), true)) -#endif - -#ifdef _GLIBCXX_DEBUG -# define _GLIBCXX_DEBUG_ASSERT(_Condition) __glibcxx_assert(_Condition) - -# ifdef _GLIBCXX_DEBUG_PEDANTIC -# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) _GLIBCXX_DEBUG_ASSERT(_Condition) -# else -# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) -# endif - -# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement -#endif - -#endif // _GLIBCXX_DEBUG_ASSERTIONS diff --git a/resources/sources/avr-libstdcpp/include/debug/debug.h b/resources/sources/avr-libstdcpp/include/debug/debug.h deleted file mode 100644 index 5c858e1a8..000000000 --- a/resources/sources/avr-libstdcpp/include/debug/debug.h +++ /dev/null @@ -1,137 +0,0 @@ -// Debugging support implementation -*- C++ -*- - -// Copyright (C) 2003-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file debug/debug.h - * This file is a GNU debug extension to the Standard C++ Library. - */ - -#ifndef _GLIBCXX_DEBUG_MACRO_SWITCH_H -#define _GLIBCXX_DEBUG_MACRO_SWITCH_H 1 - -/** Macros and namespaces used by the implementation outside of debug - * wrappers to verify certain properties. The __glibcxx_requires_xxx - * macros are merely wrappers around the __glibcxx_check_xxx wrappers - * when we are compiling with debug mode, but disappear when we are - * in release mode so that there is no checking performed in, e.g., - * the standard library algorithms. -*/ - -#include - -// Debug mode namespaces. - -/** - * @namespace std::__debug - * @brief GNU debug code, replaces standard behavior with debug behavior. - */ -namespace std -{ - namespace __debug { } -} - -/** @namespace __gnu_debug - * @brief GNU debug classes for public use. -*/ -namespace __gnu_debug -{ - using namespace std::__debug; - - template - struct _Safe_iterator; -} - -#ifndef _GLIBCXX_DEBUG - -# define __glibcxx_requires_cond(_Cond,_Msg) -# define __glibcxx_requires_valid_range(_First,_Last) -# define __glibcxx_requires_can_increment(_First,_Size) -# define __glibcxx_requires_can_increment_range(_First1,_Last1,_First2) -# define __glibcxx_requires_can_decrement_range(_First1,_Last1,_First2) -# define __glibcxx_requires_sorted(_First,_Last) -# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) -# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) -# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) -# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) -# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) -# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) -# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) -# define __glibcxx_requires_heap(_First,_Last) -# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) -# define __glibcxx_requires_string(_String) -# define __glibcxx_requires_string_len(_String,_Len) -# define __glibcxx_requires_irreflexive(_First,_Last) -# define __glibcxx_requires_irreflexive2(_First,_Last) -# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) -# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) - -#else - -# include - -# define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg) -# define __glibcxx_requires_valid_range(_First,_Last) \ - __glibcxx_check_valid_range(_First,_Last) -# define __glibcxx_requires_can_increment(_First,_Size) \ - __glibcxx_check_can_increment(_First,_Size) -# define __glibcxx_requires_can_increment_range(_First1,_Last1,_First2) \ - __glibcxx_check_can_increment_range(_First1,_Last1,_First2) -# define __glibcxx_requires_can_decrement_range(_First1,_Last1,_First2) \ - __glibcxx_check_can_decrement_range(_First1,_Last1,_First2) -# define __glibcxx_requires_sorted(_First,_Last) \ - __glibcxx_check_sorted(_First,_Last) -# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) \ - __glibcxx_check_sorted_pred(_First,_Last,_Pred) -# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) \ - __glibcxx_check_sorted_set(_First1,_Last1,_First2) -# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ - __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) -# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) \ - __glibcxx_check_partitioned_lower(_First,_Last,_Value) -# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) \ - __glibcxx_check_partitioned_upper(_First,_Last,_Value) -# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ - __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) -# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ - __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) -# define __glibcxx_requires_heap(_First,_Last) \ - __glibcxx_check_heap(_First,_Last) -# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) \ - __glibcxx_check_heap_pred(_First,_Last,_Pred) -# define __glibcxx_requires_string(_String) __glibcxx_check_string(_String) -# define __glibcxx_requires_string_len(_String,_Len) \ - __glibcxx_check_string_len(_String,_Len) -# define __glibcxx_requires_irreflexive(_First,_Last) \ - __glibcxx_check_irreflexive(_First,_Last) -# define __glibcxx_requires_irreflexive2(_First,_Last) \ - __glibcxx_check_irreflexive2(_First,_Last) -# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) \ - __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) -# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) \ - __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) - -# include - -#endif - -#endif // _GLIBCXX_DEBUG_MACRO_SWITCH_H diff --git a/resources/sources/avr-libstdcpp/include/debug/formatter.h b/resources/sources/avr-libstdcpp/include/debug/formatter.h deleted file mode 100644 index bb9b3e565..000000000 --- a/resources/sources/avr-libstdcpp/include/debug/formatter.h +++ /dev/null @@ -1,593 +0,0 @@ -// Debug-mode error formatting implementation -*- C++ -*- - -// Copyright (C) 2003-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file debug/formatter.h - * This file is a GNU debug extension to the Standard C++ Library. - */ - -#ifndef _GLIBCXX_DEBUG_FORMATTER_H -#define _GLIBCXX_DEBUG_FORMATTER_H 1 - -#include - -#if __cpp_rtti -# include -# define _GLIBCXX_TYPEID(_Type) &typeid(_Type) -#else -namespace std -{ - class type_info; -} -# define _GLIBCXX_TYPEID(_Type) 0 -#endif - -#if __cplusplus >= 201103L -namespace __gnu_cxx -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -template - class __normal_iterator; - -_GLIBCXX_END_NAMESPACE_VERSION -} - -namespace std -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -template - class reverse_iterator; - -template - class move_iterator; - -_GLIBCXX_END_NAMESPACE_VERSION -} -#endif - -namespace __gnu_debug -{ - using std::type_info; - - template - bool __check_singular(const _Iterator&); - - class _Safe_sequence_base; - - template - class _Safe_iterator; - - template - class _Safe_local_iterator; - - template - class _Safe_sequence; - - enum _Debug_msg_id - { - // General checks - __msg_valid_range, - __msg_insert_singular, - __msg_insert_different, - __msg_erase_bad, - __msg_erase_different, - __msg_subscript_oob, - __msg_empty, - __msg_unpartitioned, - __msg_unpartitioned_pred, - __msg_unsorted, - __msg_unsorted_pred, - __msg_not_heap, - __msg_not_heap_pred, - // std::bitset checks - __msg_bad_bitset_write, - __msg_bad_bitset_read, - __msg_bad_bitset_flip, - // std::list checks - __msg_self_splice, - __msg_splice_alloc, - __msg_splice_bad, - __msg_splice_other, - __msg_splice_overlap, - // iterator checks - __msg_init_singular, - __msg_init_copy_singular, - __msg_init_const_singular, - __msg_copy_singular, - __msg_bad_deref, - __msg_bad_inc, - __msg_bad_dec, - __msg_iter_subscript_oob, - __msg_advance_oob, - __msg_retreat_oob, - __msg_iter_compare_bad, - __msg_compare_different, - __msg_iter_order_bad, - __msg_order_different, - __msg_distance_bad, - __msg_distance_different, - // istream_iterator - __msg_deref_istream, - __msg_inc_istream, - // ostream_iterator - __msg_output_ostream, - // istreambuf_iterator - __msg_deref_istreambuf, - __msg_inc_istreambuf, - // forward_list - __msg_insert_after_end, - __msg_erase_after_bad, - __msg_valid_range2, - // unordered container local iterators - __msg_local_iter_compare_bad, - __msg_non_empty_range, - // self move assign - __msg_self_move_assign, - // unordered container buckets - __msg_bucket_index_oob, - __msg_valid_load_factor, - // others - __msg_equal_allocs, - __msg_insert_range_from_self, - __msg_irreflexive_ordering - }; - - class _Error_formatter - { - // Tags denoting the type of parameter for construction - struct _Is_iterator { }; - struct _Is_iterator_value_type { }; - struct _Is_sequence { }; - struct _Is_instance { }; - - public: - /// Whether an iterator is constant, mutable, or unknown - enum _Constness - { - __unknown_constness, - __const_iterator, - __mutable_iterator, - __last_constness - }; - - // The state of the iterator (fine-grained), if we know it. - enum _Iterator_state - { - __unknown_state, - __singular, // singular, may still be attached to a sequence - __begin, // dereferenceable, and at the beginning - __middle, // dereferenceable, not at the beginning - __end, // past-the-end, may be at beginning if sequence empty - __before_begin, // before begin - __rbegin, // dereferenceable, and at the reverse-beginning - __rmiddle, // reverse-dereferenceable, not at the reverse-beginning - __rend, // reverse-past-the-end - __last_state - }; - - // A parameter that may be referenced by an error message - struct _Parameter - { - enum - { - __unused_param, - __iterator, - __sequence, - __integer, - __string, - __instance, - __iterator_value_type - } _M_kind; - - struct _Type - { - const char* _M_name; - const type_info* _M_type; - }; - - struct _Instance : _Type - { - const void* _M_address; - }; - - union - { - // When _M_kind == __iterator - struct : _Instance - { - _Constness _M_constness; - _Iterator_state _M_state; - const void* _M_sequence; - const type_info* _M_seq_type; - } _M_iterator; - - // When _M_kind == __sequence - _Instance _M_sequence; - - // When _M_kind == __integer - struct - { - const char* _M_name; - long _M_value; - } _M_integer; - - // When _M_kind == __string - struct - { - const char* _M_name; - const char* _M_value; - } _M_string; - - // When _M_kind == __instance - _Instance _M_instance; - - // When _M_kind == __iterator_value_type - _Type _M_iterator_value_type; - } _M_variant; - - _Parameter() : _M_kind(__unused_param), _M_variant() { } - - _Parameter(long __value, const char* __name) - : _M_kind(__integer), _M_variant() - { - _M_variant._M_integer._M_name = __name; - _M_variant._M_integer._M_value = __value; - } - - _Parameter(const char* __value, const char* __name) - : _M_kind(__string), _M_variant() - { - _M_variant._M_string._M_name = __name; - _M_variant._M_string._M_value = __value; - } - - template - _Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it, - const char* __name, _Is_iterator) - : _M_kind(__iterator), _M_variant() - { - _M_variant._M_iterator._M_name = __name; - _M_variant._M_iterator._M_address = std::__addressof(__it); - _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); - _M_variant._M_iterator._M_constness = - __it._S_constant() ? __const_iterator : __mutable_iterator; - _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); - _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); - - if (__it._M_singular()) - _M_variant._M_iterator._M_state = __singular; - else - { - if (__it._M_is_before_begin()) - _M_variant._M_iterator._M_state = __before_begin; - else if (__it._M_is_end()) - _M_variant._M_iterator._M_state = __end; - else if (__it._M_is_begin()) - _M_variant._M_iterator._M_state = __begin; - else - _M_variant._M_iterator._M_state = __middle; - } - } - - template - _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it, - const char* __name, _Is_iterator) - : _M_kind(__iterator), _M_variant() - { - _M_variant._M_iterator._M_name = __name; - _M_variant._M_iterator._M_address = std::__addressof(__it); - _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); - _M_variant._M_iterator._M_constness = - __it._S_constant() ? __const_iterator : __mutable_iterator; - _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); - _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); - - if (__it._M_singular()) - _M_variant._M_iterator._M_state = __singular; - else - { - if (__it._M_is_end()) - _M_variant._M_iterator._M_state = __end; - else if (__it._M_is_begin()) - _M_variant._M_iterator._M_state = __begin; - else - _M_variant._M_iterator._M_state = __middle; - } - } - - template - _Parameter(const _Type* const& __it, const char* __name, _Is_iterator) - : _M_kind(__iterator), _M_variant() - { - _M_variant._M_iterator._M_name = __name; - _M_variant._M_iterator._M_address = std::__addressof(__it); - _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); - _M_variant._M_iterator._M_constness = __const_iterator; - _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; - _M_variant._M_iterator._M_sequence = 0; - _M_variant._M_iterator._M_seq_type = 0; - } - - template - _Parameter(_Type* const& __it, const char* __name, _Is_iterator) - : _M_kind(__iterator), _M_variant() - { - _M_variant._M_iterator._M_name = __name; - _M_variant._M_iterator._M_address = std::__addressof(__it); - _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); - _M_variant._M_iterator._M_constness = __mutable_iterator; - _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; - _M_variant._M_iterator._M_sequence = 0; - _M_variant._M_iterator._M_seq_type = 0; - } - - template - _Parameter(_Iterator const& __it, const char* __name, _Is_iterator) - : _M_kind(__iterator), _M_variant() - { - _M_variant._M_iterator._M_name = __name; - _M_variant._M_iterator._M_address = std::__addressof(__it); - _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); - _M_variant._M_iterator._M_constness = __unknown_constness; - _M_variant._M_iterator._M_state = - __gnu_debug::__check_singular(__it) ? __singular : __unknown_state; - _M_variant._M_iterator._M_sequence = 0; - _M_variant._M_iterator._M_seq_type = 0; - } - -#if __cplusplus >= 201103L - // The following constructors are only defined in C++11 to take - // advantage of the constructor delegation feature. - template - _Parameter( - __gnu_cxx::__normal_iterator<_Iterator, _Container> const& __it, - const char* __name, _Is_iterator) - : _Parameter(__it.base(), __name, _Is_iterator{}) - { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } - - template - _Parameter(std::reverse_iterator<_Iterator> const& __it, - const char* __name, _Is_iterator) - : _Parameter(__it.base(), __name, _Is_iterator{}) - { - _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); - _M_variant._M_iterator._M_state - = _S_reverse_state(_M_variant._M_iterator._M_state); - } - - template - _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence, - _Category>> const& __it, - const char* __name, _Is_iterator) - : _Parameter(__it.base(), __name, _Is_iterator{}) - { - _M_variant._M_iterator._M_type - = _GLIBCXX_TYPEID(std::reverse_iterator<_Iterator>); - _M_variant._M_iterator._M_state - = _S_reverse_state(_M_variant._M_iterator._M_state); - } - - template - _Parameter(std::move_iterator<_Iterator> const& __it, - const char* __name, _Is_iterator) - : _Parameter(__it.base(), __name, _Is_iterator{}) - { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } - - template - _Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence, - _Category>> const& __it, - const char* __name, _Is_iterator) - : _Parameter(__it.base(), __name, _Is_iterator{}) - { - _M_variant._M_iterator._M_type - = _GLIBCXX_TYPEID(std::move_iterator<_Iterator>); - } - - private: - _Iterator_state - _S_reverse_state(_Iterator_state __state) - { - switch (__state) - { - case __begin: - return __rend; - case __middle: - return __rmiddle; - case __end: - return __rbegin; - default: - return __state; - } - } - - public: -#endif - - template - _Parameter(const _Safe_sequence<_Sequence>& __seq, - const char* __name, _Is_sequence) - : _M_kind(__sequence), _M_variant() - { - _M_variant._M_sequence._M_name = __name; - _M_variant._M_sequence._M_address = - static_cast(std::__addressof(__seq)); - _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); - } - - template - _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) - : _M_kind(__sequence), _M_variant() - { - _M_variant._M_sequence._M_name = __name; - _M_variant._M_sequence._M_address = std::__addressof(__seq); - _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); - } - - template - _Parameter(const _Iterator& __it, const char* __name, - _Is_iterator_value_type) - : _M_kind(__iterator_value_type), _M_variant() - { - _M_variant._M_iterator_value_type._M_name = __name; - _M_variant._M_iterator_value_type._M_type = - _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type); - } - - template - _Parameter(const _Type& __inst, const char* __name, _Is_instance) - : _M_kind(__instance), _M_variant() - { - _M_variant._M_instance._M_name = __name; - _M_variant._M_instance._M_address = &__inst; - _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type); - } - -#if !_GLIBCXX_INLINE_VERSION - void - _M_print_field(const _Error_formatter* __formatter, - const char* __name) const _GLIBCXX_DEPRECATED; - - void - _M_print_description(const _Error_formatter* __formatter) - const _GLIBCXX_DEPRECATED; -#endif - }; - - template - _Error_formatter& - _M_iterator(const _Iterator& __it, const char* __name = 0) - { - if (_M_num_parameters < std::size_t(__max_parameters)) - _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, - _Is_iterator()); - return *this; - } - - template - _Error_formatter& - _M_iterator_value_type(const _Iterator& __it, - const char* __name = 0) - { - if (_M_num_parameters < __max_parameters) - _M_parameters[_M_num_parameters++] = - _Parameter(__it, __name, _Is_iterator_value_type()); - return *this; - } - - _Error_formatter& - _M_integer(long __value, const char* __name = 0) - { - if (_M_num_parameters < __max_parameters) - _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); - return *this; - } - - _Error_formatter& - _M_string(const char* __value, const char* __name = 0) - { - if (_M_num_parameters < __max_parameters) - _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); - return *this; - } - - template - _Error_formatter& - _M_sequence(const _Sequence& __seq, const char* __name = 0) - { - if (_M_num_parameters < __max_parameters) - _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, - _Is_sequence()); - return *this; - } - - template - _Error_formatter& - _M_instance(const _Type& __inst, const char* __name = 0) - { - if (_M_num_parameters < __max_parameters) - _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name, - _Is_instance()); - return *this; - } - - _Error_formatter& - _M_message(const char* __text) - { _M_text = __text; return *this; } - - // Kept const qualifier for backward compatibility, to keep the same - // exported symbol. - _Error_formatter& - _M_message(_Debug_msg_id __id) const throw (); - - _GLIBCXX_NORETURN void - _M_error() const; - -#if !_GLIBCXX_INLINE_VERSION - template - void - _M_format_word(char*, int, const char*, _Tp) - const throw () _GLIBCXX_DEPRECATED; - - void - _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED; - - void - _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED; -#endif - - private: - _Error_formatter(const char* __file, unsigned int __line, - const char* __function) - : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) - , _M_function(__function) - { } - -#if !_GLIBCXX_INLINE_VERSION - void - _M_get_max_length() const throw () _GLIBCXX_DEPRECATED; -#endif - - enum { __max_parameters = 9 }; - - const char* _M_file; - unsigned int _M_line; - _Parameter _M_parameters[__max_parameters]; - unsigned int _M_num_parameters; - const char* _M_text; - const char* _M_function; - - public: - static _Error_formatter& - _S_at(const char* __file, unsigned int __line, const char* __function) - { - static _Error_formatter __formatter(__file, __line, __function); - return __formatter; - } - }; -} // namespace __gnu_debug - -#undef _GLIBCXX_TYPEID - -#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/functions.h b/resources/sources/avr-libstdcpp/include/debug/functions.h deleted file mode 100644 index aaccc8dfe..000000000 --- a/resources/sources/avr-libstdcpp/include/debug/functions.h +++ /dev/null @@ -1,470 +0,0 @@ -// Debugging support implementation -*- C++ -*- - -// Copyright (C) 2003-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file debug/functions.h - * This file is a GNU debug extension to the Standard C++ Library. - */ - -#ifndef _GLIBCXX_DEBUG_FUNCTIONS_H -#define _GLIBCXX_DEBUG_FUNCTIONS_H 1 - -#include // for less - -#if __cplusplus >= 201103L -# include // for __miter_base -# include // for is_lvalue_reference and conditional. -#endif - -#include -#include - -namespace __gnu_debug -{ - template - struct _Insert_range_from_self_is_safe - { enum { __value = 0 }; }; - - template - struct _Is_contiguous_sequence : std::__false_type { }; - - /* Checks that [first, last) is a valid range, and then returns - * __first. This routine is useful when we can't use a separate - * assertion statement because, e.g., we are in a constructor. - */ - template - inline _InputIterator - __check_valid_range(const _InputIterator& __first, - const _InputIterator& __last, - const char* __file, - unsigned int __line, - const char* __function) - { - __glibcxx_check_valid_range_at(__first, __last, - __file, __line, __function); - return __first; - } - - /* Handle the case where __other is a pointer to _Sequence::value_type. */ - template - inline bool - __foreign_iterator_aux4( - const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, - const typename _Sequence::value_type* __other) - { - typedef const typename _Sequence::value_type* _PointerType; - typedef std::less<_PointerType> _Less; -#if __cplusplus >= 201103L - constexpr _Less __l{}; -#else - const _Less __l = _Less(); -#endif - const _Sequence* __seq = __it._M_get_sequence(); - const _PointerType __begin = std::__addressof(*__seq->_M_base().begin()); - const _PointerType __end = std::__addressof(*(__seq->_M_base().end()-1)); - - // Check whether __other points within the contiguous storage. - return __l(__other, __begin) || __l(__end, __other); - } - - /* Fallback overload for when we can't tell, assume it is valid. */ - template - inline bool - __foreign_iterator_aux4( - const _Safe_iterator<_Iterator, _Sequence, _Category>&, ...) - { return true; } - - /* Handle sequences with contiguous storage */ - template - inline bool - __foreign_iterator_aux3( - const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, - const _InputIterator& __other, const _InputIterator& __other_end, - std::__true_type) - { - if (__other == __other_end) - return true; // inserting nothing is safe even if not foreign iters - if (__it._M_get_sequence()->empty()) - return true; // can't be self-inserting if self is empty - return __foreign_iterator_aux4(__it, std::__addressof(*__other)); - } - - /* Handle non-contiguous containers, assume it is valid. */ - template - inline bool - __foreign_iterator_aux3( - const _Safe_iterator<_Iterator, _Sequence, _Category>&, - const _InputIterator&, const _InputIterator&, - std::__false_type) - { return true; } - - /** Handle debug iterators from the same type of container. */ - template - inline bool - __foreign_iterator_aux2( - const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, - const _Safe_iterator<_OtherIterator, _Sequence, _Category>& __other, - const _Safe_iterator<_OtherIterator, _Sequence, _Category>&) - { return __it._M_get_sequence() != __other._M_get_sequence(); } - - /** Handle debug iterators from different types of container. */ - template - inline bool - __foreign_iterator_aux2( - const _Safe_iterator<_Iterator, _Sequence, _Category>&, - const _Safe_iterator<_OtherIterator, _OtherSequence, - _OtherCategory>&, - const _Safe_iterator<_OtherIterator, _OtherSequence, - _OtherCategory>&) - { return true; } - - /* Handle non-debug iterators. */ - template - inline bool - __foreign_iterator_aux2( - const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, - const _InputIterator& __other, - const _InputIterator& __other_end) - { -#if __cplusplus < 201103L - typedef _Is_contiguous_sequence<_Sequence> __tag; -#else - using __lvalref = std::is_lvalue_reference< - typename std::iterator_traits<_InputIterator>::reference>; - using __contiguous = _Is_contiguous_sequence<_Sequence>; - using __tag = typename std::conditional<__lvalref::value, __contiguous, - std::__false_type>::type; -#endif - return __foreign_iterator_aux3(__it, __other, __other_end, __tag()); - } - - /* Handle the case where we aren't really inserting a range after all */ - template - inline bool - __foreign_iterator_aux( - const _Safe_iterator<_Iterator, _Sequence, _Category>&, - _Integral, _Integral, std::__true_type) - { return true; } - - /* Handle all iterators. */ - template - inline bool - __foreign_iterator_aux( - const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, - _InputIterator __other, _InputIterator __other_end, - std::__false_type) - { - return _Insert_range_from_self_is_safe<_Sequence>::__value - || __foreign_iterator_aux2(__it, std::__miter_base(__other), - std::__miter_base(__other_end)); - } - - template - inline bool - __foreign_iterator( - const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, - _InputIterator __other, _InputIterator __other_end) - { - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - return __foreign_iterator_aux(__it, __other, __other_end, _Integral()); - } - - // Can't check if an input iterator sequence is sorted, because we - // can't step through the sequence. - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_aux(const _InputIterator&, const _InputIterator&, - std::input_iterator_tag) - { return true; } - - // Can verify if a forward iterator sequence is in fact sorted using - // std::__is_sorted - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, - std::forward_iterator_tag) - { - if (__first == __last) - return true; - - _ForwardIterator __next = __first; - for (++__next; __next != __last; __first = __next, (void)++__next) - if (*__next < *__first) - return false; - - return true; - } - - // Can't check if an input iterator sequence is sorted, because we can't step - // through the sequence. - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_aux(const _InputIterator&, const _InputIterator&, - _Predicate, std::input_iterator_tag) - { return true; } - - // Can verify if a forward iterator sequence is in fact sorted using - // std::__is_sorted - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, - _Predicate __pred, std::forward_iterator_tag) - { - if (__first == __last) - return true; - - _ForwardIterator __next = __first; - for (++__next; __next != __last; __first = __next, (void)++__next) - if (__pred(*__next, *__first)) - return false; - - return true; - } - - // Determine if a sequence is sorted. - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted(const _InputIterator& __first, const _InputIterator& __last) - { - return __check_sorted_aux(__first, __last, - std::__iterator_category(__first)); - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted(const _InputIterator& __first, const _InputIterator& __last, - _Predicate __pred) - { - return __check_sorted_aux(__first, __last, __pred, - std::__iterator_category(__first)); - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_set_aux(const _InputIterator& __first, - const _InputIterator& __last, - std::__true_type) - { return __check_sorted(__first, __last); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_set_aux(const _InputIterator&, - const _InputIterator&, - std::__false_type) - { return true; } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_set_aux(const _InputIterator& __first, - const _InputIterator& __last, - _Predicate __pred, std::__true_type) - { return __check_sorted(__first, __last, __pred); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_set_aux(const _InputIterator&, - const _InputIterator&, _Predicate, - std::__false_type) - { return true; } - - // ... special variant used in std::merge, std::includes, std::set_*. - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_set(const _InputIterator1& __first, - const _InputIterator1& __last, - const _InputIterator2&) - { - typedef typename std::iterator_traits<_InputIterator1>::value_type - _ValueType1; - typedef typename std::iterator_traits<_InputIterator2>::value_type - _ValueType2; - - typedef typename std::__are_same<_ValueType1, _ValueType2>::__type - _SameType; - return __check_sorted_set_aux(__first, __last, _SameType()); - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_sorted_set(const _InputIterator1& __first, - const _InputIterator1& __last, - const _InputIterator2&, _Predicate __pred) - { - typedef typename std::iterator_traits<_InputIterator1>::value_type - _ValueType1; - typedef typename std::iterator_traits<_InputIterator2>::value_type - _ValueType2; - - typedef typename std::__are_same<_ValueType1, _ValueType2>::__type - _SameType; - return __check_sorted_set_aux(__first, __last, __pred, _SameType()); - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 270. Binary search requirements overly strict - // Determine if a sequence is partitioned w.r.t. this element. - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_partitioned_lower(_ForwardIterator __first, - _ForwardIterator __last, const _Tp& __value) - { - while (__first != __last && *__first < __value) - ++__first; - if (__first != __last) - { - ++__first; - while (__first != __last && !(*__first < __value)) - ++__first; - } - return __first == __last; - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_partitioned_upper(_ForwardIterator __first, - _ForwardIterator __last, const _Tp& __value) - { - while (__first != __last && !(__value < *__first)) - ++__first; - if (__first != __last) - { - ++__first; - while (__first != __last && __value < *__first) - ++__first; - } - return __first == __last; - } - - // Determine if a sequence is partitioned w.r.t. this element. - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_partitioned_lower(_ForwardIterator __first, - _ForwardIterator __last, const _Tp& __value, - _Pred __pred) - { - while (__first != __last && bool(__pred(*__first, __value))) - ++__first; - if (__first != __last) - { - ++__first; - while (__first != __last && !bool(__pred(*__first, __value))) - ++__first; - } - return __first == __last; - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __check_partitioned_upper(_ForwardIterator __first, - _ForwardIterator __last, const _Tp& __value, - _Pred __pred) - { - while (__first != __last && !bool(__pred(__value, *__first))) - ++__first; - if (__first != __last) - { - ++__first; - while (__first != __last && bool(__pred(__value, *__first))) - ++__first; - } - return __first == __last; - } - -#if __cplusplus >= 201103L - struct _Irreflexive_checker - { - template - static typename std::iterator_traits<_It>::reference - __deref(); - - template() < __deref<_It>())> - _GLIBCXX20_CONSTEXPR - static bool - _S_is_valid(_It __it) - { return !(*__it < *__it); } - - // Fallback method if operator doesn't exist. - template - _GLIBCXX20_CONSTEXPR - static bool - _S_is_valid(_Args...) - { return true; } - - template()(__deref<_It>(), __deref<_It>()))> - _GLIBCXX20_CONSTEXPR - static bool - _S_is_valid_pred(_It __it, _Pred __pred) - { return !__pred(*__it, *__it); } - - // Fallback method if predicate can't be invoked. - template - _GLIBCXX20_CONSTEXPR - static bool - _S_is_valid_pred(_Args...) - { return true; } - }; - - template - _GLIBCXX20_CONSTEXPR - inline bool - __is_irreflexive(_Iterator __it) - { return _Irreflexive_checker::_S_is_valid(__it); } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __is_irreflexive_pred(_Iterator __it, _Pred __pred) - { return _Irreflexive_checker::_S_is_valid_pred(__it, __pred); } -#endif - -} // namespace __gnu_debug - -#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/helper_functions.h b/resources/sources/avr-libstdcpp/include/debug/helper_functions.h deleted file mode 100644 index 62d530925..000000000 --- a/resources/sources/avr-libstdcpp/include/debug/helper_functions.h +++ /dev/null @@ -1,315 +0,0 @@ -// Debugging support implementation -*- C++ -*- - -// Copyright (C) 2003-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file debug/helper_functions.h - * This file is a GNU debug extension to the Standard C++ Library. - */ - -#ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H -#define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1 - -#include // for __addressof -#include // for iterator_traits, - // categories and _Iter_base -#include // for __is_integer - -#include // for pair - -namespace __gnu_debug -{ - template - class _Safe_iterator; - -#if __cplusplus >= 201103L - template - class _Safe_local_iterator; -#endif - - /** The precision to which we can calculate the distance between - * two iterators. - */ - enum _Distance_precision - { - __dp_none, // Not even an iterator type - __dp_equality, //< Can compare iterator equality, only - __dp_sign, //< Can determine equality and ordering - __dp_sign_max_size, //< __dp_sign and gives max range size - __dp_exact //< Can determine distance precisely - }; - - template::__type> - struct _Distance_traits - { - private: - typedef - typename std::iterator_traits<_Iterator>::difference_type _ItDiffType; - - template::__type> - struct _DiffTraits - { typedef _DiffType __type; }; - - template - struct _DiffTraits<_DiffType, std::__true_type> - { typedef std::ptrdiff_t __type; }; - - typedef typename _DiffTraits<_ItDiffType>::__type _DiffType; - - public: - typedef std::pair<_DiffType, _Distance_precision> __type; - }; - - template - struct _Distance_traits<_Integral, std::__true_type> - { typedef std::pair __type; }; - - /** Determine the distance between two iterators with some known - * precision. - */ - template - _GLIBCXX_CONSTEXPR - inline typename _Distance_traits<_Iterator>::__type - __get_distance(_Iterator __lhs, _Iterator __rhs, - std::random_access_iterator_tag) - { return std::make_pair(__rhs - __lhs, __dp_exact); } - - template - _GLIBCXX14_CONSTEXPR - inline typename _Distance_traits<_Iterator>::__type - __get_distance(_Iterator __lhs, _Iterator __rhs, - std::input_iterator_tag) - { - if (__lhs == __rhs) - return std::make_pair(0, __dp_exact); - - return std::make_pair(1, __dp_equality); - } - - template - _GLIBCXX_CONSTEXPR - inline typename _Distance_traits<_Iterator>::__type - __get_distance(_Iterator __lhs, _Iterator __rhs) - { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } - - // An arbitrary iterator pointer is not singular. - inline bool - __check_singular_aux(const void*) { return false; } - - // We may have an iterator that derives from _Safe_iterator_base but isn't - // a _Safe_iterator. - template - inline bool - __check_singular(_Iterator const& __x) - { return __check_singular_aux(std::__addressof(__x)); } - - /** Non-NULL pointers are nonsingular. */ - template - inline bool - __check_singular(_Tp* const& __ptr) - { return __ptr == 0; } - - /** We say that integral types for a valid range, and defer to other - * routines to realize what to do with integral types instead of - * iterators. - */ - template - _GLIBCXX_CONSTEXPR - inline bool - __valid_range_aux(_Integral, _Integral, std::__true_type) - { return true; } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __valid_range_aux(_Integral, _Integral, - typename _Distance_traits<_Integral>::__type& __dist, - std::__true_type) - { - __dist = std::make_pair(0, __dp_none); - return true; - } - - template - _GLIBCXX_CONSTEXPR - inline bool - __valid_range_aux(_InputIterator __first, _InputIterator __last, - std::input_iterator_tag) - { - return __first == __last - || (!__check_singular(__first) && !__check_singular(__last)); - } - - template - _GLIBCXX_CONSTEXPR - inline bool - __valid_range_aux(_InputIterator __first, _InputIterator __last, - std::random_access_iterator_tag) - { - return - __valid_range_aux(__first, __last, std::input_iterator_tag()) - && __first <= __last; - } - - /** We have iterators, so figure out what kind of iterators they are - * to see if we can check the range ahead of time. - */ - template - _GLIBCXX_CONSTEXPR - inline bool - __valid_range_aux(_InputIterator __first, _InputIterator __last, - std::__false_type) - { - return __valid_range_aux(__first, __last, - std::__iterator_category(__first)); - } - - template - _GLIBCXX20_CONSTEXPR - inline bool - __valid_range_aux(_InputIterator __first, _InputIterator __last, - typename _Distance_traits<_InputIterator>::__type& __dist, - std::__false_type) - { - if (!__valid_range_aux(__first, __last, std::input_iterator_tag())) - return false; - - __dist = __get_distance(__first, __last); - switch (__dist.second) - { - case __dp_none: - break; - case __dp_equality: - if (__dist.first == 0) - return true; - break; - case __dp_sign: - case __dp_sign_max_size: - case __dp_exact: - return __dist.first >= 0; - } - - // Can't tell so assume it is fine. - return true; - } - - /** Don't know what these iterators are, or if they are even - * iterators (we may get an integral type for InputIterator), so - * see if they are integral and pass them on to the next phase - * otherwise. - */ - template - _GLIBCXX20_CONSTEXPR - inline bool - __valid_range(_InputIterator __first, _InputIterator __last, - typename _Distance_traits<_InputIterator>::__type& __dist) - { -#ifdef __cpp_lib_is_constant_evaluated - if (std::is_constant_evaluated()) - // Detected by the compiler directly. - return true; -#endif - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - return __valid_range_aux(__first, __last, __dist, _Integral()); - } - - template - bool - __valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&, - const _Safe_iterator<_Iterator, _Sequence, _Category>&, - typename _Distance_traits<_Iterator>::__type&); - -#if __cplusplus >= 201103L - template - bool - __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&, - const _Safe_local_iterator<_Iterator, _Sequence>&, - typename _Distance_traits<_Iterator>::__type&); -#endif - - template - _GLIBCXX14_CONSTEXPR - inline bool - __valid_range(_InputIterator __first, _InputIterator __last) - { -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - if (__builtin_is_constant_evaluated()) - // Detected by the compiler directly. - return true; -#endif - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - return __valid_range_aux(__first, __last, _Integral()); - } - - template - bool - __valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&, - const _Safe_iterator<_Iterator, _Sequence, _Category>&); - -#if __cplusplus >= 201103L - template - bool - __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&, - const _Safe_local_iterator<_Iterator, _Sequence>&); -#endif - - // Fallback method, always ok. - template - _GLIBCXX_CONSTEXPR - inline bool - __can_advance(_InputIterator, _Size) - { return true; } - - template - bool - __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>&, - _Size); - - /** Helper function to extract base iterator of random access safe iterator - * in order to reduce performance impact of debug mode. Limited to random - * access iterator because it is the only category for which it is possible - * to check for correct iterators order in the __valid_range function - * thanks to the < operator. - */ - template - _GLIBCXX_CONSTEXPR - inline _Iterator - __base(_Iterator __it) - { return __it; } - -#if __cplusplus < 201103L - template - struct _Unsafe_type - { typedef _Iterator _Type; }; -#endif - - /* Remove debug mode safe iterator layer, if any. */ - template - inline _Iterator - __unsafe(_Iterator __it) - { return __it; } -} - -#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/macros.h b/resources/sources/avr-libstdcpp/include/debug/macros.h deleted file mode 100644 index 73fb50d0c..000000000 --- a/resources/sources/avr-libstdcpp/include/debug/macros.h +++ /dev/null @@ -1,471 +0,0 @@ -// Debugging support implementation -*- C++ -*- - -// Copyright (C) 2003-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file debug/macros.h - * This file is a GNU debug extension to the Standard C++ Library. - */ - -#ifndef _GLIBCXX_DEBUG_MACROS_H -#define _GLIBCXX_DEBUG_MACROS_H 1 - -/** - * Macros used by the implementation to verify certain - * properties. These macros may only be used directly by the debug - * wrappers. Note that these are macros (instead of the more obviously - * @a correct choice of making them functions) because we need line and - * file information at the call site, to minimize the distance between - * the user error and where the error is reported. - * - */ -#if 0 /* defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED */ -# define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ - if (__builtin_is_constant_evaluated()) \ - /* FIXME: Compilation error here when !_Cond. */ \ - break; \ - if (! (_Cond)) \ - __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ - ._ErrMsg._M_error() -#else -# define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ - if (! (_Cond)) \ - __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ - ._ErrMsg._M_error() -#endif - -#define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func) \ - do \ - { \ - _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func); \ - } while (false) - -#define _GLIBCXX_DEBUG_VERIFY_AT(_Cond,_ErrMsg,_File,_Line) \ - _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,__PRETTY_FUNCTION__) - -#define _GLIBCXX_DEBUG_VERIFY(_Cond,_ErrMsg) \ - _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond, _ErrMsg, __FILE__, __LINE__, \ - __PRETTY_FUNCTION__) - -// Verify that [_First, _Last) forms a valid iterator range. -#define __glibcxx_check_valid_range(_First,_Last) \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last), \ - _M_message(__gnu_debug::__msg_valid_range) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)) - -#define __glibcxx_check_valid_range_at(_First,_Last,_File,_Line,_Func) \ -_GLIBCXX_DEBUG_VERIFY_AT_F(__gnu_debug::__valid_range(_First, _Last), \ - _M_message(__gnu_debug::__msg_valid_range) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last), \ - _File,_Line,_Func) - -#define __glibcxx_check_valid_range2(_First,_Last,_Dist) \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last, _Dist), \ - _M_message(__gnu_debug::__msg_valid_range) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)) - -#define __glibcxx_check_valid_constructor_range(_First,_Last) \ - __gnu_debug::__check_valid_range(_First, _Last, \ - __FILE__, __LINE__, __PRETTY_FUNCTION__) - -// Verify that [_First, _Last) forms a non-empty iterator range. -#define __glibcxx_check_non_empty_range(_First,_Last) \ -_GLIBCXX_DEBUG_VERIFY(_First != _Last, \ - _M_message(__gnu_debug::__msg_non_empty_range) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)) - -// Verify that [_First, _First + _Size) forms a valid range. -#define __glibcxx_check_can_increment(_First,_Size) \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__can_advance(_First, _Size), \ - _M_message(__gnu_debug::__msg_iter_subscript_oob) \ - ._M_iterator(_First, #_First) \ - ._M_integer(_Size, #_Size)) - -#define __glibcxx_check_can_increment_range(_First1,_Last1,_First2) \ - do \ - { \ - typename __gnu_debug::_Distance_traits<__decltype(_First1)>::__type __dist;\ - _GLIBCXX_DEBUG_VERIFY_COND_AT( \ - __gnu_debug::__valid_range(_First1, _Last1, __dist),\ - _M_message(__gnu_debug::__msg_valid_range) \ - ._M_iterator(_First1, #_First1) \ - ._M_iterator(_Last1, #_Last1), \ - __FILE__,__LINE__,__PRETTY_FUNCTION__); \ - _GLIBCXX_DEBUG_VERIFY_COND_AT( \ - __gnu_debug::__can_advance(_First2, __dist.first),\ - _M_message(__gnu_debug::__msg_iter_subscript_oob)\ - ._M_iterator(_First2, #_First2) \ - ._M_integer(__dist.first), \ - __FILE__,__LINE__,__PRETTY_FUNCTION__); \ - } while(false) - -#define __glibcxx_check_can_decrement_range(_First1,_Last1,_First2) \ - do \ - { \ - typename __gnu_debug::_Distance_traits<__decltype(_First1)>::__type __dist;\ - _GLIBCXX_DEBUG_VERIFY_COND_AT( \ - __gnu_debug::__valid_range(_First1, _Last1, __dist),\ - _M_message(__gnu_debug::__msg_valid_range) \ - ._M_iterator(_First1, #_First1) \ - ._M_iterator(_Last1, #_Last1), \ - __FILE__,__LINE__,__PRETTY_FUNCTION__); \ - _GLIBCXX_DEBUG_VERIFY_COND_AT( \ - __gnu_debug::__can_advance(_First2, -__dist.first),\ - _M_message(__gnu_debug::__msg_iter_subscript_oob)\ - ._M_iterator(_First2, #_First2) \ - ._M_integer(-__dist.first), \ - __FILE__,__LINE__,__PRETTY_FUNCTION__); \ - } while(false) - -/** Verify that we can insert into *this with the iterator _Position. - * Insertion into a container at a specific position requires that - * the iterator be nonsingular, either dereferenceable or past-the-end, - * and that it reference the sequence we are inserting into. Note that - * this macro is only valid when the container is a_Safe_sequence and - * the iterator is a _Safe_iterator. -*/ -#define __glibcxx_check_insert(_Position) \ -_GLIBCXX_DEBUG_VERIFY(!_Position._M_singular(), \ - _M_message(__gnu_debug::__msg_insert_singular) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_Position, #_Position)); \ -_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ - _M_message(__gnu_debug::__msg_insert_different) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_Position, #_Position)) - -/** Verify that we can insert into *this after the iterator _Position. - * Insertion into a container after a specific position requires that - * the iterator be nonsingular, either dereferenceable or before-begin, - * and that it reference the sequence we are inserting into. Note that - * this macro is only valid when the container is a_Safe_sequence and - * the iterator is a _Safe_iterator. -*/ -#define __glibcxx_check_insert_after(_Position) \ -__glibcxx_check_insert(_Position); \ -_GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(), \ - _M_message(__gnu_debug::__msg_insert_after_end) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_Position, #_Position)) - -/** Verify that we can insert the values in the iterator range - * [_First, _Last) into *this with the iterator _Position. Insertion - * into a container at a specific position requires that the iterator - * be nonsingular (i.e., either dereferenceable or past-the-end), - * that it reference the sequence we are inserting into, and that the - * iterator range [_First, _Last) is a valid (possibly empty) - * range which does not reference the sequence we are inserting into. - * Note that this macro is only valid when the container is a - * _Safe_sequence and the _Position iterator is a _Safe_iterator. -*/ -#define __glibcxx_check_insert_range(_Position,_First,_Last,_Dist) \ -__glibcxx_check_valid_range2(_First,_Last,_Dist); \ -__glibcxx_check_insert(_Position); \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\ - _M_message(__gnu_debug::__msg_insert_range_from_self)\ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last) \ - ._M_sequence(*this, "this")) - -/** Verify that we can insert the values in the iterator range - * [_First, _Last) into *this after the iterator _Position. Insertion - * into a container after a specific position requires that the iterator - * be nonsingular (i.e., either dereferenceable or past-the-end), - * that it reference the sequence we are inserting into, and that the - * iterator range [_First, _Last) is a valid (possibly empty) - * range which does not reference the sequence we are inserting into. - * Note that this macro is only valid when the container is a - * _Safe_sequence and the _Position iterator is a _Safe_iterator. -*/ -#define __glibcxx_check_insert_range_after(_Position,_First,_Last,_Dist)\ -__glibcxx_check_valid_range2(_First,_Last,_Dist); \ -__glibcxx_check_insert_after(_Position); \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\ - _M_message(__gnu_debug::__msg_insert_range_from_self)\ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last) \ - ._M_sequence(*this, "this")) - -/** Verify that we can erase the element referenced by the iterator - * _Position. We can erase the element if the _Position iterator is - * dereferenceable and references this sequence. -*/ -#define __glibcxx_check_erase(_Position) \ -_GLIBCXX_DEBUG_VERIFY(_Position._M_dereferenceable(), \ - _M_message(__gnu_debug::__msg_erase_bad) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_Position, #_Position)); \ -_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ - _M_message(__gnu_debug::__msg_erase_different) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_Position, #_Position)) - -/** Verify that we can erase the element after the iterator - * _Position. We can erase the element if the _Position iterator is - * before a dereferenceable one and references this sequence. -*/ -#define __glibcxx_check_erase_after(_Position) \ -_GLIBCXX_DEBUG_VERIFY(_Position._M_before_dereferenceable(), \ - _M_message(__gnu_debug::__msg_erase_after_bad) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_Position, #_Position)); \ -_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ - _M_message(__gnu_debug::__msg_erase_different) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_Position, #_Position)) - -/** Verify that we can erase the elements in the iterator range - * [_First, _Last). We can erase the elements if [_First, _Last) is a - * valid iterator range within this sequence. -*/ -#define __glibcxx_check_erase_range(_First,_Last) \ -__glibcxx_check_valid_range(_First,_Last); \ -_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \ - _M_message(__gnu_debug::__msg_erase_different) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)) - -/** Verify that we can erase the elements in the iterator range - * (_First, _Last). We can erase the elements if (_First, _Last) is a - * valid iterator range within this sequence. -*/ -#define __glibcxx_check_erase_range_after(_First,_Last) \ -_GLIBCXX_DEBUG_VERIFY(_First._M_can_compare(_Last), \ - _M_message(__gnu_debug::__msg_erase_different) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)); \ -_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \ - _M_message(__gnu_debug::__msg_erase_different) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_First, #_First)); \ -_GLIBCXX_DEBUG_VERIFY(_First != _Last, \ - _M_message(__gnu_debug::__msg_valid_range2) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)); \ -_GLIBCXX_DEBUG_VERIFY(_First._M_incrementable(), \ - _M_message(__gnu_debug::__msg_valid_range2) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)); \ -_GLIBCXX_DEBUG_VERIFY(!_Last._M_is_before_begin(), \ - _M_message(__gnu_debug::__msg_valid_range2) \ - ._M_sequence(*this, "this") \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)) \ - -// Verify that the subscript _N is less than the container's size. -#define __glibcxx_check_subscript(_N) \ -_GLIBCXX_DEBUG_VERIFY(_N < this->size(), \ - _M_message(__gnu_debug::__msg_subscript_oob) \ - ._M_sequence(*this, "this") \ - ._M_integer(_N, #_N) \ - ._M_integer(this->size(), "size")) - -// Verify that the bucket _N is less than the container's buckets count. -#define __glibcxx_check_bucket_index(_N) \ -_GLIBCXX_DEBUG_VERIFY(_N < this->bucket_count(), \ - _M_message(__gnu_debug::__msg_bucket_index_oob) \ - ._M_sequence(*this, "this") \ - ._M_integer(_N, #_N) \ - ._M_integer(this->bucket_count(), "size")) - -// Verify that the container is nonempty -#define __glibcxx_check_nonempty() \ -_GLIBCXX_DEBUG_VERIFY(! this->empty(), \ - _M_message(__gnu_debug::__msg_empty) \ - ._M_sequence(*this, "this")) - -// Verify that a predicate is irreflexive -#define __glibcxx_check_irreflexive(_First,_Last) \ - _GLIBCXX_DEBUG_VERIFY(_First == _Last || !(*_First < *_First), \ - _M_message(__gnu_debug::__msg_irreflexive_ordering) \ - ._M_iterator_value_type(_First, "< operator type")) - -#if __cplusplus >= 201103L -# define __glibcxx_check_irreflexive2(_First,_Last) \ - _GLIBCXX_DEBUG_VERIFY(_First == _Last \ - || __gnu_debug::__is_irreflexive(_First), \ - _M_message(__gnu_debug::__msg_irreflexive_ordering) \ - ._M_iterator_value_type(_First, "< operator type")) -#else -# define __glibcxx_check_irreflexive2(_First,_Last) -#endif - -#define __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) \ - _GLIBCXX_DEBUG_VERIFY(_First == _Last || !_Pred(*_First, *_First), \ - _M_message(__gnu_debug::__msg_irreflexive_ordering) \ - ._M_instance(_Pred, "functor") \ - ._M_iterator_value_type(_First, "ordered type")) - -#if __cplusplus >= 201103L -# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) \ - _GLIBCXX_DEBUG_VERIFY(_First == _Last \ - ||__gnu_debug::__is_irreflexive_pred(_First, _Pred), \ - _M_message(__gnu_debug::__msg_irreflexive_ordering) \ - ._M_instance(_Pred, "functor") \ - ._M_iterator_value_type(_First, "ordered type")) -#else -# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) -#endif - -// Verify that the iterator range [_First, _Last) is sorted -#define __glibcxx_check_sorted(_First,_Last) \ -__glibcxx_check_valid_range(_First,_Last); \ -__glibcxx_check_irreflexive(_First,_Last); \ - _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \ - __gnu_debug::__base(_First), \ - __gnu_debug::__base(_Last)), \ - _M_message(__gnu_debug::__msg_unsorted) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)) - -/** Verify that the iterator range [_First, _Last) is sorted by the - predicate _Pred. */ -#define __glibcxx_check_sorted_pred(_First,_Last,_Pred) \ -__glibcxx_check_valid_range(_First,_Last); \ -__glibcxx_check_irreflexive_pred(_First,_Last,_Pred); \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \ - __gnu_debug::__base(_First), \ - __gnu_debug::__base(_Last), _Pred), \ - _M_message(__gnu_debug::__msg_unsorted_pred) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last) \ - ._M_string(#_Pred)) - -// Special variant for std::merge, std::includes, std::set_* -#define __glibcxx_check_sorted_set(_First1,_Last1,_First2) \ -__glibcxx_check_valid_range(_First1,_Last1); \ -_GLIBCXX_DEBUG_VERIFY( \ - __gnu_debug::__check_sorted_set(__gnu_debug::__base(_First1), \ - __gnu_debug::__base(_Last1), _First2),\ - _M_message(__gnu_debug::__msg_unsorted) \ - ._M_iterator(_First1, #_First1) \ - ._M_iterator(_Last1, #_Last1)) - -// Likewise with a _Pred. -#define __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ -__glibcxx_check_valid_range(_First1,_Last1); \ -_GLIBCXX_DEBUG_VERIFY( \ - __gnu_debug::__check_sorted_set(__gnu_debug::__base(_First1), \ - __gnu_debug::__base(_Last1), \ - _First2, _Pred), \ - _M_message(__gnu_debug::__msg_unsorted_pred) \ - ._M_iterator(_First1, #_First1) \ - ._M_iterator(_Last1, #_Last1) \ - ._M_string(#_Pred)) - -/** Verify that the iterator range [_First, _Last) is partitioned - w.r.t. the value _Value. */ -#define __glibcxx_check_partitioned_lower(_First,_Last,_Value) \ -__glibcxx_check_valid_range(_First,_Last); \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_lower( \ - __gnu_debug::__base(_First), \ - __gnu_debug::__base(_Last), _Value), \ - _M_message(__gnu_debug::__msg_unpartitioned) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last) \ - ._M_string(#_Value)) - -#define __glibcxx_check_partitioned_upper(_First,_Last,_Value) \ -__glibcxx_check_valid_range(_First,_Last); \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper( \ - __gnu_debug::__base(_First), \ - __gnu_debug::__base(_Last), _Value), \ - _M_message(__gnu_debug::__msg_unpartitioned) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last) \ - ._M_string(#_Value)) - -/** Verify that the iterator range [_First, _Last) is partitioned - w.r.t. the value _Value and predicate _Pred. */ -#define __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ -__glibcxx_check_valid_range(_First,_Last); \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_lower( \ - __gnu_debug::__base(_First), \ - __gnu_debug::__base(_Last), _Value, _Pred), \ - _M_message(__gnu_debug::__msg_unpartitioned_pred) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last) \ - ._M_string(#_Pred) \ - ._M_string(#_Value)) - -/** Verify that the iterator range [_First, _Last) is partitioned - w.r.t. the value _Value and predicate _Pred. */ -#define __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ -__glibcxx_check_valid_range(_First,_Last); \ -_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper( \ - __gnu_debug::__base(_First), \ - __gnu_debug::__base(_Last), _Value, _Pred), \ - _M_message(__gnu_debug::__msg_unpartitioned_pred) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last) \ - ._M_string(#_Pred) \ - ._M_string(#_Value)) - -// Verify that the iterator range [_First, _Last) is a heap -#define __glibcxx_check_heap(_First,_Last) \ - _GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \ - __gnu_debug::__base(_Last)), \ - _M_message(__gnu_debug::__msg_not_heap) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last)) - -/** Verify that the iterator range [_First, _Last) is a heap - w.r.t. the predicate _Pred. */ -#define __glibcxx_check_heap_pred(_First,_Last,_Pred) \ - _GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \ - __gnu_debug::__base(_Last), \ - _Pred), \ - _M_message(__gnu_debug::__msg_not_heap_pred) \ - ._M_iterator(_First, #_First) \ - ._M_iterator(_Last, #_Last) \ - ._M_string(#_Pred)) - -// Verify that the container is not self move assigned -#define __glibcxx_check_self_move_assign(_Other) \ -_GLIBCXX_DEBUG_VERIFY(this != &_Other, \ - _M_message(__gnu_debug::__msg_self_move_assign) \ - ._M_sequence(*this, "this")) - -// Verify that load factor is positive -#define __glibcxx_check_max_load_factor(_F) \ -_GLIBCXX_DEBUG_VERIFY(_F > 0.0f, \ - _M_message(__gnu_debug::__msg_valid_load_factor) \ - ._M_sequence(*this, "this")) - -#define __glibcxx_check_equal_allocs(_This, _Other) \ -_GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \ - _M_message(__gnu_debug::__msg_equal_allocs) \ - ._M_sequence(_This, "this")) - -#define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_PEDASSERT(_String != 0) -#define __glibcxx_check_string_len(_String,_Len) \ - _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0) - -#endif diff --git a/resources/sources/avr-libstdcpp/include/decimal/decimal b/resources/sources/avr-libstdcpp/include/decimal/decimal deleted file mode 100644 index 8863d7e2a..000000000 --- a/resources/sources/avr-libstdcpp/include/decimal/decimal +++ /dev/null @@ -1,494 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2009-2020 Free Software Foundation, Inc. -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file decimal/decimal - * This is a Standard C++ Library header. - */ - -// ISO/IEC TR 24733 -// Written by Janis Johnson - -#ifndef _GLIBCXX_DECIMAL -#define _GLIBCXX_DECIMAL 1 - -#pragma GCC system_header - -#include - -#ifndef _GLIBCXX_USE_DECIMAL_FLOAT -#error This file requires compiler and library support for ISO/IEC TR 24733 \ -that is currently not available. -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup decimal Decimal Floating-Point Arithmetic - * @ingroup numerics - * - * Classes and functions for decimal floating-point arithmetic. - * @{ - */ - - /** @namespace std::decimal - * @brief ISO/IEC TR 24733 Decimal floating-point arithmetic. - */ -namespace decimal -{ - class decimal32; - class decimal64; - class decimal128; - - // 3.2.5 Initialization from coefficient and exponent. - static decimal32 make_decimal32(long long __coeff, int __exp); - static decimal32 make_decimal32(unsigned long long __coeff, int __exp); - static decimal64 make_decimal64(long long __coeff, int __exp); - static decimal64 make_decimal64(unsigned long long __coeff, int __exp); - static decimal128 make_decimal128(long long __coeff, int __exp); - static decimal128 make_decimal128(unsigned long long __coeff, int __exp); - - /// Non-conforming extension: Conversion to integral type. - long long decimal32_to_long_long(decimal32 __d); - long long decimal64_to_long_long(decimal64 __d); - long long decimal128_to_long_long(decimal128 __d); - long long decimal_to_long_long(decimal32 __d); - long long decimal_to_long_long(decimal64 __d); - long long decimal_to_long_long(decimal128 __d); - - // 3.2.6 Conversion to generic floating-point type. - float decimal32_to_float(decimal32 __d); - float decimal64_to_float(decimal64 __d); - float decimal128_to_float(decimal128 __d); - float decimal_to_float(decimal32 __d); - float decimal_to_float(decimal64 __d); - float decimal_to_float(decimal128 __d); - - double decimal32_to_double(decimal32 __d); - double decimal64_to_double(decimal64 __d); - double decimal128_to_double(decimal128 __d); - double decimal_to_double(decimal32 __d); - double decimal_to_double(decimal64 __d); - double decimal_to_double(decimal128 __d); - - long double decimal32_to_long_double(decimal32 __d); - long double decimal64_to_long_double(decimal64 __d); - long double decimal128_to_long_double(decimal128 __d); - long double decimal_to_long_double(decimal32 __d); - long double decimal_to_long_double(decimal64 __d); - long double decimal_to_long_double(decimal128 __d); - - // 3.2.7 Unary arithmetic operators. - decimal32 operator+(decimal32 __rhs); - decimal64 operator+(decimal64 __rhs); - decimal128 operator+(decimal128 __rhs); - decimal32 operator-(decimal32 __rhs); - decimal64 operator-(decimal64 __rhs); - decimal128 operator-(decimal128 __rhs); - - // 3.2.8 Binary arithmetic operators. -#define _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(_Op, _T1, _T2, _T3) \ - _T1 operator _Op(_T2 __lhs, _T3 __rhs); -#define _DECLARE_DECIMAL_BINARY_OP_WITH_INT(_Op, _Tp) \ - _Tp operator _Op(_Tp __lhs, int __rhs); \ - _Tp operator _Op(_Tp __lhs, unsigned int __rhs); \ - _Tp operator _Op(_Tp __lhs, long __rhs); \ - _Tp operator _Op(_Tp __lhs, unsigned long __rhs); \ - _Tp operator _Op(_Tp __lhs, long long __rhs); \ - _Tp operator _Op(_Tp __lhs, unsigned long long __rhs); \ - _Tp operator _Op(int __lhs, _Tp __rhs); \ - _Tp operator _Op(unsigned int __lhs, _Tp __rhs); \ - _Tp operator _Op(long __lhs, _Tp __rhs); \ - _Tp operator _Op(unsigned long __lhs, _Tp __rhs); \ - _Tp operator _Op(long long __lhs, _Tp __rhs); \ - _Tp operator _Op(unsigned long long __lhs, _Tp __rhs); - - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal32, decimal32, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal32, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal32, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal64, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal128) - - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal32, decimal32, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal32, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal32, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal64, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal128) - - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal32, decimal32, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal32, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal32, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal64, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal128) - - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal32, decimal32, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal32, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal32, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal64, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal32) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal64) - _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal128) - _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal128) - -#undef _DECLARE_DECIMAL_BINARY_OP_WITH_DEC -#undef _DECLARE_DECIMAL_BINARY_OP_WITH_INT - - // 3.2.9 Comparison operators. -#define _DECLARE_DECIMAL_COMPARISON(_Op, _Tp) \ - bool operator _Op(_Tp __lhs, decimal32 __rhs); \ - bool operator _Op(_Tp __lhs, decimal64 __rhs); \ - bool operator _Op(_Tp __lhs, decimal128 __rhs); \ - bool operator _Op(_Tp __lhs, int __rhs); \ - bool operator _Op(_Tp __lhs, unsigned int __rhs); \ - bool operator _Op(_Tp __lhs, long __rhs); \ - bool operator _Op(_Tp __lhs, unsigned long __rhs); \ - bool operator _Op(_Tp __lhs, long long __rhs); \ - bool operator _Op(_Tp __lhs, unsigned long long __rhs); \ - bool operator _Op(int __lhs, _Tp __rhs); \ - bool operator _Op(unsigned int __lhs, _Tp __rhs); \ - bool operator _Op(long __lhs, _Tp __rhs); \ - bool operator _Op(unsigned long __lhs, _Tp __rhs); \ - bool operator _Op(long long __lhs, _Tp __rhs); \ - bool operator _Op(unsigned long long __lhs, _Tp __rhs); - - _DECLARE_DECIMAL_COMPARISON(==, decimal32) - _DECLARE_DECIMAL_COMPARISON(==, decimal64) - _DECLARE_DECIMAL_COMPARISON(==, decimal128) - - _DECLARE_DECIMAL_COMPARISON(!=, decimal32) - _DECLARE_DECIMAL_COMPARISON(!=, decimal64) - _DECLARE_DECIMAL_COMPARISON(!=, decimal128) - - _DECLARE_DECIMAL_COMPARISON(<, decimal32) - _DECLARE_DECIMAL_COMPARISON(<, decimal64) - _DECLARE_DECIMAL_COMPARISON(<, decimal128) - - _DECLARE_DECIMAL_COMPARISON(>=, decimal32) - _DECLARE_DECIMAL_COMPARISON(>=, decimal64) - _DECLARE_DECIMAL_COMPARISON(>=, decimal128) - - _DECLARE_DECIMAL_COMPARISON(>, decimal32) - _DECLARE_DECIMAL_COMPARISON(>, decimal64) - _DECLARE_DECIMAL_COMPARISON(>, decimal128) - - _DECLARE_DECIMAL_COMPARISON(>=, decimal32) - _DECLARE_DECIMAL_COMPARISON(>=, decimal64) - _DECLARE_DECIMAL_COMPARISON(>=, decimal128) - -#undef _DECLARE_DECIMAL_COMPARISON - - /// 3.2.2 Class decimal32. - class decimal32 - { - public: - typedef float __decfloat32 __attribute__((mode(SD))); - - // 3.2.2.2 Construct/copy/destroy. - decimal32() : __val(0.e-101DF) {} - - // 3.2.2.3 Conversion from floating-point type. - explicit decimal32(decimal64 __d64); - explicit decimal32(decimal128 __d128); - explicit decimal32(float __r) : __val(__r) {} - explicit decimal32(double __r) : __val(__r) {} - explicit decimal32(long double __r) : __val(__r) {} - - // 3.2.2.4 Conversion from integral type. - decimal32(int __z) : __val(__z) {} - decimal32(unsigned int __z) : __val(__z) {} - decimal32(long __z) : __val(__z) {} - decimal32(unsigned long __z) : __val(__z) {} - decimal32(long long __z) : __val(__z) {} - decimal32(unsigned long long __z) : __val(__z) {} - - /// Conforming extension: Conversion from scalar decimal type. - decimal32(__decfloat32 __z) : __val(__z) {} - -#if __cplusplus >= 201103L - // 3.2.2.5 Conversion to integral type. - // Note: explicit per n3407. - explicit operator long long() const { return (long long)__val; } -#endif - - // 3.2.2.6 Increment and decrement operators. - decimal32& operator++() - { - __val += 1; - return *this; - } - - decimal32 operator++(int) - { - decimal32 __tmp = *this; - __val += 1; - return __tmp; - } - - decimal32& operator--() - { - __val -= 1; - return *this; - } - - decimal32 operator--(int) - { - decimal32 __tmp = *this; - __val -= 1; - return __tmp; - } - - // 3.2.2.7 Compound assignment. -#define _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(_Op) \ - decimal32& operator _Op(decimal32 __rhs); \ - decimal32& operator _Op(decimal64 __rhs); \ - decimal32& operator _Op(decimal128 __rhs); \ - decimal32& operator _Op(int __rhs); \ - decimal32& operator _Op(unsigned int __rhs); \ - decimal32& operator _Op(long __rhs); \ - decimal32& operator _Op(unsigned long __rhs); \ - decimal32& operator _Op(long long __rhs); \ - decimal32& operator _Op(unsigned long long __rhs); - - _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(+=) - _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(-=) - _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(*=) - _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(/=) -#undef _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT - - private: - __decfloat32 __val; - - public: - __decfloat32 __getval(void) { return __val; } - void __setval(__decfloat32 __x) { __val = __x; } - }; - - /// 3.2.3 Class decimal64. - class decimal64 - { - public: - typedef float __decfloat64 __attribute__((mode(DD))); - - // 3.2.3.2 Construct/copy/destroy. - decimal64() : __val(0.e-398dd) {} - - // 3.2.3.3 Conversion from floating-point type. - decimal64(decimal32 d32); - explicit decimal64(decimal128 d128); - explicit decimal64(float __r) : __val(__r) {} - explicit decimal64(double __r) : __val(__r) {} - explicit decimal64(long double __r) : __val(__r) {} - - // 3.2.3.4 Conversion from integral type. - decimal64(int __z) : __val(__z) {} - decimal64(unsigned int __z) : __val(__z) {} - decimal64(long __z) : __val(__z) {} - decimal64(unsigned long __z) : __val(__z) {} - decimal64(long long __z) : __val(__z) {} - decimal64(unsigned long long __z) : __val(__z) {} - - /// Conforming extension: Conversion from scalar decimal type. - decimal64(__decfloat64 __z) : __val(__z) {} - -#if __cplusplus >= 201103L - // 3.2.3.5 Conversion to integral type. - // Note: explicit per n3407. - explicit operator long long() const { return (long long)__val; } -#endif - - // 3.2.3.6 Increment and decrement operators. - decimal64& operator++() - { - __val += 1; - return *this; - } - - decimal64 operator++(int) - { - decimal64 __tmp = *this; - __val += 1; - return __tmp; - } - - decimal64& operator--() - { - __val -= 1; - return *this; - } - - decimal64 operator--(int) - { - decimal64 __tmp = *this; - __val -= 1; - return __tmp; - } - - // 3.2.3.7 Compound assignment. -#define _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(_Op) \ - decimal64& operator _Op(decimal32 __rhs); \ - decimal64& operator _Op(decimal64 __rhs); \ - decimal64& operator _Op(decimal128 __rhs); \ - decimal64& operator _Op(int __rhs); \ - decimal64& operator _Op(unsigned int __rhs); \ - decimal64& operator _Op(long __rhs); \ - decimal64& operator _Op(unsigned long __rhs); \ - decimal64& operator _Op(long long __rhs); \ - decimal64& operator _Op(unsigned long long __rhs); - - _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(+=) - _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(-=) - _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(*=) - _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(/=) -#undef _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT - - private: - __decfloat64 __val; - - public: - __decfloat64 __getval(void) { return __val; } - void __setval(__decfloat64 __x) { __val = __x; } - }; - - /// 3.2.4 Class decimal128. - class decimal128 - { - public: - typedef float __decfloat128 __attribute__((mode(TD))); - - // 3.2.4.2 Construct/copy/destroy. - decimal128() : __val(0.e-6176DL) {} - - // 3.2.4.3 Conversion from floating-point type. - decimal128(decimal32 d32); - decimal128(decimal64 d64); - explicit decimal128(float __r) : __val(__r) {} - explicit decimal128(double __r) : __val(__r) {} - explicit decimal128(long double __r) : __val(__r) {} - - - // 3.2.4.4 Conversion from integral type. - decimal128(int __z) : __val(__z) {} - decimal128(unsigned int __z) : __val(__z) {} - decimal128(long __z) : __val(__z) {} - decimal128(unsigned long __z) : __val(__z) {} - decimal128(long long __z) : __val(__z) {} - decimal128(unsigned long long __z) : __val(__z) {} - - /// Conforming extension: Conversion from scalar decimal type. - decimal128(__decfloat128 __z) : __val(__z) {} - -#if __cplusplus >= 201103L - // 3.2.4.5 Conversion to integral type. - // Note: explicit per n3407. - explicit operator long long() const { return (long long)__val; } -#endif - - // 3.2.4.6 Increment and decrement operators. - decimal128& operator++() - { - __val += 1; - return *this; - } - - decimal128 operator++(int) - { - decimal128 __tmp = *this; - __val += 1; - return __tmp; - } - - decimal128& operator--() - { - __val -= 1; - return *this; - } - - decimal128 operator--(int) - { - decimal128 __tmp = *this; - __val -= 1; - return __tmp; - } - - // 3.2.4.7 Compound assignment. -#define _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(_Op) \ - decimal128& operator _Op(decimal32 __rhs); \ - decimal128& operator _Op(decimal64 __rhs); \ - decimal128& operator _Op(decimal128 __rhs); \ - decimal128& operator _Op(int __rhs); \ - decimal128& operator _Op(unsigned int __rhs); \ - decimal128& operator _Op(long __rhs); \ - decimal128& operator _Op(unsigned long __rhs); \ - decimal128& operator _Op(long long __rhs); \ - decimal128& operator _Op(unsigned long long __rhs); - - _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(+=) - _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(-=) - _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(*=) - _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(/=) -#undef _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT - - private: - __decfloat128 __val; - - public: - __decfloat128 __getval(void) { return __val; } - void __setval(__decfloat128 __x) { __val = __x; } - }; - -#define _GLIBCXX_USE_DECIMAL_ 1 -} // namespace decimal - // @} group decimal - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#include - -#endif /* _GLIBCXX_DECIMAL */ diff --git a/resources/sources/avr-libstdcpp/include/decimal/decimal.h b/resources/sources/avr-libstdcpp/include/decimal/decimal.h deleted file mode 100644 index 50147e7e8..000000000 --- a/resources/sources/avr-libstdcpp/include/decimal/decimal.h +++ /dev/null @@ -1,469 +0,0 @@ -// decimal classes -*- C++ -*- - -// Copyright (C) 2009-2020 Free Software Foundation, Inc. - -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file decimal/decimal.h - * This is an internal header file, included by other library headers. - * Do not attempt to use it directly. @headername{decimal} - */ - -// ISO/IEC TR 24733 -// Written by Janis Johnson - -#ifndef _GLIBCXX_DECIMAL_IMPL -#define _GLIBCXX_DECIMAL_IMPL 1 - -#pragma GCC system_header - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -namespace decimal -{ - // ISO/IEC TR 24733 3.2.[234].1 Construct/copy/destroy. - - inline decimal32::decimal32(decimal64 __r) : __val(__r.__getval()) {} - inline decimal32::decimal32(decimal128 __r) : __val(__r.__getval()) {} - inline decimal64::decimal64(decimal32 __r) : __val(__r.__getval()) {} - inline decimal64::decimal64(decimal128 __r) : __val(__r.__getval()) {} - inline decimal128::decimal128(decimal32 __r) : __val(__r.__getval()) {} - inline decimal128::decimal128(decimal64 __r) : __val(__r.__getval()) {} - - // ISO/IEC TR 24733 3.2.[234].6 Compound assignment. - -#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, _T2) \ - inline _T1& _T1::operator _Op1(_T2 __rhs) \ - { \ - __setval(__getval() _Op2 __rhs.__getval()); \ - return *this; \ - } - -#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, _T2) \ - inline _T1& _T1::operator _Op1(_T2 __rhs) \ - { \ - __setval(__getval() _Op2 __rhs); \ - return *this; \ - } - -#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(_Op1, _Op2, _T1) \ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal32) \ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal64) \ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal128) \ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, int) \ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned int) \ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, long) \ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned long)\ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, long long) \ - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned long long) - - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal32) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal32) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal32) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal32) - - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal64) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal64) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal64) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal64) - - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal128) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal128) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal128) - _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal128) - -#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC -#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT -#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS - - // Extension: Conversion to integral type. - - inline long long decimal32_to_long_long(decimal32 __d) - { return (long long)__d.__getval(); } - - inline long long decimal64_to_long_long(decimal64 __d) - { return (long long)__d.__getval(); } - - inline long long decimal128_to_long_long(decimal128 __d) - { return (long long)__d.__getval(); } - - inline long long decimal_to_long_long(decimal32 __d) - { return (long long)__d.__getval(); } - - inline long long decimal_to_long_long(decimal64 __d) - { return (long long)__d.__getval(); } - - inline long long decimal_to_long_long(decimal128 __d) - { return (long long)__d.__getval(); } - - // ISO/IEC TR 24733 3.2.5 Initialization from coefficient and exponent. - - static decimal32 make_decimal32(long long __coeff, int __exponent) - { - decimal32 __decexp = 1, __multiplier; - - if (__exponent < 0) - { - __multiplier = 1.E-1DF; - __exponent = -__exponent; - } - else - __multiplier = 1.E1DF; - - for (int __i = 0; __i < __exponent; ++__i) - __decexp *= __multiplier; - - return __coeff * __decexp; - } - - static decimal32 make_decimal32(unsigned long long __coeff, int __exponent) - { - decimal32 __decexp = 1, __multiplier; - - if (__exponent < 0) - { - __multiplier = 1.E-1DF; - __exponent = -__exponent; - } - else - __multiplier = 1.E1DF; - - for (int __i = 0; __i < __exponent; ++__i) - __decexp *= __multiplier; - - return __coeff * __decexp; - } - - static decimal64 make_decimal64(long long __coeff, int __exponent) - { - decimal64 __decexp = 1, __multiplier; - - if (__exponent < 0) - { - __multiplier = 1.E-1DD; - __exponent = -__exponent; - } - else - __multiplier = 1.E1DD; - - for (int __i = 0; __i < __exponent; ++__i) - __decexp *= __multiplier; - - return __coeff * __decexp; - } - - static decimal64 make_decimal64(unsigned long long __coeff, int __exponent) - { - decimal64 __decexp = 1, __multiplier; - - if (__exponent < 0) - { - __multiplier = 1.E-1DD; - __exponent = -__exponent; - } - else - __multiplier = 1.E1DD; - - for (int __i = 0; __i < __exponent; ++__i) - __decexp *= __multiplier; - - return __coeff * __decexp; - } - - static decimal128 make_decimal128(long long __coeff, int __exponent) - { - decimal128 __decexp = 1, __multiplier; - - if (__exponent < 0) - { - __multiplier = 1.E-1DL; - __exponent = -__exponent; - } - else - __multiplier = 1.E1DL; - - for (int __i = 0; __i < __exponent; ++__i) - __decexp *= __multiplier; - - return __coeff * __decexp; - } - - static decimal128 make_decimal128(unsigned long long __coeff, int __exponent) - { - decimal128 __decexp = 1, __multiplier; - - if (__exponent < 0) - { - __multiplier = 1.E-1DL; - __exponent = -__exponent; - } - else - __multiplier = 1.E1DL; - - for (int __i = 0; __i < __exponent; ++__i) - __decexp *= __multiplier; - - return __coeff * __decexp; - } - - // ISO/IEC TR 24733 3.2.6 Conversion to generic floating-point type. - - inline float decimal32_to_float(decimal32 __d) - { return (float)__d.__getval(); } - - inline float decimal64_to_float(decimal64 __d) - { return (float)__d.__getval(); } - - inline float decimal128_to_float(decimal128 __d) - { return (float)__d.__getval(); } - - inline float decimal_to_float(decimal32 __d) - { return (float)__d.__getval(); } - - inline float decimal_to_float(decimal64 __d) - { return (float)__d.__getval(); } - - inline float decimal_to_float(decimal128 __d) - { return (float)__d.__getval(); } - - inline double decimal32_to_double(decimal32 __d) - { return (double)__d.__getval(); } - - inline double decimal64_to_double(decimal64 __d) - { return (double)__d.__getval(); } - - inline double decimal128_to_double(decimal128 __d) - { return (double)__d.__getval(); } - - inline double decimal_to_double(decimal32 __d) - { return (double)__d.__getval(); } - - inline double decimal_to_double(decimal64 __d) - { return (double)__d.__getval(); } - - inline double decimal_to_double(decimal128 __d) - { return (double)__d.__getval(); } - - inline long double decimal32_to_long_double(decimal32 __d) - { return (long double)__d.__getval(); } - - inline long double decimal64_to_long_double(decimal64 __d) - { return (long double)__d.__getval(); } - - inline long double decimal128_to_long_double(decimal128 __d) - { return (long double)__d.__getval(); } - - inline long double decimal_to_long_double(decimal32 __d) - { return (long double)__d.__getval(); } - - inline long double decimal_to_long_double(decimal64 __d) - { return (long double)__d.__getval(); } - - inline long double decimal_to_long_double(decimal128 __d) - { return (long double)__d.__getval(); } - - // ISO/IEC TR 24733 3.2.7 Unary arithmetic operators. - -#define _DEFINE_DECIMAL_UNARY_OP(_Op, _Tp) \ - inline _Tp operator _Op(_Tp __rhs) \ - { \ - _Tp __tmp; \ - __tmp.__setval(_Op __rhs.__getval()); \ - return __tmp; \ - } - - _DEFINE_DECIMAL_UNARY_OP(+, decimal32) - _DEFINE_DECIMAL_UNARY_OP(+, decimal64) - _DEFINE_DECIMAL_UNARY_OP(+, decimal128) - _DEFINE_DECIMAL_UNARY_OP(-, decimal32) - _DEFINE_DECIMAL_UNARY_OP(-, decimal64) - _DEFINE_DECIMAL_UNARY_OP(-, decimal128) - -#undef _DEFINE_DECIMAL_UNARY_OP - - // ISO/IEC TR 24733 3.2.8 Binary arithmetic operators. - -#define _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(_Op, _T1, _T2, _T3) \ - inline _T1 operator _Op(_T2 __lhs, _T3 __rhs) \ - { \ - _T1 __retval; \ - __retval.__setval(__lhs.__getval() _Op __rhs.__getval()); \ - return __retval; \ - } - -#define _DEFINE_DECIMAL_BINARY_OP_BOTH(_Op, _T1, _T2, _T3) \ - inline _T1 operator _Op(_T2 __lhs, _T3 __rhs) \ - { \ - _T1 __retval; \ - __retval.__setval(__lhs.__getval() _Op __rhs.__getval()); \ - return __retval; \ - } - -#define _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, _T2) \ - inline _T1 operator _Op(_T1 __lhs, _T2 __rhs) \ - { \ - _T1 __retval; \ - __retval.__setval(__lhs.__getval() _Op __rhs); \ - return __retval; \ - } - -#define _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, _T2) \ - inline _T1 operator _Op(_T2 __lhs, _T1 __rhs) \ - { \ - _T1 __retval; \ - __retval.__setval(__lhs _Op __rhs.__getval()); \ - return __retval; \ - } - -#define _DEFINE_DECIMAL_BINARY_OP_WITH_INT(_Op, _T1) \ - _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, int); \ - _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned int); \ - _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, long); \ - _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned long); \ - _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, long long); \ - _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned long long); \ - _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, int); \ - _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned int); \ - _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, long); \ - _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned long); \ - _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, long long); \ - _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned long long); \ - - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal32, decimal32, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal32, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal32, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal64, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal128) - - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal32, decimal32, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal32, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal32, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal64, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal128) - - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal32, decimal32, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal32, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal32, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal64, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal128) - - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal32, decimal32, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal32, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal32, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal64, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal32) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal64) - _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal128) - _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal128) - -#undef _DEFINE_DECIMAL_BINARY_OP_WITH_DEC -#undef _DEFINE_DECIMAL_BINARY_OP_BOTH -#undef _DEFINE_DECIMAL_BINARY_OP_LHS -#undef _DEFINE_DECIMAL_BINARY_OP_RHS -#undef _DEFINE_DECIMAL_BINARY_OP_WITH_INT - - // ISO/IEC TR 24733 3.2.9 Comparison operators. - -#define _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _T1, _T2) \ - inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ - { return __lhs.__getval() _Op __rhs.__getval(); } - -#define _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _T1, _T2) \ - inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ - { return __lhs.__getval() _Op __rhs; } - -#define _DEFINE_DECIMAL_COMPARISON_RHS(_Op, _T1, _T2) \ - inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ - { return __lhs _Op __rhs.__getval(); } - -#define _DEFINE_DECIMAL_COMPARISONS(_Op, _Tp) \ - _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal32) \ - _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal64) \ - _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal128) \ - _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, int) \ - _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned int) \ - _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, long) \ - _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned long) \ - _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, long long) \ - _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned long long) \ - _DEFINE_DECIMAL_COMPARISON_RHS(_Op, int, _Tp) \ - _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned int, _Tp) \ - _DEFINE_DECIMAL_COMPARISON_RHS(_Op, long, _Tp) \ - _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned long, _Tp) \ - _DEFINE_DECIMAL_COMPARISON_RHS(_Op, long long, _Tp) \ - _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned long long, _Tp) - - _DEFINE_DECIMAL_COMPARISONS(==, decimal32) - _DEFINE_DECIMAL_COMPARISONS(==, decimal64) - _DEFINE_DECIMAL_COMPARISONS(==, decimal128) - _DEFINE_DECIMAL_COMPARISONS(!=, decimal32) - _DEFINE_DECIMAL_COMPARISONS(!=, decimal64) - _DEFINE_DECIMAL_COMPARISONS(!=, decimal128) - _DEFINE_DECIMAL_COMPARISONS(<, decimal32) - _DEFINE_DECIMAL_COMPARISONS(<, decimal64) - _DEFINE_DECIMAL_COMPARISONS(<, decimal128) - _DEFINE_DECIMAL_COMPARISONS(<=, decimal32) - _DEFINE_DECIMAL_COMPARISONS(<=, decimal64) - _DEFINE_DECIMAL_COMPARISONS(<=, decimal128) - _DEFINE_DECIMAL_COMPARISONS(>, decimal32) - _DEFINE_DECIMAL_COMPARISONS(>, decimal64) - _DEFINE_DECIMAL_COMPARISONS(>, decimal128) - _DEFINE_DECIMAL_COMPARISONS(>=, decimal32) - _DEFINE_DECIMAL_COMPARISONS(>=, decimal64) - _DEFINE_DECIMAL_COMPARISONS(>=, decimal128) - -#undef _DEFINE_DECIMAL_COMPARISON_BOTH -#undef _DEFINE_DECIMAL_COMPARISON_LHS -#undef _DEFINE_DECIMAL_COMPARISON_RHS -#undef _DEFINE_DECIMAL_COMPARISONS -} // namespace decimal - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif /* _GLIBCXX_DECIMAL_IMPL */ diff --git a/resources/sources/avr-libstdcpp/include/deque b/resources/sources/avr-libstdcpp/include/deque deleted file mode 100644 index 07e2c69d0..000000000 --- a/resources/sources/avr-libstdcpp/include/deque +++ /dev/null @@ -1,119 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/deque - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_DEQUE -#define _GLIBCXX_DEQUE 1 - -#pragma GCC system_header - -#include -#if __cplusplus > 201703L -# include // For remove and remove_if -#endif // C++20 -#include -#include -#include -#include -#include -#include - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#if __cplusplus >= 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace pmr - { - template class polymorphic_allocator; - template - using deque = std::deque<_Tp, polymorphic_allocator<_Tp>>; - } // namespace pmr -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 - -#if __cplusplus > 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#define __cpp_lib_erase_if 202002L - - template - inline typename deque<_Tp, _Alloc>::size_type - erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred) - { - const auto __osz = __cont.size(); - __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred), - __cont.end()); - return __osz - __cont.size(); - } - - template - inline typename deque<_Tp, _Alloc>::size_type - erase(deque<_Tp, _Alloc>& __cont, const _Up& __value) - { - const auto __osz = __cont.size(); - __cont.erase(std::remove(__cont.begin(), __cont.end(), __value), - __cont.end()); - return __osz - __cont.size(); - } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 - -#endif /* _GLIBCXX_DEQUE */ diff --git a/resources/sources/avr-libstdcpp/include/ext/algorithm b/resources/sources/avr-libstdcpp/include/ext/algorithm deleted file mode 100644 index e7106fde4..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/algorithm +++ /dev/null @@ -1,596 +0,0 @@ -// Algorithm extensions -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file ext/algorithm - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _EXT_ALGORITHM -#define _EXT_ALGORITHM 1 - -#pragma GCC system_header - -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - //-------------------------------------------------- - // copy_n (not part of the C++ standard) - - template - std::pair<_InputIterator, _OutputIterator> - __copy_n(_InputIterator __first, _Size __count, - _OutputIterator __result, - std::input_iterator_tag) - { - for ( ; __count > 0; --__count) - { - *__result = *__first; - ++__first; - ++__result; - } - return std::pair<_InputIterator, _OutputIterator>(__first, __result); - } - - template - inline std::pair<_RAIterator, _OutputIterator> - __copy_n(_RAIterator __first, _Size __count, - _OutputIterator __result, - std::random_access_iterator_tag) - { - _RAIterator __last = __first + __count; - return std::pair<_RAIterator, _OutputIterator>(__last, std::copy(__first, - __last, - __result)); - } - - /** - * @brief Copies the range [first,first+count) into [result,result+count). - * @param __first An input iterator. - * @param __count The number of elements to copy. - * @param __result An output iterator. - * @return A std::pair composed of first+count and result+count. - * - * This is an SGI extension. - * This inline function will boil down to a call to @c memmove whenever - * possible. Failing that, if random access iterators are passed, then the - * loop count will be known (and therefore a candidate for compiler - * optimizations such as unrolling). - * @ingroup SGIextensions - */ - template - inline std::pair<_InputIterator, _OutputIterator> - copy_n(_InputIterator __first, _Size __count, _OutputIterator __result) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename std::iterator_traits<_InputIterator>::value_type>) - - return __gnu_cxx::__copy_n(__first, __count, __result, - std::__iterator_category(__first)); - } - - template - int - __lexicographical_compare_3way(_InputIterator1 __first1, - _InputIterator1 __last1, - _InputIterator2 __first2, - _InputIterator2 __last2) - { - while (__first1 != __last1 && __first2 != __last2) - { - if (*__first1 < *__first2) - return -1; - if (*__first2 < *__first1) - return 1; - ++__first1; - ++__first2; - } - if (__first2 == __last2) - return !(__first1 == __last1); - else - return -1; - } - - inline int - __lexicographical_compare_3way(const unsigned char* __first1, - const unsigned char* __last1, - const unsigned char* __first2, - const unsigned char* __last2) - { - const std::ptrdiff_t __len1 = __last1 - __first1; - const std::ptrdiff_t __len2 = __last2 - __first2; - const int __result = __builtin_memcmp(__first1, __first2, - (std::min)(__len1, __len2)); - return __result != 0 ? __result - : (__len1 == __len2 ? 0 : (__len1 < __len2 ? -1 : 1)); - } - - inline int - __lexicographical_compare_3way(const char* __first1, const char* __last1, - const char* __first2, const char* __last2) - { -#if CHAR_MAX == SCHAR_MAX - return __lexicographical_compare_3way((const signed char*) __first1, - (const signed char*) __last1, - (const signed char*) __first2, - (const signed char*) __last2); -#else - return __lexicographical_compare_3way((const unsigned char*) __first1, - (const unsigned char*) __last1, - (const unsigned char*) __first2, - (const unsigned char*) __last2); -#endif - } - - /** - * @brief @c memcmp on steroids. - * @param __first1 An input iterator. - * @param __last1 An input iterator. - * @param __first2 An input iterator. - * @param __last2 An input iterator. - * @return An int, as with @c memcmp. - * - * The return value will be less than zero if the first range is - * lexigraphically less than the second, greater than zero - * if the second range is lexigraphically less than the - * first, and zero otherwise. - * This is an SGI extension. - * @ingroup SGIextensions - */ - template - int - lexicographical_compare_3way(_InputIterator1 __first1, - _InputIterator1 __last1, - _InputIterator2 __first2, - _InputIterator2 __last2) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename std::iterator_traits<_InputIterator1>::value_type>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename std::iterator_traits<_InputIterator2>::value_type>) - __glibcxx_requires_valid_range(__first1, __last1); - __glibcxx_requires_valid_range(__first2, __last2); - - return __lexicographical_compare_3way(__first1, __last1, __first2, - __last2); - } - - // count and count_if: this version, whose return type is void, was present - // in the HP STL, and is retained as an extension for backward compatibility. - template - void - count(_InputIterator __first, _InputIterator __last, - const _Tp& __value, - _Size& __n) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_EqualityComparableConcept< - typename std::iterator_traits<_InputIterator>::value_type >) - __glibcxx_function_requires(_EqualityComparableConcept<_Tp>) - __glibcxx_requires_valid_range(__first, __last); - - for ( ; __first != __last; ++__first) - if (*__first == __value) - ++__n; - } - - template - void - count_if(_InputIterator __first, _InputIterator __last, - _Predicate __pred, - _Size& __n) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, - typename std::iterator_traits<_InputIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - for ( ; __first != __last; ++__first) - if (__pred(*__first)) - ++__n; - } - - // random_sample and random_sample_n (extensions, not part of the standard). - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - _OutputIterator - random_sample_n(_ForwardIterator __first, _ForwardIterator __last, - _OutputIterator __out, const _Distance __n) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename std::iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - _Distance __remaining = std::distance(__first, __last); - _Distance __m = (std::min)(__n, __remaining); - - while (__m > 0) - { - if ((std::rand() % __remaining) < __m) - { - *__out = *__first; - ++__out; - --__m; - } - --__remaining; - ++__first; - } - return __out; - } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - _OutputIterator - random_sample_n(_ForwardIterator __first, _ForwardIterator __last, - _OutputIterator __out, const _Distance __n, - _RandomNumberGenerator& __rand) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, - typename std::iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_function_requires(_UnaryFunctionConcept< - _RandomNumberGenerator, _Distance, _Distance>) - __glibcxx_requires_valid_range(__first, __last); - - _Distance __remaining = std::distance(__first, __last); - _Distance __m = (std::min)(__n, __remaining); - - while (__m > 0) - { - if (__rand(__remaining) < __m) - { - *__out = *__first; - ++__out; - --__m; - } - --__remaining; - ++__first; - } - return __out; - } - - template - _RandomAccessIterator - __random_sample(_InputIterator __first, _InputIterator __last, - _RandomAccessIterator __out, - const _Distance __n) - { - _Distance __m = 0; - _Distance __t = __n; - for ( ; __first != __last && __m < __n; ++__m, ++__first) - __out[__m] = *__first; - - while (__first != __last) - { - ++__t; - _Distance __M = std::rand() % (__t); - if (__M < __n) - __out[__M] = *__first; - ++__first; - } - return __out + __m; - } - - template - _RandomAccessIterator - __random_sample(_InputIterator __first, _InputIterator __last, - _RandomAccessIterator __out, - _RandomNumberGenerator& __rand, - const _Distance __n) - { - // concept requirements - __glibcxx_function_requires(_UnaryFunctionConcept< - _RandomNumberGenerator, _Distance, _Distance>) - - _Distance __m = 0; - _Distance __t = __n; - for ( ; __first != __last && __m < __n; ++__m, ++__first) - __out[__m] = *__first; - - while (__first != __last) - { - ++__t; - _Distance __M = __rand(__t); - if (__M < __n) - __out[__M] = *__first; - ++__first; - } - return __out + __m; - } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - inline _RandomAccessIterator - random_sample(_InputIterator __first, _InputIterator __last, - _RandomAccessIterator __out_first, - _RandomAccessIterator __out_last) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_valid_range(__out_first, __out_last); - - return __random_sample(__first, __last, - __out_first, __out_last - __out_first); - } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - inline _RandomAccessIterator - random_sample(_InputIterator __first, _InputIterator __last, - _RandomAccessIterator __out_first, - _RandomAccessIterator __out_last, - _RandomNumberGenerator& __rand) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_requires_valid_range(__first, __last); - __glibcxx_requires_valid_range(__out_first, __out_last); - - return __random_sample(__first, __last, - __out_first, __rand, - __out_last - __out_first); - } - -#if __cplusplus >= 201103L - using std::is_heap; -#else - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - inline bool - is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) - { - // concept requirements - __glibcxx_function_requires(_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename std::iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__is_heap(__first, __last - __first); - } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - inline bool - is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, - _StrictWeakOrdering __comp) - { - // concept requirements - __glibcxx_function_requires(_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering, - typename std::iterator_traits<_RandomAccessIterator>::value_type, - typename std::iterator_traits<_RandomAccessIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - return std::__is_heap(__first, __comp, __last - __first); - } -#endif - -#if __cplusplus >= 201103L - using std::is_sorted; -#else - // is_sorted, a predicated testing whether a range is sorted in - // nondescending order. This is an extension, not part of the C++ - // standard. - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - bool - is_sorted(_ForwardIterator __first, _ForwardIterator __last) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_LessThanComparableConcept< - typename std::iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return true; - - _ForwardIterator __next = __first; - for (++__next; __next != __last; __first = __next, ++__next) - if (*__next < *__first) - return false; - return true; - } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - bool - is_sorted(_ForwardIterator __first, _ForwardIterator __last, - _StrictWeakOrdering __comp) - { - // concept requirements - __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) - __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering, - typename std::iterator_traits<_ForwardIterator>::value_type, - typename std::iterator_traits<_ForwardIterator>::value_type>) - __glibcxx_requires_valid_range(__first, __last); - - if (__first == __last) - return true; - - _ForwardIterator __next = __first; - for (++__next; __next != __last; __first = __next, ++__next) - if (__comp(*__next, *__first)) - return false; - return true; - } -#endif // C++11 - - /** - * @brief Find the median of three values. - * @param __a A value. - * @param __b A value. - * @param __c A value. - * @return One of @p a, @p b or @p c. - * - * If @c {l,m,n} is some convolution of @p {a,b,c} such that @c l<=m<=n - * then the value returned will be @c m. - * This is an SGI extension. - * @ingroup SGIextensions - */ - template - const _Tp& - __median(const _Tp& __a, const _Tp& __b, const _Tp& __c) - { - // concept requirements - __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) - if (__a < __b) - if (__b < __c) - return __b; - else if (__a < __c) - return __c; - else - return __a; - else if (__a < __c) - return __a; - else if (__b < __c) - return __c; - else - return __b; - } - - /** - * @brief Find the median of three values using a predicate for comparison. - * @param __a A value. - * @param __b A value. - * @param __c A value. - * @param __comp A binary predicate. - * @return One of @p a, @p b or @p c. - * - * If @c {l,m,n} is some convolution of @p {a,b,c} such that @p comp(l,m) - * and @p comp(m,n) are both true then the value returned will be @c m. - * This is an SGI extension. - * @ingroup SGIextensions - */ - template - const _Tp& - __median(const _Tp& __a, const _Tp& __b, const _Tp& __c, _Compare __comp) - { - // concept requirements - __glibcxx_function_requires(_BinaryFunctionConcept<_Compare, bool, - _Tp, _Tp>) - if (__comp(__a, __b)) - if (__comp(__b, __c)) - return __b; - else if (__comp(__a, __c)) - return __c; - else - return __a; - else if (__comp(__a, __c)) - return __a; - else if (__comp(__b, __c)) - return __c; - else - return __b; - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _EXT_ALGORITHM */ diff --git a/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h b/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h deleted file mode 100644 index 667a9c084..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h +++ /dev/null @@ -1,125 +0,0 @@ -// Aligned memory buffer -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/aligned_buffer.h - * This file is a GNU extension to the Standard C++ Library. - */ - -#ifndef _ALIGNED_BUFFER_H -#define _ALIGNED_BUFFER_H 1 - -#pragma GCC system_header - -#if __cplusplus >= 201103L -# include -#else -# include -#endif - -namespace __gnu_cxx -{ - // A utility type containing a POD object that can hold an object of type - // _Tp initialized via placement new or allocator_traits::construct. - // Intended for use as a data member subobject, use __aligned_buffer for - // complete objects. - template - struct __aligned_membuf - { - // Target macro ADJUST_FIELD_ALIGN can produce different alignment for - // types when used as class members. __aligned_membuf is intended - // for use as a class member, so align the buffer as for a class member. - // Since GCC 8 we could just use alignof(_Tp) instead, but older - // versions of non-GNU compilers might still need this trick. - struct _Tp2 { _Tp _M_t; }; - - alignas(__alignof__(_Tp2::_M_t)) unsigned char _M_storage[sizeof(_Tp)]; - - __aligned_membuf() = default; - - // Can be used to avoid value-initialization zeroing _M_storage. - __aligned_membuf(std::nullptr_t) { } - - void* - _M_addr() noexcept - { return static_cast(&_M_storage); } - - const void* - _M_addr() const noexcept - { return static_cast(&_M_storage); } - - _Tp* - _M_ptr() noexcept - { return static_cast<_Tp*>(_M_addr()); } - - const _Tp* - _M_ptr() const noexcept - { return static_cast(_M_addr()); } - }; - -#if _GLIBCXX_INLINE_VERSION - template - using __aligned_buffer = __aligned_membuf<_Tp>; -#else - // Similar to __aligned_membuf but aligned for complete objects, not members. - // This type is used in , , - // and , but ideally they would use __aligned_membuf - // instead, as it has smaller size for some types on some targets. - // This type is still used to avoid an ABI change. - template - struct __aligned_buffer - : std::aligned_storage - { - typename - std::aligned_storage::type _M_storage; - - __aligned_buffer() = default; - - // Can be used to avoid value-initialization - __aligned_buffer(std::nullptr_t) { } - - void* - _M_addr() noexcept - { - return static_cast(&_M_storage); - } - - const void* - _M_addr() const noexcept - { - return static_cast(&_M_storage); - } - - _Tp* - _M_ptr() noexcept - { return static_cast<_Tp*>(_M_addr()); } - - const _Tp* - _M_ptr() const noexcept - { return static_cast(_M_addr()); } - }; -#endif - -} // namespace - -#endif /* _ALIGNED_BUFFER_H */ diff --git a/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h b/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h deleted file mode 100644 index 3bbef9ec5..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h +++ /dev/null @@ -1,171 +0,0 @@ -// Allocator traits -*- C++ -*- - -// Copyright (C) 2011-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/alloc_traits.h - * This file is a GNU extension to the Standard C++ Library. - */ - -#ifndef _EXT_ALLOC_TRAITS_H -#define _EXT_ALLOC_TRAITS_H 1 - -#pragma GCC system_header - -# include -#if __cplusplus < 201103L -# include // for __alloc_swap -#endif - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -/** - * @brief Uniform interface to C++98 and C++11 allocators. - * @ingroup allocators -*/ -template - struct __alloc_traits -#if __cplusplus >= 201103L - : std::allocator_traits<_Alloc> -#endif - { - typedef _Alloc allocator_type; -#if __cplusplus >= 201103L - typedef std::allocator_traits<_Alloc> _Base_type; - typedef typename _Base_type::value_type value_type; - typedef typename _Base_type::pointer pointer; - typedef typename _Base_type::const_pointer const_pointer; - typedef typename _Base_type::size_type size_type; - typedef typename _Base_type::difference_type difference_type; - // C++11 allocators do not define reference or const_reference - typedef value_type& reference; - typedef const value_type& const_reference; - using _Base_type::allocate; - using _Base_type::deallocate; - using _Base_type::construct; - using _Base_type::destroy; - using _Base_type::max_size; - - private: - template - using __is_custom_pointer - = std::__and_, - std::__not_>>; - - public: - // overload construct for non-standard pointer types - template - static _GLIBCXX14_CONSTEXPR - std::__enable_if_t<__is_custom_pointer<_Ptr>::value> - construct(_Alloc& __a, _Ptr __p, _Args&&... __args) - noexcept(noexcept(_Base_type::construct(__a, std::__to_address(__p), - std::forward<_Args>(__args)...))) - { - _Base_type::construct(__a, std::__to_address(__p), - std::forward<_Args>(__args)...); - } - - // overload destroy for non-standard pointer types - template - static _GLIBCXX14_CONSTEXPR - std::__enable_if_t<__is_custom_pointer<_Ptr>::value> - destroy(_Alloc& __a, _Ptr __p) - noexcept(noexcept(_Base_type::destroy(__a, std::__to_address(__p)))) - { _Base_type::destroy(__a, std::__to_address(__p)); } - - static constexpr _Alloc _S_select_on_copy(const _Alloc& __a) - { return _Base_type::select_on_container_copy_construction(__a); } - - static _GLIBCXX14_CONSTEXPR void _S_on_swap(_Alloc& __a, _Alloc& __b) - { std::__alloc_on_swap(__a, __b); } - - static constexpr bool _S_propagate_on_copy_assign() - { return _Base_type::propagate_on_container_copy_assignment::value; } - - static constexpr bool _S_propagate_on_move_assign() - { return _Base_type::propagate_on_container_move_assignment::value; } - - static constexpr bool _S_propagate_on_swap() - { return _Base_type::propagate_on_container_swap::value; } - - static constexpr bool _S_always_equal() - { return _Base_type::is_always_equal::value; } - - static constexpr bool _S_nothrow_move() - { return _S_propagate_on_move_assign() || _S_always_equal(); } - - template - struct rebind - { typedef typename _Base_type::template rebind_alloc<_Tp> other; }; -#else // ! C++11 - - typedef typename _Alloc::pointer pointer; - typedef typename _Alloc::const_pointer const_pointer; - typedef typename _Alloc::value_type value_type; - typedef typename _Alloc::reference reference; - typedef typename _Alloc::const_reference const_reference; - typedef typename _Alloc::size_type size_type; - typedef typename _Alloc::difference_type difference_type; - - _GLIBCXX_NODISCARD static pointer - allocate(_Alloc& __a, size_type __n) - { return __a.allocate(__n); } - - template - _GLIBCXX_NODISCARD static pointer - allocate(_Alloc& __a, size_type __n, _Hint __hint) - { return __a.allocate(__n, __hint); } - - static void deallocate(_Alloc& __a, pointer __p, size_type __n) - { __a.deallocate(__p, __n); } - - template - static void construct(_Alloc& __a, pointer __p, const _Tp& __arg) - { __a.construct(__p, __arg); } - - static void destroy(_Alloc& __a, pointer __p) - { __a.destroy(__p); } - - static size_type max_size(const _Alloc& __a) - { return __a.max_size(); } - - static const _Alloc& _S_select_on_copy(const _Alloc& __a) { return __a; } - - static void _S_on_swap(_Alloc& __a, _Alloc& __b) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 431. Swapping containers with unequal allocators. - std::__alloc_swap<_Alloc>::_S_do_it(__a, __b); - } - - template - struct rebind - { typedef typename _Alloc::template rebind<_Tp>::other other; }; -#endif // C++11 - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace __gnu_cxx - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/atomicity.h b/resources/sources/avr-libstdcpp/include/ext/atomicity.h deleted file mode 100644 index 581e0c92a..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/atomicity.h +++ /dev/null @@ -1,116 +0,0 @@ -// Support for atomic operations -*- C++ -*- - -// Copyright (C) 2004-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/atomicity.h - * This file is a GNU extension to the Standard C++ Library. - */ - -#ifndef _GLIBCXX_ATOMICITY_H -#define _GLIBCXX_ATOMICITY_H 1 - -#pragma GCC system_header - -#include - -typedef int _Atomic_word; - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Functions for portable atomic access. - // To abstract locking primitives across all thread policies, use: - // __exchange_and_add_dispatch - // __atomic_add_dispatch -#ifdef _GLIBCXX_ATOMIC_BUILTINS - inline _Atomic_word - __attribute__((__always_inline__)) - __exchange_and_add(volatile _Atomic_word* __mem, int __val) - { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } - - inline void - __attribute__((__always_inline__)) - __atomic_add(volatile _Atomic_word* __mem, int __val) - { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } -#else - _Atomic_word - __exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; - - void - __atomic_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; -#endif - - inline _Atomic_word - __attribute__((__always_inline__)) - __exchange_and_add_single(_Atomic_word* __mem, int __val) - { - _Atomic_word __result = *__mem; - *__mem += __val; - return __result; - } - - inline void - __attribute__((__always_inline__)) - __atomic_add_single(_Atomic_word* __mem, int __val) - { *__mem += __val; } - - inline _Atomic_word - __attribute__ ((__always_inline__)) - __exchange_and_add_dispatch(_Atomic_word* __mem, int __val) - { -#ifdef __GTHREADS - if (__gthread_active_p()) - return __exchange_and_add(__mem, __val); -#endif - return __exchange_and_add_single(__mem, __val); - } - - inline void - __attribute__ ((__always_inline__)) - __atomic_add_dispatch(_Atomic_word* __mem, int __val) - { -#ifdef __GTHREADS - if (__gthread_active_p()) - { - __atomic_add(__mem, __val); - return; - } -#endif - __atomic_add_single(__mem, __val); - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -// Even if the CPU doesn't need a memory barrier, we need to ensure -// that the compiler doesn't reorder memory accesses across the -// barriers. -#ifndef _GLIBCXX_READ_MEM_BARRIER -#define _GLIBCXX_READ_MEM_BARRIER __atomic_thread_fence (__ATOMIC_ACQUIRE) -#endif -#ifndef _GLIBCXX_WRITE_MEM_BARRIER -#define _GLIBCXX_WRITE_MEM_BARRIER __atomic_thread_fence (__ATOMIC_RELEASE) -#endif - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/cmath b/resources/sources/avr-libstdcpp/include/ext/cmath deleted file mode 100644 index 09c6e44b8..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/cmath +++ /dev/null @@ -1,152 +0,0 @@ -// Math extensions -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/cmath - * This file is a GNU extension to the Standard C++ Library. - */ - -#ifndef _EXT_CMATH -#define _EXT_CMATH 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // A class for math constants. - template - struct __math_constants - { - static_assert(std::is_floating_point<_RealType>::value, - "template argument not a floating point type"); - - // Constant @f$ \pi @f$. - static constexpr _RealType __pi = 3.1415926535897932384626433832795029L; - // Constant @f$ \pi / 2 @f$. - static constexpr _RealType __pi_half = 1.5707963267948966192313216916397514L; - // Constant @f$ \pi / 3 @f$. - static constexpr _RealType __pi_third = 1.0471975511965977461542144610931676L; - // Constant @f$ \pi / 4 @f$. - static constexpr _RealType __pi_quarter = 0.7853981633974483096156608458198757L; - // Constant @f$ \sqrt(\pi / 2) @f$. - static constexpr _RealType __root_pi_div_2 = 1.2533141373155002512078826424055226L; - // Constant @f$ 1 / \pi @f$. - static constexpr _RealType __one_div_pi = 0.3183098861837906715377675267450287L; - // Constant @f$ 2 / \pi @f$. - static constexpr _RealType __two_div_pi = 0.6366197723675813430755350534900574L; - // Constant @f$ 2 / \sqrt(\pi) @f$. - static constexpr _RealType __two_div_root_pi = 1.1283791670955125738961589031215452L; - - // Constant Euler's number @f$ e @f$. - static constexpr _RealType __e = 2.7182818284590452353602874713526625L; - // Constant @f$ 1 / e @f$. - static constexpr _RealType __one_div_e = 0.36787944117144232159552377016146087L; - // Constant @f$ \log_2(e) @f$. - static constexpr _RealType __log2_e = 1.4426950408889634073599246810018921L; - // Constant @f$ \log_10(e) @f$. - static constexpr _RealType __log10_e = 0.4342944819032518276511289189166051L; - // Constant @f$ \ln(2) @f$. - static constexpr _RealType __ln_2 = 0.6931471805599453094172321214581766L; - // Constant @f$ \ln(3) @f$. - static constexpr _RealType __ln_3 = 1.0986122886681096913952452369225257L; - // Constant @f$ \ln(10) @f$. - static constexpr _RealType __ln_10 = 2.3025850929940456840179914546843642L; - - // Constant Euler-Mascheroni @f$ \gamma_E @f$. - static constexpr _RealType __gamma_e = 0.5772156649015328606065120900824024L; - // Constant Golden Ratio @f$ \phi @f$. - static constexpr _RealType __phi = 1.6180339887498948482045868343656381L; - - // Constant @f$ \sqrt(2) @f$. - static constexpr _RealType __root_2 = 1.4142135623730950488016887242096981L; - // Constant @f$ \sqrt(3) @f$. - static constexpr _RealType __root_3 = 1.7320508075688772935274463415058724L; - // Constant @f$ \sqrt(5) @f$. - static constexpr _RealType __root_5 = 2.2360679774997896964091736687312762L; - // Constant @f$ \sqrt(7) @f$. - static constexpr _RealType __root_7 = 2.6457513110645905905016157536392604L; - // Constant @f$ 1 / \sqrt(2) @f$. - static constexpr _RealType __one_div_root_2 = 0.7071067811865475244008443621048490L; - }; - - // And the template definitions for the constants. - template - constexpr _RealType __math_constants<_RealType>::__pi; - template - constexpr _RealType __math_constants<_RealType>::__pi_half; - template - constexpr _RealType __math_constants<_RealType>::__pi_third; - template - constexpr _RealType __math_constants<_RealType>::__pi_quarter; - template - constexpr _RealType __math_constants<_RealType>::__root_pi_div_2; - template - constexpr _RealType __math_constants<_RealType>::__one_div_pi; - template - constexpr _RealType __math_constants<_RealType>::__two_div_pi; - template - constexpr _RealType __math_constants<_RealType>::__two_div_root_pi; - template - constexpr _RealType __math_constants<_RealType>::__e; - template - constexpr _RealType __math_constants<_RealType>::__one_div_e; - template - constexpr _RealType __math_constants<_RealType>::__log2_e; - template - constexpr _RealType __math_constants<_RealType>::__log10_e; - template - constexpr _RealType __math_constants<_RealType>::__ln_2; - template - constexpr _RealType __math_constants<_RealType>::__ln_3; - template - constexpr _RealType __math_constants<_RealType>::__ln_10; - template - constexpr _RealType __math_constants<_RealType>::__gamma_e; - template - constexpr _RealType __math_constants<_RealType>::__phi; - template - constexpr _RealType __math_constants<_RealType>::__root_2; - template - constexpr _RealType __math_constants<_RealType>::__root_3; - template - constexpr _RealType __math_constants<_RealType>::__root_5; - template - constexpr _RealType __math_constants<_RealType>::__root_7; - template - constexpr _RealType __math_constants<_RealType>::__one_div_root_2; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace __gnu_cxx - -#endif // C++11 - -#endif // _EXT_CMATH diff --git a/resources/sources/avr-libstdcpp/include/ext/functional b/resources/sources/avr-libstdcpp/include/ext/functional deleted file mode 100644 index 4f50a6003..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/functional +++ /dev/null @@ -1,422 +0,0 @@ -// Functional extensions -*- C++ -*- - -// Copyright (C) 2002-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file ext/functional - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _EXT_FUNCTIONAL -#define _EXT_FUNCTIONAL 1 - -#pragma GCC system_header - -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** The @c identity_element functions are not part of the C++ - * standard; SGI provided them as an extension. Its argument is an - * operation, and its return value is the identity element for that - * operation. It is overloaded for addition and multiplication, - * and you can overload it for your own nefarious operations. - * - * @addtogroup SGIextensions - * @{ - */ - /// An \link SGIextensions SGI extension \endlink. - template - inline _Tp - identity_element(std::plus<_Tp>) - { return _Tp(0); } - - /// An \link SGIextensions SGI extension \endlink. - template - inline _Tp - identity_element(std::multiplies<_Tp>) - { return _Tp(1); } - /** @} */ - - /** As an extension to the binders, SGI provided composition functors and - * wrapper functions to aid in their creation. The @c unary_compose - * functor is constructed from two functions/functors, @c f and @c g. - * Calling @c operator() with a single argument @c x returns @c f(g(x)). - * The function @c compose1 takes the two functions and constructs a - * @c unary_compose variable for you. - * - * @c binary_compose is constructed from three functors, @c f, @c g1, - * and @c g2. Its @c operator() returns @c f(g1(x),g2(x)). The function - * compose2 takes f, g1, and g2, and constructs the @c binary_compose - * instance for you. For example, if @c f returns an int, then - * \code - * int answer = (compose2(f,g1,g2))(x); - * \endcode - * is equivalent to - * \code - * int temp1 = g1(x); - * int temp2 = g2(x); - * int answer = f(temp1,temp2); - * \endcode - * But the first form is more compact, and can be passed around as a - * functor to other algorithms. - * - * @addtogroup SGIextensions - * @{ - */ - /// An \link SGIextensions SGI extension \endlink. - template - class unary_compose - : public std::unary_function - { - protected: - _Operation1 _M_fn1; - _Operation2 _M_fn2; - - public: - unary_compose(const _Operation1& __x, const _Operation2& __y) - : _M_fn1(__x), _M_fn2(__y) {} - - typename _Operation1::result_type - operator()(const typename _Operation2::argument_type& __x) const - { return _M_fn1(_M_fn2(__x)); } - }; - - /// An \link SGIextensions SGI extension \endlink. - template - inline unary_compose<_Operation1, _Operation2> - compose1(const _Operation1& __fn1, const _Operation2& __fn2) - { return unary_compose<_Operation1,_Operation2>(__fn1, __fn2); } - - /// An \link SGIextensions SGI extension \endlink. - template - class binary_compose - : public std::unary_function - { - protected: - _Operation1 _M_fn1; - _Operation2 _M_fn2; - _Operation3 _M_fn3; - - public: - binary_compose(const _Operation1& __x, const _Operation2& __y, - const _Operation3& __z) - : _M_fn1(__x), _M_fn2(__y), _M_fn3(__z) { } - - typename _Operation1::result_type - operator()(const typename _Operation2::argument_type& __x) const - { return _M_fn1(_M_fn2(__x), _M_fn3(__x)); } - }; - - /// An \link SGIextensions SGI extension \endlink. - template - inline binary_compose<_Operation1, _Operation2, _Operation3> - compose2(const _Operation1& __fn1, const _Operation2& __fn2, - const _Operation3& __fn3) - { return binary_compose<_Operation1, _Operation2, _Operation3> - (__fn1, __fn2, __fn3); } - /** @} */ - - /** As an extension, SGI provided a functor called @c identity. When a - * functor is required but no operations are desired, this can be used as a - * pass-through. Its @c operator() returns its argument unchanged. - * - * @addtogroup SGIextensions - */ - template - struct identity - : public std::_Identity<_Tp> {}; - - /** @c select1st and @c select2nd are extensions provided by SGI. Their - * @c operator()s - * take a @c std::pair as an argument, and return either the first member - * or the second member, respectively. They can be used (especially with - * the composition functors) to @a strip data from a sequence before - * performing the remainder of an algorithm. - * - * @addtogroup SGIextensions - * @{ - */ - /// An \link SGIextensions SGI extension \endlink. - template - struct select1st - : public std::_Select1st<_Pair> {}; - - /// An \link SGIextensions SGI extension \endlink. - template - struct select2nd - : public std::_Select2nd<_Pair> {}; - - /** @} */ - - // extension documented next - template - struct _Project1st : public std::binary_function<_Arg1, _Arg2, _Arg1> - { - _Arg1 - operator()(const _Arg1& __x, const _Arg2&) const - { return __x; } - }; - - template - struct _Project2nd : public std::binary_function<_Arg1, _Arg2, _Arg2> - { - _Arg2 - operator()(const _Arg1&, const _Arg2& __y) const - { return __y; } - }; - - /** The @c operator() of the @c project1st functor takes two arbitrary - * arguments and returns the first one, while @c project2nd returns the - * second one. They are extensions provided by SGI. - * - * @addtogroup SGIextensions - * @{ - */ - - /// An \link SGIextensions SGI extension \endlink. - template - struct project1st : public _Project1st<_Arg1, _Arg2> {}; - - /// An \link SGIextensions SGI extension \endlink. - template - struct project2nd : public _Project2nd<_Arg1, _Arg2> {}; - /** @} */ - - // extension documented next - template - struct _Constant_void_fun - { - typedef _Result result_type; - result_type _M_val; - - _Constant_void_fun(const result_type& __v) : _M_val(__v) {} - - const result_type& - operator()() const - { return _M_val; } - }; - - template - struct _Constant_unary_fun - { - typedef _Argument argument_type; - typedef _Result result_type; - result_type _M_val; - - _Constant_unary_fun(const result_type& __v) : _M_val(__v) {} - - const result_type& - operator()(const _Argument&) const - { return _M_val; } - }; - - template - struct _Constant_binary_fun - { - typedef _Arg1 first_argument_type; - typedef _Arg2 second_argument_type; - typedef _Result result_type; - _Result _M_val; - - _Constant_binary_fun(const _Result& __v) : _M_val(__v) {} - - const result_type& - operator()(const _Arg1&, const _Arg2&) const - { return _M_val; } - }; - - /** These three functors are each constructed from a single arbitrary - * variable/value. Later, their @c operator()s completely ignore any - * arguments passed, and return the stored value. - * - @c constant_void_fun's @c operator() takes no arguments - * - @c constant_unary_fun's @c operator() takes one argument (ignored) - * - @c constant_binary_fun's @c operator() takes two arguments (ignored) - * - * The helper creator functions @c constant0, @c constant1, and - * @c constant2 each take a @a result argument and construct variables of - * the appropriate functor type. - * - * @addtogroup SGIextensions - * @{ - */ - /// An \link SGIextensions SGI extension \endlink. - template - struct constant_void_fun - : public _Constant_void_fun<_Result> - { - constant_void_fun(const _Result& __v) - : _Constant_void_fun<_Result>(__v) {} - }; - - /// An \link SGIextensions SGI extension \endlink. - template - struct constant_unary_fun : public _Constant_unary_fun<_Result, _Argument> - { - constant_unary_fun(const _Result& __v) - : _Constant_unary_fun<_Result, _Argument>(__v) {} - }; - - /// An \link SGIextensions SGI extension \endlink. - template - struct constant_binary_fun - : public _Constant_binary_fun<_Result, _Arg1, _Arg2> - { - constant_binary_fun(const _Result& __v) - : _Constant_binary_fun<_Result, _Arg1, _Arg2>(__v) {} - }; - - /// An \link SGIextensions SGI extension \endlink. - template - inline constant_void_fun<_Result> - constant0(const _Result& __val) - { return constant_void_fun<_Result>(__val); } - - /// An \link SGIextensions SGI extension \endlink. - template - inline constant_unary_fun<_Result, _Result> - constant1(const _Result& __val) - { return constant_unary_fun<_Result, _Result>(__val); } - - /// An \link SGIextensions SGI extension \endlink. - template - inline constant_binary_fun<_Result,_Result,_Result> - constant2(const _Result& __val) - { return constant_binary_fun<_Result, _Result, _Result>(__val); } - /** @} */ - - /** The @c subtractive_rng class is documented on - * SGI's site. - * Note that this code assumes that @c int is 32 bits. - * - * @ingroup SGIextensions - */ - class subtractive_rng - : public std::unary_function - { - private: - unsigned int _M_table[55]; - std::size_t _M_index1; - std::size_t _M_index2; - - public: - /// Returns a number less than the argument. - unsigned int - operator()(unsigned int __limit) - { - _M_index1 = (_M_index1 + 1) % 55; - _M_index2 = (_M_index2 + 1) % 55; - _M_table[_M_index1] = _M_table[_M_index1] - _M_table[_M_index2]; - return _M_table[_M_index1] % __limit; - } - - void - _M_initialize(unsigned int __seed) - { - unsigned int __k = 1; - _M_table[54] = __seed; - std::size_t __i; - for (__i = 0; __i < 54; __i++) - { - std::size_t __ii = (21 * (__i + 1) % 55) - 1; - _M_table[__ii] = __k; - __k = __seed - __k; - __seed = _M_table[__ii]; - } - for (int __loop = 0; __loop < 4; __loop++) - { - for (__i = 0; __i < 55; __i++) - _M_table[__i] = _M_table[__i] - _M_table[(1 + __i + 30) % 55]; - } - _M_index1 = 0; - _M_index2 = 31; - } - - /// Ctor allowing you to initialize the seed. - subtractive_rng(unsigned int __seed) - { _M_initialize(__seed); } - - /// Default ctor; initializes its state with some number you don't see. - subtractive_rng() - { _M_initialize(161803398u); } - }; - - // Mem_fun adaptor helper functions mem_fun1 and mem_fun1_ref, - // provided for backward compatibility, they are no longer part of - // the C++ standard. - - template - inline std::mem_fun1_t<_Ret, _Tp, _Arg> - mem_fun1(_Ret (_Tp::*__f)(_Arg)) - { return std::mem_fun1_t<_Ret, _Tp, _Arg>(__f); } - - template - inline std::const_mem_fun1_t<_Ret, _Tp, _Arg> - mem_fun1(_Ret (_Tp::*__f)(_Arg) const) - { return std::const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); } - - template - inline std::mem_fun1_ref_t<_Ret, _Tp, _Arg> - mem_fun1_ref(_Ret (_Tp::*__f)(_Arg)) - { return std::mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } - - template - inline std::const_mem_fun1_ref_t<_Ret, _Tp, _Arg> - mem_fun1_ref(_Ret (_Tp::*__f)(_Arg) const) - { return std::const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif - diff --git a/resources/sources/avr-libstdcpp/include/ext/hash_map b/resources/sources/avr-libstdcpp/include/ext/hash_map deleted file mode 100644 index 93db70d56..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/hash_map +++ /dev/null @@ -1,599 +0,0 @@ -// Hashing map implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file backward/hash_map - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _BACKWARD_HASH_MAP -#define _BACKWARD_HASH_MAP 1 - -#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH -#include -#endif - -#include -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using std::equal_to; - using std::allocator; - using std::pair; - using std::_Select1st; - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template, - class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> > - class hash_map - { - private: - typedef hashtable,_Key, _HashFn, - _Select1st >, - _EqualKey, _Alloc> _Ht; - - _Ht _M_ht; - - public: - typedef typename _Ht::key_type key_type; - typedef _Tp data_type; - typedef _Tp mapped_type; - typedef typename _Ht::value_type value_type; - typedef typename _Ht::hasher hasher; - typedef typename _Ht::key_equal key_equal; - - typedef typename _Ht::size_type size_type; - typedef typename _Ht::difference_type difference_type; - typedef typename _Ht::pointer pointer; - typedef typename _Ht::const_pointer const_pointer; - typedef typename _Ht::reference reference; - typedef typename _Ht::const_reference const_reference; - - typedef typename _Ht::iterator iterator; - typedef typename _Ht::const_iterator const_iterator; - - typedef typename _Ht::allocator_type allocator_type; - - hasher - hash_funct() const - { return _M_ht.hash_funct(); } - - key_equal - key_eq() const - { return _M_ht.key_eq(); } - - allocator_type - get_allocator() const - { return _M_ht.get_allocator(); } - - hash_map() - : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - - explicit - hash_map(size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - - hash_map(size_type __n, const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - - hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) {} - - template - hash_map(_InputIterator __f, _InputIterator __l) - : _M_ht(100, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_map(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) - { _M_ht.insert_unique(__f, __l); } - - size_type - size() const - { return _M_ht.size(); } - - size_type - max_size() const - { return _M_ht.max_size(); } - - _GLIBCXX_NODISCARD bool - empty() const - { return _M_ht.empty(); } - - void - swap(hash_map& __hs) - { _M_ht.swap(__hs._M_ht); } - - template - friend bool - operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&, - const hash_map<_K1, _T1, _HF, _EqK, _Al>&); - - iterator - begin() - { return _M_ht.begin(); } - - iterator - end() - { return _M_ht.end(); } - - const_iterator - begin() const - { return _M_ht.begin(); } - - const_iterator - end() const - { return _M_ht.end(); } - - pair - insert(const value_type& __obj) - { return _M_ht.insert_unique(__obj); } - - template - void - insert(_InputIterator __f, _InputIterator __l) - { _M_ht.insert_unique(__f, __l); } - - pair - insert_noresize(const value_type& __obj) - { return _M_ht.insert_unique_noresize(__obj); } - - iterator - find(const key_type& __key) - { return _M_ht.find(__key); } - - const_iterator - find(const key_type& __key) const - { return _M_ht.find(__key); } - - _Tp& - operator[](const key_type& __key) - { return _M_ht.find_or_insert(value_type(__key, _Tp())).second; } - - size_type - count(const key_type& __key) const - { return _M_ht.count(__key); } - - pair - equal_range(const key_type& __key) - { return _M_ht.equal_range(__key); } - - pair - equal_range(const key_type& __key) const - { return _M_ht.equal_range(__key); } - - size_type - erase(const key_type& __key) - {return _M_ht.erase(__key); } - - void - erase(iterator __it) - { _M_ht.erase(__it); } - - void - erase(iterator __f, iterator __l) - { _M_ht.erase(__f, __l); } - - void - clear() - { _M_ht.clear(); } - - void - resize(size_type __hint) - { _M_ht.resize(__hint); } - - size_type - bucket_count() const - { return _M_ht.bucket_count(); } - - size_type - max_bucket_count() const - { return _M_ht.max_bucket_count(); } - - size_type - elems_in_bucket(size_type __n) const - { return _M_ht.elems_in_bucket(__n); } - }; - - template - inline bool - operator==(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, - const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) - { return __hm1._M_ht == __hm2._M_ht; } - - template - inline bool - operator!=(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, - const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) - { return !(__hm1 == __hm2); } - - template - inline void - swap(hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, - hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) - { __hm1.swap(__hm2); } - - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template, - class _EqualKey = equal_to<_Key>, - class _Alloc = allocator<_Tp> > - class hash_multimap - { - // concept requirements - __glibcxx_class_requires(_Key, _SGIAssignableConcept) - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) - __glibcxx_class_requires3(_HashFn, size_t, _Key, _UnaryFunctionConcept) - __glibcxx_class_requires3(_EqualKey, _Key, _Key, _BinaryPredicateConcept) - - private: - typedef hashtable, _Key, _HashFn, - _Select1st >, _EqualKey, _Alloc> - _Ht; - - _Ht _M_ht; - - public: - typedef typename _Ht::key_type key_type; - typedef _Tp data_type; - typedef _Tp mapped_type; - typedef typename _Ht::value_type value_type; - typedef typename _Ht::hasher hasher; - typedef typename _Ht::key_equal key_equal; - - typedef typename _Ht::size_type size_type; - typedef typename _Ht::difference_type difference_type; - typedef typename _Ht::pointer pointer; - typedef typename _Ht::const_pointer const_pointer; - typedef typename _Ht::reference reference; - typedef typename _Ht::const_reference const_reference; - - typedef typename _Ht::iterator iterator; - typedef typename _Ht::const_iterator const_iterator; - - typedef typename _Ht::allocator_type allocator_type; - - hasher - hash_funct() const - { return _M_ht.hash_funct(); } - - key_equal - key_eq() const - { return _M_ht.key_eq(); } - - allocator_type - get_allocator() const - { return _M_ht.get_allocator(); } - - hash_multimap() - : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - - explicit - hash_multimap(size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - - hash_multimap(size_type __n, const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - - hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) {} - - template - hash_multimap(_InputIterator __f, _InputIterator __l) - : _M_ht(100, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) - { _M_ht.insert_equal(__f, __l); } - - size_type - size() const - { return _M_ht.size(); } - - size_type - max_size() const - { return _M_ht.max_size(); } - - _GLIBCXX_NODISCARD bool - empty() const - { return _M_ht.empty(); } - - void - swap(hash_multimap& __hs) - { _M_ht.swap(__hs._M_ht); } - - template - friend bool - operator==(const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&, - const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&); - - iterator - begin() - { return _M_ht.begin(); } - - iterator - end() - { return _M_ht.end(); } - - const_iterator - begin() const - { return _M_ht.begin(); } - - const_iterator - end() const - { return _M_ht.end(); } - - iterator - insert(const value_type& __obj) - { return _M_ht.insert_equal(__obj); } - - template - void - insert(_InputIterator __f, _InputIterator __l) - { _M_ht.insert_equal(__f,__l); } - - iterator - insert_noresize(const value_type& __obj) - { return _M_ht.insert_equal_noresize(__obj); } - - iterator - find(const key_type& __key) - { return _M_ht.find(__key); } - - const_iterator - find(const key_type& __key) const - { return _M_ht.find(__key); } - - size_type - count(const key_type& __key) const - { return _M_ht.count(__key); } - - pair - equal_range(const key_type& __key) - { return _M_ht.equal_range(__key); } - - pair - equal_range(const key_type& __key) const - { return _M_ht.equal_range(__key); } - - size_type - erase(const key_type& __key) - { return _M_ht.erase(__key); } - - void - erase(iterator __it) - { _M_ht.erase(__it); } - - void - erase(iterator __f, iterator __l) - { _M_ht.erase(__f, __l); } - - void - clear() - { _M_ht.clear(); } - - void - resize(size_type __hint) - { _M_ht.resize(__hint); } - - size_type - bucket_count() const - { return _M_ht.bucket_count(); } - - size_type - max_bucket_count() const - { return _M_ht.max_bucket_count(); } - - size_type - elems_in_bucket(size_type __n) const - { return _M_ht.elems_in_bucket(__n); } - }; - - template - inline bool - operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, - const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) - { return __hm1._M_ht == __hm2._M_ht; } - - template - inline bool - operator!=(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, - const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) - { return !(__hm1 == __hm2); } - - template - inline void - swap(hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, - hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) - { __hm1.swap(__hm2); } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Specialization of insert_iterator so that it will work for hash_map - // and hash_multimap. - template - class insert_iterator<__gnu_cxx::hash_map<_Key, _Tp, _HashFn, - _EqKey, _Alloc> > - { - protected: - typedef __gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc> - _Container; - _Container* container; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x) - : container(&__x) {} - - insert_iterator(_Container& __x, typename _Container::iterator) - : container(&__x) {} - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - container->insert(__value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() { return *this; } - - insert_iterator<_Container>& - operator++(int) - { return *this; } - }; - - template - class insert_iterator<__gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, - _EqKey, _Alloc> > - { - protected: - typedef __gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc> - _Container; - _Container* container; - typename _Container::iterator iter; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x) - : container(&__x) {} - - insert_iterator(_Container& __x, typename _Container::iterator) - : container(&__x) {} - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - container->insert(__value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() - { return *this; } - - insert_iterator<_Container>& - operator++(int) - { return *this; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/hash_set b/resources/sources/avr-libstdcpp/include/ext/hash_set deleted file mode 100644 index 0b99302af..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/hash_set +++ /dev/null @@ -1,569 +0,0 @@ -// Hashing set implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file backward/hash_set - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _BACKWARD_HASH_SET -#define _BACKWARD_HASH_SET 1 - -#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH -#include -#endif - -#include -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using std::equal_to; - using std::allocator; - using std::pair; - using std::_Identity; - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template, - class _EqualKey = equal_to<_Value>, - class _Alloc = allocator<_Value> > - class hash_set - { - // concept requirements - __glibcxx_class_requires(_Value, _SGIAssignableConcept) - __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) - __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) - - typedef __alloc_traits<_Alloc> _Alloc_traits; - - private: - typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, - _EqualKey, _Alloc> _Ht; - _Ht _M_ht; - - public: - typedef typename _Ht::key_type key_type; - typedef typename _Ht::value_type value_type; - typedef typename _Ht::hasher hasher; - typedef typename _Ht::key_equal key_equal; - - typedef typename _Ht::size_type size_type; - typedef typename _Ht::difference_type difference_type; - typedef typename _Alloc_traits::pointer pointer; - typedef typename _Alloc_traits::const_pointer const_pointer; - typedef typename _Alloc_traits::reference reference; - typedef typename _Alloc_traits::const_reference const_reference; - - typedef typename _Ht::const_iterator iterator; - typedef typename _Ht::const_iterator const_iterator; - - typedef typename _Ht::allocator_type allocator_type; - - hasher - hash_funct() const - { return _M_ht.hash_funct(); } - - key_equal - key_eq() const - { return _M_ht.key_eq(); } - - allocator_type - get_allocator() const - { return _M_ht.get_allocator(); } - - hash_set() - : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - - explicit - hash_set(size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - - hash_set(size_type __n, const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - - hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) {} - - template - hash_set(_InputIterator __f, _InputIterator __l) - : _M_ht(100, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) - { _M_ht.insert_unique(__f, __l); } - - template - hash_set(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) - { _M_ht.insert_unique(__f, __l); } - - size_type - size() const - { return _M_ht.size(); } - - size_type - max_size() const - { return _M_ht.max_size(); } - - _GLIBCXX_NODISCARD bool - empty() const - { return _M_ht.empty(); } - - void - swap(hash_set& __hs) - { _M_ht.swap(__hs._M_ht); } - - template - friend bool - operator==(const hash_set<_Val, _HF, _EqK, _Al>&, - const hash_set<_Val, _HF, _EqK, _Al>&); - - iterator - begin() const - { return _M_ht.begin(); } - - iterator - end() const - { return _M_ht.end(); } - - pair - insert(const value_type& __obj) - { - pair __p = _M_ht.insert_unique(__obj); - return pair(__p.first, __p.second); - } - - template - void - insert(_InputIterator __f, _InputIterator __l) - { _M_ht.insert_unique(__f, __l); } - - pair - insert_noresize(const value_type& __obj) - { - pair __p - = _M_ht.insert_unique_noresize(__obj); - return pair(__p.first, __p.second); - } - - iterator - find(const key_type& __key) const - { return _M_ht.find(__key); } - - size_type - count(const key_type& __key) const - { return _M_ht.count(__key); } - - pair - equal_range(const key_type& __key) const - { return _M_ht.equal_range(__key); } - - size_type - erase(const key_type& __key) - {return _M_ht.erase(__key); } - - void - erase(iterator __it) - { _M_ht.erase(__it); } - - void - erase(iterator __f, iterator __l) - { _M_ht.erase(__f, __l); } - - void - clear() - { _M_ht.clear(); } - - void - resize(size_type __hint) - { _M_ht.resize(__hint); } - - size_type - bucket_count() const - { return _M_ht.bucket_count(); } - - size_type - max_bucket_count() const - { return _M_ht.max_bucket_count(); } - - size_type - elems_in_bucket(size_type __n) const - { return _M_ht.elems_in_bucket(__n); } - }; - - template - inline bool - operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, - const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) - { return __hs1._M_ht == __hs2._M_ht; } - - template - inline bool - operator!=(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, - const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) - { return !(__hs1 == __hs2); } - - template - inline void - swap(hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, - hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) - { __hs1.swap(__hs2); } - - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template, - class _EqualKey = equal_to<_Value>, - class _Alloc = allocator<_Value> > - class hash_multiset - { - // concept requirements - __glibcxx_class_requires(_Value, _SGIAssignableConcept) - __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) - __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) - - private: - typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, - _EqualKey, _Alloc> _Ht; - _Ht _M_ht; - - public: - typedef typename _Ht::key_type key_type; - typedef typename _Ht::value_type value_type; - typedef typename _Ht::hasher hasher; - typedef typename _Ht::key_equal key_equal; - - typedef typename _Ht::size_type size_type; - typedef typename _Ht::difference_type difference_type; - typedef typename _Alloc::pointer pointer; - typedef typename _Alloc::const_pointer const_pointer; - typedef typename _Alloc::reference reference; - typedef typename _Alloc::const_reference const_reference; - - typedef typename _Ht::const_iterator iterator; - typedef typename _Ht::const_iterator const_iterator; - - typedef typename _Ht::allocator_type allocator_type; - - hasher - hash_funct() const - { return _M_ht.hash_funct(); } - - key_equal - key_eq() const - { return _M_ht.key_eq(); } - - allocator_type - get_allocator() const - { return _M_ht.get_allocator(); } - - hash_multiset() - : _M_ht(100, hasher(), key_equal(), allocator_type()) {} - - explicit - hash_multiset(size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} - - hash_multiset(size_type __n, const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) {} - - hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) {} - - template - hash_multiset(_InputIterator __f, _InputIterator __l) - : _M_ht(100, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) - : _M_ht(__n, hasher(), key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf) - : _M_ht(__n, __hf, key_equal(), allocator_type()) - { _M_ht.insert_equal(__f, __l); } - - template - hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, - const hasher& __hf, const key_equal& __eql, - const allocator_type& __a = allocator_type()) - : _M_ht(__n, __hf, __eql, __a) - { _M_ht.insert_equal(__f, __l); } - - size_type - size() const - { return _M_ht.size(); } - - size_type - max_size() const - { return _M_ht.max_size(); } - - _GLIBCXX_NODISCARD bool - empty() const - { return _M_ht.empty(); } - - void - swap(hash_multiset& hs) - { _M_ht.swap(hs._M_ht); } - - template - friend bool - operator==(const hash_multiset<_Val, _HF, _EqK, _Al>&, - const hash_multiset<_Val, _HF, _EqK, _Al>&); - - iterator - begin() const - { return _M_ht.begin(); } - - iterator - end() const - { return _M_ht.end(); } - - iterator - insert(const value_type& __obj) - { return _M_ht.insert_equal(__obj); } - - template - void - insert(_InputIterator __f, _InputIterator __l) - { _M_ht.insert_equal(__f,__l); } - - iterator - insert_noresize(const value_type& __obj) - { return _M_ht.insert_equal_noresize(__obj); } - - iterator - find(const key_type& __key) const - { return _M_ht.find(__key); } - - size_type - count(const key_type& __key) const - { return _M_ht.count(__key); } - - pair - equal_range(const key_type& __key) const - { return _M_ht.equal_range(__key); } - - size_type - erase(const key_type& __key) - { return _M_ht.erase(__key); } - - void - erase(iterator __it) - { _M_ht.erase(__it); } - - void - erase(iterator __f, iterator __l) - { _M_ht.erase(__f, __l); } - - void - clear() - { _M_ht.clear(); } - - void - resize(size_type __hint) - { _M_ht.resize(__hint); } - - size_type - bucket_count() const - { return _M_ht.bucket_count(); } - - size_type - max_bucket_count() const - { return _M_ht.max_bucket_count(); } - - size_type - elems_in_bucket(size_type __n) const - { return _M_ht.elems_in_bucket(__n); } - }; - - template - inline bool - operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, - const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) - { return __hs1._M_ht == __hs2._M_ht; } - - template - inline bool - operator!=(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, - const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) - { return !(__hs1 == __hs2); } - - template - inline void - swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, - hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) - { __hs1.swap(__hs2); } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Specialization of insert_iterator so that it will work for hash_set - // and hash_multiset. - template - class insert_iterator<__gnu_cxx::hash_set<_Value, _HashFcn, - _EqualKey, _Alloc> > - { - protected: - typedef __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc> - _Container; - _Container* container; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x) - : container(&__x) {} - - insert_iterator(_Container& __x, typename _Container::iterator) - : container(&__x) {} - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - container->insert(__value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() - { return *this; } - - insert_iterator<_Container>& - operator++(int) - { return *this; } - }; - - template - class insert_iterator<__gnu_cxx::hash_multiset<_Value, _HashFcn, - _EqualKey, _Alloc> > - { - protected: - typedef __gnu_cxx::hash_multiset<_Value, _HashFcn, _EqualKey, _Alloc> - _Container; - _Container* container; - typename _Container::iterator iter; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x) - : container(&__x) {} - - insert_iterator(_Container& __x, typename _Container::iterator) - : container(&__x) {} - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - container->insert(__value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() - { return *this; } - - insert_iterator<_Container>& - operator++(int) { return *this; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/iterator b/resources/sources/avr-libstdcpp/include/ext/iterator deleted file mode 100644 index acfb353a9..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/iterator +++ /dev/null @@ -1,116 +0,0 @@ -// HP/SGI iterator extensions -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996-1998 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file ext/iterator - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _EXT_ITERATOR -#define _EXT_ITERATOR 1 - -#pragma GCC system_header - -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // There are two signatures for distance. In addition to the one - // taking two iterators and returning a result, there is another - // taking two iterators and a reference-to-result variable, and - // returning nothing. The latter seems to be an SGI extension. - // -- pedwards - template - inline void - __distance(_InputIterator __first, _InputIterator __last, - _Distance& __n, std::input_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) - while (__first != __last) - { - ++__first; - ++__n; - } - } - - template - inline void - __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, - _Distance& __n, std::random_access_iterator_tag) - { - // concept requirements - __glibcxx_function_requires(_RandomAccessIteratorConcept< - _RandomAccessIterator>) - __n += __last - __first; - } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - inline void - distance(_InputIterator __first, _InputIterator __last, - _Distance& __n) - { - // concept requirements -- taken care of in __distance - __distance(__first, __last, __n, std::__iterator_category(__first)); - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif - diff --git a/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h b/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h deleted file mode 100644 index 366c766f2..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h +++ /dev/null @@ -1,199 +0,0 @@ -// Allocator that wraps "C" malloc -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/malloc_allocator.h - * This file is a GNU extension to the Standard C++ Library. - */ - -#ifndef _MALLOC_ALLOCATOR_H -#define _MALLOC_ALLOCATOR_H 1 - -#include -#include -#include -#include -#include -#if __cplusplus >= 201103L -#include -#endif - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @brief An allocator that uses malloc. - * @ingroup allocators - * - * This is precisely the allocator defined in the C++ Standard. - * - all allocation calls malloc - * - all deallocation calls free - */ - template - class malloc_allocator - { - public: - typedef _Tp value_type; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; -#if __cplusplus <= 201703L - typedef _Tp* pointer; - typedef const _Tp* const_pointer; - typedef _Tp& reference; - typedef const _Tp& const_reference; - - template - struct rebind - { typedef malloc_allocator<_Tp1> other; }; -#endif - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2103. propagate_on_container_move_assignment - typedef std::true_type propagate_on_container_move_assignment; -#endif - - _GLIBCXX20_CONSTEXPR - malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } - - _GLIBCXX20_CONSTEXPR - malloc_allocator(const malloc_allocator&) _GLIBCXX_USE_NOEXCEPT { } - - template - _GLIBCXX20_CONSTEXPR - malloc_allocator(const malloc_allocator<_Tp1>&) - _GLIBCXX_USE_NOEXCEPT { } - -#if __cplusplus <= 201703L - ~malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } - - pointer - address(reference __x) const _GLIBCXX_NOEXCEPT - { return std::__addressof(__x); } - - const_pointer - address(const_reference __x) const _GLIBCXX_NOEXCEPT - { return std::__addressof(__x); } -#endif - - // NB: __n is permitted to be 0. The C++ standard says nothing - // about what the return value is when __n == 0. - _Tp* - allocate(size_type __n, const void* = 0) - { - if (__n > this->_M_max_size()) - std::__throw_bad_alloc(); - - _Tp* __ret = 0; -#if __cpp_aligned_new -#if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC - if (alignof(_Tp) > alignof(std::max_align_t)) - { - __ret = static_cast<_Tp*>(::aligned_alloc(alignof(_Tp), - __n * sizeof(_Tp))); - } -#else -# define _GLIBCXX_CHECK_MALLOC_RESULT -#endif -#endif - if (!__ret) - __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp))); - if (!__ret) - std::__throw_bad_alloc(); -#ifdef _GLIBCXX_CHECK_MALLOC_RESULT -#undef _GLIBCXX_CHECK_MALLOC_RESULT - if (reinterpret_cast(__ret) % alignof(_Tp)) - { - // Memory returned by malloc is not suitably aligned for _Tp. - deallocate(__ret, __n); - std::__throw_bad_alloc(); - } -#endif - return __ret; - } - - // __p is not permitted to be a null pointer. - void - deallocate(_Tp* __p, size_type) - { std::free(static_cast(__p)); } - -#if __cplusplus <= 201703L - size_type - max_size() const _GLIBCXX_USE_NOEXCEPT - { return _M_max_size(); } - -#if __cplusplus >= 201103L - template - void - construct(_Up* __p, _Args&&... __args) - noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) - { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } - - template - void - destroy(_Up* __p) - noexcept(std::is_nothrow_destructible<_Up>::value) - { __p->~_Up(); } -#else - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 402. wrong new expression in [some_] allocator::construct - void - construct(pointer __p, const _Tp& __val) - { ::new((void *)__p) value_type(__val); } - - void - destroy(pointer __p) { __p->~_Tp(); } -#endif -#endif // ! C++20 - - template - friend _GLIBCXX20_CONSTEXPR bool - operator==(const malloc_allocator&, const malloc_allocator<_Up>&) - _GLIBCXX_NOTHROW - { return true; } - -#if __cpp_impl_three_way_comparison < 201907L - template - friend _GLIBCXX20_CONSTEXPR bool - operator!=(const malloc_allocator&, const malloc_allocator<_Up>&) - _GLIBCXX_NOTHROW - { return false; } -#endif - - private: - _GLIBCXX_CONSTEXPR size_type - _M_max_size() const _GLIBCXX_USE_NOEXCEPT - { -#if __PTRDIFF_MAX__ < __SIZE_MAX__ - return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); -#else - return std::size_t(-1) / sizeof(_Tp); -#endif - } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/memory b/resources/sources/avr-libstdcpp/include/ext/memory deleted file mode 100644 index f590fd98c..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/memory +++ /dev/null @@ -1,200 +0,0 @@ -// Memory extensions -*- C++ -*- - -// Copyright (C) 2002-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file ext/memory - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _EXT_MEMORY -#define _EXT_MEMORY 1 - -#pragma GCC system_header - -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - using std::_Temporary_buffer; - - template - std::pair<_InputIter, _ForwardIter> - __uninitialized_copy_n(_InputIter __first, _Size __count, - _ForwardIter __result, std::input_iterator_tag) - { - _ForwardIter __cur = __result; - __try - { - for (; __count > 0 ; --__count, ++__first, ++__cur) - std::_Construct(&*__cur, *__first); - return std::pair<_InputIter, _ForwardIter>(__first, __cur); - } - __catch(...) - { - std::_Destroy(__result, __cur); - __throw_exception_again; - } - } - - template - inline std::pair<_RandomAccessIter, _ForwardIter> - __uninitialized_copy_n(_RandomAccessIter __first, _Size __count, - _ForwardIter __result, - std::random_access_iterator_tag) - { - _RandomAccessIter __last = __first + __count; - return (std::pair<_RandomAccessIter, _ForwardIter> - (__last, std::uninitialized_copy(__first, __last, __result))); - } - - template - inline std::pair<_InputIter, _ForwardIter> - __uninitialized_copy_n(_InputIter __first, _Size __count, - _ForwardIter __result) - { - return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result, - std::__iterator_category(__first)); - } - - /** - * @brief Copies the range [first,last) into result. - * @param __first An input iterator. - * @param __count Length - * @param __result An output iterator. - * @return __result + (__first + __count) - * @ingroup SGIextensions - * - * Like copy(), but does not require an initialized output range. - */ - template - inline std::pair<_InputIter, _ForwardIter> - uninitialized_copy_n(_InputIter __first, _Size __count, - _ForwardIter __result) - { - return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result, - std::__iterator_category(__first)); - } - - - // An alternative version of uninitialized_copy_n that constructs - // and destroys objects with a user-provided allocator. - template - std::pair<_InputIter, _ForwardIter> - __uninitialized_copy_n_a(_InputIter __first, _Size __count, - _ForwardIter __result, - _Allocator __alloc) - { - _ForwardIter __cur = __result; - __try - { - for (; __count > 0 ; --__count, ++__first, ++__cur) - __alloc.construct(&*__cur, *__first); - return std::pair<_InputIter, _ForwardIter>(__first, __cur); - } - __catch(...) - { - std::_Destroy(__result, __cur, __alloc); - __throw_exception_again; - } - } - - template - inline std::pair<_InputIter, _ForwardIter> - __uninitialized_copy_n_a(_InputIter __first, _Size __count, - _ForwardIter __result, - std::allocator<_Tp>) - { - return __gnu_cxx::uninitialized_copy_n(__first, __count, __result); - } - - /** - * This class provides similar behavior and semantics of the standard - * functions get_temporary_buffer() and return_temporary_buffer(), but - * encapsulated in a type vaguely resembling a standard container. - * - * By default, a temporary_buffer stores space for objects of - * whatever type the Iter iterator points to. It is constructed from a - * typical [first,last) range, and provides the begin(), end(), size() - * functions, as well as requested_size(). For non-trivial types, copies - * of *first will be used to initialize the storage. - * - * @c malloc is used to obtain underlying storage. - * - * Like get_temporary_buffer(), not all the requested memory may be - * available. Ideally, the created buffer will be large enough to hold a - * copy of [first,last), but if size() is less than requested_size(), - * then this didn't happen. - * - * @ingroup SGIextensions - */ - template ::value_type > - struct temporary_buffer : public _Temporary_buffer<_ForwardIterator, _Tp> - { - /// Requests storage large enough to hold a copy of [first,last). - temporary_buffer(_ForwardIterator __first, _ForwardIterator __last) - : _Temporary_buffer<_ForwardIterator, _Tp>(__first, - std::distance(__first, __last)) - { } - - /// Destroys objects and frees storage. - ~temporary_buffer() { } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif - diff --git a/resources/sources/avr-libstdcpp/include/ext/new_allocator.h b/resources/sources/avr-libstdcpp/include/ext/new_allocator.h deleted file mode 100644 index 131718b8b..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/new_allocator.h +++ /dev/null @@ -1,198 +0,0 @@ -// Allocator that wraps operator new -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/new_allocator.h - * This file is a GNU extension to the Standard C++ Library. - */ - -#ifndef _NEW_ALLOCATOR_H -#define _NEW_ALLOCATOR_H 1 - -#include -#include -#include -#include -#if __cplusplus >= 201103L -#include -#endif - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @brief An allocator that uses global new, as per [20.4]. - * @ingroup allocators - * - * This is precisely the allocator defined in the C++ Standard. - * - all allocation calls operator new - * - all deallocation calls operator delete - * - * @tparam _Tp Type of allocated object. - */ - template - class new_allocator - { - public: - typedef _Tp value_type; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; -#if __cplusplus <= 201703L - typedef _Tp* pointer; - typedef const _Tp* const_pointer; - typedef _Tp& reference; - typedef const _Tp& const_reference; - - template - struct rebind - { typedef new_allocator<_Tp1> other; }; -#endif - -#if __cplusplus >= 201103L - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2103. propagate_on_container_move_assignment - typedef std::true_type propagate_on_container_move_assignment; -#endif - - _GLIBCXX20_CONSTEXPR - new_allocator() _GLIBCXX_USE_NOEXCEPT { } - - _GLIBCXX20_CONSTEXPR - new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { } - - template - _GLIBCXX20_CONSTEXPR - new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } - -#if __cplusplus <= 201703L - ~new_allocator() _GLIBCXX_USE_NOEXCEPT { } - - pointer - address(reference __x) const _GLIBCXX_NOEXCEPT - { return std::__addressof(__x); } - - const_pointer - address(const_reference __x) const _GLIBCXX_NOEXCEPT - { return std::__addressof(__x); } -#endif - - // NB: __n is permitted to be 0. The C++ standard says nothing - // about what the return value is when __n == 0. - _GLIBCXX_NODISCARD _Tp* - allocate(size_type __n, const void* = static_cast(0)) - { - if (__n > this->_M_max_size()) - std::__throw_bad_alloc(); - -#if __cpp_aligned_new - if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) - { - std::align_val_t __al = std::align_val_t(alignof(_Tp)); - return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al)); - } -#endif - return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); - } - - // __p is not permitted to be a null pointer. - void - deallocate(_Tp* __p, size_type __t) - { -#if __cpp_aligned_new - if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) - { - ::operator delete(__p, -# if __cpp_sized_deallocation - __t * sizeof(_Tp), -# endif - std::align_val_t(alignof(_Tp))); - return; - } -#endif - ::operator delete(__p -#if __cpp_sized_deallocation - , __t * sizeof(_Tp) -#endif - ); - } - -#if __cplusplus <= 201703L - size_type - max_size() const _GLIBCXX_USE_NOEXCEPT - { return _M_max_size(); } - -#if __cplusplus >= 201103L - template - void - construct(_Up* __p, _Args&&... __args) - noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) - { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } - - template - void - destroy(_Up* __p) - noexcept(std::is_nothrow_destructible<_Up>::value) - { __p->~_Up(); } -#else - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 402. wrong new expression in [some_] allocator::construct - void - construct(pointer __p, const _Tp& __val) - { ::new((void *)__p) _Tp(__val); } - - void - destroy(pointer __p) { __p->~_Tp(); } -#endif -#endif // ! C++20 - - template - friend _GLIBCXX20_CONSTEXPR bool - operator==(const new_allocator&, const new_allocator<_Up>&) - _GLIBCXX_NOTHROW - { return true; } - -#if __cpp_impl_three_way_comparison < 201907L - template - friend _GLIBCXX20_CONSTEXPR bool - operator!=(const new_allocator&, const new_allocator<_Up>&) - _GLIBCXX_NOTHROW - { return false; } -#endif - - private: - _GLIBCXX_CONSTEXPR size_type - _M_max_size() const _GLIBCXX_USE_NOEXCEPT - { -#if __PTRDIFF_MAX__ < __SIZE_MAX__ - return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); -#else - return std::size_t(-1) / sizeof(_Tp); -#endif - } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/numeric b/resources/sources/avr-libstdcpp/include/ext/numeric deleted file mode 100644 index f437ecafd..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/numeric +++ /dev/null @@ -1,152 +0,0 @@ -// Numeric extensions -*- C++ -*- - -// Copyright (C) 2002-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file ext/numeric - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _EXT_NUMERIC -#define _EXT_NUMERIC 1 - -#pragma GCC system_header - -#include -#include - -#include // For identity_element - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Returns __x ** __n, where __n >= 0. _Note that "multiplication" - // is required to be associative, but not necessarily commutative. - template - _Tp - __power(_Tp __x, _Integer __n, _MonoidOperation __monoid_op) - { - if (__n == 0) - return identity_element(__monoid_op); - else - { - while ((__n & 1) == 0) - { - __n >>= 1; - __x = __monoid_op(__x, __x); - } - - _Tp __result = __x; - __n >>= 1; - while (__n != 0) - { - __x = __monoid_op(__x, __x); - if ((__n & 1) != 0) - __result = __monoid_op(__result, __x); - __n >>= 1; - } - return __result; - } - } - - template - inline _Tp - __power(_Tp __x, _Integer __n) - { return __power(__x, __n, std::multiplies<_Tp>()); } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - // Alias for the internal name __power. Note that power is an extension, - // not part of the C++ standard. - template - inline _Tp - power(_Tp __x, _Integer __n, _MonoidOperation __monoid_op) - { return __power(__x, __n, __monoid_op); } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template - inline _Tp - power(_Tp __x, _Integer __n) - { return __power(__x, __n); } - -#if __cplusplus >= 201103L - using std::iota; -#else - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - // iota is not part of the standard until C++11. It is an extension. - template - void - iota(_ForwardIter __first, _ForwardIter __last, _Tp __value) - { - // concept requirements - __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) - __glibcxx_function_requires(_ConvertibleConcept<_Tp, - typename std::iterator_traits<_ForwardIter>::value_type>) - - while (__first != __last) - *__first++ = __value++; - } -#endif // C++11 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h b/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h deleted file mode 100644 index 69f286d7b..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h +++ /dev/null @@ -1,148 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// of the GNU General Public License as published by the Free Software -// Foundation; either version 3, or (at your option) any later -// version. - -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/numeric_traits.h - * This file is a GNU extension to the Standard C++ Library. - */ - -#ifndef _EXT_NUMERIC_TRAITS -#define _EXT_NUMERIC_TRAITS 1 - -#pragma GCC system_header - -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Compile time constants for builtin types. - // In C++98 std::numeric_limits member functions cannot be used for this. -#define __glibcxx_signed(_Tp) ((_Tp)(-1) < 0) -#define __glibcxx_digits(_Tp) \ - (sizeof(_Tp) * __CHAR_BIT__ - __glibcxx_signed(_Tp)) - -#define __glibcxx_min(_Tp) \ - (__glibcxx_signed(_Tp) ? -__glibcxx_max(_Tp) - 1 : (_Tp)0) - -#define __glibcxx_max(_Tp) \ - (__glibcxx_signed(_Tp) ? \ - (((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0) - - template - struct __numeric_traits_integer - { -#if __cplusplus >= 201103L - static_assert(std::__is_integer<_Value>::__value, - "invalid specialization"); -#endif - - // Only integers for initialization of member constant. - static const _Value __min = __glibcxx_min(_Value); - static const _Value __max = __glibcxx_max(_Value); - - // NB: these two also available in std::numeric_limits as compile - // time constants, but is big and we avoid including it. - static const bool __is_signed = __glibcxx_signed(_Value); - static const int __digits = __glibcxx_digits(_Value); - }; - - template - const _Value __numeric_traits_integer<_Value>::__min; - - template - const _Value __numeric_traits_integer<_Value>::__max; - - template - const bool __numeric_traits_integer<_Value>::__is_signed; - - template - const int __numeric_traits_integer<_Value>::__digits; - -#if __cplusplus >= 201103L - template - using __int_traits = __numeric_traits_integer<_Tp>; -#endif - -#undef __glibcxx_signed -#undef __glibcxx_digits -#undef __glibcxx_min -#undef __glibcxx_max - -#define __glibcxx_floating(_Tp, _Fval, _Dval, _LDval) \ - (std::__are_same<_Tp, float>::__value ? _Fval \ - : std::__are_same<_Tp, double>::__value ? _Dval : _LDval) - -#define __glibcxx_max_digits10(_Tp) \ - (2 + __glibcxx_floating(_Tp, __FLT_MANT_DIG__, __DBL_MANT_DIG__, \ - __LDBL_MANT_DIG__) * 643L / 2136) - -#define __glibcxx_digits10(_Tp) \ - __glibcxx_floating(_Tp, __FLT_DIG__, __DBL_DIG__, __LDBL_DIG__) - -#define __glibcxx_max_exponent10(_Tp) \ - __glibcxx_floating(_Tp, __FLT_MAX_10_EXP__, __DBL_MAX_10_EXP__, \ - __LDBL_MAX_10_EXP__) - - template - struct __numeric_traits_floating - { - // Only floating point types. See N1822. - static const int __max_digits10 = __glibcxx_max_digits10(_Value); - - // See above comment... - static const bool __is_signed = true; - static const int __digits10 = __glibcxx_digits10(_Value); - static const int __max_exponent10 = __glibcxx_max_exponent10(_Value); - }; - - template - const int __numeric_traits_floating<_Value>::__max_digits10; - - template - const bool __numeric_traits_floating<_Value>::__is_signed; - - template - const int __numeric_traits_floating<_Value>::__digits10; - - template - const int __numeric_traits_floating<_Value>::__max_exponent10; - - template - struct __numeric_traits - : public __conditional_type::__value, - __numeric_traits_integer<_Value>, - __numeric_traits_floating<_Value> >::__type - { }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#undef __glibcxx_floating -#undef __glibcxx_max_digits10 -#undef __glibcxx_digits10 -#undef __glibcxx_max_exponent10 - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h b/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h deleted file mode 100644 index fc68a7290..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h +++ /dev/null @@ -1,198 +0,0 @@ -// POD character, std::char_traits specialization -*- C++ -*- - -// Copyright (C) 2002-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/pod_char_traits.h - * This file is a GNU extension to the Standard C++ Library. - */ - -// Gabriel Dos Reis -// Benjamin Kosnik - -#ifndef _POD_CHAR_TRAITS_H -#define _POD_CHAR_TRAITS_H 1 - -#pragma GCC system_header - -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // POD character abstraction. - // NB: The char_type parameter is a subset of int_type, as to allow - // int_type to properly hold the full range of char_type values as - // well as EOF. - /// @brief A POD class that serves as a character abstraction class. - template - struct character - { - typedef _Value value_type; - typedef _Int int_type; - typedef _St state_type; - typedef character<_Value, _Int, _St> char_type; - - value_type value; - - template - static char_type - from(const V2& v) - { - char_type ret = { static_cast(v) }; - return ret; - } - - template - static V2 - to(const char_type& c) - { - V2 ret = { static_cast(c.value) }; - return ret; - } - - }; - - template - inline bool - operator==(const character<_Value, _Int, _St>& lhs, - const character<_Value, _Int, _St>& rhs) - { return lhs.value == rhs.value; } - - template - inline bool - operator<(const character<_Value, _Int, _St>& lhs, - const character<_Value, _Int, _St>& rhs) - { return lhs.value < rhs.value; } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /// char_traits<__gnu_cxx::character> specialization. - template - struct char_traits<__gnu_cxx::character<_Value, _Int, _St> > - { - typedef __gnu_cxx::character<_Value, _Int, _St> char_type; - typedef typename char_type::int_type int_type; - typedef typename char_type::state_type state_type; - typedef fpos pos_type; - typedef streamoff off_type; - - static void - assign(char_type& __c1, const char_type& __c2) - { __c1 = __c2; } - - static bool - eq(const char_type& __c1, const char_type& __c2) - { return __c1 == __c2; } - - static bool - lt(const char_type& __c1, const char_type& __c2) - { return __c1 < __c2; } - - static int - compare(const char_type* __s1, const char_type* __s2, size_t __n) - { - for (size_t __i = 0; __i < __n; ++__i) - if (!eq(__s1[__i], __s2[__i])) - return lt(__s1[__i], __s2[__i]) ? -1 : 1; - return 0; - } - - static size_t - length(const char_type* __s) - { - const char_type* __p = __s; - while (__p->value) - ++__p; - return (__p - __s); - } - - static const char_type* - find(const char_type* __s, size_t __n, const char_type& __a) - { - for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p) - if (*__p == __a) - return __p; - return 0; - } - - static char_type* - move(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; - return static_cast - (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))); - } - - static char_type* - copy(char_type* __s1, const char_type* __s2, size_t __n) - { - if (__n == 0) - return __s1; - std::copy(__s2, __s2 + __n, __s1); - return __s1; - } - - static char_type* - assign(char_type* __s, size_t __n, char_type __a) - { - std::fill_n(__s, __n, __a); - return __s; - } - - static char_type - to_char_type(const int_type& __i) - { return char_type::template from(__i); } - - static int_type - to_int_type(const char_type& __c) - { return char_type::template to(__c); } - - static bool - eq_int_type(const int_type& __c1, const int_type& __c2) - { return __c1 == __c2; } - - static int_type - eof() - { - int_type __r = { static_cast::__value, - int_type, int>::__type>(-1) }; - return __r; - } - - static int_type - not_eof(const int_type& __c) - { return eq_int_type(__c, eof()) ? int_type() : __c; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/rb_tree b/resources/sources/avr-libstdcpp/include/ext/rb_tree deleted file mode 100644 index 036e959b1..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/rb_tree +++ /dev/null @@ -1,93 +0,0 @@ -// rb_tree extension -*- C++ -*- - -// Copyright (C) 2002-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file ext/rb_tree - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _RB_TREE -#define _RB_TREE 1 - -#pragma GCC system_header - -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Class rb_tree is not part of the C++ standard. It is provided for - // compatibility with the HP STL. - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template > - struct rb_tree - : public std::_Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc> - { - typedef std::_Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc> _Base; - typedef typename _Base::allocator_type allocator_type; - - rb_tree(const _Compare& __comp = _Compare(), - const allocator_type& __a = allocator_type()) - : _Base(__comp, __a) { } - - ~rb_tree() { } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/slist b/resources/sources/avr-libstdcpp/include/ext/slist deleted file mode 100644 index 03c550127..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/slist +++ /dev/null @@ -1,1082 +0,0 @@ -// Singly-linked list implementation -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file ext/slist - * This file is a GNU extension to the Standard C++ Library (possibly - * containing extensions from the HP/SGI STL subset). - */ - -#ifndef _SLIST -#define _SLIST 1 - -#include -#include -#include -#include -#include -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - struct _Slist_node_base - { - _Slist_node_base* _M_next; - }; - - inline _Slist_node_base* - __slist_make_link(_Slist_node_base* __prev_node, - _Slist_node_base* __new_node) - { - __new_node->_M_next = __prev_node->_M_next; - __prev_node->_M_next = __new_node; - return __new_node; - } - - inline _Slist_node_base* - __slist_previous(_Slist_node_base* __head, - const _Slist_node_base* __node) - { - while (__head && __head->_M_next != __node) - __head = __head->_M_next; - return __head; - } - - inline const _Slist_node_base* - __slist_previous(const _Slist_node_base* __head, - const _Slist_node_base* __node) - { - while (__head && __head->_M_next != __node) - __head = __head->_M_next; - return __head; - } - - inline void - __slist_splice_after(_Slist_node_base* __pos, - _Slist_node_base* __before_first, - _Slist_node_base* __before_last) - { - if (__pos != __before_first && __pos != __before_last) - { - _Slist_node_base* __first = __before_first->_M_next; - _Slist_node_base* __after = __pos->_M_next; - __before_first->_M_next = __before_last->_M_next; - __pos->_M_next = __first; - __before_last->_M_next = __after; - } - } - - inline void - __slist_splice_after(_Slist_node_base* __pos, _Slist_node_base* __head) - { - _Slist_node_base* __before_last = __slist_previous(__head, 0); - if (__before_last != __head) - { - _Slist_node_base* __after = __pos->_M_next; - __pos->_M_next = __head->_M_next; - __head->_M_next = 0; - __before_last->_M_next = __after; - } - } - - inline _Slist_node_base* - __slist_reverse(_Slist_node_base* __node) - { - _Slist_node_base* __result = __node; - __node = __node->_M_next; - __result->_M_next = 0; - while(__node) - { - _Slist_node_base* __next = __node->_M_next; - __node->_M_next = __result; - __result = __node; - __node = __next; - } - return __result; - } - - inline std::size_t - __slist_size(_Slist_node_base* __node) - { - std::size_t __result = 0; - for (; __node != 0; __node = __node->_M_next) - ++__result; - return __result; - } - - template - struct _Slist_node : public _Slist_node_base - { - _Tp _M_data; - }; - - struct _Slist_iterator_base - { - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - typedef std::forward_iterator_tag iterator_category; - - _Slist_node_base* _M_node; - - _Slist_iterator_base(_Slist_node_base* __x) - : _M_node(__x) {} - - void - _M_incr() - { _M_node = _M_node->_M_next; } - - bool - operator==(const _Slist_iterator_base& __x) const - { return _M_node == __x._M_node; } - - bool - operator!=(const _Slist_iterator_base& __x) const - { return _M_node != __x._M_node; } - }; - - template - struct _Slist_iterator : public _Slist_iterator_base - { - typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; - typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; - typedef _Slist_iterator<_Tp, _Ref, _Ptr> _Self; - - typedef _Tp value_type; - typedef _Ptr pointer; - typedef _Ref reference; - typedef _Slist_node<_Tp> _Node; - - explicit - _Slist_iterator(_Node* __x) - : _Slist_iterator_base(__x) {} - - _Slist_iterator() - : _Slist_iterator_base(0) {} - - _Slist_iterator(const iterator& __x) - : _Slist_iterator_base(__x._M_node) {} - - reference - operator*() const - { return ((_Node*) _M_node)->_M_data; } - - pointer - operator->() const - { return &(operator*()); } - - _Self& - operator++() - { - _M_incr(); - return *this; - } - - _Self - operator++(int) - { - _Self __tmp = *this; - _M_incr(); - return __tmp; - } - }; - - template - struct _Slist_base - : public __alloc_traits<_Alloc>::template rebind<_Slist_node<_Tp> >::other - { - typedef typename __alloc_traits<_Alloc>::template - rebind<_Slist_node<_Tp> >::other _Node_alloc; - typedef _Alloc allocator_type; - - allocator_type - get_allocator() const - { return *static_cast(this); } - - _Slist_base(const allocator_type& __a) - : _Node_alloc(__a) - { this->_M_head._M_next = 0; } - - ~_Slist_base() - { _M_erase_after(&this->_M_head, 0); } - - protected: - _Slist_node_base _M_head; - - _Slist_node<_Tp>* - _M_get_node() - { return _Node_alloc::allocate(1); } - - void - _M_put_node(_Slist_node<_Tp>* __p) - { _Node_alloc::deallocate(__p, 1); } - - protected: - _Slist_node_base* _M_erase_after(_Slist_node_base* __pos) - { - _Slist_node<_Tp>* __next = (_Slist_node<_Tp>*) (__pos->_M_next); - _Slist_node_base* __next_next = __next->_M_next; - __pos->_M_next = __next_next; - allocator_type __a = get_allocator(); - __alloc_traits::destroy(__a, &__next->_M_data); - _M_put_node(__next); - return __next_next; - } - _Slist_node_base* _M_erase_after(_Slist_node_base*, _Slist_node_base*); - }; - - template - _Slist_node_base* - _Slist_base<_Tp,_Alloc>::_M_erase_after(_Slist_node_base* __before_first, - _Slist_node_base* __last_node) - { - _Slist_node<_Tp>* __cur = (_Slist_node<_Tp>*) (__before_first->_M_next); - while (__cur != __last_node) - { - _Slist_node<_Tp>* __tmp = __cur; - __cur = (_Slist_node<_Tp>*) __cur->_M_next; - allocator_type __a = get_allocator(); - __alloc_traits::destroy(__a, &__tmp->_M_data); - _M_put_node(__tmp); - } - __before_first->_M_next = __last_node; - return __last_node; - } - - /** - * This is an SGI extension. - * @ingroup SGIextensions - * @doctodo - */ - template > - class slist : private _Slist_base<_Tp,_Alloc> - { - // concept requirements - __glibcxx_class_requires(_Tp, _SGIAssignableConcept) - - private: - typedef _Slist_base<_Tp,_Alloc> _Base; - - public: - typedef _Tp value_type; - typedef value_type* pointer; - typedef const value_type* const_pointer; - typedef value_type& reference; - typedef const value_type& const_reference; - typedef std::size_t size_type; - typedef std::ptrdiff_t difference_type; - - typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; - typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; - - typedef typename _Base::allocator_type allocator_type; - - allocator_type - get_allocator() const - { return _Base::get_allocator(); } - - private: - typedef _Slist_node<_Tp> _Node; - typedef _Slist_node_base _Node_base; - typedef _Slist_iterator_base _Iterator_base; - - _Node* - _M_create_node(const value_type& __x) - { - _Node* __node = this->_M_get_node(); - __try - { - allocator_type __a = get_allocator(); - __alloc_traits::construct(__a, &__node->_M_data, - __x); - __node->_M_next = 0; - } - __catch(...) - { - this->_M_put_node(__node); - __throw_exception_again; - } - return __node; - } - - _Node* - _M_create_node() - { - _Node* __node = this->_M_get_node(); - __try - { - allocator_type __a = get_allocator(); - __alloc_traits::construct(__a, &__node->_M_data, - value_type()); - __node->_M_next = 0; - } - __catch(...) - { - this->_M_put_node(__node); - __throw_exception_again; - } - return __node; - } - - public: - explicit - slist(const allocator_type& __a = allocator_type()) - : _Base(__a) {} - - slist(size_type __n, const value_type& __x, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { _M_insert_after_fill(&this->_M_head, __n, __x); } - - explicit - slist(size_type __n) - : _Base(allocator_type()) - { _M_insert_after_fill(&this->_M_head, __n, value_type()); } - - // We don't need any dispatching tricks here, because - // _M_insert_after_range already does them. - template - slist(_InputIterator __first, _InputIterator __last, - const allocator_type& __a = allocator_type()) - : _Base(__a) - { _M_insert_after_range(&this->_M_head, __first, __last); } - - slist(const slist& __x) - : _Base(__x.get_allocator()) - { _M_insert_after_range(&this->_M_head, __x.begin(), __x.end()); } - - slist& - operator= (const slist& __x); - - ~slist() {} - - public: - // assign(), a generalized assignment member function. Two - // versions: one that takes a count, and one that takes a range. - // The range version is a member template, so we dispatch on whether - // or not the type is an integer. - - void - assign(size_type __n, const _Tp& __val) - { _M_fill_assign(__n, __val); } - - void - _M_fill_assign(size_type __n, const _Tp& __val); - - template - void - assign(_InputIterator __first, _InputIterator __last) - { - typedef typename std::__is_integer<_InputIterator>::__type _Integral; - _M_assign_dispatch(__first, __last, _Integral()); - } - - template - void - _M_assign_dispatch(_Integer __n, _Integer __val, std::__true_type) - { _M_fill_assign((size_type) __n, (_Tp) __val); } - - template - void - _M_assign_dispatch(_InputIterator __first, _InputIterator __last, - std::__false_type); - - public: - - iterator - begin() - { return iterator((_Node*)this->_M_head._M_next); } - - const_iterator - begin() const - { return const_iterator((_Node*)this->_M_head._M_next);} - - iterator - end() - { return iterator(0); } - - const_iterator - end() const - { return const_iterator(0); } - - // Experimental new feature: before_begin() returns a - // non-dereferenceable iterator that, when incremented, yields - // begin(). This iterator may be used as the argument to - // insert_after, erase_after, etc. Note that even for an empty - // slist, before_begin() is not the same iterator as end(). It - // is always necessary to increment before_begin() at least once to - // obtain end(). - iterator - before_begin() - { return iterator((_Node*) &this->_M_head); } - - const_iterator - before_begin() const - { return const_iterator((_Node*) &this->_M_head); } - - size_type - size() const - { return __slist_size(this->_M_head._M_next); } - - size_type - max_size() const - { return size_type(-1); } - - _GLIBCXX_NODISCARD bool - empty() const - { return this->_M_head._M_next == 0; } - - void - swap(slist& __x) - { std::swap(this->_M_head._M_next, __x._M_head._M_next); } - - public: - - reference - front() - { return ((_Node*) this->_M_head._M_next)->_M_data; } - - const_reference - front() const - { return ((_Node*) this->_M_head._M_next)->_M_data; } - - void - push_front(const value_type& __x) - { __slist_make_link(&this->_M_head, _M_create_node(__x)); } - - void - push_front() - { __slist_make_link(&this->_M_head, _M_create_node()); } - - void - pop_front() - { - _Node* __node = (_Node*) this->_M_head._M_next; - this->_M_head._M_next = __node->_M_next; - allocator_type __a = get_allocator(); - __alloc_traits::destroy(__a, &__node->_M_data); - this->_M_put_node(__node); - } - - iterator - previous(const_iterator __pos) - { return iterator((_Node*) __slist_previous(&this->_M_head, - __pos._M_node)); } - - const_iterator - previous(const_iterator __pos) const - { return const_iterator((_Node*) __slist_previous(&this->_M_head, - __pos._M_node)); } - - private: - _Node* - _M_insert_after(_Node_base* __pos, const value_type& __x) - { return (_Node*) (__slist_make_link(__pos, _M_create_node(__x))); } - - _Node* - _M_insert_after(_Node_base* __pos) - { return (_Node*) (__slist_make_link(__pos, _M_create_node())); } - - void - _M_insert_after_fill(_Node_base* __pos, - size_type __n, const value_type& __x) - { - for (size_type __i = 0; __i < __n; ++__i) - __pos = __slist_make_link(__pos, _M_create_node(__x)); - } - - // Check whether it's an integral type. If so, it's not an iterator. - template - void - _M_insert_after_range(_Node_base* __pos, - _InIterator __first, _InIterator __last) - { - typedef typename std::__is_integer<_InIterator>::__type _Integral; - _M_insert_after_range(__pos, __first, __last, _Integral()); - } - - template - void - _M_insert_after_range(_Node_base* __pos, _Integer __n, _Integer __x, - std::__true_type) - { _M_insert_after_fill(__pos, __n, __x); } - - template - void - _M_insert_after_range(_Node_base* __pos, - _InIterator __first, _InIterator __last, - std::__false_type) - { - while (__first != __last) - { - __pos = __slist_make_link(__pos, _M_create_node(*__first)); - ++__first; - } - } - - public: - iterator - insert_after(iterator __pos, const value_type& __x) - { return iterator(_M_insert_after(__pos._M_node, __x)); } - - iterator - insert_after(iterator __pos) - { return insert_after(__pos, value_type()); } - - void - insert_after(iterator __pos, size_type __n, const value_type& __x) - { _M_insert_after_fill(__pos._M_node, __n, __x); } - - // We don't need any dispatching tricks here, because - // _M_insert_after_range already does them. - template - void - insert_after(iterator __pos, _InIterator __first, _InIterator __last) - { _M_insert_after_range(__pos._M_node, __first, __last); } - - iterator - insert(iterator __pos, const value_type& __x) - { return iterator(_M_insert_after(__slist_previous(&this->_M_head, - __pos._M_node), - __x)); } - - iterator - insert(iterator __pos) - { return iterator(_M_insert_after(__slist_previous(&this->_M_head, - __pos._M_node), - value_type())); } - - void - insert(iterator __pos, size_type __n, const value_type& __x) - { _M_insert_after_fill(__slist_previous(&this->_M_head, __pos._M_node), - __n, __x); } - - // We don't need any dispatching tricks here, because - // _M_insert_after_range already does them. - template - void - insert(iterator __pos, _InIterator __first, _InIterator __last) - { _M_insert_after_range(__slist_previous(&this->_M_head, __pos._M_node), - __first, __last); } - - public: - iterator - erase_after(iterator __pos) - { return iterator((_Node*) this->_M_erase_after(__pos._M_node)); } - - iterator - erase_after(iterator __before_first, iterator __last) - { - return iterator((_Node*) this->_M_erase_after(__before_first._M_node, - __last._M_node)); - } - - iterator - erase(iterator __pos) - { - return iterator((_Node*) this->_M_erase_after - (__slist_previous(&this->_M_head, __pos._M_node))); - } - - iterator - erase(iterator __first, iterator __last) - { - return iterator((_Node*) this->_M_erase_after - (__slist_previous(&this->_M_head, __first._M_node), - __last._M_node)); - } - - void - resize(size_type new_size, const _Tp& __x); - - void - resize(size_type new_size) - { resize(new_size, _Tp()); } - - void - clear() - { this->_M_erase_after(&this->_M_head, 0); } - - public: - // Moves the range [__before_first + 1, __before_last + 1) to *this, - // inserting it immediately after __pos. This is constant time. - void - splice_after(iterator __pos, - iterator __before_first, iterator __before_last) - { - if (__before_first != __before_last) - __slist_splice_after(__pos._M_node, __before_first._M_node, - __before_last._M_node); - } - - // Moves the element that follows __prev to *this, inserting it - // immediately after __pos. This is constant time. - void - splice_after(iterator __pos, iterator __prev) - { __slist_splice_after(__pos._M_node, - __prev._M_node, __prev._M_node->_M_next); } - - // Removes all of the elements from the list __x to *this, inserting - // them immediately after __pos. __x must not be *this. Complexity: - // linear in __x.size(). - void - splice_after(iterator __pos, slist& __x) - { __slist_splice_after(__pos._M_node, &__x._M_head); } - - // Linear in distance(begin(), __pos), and linear in __x.size(). - void - splice(iterator __pos, slist& __x) - { - if (__x._M_head._M_next) - __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), - &__x._M_head, - __slist_previous(&__x._M_head, 0)); } - - // Linear in distance(begin(), __pos), and in distance(__x.begin(), __i). - void - splice(iterator __pos, slist& __x, iterator __i) - { __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), - __slist_previous(&__x._M_head, __i._M_node), - __i._M_node); } - - // Linear in distance(begin(), __pos), in distance(__x.begin(), __first), - // and in distance(__first, __last). - void - splice(iterator __pos, slist& __x, iterator __first, iterator __last) - { - if (__first != __last) - __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), - __slist_previous(&__x._M_head, __first._M_node), - __slist_previous(__first._M_node, - __last._M_node)); - } - - public: - void - reverse() - { - if (this->_M_head._M_next) - this->_M_head._M_next = __slist_reverse(this->_M_head._M_next); - } - - void - remove(const _Tp& __val); - - void - unique(); - - void - merge(slist& __x); - - void - sort(); - - template - void - remove_if(_Predicate __pred); - - template - void - unique(_BinaryPredicate __pred); - - template - void - merge(slist&, _StrictWeakOrdering); - - template - void - sort(_StrictWeakOrdering __comp); - }; - - template - slist<_Tp, _Alloc>& - slist<_Tp, _Alloc>::operator=(const slist<_Tp, _Alloc>& __x) - { - if (&__x != this) - { - _Node_base* __p1 = &this->_M_head; - _Node* __n1 = (_Node*) this->_M_head._M_next; - const _Node* __n2 = (const _Node*) __x._M_head._M_next; - while (__n1 && __n2) - { - __n1->_M_data = __n2->_M_data; - __p1 = __n1; - __n1 = (_Node*) __n1->_M_next; - __n2 = (const _Node*) __n2->_M_next; - } - if (__n2 == 0) - this->_M_erase_after(__p1, 0); - else - _M_insert_after_range(__p1, const_iterator((_Node*)__n2), - const_iterator(0)); - } - return *this; - } - - template - void - slist<_Tp, _Alloc>::_M_fill_assign(size_type __n, const _Tp& __val) - { - _Node_base* __prev = &this->_M_head; - _Node* __node = (_Node*) this->_M_head._M_next; - for (; __node != 0 && __n > 0; --__n) - { - __node->_M_data = __val; - __prev = __node; - __node = (_Node*) __node->_M_next; - } - if (__n > 0) - _M_insert_after_fill(__prev, __n, __val); - else - this->_M_erase_after(__prev, 0); - } - - template - template - void - slist<_Tp, _Alloc>::_M_assign_dispatch(_InputIterator __first, - _InputIterator __last, - std::__false_type) - { - _Node_base* __prev = &this->_M_head; - _Node* __node = (_Node*) this->_M_head._M_next; - while (__node != 0 && __first != __last) - { - __node->_M_data = *__first; - __prev = __node; - __node = (_Node*) __node->_M_next; - ++__first; - } - if (__first != __last) - _M_insert_after_range(__prev, __first, __last); - else - this->_M_erase_after(__prev, 0); - } - - template - inline bool - operator==(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) - { - typedef typename slist<_Tp,_Alloc>::const_iterator const_iterator; - const_iterator __end1 = _SL1.end(); - const_iterator __end2 = _SL2.end(); - - const_iterator __i1 = _SL1.begin(); - const_iterator __i2 = _SL2.begin(); - while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) - { - ++__i1; - ++__i2; - } - return __i1 == __end1 && __i2 == __end2; - } - - - template - inline bool - operator<(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) - { return std::lexicographical_compare(_SL1.begin(), _SL1.end(), - _SL2.begin(), _SL2.end()); } - - template - inline bool - operator!=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) - { return !(_SL1 == _SL2); } - - template - inline bool - operator>(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) - { return _SL2 < _SL1; } - - template - inline bool - operator<=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) - { return !(_SL2 < _SL1); } - - template - inline bool - operator>=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) - { return !(_SL1 < _SL2); } - - template - inline void - swap(slist<_Tp, _Alloc>& __x, slist<_Tp, _Alloc>& __y) - { __x.swap(__y); } - - template - void - slist<_Tp, _Alloc>::resize(size_type __len, const _Tp& __x) - { - _Node_base* __cur = &this->_M_head; - while (__cur->_M_next != 0 && __len > 0) - { - --__len; - __cur = __cur->_M_next; - } - if (__cur->_M_next) - this->_M_erase_after(__cur, 0); - else - _M_insert_after_fill(__cur, __len, __x); - } - - template - void - slist<_Tp, _Alloc>::remove(const _Tp& __val) - { - _Node_base* __cur = &this->_M_head; - while (__cur && __cur->_M_next) - { - if (((_Node*) __cur->_M_next)->_M_data == __val) - this->_M_erase_after(__cur); - else - __cur = __cur->_M_next; - } - } - - template - void - slist<_Tp, _Alloc>::unique() - { - _Node_base* __cur = this->_M_head._M_next; - if (__cur) - { - while (__cur->_M_next) - { - if (((_Node*)__cur)->_M_data - == ((_Node*)(__cur->_M_next))->_M_data) - this->_M_erase_after(__cur); - else - __cur = __cur->_M_next; - } - } - } - - template - void - slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x) - { - _Node_base* __n1 = &this->_M_head; - while (__n1->_M_next && __x._M_head._M_next) - { - if (((_Node*) __x._M_head._M_next)->_M_data - < ((_Node*) __n1->_M_next)->_M_data) - __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); - __n1 = __n1->_M_next; - } - if (__x._M_head._M_next) - { - __n1->_M_next = __x._M_head._M_next; - __x._M_head._M_next = 0; - } - } - - template - void - slist<_Tp, _Alloc>::sort() - { - if (this->_M_head._M_next && this->_M_head._M_next->_M_next) - { - slist __carry; - slist __counter[64]; - int __fill = 0; - while (!empty()) - { - __slist_splice_after(&__carry._M_head, - &this->_M_head, this->_M_head._M_next); - int __i = 0; - while (__i < __fill && !__counter[__i].empty()) - { - __counter[__i].merge(__carry); - __carry.swap(__counter[__i]); - ++__i; - } - __carry.swap(__counter[__i]); - if (__i == __fill) - ++__fill; - } - - for (int __i = 1; __i < __fill; ++__i) - __counter[__i].merge(__counter[__i-1]); - this->swap(__counter[__fill-1]); - } - } - - template - template - void slist<_Tp, _Alloc>::remove_if(_Predicate __pred) - { - _Node_base* __cur = &this->_M_head; - while (__cur->_M_next) - { - if (__pred(((_Node*) __cur->_M_next)->_M_data)) - this->_M_erase_after(__cur); - else - __cur = __cur->_M_next; - } - } - - template - template - void - slist<_Tp, _Alloc>::unique(_BinaryPredicate __pred) - { - _Node* __cur = (_Node*) this->_M_head._M_next; - if (__cur) - { - while (__cur->_M_next) - { - if (__pred(((_Node*)__cur)->_M_data, - ((_Node*)(__cur->_M_next))->_M_data)) - this->_M_erase_after(__cur); - else - __cur = (_Node*) __cur->_M_next; - } - } - } - - template - template - void - slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x, - _StrictWeakOrdering __comp) - { - _Node_base* __n1 = &this->_M_head; - while (__n1->_M_next && __x._M_head._M_next) - { - if (__comp(((_Node*) __x._M_head._M_next)->_M_data, - ((_Node*) __n1->_M_next)->_M_data)) - __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); - __n1 = __n1->_M_next; - } - if (__x._M_head._M_next) - { - __n1->_M_next = __x._M_head._M_next; - __x._M_head._M_next = 0; - } - } - - template - template - void - slist<_Tp, _Alloc>::sort(_StrictWeakOrdering __comp) - { - if (this->_M_head._M_next && this->_M_head._M_next->_M_next) - { - slist __carry; - slist __counter[64]; - int __fill = 0; - while (!empty()) - { - __slist_splice_after(&__carry._M_head, - &this->_M_head, this->_M_head._M_next); - int __i = 0; - while (__i < __fill && !__counter[__i].empty()) - { - __counter[__i].merge(__carry, __comp); - __carry.swap(__counter[__i]); - ++__i; - } - __carry.swap(__counter[__i]); - if (__i == __fill) - ++__fill; - } - - for (int __i = 1; __i < __fill; ++__i) - __counter[__i].merge(__counter[__i-1], __comp); - this->swap(__counter[__fill-1]); - } - } - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Specialization of insert_iterator so that insertions will be constant - // time rather than linear time. - template - class insert_iterator<__gnu_cxx::slist<_Tp, _Alloc> > - { - protected: - typedef __gnu_cxx::slist<_Tp, _Alloc> _Container; - _Container* container; - typename _Container::iterator iter; - - public: - typedef _Container container_type; - typedef output_iterator_tag iterator_category; - typedef void value_type; - typedef void difference_type; - typedef void pointer; - typedef void reference; - - insert_iterator(_Container& __x, typename _Container::iterator __i) - : container(&__x) - { - if (__i == __x.begin()) - iter = __x.before_begin(); - else - iter = __x.previous(__i); - } - - insert_iterator<_Container>& - operator=(const typename _Container::value_type& __value) - { - iter = container->insert_after(iter, __value); - return *this; - } - - insert_iterator<_Container>& - operator*() - { return *this; } - - insert_iterator<_Container>& - operator++() - { return *this; } - - insert_iterator<_Container>& - operator++(int) - { return *this; } - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/type_traits.h b/resources/sources/avr-libstdcpp/include/ext/type_traits.h deleted file mode 100644 index cf773cf2d..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/type_traits.h +++ /dev/null @@ -1,221 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2005-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the terms -// of the GNU General Public License as published by the Free Software -// Foundation; either version 3, or (at your option) any later -// version. - -// This library is distributed in the hope that it will be useful, but -// WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU -// General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file ext/type_traits.h - * This file is a GNU extension to the Standard C++ Library. - */ - -#ifndef _EXT_TYPE_TRAITS -#define _EXT_TYPE_TRAITS 1 - -#pragma GCC system_header - -#include -#include - -extern "C++" { - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - // Define a nested type if some predicate holds. - template - struct __enable_if - { }; - - template - struct __enable_if - { typedef _Tp __type; }; - - - // Conditional expression for types. If true, first, if false, second. - template - struct __conditional_type - { typedef _Iftrue __type; }; - - template - struct __conditional_type - { typedef _Iffalse __type; }; - - - // Given an integral builtin type, return the corresponding unsigned type. - template - struct __add_unsigned - { - private: - typedef __enable_if::__value, _Tp> __if_type; - - public: - typedef typename __if_type::__type __type; - }; - - template<> - struct __add_unsigned - { typedef unsigned char __type; }; - - template<> - struct __add_unsigned - { typedef unsigned char __type; }; - - template<> - struct __add_unsigned - { typedef unsigned short __type; }; - - template<> - struct __add_unsigned - { typedef unsigned int __type; }; - - template<> - struct __add_unsigned - { typedef unsigned long __type; }; - - template<> - struct __add_unsigned - { typedef unsigned long long __type; }; - - // Declare but don't define. - template<> - struct __add_unsigned; - - template<> - struct __add_unsigned; - - - // Given an integral builtin type, return the corresponding signed type. - template - struct __remove_unsigned - { - private: - typedef __enable_if::__value, _Tp> __if_type; - - public: - typedef typename __if_type::__type __type; - }; - - template<> - struct __remove_unsigned - { typedef signed char __type; }; - - template<> - struct __remove_unsigned - { typedef signed char __type; }; - - template<> - struct __remove_unsigned - { typedef short __type; }; - - template<> - struct __remove_unsigned - { typedef int __type; }; - - template<> - struct __remove_unsigned - { typedef long __type; }; - - template<> - struct __remove_unsigned - { typedef long long __type; }; - - // Declare but don't define. - template<> - struct __remove_unsigned; - - template<> - struct __remove_unsigned; - - - // For use in string and vstring. - template - inline bool - __is_null_pointer(_Type* __ptr) - { return __ptr == 0; } - - template - inline bool - __is_null_pointer(_Type) - { return false; } - -#if __cplusplus >= 201103L - inline bool - __is_null_pointer(std::nullptr_t) - { return true; } -#endif - - // For complex and cmath - template::__value> - struct __promote - { typedef double __type; }; - - // No nested __type member for non-integer non-floating point types, - // allows this type to be used for SFINAE to constrain overloads in - // and to only the intended types. - template - struct __promote<_Tp, false> - { }; - - template<> - struct __promote - { typedef long double __type; }; - - template<> - struct __promote - { typedef double __type; }; - - template<> - struct __promote - { typedef float __type; }; - - template::__type, - typename _Up2 = typename __promote<_Up>::__type> - struct __promote_2 - { - typedef __typeof__(_Tp2() + _Up2()) __type; - }; - - template::__type, - typename _Up2 = typename __promote<_Up>::__type, - typename _Vp2 = typename __promote<_Vp>::__type> - struct __promote_3 - { - typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type; - }; - - template::__type, - typename _Up2 = typename __promote<_Up>::__type, - typename _Vp2 = typename __promote<_Vp>::__type, - typename _Wp2 = typename __promote<_Wp>::__type> - struct __promote_4 - { - typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type; - }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -} // extern "C++" - -#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/typelist.h b/resources/sources/avr-libstdcpp/include/ext/typelist.h deleted file mode 100644 index 1835c141f..000000000 --- a/resources/sources/avr-libstdcpp/include/ext/typelist.h +++ /dev/null @@ -1,538 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2005-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. - -// Permission to use, copy, modify, sell, and distribute this software -// is hereby granted without fee, provided that the above copyright -// notice appears in all copies, and that both that copyright notice and -// this permission notice appear in supporting documentation. None of -// the above authors, nor IBM Haifa Research Laboratories, make any -// representation about the suitability of this software for any -// purpose. It is provided "as is" without express or implied warranty. - -/** - * @file ext/typelist.h - * This file is a GNU extension to the Standard C++ Library. - * - * Contains typelist_chain definitions. - * Typelists are an idea by Andrei Alexandrescu. - */ - -#ifndef _TYPELIST_H -#define _TYPELIST_H 1 - -#include - -namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -/** @namespace __gnu_cxx::typelist - * @brief GNU typelist extensions for public compile-time use. -*/ -namespace typelist -{ - struct null_type { }; - - template - struct node - { - typedef Root root; - }; - - // Forward declarations of functors. - template - struct chain - { - typedef Hd head; - typedef Typelist tail; - }; - - // Apply all typelist types to unary functor. - template - void - apply(Fn&, Typelist); - - /// Apply all typelist types to generator functor. - template - void - apply_generator(Gn&, Typelist); - - // Apply all typelist types and values to generator functor. - template - void - apply_generator(Gn&, TypelistT, TypelistV); - - template - struct append; - - template - struct append_typelist; - - template - struct contains; - - template class Pred> - struct filter; - - template - struct at_index; - - template class Transform> - struct transform; - - template - struct flatten; - - template - struct from_first; - - template - struct create1; - - template - struct create2; - - template - struct create3; - - template - struct create4; - - template - struct create5; - - template - struct create6; - -namespace detail -{ - template - struct apply_; - - template - struct apply_ > - { - void - operator()(Fn& f) - { - f.operator()(Hd()); - apply_ next; - next(f); - } - }; - - template - struct apply_ - { - void - operator()(Fn&) { } - }; - - template - struct apply_generator1_; - - template - struct apply_generator1_ > - { - void - operator()(Gn& g) - { - g.template operator()(); - apply_generator1_ next; - next(g); - } - }; - - template - struct apply_generator1_ - { - void - operator()(Gn&) { } - }; - - template - struct apply_generator2_; - - template - struct apply_generator2_, chain > - { - void - operator()(Gn& g) - { - g.template operator()(); - apply_generator2_ next; - next(g); - } - }; - - template - struct apply_generator2_ - { - void - operator()(Gn&) { } - }; - - template - struct append_; - - template - struct append_, Typelist_Chain> - { - private: - typedef append_ append_type; - - public: - typedef chain type; - }; - - template - struct append_ - { - typedef Typelist_Chain type; - }; - - template - struct append_, null_type> - { - typedef chain type; - }; - - template<> - struct append_ - { - typedef null_type type; - }; - - template - struct append_typelist_; - - template - struct append_typelist_ > - { - typedef chain type; - }; - - template - struct append_typelist_ > - { - private: - typedef typename append_typelist_::type rest_type; - - public: - typedef typename append >::type::root type; - }; - - template - struct contains_; - - template - struct contains_ - { - enum - { - value = false - }; - }; - - template - struct contains_, T> - { - enum - { - value = contains_::value - }; - }; - - template - struct contains_, T> - { - enum - { - value = true - }; - }; - - template class Pred> - struct chain_filter_; - - template class Pred> - struct chain_filter_ - { - typedef null_type type; - }; - - template class Pred> - struct chain_filter_, Pred> - { - private: - enum - { - include_hd = Pred::value - }; - - typedef typename chain_filter_::type rest_type; - typedef chain chain_type; - - public: - typedef typename __conditional_type::__type type; - }; - - template - struct chain_at_index_; - - template - struct chain_at_index_, 0> - { - typedef Hd type; - }; - - template - struct chain_at_index_, i> - { - typedef typename chain_at_index_::type type; - }; - - template class Transform> - struct chain_transform_; - - template class Transform> - struct chain_transform_ - { - typedef null_type type; - }; - - template class Transform> - struct chain_transform_, Transform> - { - private: - typedef typename chain_transform_::type rest_type; - typedef typename Transform::type transform_type; - - public: - typedef chain type; - }; - - template - struct chain_flatten_; - - template - struct chain_flatten_ > - { - typedef typename Hd_Tl::root type; - }; - - template - struct chain_flatten_ > - { - private: - typedef typename chain_flatten_::type rest_type; - typedef append > append_type; - public: - typedef typename append_type::type::root type; - }; -} // namespace detail - -#define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN7(X0, X1, X2, X3, X4, X5, X6) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN8(X0, X1, X2, X3, X4, X5, X6, X7) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN9(X0, X1, X2, X3, X4, X5, X6, X7, X8) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN10(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN11(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN12(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN13(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN14(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN15(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN16(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN17(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN18(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN19(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) __gnu_cxx::typelist::chain -#define _GLIBCXX_TYPELIST_CHAIN20(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) __gnu_cxx::typelist::chain - - template - void - apply(Fn& fn, Typelist) - { - detail::apply_ a; - a(fn); - } - - template - void - apply_generator(Fn& fn, Typelist) - { - detail::apply_generator1_ a; - a(fn); - } - - template - void - apply_generator(Fn& fn, TypelistT, TypelistV) - { - typedef typename TypelistT::root rootT; - typedef typename TypelistV::root rootV; - detail::apply_generator2_ a; - a(fn); - } - - template - struct append - { - private: - typedef typename Typelist0::root root0_type; - typedef typename Typelist1::root root1_type; - typedef detail::append_ append_type; - - public: - typedef node type; - }; - - template - struct append_typelist - { - private: - typedef typename Typelist_Typelist::root root_type; - typedef detail::append_typelist_ append_type; - - public: - typedef node type; - }; - - template - struct contains - { - private: - typedef typename Typelist::root root_type; - - public: - enum - { - value = detail::contains_::value - }; - }; - - template class Pred> - struct filter - { - private: - typedef typename Typelist::root root_type; - typedef detail::chain_filter_ filter_type; - - public: - typedef node type; - }; - - template - struct at_index - { - private: - typedef typename Typelist::root root_type; - typedef detail::chain_at_index_ index_type; - - public: - typedef typename index_type::type type; - }; - - template class Transform> - struct transform - { - private: - typedef typename Typelist::root root_type; - typedef detail::chain_transform_ transform_type; - - public: - typedef node type; - }; - - template - struct flatten - { - private: - typedef typename Typelist_Typelist::root root_type; - typedef typename detail::chain_flatten_::type flatten_type; - - public: - typedef node type; - }; - - template - struct from_first - { - private: - typedef typename at_index::type first_type; - - public: - typedef node > type; - }; - - template - struct create1 - { - typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> type; - }; - - template - struct create2 - { - typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> type; - }; - - template - struct create3 - { - typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)> type; - }; - - template - struct create4 - { - typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)> type; - }; - - template - struct create5 - { - typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)> type; - }; - - template - struct create6 - { - typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type; - }; -} // namespace typelist -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - - -#endif diff --git a/resources/sources/avr-libstdcpp/include/forward_list b/resources/sources/avr-libstdcpp/include/forward_list deleted file mode 100644 index 439ef6b38..000000000 --- a/resources/sources/avr-libstdcpp/include/forward_list +++ /dev/null @@ -1,87 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/forward_list - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_FORWARD_LIST -#define _GLIBCXX_FORWARD_LIST 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#if __cplusplus >= 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace pmr - { - template class polymorphic_allocator; - template - using forward_list = std::forward_list<_Tp, polymorphic_allocator<_Tp>>; - } // namespace pmr -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 - -#if __cplusplus > 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#define __cpp_lib_erase_if 202002L - - template - inline typename forward_list<_Tp, _Alloc>::size_type - erase_if(forward_list<_Tp, _Alloc>& __cont, _Predicate __pred) - { return __cont.remove_if(__pred); } - - template - inline typename forward_list<_Tp, _Alloc>::size_type - erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value) - { - using __elem_type = typename forward_list<_Tp, _Alloc>::value_type; - return std::erase_if(__cont, [&](__elem_type& __elem) { - return __elem == __value; - }); - } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 - -#endif // C++11 - -#endif // _GLIBCXX_FORWARD_LIST diff --git a/resources/sources/avr-libstdcpp/include/functional b/resources/sources/avr-libstdcpp/include/functional deleted file mode 100644 index dc21c10b7..000000000 --- a/resources/sources/avr-libstdcpp/include/functional +++ /dev/null @@ -1,1280 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file include/functional - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_FUNCTIONAL -#define _GLIBCXX_FUNCTIONAL 1 - -#pragma GCC system_header - -#include -#include - -#if __cplusplus >= 201103L - -#include -#include -#include -#include -#include -#include // std::reference_wrapper and _Mem_fn_traits -#include // std::function -#if __cplusplus > 201402L -# include -# include -# include -# include -# include -#endif -#if __cplusplus > 201703L -# include -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#if __cplusplus >= 201703L -# define __cpp_lib_invoke 201411L -# if __cplusplus > 201703L -# define __cpp_lib_constexpr_functional 201907L -# endif - - /// Invoke a callable object. - template - inline _GLIBCXX20_CONSTEXPR invoke_result_t<_Callable, _Args...> - invoke(_Callable&& __fn, _Args&&... __args) - noexcept(is_nothrow_invocable_v<_Callable, _Args...>) - { - return std::__invoke(std::forward<_Callable>(__fn), - std::forward<_Args>(__args)...); - } -#endif // C++17 - - template::value> - class _Mem_fn_base - : public _Mem_fn_traits<_MemFunPtr>::__maybe_type - { - using _Traits = _Mem_fn_traits<_MemFunPtr>; - - using _Arity = typename _Traits::__arity; - using _Varargs = typename _Traits::__vararg; - - template - friend struct _Bind_check_arity; - - _MemFunPtr _M_pmf; - - public: - - using result_type = typename _Traits::__result_type; - - explicit constexpr - _Mem_fn_base(_MemFunPtr __pmf) noexcept : _M_pmf(__pmf) { } - - template - _GLIBCXX20_CONSTEXPR - auto - operator()(_Args&&... __args) const - noexcept(noexcept( - std::__invoke(_M_pmf, std::forward<_Args>(__args)...))) - -> decltype(std::__invoke(_M_pmf, std::forward<_Args>(__args)...)) - { return std::__invoke(_M_pmf, std::forward<_Args>(__args)...); } - }; - - // Partial specialization for member object pointers. - template - class _Mem_fn_base<_MemObjPtr, false> - { - using _Arity = integral_constant; - using _Varargs = false_type; - - template - friend struct _Bind_check_arity; - - _MemObjPtr _M_pm; - - public: - explicit constexpr - _Mem_fn_base(_MemObjPtr __pm) noexcept : _M_pm(__pm) { } - - template - _GLIBCXX20_CONSTEXPR - auto - operator()(_Tp&& __obj) const - noexcept(noexcept(std::__invoke(_M_pm, std::forward<_Tp>(__obj)))) - -> decltype(std::__invoke(_M_pm, std::forward<_Tp>(__obj))) - { return std::__invoke(_M_pm, std::forward<_Tp>(__obj)); } - }; - - template - struct _Mem_fn; // undefined - - template - struct _Mem_fn<_Res _Class::*> - : _Mem_fn_base<_Res _Class::*> - { - using _Mem_fn_base<_Res _Class::*>::_Mem_fn_base; - }; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2048. Unnecessary mem_fn overloads - /** - * @brief Returns a function object that forwards to the member - * pointer @a pm. - * @ingroup functors - */ - template - _GLIBCXX20_CONSTEXPR - inline _Mem_fn<_Tp _Class::*> - mem_fn(_Tp _Class::* __pm) noexcept - { - return _Mem_fn<_Tp _Class::*>(__pm); - } - - /** - * @brief Determines if the given type _Tp is a function object that - * should be treated as a subexpression when evaluating calls to - * function objects returned by bind(). - * - * C++11 [func.bind.isbind]. - * @ingroup binders - */ - template - struct is_bind_expression - : public false_type { }; - - /** - * @brief Determines if the given type _Tp is a placeholder in a - * bind() expression and, if so, which placeholder it is. - * - * C++11 [func.bind.isplace]. - * @ingroup binders - */ - template - struct is_placeholder - : public integral_constant - { }; - -#if __cplusplus > 201402L - template inline constexpr bool is_bind_expression_v - = is_bind_expression<_Tp>::value; - template inline constexpr int is_placeholder_v - = is_placeholder<_Tp>::value; -#endif // C++17 - - /** @brief The type of placeholder objects defined by libstdc++. - * @ingroup binders - */ - template struct _Placeholder { }; - - /** @namespace std::placeholders - * @brief ISO C++ 2011 namespace for std::bind placeholders. - * @ingroup binders - */ - namespace placeholders - { - /* Define a large number of placeholders. There is no way to - * simplify this with variadic templates, because we're introducing - * unique names for each. - */ - extern const _Placeholder<1> _1; - extern const _Placeholder<2> _2; - extern const _Placeholder<3> _3; - extern const _Placeholder<4> _4; - extern const _Placeholder<5> _5; - extern const _Placeholder<6> _6; - extern const _Placeholder<7> _7; - extern const _Placeholder<8> _8; - extern const _Placeholder<9> _9; - extern const _Placeholder<10> _10; - extern const _Placeholder<11> _11; - extern const _Placeholder<12> _12; - extern const _Placeholder<13> _13; - extern const _Placeholder<14> _14; - extern const _Placeholder<15> _15; - extern const _Placeholder<16> _16; - extern const _Placeholder<17> _17; - extern const _Placeholder<18> _18; - extern const _Placeholder<19> _19; - extern const _Placeholder<20> _20; - extern const _Placeholder<21> _21; - extern const _Placeholder<22> _22; - extern const _Placeholder<23> _23; - extern const _Placeholder<24> _24; - extern const _Placeholder<25> _25; - extern const _Placeholder<26> _26; - extern const _Placeholder<27> _27; - extern const _Placeholder<28> _28; - extern const _Placeholder<29> _29; - } - - /** - * Partial specialization of is_placeholder that provides the placeholder - * number for the placeholder objects defined by libstdc++. - * @ingroup binders - */ - template - struct is_placeholder<_Placeholder<_Num> > - : public integral_constant - { }; - - template - struct is_placeholder > - : public integral_constant - { }; - - - // Like tuple_element_t but SFINAE-friendly. - template - using _Safe_tuple_element_t - = typename enable_if<(__i < tuple_size<_Tuple>::value), - tuple_element<__i, _Tuple>>::type::type; - - /** - * Maps an argument to bind() into an actual argument to the bound - * function object [func.bind.bind]/10. Only the first parameter should - * be specified: the rest are used to determine among the various - * implementations. Note that, although this class is a function - * object, it isn't entirely normal because it takes only two - * parameters regardless of the number of parameters passed to the - * bind expression. The first parameter is the bound argument and - * the second parameter is a tuple containing references to the - * rest of the arguments. - */ - template::value, - bool _IsPlaceholder = (is_placeholder<_Arg>::value > 0)> - class _Mu; - - /** - * If the argument is reference_wrapper<_Tp>, returns the - * underlying reference. - * C++11 [func.bind.bind] p10 bullet 1. - */ - template - class _Mu, false, false> - { - public: - /* Note: This won't actually work for const volatile - * reference_wrappers, because reference_wrapper::get() is const - * but not volatile-qualified. This might be a defect in the TR. - */ - template - _GLIBCXX20_CONSTEXPR - _Tp& - operator()(_CVRef& __arg, _Tuple&) const volatile - { return __arg.get(); } - }; - - /** - * If the argument is a bind expression, we invoke the underlying - * function object with the same cv-qualifiers as we are given and - * pass along all of our arguments (unwrapped). - * C++11 [func.bind.bind] p10 bullet 2. - */ - template - class _Mu<_Arg, true, false> - { - public: - template - _GLIBCXX20_CONSTEXPR - auto - operator()(_CVArg& __arg, - tuple<_Args...>& __tuple) const volatile - -> decltype(__arg(declval<_Args>()...)) - { - // Construct an index tuple and forward to __call - typedef typename _Build_index_tuple::__type - _Indexes; - return this->__call(__arg, __tuple, _Indexes()); - } - - private: - // Invokes the underlying function object __arg by unpacking all - // of the arguments in the tuple. - template - _GLIBCXX20_CONSTEXPR - auto - __call(_CVArg& __arg, tuple<_Args...>& __tuple, - const _Index_tuple<_Indexes...>&) const volatile - -> decltype(__arg(declval<_Args>()...)) - { - return __arg(std::get<_Indexes>(std::move(__tuple))...); - } - }; - - /** - * If the argument is a placeholder for the Nth argument, returns - * a reference to the Nth argument to the bind function object. - * C++11 [func.bind.bind] p10 bullet 3. - */ - template - class _Mu<_Arg, false, true> - { - public: - template - _GLIBCXX20_CONSTEXPR - _Safe_tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>&& - operator()(const volatile _Arg&, _Tuple& __tuple) const volatile - { - return - ::std::get<(is_placeholder<_Arg>::value - 1)>(std::move(__tuple)); - } - }; - - /** - * If the argument is just a value, returns a reference to that - * value. The cv-qualifiers on the reference are determined by the caller. - * C++11 [func.bind.bind] p10 bullet 4. - */ - template - class _Mu<_Arg, false, false> - { - public: - template - _GLIBCXX20_CONSTEXPR - _CVArg&& - operator()(_CVArg&& __arg, _Tuple&) const volatile - { return std::forward<_CVArg>(__arg); } - }; - - // std::get for volatile-qualified tuples - template - inline auto - __volget(volatile tuple<_Tp...>& __tuple) - -> __tuple_element_t<_Ind, tuple<_Tp...>> volatile& - { return std::get<_Ind>(const_cast&>(__tuple)); } - - // std::get for const-volatile-qualified tuples - template - inline auto - __volget(const volatile tuple<_Tp...>& __tuple) - -> __tuple_element_t<_Ind, tuple<_Tp...>> const volatile& - { return std::get<_Ind>(const_cast&>(__tuple)); } - - /// Type of the function object returned from bind(). - template - struct _Bind; - - template - class _Bind<_Functor(_Bound_args...)> - : public _Weak_result_type<_Functor> - { - typedef typename _Build_index_tuple::__type - _Bound_indexes; - - _Functor _M_f; - tuple<_Bound_args...> _M_bound_args; - - // Call unqualified - template - _GLIBCXX20_CONSTEXPR - _Result - __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) - { - return std::__invoke(_M_f, - _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... - ); - } - - // Call as const - template - _GLIBCXX20_CONSTEXPR - _Result - __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const - { - return std::__invoke(_M_f, - _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... - ); - } - - // Call as volatile - template - _Result - __call_v(tuple<_Args...>&& __args, - _Index_tuple<_Indexes...>) volatile - { - return std::__invoke(_M_f, - _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... - ); - } - - // Call as const volatile - template - _Result - __call_c_v(tuple<_Args...>&& __args, - _Index_tuple<_Indexes...>) const volatile - { - return std::__invoke(_M_f, - _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... - ); - } - - template - using _Mu_type = decltype( - _Mu::type>()( - std::declval<_BoundArg&>(), std::declval<_CallArgs&>()) ); - - template - using _Res_type_impl - = typename result_of< _Fn&(_Mu_type<_BArgs, _CallArgs>&&...) >::type; - - template - using _Res_type = _Res_type_impl<_Functor, _CallArgs, _Bound_args...>; - - template - using __dependent = typename - enable_if::value+1), _Functor>::type; - - template class __cv_quals> - using _Res_type_cv = _Res_type_impl< - typename __cv_quals<__dependent<_CallArgs>>::type, - _CallArgs, - typename __cv_quals<_Bound_args>::type...>; - - public: - template - explicit _GLIBCXX20_CONSTEXPR - _Bind(const _Functor& __f, _Args&&... __args) - : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) - { } - - template - explicit _GLIBCXX20_CONSTEXPR - _Bind(_Functor&& __f, _Args&&... __args) - : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) - { } - - _Bind(const _Bind&) = default; - _Bind(_Bind&&) = default; - - // Call unqualified - template>> - _GLIBCXX20_CONSTEXPR - _Result - operator()(_Args&&... __args) - { - return this->__call<_Result>( - std::forward_as_tuple(std::forward<_Args>(__args)...), - _Bound_indexes()); - } - - // Call as const - template, add_const>> - _GLIBCXX20_CONSTEXPR - _Result - operator()(_Args&&... __args) const - { - return this->__call_c<_Result>( - std::forward_as_tuple(std::forward<_Args>(__args)...), - _Bound_indexes()); - } - -#if __cplusplus > 201402L -# define _GLIBCXX_DEPR_BIND \ - [[deprecated("std::bind does not support volatile in C++17")]] -#else -# define _GLIBCXX_DEPR_BIND -#endif - // Call as volatile - template, add_volatile>> - _GLIBCXX_DEPR_BIND - _Result - operator()(_Args&&... __args) volatile - { - return this->__call_v<_Result>( - std::forward_as_tuple(std::forward<_Args>(__args)...), - _Bound_indexes()); - } - - // Call as const volatile - template, add_cv>> - _GLIBCXX_DEPR_BIND - _Result - operator()(_Args&&... __args) const volatile - { - return this->__call_c_v<_Result>( - std::forward_as_tuple(std::forward<_Args>(__args)...), - _Bound_indexes()); - } - }; - - /// Type of the function object returned from bind(). - template - struct _Bind_result; - - template - class _Bind_result<_Result, _Functor(_Bound_args...)> - { - typedef typename _Build_index_tuple::__type - _Bound_indexes; - - _Functor _M_f; - tuple<_Bound_args...> _M_bound_args; - - // Call unqualified - template - _GLIBCXX20_CONSTEXPR - _Res - __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) - { - return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() - (std::get<_Indexes>(_M_bound_args), __args)...); - } - - // Call as const - template - _GLIBCXX20_CONSTEXPR - _Res - __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const - { - return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() - (std::get<_Indexes>(_M_bound_args), __args)...); - } - - // Call as volatile - template - _GLIBCXX20_CONSTEXPR - _Res - __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile - { - return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() - (__volget<_Indexes>(_M_bound_args), __args)...); - } - - // Call as const volatile - template - _GLIBCXX20_CONSTEXPR - _Res - __call(tuple<_Args...>&& __args, - _Index_tuple<_Indexes...>) const volatile - { - return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() - (__volget<_Indexes>(_M_bound_args), __args)...); - } - - public: - typedef _Result result_type; - - template - explicit _GLIBCXX20_CONSTEXPR - _Bind_result(const _Functor& __f, _Args&&... __args) - : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) - { } - - template - explicit _GLIBCXX20_CONSTEXPR - _Bind_result(_Functor&& __f, _Args&&... __args) - : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) - { } - - _Bind_result(const _Bind_result&) = default; - _Bind_result(_Bind_result&&) = default; - - // Call unqualified - template - _GLIBCXX20_CONSTEXPR - result_type - operator()(_Args&&... __args) - { - return this->__call<_Result>( - std::forward_as_tuple(std::forward<_Args>(__args)...), - _Bound_indexes()); - } - - // Call as const - template - _GLIBCXX20_CONSTEXPR - result_type - operator()(_Args&&... __args) const - { - return this->__call<_Result>( - std::forward_as_tuple(std::forward<_Args>(__args)...), - _Bound_indexes()); - } - - // Call as volatile - template - _GLIBCXX_DEPR_BIND - result_type - operator()(_Args&&... __args) volatile - { - return this->__call<_Result>( - std::forward_as_tuple(std::forward<_Args>(__args)...), - _Bound_indexes()); - } - - // Call as const volatile - template - _GLIBCXX_DEPR_BIND - result_type - operator()(_Args&&... __args) const volatile - { - return this->__call<_Result>( - std::forward_as_tuple(std::forward<_Args>(__args)...), - _Bound_indexes()); - } - }; -#undef _GLIBCXX_DEPR_BIND - - /** - * @brief Class template _Bind is always a bind expression. - * @ingroup binders - */ - template - struct is_bind_expression<_Bind<_Signature> > - : public true_type { }; - - /** - * @brief Class template _Bind is always a bind expression. - * @ingroup binders - */ - template - struct is_bind_expression > - : public true_type { }; - - /** - * @brief Class template _Bind is always a bind expression. - * @ingroup binders - */ - template - struct is_bind_expression > - : public true_type { }; - - /** - * @brief Class template _Bind is always a bind expression. - * @ingroup binders - */ - template - struct is_bind_expression> - : public true_type { }; - - /** - * @brief Class template _Bind_result is always a bind expression. - * @ingroup binders - */ - template - struct is_bind_expression<_Bind_result<_Result, _Signature>> - : public true_type { }; - - /** - * @brief Class template _Bind_result is always a bind expression. - * @ingroup binders - */ - template - struct is_bind_expression> - : public true_type { }; - - /** - * @brief Class template _Bind_result is always a bind expression. - * @ingroup binders - */ - template - struct is_bind_expression> - : public true_type { }; - - /** - * @brief Class template _Bind_result is always a bind expression. - * @ingroup binders - */ - template - struct is_bind_expression> - : public true_type { }; - - template - struct _Bind_check_arity { }; - - template - struct _Bind_check_arity<_Ret (*)(_Args...), _BoundArgs...> - { - static_assert(sizeof...(_BoundArgs) == sizeof...(_Args), - "Wrong number of arguments for function"); - }; - - template - struct _Bind_check_arity<_Ret (*)(_Args......), _BoundArgs...> - { - static_assert(sizeof...(_BoundArgs) >= sizeof...(_Args), - "Wrong number of arguments for function"); - }; - - template - struct _Bind_check_arity<_Tp _Class::*, _BoundArgs...> - { - using _Arity = typename _Mem_fn<_Tp _Class::*>::_Arity; - using _Varargs = typename _Mem_fn<_Tp _Class::*>::_Varargs; - static_assert(_Varargs::value - ? sizeof...(_BoundArgs) >= _Arity::value + 1 - : sizeof...(_BoundArgs) == _Arity::value + 1, - "Wrong number of arguments for pointer-to-member"); - }; - - // Trait type used to remove std::bind() from overload set via SFINAE - // when first argument has integer type, so that std::bind() will - // not be a better match than ::bind() from the BSD Sockets API. - template::type> - using __is_socketlike = __or_, is_enum<_Tp2>>; - - template - struct _Bind_helper - : _Bind_check_arity::type, _BoundArgs...> - { - typedef typename decay<_Func>::type __func_type; - typedef _Bind<__func_type(typename decay<_BoundArgs>::type...)> type; - }; - - // Partial specialization for is_socketlike == true, does not define - // nested type so std::bind() will not participate in overload resolution - // when the first argument might be a socket file descriptor. - template - struct _Bind_helper - { }; - - /** - * @brief Function template for std::bind. - * @ingroup binders - */ - template - inline _GLIBCXX20_CONSTEXPR typename - _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type - bind(_Func&& __f, _BoundArgs&&... __args) - { - typedef _Bind_helper __helper_type; - return typename __helper_type::type(std::forward<_Func>(__f), - std::forward<_BoundArgs>(__args)...); - } - - template - struct _Bindres_helper - : _Bind_check_arity::type, _BoundArgs...> - { - typedef typename decay<_Func>::type __functor_type; - typedef _Bind_result<_Result, - __functor_type(typename decay<_BoundArgs>::type...)> - type; - }; - - /** - * @brief Function template for std::bind. - * @ingroup binders - */ - template - inline _GLIBCXX20_CONSTEXPR - typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type - bind(_Func&& __f, _BoundArgs&&... __args) - { - typedef _Bindres_helper<_Result, _Func, _BoundArgs...> __helper_type; - return typename __helper_type::type(std::forward<_Func>(__f), - std::forward<_BoundArgs>(__args)...); - } - -#if __cplusplus > 201703L -#define __cpp_lib_bind_front 201907L - - template - struct _Bind_front - { - static_assert(is_move_constructible_v<_Fd>); - static_assert((is_move_constructible_v<_BoundArgs> && ...)); - - // First parameter is to ensure this constructor is never used - // instead of the copy/move constructor. - template - explicit constexpr - _Bind_front(int, _Fn&& __fn, _Args&&... __args) - noexcept(__and_, - is_nothrow_constructible<_BoundArgs, _Args>...>::value) - : _M_fd(std::forward<_Fn>(__fn)), - _M_bound_args(std::forward<_Args>(__args)...) - { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); } - - _Bind_front(const _Bind_front&) = default; - _Bind_front(_Bind_front&&) = default; - _Bind_front& operator=(const _Bind_front&) = default; - _Bind_front& operator=(_Bind_front&&) = default; - ~_Bind_front() = default; - - template - constexpr - invoke_result_t<_Fd&, _BoundArgs&..., _CallArgs...> - operator()(_CallArgs&&... __call_args) & - noexcept(is_nothrow_invocable_v<_Fd&, _BoundArgs&..., _CallArgs...>) - { - return _S_call(*this, _BoundIndices(), - std::forward<_CallArgs>(__call_args)...); - } - - template - constexpr - invoke_result_t - operator()(_CallArgs&&... __call_args) const & - noexcept(is_nothrow_invocable_v) - { - return _S_call(*this, _BoundIndices(), - std::forward<_CallArgs>(__call_args)...); - } - - template - constexpr - invoke_result_t<_Fd, _BoundArgs..., _CallArgs...> - operator()(_CallArgs&&... __call_args) && - noexcept(is_nothrow_invocable_v<_Fd, _BoundArgs..., _CallArgs...>) - { - return _S_call(std::move(*this), _BoundIndices(), - std::forward<_CallArgs>(__call_args)...); - } - - template - constexpr - invoke_result_t - operator()(_CallArgs&&... __call_args) const && - noexcept(is_nothrow_invocable_v) - { - return _S_call(std::move(*this), _BoundIndices(), - std::forward<_CallArgs>(__call_args)...); - } - - private: - using _BoundIndices = index_sequence_for<_BoundArgs...>; - - template - static constexpr - decltype(auto) - _S_call(_Tp&& __g, index_sequence<_Ind...>, _CallArgs&&... __call_args) - { - return std::invoke(std::forward<_Tp>(__g)._M_fd, - std::get<_Ind>(std::forward<_Tp>(__g)._M_bound_args)..., - std::forward<_CallArgs>(__call_args)...); - } - - _Fd _M_fd; - std::tuple<_BoundArgs...> _M_bound_args; - }; - - template - using _Bind_front_t - = _Bind_front, decay_t<_Args>...>; - - template - constexpr _Bind_front_t<_Fn, _Args...> - bind_front(_Fn&& __fn, _Args&&... __args) - noexcept(is_nothrow_constructible_v<_Bind_front_t<_Fn, _Args...>, - int, _Fn, _Args...>) - { - return _Bind_front_t<_Fn, _Args...>(0, std::forward<_Fn>(__fn), - std::forward<_Args>(__args)...); - } -#endif - -#if __cplusplus >= 201402L - /// Generalized negator. - template - class _Not_fn - { - template - using __inv_res_t = typename __invoke_result<_Fn2, _Args...>::type; - - template - static decltype(!std::declval<_Tp>()) - _S_not() noexcept(noexcept(!std::declval<_Tp>())); - - public: - template - constexpr - _Not_fn(_Fn2&& __fn, int) - : _M_fn(std::forward<_Fn2>(__fn)) { } - - _Not_fn(const _Not_fn& __fn) = default; - _Not_fn(_Not_fn&& __fn) = default; - ~_Not_fn() = default; - - // Macro to define operator() with given cv-qualifiers ref-qualifiers, - // forwarding _M_fn and the function arguments with the same qualifiers, - // and deducing the return type and exception-specification. -#define _GLIBCXX_NOT_FN_CALL_OP( _QUALS ) \ - template \ - _GLIBCXX20_CONSTEXPR \ - decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()) \ - operator()(_Args&&... __args) _QUALS \ - noexcept(__is_nothrow_invocable<_Fn _QUALS, _Args...>::value \ - && noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())) \ - { \ - return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn), \ - std::forward<_Args>(__args)...); \ - } - _GLIBCXX_NOT_FN_CALL_OP( & ) - _GLIBCXX_NOT_FN_CALL_OP( const & ) - _GLIBCXX_NOT_FN_CALL_OP( && ) - _GLIBCXX_NOT_FN_CALL_OP( const && ) -#undef _GLIBCXX_NOT_FN_CALL_OP - - private: - _Fn _M_fn; - }; - - template - struct __is_byte_like : false_type { }; - - template - struct __is_byte_like<_Tp, equal_to<_Tp>> - : __bool_constant::value> { }; - - template - struct __is_byte_like<_Tp, equal_to> - : __bool_constant::value> { }; - -#if __cplusplus >= 201703L - // Declare std::byte (full definition is in ). - enum class byte : unsigned char; - - template<> - struct __is_byte_like> - : true_type { }; - - template<> - struct __is_byte_like> - : true_type { }; - -#define __cpp_lib_not_fn 201603 - /// [func.not_fn] Function template not_fn - template - _GLIBCXX20_CONSTEXPR - inline auto - not_fn(_Fn&& __fn) - noexcept(std::is_nothrow_constructible, _Fn&&>::value) - { - return _Not_fn>{std::forward<_Fn>(__fn), 0}; - } - - // Searchers -#define __cpp_lib_boyer_moore_searcher 201603 - - template> - class default_searcher - { - public: - _GLIBCXX20_CONSTEXPR - default_searcher(_ForwardIterator1 __pat_first, - _ForwardIterator1 __pat_last, - _BinaryPredicate __pred = _BinaryPredicate()) - : _M_m(__pat_first, __pat_last, std::move(__pred)) - { } - - template - _GLIBCXX20_CONSTEXPR - pair<_ForwardIterator2, _ForwardIterator2> - operator()(_ForwardIterator2 __first, _ForwardIterator2 __last) const - { - _ForwardIterator2 __first_ret = - std::search(__first, __last, std::get<0>(_M_m), std::get<1>(_M_m), - std::get<2>(_M_m)); - auto __ret = std::make_pair(__first_ret, __first_ret); - if (__ret.first != __last) - std::advance(__ret.second, std::distance(std::get<0>(_M_m), - std::get<1>(_M_m))); - return __ret; - } - - private: - tuple<_ForwardIterator1, _ForwardIterator1, _BinaryPredicate> _M_m; - }; - - template - struct __boyer_moore_map_base - { - template - __boyer_moore_map_base(_RAIter __pat, size_t __patlen, - _Hash&& __hf, _Pred&& __pred) - : _M_bad_char{ __patlen, std::move(__hf), std::move(__pred) } - { - if (__patlen > 0) - for (__diff_type __i = 0; __i < __patlen - 1; ++__i) - _M_bad_char[__pat[__i]] = __patlen - 1 - __i; - } - - using __diff_type = _Tp; - - __diff_type - _M_lookup(_Key __key, __diff_type __not_found) const - { - auto __iter = _M_bad_char.find(__key); - if (__iter == _M_bad_char.end()) - return __not_found; - return __iter->second; - } - - _Pred - _M_pred() const { return _M_bad_char.key_eq(); } - - _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred> _M_bad_char; - }; - - template - struct __boyer_moore_array_base - { - template - __boyer_moore_array_base(_RAIter __pat, size_t __patlen, - _Unused&&, _Pred&& __pred) - : _M_bad_char{ _GLIBCXX_STD_C::array<_Tp, _Len>{}, std::move(__pred) } - { - std::get<0>(_M_bad_char).fill(__patlen); - if (__patlen > 0) - for (__diff_type __i = 0; __i < __patlen - 1; ++__i) - { - auto __ch = __pat[__i]; - using _UCh = make_unsigned_t; - auto __uch = static_cast<_UCh>(__ch); - std::get<0>(_M_bad_char)[__uch] = __patlen - 1 - __i; - } - } - - using __diff_type = _Tp; - - template - __diff_type - _M_lookup(_Key __key, __diff_type __not_found) const - { - auto __ukey = static_cast>(__key); - if (__ukey >= _Len) - return __not_found; - return std::get<0>(_M_bad_char)[__ukey]; - } - - const _Pred& - _M_pred() const { return std::get<1>(_M_bad_char); } - - tuple<_GLIBCXX_STD_C::array<_Tp, _Len>, _Pred> _M_bad_char; - }; - - // Use __boyer_moore_array_base when pattern consists of narrow characters - // (or std::byte) and uses std::equal_to as the predicate. - template::value_type, - typename _Diff = typename iterator_traits<_RAIter>::difference_type> - using __boyer_moore_base_t - = conditional_t<__is_byte_like<_Val, _Pred>::value, - __boyer_moore_array_base<_Diff, 256, _Pred>, - __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>; - - template::value_type>, - typename _BinaryPredicate = equal_to<>> - class boyer_moore_searcher - : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate> - { - using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>; - using typename _Base::__diff_type; - - public: - boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last, - _Hash __hf = _Hash(), - _BinaryPredicate __pred = _BinaryPredicate()); - - template - pair<_RandomAccessIterator2, _RandomAccessIterator2> - operator()(_RandomAccessIterator2 __first, - _RandomAccessIterator2 __last) const; - - private: - bool - _M_is_prefix(_RAIter __word, __diff_type __len, - __diff_type __pos) - { - const auto& __pred = this->_M_pred(); - __diff_type __suffixlen = __len - __pos; - for (__diff_type __i = 0; __i < __suffixlen; ++__i) - if (!__pred(__word[__i], __word[__pos + __i])) - return false; - return true; - } - - __diff_type - _M_suffix_length(_RAIter __word, __diff_type __len, - __diff_type __pos) - { - const auto& __pred = this->_M_pred(); - __diff_type __i = 0; - while (__pred(__word[__pos - __i], __word[__len - 1 - __i]) - && __i < __pos) - { - ++__i; - } - return __i; - } - - template - __diff_type - _M_bad_char_shift(_Tp __c) const - { return this->_M_lookup(__c, _M_pat_end - _M_pat); } - - _RAIter _M_pat; - _RAIter _M_pat_end; - _GLIBCXX_STD_C::vector<__diff_type> _M_good_suffix; - }; - - template::value_type>, - typename _BinaryPredicate = equal_to<>> - class boyer_moore_horspool_searcher - : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate> - { - using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>; - using typename _Base::__diff_type; - - public: - boyer_moore_horspool_searcher(_RAIter __pat, - _RAIter __pat_end, - _Hash __hf = _Hash(), - _BinaryPredicate __pred - = _BinaryPredicate()) - : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)), - _M_pat(__pat), _M_pat_end(__pat_end) - { } - - template - pair<_RandomAccessIterator2, _RandomAccessIterator2> - operator()(_RandomAccessIterator2 __first, - _RandomAccessIterator2 __last) const - { - const auto& __pred = this->_M_pred(); - auto __patlen = _M_pat_end - _M_pat; - if (__patlen == 0) - return std::make_pair(__first, __first); - auto __len = __last - __first; - while (__len >= __patlen) - { - for (auto __scan = __patlen - 1; - __pred(__first[__scan], _M_pat[__scan]); --__scan) - if (__scan == 0) - return std::make_pair(__first, __first + __patlen); - auto __shift = _M_bad_char_shift(__first[__patlen - 1]); - __len -= __shift; - __first += __shift; - } - return std::make_pair(__last, __last); - } - - private: - template - __diff_type - _M_bad_char_shift(_Tp __c) const - { return this->_M_lookup(__c, _M_pat_end - _M_pat); } - - _RAIter _M_pat; - _RAIter _M_pat_end; - }; - - template - boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>:: - boyer_moore_searcher(_RAIter __pat, _RAIter __pat_end, - _Hash __hf, _BinaryPredicate __pred) - : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)), - _M_pat(__pat), _M_pat_end(__pat_end), _M_good_suffix(__pat_end - __pat) - { - auto __patlen = __pat_end - __pat; - if (__patlen == 0) - return; - __diff_type __last_prefix = __patlen - 1; - for (__diff_type __p = __patlen - 1; __p >= 0; --__p) - { - if (_M_is_prefix(__pat, __patlen, __p + 1)) - __last_prefix = __p + 1; - _M_good_suffix[__p] = __last_prefix + (__patlen - 1 - __p); - } - for (__diff_type __p = 0; __p < __patlen - 1; ++__p) - { - auto __slen = _M_suffix_length(__pat, __patlen, __p); - auto __pos = __patlen - 1 - __slen; - if (!__pred(__pat[__p - __slen], __pat[__pos])) - _M_good_suffix[__pos] = __patlen - 1 - __p + __slen; - } - } - - template - template - pair<_RandomAccessIterator2, _RandomAccessIterator2> - boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>:: - operator()(_RandomAccessIterator2 __first, - _RandomAccessIterator2 __last) const - { - auto __patlen = _M_pat_end - _M_pat; - if (__patlen == 0) - return std::make_pair(__first, __first); - const auto& __pred = this->_M_pred(); - __diff_type __i = __patlen - 1; - auto __stringlen = __last - __first; - while (__i < __stringlen) - { - __diff_type __j = __patlen - 1; - while (__j >= 0 && __pred(__first[__i], _M_pat[__j])) - { - --__i; - --__j; - } - if (__j < 0) - { - const auto __match = __first + __i + 1; - return std::make_pair(__match, __match + __patlen); - } - __i += std::max(_M_bad_char_shift(__first[__i]), - _M_good_suffix[__j]); - } - return std::make_pair(__last, __last); - } - -#endif // C++17 -#endif // C++14 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++11 - -#endif // _GLIBCXX_FUNCTIONAL diff --git a/resources/sources/avr-libstdcpp/include/initializer_list b/resources/sources/avr-libstdcpp/include/initializer_list index 9f4859514..031640ecb 100644 --- a/resources/sources/avr-libstdcpp/include/initializer_list +++ b/resources/sources/avr-libstdcpp/include/initializer_list @@ -1,109 +1,25 @@ -// std::initializer_list support -*- C++ -*- - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of GCC. -// -// GCC is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3, or (at your option) -// any later version. -// -// GCC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file initializer_list - * This is a Standard C++ Library header. - */ - -#ifndef _INITIALIZER_LIST -#define _INITIALIZER_LIST - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else // C++0x - -#pragma GCC visibility push(default) - -#include - -namespace std -{ - /// initializer_list - template - class initializer_list - { - public: - typedef _E value_type; - typedef const _E& reference; - typedef const _E& const_reference; - typedef size_t size_type; - typedef const _E* iterator; - typedef const _E* const_iterator; - - private: - iterator _M_array; - size_type _M_len; - - // The compiler can call a private constructor. - constexpr initializer_list(const_iterator __a, size_type __l) - : _M_array(__a), _M_len(__l) { } - - public: - constexpr initializer_list() noexcept - : _M_array(0), _M_len(0) { } - - // Number of elements. - constexpr size_type - size() const noexcept { return _M_len; } - - // First element. - constexpr const_iterator - begin() const noexcept { return _M_array; } - - // One past the last element. - constexpr const_iterator - end() const noexcept { return begin() + size(); } - }; - - /** - * @brief Return an iterator pointing to the first element of - * the initializer_list. - * @param __ils Initializer list. - * @relates initializer_list - */ - template - constexpr const _Tp* - begin(initializer_list<_Tp> __ils) noexcept - { return __ils.begin(); } - - /** - * @brief Return an iterator pointing to one past the last element - * of the initializer_list. - * @param __ils Initializer list. - * @relates initializer_list - */ - template - constexpr const _Tp* - end(initializer_list<_Tp> __ils) noexcept - { return __ils.end(); } +// Minimal for AVR +// GCC has built-in support for initializer_list, this just provides the type. +#ifndef _AVR_INITIALIZER_LIST +#define _AVR_INITIALIZER_LIST + +namespace std { + template + class initializer_list { + const T* _begin; + size_t _size; + constexpr initializer_list(const T* b, size_t s) noexcept : _begin(b), _size(s) {} + public: + using value_type = T; + using reference = const T&; + using const_reference = const T&; + using size_type = size_t; + using iterator = const T*; + using const_iterator = const T*; + constexpr initializer_list() noexcept : _begin(nullptr), _size(0) {} + constexpr size_type size() const noexcept { return _size; } + constexpr const_iterator begin() const noexcept { return _begin; } + constexpr const_iterator end() const noexcept { return _begin + _size; } + }; } - -#pragma GCC visibility pop - -#endif // C++11 - -#endif // _INITIALIZER_LIST +#endif diff --git a/resources/sources/avr-libstdcpp/include/iterator b/resources/sources/avr-libstdcpp/include/iterator deleted file mode 100644 index fbc47e01e..000000000 --- a/resources/sources/avr-libstdcpp/include/iterator +++ /dev/null @@ -1,70 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/iterator - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_ITERATOR -#define _GLIBCXX_ITERATOR 1 - -#pragma GCC system_header - -#include -#include -#include -#include -#include - -#if __cplusplus >= 201402L && ! defined _GLIBCXX_DEBUG // PR libstdc++/70303 -# define __cpp_lib_null_iterators 201304L -#endif - -#endif /* _GLIBCXX_ITERATOR */ diff --git a/resources/sources/avr-libstdcpp/include/limits b/resources/sources/avr-libstdcpp/include/limits deleted file mode 100644 index 898406f91..000000000 --- a/resources/sources/avr-libstdcpp/include/limits +++ /dev/null @@ -1,1893 +0,0 @@ -// The template and inlines for the numeric_limits classes. -*- C++ -*- - -// Copyright (C) 1999-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/limits - * This is a Standard C++ Library header. - */ - -// Note: this is not a conforming implementation. -// Written by Gabriel Dos Reis - -// -// ISO 14882:1998 -// 18.2.1 -// - -#ifndef _GLIBCXX_NUMERIC_LIMITS -#define _GLIBCXX_NUMERIC_LIMITS 1 - -#pragma GCC system_header - -#include - -// -// The numeric_limits<> traits document implementation-defined aspects -// of fundamental arithmetic data types (integers and floating points). -// From Standard C++ point of view, there are 14 such types: -// * integers -// bool (1) -// char, signed char, unsigned char, wchar_t (4) -// short, unsigned short (2) -// int, unsigned (2) -// long, unsigned long (2) -// -// * floating points -// float (1) -// double (1) -// long double (1) -// -// GNU C++ understands (where supported by the host C-library) -// * integer -// long long, unsigned long long (2) -// -// which brings us to 16 fundamental arithmetic data types in GNU C++. -// -// -// Since a numeric_limits<> is a bit tricky to get right, we rely on -// an interface composed of macros which should be defined in config/os -// or config/cpu when they differ from the generic (read arbitrary) -// definitions given here. -// - -// These values can be overridden in the target configuration file. -// The default values are appropriate for many 32-bit targets. - -// GCC only intrinsically supports modulo integral types. The only remaining -// integral exceptional values is division by zero. Only targets that do not -// signal division by zero in some "hard to ignore" way should use false. -#ifndef __glibcxx_integral_traps -# define __glibcxx_integral_traps true -#endif - -// float -// - -// Default values. Should be overridden in configuration files if necessary. - -#ifndef __glibcxx_float_has_denorm_loss -# define __glibcxx_float_has_denorm_loss false -#endif -#ifndef __glibcxx_float_traps -# define __glibcxx_float_traps false -#endif -#ifndef __glibcxx_float_tinyness_before -# define __glibcxx_float_tinyness_before false -#endif - -// double - -// Default values. Should be overridden in configuration files if necessary. - -#ifndef __glibcxx_double_has_denorm_loss -# define __glibcxx_double_has_denorm_loss false -#endif -#ifndef __glibcxx_double_traps -# define __glibcxx_double_traps false -#endif -#ifndef __glibcxx_double_tinyness_before -# define __glibcxx_double_tinyness_before false -#endif - -// long double - -// Default values. Should be overridden in configuration files if necessary. - -#ifndef __glibcxx_long_double_has_denorm_loss -# define __glibcxx_long_double_has_denorm_loss false -#endif -#ifndef __glibcxx_long_double_traps -# define __glibcxx_long_double_traps false -#endif -#ifndef __glibcxx_long_double_tinyness_before -# define __glibcxx_long_double_tinyness_before false -#endif - -// You should not need to define any macros below this point. - -#define __glibcxx_signed_b(T,B) ((T)(-1) < 0) - -#define __glibcxx_min_b(T,B) \ - (__glibcxx_signed_b (T,B) ? -__glibcxx_max_b (T,B) - 1 : (T)0) - -#define __glibcxx_max_b(T,B) \ - (__glibcxx_signed_b (T,B) ? \ - (((((T)1 << (__glibcxx_digits_b (T,B) - 1)) - 1) << 1) + 1) : ~(T)0) - -#define __glibcxx_digits_b(T,B) \ - (B - __glibcxx_signed_b (T,B)) - -// The fraction 643/2136 approximates log10(2) to 7 significant digits. -#define __glibcxx_digits10_b(T,B) \ - (__glibcxx_digits_b (T,B) * 643L / 2136) - -#define __glibcxx_signed(T) \ - __glibcxx_signed_b (T, sizeof(T) * __CHAR_BIT__) -#define __glibcxx_min(T) \ - __glibcxx_min_b (T, sizeof(T) * __CHAR_BIT__) -#define __glibcxx_max(T) \ - __glibcxx_max_b (T, sizeof(T) * __CHAR_BIT__) -#define __glibcxx_digits(T) \ - __glibcxx_digits_b (T, sizeof(T) * __CHAR_BIT__) -#define __glibcxx_digits10(T) \ - __glibcxx_digits10_b (T, sizeof(T) * __CHAR_BIT__) - -#define __glibcxx_max_digits10(T) \ - (2 + (T) * 643L / 2136) - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @brief Describes the rounding style for floating-point types. - * - * This is used in the std::numeric_limits class. - */ - enum float_round_style - { - round_indeterminate = -1, /// Intermediate. - round_toward_zero = 0, /// To zero. - round_to_nearest = 1, /// To the nearest representable value. - round_toward_infinity = 2, /// To infinity. - round_toward_neg_infinity = 3 /// To negative infinity. - }; - - /** - * @brief Describes the denormalization for floating-point types. - * - * These values represent the presence or absence of a variable number - * of exponent bits. This type is used in the std::numeric_limits class. - */ - enum float_denorm_style - { - /// Indeterminate at compile time whether denormalized values are allowed. - denorm_indeterminate = -1, - /// The type does not allow denormalized values. - denorm_absent = 0, - /// The type allows denormalized values. - denorm_present = 1 - }; - - /** - * @brief Part of std::numeric_limits. - * - * The @c static @c const members are usable as integral constant - * expressions. - * - * @note This is a separate class for purposes of efficiency; you - * should only access these members as part of an instantiation - * of the std::numeric_limits class. - */ - struct __numeric_limits_base - { - /** This will be true for all fundamental types (which have - specializations), and false for everything else. */ - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = false; - - /** The number of @c radix digits that be represented without change: for - integer types, the number of non-sign bits in the mantissa; for - floating types, the number of @c radix digits in the mantissa. */ - static _GLIBCXX_USE_CONSTEXPR int digits = 0; - - /** The number of base 10 digits that can be represented without change. */ - static _GLIBCXX_USE_CONSTEXPR int digits10 = 0; - -#if __cplusplus >= 201103L - /** The number of base 10 digits required to ensure that values which - differ are always differentiated. */ - static constexpr int max_digits10 = 0; -#endif - - /** True if the type is signed. */ - static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; - - /** True if the type is integer. */ - static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; - - /** True if the type uses an exact representation. All integer types are - exact, but not all exact types are integer. For example, rational and - fixed-exponent representations are exact but not integer. */ - static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; - - /** For integer types, specifies the base of the representation. For - floating types, specifies the base of the exponent representation. */ - static _GLIBCXX_USE_CONSTEXPR int radix = 0; - - /** The minimum negative integer such that @c radix raised to the power of - (one less than that integer) is a normalized floating point number. */ - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - - /** The minimum negative integer such that 10 raised to that power is in - the range of normalized floating point numbers. */ - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - - /** The maximum positive integer such that @c radix raised to the power of - (one less than that integer) is a representable finite floating point - number. */ - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - - /** The maximum positive integer such that 10 raised to that power is in - the range of representable finite floating point numbers. */ - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - /** True if the type has a representation for positive infinity. */ - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - - /** True if the type has a representation for a quiet (non-signaling) - Not a Number. */ - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - - /** True if the type has a representation for a signaling - Not a Number. */ - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - - /** See std::float_denorm_style for more information. */ - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_absent; - - /** True if loss of accuracy is detected as a denormalization loss, - rather than as an inexact result. */ - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - /** True if-and-only-if the type adheres to the IEC 559 standard, also - known as IEEE 754. (Only makes sense for floating point types.) */ - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - - /** True if the set of values representable by the type is - finite. All built-in types are bounded, this member would be - false for arbitrary precision types. */ - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = false; - - /** True if the type is @e modulo. A type is modulo if, for any - operation involving +, -, or * on values of that type whose - result would fall outside the range [min(),max()], the value - returned differs from the true value by an integer multiple of - max() - min() + 1. On most machines, this is false for floating - types, true for unsigned integers, and true for signed integers. - See PR22200 about signed integers. */ - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - /** True if trapping is implemented for this type. */ - static _GLIBCXX_USE_CONSTEXPR bool traps = false; - - /** True if tininess is detected before rounding. (see IEC 559) */ - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - - /** See std::float_round_style for more information. This is only - meaningful for floating types; integer types will all be - round_toward_zero. */ - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = - round_toward_zero; - }; - - /** - * @brief Properties of fundamental types. - * - * This class allows a program to obtain information about the - * representation of a fundamental type on a given platform. For - * non-fundamental types, the functions will return 0 and the data - * members will all be @c false. - */ - template - struct numeric_limits : public __numeric_limits_base - { - /** The minimum finite value, or for floating types with - denormalization, the minimum positive normalized value. */ - static _GLIBCXX_CONSTEXPR _Tp - min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - - /** The maximum finite value. */ - static _GLIBCXX_CONSTEXPR _Tp - max() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - -#if __cplusplus >= 201103L - /** A finite value x such that there is no other finite value y - * where y < x. */ - static constexpr _Tp - lowest() noexcept { return _Tp(); } -#endif - - /** The @e machine @e epsilon: the difference between 1 and the least - value greater than 1 that is representable. */ - static _GLIBCXX_CONSTEXPR _Tp - epsilon() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - - /** The maximum rounding error measurement (see LIA-1). */ - static _GLIBCXX_CONSTEXPR _Tp - round_error() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - - /** The representation of positive infinity, if @c has_infinity. */ - static _GLIBCXX_CONSTEXPR _Tp - infinity() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - - /** The representation of a quiet Not a Number, - if @c has_quiet_NaN. */ - static _GLIBCXX_CONSTEXPR _Tp - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - - /** The representation of a signaling Not a Number, if - @c has_signaling_NaN. */ - static _GLIBCXX_CONSTEXPR _Tp - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - - /** The minimum positive denormalized value. For types where - @c has_denorm is false, this is the minimum positive normalized - value. */ - static _GLIBCXX_CONSTEXPR _Tp - denorm_min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } - }; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 559. numeric_limits - - template - struct numeric_limits - : public numeric_limits<_Tp> { }; - - template - struct numeric_limits - : public numeric_limits<_Tp> { }; - - template - struct numeric_limits - : public numeric_limits<_Tp> { }; - - // Now there follow 16 explicit specializations. Yes, 16. Make sure - // you get the count right. (18 in C++11 mode, with char16_t and char32_t.) - // (+1 if char8_t is enabled.) - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 184. numeric_limits wording problems - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR bool - min() _GLIBCXX_USE_NOEXCEPT { return false; } - - static _GLIBCXX_CONSTEXPR bool - max() _GLIBCXX_USE_NOEXCEPT { return true; } - -#if __cplusplus >= 201103L - static constexpr bool - lowest() noexcept { return min(); } -#endif - static _GLIBCXX_USE_CONSTEXPR int digits = 1; - static _GLIBCXX_USE_CONSTEXPR int digits10 = 0; -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR bool - epsilon() _GLIBCXX_USE_NOEXCEPT { return false; } - - static _GLIBCXX_CONSTEXPR bool - round_error() _GLIBCXX_USE_NOEXCEPT { return false; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR bool - infinity() _GLIBCXX_USE_NOEXCEPT { return false; } - - static _GLIBCXX_CONSTEXPR bool - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return false; } - - static _GLIBCXX_CONSTEXPR bool - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return false; } - - static _GLIBCXX_CONSTEXPR bool - denorm_min() _GLIBCXX_USE_NOEXCEPT { return false; } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - // It is not clear what it means for a boolean type to trap. - // This is a DR on the LWG issue list. Here, I use integer - // promotion semantics. - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR char - min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min(char); } - - static _GLIBCXX_CONSTEXPR char - max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max(char); } - -#if __cplusplus >= 201103L - static constexpr char - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char); - static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char); - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR char - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR char - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR - char infinity() _GLIBCXX_USE_NOEXCEPT { return char(); } - - static _GLIBCXX_CONSTEXPR char - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char(); } - - static _GLIBCXX_CONSTEXPR char - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char(); } - - static _GLIBCXX_CONSTEXPR char - denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR signed char - min() _GLIBCXX_USE_NOEXCEPT { return -__SCHAR_MAX__ - 1; } - - static _GLIBCXX_CONSTEXPR signed char - max() _GLIBCXX_USE_NOEXCEPT { return __SCHAR_MAX__; } - -#if __cplusplus >= 201103L - static constexpr signed char - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (signed char); - static _GLIBCXX_USE_CONSTEXPR int digits10 - = __glibcxx_digits10 (signed char); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR signed char - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR signed char - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR signed char - infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR signed char - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR signed char - signaling_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR signed char - denorm_min() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR unsigned char - min() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned char - max() _GLIBCXX_USE_NOEXCEPT { return __SCHAR_MAX__ * 2U + 1; } - -#if __cplusplus >= 201103L - static constexpr unsigned char - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits - = __glibcxx_digits (unsigned char); - static _GLIBCXX_USE_CONSTEXPR int digits10 - = __glibcxx_digits10 (unsigned char); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR unsigned char - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned char - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR unsigned char - infinity() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned char - quiet_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned char - signaling_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned char - denorm_min() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR wchar_t - min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (wchar_t); } - - static _GLIBCXX_CONSTEXPR wchar_t - max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (wchar_t); } - -#if __cplusplus >= 201103L - static constexpr wchar_t - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (wchar_t); - static _GLIBCXX_USE_CONSTEXPR int digits10 - = __glibcxx_digits10 (wchar_t); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (wchar_t); - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR wchar_t - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR wchar_t - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR wchar_t - infinity() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } - - static _GLIBCXX_CONSTEXPR wchar_t - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } - - static _GLIBCXX_CONSTEXPR wchar_t - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } - - static _GLIBCXX_CONSTEXPR wchar_t - denorm_min() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - -#if _GLIBCXX_USE_CHAR8_T - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR char8_t - min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (char8_t); } - - static _GLIBCXX_CONSTEXPR char8_t - max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (char8_t); } - - static _GLIBCXX_CONSTEXPR char8_t - lowest() _GLIBCXX_USE_NOEXCEPT { return min(); } - - static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char8_t); - static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char8_t); - static _GLIBCXX_USE_CONSTEXPR int max_digits10 = 0; - static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char8_t); - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR char8_t - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR char8_t - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR char8_t - infinity() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } - - static _GLIBCXX_CONSTEXPR char8_t - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } - - static _GLIBCXX_CONSTEXPR char8_t - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } - - static _GLIBCXX_CONSTEXPR char8_t - denorm_min() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; -#endif - -#if __cplusplus >= 201103L - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static constexpr bool is_specialized = true; - - static constexpr char16_t - min() noexcept { return __glibcxx_min (char16_t); } - - static constexpr char16_t - max() noexcept { return __glibcxx_max (char16_t); } - - static constexpr char16_t - lowest() noexcept { return min(); } - - static constexpr int digits = __glibcxx_digits (char16_t); - static constexpr int digits10 = __glibcxx_digits10 (char16_t); - static constexpr int max_digits10 = 0; - static constexpr bool is_signed = __glibcxx_signed (char16_t); - static constexpr bool is_integer = true; - static constexpr bool is_exact = true; - static constexpr int radix = 2; - - static constexpr char16_t - epsilon() noexcept { return 0; } - - static constexpr char16_t - round_error() noexcept { return 0; } - - static constexpr int min_exponent = 0; - static constexpr int min_exponent10 = 0; - static constexpr int max_exponent = 0; - static constexpr int max_exponent10 = 0; - - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = false; - static constexpr bool has_signaling_NaN = false; - static constexpr float_denorm_style has_denorm = denorm_absent; - static constexpr bool has_denorm_loss = false; - - static constexpr char16_t - infinity() noexcept { return char16_t(); } - - static constexpr char16_t - quiet_NaN() noexcept { return char16_t(); } - - static constexpr char16_t - signaling_NaN() noexcept { return char16_t(); } - - static constexpr char16_t - denorm_min() noexcept { return char16_t(); } - - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = !is_signed; - - static constexpr bool traps = __glibcxx_integral_traps; - static constexpr bool tinyness_before = false; - static constexpr float_round_style round_style = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static constexpr bool is_specialized = true; - - static constexpr char32_t - min() noexcept { return __glibcxx_min (char32_t); } - - static constexpr char32_t - max() noexcept { return __glibcxx_max (char32_t); } - - static constexpr char32_t - lowest() noexcept { return min(); } - - static constexpr int digits = __glibcxx_digits (char32_t); - static constexpr int digits10 = __glibcxx_digits10 (char32_t); - static constexpr int max_digits10 = 0; - static constexpr bool is_signed = __glibcxx_signed (char32_t); - static constexpr bool is_integer = true; - static constexpr bool is_exact = true; - static constexpr int radix = 2; - - static constexpr char32_t - epsilon() noexcept { return 0; } - - static constexpr char32_t - round_error() noexcept { return 0; } - - static constexpr int min_exponent = 0; - static constexpr int min_exponent10 = 0; - static constexpr int max_exponent = 0; - static constexpr int max_exponent10 = 0; - - static constexpr bool has_infinity = false; - static constexpr bool has_quiet_NaN = false; - static constexpr bool has_signaling_NaN = false; - static constexpr float_denorm_style has_denorm = denorm_absent; - static constexpr bool has_denorm_loss = false; - - static constexpr char32_t - infinity() noexcept { return char32_t(); } - - static constexpr char32_t - quiet_NaN() noexcept { return char32_t(); } - - static constexpr char32_t - signaling_NaN() noexcept { return char32_t(); } - - static constexpr char32_t - denorm_min() noexcept { return char32_t(); } - - static constexpr bool is_iec559 = false; - static constexpr bool is_bounded = true; - static constexpr bool is_modulo = !is_signed; - - static constexpr bool traps = __glibcxx_integral_traps; - static constexpr bool tinyness_before = false; - static constexpr float_round_style round_style = round_toward_zero; - }; -#endif - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR short - min() _GLIBCXX_USE_NOEXCEPT { return -__SHRT_MAX__ - 1; } - - static _GLIBCXX_CONSTEXPR short - max() _GLIBCXX_USE_NOEXCEPT { return __SHRT_MAX__; } - -#if __cplusplus >= 201103L - static constexpr short - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (short); - static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (short); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR short - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR short - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR short - infinity() _GLIBCXX_USE_NOEXCEPT { return short(); } - - static _GLIBCXX_CONSTEXPR short - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return short(); } - - static _GLIBCXX_CONSTEXPR short - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return short(); } - - static _GLIBCXX_CONSTEXPR short - denorm_min() _GLIBCXX_USE_NOEXCEPT { return short(); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR unsigned short - min() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned short - max() _GLIBCXX_USE_NOEXCEPT { return __SHRT_MAX__ * 2U + 1; } - -#if __cplusplus >= 201103L - static constexpr unsigned short - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits - = __glibcxx_digits (unsigned short); - static _GLIBCXX_USE_CONSTEXPR int digits10 - = __glibcxx_digits10 (unsigned short); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR unsigned short - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned short - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR unsigned short - infinity() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned short - quiet_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned short - signaling_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned short - denorm_min() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR int - min() _GLIBCXX_USE_NOEXCEPT { return -__INT_MAX__ - 1; } - - static _GLIBCXX_CONSTEXPR int - max() _GLIBCXX_USE_NOEXCEPT { return __INT_MAX__; } - -#if __cplusplus >= 201103L - static constexpr int - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (int); - static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (int); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR int - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR int - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR int - infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR int - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR int - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR int - denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR unsigned int - min() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned int - max() _GLIBCXX_USE_NOEXCEPT { return __INT_MAX__ * 2U + 1; } - -#if __cplusplus >= 201103L - static constexpr unsigned int - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits - = __glibcxx_digits (unsigned int); - static _GLIBCXX_USE_CONSTEXPR int digits10 - = __glibcxx_digits10 (unsigned int); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR unsigned int - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned int - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR unsigned int - infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned int - quiet_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned int - signaling_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned int - denorm_min() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR long - min() _GLIBCXX_USE_NOEXCEPT { return -__LONG_MAX__ - 1; } - - static _GLIBCXX_CONSTEXPR long - max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__; } - -#if __cplusplus >= 201103L - static constexpr long - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (long); - static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (long); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR long - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR long - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR long - infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR long - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR long - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR long - denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR unsigned long - min() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned long - max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__ * 2UL + 1; } - -#if __cplusplus >= 201103L - static constexpr unsigned long - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits - = __glibcxx_digits (unsigned long); - static _GLIBCXX_USE_CONSTEXPR int digits10 - = __glibcxx_digits10 (unsigned long); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR unsigned long - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned long - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR unsigned long - infinity() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned long - quiet_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned long - signaling_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned long - denorm_min() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR long long - min() _GLIBCXX_USE_NOEXCEPT { return -__LONG_LONG_MAX__ - 1; } - - static _GLIBCXX_CONSTEXPR long long - max() _GLIBCXX_USE_NOEXCEPT { return __LONG_LONG_MAX__; } - -#if __cplusplus >= 201103L - static constexpr long long - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits - = __glibcxx_digits (long long); - static _GLIBCXX_USE_CONSTEXPR int digits10 - = __glibcxx_digits10 (long long); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR long long - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR long long - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR long long - infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR long long - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR long long - signaling_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR long long - denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR unsigned long long - min() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned long long - max() _GLIBCXX_USE_NOEXCEPT { return __LONG_LONG_MAX__ * 2ULL + 1; } - -#if __cplusplus >= 201103L - static constexpr unsigned long long - lowest() noexcept { return min(); } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits - = __glibcxx_digits (unsigned long long); - static _GLIBCXX_USE_CONSTEXPR int digits10 - = __glibcxx_digits10 (unsigned long long); -#if __cplusplus >= 201103L - static constexpr int max_digits10 = 0; -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; - static _GLIBCXX_USE_CONSTEXPR int radix = 2; - - static _GLIBCXX_CONSTEXPR unsigned long long - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_CONSTEXPR unsigned long long - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; - - static _GLIBCXX_CONSTEXPR unsigned long long - infinity() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned long long - quiet_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned long long - signaling_NaN() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_CONSTEXPR unsigned long long - denorm_min() _GLIBCXX_USE_NOEXCEPT - { return static_cast(0); } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_toward_zero; - }; - -#if !defined(__STRICT_ANSI__) - -#define __INT_N(TYPE, BITSIZE, EXT, UEXT) \ - template<> \ - struct numeric_limits \ - { \ - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ - \ - static _GLIBCXX_CONSTEXPR TYPE \ - min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min_b (TYPE, BITSIZE); } \ - \ - static _GLIBCXX_CONSTEXPR TYPE \ - max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max_b (TYPE, BITSIZE); } \ - \ - static _GLIBCXX_USE_CONSTEXPR int digits \ - = BITSIZE - 1; \ - static _GLIBCXX_USE_CONSTEXPR int digits10 \ - = (BITSIZE - 1) * 643L / 2136; \ - \ - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; \ - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; \ - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; \ - static _GLIBCXX_USE_CONSTEXPR int radix = 2; \ - \ - static _GLIBCXX_CONSTEXPR TYPE \ - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } \ - \ - static _GLIBCXX_CONSTEXPR TYPE \ - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } \ - \ - EXT \ - \ - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; \ - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; \ - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; \ - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; \ - \ - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; \ - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; \ - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; \ - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ - = denorm_absent; \ - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ - \ - static _GLIBCXX_CONSTEXPR TYPE \ - infinity() _GLIBCXX_USE_NOEXCEPT \ - { return static_cast(0); } \ - \ - static _GLIBCXX_CONSTEXPR TYPE \ - quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ - { return static_cast(0); } \ - \ - static _GLIBCXX_CONSTEXPR TYPE \ - signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ - { return static_cast(0); } \ - \ - static _GLIBCXX_CONSTEXPR TYPE \ - denorm_min() _GLIBCXX_USE_NOEXCEPT \ - { return static_cast(0); } \ - \ - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; \ - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; \ - \ - static _GLIBCXX_USE_CONSTEXPR bool traps \ - = __glibcxx_integral_traps; \ - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ - = round_toward_zero; \ - }; \ - \ - template<> \ - struct numeric_limits \ - { \ - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ - \ - static _GLIBCXX_CONSTEXPR unsigned TYPE \ - min() _GLIBCXX_USE_NOEXCEPT { return 0; } \ - \ - static _GLIBCXX_CONSTEXPR unsigned TYPE \ - max() _GLIBCXX_USE_NOEXCEPT \ - { return __glibcxx_max_b (unsigned TYPE, BITSIZE); } \ - \ - UEXT \ - \ - static _GLIBCXX_USE_CONSTEXPR int digits \ - = BITSIZE; \ - static _GLIBCXX_USE_CONSTEXPR int digits10 \ - = BITSIZE * 643L / 2136; \ - static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; \ - static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; \ - static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; \ - static _GLIBCXX_USE_CONSTEXPR int radix = 2; \ - \ - static _GLIBCXX_CONSTEXPR unsigned TYPE \ - epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } \ - \ - static _GLIBCXX_CONSTEXPR unsigned TYPE \ - round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } \ - \ - static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; \ - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; \ - static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; \ - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; \ - \ - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; \ - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; \ - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; \ - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ - = denorm_absent; \ - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ - \ - static _GLIBCXX_CONSTEXPR unsigned TYPE \ - infinity() _GLIBCXX_USE_NOEXCEPT \ - { return static_cast(0); } \ - \ - static _GLIBCXX_CONSTEXPR unsigned TYPE \ - quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ - { return static_cast(0); } \ - \ - static _GLIBCXX_CONSTEXPR unsigned TYPE \ - signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ - { return static_cast(0); } \ - \ - static _GLIBCXX_CONSTEXPR unsigned TYPE \ - denorm_min() _GLIBCXX_USE_NOEXCEPT \ - { return static_cast(0); } \ - \ - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; \ - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; \ - \ - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; \ - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ - = round_toward_zero; \ - }; - -#if __cplusplus >= 201103L - -#define __INT_N_201103(TYPE) \ - static constexpr TYPE \ - lowest() noexcept { return min(); } \ - static constexpr int max_digits10 = 0; - -#define __INT_N_U201103(TYPE) \ - static constexpr unsigned TYPE \ - lowest() noexcept { return min(); } \ - static constexpr int max_digits10 = 0; - -#else -#define __INT_N_201103(TYPE) -#define __INT_N_U201103(TYPE) -#endif - -#ifdef __GLIBCXX_TYPE_INT_N_0 - __INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0, - __INT_N_201103 (__GLIBCXX_TYPE_INT_N_0), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_0)) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_1 - __INT_N (__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1, - __INT_N_201103 (__GLIBCXX_TYPE_INT_N_1), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_1)) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_2 - __INT_N (__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2, - __INT_N_201103 (__GLIBCXX_TYPE_INT_N_2), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_2)) -#endif -#ifdef __GLIBCXX_TYPE_INT_N_3 - __INT_N (__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3, - __INT_N_201103 (__GLIBCXX_TYPE_INT_N_3), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3)) -#endif - -#undef __INT_N -#undef __INT_N_201103 -#undef __INT_N_U201103 - -#endif - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR float - min() _GLIBCXX_USE_NOEXCEPT { return __FLT_MIN__; } - - static _GLIBCXX_CONSTEXPR float - max() _GLIBCXX_USE_NOEXCEPT { return __FLT_MAX__; } - -#if __cplusplus >= 201103L - static constexpr float - lowest() noexcept { return -__FLT_MAX__; } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __FLT_MANT_DIG__; - static _GLIBCXX_USE_CONSTEXPR int digits10 = __FLT_DIG__; -#if __cplusplus >= 201103L - static constexpr int max_digits10 - = __glibcxx_max_digits10 (__FLT_MANT_DIG__); -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; - static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; - - static _GLIBCXX_CONSTEXPR float - epsilon() _GLIBCXX_USE_NOEXCEPT { return __FLT_EPSILON__; } - - static _GLIBCXX_CONSTEXPR float - round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5F; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = __FLT_MIN_EXP__; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __FLT_MIN_10_EXP__; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = __FLT_MAX_EXP__; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __FLT_MAX_10_EXP__; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __FLT_HAS_INFINITY__; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __FLT_HAS_QUIET_NAN__; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = bool(__FLT_HAS_DENORM__) ? denorm_present : denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss - = __glibcxx_float_has_denorm_loss; - - static _GLIBCXX_CONSTEXPR float - infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_valf(); } - - static _GLIBCXX_CONSTEXPR float - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nanf(""); } - - static _GLIBCXX_CONSTEXPR float - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nansf(""); } - - static _GLIBCXX_CONSTEXPR float - denorm_min() _GLIBCXX_USE_NOEXCEPT { return __FLT_DENORM_MIN__; } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 - = has_infinity && has_quiet_NaN && has_denorm == denorm_present; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_float_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before - = __glibcxx_float_tinyness_before; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_to_nearest; - }; - -#undef __glibcxx_float_has_denorm_loss -#undef __glibcxx_float_traps -#undef __glibcxx_float_tinyness_before - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR double - min() _GLIBCXX_USE_NOEXCEPT { return __DBL_MIN__; } - - static _GLIBCXX_CONSTEXPR double - max() _GLIBCXX_USE_NOEXCEPT { return __DBL_MAX__; } - -#if __cplusplus >= 201103L - static constexpr double - lowest() noexcept { return -__DBL_MAX__; } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __DBL_MANT_DIG__; - static _GLIBCXX_USE_CONSTEXPR int digits10 = __DBL_DIG__; -#if __cplusplus >= 201103L - static constexpr int max_digits10 - = __glibcxx_max_digits10 (__DBL_MANT_DIG__); -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; - static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; - - static _GLIBCXX_CONSTEXPR double - epsilon() _GLIBCXX_USE_NOEXCEPT { return __DBL_EPSILON__; } - - static _GLIBCXX_CONSTEXPR double - round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = __DBL_MIN_EXP__; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __DBL_MIN_10_EXP__; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = __DBL_MAX_EXP__; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __DBL_MAX_10_EXP__; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __DBL_HAS_INFINITY__; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = bool(__DBL_HAS_DENORM__) ? denorm_present : denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss - = __glibcxx_double_has_denorm_loss; - - static _GLIBCXX_CONSTEXPR double - infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_val(); } - - static _GLIBCXX_CONSTEXPR double - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nan(""); } - - static _GLIBCXX_CONSTEXPR double - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nans(""); } - - static _GLIBCXX_CONSTEXPR double - denorm_min() _GLIBCXX_USE_NOEXCEPT { return __DBL_DENORM_MIN__; } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 - = has_infinity && has_quiet_NaN && has_denorm == denorm_present; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_double_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before - = __glibcxx_double_tinyness_before; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style - = round_to_nearest; - }; - -#undef __glibcxx_double_has_denorm_loss -#undef __glibcxx_double_traps -#undef __glibcxx_double_tinyness_before - - /// numeric_limits specialization. - template<> - struct numeric_limits - { - static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; - - static _GLIBCXX_CONSTEXPR long double - min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_MIN__; } - - static _GLIBCXX_CONSTEXPR long double - max() _GLIBCXX_USE_NOEXCEPT { return __LDBL_MAX__; } - -#if __cplusplus >= 201103L - static constexpr long double - lowest() noexcept { return -__LDBL_MAX__; } -#endif - - static _GLIBCXX_USE_CONSTEXPR int digits = __LDBL_MANT_DIG__; - static _GLIBCXX_USE_CONSTEXPR int digits10 = __LDBL_DIG__; -#if __cplusplus >= 201103L - static _GLIBCXX_USE_CONSTEXPR int max_digits10 - = __glibcxx_max_digits10 (__LDBL_MANT_DIG__); -#endif - static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; - static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; - static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; - static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; - - static _GLIBCXX_CONSTEXPR long double - epsilon() _GLIBCXX_USE_NOEXCEPT { return __LDBL_EPSILON__; } - - static _GLIBCXX_CONSTEXPR long double - round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5L; } - - static _GLIBCXX_USE_CONSTEXPR int min_exponent = __LDBL_MIN_EXP__; - static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __LDBL_MIN_10_EXP__; - static _GLIBCXX_USE_CONSTEXPR int max_exponent = __LDBL_MAX_EXP__; - static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __LDBL_MAX_10_EXP__; - - static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __LDBL_HAS_INFINITY__; - static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __LDBL_HAS_QUIET_NAN__; - static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; - static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm - = bool(__LDBL_HAS_DENORM__) ? denorm_present : denorm_absent; - static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss - = __glibcxx_long_double_has_denorm_loss; - - static _GLIBCXX_CONSTEXPR long double - infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_vall(); } - - static _GLIBCXX_CONSTEXPR long double - quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nanl(""); } - - static _GLIBCXX_CONSTEXPR long double - signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nansl(""); } - - static _GLIBCXX_CONSTEXPR long double - denorm_min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_DENORM_MIN__; } - - static _GLIBCXX_USE_CONSTEXPR bool is_iec559 - = has_infinity && has_quiet_NaN && has_denorm == denorm_present; - static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; - static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; - - static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_long_double_traps; - static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = - __glibcxx_long_double_tinyness_before; - static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = - round_to_nearest; - }; - -#undef __glibcxx_long_double_has_denorm_loss -#undef __glibcxx_long_double_traps -#undef __glibcxx_long_double_tinyness_before - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#undef __glibcxx_signed -#undef __glibcxx_min -#undef __glibcxx_max -#undef __glibcxx_digits -#undef __glibcxx_digits10 -#undef __glibcxx_max_digits10 - -#endif // _GLIBCXX_NUMERIC_LIMITS diff --git a/resources/sources/avr-libstdcpp/include/list b/resources/sources/avr-libstdcpp/include/list deleted file mode 100644 index 7b3d3c2e8..000000000 --- a/resources/sources/avr-libstdcpp/include/list +++ /dev/null @@ -1,109 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/list - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_LIST -#define _GLIBCXX_LIST 1 - -#pragma GCC system_header - -#include -#include -#include -#include -#include - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#if __cplusplus >= 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace pmr - { - template class polymorphic_allocator; - template - using list = std::list<_Tp, polymorphic_allocator<_Tp>>; - } // namespace pmr -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 - -#if __cplusplus > 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#define __cpp_lib_erase_if 202002L - - template - inline typename list<_Tp, _Alloc>::size_type - erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred) - { return __cont.remove_if(__pred); } - - template - inline typename list<_Tp, _Alloc>::size_type - erase(list<_Tp, _Alloc>& __cont, const _Up& __value) - { - using __elem_type = typename list<_Tp, _Alloc>::value_type; - return std::erase_if(__cont, [&](__elem_type& __elem) { - return __elem == __value; - }); - } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 - -#endif /* _GLIBCXX_LIST */ diff --git a/resources/sources/avr-libstdcpp/include/map b/resources/sources/avr-libstdcpp/include/map deleted file mode 100644 index 9e8f76b48..000000000 --- a/resources/sources/avr-libstdcpp/include/map +++ /dev/null @@ -1,109 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/map - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_MAP -#define _GLIBCXX_MAP 1 - -#pragma GCC system_header - -#include -#include -#include -#include -#include - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#if __cplusplus >= 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace pmr - { - template class polymorphic_allocator; - template> - using map - = std::map<_Key, _Tp, _Cmp, - polymorphic_allocator>>; - template> - using multimap - = std::multimap<_Key, _Tp, _Cmp, - polymorphic_allocator>>; - } // namespace pmr -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 - -#if __cplusplus > 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - template - inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type - erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) - { return __detail::__erase_nodes_if(__cont, __pred); } - - template - inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type - erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) - { return __detail::__erase_nodes_if(__cont, __pred); } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 - -#endif /* _GLIBCXX_MAP */ diff --git a/resources/sources/avr-libstdcpp/include/memory b/resources/sources/avr-libstdcpp/include/memory deleted file mode 100644 index 0ed1a86b5..000000000 --- a/resources/sources/avr-libstdcpp/include/memory +++ /dev/null @@ -1,404 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * Copyright (c) 1997-1999 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - */ - -/** @file include/memory - * This is a Standard C++ Library header. - * @ingroup memory - */ - -#ifndef _GLIBCXX_MEMORY -#define _GLIBCXX_MEMORY 1 - -#pragma GCC system_header - -/** - * @defgroup memory Memory - * @ingroup utilities - * - * Components for memory allocation, deallocation, and management. - */ - -/** - * @defgroup pointer_abstractions Pointer Abstractions - * @ingroup memory - * - * Smart pointers, etc. - */ - -#include -#include -#include -#include -#include -#include -#include - -#if __cplusplus >= 201103L -# include -# include -# include // std::less -# include -# include -# include -# include -# include -#endif - -#if __cplusplus >= 201103L -#include -#if __cplusplus > 201703L -# include // for has_single_bit -# include // for placement operator new -# include // for tuple, make_tuple, make_from_tuple -#endif -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -/** - * @brief Fit aligned storage in buffer. - * @ingroup memory - * - * This function tries to fit @a __size bytes of storage with alignment - * @a __align into the buffer @a __ptr of size @a __space bytes. If such - * a buffer fits then @a __ptr is changed to point to the first byte of the - * aligned storage and @a __space is reduced by the bytes used for alignment. - * - * C++11 20.6.5 [ptr.align] - * - * @param __align A fundamental or extended alignment value. - * @param __size Size of the aligned storage required. - * @param __ptr Pointer to a buffer of @a __space bytes. - * @param __space Size of the buffer pointed to by @a __ptr. - * @return the updated pointer if the aligned storage fits, otherwise nullptr. - * - */ -inline void* -align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept -{ -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - const auto __intptr = reinterpret_cast(__ptr); -#else - // Cannot use std::uintptr_t so assume that std::size_t can be used instead. - static_assert(sizeof(size_t) >= sizeof(void*), - "std::size_t must be a suitable substitute for std::uintptr_t"); - const auto __intptr = reinterpret_cast(__ptr); -#endif - const auto __aligned = (__intptr - 1u + __align) & -__align; - const auto __diff = __aligned - __intptr; - if ((__size + __diff) > __space) - return nullptr; - else - { - __space -= __diff; - return __ptr = reinterpret_cast(__aligned); - } -} - -/** @defgroup ptr_safety Pointer Safety and Garbage Collection - * @ingroup memory - * - * Utilities to assist with garbage collection in an implementation - * that supports strict pointer safety. - * This implementation only supports relaxed pointer safety - * and so these functions have no effect. - * - * C++11 20.6.4 [util.dynamic.safety], Pointer safety - * - * @{ - */ - -/// Constants representing the different types of pointer safety. -enum class pointer_safety { relaxed, preferred, strict }; - -/// Inform a garbage collector that an object is still in use. -inline void -declare_reachable(void*) { } - -/// Unregister an object previously registered with declare_reachable. -template - inline _Tp* - undeclare_reachable(_Tp* __p) { return __p; } - -/// Inform a garbage collector that a region of memory need not be traced. -inline void -declare_no_pointers(char*, size_t) { } - -/// Unregister a range previously registered with declare_no_pointers. -inline void -undeclare_no_pointers(char*, size_t) { } - -/// The type of pointer safety supported by the implementation. -inline pointer_safety -get_pointer_safety() noexcept { return pointer_safety::relaxed; } -// @} - -#if __cplusplus > 201703L -#define __cpp_lib_assume_aligned 201811L - /** @brief Inform the compiler that a pointer is aligned. - * - * @tparam _Align An alignment value (i.e. a power of two) - * @tparam _Tp An object type - * @param __ptr A pointer that is aligned to _Align - * - * C++20 20.10.6 [ptr.align] - * - * @ingroup memory - */ - template - [[nodiscard,__gnu__::__always_inline__]] - constexpr _Tp* - assume_aligned(_Tp* __ptr) noexcept - { - static_assert(std::has_single_bit(_Align)); - if (std::is_constant_evaluated()) - return __ptr; - else - { - // This function is expected to be used in hot code, where - // __glibcxx_assert would add unwanted overhead. - _GLIBCXX_DEBUG_ASSERT((std::uintptr_t)__ptr % _Align == 0); - return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align)); - } - } -#endif // C++2a - -#if __cplusplus > 201703L - template - struct __is_pair : false_type { }; - template - struct __is_pair> : true_type { }; - template - struct __is_pair> : true_type { }; - -/** @addtogroup allocators - * @{ - */ - template>>, - typename _Alloc, typename... _Args> - constexpr auto - __uses_alloc_args(const _Alloc& __a, _Args&&... __args) noexcept - { - if constexpr (uses_allocator_v, _Alloc>) - { - if constexpr (is_constructible_v<_Tp, allocator_arg_t, - const _Alloc&, _Args...>) - { - return tuple( - allocator_arg, __a, std::forward<_Args>(__args)...); - } - else - { - static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>, - "construction with an allocator must be possible" - " if uses_allocator is true"); - - return tuple<_Args&&..., const _Alloc&>( - std::forward<_Args>(__args)..., __a); - } - } - else - { - static_assert(is_constructible_v<_Tp, _Args...>); - - return tuple<_Args&&...>(std::forward<_Args>(__args)...); - } - } - -#if __cpp_concepts - template - concept _Std_pair = __is_pair<_Tp>::value; -#endif - -// This is a temporary workaround until -fconcepts is implied by -std=gnu++2a -#if __cpp_concepts -# define _GLIBCXX_STD_PAIR_CONSTRAINT(T) _Std_pair T -# define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) _Std_pair T -#else -# define _GLIBCXX_STD_PAIR_CONSTRAINT(T) \ - typename T, typename __ = _Require<__is_pair> -# define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) typename T, typename -#endif - - template>>, -#endif - typename _Alloc, typename... _Args> - constexpr auto - uses_allocator_construction_args(const _Alloc& __a, - _Args&&... __args) noexcept -#if __cpp_concepts - requires (! _Std_pair<_Tp>) -#endif - { - return std::__uses_alloc_args<_Tp>(__a, std::forward<_Args>(__args)...); - } - - template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, - typename _Tuple1, typename _Tuple2> - constexpr auto - uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, - _Tuple1&& __x, _Tuple2&& __y) noexcept; - - template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc> - constexpr auto - uses_allocator_construction_args(const _Alloc&) noexcept; - - template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, - typename _Up, typename _Vp> - constexpr auto - uses_allocator_construction_args(const _Alloc&, _Up&&, _Vp&&) noexcept; - - template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, - typename _Up, typename _Vp> - constexpr auto - uses_allocator_construction_args(const _Alloc&, - const pair<_Up, _Vp>&) noexcept; - - template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, - typename _Up, typename _Vp> - constexpr auto - uses_allocator_construction_args(const _Alloc&, pair<_Up, _Vp>&&) noexcept; - - template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, - typename _Tuple1, typename _Tuple2> - constexpr auto - uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, - _Tuple1&& __x, _Tuple2&& __y) noexcept - { - using _Tp1 = typename _Tp::first_type; - using _Tp2 = typename _Tp::second_type; - - return std::make_tuple(piecewise_construct, - std::apply([&__a](auto&&... __args1) { - return std::uses_allocator_construction_args<_Tp1>( - __a, std::forward(__args1)...); - }, std::forward<_Tuple1>(__x)), - std::apply([&__a](auto&&... __args2) { - return std::uses_allocator_construction_args<_Tp2>( - __a, std::forward(__args2)...); - }, std::forward<_Tuple2>(__y))); - } - - template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc> - constexpr auto - uses_allocator_construction_args(const _Alloc& __a) noexcept - { - using _Tp1 = typename _Tp::first_type; - using _Tp2 = typename _Tp::second_type; - - return std::make_tuple(piecewise_construct, - std::uses_allocator_construction_args<_Tp1>(__a), - std::uses_allocator_construction_args<_Tp2>(__a)); - } - - template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, - typename _Up, typename _Vp> - constexpr auto - uses_allocator_construction_args(const _Alloc& __a, _Up&& __u, _Vp&& __v) - noexcept - { - using _Tp1 = typename _Tp::first_type; - using _Tp2 = typename _Tp::second_type; - - return std::make_tuple(piecewise_construct, - std::uses_allocator_construction_args<_Tp1>(__a, - std::forward<_Up>(__u)), - std::uses_allocator_construction_args<_Tp2>(__a, - std::forward<_Vp>(__v))); - } - - template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, - typename _Up, typename _Vp> - constexpr auto - uses_allocator_construction_args(const _Alloc& __a, - const pair<_Up, _Vp>& __pr) noexcept - { - using _Tp1 = typename _Tp::first_type; - using _Tp2 = typename _Tp::second_type; - - return std::make_tuple(piecewise_construct, - std::uses_allocator_construction_args<_Tp1>(__a, __pr.first), - std::uses_allocator_construction_args<_Tp2>(__a, __pr.second)); - } - - template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, - typename _Up, typename _Vp> - constexpr auto - uses_allocator_construction_args(const _Alloc& __a, - pair<_Up, _Vp>&& __pr) noexcept - { - using _Tp1 = typename _Tp::first_type; - using _Tp2 = typename _Tp::second_type; - - return std::make_tuple(piecewise_construct, - std::uses_allocator_construction_args<_Tp1>(__a, - std::move(__pr).first), - std::uses_allocator_construction_args<_Tp2>(__a, - std::move(__pr).second)); - } - - template - inline _Tp - make_obj_using_allocator(const _Alloc& __a, _Args&&... __args) - { - return std::make_from_tuple<_Tp>( - std::uses_allocator_construction_args<_Tp>(__a, - std::forward<_Args>(__args)...)); - } - - template - inline _Tp* - uninitialized_construct_using_allocator(_Tp* __p, const _Alloc& __a, - _Args&&... __args) - { - return std::apply([&](auto&&... __xs) { - return std::construct_at(__p, std::forward(__xs)...); - }, std::uses_allocator_construction_args<_Tp>(__a, - std::forward<_Args>(__args)...)); - } -// @} - -#endif // C++2a - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -#endif // C++11 - -#endif /* _GLIBCXX_MEMORY */ diff --git a/resources/sources/avr-libstdcpp/include/mutex b/resources/sources/avr-libstdcpp/include/mutex deleted file mode 100644 index 389504d7d..000000000 --- a/resources/sources/avr-libstdcpp/include/mutex +++ /dev/null @@ -1,746 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2003-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/mutex - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_MUTEX -#define _GLIBCXX_MUTEX 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include -#include -#ifndef _GLIBCXX_HAVE_TLS -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup mutexes - * @{ - */ - -#ifdef _GLIBCXX_HAS_GTHREADS - - // Common base class for std::recursive_mutex and std::recursive_timed_mutex - class __recursive_mutex_base - { - protected: - typedef __gthread_recursive_mutex_t __native_type; - - __recursive_mutex_base(const __recursive_mutex_base&) = delete; - __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; - -#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT - __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; - - __recursive_mutex_base() = default; -#else - __native_type _M_mutex; - - __recursive_mutex_base() - { - // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) - __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); - } - - ~__recursive_mutex_base() - { __gthread_recursive_mutex_destroy(&_M_mutex); } -#endif - }; - - /// The standard recursive mutex type. - class recursive_mutex : private __recursive_mutex_base - { - public: - typedef __native_type* native_handle_type; - - recursive_mutex() = default; - ~recursive_mutex() = default; - - recursive_mutex(const recursive_mutex&) = delete; - recursive_mutex& operator=(const recursive_mutex&) = delete; - - void - lock() - { - int __e = __gthread_recursive_mutex_lock(&_M_mutex); - - // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) - if (__e) - __throw_system_error(__e); - } - - bool - try_lock() noexcept - { - // XXX EINVAL, EAGAIN, EBUSY - return !__gthread_recursive_mutex_trylock(&_M_mutex); - } - - void - unlock() - { - // XXX EINVAL, EAGAIN, EBUSY - __gthread_recursive_mutex_unlock(&_M_mutex); - } - - native_handle_type - native_handle() noexcept - { return &_M_mutex; } - }; - -#if _GTHREAD_USE_MUTEX_TIMEDLOCK - template - class __timed_mutex_impl - { - protected: - template - bool - _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { -#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK - using __clock = chrono::steady_clock; -#else - using __clock = chrono::system_clock; -#endif - - auto __rt = chrono::duration_cast<__clock::duration>(__rtime); - if (ratio_greater<__clock::period, _Period>()) - ++__rt; - return _M_try_lock_until(__clock::now() + __rt); - } - - template - bool - _M_try_lock_until(const chrono::time_point& __atime) - { - auto __s = chrono::time_point_cast(__atime); - auto __ns = chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - return static_cast<_Derived*>(this)->_M_timedlock(__ts); - } - -#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK - template - bool - _M_try_lock_until(const chrono::time_point& __atime) - { - auto __s = chrono::time_point_cast(__atime); - auto __ns = chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - return static_cast<_Derived*>(this)->_M_clocklock(CLOCK_MONOTONIC, - __ts); - } -#endif - - template - bool - _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { -#if __cplusplus > 201703L - static_assert(chrono::is_clock_v<_Clock>); -#endif - // The user-supplied clock may not tick at the same rate as - // steady_clock, so we must loop in order to guarantee that - // the timeout has expired before returning false. - auto __now = _Clock::now(); - do { - auto __rtime = __atime - __now; - if (_M_try_lock_for(__rtime)) - return true; - __now = _Clock::now(); - } while (__atime > __now); - return false; - } - }; - - /// The standard timed mutex type. - class timed_mutex - : private __mutex_base, public __timed_mutex_impl - { - public: - typedef __native_type* native_handle_type; - - timed_mutex() = default; - ~timed_mutex() = default; - - timed_mutex(const timed_mutex&) = delete; - timed_mutex& operator=(const timed_mutex&) = delete; - - void - lock() - { - int __e = __gthread_mutex_lock(&_M_mutex); - - // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) - if (__e) - __throw_system_error(__e); - } - - bool - try_lock() noexcept - { - // XXX EINVAL, EAGAIN, EBUSY - return !__gthread_mutex_trylock(&_M_mutex); - } - - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { return _M_try_lock_for(__rtime); } - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { return _M_try_lock_until(__atime); } - - void - unlock() - { - // XXX EINVAL, EAGAIN, EBUSY - __gthread_mutex_unlock(&_M_mutex); - } - - native_handle_type - native_handle() noexcept - { return &_M_mutex; } - - private: - friend class __timed_mutex_impl; - - bool - _M_timedlock(const __gthread_time_t& __ts) - { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); } - -#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK - bool - _M_clocklock(clockid_t clockid, const __gthread_time_t& __ts) - { return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); } -#endif - }; - - /// recursive_timed_mutex - class recursive_timed_mutex - : private __recursive_mutex_base, - public __timed_mutex_impl - { - public: - typedef __native_type* native_handle_type; - - recursive_timed_mutex() = default; - ~recursive_timed_mutex() = default; - - recursive_timed_mutex(const recursive_timed_mutex&) = delete; - recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; - - void - lock() - { - int __e = __gthread_recursive_mutex_lock(&_M_mutex); - - // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) - if (__e) - __throw_system_error(__e); - } - - bool - try_lock() noexcept - { - // XXX EINVAL, EAGAIN, EBUSY - return !__gthread_recursive_mutex_trylock(&_M_mutex); - } - - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { return _M_try_lock_for(__rtime); } - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { return _M_try_lock_until(__atime); } - - void - unlock() - { - // XXX EINVAL, EAGAIN, EBUSY - __gthread_recursive_mutex_unlock(&_M_mutex); - } - - native_handle_type - native_handle() noexcept - { return &_M_mutex; } - - private: - friend class __timed_mutex_impl; - - bool - _M_timedlock(const __gthread_time_t& __ts) - { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); } - -#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK - bool - _M_clocklock(clockid_t clockid, const __gthread_time_t& __ts) - { return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); } -#endif - }; - -#else // !_GTHREAD_USE_MUTEX_TIMEDLOCK - - /// timed_mutex - class timed_mutex - { - mutex _M_mut; - condition_variable _M_cv; - bool _M_locked = false; - - public: - - timed_mutex() = default; - ~timed_mutex() { __glibcxx_assert( !_M_locked ); } - - timed_mutex(const timed_mutex&) = delete; - timed_mutex& operator=(const timed_mutex&) = delete; - - void - lock() - { - unique_lock __lk(_M_mut); - _M_cv.wait(__lk, [&]{ return !_M_locked; }); - _M_locked = true; - } - - bool - try_lock() - { - lock_guard __lk(_M_mut); - if (_M_locked) - return false; - _M_locked = true; - return true; - } - - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { - unique_lock __lk(_M_mut); - if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; })) - return false; - _M_locked = true; - return true; - } - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { - unique_lock __lk(_M_mut); - if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; })) - return false; - _M_locked = true; - return true; - } - - void - unlock() - { - lock_guard __lk(_M_mut); - __glibcxx_assert( _M_locked ); - _M_locked = false; - _M_cv.notify_one(); - } - }; - - /// recursive_timed_mutex - class recursive_timed_mutex - { - mutex _M_mut; - condition_variable _M_cv; - thread::id _M_owner; - unsigned _M_count = 0; - - // Predicate type that tests whether the current thread can lock a mutex. - struct _Can_lock - { - // Returns true if the mutex is unlocked or is locked by _M_caller. - bool - operator()() const noexcept - { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; } - - const recursive_timed_mutex* _M_mx; - thread::id _M_caller; - }; - - public: - - recursive_timed_mutex() = default; - ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); } - - recursive_timed_mutex(const recursive_timed_mutex&) = delete; - recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; - - void - lock() - { - auto __id = this_thread::get_id(); - _Can_lock __can_lock{this, __id}; - unique_lock __lk(_M_mut); - _M_cv.wait(__lk, __can_lock); - if (_M_count == -1u) - __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3 - _M_owner = __id; - ++_M_count; - } - - bool - try_lock() - { - auto __id = this_thread::get_id(); - _Can_lock __can_lock{this, __id}; - lock_guard __lk(_M_mut); - if (!__can_lock()) - return false; - if (_M_count == -1u) - return false; - _M_owner = __id; - ++_M_count; - return true; - } - - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { - auto __id = this_thread::get_id(); - _Can_lock __can_lock{this, __id}; - unique_lock __lk(_M_mut); - if (!_M_cv.wait_for(__lk, __rtime, __can_lock)) - return false; - if (_M_count == -1u) - return false; - _M_owner = __id; - ++_M_count; - return true; - } - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { - auto __id = this_thread::get_id(); - _Can_lock __can_lock{this, __id}; - unique_lock __lk(_M_mut); - if (!_M_cv.wait_until(__lk, __atime, __can_lock)) - return false; - if (_M_count == -1u) - return false; - _M_owner = __id; - ++_M_count; - return true; - } - - void - unlock() - { - lock_guard __lk(_M_mut); - __glibcxx_assert( _M_owner == this_thread::get_id() ); - __glibcxx_assert( _M_count > 0 ); - if (--_M_count == 0) - { - _M_owner = {}; - _M_cv.notify_one(); - } - } - }; - -#endif -#endif // _GLIBCXX_HAS_GTHREADS - - /// @cond undocumented - template - inline unique_lock<_Lock> - __try_to_lock(_Lock& __l) - { return unique_lock<_Lock>{__l, try_to_lock}; } - - template - struct __try_lock_impl - { - template - static void - __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) - { - __idx = _Idx; - auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); - if (__lock.owns_lock()) - { - constexpr bool __cont = _Idx + 2 < sizeof...(_Lock); - using __try_locker = __try_lock_impl<_Idx + 1, __cont>; - __try_locker::__do_try_lock(__locks, __idx); - if (__idx == -1) - __lock.release(); - } - } - }; - - template - struct __try_lock_impl<_Idx, false> - { - template - static void - __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) - { - __idx = _Idx; - auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); - if (__lock.owns_lock()) - { - __idx = -1; - __lock.release(); - } - } - }; - /// @endcond - - /** @brief Generic try_lock. - * @param __l1 Meets Lockable requirements (try_lock() may throw). - * @param __l2 Meets Lockable requirements (try_lock() may throw). - * @param __l3 Meets Lockable requirements (try_lock() may throw). - * @return Returns -1 if all try_lock() calls return true. Otherwise returns - * a 0-based index corresponding to the argument that returned false. - * @post Either all arguments are locked, or none will be. - * - * Sequentially calls try_lock() on each argument. - */ - template - int - try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3) - { - int __idx; - auto __locks = std::tie(__l1, __l2, __l3...); - __try_lock_impl<0>::__do_try_lock(__locks, __idx); - return __idx; - } - - /** @brief Generic lock. - * @param __l1 Meets Lockable requirements (try_lock() may throw). - * @param __l2 Meets Lockable requirements (try_lock() may throw). - * @param __l3 Meets Lockable requirements (try_lock() may throw). - * @throw An exception thrown by an argument's lock() or try_lock() member. - * @post All arguments are locked. - * - * All arguments are locked via a sequence of calls to lock(), try_lock() - * and unlock(). If the call exits via an exception any locks that were - * obtained will be released. - */ - template - void - lock(_L1& __l1, _L2& __l2, _L3&... __l3) - { - while (true) - { - using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>; - unique_lock<_L1> __first(__l1); - int __idx; - auto __locks = std::tie(__l2, __l3...); - __try_locker::__do_try_lock(__locks, __idx); - if (__idx == -1) - { - __first.release(); - return; - } - } - } - -#if __cplusplus >= 201703L -#define __cpp_lib_scoped_lock 201703 - /** @brief A scoped lock type for multiple lockable objects. - * - * A scoped_lock controls mutex ownership within a scope, releasing - * ownership in the destructor. - */ - template - class scoped_lock - { - public: - explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...)) - { std::lock(__m...); } - - explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept - : _M_devices(std::tie(__m...)) - { } // calling thread owns mutex - - ~scoped_lock() - { std::apply([](auto&... __m) { (__m.unlock(), ...); }, _M_devices); } - - scoped_lock(const scoped_lock&) = delete; - scoped_lock& operator=(const scoped_lock&) = delete; - - private: - tuple<_MutexTypes&...> _M_devices; - }; - - template<> - class scoped_lock<> - { - public: - explicit scoped_lock() = default; - explicit scoped_lock(adopt_lock_t) noexcept { } - ~scoped_lock() = default; - - scoped_lock(const scoped_lock&) = delete; - scoped_lock& operator=(const scoped_lock&) = delete; - }; - - template - class scoped_lock<_Mutex> - { - public: - using mutex_type = _Mutex; - - explicit scoped_lock(mutex_type& __m) : _M_device(__m) - { _M_device.lock(); } - - explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept - : _M_device(__m) - { } // calling thread owns mutex - - ~scoped_lock() - { _M_device.unlock(); } - - scoped_lock(const scoped_lock&) = delete; - scoped_lock& operator=(const scoped_lock&) = delete; - - private: - mutex_type& _M_device; - }; -#endif // C++17 - -#ifdef _GLIBCXX_HAS_GTHREADS - /// Flag type used by std::call_once - struct once_flag - { - private: - typedef __gthread_once_t __native_type; - __native_type _M_once = __GTHREAD_ONCE_INIT; - - public: - /// Constructor - constexpr once_flag() noexcept = default; - - /// Deleted copy constructor - once_flag(const once_flag&) = delete; - /// Deleted assignment operator - once_flag& operator=(const once_flag&) = delete; - - template - friend void - call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); - }; - - /// @cond undocumented -#ifdef _GLIBCXX_HAVE_TLS - extern __thread void* __once_callable; - extern __thread void (*__once_call)(); -#else - extern function __once_functor; - - extern void - __set_once_functor_lock_ptr(unique_lock*); - - extern mutex& - __get_once_mutex(); -#endif - - extern "C" void __once_proxy(void); - /// @endcond - - /// Invoke a callable and synchronize with other calls using the same flag - template - void - call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2442. call_once() shouldn't DECAY_COPY() - auto __callable = [&] { - std::__invoke(std::forward<_Callable>(__f), - std::forward<_Args>(__args)...); - }; -#ifdef _GLIBCXX_HAVE_TLS - __once_callable = std::__addressof(__callable); - __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; -#else - unique_lock __functor_lock(__get_once_mutex()); - __once_functor = __callable; - __set_once_functor_lock_ptr(&__functor_lock); -#endif - - int __e = __gthread_once(&__once._M_once, &__once_proxy); - -#ifndef _GLIBCXX_HAVE_TLS - if (__functor_lock) - __set_once_functor_lock_ptr(0); -#endif - -#ifdef __clang_analyzer__ - // PR libstdc++/82481 - __once_callable = nullptr; - __once_call = nullptr; -#endif - - if (__e) - __throw_system_error(__e); - } -#endif // _GLIBCXX_HAS_GTHREADS - - // @} group mutexes -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 - -#endif // _GLIBCXX_MUTEX diff --git a/resources/sources/avr-libstdcpp/include/new b/resources/sources/avr-libstdcpp/include/new index 06e43dc6f..aa5574829 100644 --- a/resources/sources/avr-libstdcpp/include/new +++ b/resources/sources/avr-libstdcpp/include/new @@ -1,193 +1,7 @@ -// The -*- C++ -*- dynamic memory management header. - -// Copyright (C) 1994-2020 Free Software Foundation, Inc. - -// This file is part of GCC. -// -// GCC is free software; you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation; either version 3, or (at your option) -// any later version. -// -// GCC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file new - * This is a Standard C++ Library header. - * - * The header @c new defines several functions to manage dynamic memory and - * handling memory allocation errors; see - * https://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html - * for more. - */ - -#ifndef _NEW -#define _NEW - -#pragma GCC system_header - -#include +// Minimal for AVR -- placement new +#ifndef _AVR_NEW +#define _AVR_NEW #include - -#pragma GCC visibility push(default) - -extern "C++" { - -namespace std -{ -#if __cpp_aligned_new - enum class align_val_t: size_t {}; -#endif - - struct nothrow_t - { -#if __cplusplus >= 201103L - explicit nothrow_t() = default; -#endif - }; - - extern const nothrow_t nothrow; - - /** If you write your own error handler to be called by @c new, it must - * be of this type. */ - typedef void (*new_handler)(); - - /// Takes a replacement handler as the argument, returns the - /// previous handler. - new_handler set_new_handler(new_handler) throw(); - -#if __cplusplus >= 201103L - /// Return the current new handler. - new_handler get_new_handler() noexcept; -#endif -} // namespace std - -//@{ -/** These are replaceable signatures: - * - normal single new and delete (no arguments, throw @c bad_alloc on error) - * - normal array new and delete (same) - * - @c nothrow single new and delete (take a @c nothrow argument, return - * @c NULL on error) - * - @c nothrow array new and delete (same) - * - * Placement new and delete signatures (take a memory address argument, - * does nothing) may not be replaced by a user's program. -*/ -_GLIBCXX_NODISCARD void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc) - __attribute__((__externally_visible__)); -_GLIBCXX_NODISCARD void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc) - __attribute__((__externally_visible__)); -void operator delete(void*) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__)); -void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__)); -#if __cpp_sized_deallocation -void operator delete(void*, std::size_t) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__)); -void operator delete[](void*, std::size_t) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__)); -#endif -_GLIBCXX_NODISCARD void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__, __malloc__)); -_GLIBCXX_NODISCARD void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__, __malloc__)); -void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__)); -void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT - __attribute__((__externally_visible__)); -#if 0 // __cpp_aligned_new -_GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t) - __attribute__((__externally_visible__)); -_GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __malloc__)); -void operator delete(void*, std::align_val_t) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); -void operator delete(void*, std::align_val_t, const std::nothrow_t&) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); -_GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t) - __attribute__((__externally_visible__)); -_GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __malloc__)); -void operator delete[](void*, std::align_val_t) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); -void operator delete[](void*, std::align_val_t, const std::nothrow_t&) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); -#if __cpp_sized_deallocation -void operator delete(void*, std::size_t, std::align_val_t) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); -void operator delete[](void*, std::size_t, std::align_val_t) - _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); -#endif // __cpp_sized_deallocation -#endif // __cpp_aligned_new - -// Default placement versions of operator new. -_GLIBCXX_NODISCARD inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT -{ return __p; } -_GLIBCXX_NODISCARD inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT -{ return __p; } - -// Default placement versions of operator delete. -inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { } -inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { } -//@} -} // extern "C++" - -#if __cplusplus >= 201703L -#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER -namespace std -{ -#define __cpp_lib_launder 201606 - /// Pointer optimization barrier [ptr.launder] - template - [[nodiscard]] constexpr _Tp* - launder(_Tp* __p) noexcept - { return __builtin_launder(__p); } - - // The program is ill-formed if T is a function type or - // (possibly cv-qualified) void. - - template - void launder(_Ret (*)(_Args...) _GLIBCXX_NOEXCEPT_QUAL) = delete; - template - void launder(_Ret (*)(_Args......) _GLIBCXX_NOEXCEPT_QUAL) = delete; - - void launder(void*) = delete; - void launder(const void*) = delete; - void launder(volatile void*) = delete; - void launder(const volatile void*) = delete; -} -#endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER -#endif // C++17 - -#if __cplusplus > 201703L -namespace std -{ - /// Tag type used to declare a class-specific operator delete that can - /// invoke the destructor before deallocating the memory. - struct destroying_delete_t - { - explicit destroying_delete_t() = default; - }; - /// Tag variable of type destroying_delete_t. - inline constexpr destroying_delete_t destroying_delete{}; -} -// Only define the feature test macro if the compiler supports the feature: -#if __cpp_impl_destroying_delete -# define __cpp_lib_destroying_delete 201806L -#endif -#endif // C++20 - -#pragma GCC visibility pop - +inline void* operator new(size_t, void* p) noexcept { return p; } +inline void* operator new[](size_t, void* p) noexcept { return p; } #endif diff --git a/resources/sources/avr-libstdcpp/include/numbers b/resources/sources/avr-libstdcpp/include/numbers deleted file mode 100644 index 7e51851bd..000000000 --- a/resources/sources/avr-libstdcpp/include/numbers +++ /dev/null @@ -1,208 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2019-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/numbers - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_NUMBERS -#define _GLIBCXX_NUMBERS 1 - -#pragma GCC system_header - -#if __cplusplus > 201703L - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -/** @defgroup math_constants Mathematical constants - * @ingroup numerics - * @{ - */ - -/// Namespace for mathematical constants -namespace numbers -{ -#define __cpp_lib_math_constants 201907L - - /// @cond undoc - template - using _Enable_if_floating = enable_if_t, _Tp>; - /// @endcond - - /// e - template - inline constexpr _Tp e_v - = _Enable_if_floating<_Tp>(2.718281828459045235360287471352662498L); - - /// log_2 e - template - inline constexpr _Tp log2e_v - = _Enable_if_floating<_Tp>(1.442695040888963407359924681001892137L); - - /// log_10 e - template - inline constexpr _Tp log10e_v - = _Enable_if_floating<_Tp>(0.434294481903251827651128918916605082L); - - /// pi - template - inline constexpr _Tp pi_v - = _Enable_if_floating<_Tp>(3.141592653589793238462643383279502884L); - - /// 1/pi - template - inline constexpr _Tp inv_pi_v - = _Enable_if_floating<_Tp>(0.318309886183790671537767526745028724L); - - /// 1/sqrt(pi) - template - inline constexpr _Tp inv_sqrtpi_v - = _Enable_if_floating<_Tp>(0.564189583547756286948079451560772586L); - - /// log_e 2 - template - inline constexpr _Tp ln2_v - = _Enable_if_floating<_Tp>(0.693147180559945309417232121458176568L); - - /// log_e 10 - template - inline constexpr _Tp ln10_v - = _Enable_if_floating<_Tp>(2.302585092994045684017991454684364208L); - - /// sqrt(2) - template - inline constexpr _Tp sqrt2_v - = _Enable_if_floating<_Tp>(1.414213562373095048801688724209698079L); - - /// sqrt(3) - template - inline constexpr _Tp sqrt3_v - = _Enable_if_floating<_Tp>(1.732050807568877293527446341505872367L); - - /// 1/sqrt(3) - template - inline constexpr _Tp inv_sqrt3_v - = _Enable_if_floating<_Tp>(0.577350269189625764509148780501957456L); - - /// The Euler-Mascheroni constant - template - inline constexpr _Tp egamma_v - = _Enable_if_floating<_Tp>(0.577215664901532860606512090082402431L); - - /// The golden ratio, (1+sqrt(5))/2 - template - inline constexpr _Tp phi_v - = _Enable_if_floating<_Tp>(1.618033988749894848204586834365638118L); - - inline constexpr double e = e_v; - inline constexpr double log2e = log2e_v; - inline constexpr double log10e = log10e_v; - inline constexpr double pi = pi_v; - inline constexpr double inv_pi = inv_pi_v; - inline constexpr double inv_sqrtpi = inv_sqrtpi_v; - inline constexpr double ln2 = ln2_v; - inline constexpr double ln10 = ln10_v; - inline constexpr double sqrt2 = sqrt2_v; - inline constexpr double sqrt3 = sqrt3_v; - inline constexpr double inv_sqrt3 = inv_sqrt3_v; - inline constexpr double egamma = egamma_v; - inline constexpr double phi = phi_v; - -#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) - template<> - inline constexpr __float128 e_v<__float128> - = 2.718281828459045235360287471352662498Q; - - /// log_2 e - template<> - inline constexpr __float128 log2e_v<__float128> - = 1.442695040888963407359924681001892137Q; - - /// log_10 e - template<> - inline constexpr __float128 log10e_v<__float128> - = 0.434294481903251827651128918916605082Q; - - /// pi - template<> - inline constexpr __float128 pi_v<__float128> - = 3.141592653589793238462643383279502884Q; - - /// 1/pi - template<> - inline constexpr __float128 inv_pi_v<__float128> - = 0.318309886183790671537767526745028724Q; - - /// 1/sqrt(pi) - template<> - inline constexpr __float128 inv_sqrtpi_v<__float128> - = 0.564189583547756286948079451560772586Q; - - /// log_e 2 - template<> - inline constexpr __float128 ln2_v<__float128> - = 0.693147180559945309417232121458176568Q; - - /// log_e 10 - template<> - inline constexpr __float128 ln10_v<__float128> - = 2.302585092994045684017991454684364208Q; - - /// sqrt(2) - template<> - inline constexpr __float128 sqrt2_v<__float128> - = 1.414213562373095048801688724209698079Q; - - /// sqrt(3) - template<> - inline constexpr __float128 sqrt3_v<__float128> - = 1.732050807568877293527446341505872367Q; - - /// 1/sqrt(3) - template<> - inline constexpr __float128 inv_sqrt3_v<__float128> - = 0.577350269189625764509148780501957456Q; - - /// The Euler-Mascheroni constant - template<> - inline constexpr __float128 egamma_v<__float128> - = 0.577215664901532860606512090082402431Q; - - /// The golden ratio, (1+sqrt(5))/2 - template<> - inline constexpr __float128 phi_v<__float128> - = 1.618033988749894848204586834365638118Q; -#endif // USE_FLOAT128 - -} // namespace numbers -/// @} -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++20 -#endif // _GLIBCXX_NUMBERS diff --git a/resources/sources/avr-libstdcpp/include/numeric b/resources/sources/avr-libstdcpp/include/numeric deleted file mode 100644 index 7793c9db3..000000000 --- a/resources/sources/avr-libstdcpp/include/numeric +++ /dev/null @@ -1,699 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/numeric - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_NUMERIC -#define _GLIBCXX_NUMERIC 1 - -#pragma GCC system_header - -#include -#include -#include -#include - -/** - * @defgroup numerics Numerics - * - * Components for performing numeric operations. Includes support for - * complex number types, random number generation, numeric (n-at-a-time) - * arrays, generalized numeric algorithms, and mathematical special functions. - */ - -#if __cplusplus >= 201402L -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -namespace __detail -{ - // std::abs is not constexpr, doesn't support unsigned integers, - // and std::abs(std::numeric_limits::min()) is undefined. - template - constexpr _Up - __absu(_Tp __val) - { - static_assert(is_unsigned<_Up>::value, "result type must be unsigned"); - static_assert(sizeof(_Up) >= sizeof(_Tp), - "result type must be at least as wide as the input type"); - return __val < 0 ? -(_Up)__val : (_Up)__val; - } - - template void __absu(bool) = delete; - - // GCD implementation - template - constexpr _Tp - __gcd(_Tp __m, _Tp __n) - { - static_assert(is_unsigned<_Tp>::value, "type must be unsigned"); - return __m == 0 ? __n - : __n == 0 ? __m - : __detail::__gcd(__n, _Tp(__m % __n)); - } - - // LCM implementation - template - constexpr _Tp - __lcm(_Tp __m, _Tp __n) - { - return (__m != 0 && __n != 0) - ? (__m / __detail::__gcd(__m, __n)) * __n - : 0; - } -} // namespace __detail - -#if __cplusplus >= 201703L - -#define __cpp_lib_gcd_lcm 201606 -// These were used in drafts of SD-6: -#define __cpp_lib_gcd 201606 -#define __cpp_lib_lcm 201606 - - /// Greatest common divisor - template - constexpr common_type_t<_Mn, _Nn> - gcd(_Mn __m, _Nn __n) noexcept - { - static_assert(is_integral_v<_Mn>, "std::gcd arguments must be integers"); - static_assert(is_integral_v<_Nn>, "std::gcd arguments must be integers"); - static_assert(_Mn(2) != _Mn(1), "std::gcd arguments must not be bool"); - static_assert(_Nn(2) != _Nn(1), "std::gcd arguments must not be bool"); - using _Up = make_unsigned_t>; - return __detail::__gcd(__detail::__absu<_Up>(__m), - __detail::__absu<_Up>(__n)); - } - - /// Least common multiple - template - constexpr common_type_t<_Mn, _Nn> - lcm(_Mn __m, _Nn __n) noexcept - { - static_assert(is_integral_v<_Mn>, "std::lcm arguments must be integers"); - static_assert(is_integral_v<_Nn>, "std::lcm arguments must be integers"); - static_assert(_Mn(2) == 2, "std::lcm arguments must not be bool"); - static_assert(_Nn(2) == 2, "std::lcm arguments must not be bool"); - using _Up = make_unsigned_t>; - return __detail::__lcm(__detail::__absu<_Up>(__m), - __detail::__absu<_Up>(__n)); - } - -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++14 - -#if __cplusplus > 201703L -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - // midpoint -# define __cpp_lib_interpolate 201902L - - template - constexpr - enable_if_t<__and_v, is_same, _Tp>, - __not_>>, - _Tp> - midpoint(_Tp __a, _Tp __b) noexcept - { - if constexpr (is_integral_v<_Tp>) - { - using _Up = make_unsigned_t<_Tp>; - - int __k = 1; - _Up __m = __a; - _Up __M = __b; - if (__a > __b) - { - __k = -1; - __m = __b; - __M = __a; - } - return __a + __k * _Tp(_Up(__M - __m) / 2); - } - else // is_floating - { - constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2; - constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2; - const _Tp __abs_a = __a < 0 ? -__a : __a; - const _Tp __abs_b = __b < 0 ? -__b : __b; - if (__abs_a <= __hi && __abs_b <= __hi) [[likely]] - return (__a + __b) / 2; // always correctly rounded - if (__abs_a < __lo) // not safe to halve __a - return __a + __b/2; - if (__abs_b < __lo) // not safe to halve __b - return __a/2 + __b; - return __a/2 + __b/2; // otherwise correctly rounded - } - } - - template - constexpr enable_if_t, _Tp*> - midpoint(_Tp* __a, _Tp* __b) noexcept - { - static_assert( sizeof(_Tp) != 0, "type must be complete" ); - return __a + (__b - __a) / 2; - } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++20 - -#if __cplusplus > 201402L -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#if __cplusplus > 201703L -#define __cpp_lib_constexpr_numeric 201911L -#endif - - /// @addtogroup numeric_ops - /// @{ - - /** - * @brief Calculate reduction of values in a range. - * - * @param __first Start of range. - * @param __last End of range. - * @param __init Starting value to add other values to. - * @param __binary_op A binary function object. - * @return The final sum. - * - * Reduce the values in the range `[first,last)` using a binary operation. - * The initial value is `init`. The values are not necessarily processed - * in order. - * - * This algorithm is similar to `std::accumulate` but is not required to - * perform the operations in order from first to last. For operations - * that are commutative and associative the result will be the same as - * for `std::accumulate`, but for other operations (such as floating point - * arithmetic) the result can be different. - */ - template - _GLIBCXX20_CONSTEXPR - _Tp - reduce(_InputIterator __first, _InputIterator __last, _Tp __init, - _BinaryOperation __binary_op) - { - using value_type = typename iterator_traits<_InputIterator>::value_type; - static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>); - static_assert(is_convertible_v); - if constexpr (__is_random_access_iter<_InputIterator>::value) - { - while ((__last - __first) >= 4) - { - _Tp __v1 = __binary_op(__first[0], __first[1]); - _Tp __v2 = __binary_op(__first[2], __first[3]); - _Tp __v3 = __binary_op(__v1, __v2); - __init = __binary_op(__init, __v3); - __first += 4; - } - } - for (; __first != __last; ++__first) - __init = __binary_op(__init, *__first); - return __init; - } - - /** - * @brief Calculate reduction of values in a range. - * - * @param __first Start of range. - * @param __last End of range. - * @param __init Starting value to add other values to. - * @return The final sum. - * - * Reduce the values in the range `[first,last)` using addition. - * Equivalent to calling `std::reduce(first, last, init, std::plus<>())`. - */ - template - _GLIBCXX20_CONSTEXPR - inline _Tp - reduce(_InputIterator __first, _InputIterator __last, _Tp __init) - { return std::reduce(__first, __last, std::move(__init), plus<>()); } - - /** - * @brief Calculate reduction of values in a range. - * - * @param __first Start of range. - * @param __last End of range. - * @return The final sum. - * - * Reduce the values in the range `[first,last)` using addition, with - * an initial value of `T{}`, where `T` is the iterator's value type. - * Equivalent to calling `std::reduce(first, last, T{}, std::plus<>())`. - */ - template - _GLIBCXX20_CONSTEXPR - inline typename iterator_traits<_InputIterator>::value_type - reduce(_InputIterator __first, _InputIterator __last) - { - using value_type = typename iterator_traits<_InputIterator>::value_type; - return std::reduce(__first, __last, value_type{}, plus<>()); - } - - /** - * @brief Combine elements from two ranges and reduce - * - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __init Starting value to add other values to. - * @param __binary_op1 The function used to perform reduction. - * @param __binary_op2 The function used to combine values from the ranges. - * @return The final sum. - * - * Call `binary_op2(first1[n],first2[n])` for each `n` in `[0,last1-first1)` - * and then use `binary_op1` to reduce the values returned by `binary_op2` - * to a single value of type `T`. - * - * The range beginning at `first2` must contain at least `last1-first1` - * elements. - */ - template - _GLIBCXX20_CONSTEXPR - _Tp - transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _Tp __init, - _BinaryOperation1 __binary_op1, - _BinaryOperation2 __binary_op2) - { - if constexpr (__and_v<__is_random_access_iter<_InputIterator1>, - __is_random_access_iter<_InputIterator2>>) - { - while ((__last1 - __first1) >= 4) - { - _Tp __v1 = __binary_op1(__binary_op2(__first1[0], __first2[0]), - __binary_op2(__first1[1], __first2[1])); - _Tp __v2 = __binary_op1(__binary_op2(__first1[2], __first2[2]), - __binary_op2(__first1[3], __first2[3])); - _Tp __v3 = __binary_op1(__v1, __v2); - __init = __binary_op1(__init, __v3); - __first1 += 4; - __first2 += 4; - } - } - for (; __first1 != __last1; ++__first1, (void) ++__first2) - __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); - return __init; - } - - /** - * @brief Combine elements from two ranges and reduce - * - * @param __first1 Start of first range. - * @param __last1 End of first range. - * @param __first2 Start of second range. - * @param __init Starting value to add other values to. - * @return The final sum. - * - * Call `first1[n]*first2[n]` for each `n` in `[0,last1-first1)` and then - * use addition to sum those products to a single value of type `T`. - * - * The range beginning at `first2` must contain at least `last1-first1` - * elements. - */ - template - _GLIBCXX20_CONSTEXPR - inline _Tp - transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, - _InputIterator2 __first2, _Tp __init) - { - return std::transform_reduce(__first1, __last1, __first2, - std::move(__init), - plus<>(), multiplies<>()); - } - - /** - * @brief Transform the elements of a range and reduce - * - * @param __first Start of range. - * @param __last End of range. - * @param __init Starting value to add other values to. - * @param __binary_op The function used to perform reduction. - * @param __unary_op The function used to transform values from the range. - * @return The final sum. - * - * Call `unary_op(first[n])` for each `n` in `[0,last-first)` and then - * use `binary_op` to reduce the values returned by `unary_op` - * to a single value of type `T`. - */ - template - _GLIBCXX20_CONSTEXPR - _Tp - transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, - _BinaryOperation __binary_op, _UnaryOperation __unary_op) - { - if constexpr (__is_random_access_iter<_InputIterator>::value) - { - while ((__last - __first) >= 4) - { - _Tp __v1 = __binary_op(__unary_op(__first[0]), - __unary_op(__first[1])); - _Tp __v2 = __binary_op(__unary_op(__first[2]), - __unary_op(__first[3])); - _Tp __v3 = __binary_op(__v1, __v2); - __init = __binary_op(__init, __v3); - __first += 4; - } - } - for (; __first != __last; ++__first) - __init = __binary_op(__init, __unary_op(*__first)); - return __init; - } - - /** @brief Output the cumulative sum of one range to a second range - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Start of output range. - * @param __init Initial value. - * @param __binary_op Function to perform summation. - * @return The end of the output range. - * - * Write the cumulative sum (aka prefix sum, aka scan) of the input range - * to the output range. Each element of the output range contains the - * running total of all earlier elements (and the initial value), - * using `binary_op` for summation. - * - * This function generates an "exclusive" scan, meaning the Nth element - * of the output range is the sum of the first N-1 input elements, - * so the Nth input element is not included. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - exclusive_scan(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _Tp __init, - _BinaryOperation __binary_op) - { - while (__first != __last) - { - auto __v = __init; - __init = __binary_op(__init, *__first); - ++__first; - *__result++ = std::move(__v); - } - return __result; - } - - /** @brief Output the cumulative sum of one range to a second range - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Start of output range. - * @param __init Initial value. - * @return The end of the output range. - * - * Write the cumulative sum (aka prefix sum, aka scan) of the input range - * to the output range. Each element of the output range contains the - * running total of all earlier elements (and the initial value), - * using `std::plus<>` for summation. - * - * This function generates an "exclusive" scan, meaning the Nth element - * of the output range is the sum of the first N-1 input elements, - * so the Nth input element is not included. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - exclusive_scan(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _Tp __init) - { - return std::exclusive_scan(__first, __last, __result, std::move(__init), - plus<>()); - } - - /** @brief Output the cumulative sum of one range to a second range - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Start of output range. - * @param __binary_op Function to perform summation. - * @param __init Initial value. - * @return The end of the output range. - * - * Write the cumulative sum (aka prefix sum, aka scan) of the input range - * to the output range. Each element of the output range contains the - * running total of all earlier elements (and the initial value), - * using `binary_op` for summation. - * - * This function generates an "inclusive" scan, meaning the Nth element - * of the output range is the sum of the first N input elements, - * so the Nth input element is included. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - inclusive_scan(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _BinaryOperation __binary_op, - _Tp __init) - { - for (; __first != __last; ++__first) - *__result++ = __init = __binary_op(__init, *__first); - return __result; - } - - /** @brief Output the cumulative sum of one range to a second range - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Start of output range. - * @param __binary_op Function to perform summation. - * @return The end of the output range. - * - * Write the cumulative sum (aka prefix sum, aka scan) of the input range - * to the output range. Each element of the output range contains the - * running total of all earlier elements, using `binary_op` for summation. - * - * This function generates an "inclusive" scan, meaning the Nth element - * of the output range is the sum of the first N input elements, - * so the Nth input element is included. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - inclusive_scan(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _BinaryOperation __binary_op) - { - if (__first != __last) - { - auto __init = *__first; - *__result++ = __init; - ++__first; - if (__first != __last) - __result = std::inclusive_scan(__first, __last, __result, - __binary_op, std::move(__init)); - } - return __result; - } - - /** @brief Output the cumulative sum of one range to a second range - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Start of output range. - * @return The end of the output range. - * - * Write the cumulative sum (aka prefix sum, aka scan) of the input range - * to the output range. Each element of the output range contains the - * running total of all earlier elements, using `std::plus<>` for summation. - * - * This function generates an "inclusive" scan, meaning the Nth element - * of the output range is the sum of the first N input elements, - * so the Nth input element is included. - */ - template - _GLIBCXX20_CONSTEXPR - inline _OutputIterator - inclusive_scan(_InputIterator __first, _InputIterator __last, - _OutputIterator __result) - { return std::inclusive_scan(__first, __last, __result, plus<>()); } - - /** @brief Output the cumulative sum of one range to a second range - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Start of output range. - * @param __init Initial value. - * @param __binary_op Function to perform summation. - * @param __unary_op Function to transform elements of the input range. - * @return The end of the output range. - * - * Write the cumulative sum (aka prefix sum, aka scan) of the input range - * to the output range. Each element of the output range contains the - * running total of all earlier elements (and the initial value), - * using `__unary_op` to transform the input elements - * and using `__binary_op` for summation. - * - * This function generates an "exclusive" scan, meaning the Nth element - * of the output range is the sum of the first N-1 input elements, - * so the Nth input element is not included. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - transform_exclusive_scan(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, _Tp __init, - _BinaryOperation __binary_op, - _UnaryOperation __unary_op) - { - while (__first != __last) - { - auto __v = __init; - __init = __binary_op(__init, __unary_op(*__first)); - ++__first; - *__result++ = std::move(__v); - } - return __result; - } - - /** @brief Output the cumulative sum of one range to a second range - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Start of output range. - * @param __binary_op Function to perform summation. - * @param __unary_op Function to transform elements of the input range. - * @param __init Initial value. - * @return The end of the output range. - * - * Write the cumulative sum (aka prefix sum, aka scan) of the input range - * to the output range. Each element of the output range contains the - * running total of all earlier elements (and the initial value), - * using `__unary_op` to transform the input elements - * and using `__binary_op` for summation. - * - * This function generates an "inclusive" scan, meaning the Nth element - * of the output range is the sum of the first N input elements, - * so the Nth input element is included. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - transform_inclusive_scan(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, - _BinaryOperation __binary_op, - _UnaryOperation __unary_op, - _Tp __init) - { - for (; __first != __last; ++__first) - *__result++ = __init = __binary_op(__init, __unary_op(*__first)); - return __result; - } - - /** @brief Output the cumulative sum of one range to a second range - * - * @param __first Start of input range. - * @param __last End of input range. - * @param __result Start of output range. - * @param __binary_op Function to perform summation. - * @param __unary_op Function to transform elements of the input range. - * @return The end of the output range. - * - * Write the cumulative sum (aka prefix sum, aka scan) of the input range - * to the output range. Each element of the output range contains the - * running total of all earlier elements, - * using `__unary_op` to transform the input elements - * and using `__binary_op` for summation. - * - * This function generates an "inclusive" scan, meaning the Nth element - * of the output range is the sum of the first N input elements, - * so the Nth input element is included. - */ - template - _GLIBCXX20_CONSTEXPR - _OutputIterator - transform_inclusive_scan(_InputIterator __first, _InputIterator __last, - _OutputIterator __result, - _BinaryOperation __binary_op, - _UnaryOperation __unary_op) - { - if (__first != __last) - { - auto __init = __unary_op(*__first); - *__result++ = __init; - ++__first; - if (__first != __last) - __result = std::transform_inclusive_scan(__first, __last, __result, - __binary_op, __unary_op, - std::move(__init)); - } - return __result; - } - - // @} group numeric_ops - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++17 - -#endif /* _GLIBCXX_NUMERIC */ diff --git a/resources/sources/avr-libstdcpp/include/optional b/resources/sources/avr-libstdcpp/include/optional deleted file mode 100644 index 6c7701e21..000000000 --- a/resources/sources/avr-libstdcpp/include/optional +++ /dev/null @@ -1,1238 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/optional - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_OPTIONAL -#define _GLIBCXX_OPTIONAL 1 - -#pragma GCC system_header - -#if __cplusplus >= 201703L - -#include -#include -#include -#include -#include -#include -#include -#include -#if __cplusplus > 201703L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup utilities - * @{ - */ - -#define __cpp_lib_optional 201606L - - template - class optional; - - /// Tag type to disengage optional objects. - struct nullopt_t - { - // Do not user-declare default constructor at all for - // optional_value = {} syntax to work. - // nullopt_t() = delete; - - // Used for constructing nullopt. - enum class _Construct { _Token }; - - // Must be constexpr for nullopt_t to be literal. - explicit constexpr nullopt_t(_Construct) { } - }; - - /// Tag to disengage optional objects. - inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; - - // This class template manages construction/destruction of - // the contained value for a std::optional. - template - struct _Optional_payload_base - { - using _Stored_type = remove_const_t<_Tp>; - - _Optional_payload_base() = default; - ~_Optional_payload_base() = default; - - template - constexpr - _Optional_payload_base(in_place_t __tag, _Args&&... __args) - : _M_payload(__tag, std::forward<_Args>(__args)...), - _M_engaged(true) - { } - - template - constexpr - _Optional_payload_base(std::initializer_list<_Up> __il, - _Args&&... __args) - : _M_payload(__il, std::forward<_Args>(__args)...), - _M_engaged(true) - { } - - // Constructor used by _Optional_base copy constructor when the - // contained value is not trivially copy constructible. - constexpr - _Optional_payload_base(bool __engaged, - const _Optional_payload_base& __other) - { - if (__other._M_engaged) - this->_M_construct(__other._M_get()); - } - - // Constructor used by _Optional_base move constructor when the - // contained value is not trivially move constructible. - constexpr - _Optional_payload_base(bool __engaged, - _Optional_payload_base&& __other) - { - if (__other._M_engaged) - this->_M_construct(std::move(__other._M_get())); - } - - // Copy constructor is only used to when the contained value is - // trivially copy constructible. - _Optional_payload_base(const _Optional_payload_base&) = default; - - // Move constructor is only used to when the contained value is - // trivially copy constructible. - _Optional_payload_base(_Optional_payload_base&&) = default; - - _Optional_payload_base& - operator=(const _Optional_payload_base&) = default; - - _Optional_payload_base& - operator=(_Optional_payload_base&&) = default; - - // used to perform non-trivial copy assignment. - constexpr void - _M_copy_assign(const _Optional_payload_base& __other) - { - if (this->_M_engaged && __other._M_engaged) - this->_M_get() = __other._M_get(); - else - { - if (__other._M_engaged) - this->_M_construct(__other._M_get()); - else - this->_M_reset(); - } - } - - // used to perform non-trivial move assignment. - constexpr void - _M_move_assign(_Optional_payload_base&& __other) - noexcept(__and_v, - is_nothrow_move_assignable<_Tp>>) - { - if (this->_M_engaged && __other._M_engaged) - this->_M_get() = std::move(__other._M_get()); - else - { - if (__other._M_engaged) - this->_M_construct(std::move(__other._M_get())); - else - this->_M_reset(); - } - } - - struct _Empty_byte { }; - - template> - union _Storage - { - constexpr _Storage() noexcept : _M_empty() { } - - template - constexpr - _Storage(in_place_t, _Args&&... __args) - : _M_value(std::forward<_Args>(__args)...) - { } - - template - constexpr - _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) - : _M_value(__il, std::forward<_Args>(__args)...) - { } - - _Empty_byte _M_empty; - _Up _M_value; - }; - - template - union _Storage<_Up, false> - { - constexpr _Storage() noexcept : _M_empty() { } - - template - constexpr - _Storage(in_place_t, _Args&&... __args) - : _M_value(std::forward<_Args>(__args)...) - { } - - template - constexpr - _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) - : _M_value(__il, std::forward<_Args>(__args)...) - { } - - // User-provided destructor is needed when _Up has non-trivial dtor. - ~_Storage() { } - - _Empty_byte _M_empty; - _Up _M_value; - }; - - _Storage<_Stored_type> _M_payload; - - bool _M_engaged = false; - - template - void - _M_construct(_Args&&... __args) - noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) - { - ::new ((void *) std::__addressof(this->_M_payload)) - _Stored_type(std::forward<_Args>(__args)...); - this->_M_engaged = true; - } - - constexpr void - _M_destroy() noexcept - { - _M_engaged = false; - _M_payload._M_value.~_Stored_type(); - } - - // The _M_get() operations have _M_engaged as a precondition. - // They exist to access the contained value with the appropriate - // const-qualification, because _M_payload has had the const removed. - - constexpr _Tp& - _M_get() noexcept - { return this->_M_payload._M_value; } - - constexpr const _Tp& - _M_get() const noexcept - { return this->_M_payload._M_value; } - - // _M_reset is a 'safe' operation with no precondition. - constexpr void - _M_reset() noexcept - { - if (this->_M_engaged) - _M_destroy(); - } - }; - - // Class template that manages the payload for optionals. - template , - bool /*_HasTrivialCopy */ = - is_trivially_copy_assignable_v<_Tp> - && is_trivially_copy_constructible_v<_Tp>, - bool /*_HasTrivialMove */ = - is_trivially_move_assignable_v<_Tp> - && is_trivially_move_constructible_v<_Tp>> - struct _Optional_payload; - - // Payload for potentially-constexpr optionals (trivial copy/move/destroy). - template - struct _Optional_payload<_Tp, true, true, true> - : _Optional_payload_base<_Tp> - { - using _Optional_payload_base<_Tp>::_Optional_payload_base; - - _Optional_payload() = default; - }; - - // Payload for optionals with non-trivial copy construction/assignment. - template - struct _Optional_payload<_Tp, true, false, true> - : _Optional_payload_base<_Tp> - { - using _Optional_payload_base<_Tp>::_Optional_payload_base; - - _Optional_payload() = default; - ~_Optional_payload() = default; - _Optional_payload(const _Optional_payload&) = default; - _Optional_payload(_Optional_payload&&) = default; - _Optional_payload& operator=(_Optional_payload&&) = default; - - // Non-trivial copy assignment. - constexpr - _Optional_payload& - operator=(const _Optional_payload& __other) - { - this->_M_copy_assign(__other); - return *this; - } - }; - - // Payload for optionals with non-trivial move construction/assignment. - template - struct _Optional_payload<_Tp, true, true, false> - : _Optional_payload_base<_Tp> - { - using _Optional_payload_base<_Tp>::_Optional_payload_base; - - _Optional_payload() = default; - ~_Optional_payload() = default; - _Optional_payload(const _Optional_payload&) = default; - _Optional_payload(_Optional_payload&&) = default; - _Optional_payload& operator=(const _Optional_payload&) = default; - - // Non-trivial move assignment. - constexpr - _Optional_payload& - operator=(_Optional_payload&& __other) - noexcept(__and_v, - is_nothrow_move_assignable<_Tp>>) - { - this->_M_move_assign(std::move(__other)); - return *this; - } - }; - - // Payload for optionals with non-trivial copy and move assignment. - template - struct _Optional_payload<_Tp, true, false, false> - : _Optional_payload_base<_Tp> - { - using _Optional_payload_base<_Tp>::_Optional_payload_base; - - _Optional_payload() = default; - ~_Optional_payload() = default; - _Optional_payload(const _Optional_payload&) = default; - _Optional_payload(_Optional_payload&&) = default; - - // Non-trivial copy assignment. - constexpr - _Optional_payload& - operator=(const _Optional_payload& __other) - { - this->_M_copy_assign(__other); - return *this; - } - - // Non-trivial move assignment. - constexpr - _Optional_payload& - operator=(_Optional_payload&& __other) - noexcept(__and_v, - is_nothrow_move_assignable<_Tp>>) - { - this->_M_move_assign(std::move(__other)); - return *this; - } - }; - - // Payload for optionals with non-trivial destructors. - template - struct _Optional_payload<_Tp, false, _Copy, _Move> - : _Optional_payload<_Tp, true, false, false> - { - // Base class implements all the constructors and assignment operators: - using _Optional_payload<_Tp, true, false, false>::_Optional_payload; - _Optional_payload() = default; - _Optional_payload(const _Optional_payload&) = default; - _Optional_payload(_Optional_payload&&) = default; - _Optional_payload& operator=(const _Optional_payload&) = default; - _Optional_payload& operator=(_Optional_payload&&) = default; - - // Destructor needs to destroy the contained value: - ~_Optional_payload() { this->_M_reset(); } - }; - - // Common base class for _Optional_base to avoid repeating these - // member functions in each specialization. - template - class _Optional_base_impl - { - protected: - using _Stored_type = remove_const_t<_Tp>; - - // The _M_construct operation has !_M_engaged as a precondition - // while _M_destruct has _M_engaged as a precondition. - template - void - _M_construct(_Args&&... __args) - noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) - { - ::new - (std::__addressof(static_cast<_Dp*>(this)->_M_payload._M_payload)) - _Stored_type(std::forward<_Args>(__args)...); - static_cast<_Dp*>(this)->_M_payload._M_engaged = true; - } - - void - _M_destruct() noexcept - { static_cast<_Dp*>(this)->_M_payload._M_destroy(); } - - // _M_reset is a 'safe' operation with no precondition. - constexpr void - _M_reset() noexcept - { static_cast<_Dp*>(this)->_M_payload._M_reset(); } - - constexpr bool _M_is_engaged() const noexcept - { return static_cast(this)->_M_payload._M_engaged; } - - // The _M_get operations have _M_engaged as a precondition. - constexpr _Tp& - _M_get() noexcept - { - __glibcxx_assert(this->_M_is_engaged()); - return static_cast<_Dp*>(this)->_M_payload._M_get(); - } - - constexpr const _Tp& - _M_get() const noexcept - { - __glibcxx_assert(this->_M_is_engaged()); - return static_cast(this)->_M_payload._M_get(); - } - }; - - /** - * @brief Class template that provides copy/move constructors of optional. - * - * Such a separate base class template is necessary in order to - * conditionally make copy/move constructors trivial. - * - * When the contained value is trivially copy/move constructible, - * the copy/move constructors of _Optional_base will invoke the - * trivial copy/move constructor of _Optional_payload. Otherwise, - * they will invoke _Optional_payload(bool, const _Optional_payload&) - * or _Optional_payload(bool, _Optional_payload&&) to initialize - * the contained value, if copying/moving an engaged optional. - * - * Whether the other special members are trivial is determined by the - * _Optional_payload<_Tp> specialization used for the _M_payload member. - * - * @see optional, _Enable_special_members - */ - template, - bool = is_trivially_move_constructible_v<_Tp>> - struct _Optional_base - : _Optional_base_impl<_Tp, _Optional_base<_Tp>> - { - // Constructors for disengaged optionals. - constexpr _Optional_base() = default; - - // Constructors for engaged optionals. - template, bool> = false> - constexpr explicit _Optional_base(in_place_t, _Args&&... __args) - : _M_payload(in_place, - std::forward<_Args>(__args)...) { } - - template&, - _Args&&...>, bool> = false> - constexpr explicit _Optional_base(in_place_t, - initializer_list<_Up> __il, - _Args&&... __args) - : _M_payload(in_place, - __il, std::forward<_Args>(__args)...) - { } - - // Copy and move constructors. - constexpr _Optional_base(const _Optional_base& __other) - : _M_payload(__other._M_payload._M_engaged, - __other._M_payload) - { } - - constexpr _Optional_base(_Optional_base&& __other) - noexcept(is_nothrow_move_constructible_v<_Tp>) - : _M_payload(__other._M_payload._M_engaged, - std::move(__other._M_payload)) - { } - - // Assignment operators. - _Optional_base& operator=(const _Optional_base&) = default; - _Optional_base& operator=(_Optional_base&&) = default; - - _Optional_payload<_Tp> _M_payload; - }; - - template - struct _Optional_base<_Tp, false, true> - : _Optional_base_impl<_Tp, _Optional_base<_Tp>> - { - // Constructors for disengaged optionals. - constexpr _Optional_base() = default; - - // Constructors for engaged optionals. - template, bool> = false> - constexpr explicit _Optional_base(in_place_t, _Args&&... __args) - : _M_payload(in_place, - std::forward<_Args>(__args)...) { } - - template&, - _Args&&...>, bool> = false> - constexpr explicit _Optional_base(in_place_t, - initializer_list<_Up> __il, - _Args&&... __args) - : _M_payload(in_place, - __il, std::forward<_Args>(__args)...) - { } - - // Copy and move constructors. - constexpr _Optional_base(const _Optional_base& __other) - : _M_payload(__other._M_payload._M_engaged, - __other._M_payload) - { } - - constexpr _Optional_base(_Optional_base&& __other) = default; - - // Assignment operators. - _Optional_base& operator=(const _Optional_base&) = default; - _Optional_base& operator=(_Optional_base&&) = default; - - _Optional_payload<_Tp> _M_payload; - }; - - template - struct _Optional_base<_Tp, true, false> - : _Optional_base_impl<_Tp, _Optional_base<_Tp>> - { - // Constructors for disengaged optionals. - constexpr _Optional_base() = default; - - // Constructors for engaged optionals. - template, bool> = false> - constexpr explicit _Optional_base(in_place_t, _Args&&... __args) - : _M_payload(in_place, - std::forward<_Args>(__args)...) { } - - template&, - _Args&&...>, bool> = false> - constexpr explicit _Optional_base(in_place_t, - initializer_list<_Up> __il, - _Args&&... __args) - : _M_payload(in_place, - __il, std::forward<_Args>(__args)...) - { } - - // Copy and move constructors. - constexpr _Optional_base(const _Optional_base& __other) = default; - - constexpr _Optional_base(_Optional_base&& __other) - noexcept(is_nothrow_move_constructible_v<_Tp>) - : _M_payload(__other._M_payload._M_engaged, - std::move(__other._M_payload)) - { } - - // Assignment operators. - _Optional_base& operator=(const _Optional_base&) = default; - _Optional_base& operator=(_Optional_base&&) = default; - - _Optional_payload<_Tp> _M_payload; - }; - - template - struct _Optional_base<_Tp, true, true> - : _Optional_base_impl<_Tp, _Optional_base<_Tp>> - { - // Constructors for disengaged optionals. - constexpr _Optional_base() = default; - - // Constructors for engaged optionals. - template, bool> = false> - constexpr explicit _Optional_base(in_place_t, _Args&&... __args) - : _M_payload(in_place, - std::forward<_Args>(__args)...) { } - - template&, - _Args&&...>, bool> = false> - constexpr explicit _Optional_base(in_place_t, - initializer_list<_Up> __il, - _Args&&... __args) - : _M_payload(in_place, - __il, std::forward<_Args>(__args)...) - { } - - // Copy and move constructors. - constexpr _Optional_base(const _Optional_base& __other) = default; - constexpr _Optional_base(_Optional_base&& __other) = default; - - // Assignment operators. - _Optional_base& operator=(const _Optional_base&) = default; - _Optional_base& operator=(_Optional_base&&) = default; - - _Optional_payload<_Tp> _M_payload; - }; - - template - class optional; - - template - using __converts_from_optional = - __or_&>, - is_constructible<_Tp, optional<_Up>&>, - is_constructible<_Tp, const optional<_Up>&&>, - is_constructible<_Tp, optional<_Up>&&>, - is_convertible&, _Tp>, - is_convertible&, _Tp>, - is_convertible&&, _Tp>, - is_convertible&&, _Tp>>; - - template - using __assigns_from_optional = - __or_&>, - is_assignable<_Tp&, optional<_Up>&>, - is_assignable<_Tp&, const optional<_Up>&&>, - is_assignable<_Tp&, optional<_Up>&&>>; - - /** - * @brief Class template for optional values. - */ - template - class optional - : private _Optional_base<_Tp>, - private _Enable_copy_move< - // Copy constructor. - is_copy_constructible_v<_Tp>, - // Copy assignment. - __and_v, is_copy_assignable<_Tp>>, - // Move constructor. - is_move_constructible_v<_Tp>, - // Move assignment. - __and_v, is_move_assignable<_Tp>>, - // Unique tag type. - optional<_Tp>> - { - static_assert(!is_same_v, nullopt_t>); - static_assert(!is_same_v, in_place_t>); - static_assert(!is_reference_v<_Tp>); - - private: - using _Base = _Optional_base<_Tp>; - - // SFINAE helpers - template - using __not_self = __not_>>; - template - using __not_tag = __not_>>; - template - using _Requires = enable_if_t<__and_v<_Cond...>, bool>; - - public: - using value_type = _Tp; - - constexpr optional() = default; - - constexpr optional(nullopt_t) noexcept { } - - // Converting constructors for engaged optionals. - template, __not_tag<_Up>, - is_constructible<_Tp, _Up&&>, - is_convertible<_Up&&, _Tp>> = true> - constexpr - optional(_Up&& __t) - : _Base(std::in_place, std::forward<_Up>(__t)) { } - - template, __not_tag<_Up>, - is_constructible<_Tp, _Up&&>, - __not_>> = false> - explicit constexpr - optional(_Up&& __t) - : _Base(std::in_place, std::forward<_Up>(__t)) { } - - template>, - is_constructible<_Tp, const _Up&>, - is_convertible, - __not_<__converts_from_optional<_Tp, _Up>>> = true> - constexpr - optional(const optional<_Up>& __t) - { - if (__t) - emplace(*__t); - } - - template>, - is_constructible<_Tp, const _Up&>, - __not_>, - __not_<__converts_from_optional<_Tp, _Up>>> = false> - explicit constexpr - optional(const optional<_Up>& __t) - { - if (__t) - emplace(*__t); - } - - template >, - is_constructible<_Tp, _Up&&>, - is_convertible<_Up&&, _Tp>, - __not_<__converts_from_optional<_Tp, _Up>>> = true> - constexpr - optional(optional<_Up>&& __t) - { - if (__t) - emplace(std::move(*__t)); - } - - template >, - is_constructible<_Tp, _Up&&>, - __not_>, - __not_<__converts_from_optional<_Tp, _Up>>> = false> - explicit constexpr - optional(optional<_Up>&& __t) - { - if (__t) - emplace(std::move(*__t)); - } - - template> = false> - explicit constexpr - optional(in_place_t, _Args&&... __args) - : _Base(std::in_place, std::forward<_Args>(__args)...) { } - - template&, - _Args&&...>> = false> - explicit constexpr - optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) - : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } - - // Assignment operators. - optional& - operator=(nullopt_t) noexcept - { - this->_M_reset(); - return *this; - } - - template - enable_if_t<__and_v<__not_self<_Up>, - __not_<__and_, - is_same<_Tp, decay_t<_Up>>>>, - is_constructible<_Tp, _Up>, - is_assignable<_Tp&, _Up>>, - optional&> - operator=(_Up&& __u) - { - if (this->_M_is_engaged()) - this->_M_get() = std::forward<_Up>(__u); - else - this->_M_construct(std::forward<_Up>(__u)); - - return *this; - } - - template - enable_if_t<__and_v<__not_>, - is_constructible<_Tp, const _Up&>, - is_assignable<_Tp&, _Up>, - __not_<__converts_from_optional<_Tp, _Up>>, - __not_<__assigns_from_optional<_Tp, _Up>>>, - optional&> - operator=(const optional<_Up>& __u) - { - if (__u) - { - if (this->_M_is_engaged()) - this->_M_get() = *__u; - else - this->_M_construct(*__u); - } - else - { - this->_M_reset(); - } - return *this; - } - - template - enable_if_t<__and_v<__not_>, - is_constructible<_Tp, _Up>, - is_assignable<_Tp&, _Up>, - __not_<__converts_from_optional<_Tp, _Up>>, - __not_<__assigns_from_optional<_Tp, _Up>>>, - optional&> - operator=(optional<_Up>&& __u) - { - if (__u) - { - if (this->_M_is_engaged()) - this->_M_get() = std::move(*__u); - else - this->_M_construct(std::move(*__u)); - } - else - { - this->_M_reset(); - } - - return *this; - } - - template - enable_if_t, _Tp&> - emplace(_Args&&... __args) - { - this->_M_reset(); - this->_M_construct(std::forward<_Args>(__args)...); - return this->_M_get(); - } - - template - enable_if_t&, - _Args&&...>, _Tp&> - emplace(initializer_list<_Up> __il, _Args&&... __args) - { - this->_M_reset(); - this->_M_construct(__il, std::forward<_Args>(__args)...); - return this->_M_get(); - } - - // Destructor is implicit, implemented in _Optional_base. - - // Swap. - void - swap(optional& __other) - noexcept(is_nothrow_move_constructible_v<_Tp> - && is_nothrow_swappable_v<_Tp>) - { - using std::swap; - - if (this->_M_is_engaged() && __other._M_is_engaged()) - swap(this->_M_get(), __other._M_get()); - else if (this->_M_is_engaged()) - { - __other._M_construct(std::move(this->_M_get())); - this->_M_destruct(); - } - else if (__other._M_is_engaged()) - { - this->_M_construct(std::move(__other._M_get())); - __other._M_destruct(); - } - } - - // Observers. - constexpr const _Tp* - operator->() const - { return std::__addressof(this->_M_get()); } - - constexpr _Tp* - operator->() - { return std::__addressof(this->_M_get()); } - - constexpr const _Tp& - operator*() const& - { return this->_M_get(); } - - constexpr _Tp& - operator*()& - { return this->_M_get(); } - - constexpr _Tp&& - operator*()&& - { return std::move(this->_M_get()); } - - constexpr const _Tp&& - operator*() const&& - { return std::move(this->_M_get()); } - - constexpr explicit operator bool() const noexcept - { return this->_M_is_engaged(); } - - constexpr bool has_value() const noexcept - { return this->_M_is_engaged(); } - - constexpr const _Tp& - value() const& - { - return this->_M_is_engaged() - ? this->_M_get() - : (__throw_bad_optional_access(), this->_M_get()); - } - - constexpr _Tp& - value()& - { - return this->_M_is_engaged() - ? this->_M_get() - : (__throw_bad_optional_access(), this->_M_get()); - } - - constexpr _Tp&& - value()&& - { - return this->_M_is_engaged() - ? std::move(this->_M_get()) - : (__throw_bad_optional_access(), std::move(this->_M_get())); - } - - constexpr const _Tp&& - value() const&& - { - return this->_M_is_engaged() - ? std::move(this->_M_get()) - : (__throw_bad_optional_access(), std::move(this->_M_get())); - } - - template - constexpr _Tp - value_or(_Up&& __u) const& - { - static_assert(is_copy_constructible_v<_Tp>); - static_assert(is_convertible_v<_Up&&, _Tp>); - - return this->_M_is_engaged() - ? this->_M_get() : static_cast<_Tp>(std::forward<_Up>(__u)); - } - - template - constexpr _Tp - value_or(_Up&& __u) && - { - static_assert(is_move_constructible_v<_Tp>); - static_assert(is_convertible_v<_Up&&, _Tp>); - - return this->_M_is_engaged() - ? std::move(this->_M_get()) - : static_cast<_Tp>(std::forward<_Up>(__u)); - } - - void reset() noexcept { this->_M_reset(); } - }; - - template - using __optional_relop_t = - enable_if_t::value, bool>; - - // Comparisons between optional values. - template - constexpr auto - operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) - -> __optional_relop_t() == declval<_Up>())> - { - return static_cast(__lhs) == static_cast(__rhs) - && (!__lhs || *__lhs == *__rhs); - } - - template - constexpr auto - operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) - -> __optional_relop_t() != declval<_Up>())> - { - return static_cast(__lhs) != static_cast(__rhs) - || (static_cast(__lhs) && *__lhs != *__rhs); - } - - template - constexpr auto - operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) - -> __optional_relop_t() < declval<_Up>())> - { - return static_cast(__rhs) && (!__lhs || *__lhs < *__rhs); - } - - template - constexpr auto - operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) - -> __optional_relop_t() > declval<_Up>())> - { - return static_cast(__lhs) && (!__rhs || *__lhs > *__rhs); - } - - template - constexpr auto - operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) - -> __optional_relop_t() <= declval<_Up>())> - { - return !__lhs || (static_cast(__rhs) && *__lhs <= *__rhs); - } - - template - constexpr auto - operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) - -> __optional_relop_t() >= declval<_Up>())> - { - return !__rhs || (static_cast(__lhs) && *__lhs >= *__rhs); - } - -#ifdef __cpp_lib_three_way_comparison - template _Up> - constexpr compare_three_way_result_t<_Tp, _Up> - operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) - { - return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y); - } -#endif - - // Comparisons with nullopt. - template - constexpr bool - operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept - { return !__lhs; } - -#ifdef __cpp_lib_three_way_comparison - template - constexpr strong_ordering - operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept - { return bool(__x) <=> false; } -#else - template - constexpr bool - operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept - { return !__rhs; } - - template - constexpr bool - operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept - { return static_cast(__lhs); } - - template - constexpr bool - operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept - { return static_cast(__rhs); } - - template - constexpr bool - operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept - { return false; } - - template - constexpr bool - operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept - { return static_cast(__rhs); } - - template - constexpr bool - operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept - { return static_cast(__lhs); } - - template - constexpr bool - operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept - { return false; } - - template - constexpr bool - operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept - { return !__lhs; } - - template - constexpr bool - operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept - { return true; } - - template - constexpr bool - operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept - { return true; } - - template - constexpr bool - operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept - { return !__rhs; } -#endif // three-way-comparison - - // Comparisons with value type. - template - constexpr auto - operator==(const optional<_Tp>& __lhs, const _Up& __rhs) - -> __optional_relop_t() == declval<_Up>())> - { return __lhs && *__lhs == __rhs; } - - template - constexpr auto - operator==(const _Up& __lhs, const optional<_Tp>& __rhs) - -> __optional_relop_t() == declval<_Tp>())> - { return __rhs && __lhs == *__rhs; } - - template - constexpr auto - operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) - -> __optional_relop_t() != declval<_Up>())> - { return !__lhs || *__lhs != __rhs; } - - template - constexpr auto - operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) - -> __optional_relop_t() != declval<_Tp>())> - { return !__rhs || __lhs != *__rhs; } - - template - constexpr auto - operator<(const optional<_Tp>& __lhs, const _Up& __rhs) - -> __optional_relop_t() < declval<_Up>())> - { return !__lhs || *__lhs < __rhs; } - - template - constexpr auto - operator<(const _Up& __lhs, const optional<_Tp>& __rhs) - -> __optional_relop_t() < declval<_Tp>())> - { return __rhs && __lhs < *__rhs; } - - template - constexpr auto - operator>(const optional<_Tp>& __lhs, const _Up& __rhs) - -> __optional_relop_t() > declval<_Up>())> - { return __lhs && *__lhs > __rhs; } - - template - constexpr auto - operator>(const _Up& __lhs, const optional<_Tp>& __rhs) - -> __optional_relop_t() > declval<_Tp>())> - { return !__rhs || __lhs > *__rhs; } - - template - constexpr auto - operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) - -> __optional_relop_t() <= declval<_Up>())> - { return !__lhs || *__lhs <= __rhs; } - - template - constexpr auto - operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) - -> __optional_relop_t() <= declval<_Tp>())> - { return __rhs && __lhs <= *__rhs; } - - template - constexpr auto - operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) - -> __optional_relop_t() >= declval<_Up>())> - { return __lhs && *__lhs >= __rhs; } - - template - constexpr auto - operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) - -> __optional_relop_t() >= declval<_Tp>())> - { return !__rhs || __lhs >= *__rhs; } - -#ifdef __cpp_lib_three_way_comparison - template - constexpr compare_three_way_result_t<_Tp, _Up> - operator<=>(const optional<_Tp>& __x, const _Up& __v) - { return bool(__x) ? *__x <=> __v : strong_ordering::less; } -#endif - - // Swap and creation functions. - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2748. swappable traits for optionals - template - inline enable_if_t && is_swappable_v<_Tp>> - swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) - noexcept(noexcept(__lhs.swap(__rhs))) - { __lhs.swap(__rhs); } - - template - enable_if_t && is_swappable_v<_Tp>)> - swap(optional<_Tp>&, optional<_Tp>&) = delete; - - template - constexpr optional> - make_optional(_Tp&& __t) - { return optional> { std::forward<_Tp>(__t) }; } - - template - constexpr optional<_Tp> - make_optional(_Args&&... __args) - { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; } - - template - constexpr optional<_Tp> - make_optional(initializer_list<_Up> __il, _Args&&... __args) - { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; } - - // Hash. - - template, - bool = __poison_hash<_Up>::__enable_hash_call> - struct __optional_hash_call_base - { - size_t - operator()(const optional<_Tp>& __t) const - noexcept(noexcept(hash<_Up>{}(*__t))) - { - // We pick an arbitrary hash for disengaged optionals which hopefully - // usual values of _Tp won't typically hash to. - constexpr size_t __magic_disengaged_hash = static_cast(-3333); - return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; - } - }; - - template - struct __optional_hash_call_base<_Tp, _Up, false> {}; - - template - struct hash> - : private __poison_hash>, - public __optional_hash_call_base<_Tp> - { - using result_type [[__deprecated__]] = size_t; - using argument_type [[__deprecated__]] = optional<_Tp>; - }; - - template - struct __is_fast_hash>> : __is_fast_hash> - { }; - - /// @} - -#if __cpp_deduction_guides >= 201606 - template optional(_Tp) -> optional<_Tp>; -#endif - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++17 - -#endif // _GLIBCXX_OPTIONAL diff --git a/resources/sources/avr-libstdcpp/include/ostream b/resources/sources/avr-libstdcpp/include/ostream new file mode 100644 index 000000000..841859075 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ostream @@ -0,0 +1,4 @@ +// Stub: I/O streams not available on AVR +#ifndef _AVR_OSTREAM_STUB +#define _AVR_OSTREAM_STUB +#endif diff --git a/resources/sources/avr-libstdcpp/include/queue b/resources/sources/avr-libstdcpp/include/queue deleted file mode 100644 index ef6b6fd60..000000000 --- a/resources/sources/avr-libstdcpp/include/queue +++ /dev/null @@ -1,66 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/queue - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_QUEUE -#define _GLIBCXX_QUEUE 1 - -#pragma GCC system_header - -#include -#include -#include -#include -#include - -#endif /* _GLIBCXX_QUEUE */ diff --git a/resources/sources/avr-libstdcpp/include/random b/resources/sources/avr-libstdcpp/include/random deleted file mode 100644 index 7a68ba37f..000000000 --- a/resources/sources/avr-libstdcpp/include/random +++ /dev/null @@ -1,54 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/random - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_RANDOM -#define _GLIBCXX_RANDOM 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include -#include -#include - -#ifdef _GLIBCXX_USE_C99_STDINT_TR1 - -#include // For uint_fast32_t, uint_fast64_t, uint_least32_t -#include -#include - -#endif // _GLIBCXX_USE_C99_STDINT_TR1 - -#endif // C++11 - -#endif // _GLIBCXX_RANDOM diff --git a/resources/sources/avr-libstdcpp/include/ranges b/resources/sources/avr-libstdcpp/include/ranges deleted file mode 100644 index 56800095b..000000000 --- a/resources/sources/avr-libstdcpp/include/ranges +++ /dev/null @@ -1,3561 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2019-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/ranges - * This is a Standard C++ Library header. - * @ingroup concepts - */ - -#ifndef _GLIBCXX_RANGES -#define _GLIBCXX_RANGES 1 - -#if __cplusplus > 201703L - -#pragma GCC system_header - -#include - -#if __cpp_lib_concepts - -#include -#include -#include -#include -#include -#include - -/** - * @defgroup ranges Ranges - * - * Components for dealing with ranges of elements. - */ - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION -namespace ranges -{ - // [range.range] The range concept. - // [range.sized] The sized_range concept. - // Defined in - - // [range.refinements] - // Defined in - - struct view_base { }; - - template - inline constexpr bool enable_view = derived_from<_Tp, view_base>; - - template - concept view - = range<_Tp> && movable<_Tp> && default_initializable<_Tp> - && enable_view<_Tp>; - - /// A range which can be safely converted to a view. - template - concept viewable_range = range<_Tp> - && (borrowed_range<_Tp> || view>); - - namespace __detail - { - template - concept __simple_view = view<_Range> && range - && same_as, iterator_t> - && same_as, sentinel_t>; - - template - concept __has_arrow = input_iterator<_It> - && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); }); - - template - concept __not_same_as - = !same_as, remove_cvref_t<_Up>>; - } // namespace __detail - - template - requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> - class view_interface : public view_base - { - private: - constexpr _Derived& _M_derived() noexcept - { - static_assert(derived_from<_Derived, view_interface<_Derived>>); - static_assert(view<_Derived>); - return static_cast<_Derived&>(*this); - } - - constexpr const _Derived& _M_derived() const noexcept - { - static_assert(derived_from<_Derived, view_interface<_Derived>>); - static_assert(view<_Derived>); - return static_cast(*this); - } - - public: - constexpr bool - empty() requires forward_range<_Derived> - { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); } - - constexpr bool - empty() const requires forward_range - { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); } - - constexpr explicit - operator bool() requires requires { ranges::empty(_M_derived()); } - { return !ranges::empty(_M_derived()); } - - constexpr explicit - operator bool() const requires requires { ranges::empty(_M_derived()); } - { return !ranges::empty(_M_derived()); } - - constexpr auto - data() requires contiguous_iterator> - { return to_address(ranges::begin(_M_derived())); } - - constexpr auto - data() const - requires range - && contiguous_iterator> - { return to_address(ranges::begin(_M_derived())); } - - constexpr auto - size() - requires forward_range<_Derived> - && sized_sentinel_for, iterator_t<_Derived>> - { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); } - - constexpr auto - size() const - requires forward_range - && sized_sentinel_for, - iterator_t> - { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); } - - constexpr decltype(auto) - front() requires forward_range<_Derived> - { - __glibcxx_assert(!empty()); - return *ranges::begin(_M_derived()); - } - - constexpr decltype(auto) - front() const requires forward_range - { - __glibcxx_assert(!empty()); - return *ranges::begin(_M_derived()); - } - - constexpr decltype(auto) - back() - requires bidirectional_range<_Derived> && common_range<_Derived> - { - __glibcxx_assert(!empty()); - return *ranges::prev(ranges::end(_M_derived())); - } - - constexpr decltype(auto) - back() const - requires bidirectional_range - && common_range - { - __glibcxx_assert(!empty()); - return *ranges::prev(ranges::end(_M_derived())); - } - - template - constexpr decltype(auto) - operator[](range_difference_t<_Range> __n) - { return ranges::begin(_M_derived())[__n]; } - - template - constexpr decltype(auto) - operator[](range_difference_t<_Range> __n) const - { return ranges::begin(_M_derived())[__n]; } - }; - - namespace __detail - { - template - concept __convertible_to_non_slicing = convertible_to<_From, _To> - && !(is_pointer_v> && is_pointer_v> - && __not_same_as>, - remove_pointer_t>>); - - template - concept __pair_like - = !is_reference_v<_Tp> && requires(_Tp __t) - { - typename tuple_size<_Tp>::type; - requires derived_from, integral_constant>; - typename tuple_element_t<0, remove_const_t<_Tp>>; - typename tuple_element_t<1, remove_const_t<_Tp>>; - { get<0>(__t) } -> convertible_to&>; - { get<1>(__t) } -> convertible_to&>; - }; - - template - concept __pair_like_convertible_from - = !range<_Tp> && __pair_like<_Tp> - && constructible_from<_Tp, _Up, _Vp> - && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>> - && convertible_to<_Vp, tuple_element_t<1, _Tp>>; - - template - concept __iterator_sentinel_pair - = !range<_Tp> && __pair_like<_Tp> - && sentinel_for, tuple_element_t<0, _Tp>>; - - } // namespace __detail - - enum class subrange_kind : bool { unsized, sized }; - - template _Sent = _It, - subrange_kind _Kind = sized_sentinel_for<_Sent, _It> - ? subrange_kind::sized : subrange_kind::unsized> - requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>) - class subrange : public view_interface> - { - private: - // XXX: gcc complains when using constexpr here - static const bool _S_store_size - = _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>; - - _It _M_begin = _It(); - _Sent _M_end = _Sent(); - - template - struct _Size - { }; - - template - struct _Size<_Tp, true> - { __detail::__make_unsigned_like_t<_Tp> _M_size; }; - - [[no_unique_address]] _Size> _M_size = {}; - - public: - subrange() = default; - - constexpr - subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s) - requires (!_S_store_size) - : _M_begin(std::move(__i)), _M_end(__s) - { } - - constexpr - subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s, - __detail::__make_unsigned_like_t> __n) - requires (_Kind == subrange_kind::sized) - : _M_begin(std::move(__i)), _M_end(__s) - { - using __detail::__to_unsigned_like; - __glibcxx_assert(__n == __to_unsigned_like(ranges::distance(__i, __s))); - if constexpr (_S_store_size) - _M_size._M_size = __n; - } - - template<__detail::__not_same_as _Rng> - requires borrowed_range<_Rng> - && __detail::__convertible_to_non_slicing, _It> - && convertible_to, _Sent> - constexpr - subrange(_Rng&& __r) requires _S_store_size && sized_range<_Rng> - : subrange{__r, ranges::size(__r)} - { } - - template<__detail::__not_same_as _Rng> - requires borrowed_range<_Rng> - && __detail::__convertible_to_non_slicing, _It> - && convertible_to, _Sent> - constexpr - subrange(_Rng&& __r) requires (!_S_store_size) - : subrange{ranges::begin(__r), ranges::end(__r)} - { } - - template - requires __detail::__convertible_to_non_slicing, _It> - && convertible_to, _Sent> - constexpr - subrange(_Rng&& __r, - __detail::__make_unsigned_like_t> __n) - requires (_Kind == subrange_kind::sized) - : subrange{ranges::begin(__r), ranges::end(__r), __n} - { } - - template<__detail::__not_same_as _PairLike> - requires __detail::__pair_like_convertible_from<_PairLike, const _It&, - const _Sent&> - constexpr - operator _PairLike() const - { return _PairLike(_M_begin, _M_end); } - - constexpr _It - begin() const requires copyable<_It> - { return _M_begin; } - - [[nodiscard]] constexpr _It - begin() requires (!copyable<_It>) - { return std::move(_M_begin); } - - constexpr _Sent end() const { return _M_end; } - - constexpr bool empty() const { return _M_begin == _M_end; } - - constexpr __detail::__make_unsigned_like_t> - size() const requires (_Kind == subrange_kind::sized) - { - if constexpr (_S_store_size) - return _M_size._M_size; - else - return __detail::__to_unsigned_like(_M_end - _M_begin); - } - - [[nodiscard]] constexpr subrange - next(iter_difference_t<_It> __n = 1) const & - requires forward_iterator<_It> - { - auto __tmp = *this; - __tmp.advance(__n); - return __tmp; - } - - [[nodiscard]] constexpr subrange - next(iter_difference_t<_It> __n = 1) && - { - advance(__n); - return std::move(*this); - } - - [[nodiscard]] constexpr subrange - prev(iter_difference_t<_It> __n = 1) const - requires bidirectional_iterator<_It> - { - auto __tmp = *this; - __tmp.advance(-__n); - return __tmp; - } - - constexpr subrange& - advance(iter_difference_t<_It> __n) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3433. subrange::advance(n) has UB when n < 0 - if constexpr (bidirectional_iterator<_It>) - if (__n < 0) - { - ranges::advance(_M_begin, __n); - if constexpr (_S_store_size) - _M_size._M_size += __detail::__to_unsigned_like(-__n); - return *this; - } - - __glibcxx_assert(__n >= 0); - auto __d = __n - ranges::advance(_M_begin, __n, _M_end); - if constexpr (_S_store_size) - _M_size._M_size -= __detail::__to_unsigned_like(__d); - return *this; - } - }; - - template _Sent> - subrange(_It, _Sent) -> subrange<_It, _Sent>; - - template _Sent> - subrange(_It, _Sent, - __detail::__make_unsigned_like_t>) - -> subrange<_It, _Sent, subrange_kind::sized>; - - template<__detail::__iterator_sentinel_pair _Pr> - subrange(_Pr) - -> subrange, tuple_element_t<1, _Pr>>; - - template<__detail::__iterator_sentinel_pair _Pr> - subrange(_Pr, __detail::__make_unsigned_like_t>>) - -> subrange, tuple_element_t<1, _Pr>, - subrange_kind::sized>; - - template - subrange(_Rng&&) - -> subrange, sentinel_t<_Rng>, - (sized_range<_Rng> - || sized_sentinel_for, iterator_t<_Rng>>) - ? subrange_kind::sized : subrange_kind::unsized>; - - template - subrange(_Rng&&, - __detail::__make_unsigned_like_t>) - -> subrange, sentinel_t<_Rng>, subrange_kind::sized>; - - template - requires (_Num < 2) - constexpr auto - get(const subrange<_It, _Sent, _Kind>& __r) - { - if constexpr (_Num == 0) - return __r.begin(); - else - return __r.end(); - } - - template - requires (_Num < 2) - constexpr auto - get(subrange<_It, _Sent, _Kind>&& __r) - { - if constexpr (_Num == 0) - return __r.begin(); - else - return __r.end(); - } - - template _Sent, - subrange_kind _Kind> - inline constexpr bool - enable_borrowed_range> = true; - -} // namespace ranges - - using ranges::get; - -namespace ranges -{ - /// Type returned by algorithms instead of a dangling iterator or subrange. - struct dangling - { - constexpr dangling() noexcept = default; - template - constexpr dangling(_Args&&...) noexcept { } - }; - - template - using borrowed_iterator_t = conditional_t, - iterator_t<_Range>, - dangling>; - - template - using borrowed_subrange_t = conditional_t, - subrange>, - dangling>; - - template requires is_object_v<_Tp> - class empty_view - : public view_interface> - { - public: - static constexpr _Tp* begin() noexcept { return nullptr; } - static constexpr _Tp* end() noexcept { return nullptr; } - static constexpr _Tp* data() noexcept { return nullptr; } - static constexpr size_t size() noexcept { return 0; } - static constexpr bool empty() noexcept { return true; } - }; - - template - inline constexpr bool enable_borrowed_range> = true; - - namespace __detail - { - template requires is_object_v<_Tp> - struct __box : std::optional<_Tp> - { - using std::optional<_Tp>::optional; - - constexpr - __box() - noexcept(is_nothrow_default_constructible_v<_Tp>) - requires default_initializable<_Tp> - : std::optional<_Tp>{std::in_place} - { } - - __box(const __box&) = default; - __box(__box&&) = default; - - using std::optional<_Tp>::operator=; - - __box& - operator=(const __box& __that) - noexcept(is_nothrow_copy_constructible_v<_Tp>) - requires (!assignable_from<_Tp&, const _Tp&>) - { - if ((bool)__that) - this->emplace(*__that); - else - this->reset(); - return *this; - } - - __box& - operator=(__box&& __that) - noexcept(is_nothrow_move_constructible_v<_Tp>) - requires (!assignable_from<_Tp&, _Tp>) - { - if ((bool)__that) - this->emplace(std::move(*__that)); - else - this->reset(); - return *this; - } - }; - - } // namespace __detail - - /// A view that contains exactly one element. - template requires is_object_v<_Tp> - class single_view : public view_interface> - { - public: - single_view() = default; - - constexpr explicit - single_view(const _Tp& __t) - : _M_value(__t) - { } - - constexpr explicit - single_view(_Tp&& __t) - : _M_value(std::move(__t)) - { } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3428. single_view's in place constructor should be explicit - template - requires constructible_from<_Tp, _Args...> - constexpr explicit - single_view(in_place_t, _Args&&... __args) - : _M_value{in_place, std::forward<_Args>(__args)...} - { } - - constexpr _Tp* - begin() noexcept - { return data(); } - - constexpr const _Tp* - begin() const noexcept - { return data(); } - - constexpr _Tp* - end() noexcept - { return data() + 1; } - - constexpr const _Tp* - end() const noexcept - { return data() + 1; } - - static constexpr size_t - size() noexcept - { return 1; } - - constexpr _Tp* - data() noexcept - { return _M_value.operator->(); } - - constexpr const _Tp* - data() const noexcept - { return _M_value.operator->(); } - - private: - __detail::__box<_Tp> _M_value; - }; - - namespace __detail - { - template - constexpr auto __to_signed_like(_Wp __w) noexcept - { - if constexpr (!integral<_Wp>) - return iter_difference_t<_Wp>(); - else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp)) - return iter_difference_t<_Wp>(__w); - else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp)) - return ptrdiff_t(__w); - else if constexpr (sizeof(long long) > sizeof(_Wp)) - return (long long)(__w); -#ifdef __SIZEOF_INT128__ - else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp)) - return __int128(__w); -#endif - else - return __max_diff_type(__w); - } - - template - using __iota_diff_t = decltype(__to_signed_like(std::declval<_Wp>())); - - template - concept __decrementable = incrementable<_It> - && requires(_It __i) - { - { --__i } -> same_as<_It&>; - { __i-- } -> same_as<_It>; - }; - - template - concept __advanceable = __decrementable<_It> && totally_ordered<_It> - && requires( _It __i, const _It __j, const __iota_diff_t<_It> __n) - { - { __i += __n } -> same_as<_It&>; - { __i -= __n } -> same_as<_It&>; - _It(__j + __n); - _It(__n + __j); - _It(__j - __n); - { __j - __j } -> convertible_to<__iota_diff_t<_It>>; - }; - - } // namespace __detail - - template - requires std::__detail::__weakly_eq_cmp_with<_Winc, _Bound> - && semiregular<_Winc> - class iota_view : public view_interface> - { - private: - struct _Sentinel; - - struct _Iterator - { - private: - static auto - _S_iter_cat() - { - using namespace __detail; - if constexpr (__advanceable<_Winc>) - return random_access_iterator_tag{}; - else if constexpr (__decrementable<_Winc>) - return bidirectional_iterator_tag{}; - else if constexpr (incrementable<_Winc>) - return forward_iterator_tag{}; - else - return input_iterator_tag{}; - } - - public: - using iterator_category = decltype(_S_iter_cat()); - using value_type = _Winc; - using difference_type = __detail::__iota_diff_t<_Winc>; - - _Iterator() = default; - - constexpr explicit - _Iterator(_Winc __value) - : _M_value(__value) { } - - constexpr _Winc - operator*() const noexcept(is_nothrow_copy_constructible_v<_Winc>) - { return _M_value; } - - constexpr _Iterator& - operator++() - { - ++_M_value; - return *this; - } - - constexpr void - operator++(int) - { ++*this; } - - constexpr _Iterator - operator++(int) requires incrementable<_Winc> - { - auto __tmp = *this; - ++*this; - return __tmp; - } - - constexpr _Iterator& - operator--() requires __detail::__decrementable<_Winc> - { - --_M_value; - return *this; - } - - constexpr _Iterator - operator--(int) requires __detail::__decrementable<_Winc> - { - auto __tmp = *this; - --*this; - return __tmp; - } - - constexpr _Iterator& - operator+=(difference_type __n) requires __detail::__advanceable<_Winc> - { - using __detail::__is_integer_like; - using __detail::__is_signed_integer_like; - if constexpr (__is_integer_like<_Winc> - && !__is_signed_integer_like<_Winc>) - { - if (__n >= difference_type(0)) - _M_value += static_cast<_Winc>(__n); - else - _M_value -= static_cast<_Winc>(-__n); - } - else - _M_value += __n; - return *this; - } - - constexpr _Iterator& - operator-=(difference_type __n) requires __detail::__advanceable<_Winc> - { - using __detail::__is_integer_like; - using __detail::__is_signed_integer_like; - if constexpr (__is_integer_like<_Winc> - && !__is_signed_integer_like<_Winc>) - { - if (__n >= difference_type(0)) - _M_value -= static_cast<_Winc>(__n); - else - _M_value += static_cast<_Winc>(-__n); - } - else - _M_value -= __n; - return *this; - } - - constexpr _Winc - operator[](difference_type __n) const - requires __detail::__advanceable<_Winc> - { return _Winc(_M_value + __n); } - - friend constexpr bool - operator==(const _Iterator& __x, const _Iterator& __y) - requires equality_comparable<_Winc> - { return __x._M_value == __y._M_value; } - - friend constexpr bool - operator<(const _Iterator& __x, const _Iterator& __y) - requires totally_ordered<_Winc> - { return __x._M_value < __y._M_value; } - - friend constexpr bool - operator>(const _Iterator& __x, const _Iterator& __y) - requires totally_ordered<_Winc> - { return __y < __x; } - - friend constexpr bool - operator<=(const _Iterator& __x, const _Iterator& __y) - requires totally_ordered<_Winc> - { return !(__y < __x); } - - friend constexpr bool - operator>=(const _Iterator& __x, const _Iterator& __y) - requires totally_ordered<_Winc> - { return !(__x < __y); } - -#ifdef __cpp_lib_three_way_comparison - friend constexpr auto - operator<=>(const _Iterator& __x, const _Iterator& __y) - requires totally_ordered<_Winc> && three_way_comparable<_Winc> - { return __x._M_value <=> __y._M_value; } -#endif - - friend constexpr _Iterator - operator+(_Iterator __i, difference_type __n) - requires __detail::__advanceable<_Winc> - { return __i += __n; } - - friend constexpr _Iterator - operator+(difference_type __n, _Iterator __i) - requires __detail::__advanceable<_Winc> - { return __i += __n; } - - friend constexpr _Iterator - operator-(_Iterator __i, difference_type __n) - requires __detail::__advanceable<_Winc> - { return __i -= __n; } - - friend constexpr difference_type - operator-(const _Iterator& __x, const _Iterator& __y) - requires __detail::__advanceable<_Winc> - { - using __detail::__is_integer_like; - using __detail::__is_signed_integer_like; - using _Dt = difference_type; - if constexpr (__is_integer_like<_Winc>) - { - if constexpr (__is_signed_integer_like<_Winc>) - return _Dt(_Dt(__x._M_value) - _Dt(__y._M_value)); - else - return (__y._M_value > __x._M_value) - ? _Dt(-_Dt(__y._M_value - __x._M_value)) - : _Dt(__x._M_value - __y._M_value); - } - else - return __x._M_value - __y._M_value; - } - - private: - _Winc _M_value = _Winc(); - - friend _Sentinel; - }; - - struct _Sentinel - { - private: - constexpr bool - _M_equal(const _Iterator& __x) const - { return __x._M_value == _M_bound; } - - _Bound _M_bound = _Bound(); - - public: - _Sentinel() = default; - - constexpr explicit - _Sentinel(_Bound __bound) - : _M_bound(__bound) { } - - friend constexpr bool - operator==(const _Iterator& __x, const _Sentinel& __y) - { return __y._M_equal(__x); } - - friend constexpr iter_difference_t<_Winc> - operator-(const _Iterator& __x, const _Sentinel& __y) - requires sized_sentinel_for<_Bound, _Winc> - { return __x._M_value - __y._M_bound; } - - friend constexpr iter_difference_t<_Winc> - operator-(const _Sentinel& __x, const _Iterator& __y) - requires sized_sentinel_for<_Bound, _Winc> - { return -(__y - __x); } - }; - - _Winc _M_value = _Winc(); - _Bound _M_bound = _Bound(); - - public: - iota_view() = default; - - constexpr explicit - iota_view(_Winc __value) - : _M_value(__value) - { } - - constexpr - iota_view(type_identity_t<_Winc> __value, - type_identity_t<_Bound> __bound) - : _M_value(__value), _M_bound(__bound) - { - if constexpr (totally_ordered_with<_Winc, _Bound>) - { - __glibcxx_assert( bool(__value <= __bound) ); - } - } - - constexpr _Iterator - begin() const { return _Iterator{_M_value}; } - - constexpr auto - end() const - { - if constexpr (same_as<_Bound, unreachable_sentinel_t>) - return unreachable_sentinel; - else - return _Sentinel{_M_bound}; - } - - constexpr _Iterator - end() const requires same_as<_Winc, _Bound> - { return _Iterator{_M_bound}; } - - constexpr auto - size() const - requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>) - || (integral<_Winc> && integral<_Bound>) - || sized_sentinel_for<_Bound, _Winc> - { - using __detail::__is_integer_like; - using __detail::__to_unsigned_like; - if constexpr (__is_integer_like<_Winc> && __is_integer_like<_Bound>) - return (_M_value < 0) - ? ((_M_bound < 0) - ? __to_unsigned_like(-_M_value) - __to_unsigned_like(-_M_bound) - : __to_unsigned_like(_M_bound) + __to_unsigned_like(-_M_value)) - : __to_unsigned_like(_M_bound) - __to_unsigned_like(_M_value); - else - return __to_unsigned_like(_M_bound - _M_value); - } - }; - - template - requires (!__detail::__is_integer_like<_Winc> - || !__detail::__is_integer_like<_Bound> - || (__detail::__is_signed_integer_like<_Winc> - == __detail::__is_signed_integer_like<_Bound>)) - iota_view(_Winc, _Bound) -> iota_view<_Winc, _Bound>; - - template - inline constexpr bool - enable_borrowed_range> = true; - -namespace views -{ - template - inline constexpr empty_view<_Tp> empty{}; - - struct _Single - { - template - constexpr auto - operator()(_Tp&& __e) const - { return single_view{std::forward<_Tp>(__e)}; } - }; - - inline constexpr _Single single{}; - - struct _Iota - { - template - constexpr auto - operator()(_Tp&& __e) const - { return iota_view{std::forward<_Tp>(__e)}; } - - template - constexpr auto - operator()(_Tp&& __e, _Up&& __f) const - { return iota_view{std::forward<_Tp>(__e), std::forward<_Up>(__f)}; } - }; - - inline constexpr _Iota iota{}; -} // namespace views - -namespace __detail -{ - struct _Empty { }; - - // Alias for a type that is conditionally present - // (and is an empty type otherwise). - // Data members using this alias should use [[no_unique_address]] so that - // they take no space when not needed. - template - using __maybe_present_t = conditional_t<_Present, _Tp, _Empty>; - - // Alias for a type that is conditionally const. - template - using __maybe_const_t = conditional_t<_Const, const _Tp, _Tp>; - -} // namespace __detail - -namespace views -{ - namespace __adaptor - { - template - inline constexpr auto - __maybe_refwrap(_Tp& __arg) - { return reference_wrapper<_Tp>{__arg}; } - - template - inline constexpr auto - __maybe_refwrap(const _Tp& __arg) - { return reference_wrapper{__arg}; } - - template - inline constexpr decltype(auto) - __maybe_refwrap(_Tp&& __arg) - { return std::forward<_Tp>(__arg); } - - template - struct _RangeAdaptorClosure; - - template - struct _RangeAdaptor - { - protected: - [[no_unique_address]] - __detail::__maybe_present_t, - _Callable> _M_callable; - - public: - constexpr - _RangeAdaptor(const _Callable& = {}) - requires is_default_constructible_v<_Callable> - { } - - constexpr - _RangeAdaptor(_Callable __callable) - requires (!is_default_constructible_v<_Callable>) - : _M_callable(std::move(__callable)) - { } - - template - requires (sizeof...(_Args) >= 1) - constexpr auto - operator()(_Args&&... __args) const - { - // [range.adaptor.object]: If a range adaptor object accepts more - // than one argument, then the following expressions are equivalent: - // - // (1) adaptor(range, args...) - // (2) adaptor(args...)(range) - // (3) range | adaptor(args...) - // - // In this case, adaptor(args...) is a range adaptor closure object. - // - // We handle (1) and (2) here, and (3) is just a special case of a - // more general case already handled by _RangeAdaptorClosure. - if constexpr (is_invocable_v<_Callable, _Args...>) - { - static_assert(sizeof...(_Args) != 1, - "a _RangeAdaptor that accepts only one argument " - "should be defined as a _RangeAdaptorClosure"); - // Here we handle adaptor(range, args...) -- just forward all - // arguments to the underlying adaptor routine. - return _Callable{}(std::forward<_Args>(__args)...); - } - else - { - // Here we handle adaptor(args...)(range). - // Given args..., we return a _RangeAdaptorClosure that takes a - // range argument, such that (2) is equivalent to (1). - // - // We need to be careful about how we capture args... in this - // closure. By using __maybe_refwrap, we capture lvalue - // references by reference (through a reference_wrapper) and - // otherwise capture by value. - auto __closure - = [...__args(__maybe_refwrap(std::forward<_Args>(__args)))] - (_Range&& __r) { - // This static_cast has two purposes: it forwards a - // reference_wrapper capture as a T&, and otherwise - // forwards the captured argument as an rvalue. - return _Callable{}(std::forward<_Range>(__r), - (static_cast>> - (__args))...); - }; - using _ClosureType = decltype(__closure); - return _RangeAdaptorClosure<_ClosureType>(std::move(__closure)); - } - } - }; - - template - _RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>; - - template - struct _RangeAdaptorClosure : public _RangeAdaptor<_Callable> - { - using _RangeAdaptor<_Callable>::_RangeAdaptor; - - template - requires requires { declval<_Callable>()(declval<_Range>()); } - constexpr auto - operator()(_Range&& __r) const - { - if constexpr (is_default_constructible_v<_Callable>) - return _Callable{}(std::forward<_Range>(__r)); - else - return this->_M_callable(std::forward<_Range>(__r)); - } - - template - requires requires { declval<_Callable>()(declval<_Range>()); } - friend constexpr auto - operator|(_Range&& __r, const _RangeAdaptorClosure& __o) - { return __o(std::forward<_Range>(__r)); } - - template - friend constexpr auto - operator|(const _RangeAdaptorClosure<_Tp>& __x, - const _RangeAdaptorClosure& __y) - { - if constexpr (is_default_constructible_v<_Tp> - && is_default_constructible_v<_Callable>) - { - auto __closure = [] (_Up&& __e) { - return std::forward<_Up>(__e) | decltype(__x){} | decltype(__y){}; - }; - return _RangeAdaptorClosure(__closure); - } - else if constexpr (is_default_constructible_v<_Tp> - && !is_default_constructible_v<_Callable>) - { - auto __closure = [__y] (_Up&& __e) { - return std::forward<_Up>(__e) | decltype(__x){} | __y; - }; - return _RangeAdaptorClosure(__closure); - } - else if constexpr (!is_default_constructible_v<_Tp> - && is_default_constructible_v<_Callable>) - { - auto __closure = [__x] (_Up&& __e) { - return std::forward<_Up>(__e) | __x | decltype(__y){}; - }; - return _RangeAdaptorClosure(__closure); - } - else - { - auto __closure = [__x, __y] (_Up&& __e) { - return std::forward<_Up>(__e) | __x | __y; - }; - return _RangeAdaptorClosure(__closure); - } - } - }; - - template - _RangeAdaptorClosure(_Callable) -> _RangeAdaptorClosure<_Callable>; - } // namespace __adaptor -} // namespace views - - template requires is_object_v<_Range> - class ref_view : public view_interface> - { - private: - _Range* _M_r = nullptr; - - static void _S_fun(_Range&); // not defined - static void _S_fun(_Range&&) = delete; - - public: - constexpr - ref_view() noexcept = default; - - template<__detail::__not_same_as _Tp> - requires convertible_to<_Tp, _Range&> - && requires { _S_fun(declval<_Tp>()); } - constexpr - ref_view(_Tp&& __t) - : _M_r(std::__addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) - { } - - constexpr _Range& - base() const - { return *_M_r; } - - constexpr iterator_t<_Range> - begin() const - { return ranges::begin(*_M_r); } - - constexpr sentinel_t<_Range> - end() const - { return ranges::end(*_M_r); } - - constexpr bool - empty() const requires requires { ranges::empty(*_M_r); } - { return ranges::empty(*_M_r); } - - constexpr auto - size() const requires sized_range<_Range> - { return ranges::size(*_M_r); } - - constexpr auto - data() const requires contiguous_range<_Range> - { return ranges::data(*_M_r); } - }; - - template - ref_view(_Range&) -> ref_view<_Range>; - - template - inline constexpr bool enable_borrowed_range> = true; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptorClosure all - = [] (_Range&& __r) - { - if constexpr (view>) - return std::forward<_Range>(__r); - else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; }) - return ref_view{std::forward<_Range>(__r)}; - else - return subrange{std::forward<_Range>(__r)}; - }; - - template - using all_t = decltype(all(std::declval<_Range>())); - - } // namespace views - - // XXX: the following algos are copied from ranges_algo.h to avoid a circular - // dependency with that header. - namespace __detail - { - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr _Iter - find_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - while (__first != __last - && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__first; - return __first; - } - - template _Sent, - typename _Proj = identity, - indirect_unary_predicate> _Pred> - constexpr _Iter - find_if_not(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) - { - while (__first != __last - && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) - ++__first; - return __first; - } - - template> - _Comp = ranges::less> - constexpr const _Tp& - min(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) - { - if (std::__invoke(std::move(__comp), - std::__invoke(__proj, __b), - std::__invoke(__proj, __a))) - return __b; - else - return __a; - } - - template _Sent1, - input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, - typename _Pred = ranges::equal_to, - typename _Proj1 = identity, typename _Proj2 = identity> - requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> - constexpr pair<_Iter1, _Iter2> - mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, - _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) - { - while (__first1 != __last1 && __first2 != __last2 - && (bool)std::__invoke(__pred, - std::__invoke(__proj1, *__first1), - std::__invoke(__proj2, *__first2))) - { - ++__first1; - ++__first2; - } - return { std::move(__first1), std::move(__first2) }; - } - } // namespace __detail - - namespace __detail - { - template - struct _CachedPosition - { - constexpr bool - _M_has_value() const - { return false; } - - constexpr iterator_t<_Range> - _M_get(const _Range&) const - { - __glibcxx_assert(false); - return {}; - } - - constexpr void - _M_set(const _Range&, const iterator_t<_Range>&) const - { } - }; - - template - struct _CachedPosition<_Range> - { - private: - iterator_t<_Range> _M_iter{}; - - public: - constexpr bool - _M_has_value() const - { return _M_iter != iterator_t<_Range>{}; } - - constexpr iterator_t<_Range> - _M_get(const _Range&) const - { - __glibcxx_assert(_M_has_value()); - return _M_iter; - } - - constexpr void - _M_set(const _Range&, const iterator_t<_Range>& __it) - { - __glibcxx_assert(!_M_has_value()); - _M_iter = __it; - } - }; - - template - requires (sizeof(range_difference_t<_Range>) - <= sizeof(iterator_t<_Range>)) - struct _CachedPosition<_Range> - { - private: - range_difference_t<_Range> _M_offset = -1; - - public: - constexpr bool - _M_has_value() const - { return _M_offset >= 0; } - - constexpr iterator_t<_Range> - _M_get(_Range& __r) const - { - __glibcxx_assert(_M_has_value()); - return ranges::begin(__r) + _M_offset; - } - - constexpr void - _M_set(_Range& __r, const iterator_t<_Range>& __it) - { - __glibcxx_assert(!_M_has_value()); - _M_offset = __it - ranges::begin(__r); - } - }; - - } // namespace __detail - - template> _Pred> - requires view<_Vp> && is_object_v<_Pred> - class filter_view : public view_interface> - { - private: - struct _Sentinel; - - struct _Iterator - { - private: - static constexpr auto - _S_iter_concept() - { - if constexpr (bidirectional_range<_Vp>) - return bidirectional_iterator_tag{}; - else if constexpr (forward_range<_Vp>) - return forward_iterator_tag{}; - else - return input_iterator_tag{}; - } - - static constexpr auto - _S_iter_cat() - { - using _Cat = typename iterator_traits<_Vp_iter>::iterator_category; - if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) - return bidirectional_iterator_tag{}; - else if constexpr (derived_from<_Cat, forward_iterator_tag>) - return forward_iterator_tag{}; - else - return _Cat{}; - } - - friend filter_view; - - using _Vp_iter = iterator_t<_Vp>; - - _Vp_iter _M_current = _Vp_iter(); - filter_view* _M_parent = nullptr; - - public: - using iterator_concept = decltype(_S_iter_concept()); - using iterator_category = decltype(_S_iter_cat()); - using value_type = range_value_t<_Vp>; - using difference_type = range_difference_t<_Vp>; - - _Iterator() = default; - - constexpr - _Iterator(filter_view& __parent, _Vp_iter __current) - : _M_current(std::move(__current)), - _M_parent(std::__addressof(__parent)) - { } - - constexpr _Vp_iter - base() const & - requires copyable<_Vp_iter> - { return _M_current; } - - constexpr _Vp_iter - base() && - { return std::move(_M_current); } - - constexpr range_reference_t<_Vp> - operator*() const - { return *_M_current; } - - constexpr _Vp_iter - operator->() const - requires __detail::__has_arrow<_Vp_iter> - && copyable<_Vp_iter> - { return _M_current; } - - constexpr _Iterator& - operator++() - { - _M_current = __detail::find_if(std::move(++_M_current), - ranges::end(_M_parent->_M_base), - std::ref(*_M_parent->_M_pred)); - return *this; - } - - constexpr void - operator++(int) - { ++*this; } - - constexpr _Iterator - operator++(int) requires forward_range<_Vp> - { - auto __tmp = *this; - ++*this; - return __tmp; - } - - constexpr _Iterator& - operator--() requires bidirectional_range<_Vp> - { - do - --_M_current; - while (!std::__invoke(*_M_parent->_M_pred, *_M_current)); - return *this; - } - - constexpr _Iterator - operator--(int) requires bidirectional_range<_Vp> - { - auto __tmp = *this; - --*this; - return __tmp; - } - - friend constexpr bool - operator==(const _Iterator& __x, const _Iterator& __y) - requires equality_comparable<_Vp_iter> - { return __x._M_current == __y._M_current; } - - friend constexpr range_rvalue_reference_t<_Vp> - iter_move(const _Iterator& __i) - noexcept(noexcept(ranges::iter_move(__i._M_current))) - { return ranges::iter_move(__i._M_current); } - - friend constexpr void - iter_swap(const _Iterator& __x, const _Iterator& __y) - noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) - requires indirectly_swappable<_Vp_iter> - { ranges::iter_swap(__x._M_current, __y._M_current); } - }; - - struct _Sentinel - { - private: - sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); - - constexpr bool - __equal(const _Iterator& __i) const - { return __i._M_current == _M_end; } - - public: - _Sentinel() = default; - - constexpr explicit - _Sentinel(filter_view& __parent) - : _M_end(ranges::end(__parent._M_base)) - { } - - constexpr sentinel_t<_Vp> - base() const - { return _M_end; } - - friend constexpr bool - operator==(const _Iterator& __x, const _Sentinel& __y) - { return __y.__equal(__x); } - }; - - _Vp _M_base = _Vp(); - __detail::__box<_Pred> _M_pred; - [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; - - public: - filter_view() = default; - - constexpr - filter_view(_Vp __base, _Pred __pred) - : _M_base(std::move(__base)), _M_pred(std::move(__pred)) - { } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr const _Pred& - pred() const - { return *_M_pred; } - - constexpr _Iterator - begin() - { - if (_M_cached_begin._M_has_value()) - return {*this, _M_cached_begin._M_get(_M_base)}; - - __glibcxx_assert(_M_pred.has_value()); - auto __it = __detail::find_if(ranges::begin(_M_base), - ranges::end(_M_base), - std::ref(*_M_pred)); - _M_cached_begin._M_set(_M_base, __it); - return {*this, std::move(__it)}; - } - - constexpr auto - end() - { - if constexpr (common_range<_Vp>) - return _Iterator{*this, ranges::end(_M_base)}; - else - return _Sentinel{*this}; - } - }; - - template - filter_view(_Range&&, _Pred) -> filter_view, _Pred>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptor filter - = [] (_Range&& __r, _Pred&& __p) - { - return filter_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)}; - }; - } // namespace views - - template - requires view<_Vp> && is_object_v<_Fp> - && regular_invocable<_Fp&, range_reference_t<_Vp>> - && std::__detail::__can_reference>> - class transform_view : public view_interface> - { - private: - template - struct _Sentinel; - - template - struct _Iterator - { - private: - using _Parent = __detail::__maybe_const_t<_Const, transform_view>; - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - - static constexpr auto - _S_iter_concept() - { - if constexpr (random_access_range<_Vp>) - return random_access_iterator_tag{}; - else if constexpr (bidirectional_range<_Vp>) - return bidirectional_iterator_tag{}; - else if constexpr (forward_range<_Vp>) - return forward_iterator_tag{}; - else - return input_iterator_tag{}; - } - - static constexpr auto - _S_iter_cat() - { - using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>; - if constexpr (is_lvalue_reference_v<_Res>) - { - using _Cat - = typename iterator_traits<_Base_iter>::iterator_category; - if constexpr (derived_from<_Cat, contiguous_iterator_tag>) - return random_access_iterator_tag{}; - else - return _Cat{}; - } - else - return input_iterator_tag{}; - } - - using _Base_iter = iterator_t<_Base>; - - _Base_iter _M_current = _Base_iter(); - _Parent* _M_parent = nullptr; - - public: - using iterator_concept = decltype(_S_iter_concept()); - using iterator_category = decltype(_S_iter_cat()); - using value_type - = remove_cvref_t>>; - using difference_type = range_difference_t<_Base>; - - _Iterator() = default; - - constexpr - _Iterator(_Parent& __parent, _Base_iter __current) - : _M_current(std::move(__current)), - _M_parent(std::__addressof(__parent)) - { } - - constexpr - _Iterator(_Iterator __i) - requires _Const - && convertible_to, _Base_iter> - : _M_current(std::move(__i._M_current)), _M_parent(__i._M_parent) - { } - - constexpr _Base_iter - base() const & - requires copyable<_Base_iter> - { return _M_current; } - - constexpr _Base_iter - base() && - { return std::move(_M_current); } - - constexpr decltype(auto) - operator*() const - noexcept(noexcept(std::__invoke(*_M_parent->_M_fun, *_M_current))) - { return std::__invoke(*_M_parent->_M_fun, *_M_current); } - - constexpr _Iterator& - operator++() - { - ++_M_current; - return *this; - } - - constexpr void - operator++(int) - { ++_M_current; } - - constexpr _Iterator - operator++(int) requires forward_range<_Base> - { - auto __tmp = *this; - ++*this; - return __tmp; - } - - constexpr _Iterator& - operator--() requires bidirectional_range<_Base> - { - --_M_current; - return *this; - } - - constexpr _Iterator - operator--(int) requires bidirectional_range<_Base> - { - auto __tmp = *this; - --*this; - return __tmp; - } - - constexpr _Iterator& - operator+=(difference_type __n) requires random_access_range<_Base> - { - _M_current += __n; - return *this; - } - - constexpr _Iterator& - operator-=(difference_type __n) requires random_access_range<_Base> - { - _M_current -= __n; - return *this; - } - - constexpr decltype(auto) - operator[](difference_type __n) const - requires random_access_range<_Base> - { return std::__invoke(*_M_parent->_M_fun, _M_current[__n]); } - - friend constexpr bool - operator==(const _Iterator& __x, const _Iterator& __y) - requires equality_comparable<_Base_iter> - { return __x._M_current == __y._M_current; } - - friend constexpr bool - operator<(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return __x._M_current < __y._M_current; } - - friend constexpr bool - operator>(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return __y < __x; } - - friend constexpr bool - operator<=(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return !(__y < __x); } - - friend constexpr bool - operator>=(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return !(__x < __y); } - -#ifdef __cpp_lib_three_way_comparison - friend constexpr auto - operator<=>(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - && three_way_comparable<_Base_iter> - { return __x._M_current <=> __y._M_current; } -#endif - - friend constexpr _Iterator - operator+(_Iterator __i, difference_type __n) - requires random_access_range<_Base> - { return {*__i._M_parent, __i._M_current + __n}; } - - friend constexpr _Iterator - operator+(difference_type __n, _Iterator __i) - requires random_access_range<_Base> - { return {*__i._M_parent, __i._M_current + __n}; } - - friend constexpr _Iterator - operator-(_Iterator __i, difference_type __n) - requires random_access_range<_Base> - { return {*__i._M_parent, __i._M_current - __n}; } - - friend constexpr difference_type - operator-(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return __x._M_current - __y._M_current; } - - friend constexpr decltype(auto) - iter_move(const _Iterator& __i) noexcept(noexcept(*__i)) - { - if constexpr (is_lvalue_reference_v) - return std::move(*__i); - else - return *__i; - } - - friend constexpr void - iter_swap(const _Iterator& __x, const _Iterator& __y) - noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) - requires indirectly_swappable<_Base_iter> - { return ranges::iter_swap(__x._M_current, __y._M_current); } - - friend _Iterator; - template friend struct _Sentinel; - }; - - template - struct _Sentinel - { - private: - using _Parent = __detail::__maybe_const_t<_Const, transform_view>; - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - - template - constexpr auto - __distance_from(const _Iterator<_Const2>& __i) const - { return _M_end - __i._M_current; } - - template - constexpr bool - __equal(const _Iterator<_Const2>& __i) const - { return __i._M_current == _M_end; } - - sentinel_t<_Base> _M_end = sentinel_t<_Base>(); - - public: - _Sentinel() = default; - - constexpr explicit - _Sentinel(sentinel_t<_Base> __end) - : _M_end(__end) - { } - - constexpr - _Sentinel(_Sentinel __i) - requires _Const - && convertible_to, sentinel_t<_Base>> - : _M_end(std::move(__i._M_end)) - { } - - constexpr sentinel_t<_Base> - base() const - { return _M_end; } - - template - requires sentinel_for, - iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> - friend constexpr bool - operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) - { return __y.__equal(__x); } - - template> - requires sized_sentinel_for, iterator_t<_Base2>> - friend constexpr range_difference_t<_Base2> - operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) - { return -__y.__distance_from(__x); } - - template> - requires sized_sentinel_for, iterator_t<_Base2>> - friend constexpr range_difference_t<_Base2> - operator-(const _Sentinel& __y, const _Iterator<_Const2>& __x) - { return __y.__distance_from(__x); } - - friend _Sentinel; - }; - - _Vp _M_base = _Vp(); - __detail::__box<_Fp> _M_fun; - - public: - transform_view() = default; - - constexpr - transform_view(_Vp __base, _Fp __fun) - : _M_base(std::move(__base)), _M_fun(std::move(__fun)) - { } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base ; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr _Iterator - begin() - { return _Iterator{*this, ranges::begin(_M_base)}; } - - constexpr _Iterator - begin() const - requires range - && regular_invocable> - { return _Iterator{*this, ranges::begin(_M_base)}; } - - constexpr _Sentinel - end() - { return _Sentinel{ranges::end(_M_base)}; } - - constexpr _Iterator - end() requires common_range<_Vp> - { return _Iterator{*this, ranges::end(_M_base)}; } - - constexpr _Sentinel - end() const - requires range - && regular_invocable> - { return _Sentinel{ranges::end(_M_base)}; } - - constexpr _Iterator - end() const - requires common_range - && regular_invocable> - { return _Iterator{*this, ranges::end(_M_base)}; } - - constexpr auto - size() requires sized_range<_Vp> - { return ranges::size(_M_base); } - - constexpr auto - size() const requires sized_range - { return ranges::size(_M_base); } - }; - - template - transform_view(_Range&&, _Fp) -> transform_view, _Fp>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptor transform - = [] (_Range&& __r, _Fp&& __f) - { - return transform_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)}; - }; - } // namespace views - - template - class take_view : public view_interface> - { - private: - template - struct _Sentinel - { - private: - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - using _CI = counted_iterator>; - - sentinel_t<_Base> _M_end = sentinel_t<_Base>(); - - public: - _Sentinel() = default; - - constexpr explicit - _Sentinel(sentinel_t<_Base> __end) - : _M_end(__end) - { } - - constexpr - _Sentinel(_Sentinel __s) - requires _Const && convertible_to, sentinel_t<_Base>> - : _M_end(std::move(__s._M_end)) - { } - - constexpr sentinel_t<_Base> - base() const - { return _M_end; } - - friend constexpr bool operator==(const _CI& __y, const _Sentinel& __x) - { return __y.count() == 0 || __y.base() == __x._M_end; } - - friend _Sentinel; - }; - - _Vp _M_base = _Vp(); - range_difference_t<_Vp> _M_count = 0; - - public: - take_view() = default; - - constexpr - take_view(_Vp base, range_difference_t<_Vp> __count) - : _M_base(std::move(base)), _M_count(std::move(__count)) - { } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr auto - begin() requires (!__detail::__simple_view<_Vp>) - { - if constexpr (sized_range<_Vp>) - { - if constexpr (random_access_range<_Vp>) - return ranges::begin(_M_base); - else - { - auto __sz = size(); - return counted_iterator{ranges::begin(_M_base), __sz}; - } - } - else - return counted_iterator{ranges::begin(_M_base), _M_count}; - } - - constexpr auto - begin() const requires range - { - if constexpr (sized_range) - { - if constexpr (random_access_range) - return ranges::begin(_M_base); - else - { - auto __sz = size(); - return counted_iterator{ranges::begin(_M_base), __sz}; - } - } - else - return counted_iterator{ranges::begin(_M_base), _M_count}; - } - - constexpr auto - end() requires (!__detail::__simple_view<_Vp>) - { - if constexpr (sized_range<_Vp>) - { - if constexpr (random_access_range<_Vp>) - return ranges::begin(_M_base) + size(); - else - return default_sentinel; - } - else - return _Sentinel{ranges::end(_M_base)}; - } - - constexpr auto - end() const requires range - { - if constexpr (sized_range) - { - if constexpr (random_access_range) - return ranges::begin(_M_base) + size(); - else - return default_sentinel; - } - else - return _Sentinel{ranges::end(_M_base)}; - } - - constexpr auto - size() requires sized_range<_Vp> - { - auto __n = ranges::size(_M_base); - return __detail::min(__n, static_cast(_M_count)); - } - - constexpr auto - size() const requires sized_range - { - auto __n = ranges::size(_M_base); - return __detail::min(__n, static_cast(_M_count)); - } - }; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3447. Deduction guides for take_view and drop_view have different - // constraints - template - take_view(_Range&&, range_difference_t<_Range>) - -> take_view>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptor take - = [] (_Range&& __r, _Tp&& __n) - { - return take_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)}; - }; - } // namespace views - - template - requires input_range<_Vp> && is_object_v<_Pred> - && indirect_unary_predicate> - class take_while_view : public view_interface> - { - template - struct _Sentinel - { - private: - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - - sentinel_t<_Base> _M_end = sentinel_t<_Base>(); - const _Pred* _M_pred = nullptr; - - public: - _Sentinel() = default; - - constexpr explicit - _Sentinel(sentinel_t<_Base> __end, const _Pred* __pred) - : _M_end(__end), _M_pred(__pred) - { } - - constexpr - _Sentinel(_Sentinel __s) - requires _Const && convertible_to, sentinel_t<_Base>> - : _M_end(__s._M_end), _M_pred(__s._M_pred) - { } - - constexpr sentinel_t<_Base> - base() const { return _M_end; } - - friend constexpr bool - operator==(const iterator_t<_Base>& __x, const _Sentinel& __y) - { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); } - - friend _Sentinel; - }; - - _Vp _M_base = _Vp(); - __detail::__box<_Pred> _M_pred; - - public: - take_while_view() = default; - - constexpr - take_while_view(_Vp base, _Pred __pred) - : _M_base(std::move(base)), _M_pred(std::move(__pred)) - { - } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr const _Pred& - pred() const - { return *_M_pred; } - - constexpr auto - begin() requires (!__detail::__simple_view<_Vp>) - { return ranges::begin(_M_base); } - - constexpr auto - begin() const requires range - && indirect_unary_predicate> - { return ranges::begin(_M_base); } - - constexpr auto - end() requires (!__detail::__simple_view<_Vp>) - { return _Sentinel(ranges::end(_M_base), - std::__addressof(*_M_pred)); } - - constexpr auto - end() const requires range - && indirect_unary_predicate> - { return _Sentinel(ranges::end(_M_base), - std::__addressof(*_M_pred)); } - }; - - template - take_while_view(_Range&&, _Pred) - -> take_while_view, _Pred>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptor take_while - = [] (_Range&& __r, _Pred&& __p) - { - return take_while_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)}; - }; - } // namespace views - - template - class drop_view : public view_interface> - { - private: - _Vp _M_base = _Vp(); - range_difference_t<_Vp> _M_count = 0; - - static constexpr bool _S_needs_cached_begin = !random_access_range<_Vp>; - [[no_unique_address]] - __detail::__maybe_present_t<_S_needs_cached_begin, - __detail::_CachedPosition<_Vp>> - _M_cached_begin; - - public: - drop_view() = default; - - constexpr - drop_view(_Vp __base, range_difference_t<_Vp> __count) - : _M_base(std::move(__base)), _M_count(__count) - { __glibcxx_assert(__count >= 0); } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr auto - begin() requires (!(__detail::__simple_view<_Vp> - && random_access_range<_Vp>)) - { - if constexpr (_S_needs_cached_begin) - if (_M_cached_begin._M_has_value()) - return _M_cached_begin._M_get(_M_base); - - auto __it = ranges::next(ranges::begin(_M_base), - _M_count, ranges::end(_M_base)); - if constexpr (_S_needs_cached_begin) - _M_cached_begin._M_set(_M_base, __it); - return __it; - } - - constexpr auto - begin() const requires random_access_range - { - return ranges::next(ranges::begin(_M_base), _M_count, - ranges::end(_M_base)); - } - - constexpr auto - end() requires (!__detail::__simple_view<_Vp>) - { return ranges::end(_M_base); } - - constexpr auto - end() const requires range - { return ranges::end(_M_base); } - - constexpr auto - size() requires sized_range<_Vp> - { - const auto __s = ranges::size(_M_base); - const auto __c = static_cast(_M_count); - return __s < __c ? 0 : __s - __c; - } - - constexpr auto - size() const requires sized_range - { - const auto __s = ranges::size(_M_base); - const auto __c = static_cast(_M_count); - return __s < __c ? 0 : __s - __c; - } - }; - - template - drop_view(_Range&&, range_difference_t<_Range>) - -> drop_view>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptor drop - = [] (_Range&& __r, _Tp&& __n) - { - return drop_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)}; - }; - } // namespace views - - template - requires input_range<_Vp> && is_object_v<_Pred> - && indirect_unary_predicate> - class drop_while_view : public view_interface> - { - private: - _Vp _M_base = _Vp(); - __detail::__box<_Pred> _M_pred; - [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; - - public: - drop_while_view() = default; - - constexpr - drop_while_view(_Vp __base, _Pred __pred) - : _M_base(std::move(__base)), _M_pred(std::move(__pred)) - { } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr const _Pred& - pred() const - { return *_M_pred; } - - constexpr auto - begin() - { - if (_M_cached_begin._M_has_value()) - return _M_cached_begin._M_get(_M_base); - - auto __it = __detail::find_if_not(ranges::begin(_M_base), - ranges::end(_M_base), - std::cref(*_M_pred)); - _M_cached_begin._M_set(_M_base, __it); - return __it; - } - - constexpr auto - end() - { return ranges::end(_M_base); } - }; - - template - drop_while_view(_Range&&, _Pred) - -> drop_while_view, _Pred>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptor drop_while - = [] (_Range&& __r, _Pred&& __p) - { - return drop_while_view{std::forward<_Range>(__r), - std::forward<_Pred>(__p)}; - }; - } // namespace views - - template - requires view<_Vp> && input_range> - && (is_reference_v> - || view>) - class join_view : public view_interface> - { - private: - using _InnerRange = range_reference_t<_Vp>; - - template - struct _Sentinel; - - template - struct _Iterator - { - private: - using _Parent = __detail::__maybe_const_t<_Const, join_view>; - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - - static constexpr bool _S_ref_is_glvalue - = is_reference_v>; - - constexpr void - _M_satisfy() - { - auto __update_inner = [this] (range_reference_t<_Base> __x) -> auto& - { - if constexpr (_S_ref_is_glvalue) - return __x; - else - return (_M_parent->_M_inner = views::all(std::move(__x))); - }; - - for (; _M_outer != ranges::end(_M_parent->_M_base); ++_M_outer) - { - auto& inner = __update_inner(*_M_outer); - _M_inner = ranges::begin(inner); - if (_M_inner != ranges::end(inner)) - return; - } - - if constexpr (_S_ref_is_glvalue) - _M_inner = _Inner_iter(); - } - - static constexpr auto - _S_iter_concept() - { - if constexpr (_S_ref_is_glvalue - && bidirectional_range<_Base> - && bidirectional_range>) - return bidirectional_iterator_tag{}; - else if constexpr (_S_ref_is_glvalue - && forward_range<_Base> - && forward_range>) - return forward_iterator_tag{}; - else - return input_iterator_tag{}; - } - - static constexpr auto - _S_iter_cat() - { - using _OuterCat - = typename iterator_traits<_Outer_iter>::iterator_category; - using _InnerCat - = typename iterator_traits<_Inner_iter>::iterator_category; - if constexpr (_S_ref_is_glvalue - && derived_from<_OuterCat, bidirectional_iterator_tag> - && derived_from<_InnerCat, bidirectional_iterator_tag>) - return bidirectional_iterator_tag{}; - else if constexpr (_S_ref_is_glvalue - && derived_from<_OuterCat, forward_iterator_tag> - && derived_from<_InnerCat, forward_iterator_tag>) - return forward_iterator_tag{}; - else if constexpr (derived_from<_OuterCat, input_iterator_tag> - && derived_from<_InnerCat, input_iterator_tag>) - return input_iterator_tag{}; - else - return output_iterator_tag{}; - } - - using _Outer_iter = iterator_t<_Base>; - using _Inner_iter = iterator_t>; - - _Outer_iter _M_outer = _Outer_iter(); - _Inner_iter _M_inner = _Inner_iter(); - _Parent* _M_parent = nullptr; - - public: - using iterator_concept = decltype(_S_iter_concept()); - using iterator_category = decltype(_S_iter_cat()); - using value_type = range_value_t>; - using difference_type - = common_type_t, - range_difference_t>>; - - _Iterator() = default; - - constexpr - _Iterator(_Parent& __parent, _Outer_iter __outer) - : _M_outer(std::move(__outer)), - _M_parent(std::__addressof(__parent)) - { _M_satisfy(); } - - constexpr - _Iterator(_Iterator __i) - requires _Const - && convertible_to, _Outer_iter> - && convertible_to, _Inner_iter> - : _M_outer(std::move(__i._M_outer)), _M_inner(__i._M_inner), - _M_parent(__i._M_parent) - { } - - constexpr decltype(auto) - operator*() const - { return *_M_inner; } - - constexpr _Outer_iter - operator->() const - requires __detail::__has_arrow<_Outer_iter> - && copyable<_Outer_iter> - { return _M_inner; } - - constexpr _Iterator& - operator++() - { - auto&& __inner_range = [this] () -> decltype(auto) { - if constexpr (_S_ref_is_glvalue) - return *_M_outer; - else - return _M_parent->_M_inner; - }(); - if (++_M_inner == ranges::end(__inner_range)) - { - ++_M_outer; - _M_satisfy(); - } - return *this; - } - - constexpr void - operator++(int) - { ++*this; } - - constexpr _Iterator - operator++(int) - requires _S_ref_is_glvalue && forward_range<_Base> - && forward_range> - { - auto __tmp = *this; - ++*this; - return __tmp; - } - - constexpr _Iterator& - operator--() - requires _S_ref_is_glvalue && bidirectional_range<_Base> - && bidirectional_range> - && common_range> - { - if (_M_outer == ranges::end(_M_parent->_M_base)) - _M_inner = ranges::end(*--_M_outer); - while (_M_inner == ranges::begin(*_M_outer)) - _M_inner = ranges::end(*--_M_outer); - --_M_inner; - return *this; - } - - constexpr _Iterator - operator--(int) - requires _S_ref_is_glvalue && bidirectional_range<_Base> - && bidirectional_range> - && common_range> - { - auto __tmp = *this; - --*this; - return __tmp; - } - - friend constexpr bool - operator==(const _Iterator& __x, const _Iterator& __y) - requires _S_ref_is_glvalue - && equality_comparable<_Outer_iter> - && equality_comparable<_Inner_iter> - { - return (__x._M_outer == __y._M_outer - && __x._M_inner == __y._M_inner); - } - - friend constexpr decltype(auto) - iter_move(const _Iterator& __i) - noexcept(noexcept(ranges::iter_move(__i._M_inner))) - { return ranges::iter_move(__i._M_inner); } - - friend constexpr void - iter_swap(const _Iterator& __x, const _Iterator& __y) - noexcept(noexcept(ranges::iter_swap(__x._M_inner, __y._M_inner))) - { return ranges::iter_swap(__x._M_inner, __y._M_inner); } - - friend _Iterator; - template friend struct _Sentinel; - }; - - template - struct _Sentinel - { - private: - using _Parent = __detail::__maybe_const_t<_Const, join_view>; - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - - template - constexpr bool - __equal(const _Iterator<_Const2>& __i) const - { return __i._M_outer == _M_end; } - - sentinel_t<_Base> _M_end = sentinel_t<_Base>(); - - public: - _Sentinel() = default; - - constexpr explicit - _Sentinel(_Parent& __parent) - : _M_end(ranges::end(__parent._M_base)) - { } - - constexpr - _Sentinel(_Sentinel __s) - requires _Const && convertible_to, sentinel_t<_Base>> - : _M_end(std::move(__s._M_end)) - { } - - template - requires sentinel_for, - iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> - friend constexpr bool - operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) - { return __y.__equal(__x); } - - friend _Sentinel; - }; - - _Vp _M_base = _Vp(); - - // XXX: _M_inner is "present only when !is_reference_v<_InnerRange>" - [[no_unique_address]] - __detail::__maybe_present_t, - views::all_t<_InnerRange>> _M_inner; - - public: - join_view() = default; - - constexpr explicit - join_view(_Vp __base) - : _M_base(std::move(__base)) - { } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr auto - begin() - { - constexpr bool __use_const - = (__detail::__simple_view<_Vp> - && is_reference_v>); - return _Iterator<__use_const>{*this, ranges::begin(_M_base)}; - } - - constexpr auto - begin() const - requires input_range - && is_reference_v> - { - return _Iterator{*this, ranges::begin(_M_base)}; - } - - constexpr auto - end() - { - if constexpr (forward_range<_Vp> && is_reference_v<_InnerRange> - && forward_range<_InnerRange> - && common_range<_Vp> && common_range<_InnerRange>) - return _Iterator<__detail::__simple_view<_Vp>>{*this, - ranges::end(_M_base)}; - else - return _Sentinel<__detail::__simple_view<_Vp>>{*this}; - } - - constexpr auto - end() const - requires input_range - && is_reference_v> - { - if constexpr (forward_range - && is_reference_v> - && forward_range> - && common_range - && common_range>) - return _Iterator{*this, ranges::end(_M_base)}; - else - return _Sentinel{*this}; - } - }; - - template - explicit join_view(_Range&&) -> join_view>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptorClosure join - = [] (_Range&& __r) - { - return join_view{std::forward<_Range>(__r)}; - }; - } // namespace views - - namespace __detail - { - template - struct __require_constant; - - template - concept __tiny_range = sized_range<_Range> - && requires - { typename __require_constant::size()>; } - && (remove_reference_t<_Range>::size() <= 1); - } - - template - requires view<_Vp> && view<_Pattern> - && indirectly_comparable, iterator_t<_Pattern>, - ranges::equal_to> - && (forward_range<_Vp> || __detail::__tiny_range<_Pattern>) - class split_view : public view_interface> - { - private: - template - struct _InnerIter; - - template - struct _OuterIter - { - private: - using _Parent = __detail::__maybe_const_t<_Const, split_view>; - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - - constexpr bool - __at_end() const - { return __current() == ranges::end(_M_parent->_M_base); } - - // [range.split.outer] p1 - // Many of the following specifications refer to the notional member - // current of outer-iterator. current is equivalent to current_ if - // V models forward_range, and parent_->current_ otherwise. - constexpr auto& - __current() noexcept - { - if constexpr (forward_range<_Vp>) - return _M_current; - else - return _M_parent->_M_current; - } - - constexpr auto& - __current() const noexcept - { - if constexpr (forward_range<_Vp>) - return _M_current; - else - return _M_parent->_M_current; - } - - _Parent* _M_parent = nullptr; - - // XXX: _M_current is present only if "V models forward_range" - [[no_unique_address]] - __detail::__maybe_present_t, - iterator_t<_Base>> _M_current; - - public: - using iterator_concept = conditional_t, - forward_iterator_tag, - input_iterator_tag>; - using iterator_category = input_iterator_tag; - using difference_type = range_difference_t<_Base>; - - struct value_type : view_interface - { - private: - _OuterIter _M_i = _OuterIter(); - - public: - value_type() = default; - - constexpr explicit - value_type(_OuterIter __i) - : _M_i(std::move(__i)) - { } - - constexpr _InnerIter<_Const> - begin() const - requires copyable<_OuterIter> - { return _InnerIter<_Const>{_M_i}; } - - constexpr _InnerIter<_Const> - begin() - requires (!copyable<_OuterIter>) - { return _InnerIter<_Const>{std::move(_M_i)}; } - - constexpr default_sentinel_t - end() const - { return default_sentinel; } - }; - - _OuterIter() = default; - - constexpr explicit - _OuterIter(_Parent& __parent) requires (!forward_range<_Base>) - : _M_parent(std::__addressof(__parent)) - { } - - constexpr - _OuterIter(_Parent& __parent, iterator_t<_Base> __current) - requires forward_range<_Base> - : _M_parent(std::__addressof(__parent)), - _M_current(std::move(__current)) - { } - - constexpr - _OuterIter(_OuterIter __i) - requires _Const - && convertible_to, iterator_t<_Base>> - : _M_parent(__i._M_parent), _M_current(std::move(__i._M_current)) - { } - - constexpr value_type - operator*() const - { return value_type{*this}; } - - constexpr _OuterIter& - operator++() - { - const auto __end = ranges::end(_M_parent->_M_base); - if (__current() == __end) - return *this; - const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern}; - if (__pbegin == __pend) - ++__current(); - else - do - { - auto [__b, __p] - = __detail::mismatch(std::move(__current()), __end, - __pbegin, __pend); - __current() = std::move(__b); - if (__p == __pend) - break; - } while (++__current() != __end); - return *this; - } - - constexpr decltype(auto) - operator++(int) - { - if constexpr (forward_range<_Base>) - { - auto __tmp = *this; - ++*this; - return __tmp; - } - else - ++*this; - } - - friend constexpr bool - operator==(const _OuterIter& __x, const _OuterIter& __y) - requires forward_range<_Base> - { return __x._M_current == __y._M_current; } - - friend constexpr bool - operator==(const _OuterIter& __x, default_sentinel_t) - { return __x.__at_end(); }; - - friend _OuterIter; - friend _InnerIter<_Const>; - }; - - template - struct _InnerIter - { - private: - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - - constexpr bool - __at_end() const - { - auto [__pcur, __pend] = subrange{_M_i._M_parent->_M_pattern}; - auto __end = ranges::end(_M_i._M_parent->_M_base); - if constexpr (__detail::__tiny_range<_Pattern>) - { - const auto& __cur = _M_i_current(); - if (__cur == __end) - return true; - if (__pcur == __pend) - return _M_incremented; - return *__cur == *__pcur; - } - else - { - auto __cur = _M_i_current(); - if (__cur == __end) - return true; - if (__pcur == __pend) - return _M_incremented; - do - { - if (*__cur != *__pcur) - return false; - if (++__pcur == __pend) - return true; - } while (++__cur != __end); - return false; - } - } - - static constexpr auto - _S_iter_cat() - { - using _Cat - = typename iterator_traits>::iterator_category; - if constexpr (derived_from<_Cat, forward_iterator_tag>) - return forward_iterator_tag{}; - else - return _Cat{}; - } - - constexpr auto& - _M_i_current() noexcept - { return _M_i.__current(); } - - constexpr auto& - _M_i_current() const noexcept - { return _M_i.__current(); } - - _OuterIter<_Const> _M_i = _OuterIter<_Const>(); - bool _M_incremented = false; - - public: - using iterator_concept - = typename _OuterIter<_Const>::iterator_concept; - using iterator_category = decltype(_S_iter_cat()); - using value_type = range_value_t<_Base>; - using difference_type = range_difference_t<_Base>; - - _InnerIter() = default; - - constexpr explicit - _InnerIter(_OuterIter<_Const> __i) - : _M_i(std::move(__i)) - { } - - constexpr decltype(auto) - operator*() const - { return *_M_i_current(); } - - constexpr _InnerIter& - operator++() - { - _M_incremented = true; - if constexpr (!forward_range<_Base>) - if constexpr (_Pattern::size() == 0) - return *this; - ++_M_i_current(); - return *this; - } - - constexpr decltype(auto) - operator++(int) - { - if constexpr (forward_range<_Vp>) - { - auto __tmp = *this; - ++*this; - return __tmp; - } - else - ++*this; - } - - friend constexpr bool - operator==(const _InnerIter& __x, const _InnerIter& __y) - requires forward_range<_Base> - { return __x._M_i == __y._M_i; } - - friend constexpr bool - operator==(const _InnerIter& __x, default_sentinel_t) - { return __x.__at_end(); } - - friend constexpr decltype(auto) - iter_move(const _InnerIter& __i) - noexcept(noexcept(ranges::iter_move(__i._M_i_current()))) - { return ranges::iter_move(__i._M_i_current()); } - - friend constexpr void - iter_swap(const _InnerIter& __x, const _InnerIter& __y) - noexcept(noexcept(ranges::iter_swap(__x._M_i_current(), - __y._M_i_current()))) - requires indirectly_swappable> - { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); } - }; - - _Vp _M_base = _Vp(); - _Pattern _M_pattern = _Pattern(); - - // XXX: _M_current is "present only if !forward_range" - [[no_unique_address]] - __detail::__maybe_present_t, iterator_t<_Vp>> - _M_current; - - - public: - split_view() = default; - - constexpr - split_view(_Vp __base, _Pattern __pattern) - : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) - { } - - template - requires constructible_from<_Vp, views::all_t<_Range>> - && constructible_from<_Pattern, single_view>> - constexpr - split_view(_Range&& __r, range_value_t<_Range> __e) - : _M_base(views::all(std::forward<_Range>(__r))), - _M_pattern(std::move(__e)) - { } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr auto - begin() - { - if constexpr (forward_range<_Vp>) - return _OuterIter<__detail::__simple_view<_Vp>>{ - *this, ranges::begin(_M_base)}; - else - { - _M_current = ranges::begin(_M_base); - return _OuterIter{*this}; - } - } - - constexpr auto - begin() const requires forward_range<_Vp> && forward_range - { - return _OuterIter{*this, ranges::begin(_M_base)}; - } - - constexpr auto - end() requires forward_range<_Vp> && common_range<_Vp> - { - return _OuterIter<__detail::__simple_view<_Vp>>{ - *this, ranges::end(_M_base)}; - } - - constexpr auto - end() const - { - if constexpr (forward_range<_Vp> - && forward_range - && common_range) - return _OuterIter{*this, ranges::end(_M_base)}; - else - return default_sentinel; - } - }; - - template - split_view(_Range&&, _Pred&&) - -> split_view, views::all_t<_Pred>>; - - template - split_view(_Range&&, range_value_t<_Range>) - -> split_view, single_view>>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptor split - = [] (_Range&& __r, _Fp&& __f) - { - return split_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)}; - }; - } // namespace views - - namespace views - { - struct _Counted - { - template - constexpr auto - operator()(_Iter __i, iter_difference_t<_Iter> __n) const - { - if constexpr (random_access_iterator<_Iter>) - return subrange{__i, __i + __n}; - else - return subrange{counted_iterator{std::move(__i), __n}, - default_sentinel}; - } - }; - - inline constexpr _Counted counted{}; - } // namespace views - - template - requires (!common_range<_Vp>) && copyable> - class common_view : public view_interface> - { - private: - _Vp _M_base = _Vp(); - - public: - common_view() = default; - - constexpr explicit - common_view(_Vp __r) - : _M_base(std::move(__r)) - { } - - /* XXX: LWG 3280 didn't remove this constructor, but I think it should? - template - requires (!common_range<_Range>) - && constructible_from<_Vp, views::all_t<_Range>> - constexpr explicit - common_view(_Range&& __r) - : _M_base(views::all(std::forward<_Range>(__r))) - { } - */ - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr auto - begin() - { - if constexpr (random_access_range<_Vp> && sized_range<_Vp>) - return ranges::begin(_M_base); - else - return common_iterator, sentinel_t<_Vp>> - (ranges::begin(_M_base)); - } - - constexpr auto - begin() const requires range - { - if constexpr (random_access_range && sized_range) - return ranges::begin(_M_base); - else - return common_iterator, sentinel_t> - (ranges::begin(_M_base)); - } - - constexpr auto - end() - { - if constexpr (random_access_range<_Vp> && sized_range<_Vp>) - return ranges::begin(_M_base) + ranges::size(_M_base); - else - return common_iterator, sentinel_t<_Vp>> - (ranges::end(_M_base)); - } - - constexpr auto - end() const requires range - { - if constexpr (random_access_range && sized_range) - return ranges::begin(_M_base) + ranges::size(_M_base); - else - return common_iterator, sentinel_t> - (ranges::end(_M_base)); - } - - constexpr auto - size() requires sized_range<_Vp> - { return ranges::size(_M_base); } - - constexpr auto - size() const requires sized_range - { return ranges::size(_M_base); } - }; - - template - common_view(_Range&&) -> common_view>; - - namespace views - { - inline constexpr __adaptor::_RangeAdaptorClosure common - = [] (_Range&& __r) - { - if constexpr (common_range<_Range> - && requires { views::all(std::forward<_Range>(__r)); }) - return views::all(std::forward<_Range>(__r)); - else - return common_view{std::forward<_Range>(__r)}; - }; - - } // namespace views - - template - requires bidirectional_range<_Vp> - class reverse_view : public view_interface> - { - private: - _Vp _M_base = _Vp(); - - static constexpr bool _S_needs_cached_begin - = !common_range<_Vp> && !random_access_range<_Vp>; - [[no_unique_address]] - __detail::__maybe_present_t<_S_needs_cached_begin, - __detail::_CachedPosition<_Vp>> - _M_cached_begin; - - public: - reverse_view() = default; - - constexpr explicit - reverse_view(_Vp __r) - : _M_base(std::move(__r)) - { } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr reverse_iterator> - begin() - { - if constexpr (_S_needs_cached_begin) - if (_M_cached_begin._M_has_value()) - return make_reverse_iterator(_M_cached_begin._M_get(_M_base)); - - auto __it = ranges::next(ranges::begin(_M_base), ranges::end(_M_base)); - if constexpr (_S_needs_cached_begin) - _M_cached_begin._M_set(_M_base, __it); - return make_reverse_iterator(std::move(__it)); - } - - constexpr auto - begin() requires common_range<_Vp> - { return make_reverse_iterator(ranges::end(_M_base)); } - - constexpr auto - begin() const requires common_range - { return make_reverse_iterator(ranges::end(_M_base)); } - - constexpr reverse_iterator> - end() - { return make_reverse_iterator(ranges::begin(_M_base)); } - - constexpr auto - end() const requires common_range - { return make_reverse_iterator(ranges::begin(_M_base)); } - - constexpr auto - size() requires sized_range<_Vp> - { return ranges::size(_M_base); } - - constexpr auto - size() const requires sized_range - { return ranges::size(_M_base); } - }; - - template - reverse_view(_Range&&) -> reverse_view>; - - namespace views - { - namespace __detail - { - template - inline constexpr bool __is_reversible_subrange = false; - - template - inline constexpr bool - __is_reversible_subrange, - reverse_iterator<_Iter>, - _Kind>> = true; - - template - inline constexpr bool __is_reverse_view = false; - - template - inline constexpr bool __is_reverse_view> = true; - } - - inline constexpr __adaptor::_RangeAdaptorClosure reverse - = [] (_Range&& __r) - { - using _Tp = remove_cvref_t<_Range>; - if constexpr (__detail::__is_reverse_view<_Tp>) - return std::forward<_Range>(__r).base(); - else if constexpr (__detail::__is_reversible_subrange<_Tp>) - { - using _Iter = decltype(ranges::begin(__r).base()); - if constexpr (sized_range<_Tp>) - return subrange<_Iter, _Iter, subrange_kind::sized> - (__r.end().base(), __r.begin().base(), __r.size()); - else - return subrange<_Iter, _Iter, subrange_kind::unsized> - (__r.end().base(), __r.begin().base()); - } - else - return reverse_view{std::forward<_Range>(__r)}; - }; - } // namespace views - - namespace __detail - { - template - concept __has_tuple_element = requires(_Tp __t) - { - typename tuple_size<_Tp>::type; - requires _Nm < tuple_size_v<_Tp>; - typename tuple_element_t<_Nm, _Tp>; - { std::get<_Nm>(__t) } - -> convertible_to&>; - }; - } - - template - requires view<_Vp> - && __detail::__has_tuple_element, _Nm> - && __detail::__has_tuple_element>, - _Nm> - class elements_view : public view_interface> - { - public: - elements_view() = default; - - constexpr explicit - elements_view(_Vp base) - : _M_base(std::move(base)) - { } - - constexpr _Vp - base() const& requires copy_constructible<_Vp> - { return _M_base; } - - constexpr _Vp - base() && - { return std::move(_M_base); } - - constexpr auto - begin() requires (!__detail::__simple_view<_Vp>) - { return _Iterator(ranges::begin(_M_base)); } - - constexpr auto - begin() const requires range - { return _Iterator(ranges::begin(_M_base)); } - - constexpr auto - end() requires (!__detail::__simple_view<_Vp> && !common_range<_Vp>) - { return _Sentinel{ranges::end(_M_base)}; } - - constexpr auto - end() requires (!__detail::__simple_view<_Vp> && common_range<_Vp>) - { return _Iterator{ranges::end(_M_base)}; } - - constexpr auto - end() const requires range - { return _Sentinel{ranges::end(_M_base)}; } - - constexpr auto - end() const requires common_range - { return _Iterator{ranges::end(_M_base)}; } - - constexpr auto - size() requires sized_range<_Vp> - { return ranges::size(_M_base); } - - constexpr auto - size() const requires sized_range - { return ranges::size(_M_base); } - - private: - template - struct _Sentinel; - - template - struct _Iterator - { - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - - iterator_t<_Base> _M_current = iterator_t<_Base>(); - - friend _Iterator; - - public: - using iterator_category - = typename iterator_traits>::iterator_category; - using value_type - = remove_cvref_t>>; - using difference_type = range_difference_t<_Base>; - - _Iterator() = default; - - constexpr explicit - _Iterator(iterator_t<_Base> current) - : _M_current(std::move(current)) - { } - - constexpr - _Iterator(_Iterator i) - requires _Const && convertible_to, iterator_t<_Base>> - : _M_current(std::move(i._M_current)) - { } - - constexpr iterator_t<_Base> - base() const& - requires copyable> - { return _M_current; } - - constexpr iterator_t<_Base> - base() && - { return std::move(_M_current); } - - constexpr decltype(auto) - operator*() const - { return std::get<_Nm>(*_M_current); } - - constexpr _Iterator& - operator++() - { - ++_M_current; - return *this; - } - - constexpr void - operator++(int) requires (!forward_range<_Base>) - { ++_M_current; } - - constexpr _Iterator - operator++(int) requires forward_range<_Base> - { - auto __tmp = *this; - ++_M_current; - return __tmp; - } - - constexpr _Iterator& - operator--() requires bidirectional_range<_Base> - { - --_M_current; - return *this; - } - - constexpr _Iterator - operator--(int) requires bidirectional_range<_Base> - { - auto __tmp = *this; - --_M_current; - return __tmp; - } - - constexpr _Iterator& - operator+=(difference_type __n) - requires random_access_range<_Base> - { - _M_current += __n; - return *this; - } - - constexpr _Iterator& - operator-=(difference_type __n) - requires random_access_range<_Base> - { - _M_current -= __n; - return *this; - } - - constexpr decltype(auto) - operator[](difference_type __n) const - requires random_access_range<_Base> - { return std::get<_Nm>(*(_M_current + __n)); } - - friend constexpr bool - operator==(const _Iterator& __x, const _Iterator& __y) - requires equality_comparable> - { return __x._M_current == __y._M_current; } - - friend constexpr bool - operator<(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return __x._M_current < __y._M_current; } - - friend constexpr bool - operator>(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return __y._M_current < __x._M_current; } - - friend constexpr bool - operator<=(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return !(__y._M_current > __x._M_current); } - - friend constexpr bool - operator>=(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return !(__x._M_current > __y._M_current); } - -#ifdef __cpp_lib_three_way_comparison - friend constexpr auto - operator<=>(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - && three_way_comparable> - { return __x._M_current <=> __y._M_current; } -#endif - - friend constexpr _Iterator - operator+(const _Iterator& __x, difference_type __y) - requires random_access_range<_Base> - { return _Iterator{__x} += __y; } - - friend constexpr _Iterator - operator+(difference_type __x, const _Iterator& __y) - requires random_access_range<_Base> - { return __y + __x; } - - friend constexpr _Iterator - operator-(const _Iterator& __x, difference_type __y) - requires random_access_range<_Base> - { return _Iterator{__x} -= __y; } - - friend constexpr difference_type - operator-(const _Iterator& __x, const _Iterator& __y) - requires random_access_range<_Base> - { return __x._M_current - __y._M_current; } - - friend _Sentinel<_Const>; - }; - - template - struct _Sentinel - { - private: - constexpr bool - _M_equal(const _Iterator<_Const>& __x) const - { return __x._M_current == _M_end; } - - using _Base = __detail::__maybe_const_t<_Const, _Vp>; - sentinel_t<_Base> _M_end = sentinel_t<_Base>(); - - public: - _Sentinel() = default; - - constexpr explicit - _Sentinel(sentinel_t<_Base> __end) - : _M_end(std::move(__end)) - { } - - constexpr - _Sentinel(_Sentinel __other) - requires _Const - && convertible_to, sentinel_t<_Base>> - : _M_end(std::move(__other._M_end)) - { } - - constexpr sentinel_t<_Base> - base() const - { return _M_end; } - - template - requires sentinel_for, - iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> - friend constexpr bool - operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) - { return __y._M_equal(__x); } - - template> - requires sized_sentinel_for, iterator_t<_Base2>> - friend constexpr range_difference_t<_Base2> - operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) - { return __x._M_current - __y._M_end; } - - template> - requires sized_sentinel_for, iterator_t<_Base2>> - friend constexpr range_difference_t<_Base> - operator-(const _Sentinel& __x, const _Iterator<_Const2>& __y) - { return __x._M_end - __y._M_current; } - - friend _Sentinel; - }; - - _Vp _M_base = _Vp(); - }; - - template - using keys_view = elements_view, 0>; - - template - using values_view = elements_view, 1>; - - namespace views - { - template - inline constexpr __adaptor::_RangeAdaptorClosure elements - = [] (_Range&& __r) - { - using _El = elements_view, _Nm>; - return _El{std::forward<_Range>(__r)}; - }; - - inline constexpr __adaptor::_RangeAdaptorClosure keys = elements<0>; - inline constexpr __adaptor::_RangeAdaptorClosure values = elements<1>; - } // namespace views - -} // namespace ranges - - namespace views = ranges::views; - - template - struct tuple_size> - : integral_constant - { }; - - template - struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>> - { using type = _Iter; }; - - template - struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>> - { using type = _Sent; }; - - template - struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>> - { using type = _Iter; }; - - template - struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>> - { using type = _Sent; }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace -#endif // library concepts -#endif // C++2a -#endif /* _GLIBCXX_RANGES */ diff --git a/resources/sources/avr-libstdcpp/include/ratio b/resources/sources/avr-libstdcpp/include/ratio deleted file mode 100644 index 83c8c7927..000000000 --- a/resources/sources/avr-libstdcpp/include/ratio +++ /dev/null @@ -1,576 +0,0 @@ -// ratio -*- C++ -*- - -// Copyright (C) 2008-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/ratio - * This is a Standard C++ Library header. - * @ingroup ratio - */ - -#ifndef _GLIBCXX_RATIO -#define _GLIBCXX_RATIO 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include // intmax_t, uintmax_t - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup ratio Rational Arithmetic - * @ingroup utilities - * - * Compile time representation of finite rational numbers. - * @{ - */ - - /// @cond undocumented - - template - struct __static_sign - : integral_constant - { }; - - template - struct __static_abs - : integral_constant::value> - { }; - - template - struct __static_gcd - : __static_gcd<_Qn, (_Pn % _Qn)> - { }; - - template - struct __static_gcd<_Pn, 0> - : integral_constant::value> - { }; - - template - struct __static_gcd<0, _Qn> - : integral_constant::value> - { }; - - // Let c = 2^(half # of bits in an intmax_t) - // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0 - // The multiplication of N and M becomes, - // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0 - // Multiplication is safe if each term and the sum of the terms - // is representable by intmax_t. - template - struct __safe_multiply - { - private: - static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); - - static const uintmax_t __a0 = __static_abs<_Pn>::value % __c; - static const uintmax_t __a1 = __static_abs<_Pn>::value / __c; - static const uintmax_t __b0 = __static_abs<_Qn>::value % __c; - static const uintmax_t __b1 = __static_abs<_Qn>::value / __c; - - static_assert(__a1 == 0 || __b1 == 0, - "overflow in multiplication"); - static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), - "overflow in multiplication"); - static_assert(__b0 * __a0 <= __INTMAX_MAX__, - "overflow in multiplication"); - static_assert((__a0 * __b1 + __b0 * __a1) * __c - <= __INTMAX_MAX__ - __b0 * __a0, - "overflow in multiplication"); - - public: - static const intmax_t value = _Pn * _Qn; - }; - - // Some double-precision utilities, where numbers are represented as - // __hi*2^(8*sizeof(uintmax_t)) + __lo. - template - struct __big_less - : integral_constant - { }; - - template - struct __big_add - { - static constexpr uintmax_t __lo = __lo1 + __lo2; - static constexpr uintmax_t __hi = (__hi1 + __hi2 + - (__lo1 + __lo2 < __lo1)); // carry - }; - - // Subtract a number from a bigger one. - template - struct __big_sub - { - static_assert(!__big_less<__hi1, __lo1, __hi2, __lo2>::value, - "Internal library error"); - static constexpr uintmax_t __lo = __lo1 - __lo2; - static constexpr uintmax_t __hi = (__hi1 - __hi2 - - (__lo1 < __lo2)); // carry - }; - - // Same principle as __safe_multiply. - template - struct __big_mul - { - private: - static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); - static constexpr uintmax_t __x0 = __x % __c; - static constexpr uintmax_t __x1 = __x / __c; - static constexpr uintmax_t __y0 = __y % __c; - static constexpr uintmax_t __y1 = __y / __c; - static constexpr uintmax_t __x0y0 = __x0 * __y0; - static constexpr uintmax_t __x0y1 = __x0 * __y1; - static constexpr uintmax_t __x1y0 = __x1 * __y0; - static constexpr uintmax_t __x1y1 = __x1 * __y1; - static constexpr uintmax_t __mix = __x0y1 + __x1y0; // possible carry... - static constexpr uintmax_t __mix_lo = __mix * __c; - static constexpr uintmax_t __mix_hi - = __mix / __c + ((__mix < __x0y1) ? __c : 0); // ... added here - typedef __big_add<__mix_hi, __mix_lo, __x1y1, __x0y0> _Res; - public: - static constexpr uintmax_t __hi = _Res::__hi; - static constexpr uintmax_t __lo = _Res::__lo; - }; - - // Adapted from __udiv_qrnnd_c in longlong.h - // This version assumes that the high bit of __d is 1. - template - struct __big_div_impl - { - private: - static_assert(__d >= (uintmax_t(1) << (sizeof(intmax_t) * 8 - 1)), - "Internal library error"); - static_assert(__n1 < __d, "Internal library error"); - static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); - static constexpr uintmax_t __d1 = __d / __c; - static constexpr uintmax_t __d0 = __d % __c; - - static constexpr uintmax_t __q1x = __n1 / __d1; - static constexpr uintmax_t __r1x = __n1 % __d1; - static constexpr uintmax_t __m = __q1x * __d0; - static constexpr uintmax_t __r1y = __r1x * __c + __n0 / __c; - static constexpr uintmax_t __r1z = __r1y + __d; - static constexpr uintmax_t __r1 - = ((__r1y < __m) ? ((__r1z >= __d) && (__r1z < __m)) - ? (__r1z + __d) : __r1z : __r1y) - __m; - static constexpr uintmax_t __q1 - = __q1x - ((__r1y < __m) - ? ((__r1z >= __d) && (__r1z < __m)) ? 2 : 1 : 0); - static constexpr uintmax_t __q0x = __r1 / __d1; - static constexpr uintmax_t __r0x = __r1 % __d1; - static constexpr uintmax_t __n = __q0x * __d0; - static constexpr uintmax_t __r0y = __r0x * __c + __n0 % __c; - static constexpr uintmax_t __r0z = __r0y + __d; - static constexpr uintmax_t __r0 - = ((__r0y < __n) ? ((__r0z >= __d) && (__r0z < __n)) - ? (__r0z + __d) : __r0z : __r0y) - __n; - static constexpr uintmax_t __q0 - = __q0x - ((__r0y < __n) ? ((__r0z >= __d) - && (__r0z < __n)) ? 2 : 1 : 0); - - public: - static constexpr uintmax_t __quot = __q1 * __c + __q0; - static constexpr uintmax_t __rem = __r0; - - private: - typedef __big_mul<__quot, __d> _Prod; - typedef __big_add<_Prod::__hi, _Prod::__lo, 0, __rem> _Sum; - static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, - "Internal library error"); - }; - - template - struct __big_div - { - private: - static_assert(__d != 0, "Internal library error"); - static_assert(sizeof (uintmax_t) == sizeof (unsigned long long), - "This library calls __builtin_clzll on uintmax_t, which " - "is unsafe on your platform. Please complain to " - "http://gcc.gnu.org/bugzilla/"); - static constexpr int __shift = __builtin_clzll(__d); - static constexpr int __coshift_ = sizeof(uintmax_t) * 8 - __shift; - static constexpr int __coshift = (__shift != 0) ? __coshift_ : 0; - static constexpr uintmax_t __c1 = uintmax_t(1) << __shift; - static constexpr uintmax_t __c2 = uintmax_t(1) << __coshift; - static constexpr uintmax_t __new_d = __d * __c1; - static constexpr uintmax_t __new_n0 = __n0 * __c1; - static constexpr uintmax_t __n1_shifted = (__n1 % __d) * __c1; - static constexpr uintmax_t __n0_top = (__shift != 0) ? (__n0 / __c2) : 0; - static constexpr uintmax_t __new_n1 = __n1_shifted + __n0_top; - typedef __big_div_impl<__new_n1, __new_n0, __new_d> _Res; - - public: - static constexpr uintmax_t __quot_hi = __n1 / __d; - static constexpr uintmax_t __quot_lo = _Res::__quot; - static constexpr uintmax_t __rem = _Res::__rem / __c1; - - private: - typedef __big_mul<__quot_lo, __d> _P0; - typedef __big_mul<__quot_hi, __d> _P1; - typedef __big_add<_P0::__hi, _P0::__lo, _P1::__lo, __rem> _Sum; - // No overflow. - static_assert(_P1::__hi == 0, "Internal library error"); - static_assert(_Sum::__hi >= _P0::__hi, "Internal library error"); - // Matches the input data. - static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, - "Internal library error"); - static_assert(__rem < __d, "Internal library error"); - }; - - /// @endcond - - /** - * @brief Provides compile-time rational arithmetic. - * - * This class template represents any finite rational number with a - * numerator and denominator representable by compile-time constants of - * type intmax_t. The ratio is simplified when instantiated. - * - * For example: - * @code - * std::ratio<7,-21>::num == -1; - * std::ratio<7,-21>::den == 3; - * @endcode - * - */ - template - struct ratio - { - static_assert(_Den != 0, "denominator cannot be zero"); - static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__, - "out of range"); - - // Note: sign(N) * abs(N) == N - static constexpr intmax_t num = - _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value; - - static constexpr intmax_t den = - __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value; - - typedef ratio type; - }; - - template - constexpr intmax_t ratio<_Num, _Den>::num; - - template - constexpr intmax_t ratio<_Num, _Den>::den; - - /// @cond undocumented - - template - struct __ratio_multiply - { - private: - static const intmax_t __gcd1 = - __static_gcd<_R1::num, _R2::den>::value; - static const intmax_t __gcd2 = - __static_gcd<_R2::num, _R1::den>::value; - - public: - typedef ratio< - __safe_multiply<(_R1::num / __gcd1), - (_R2::num / __gcd2)>::value, - __safe_multiply<(_R1::den / __gcd2), - (_R2::den / __gcd1)>::value> type; - - static constexpr intmax_t num = type::num; - static constexpr intmax_t den = type::den; - }; - - template - constexpr intmax_t __ratio_multiply<_R1, _R2>::num; - - template - constexpr intmax_t __ratio_multiply<_R1, _R2>::den; - - /// @endcond - - /// ratio_multiply - template - using ratio_multiply = typename __ratio_multiply<_R1, _R2>::type; - - /// @cond undocumented - - template - struct __ratio_divide - { - static_assert(_R2::num != 0, "division by 0"); - - typedef typename __ratio_multiply< - _R1, - ratio<_R2::den, _R2::num>>::type type; - - static constexpr intmax_t num = type::num; - static constexpr intmax_t den = type::den; - }; - - template - constexpr intmax_t __ratio_divide<_R1, _R2>::num; - - template - constexpr intmax_t __ratio_divide<_R1, _R2>::den; - - /// @endcond - - /// ratio_divide - template - using ratio_divide = typename __ratio_divide<_R1, _R2>::type; - - /// ratio_equal - template - struct ratio_equal - : integral_constant - { }; - - /// ratio_not_equal - template - struct ratio_not_equal - : integral_constant::value> - { }; - - /// @cond undocumented - - // Both numbers are positive. - template, - typename _Right = __big_mul<_R2::num,_R1::den> > - struct __ratio_less_impl_1 - : integral_constant::value> - { }; - - template::value - != __static_sign<_R2::num>::value)), - bool = (__static_sign<_R1::num>::value == -1 - && __static_sign<_R2::num>::value == -1)> - struct __ratio_less_impl - : __ratio_less_impl_1<_R1, _R2>::type - { }; - - template - struct __ratio_less_impl<_R1, _R2, true, false> - : integral_constant - { }; - - template - struct __ratio_less_impl<_R1, _R2, false, true> - : __ratio_less_impl_1, - ratio<-_R1::num, _R1::den> >::type - { }; - - /// @endcond - - /// ratio_less - template - struct ratio_less - : __ratio_less_impl<_R1, _R2>::type - { }; - - /// ratio_less_equal - template - struct ratio_less_equal - : integral_constant::value> - { }; - - /// ratio_greater - template - struct ratio_greater - : integral_constant::value> - { }; - - /// ratio_greater_equal - template - struct ratio_greater_equal - : integral_constant::value> - { }; - -#if __cplusplus > 201402L - template - inline constexpr bool ratio_equal_v = ratio_equal<_R1, _R2>::value; - template - inline constexpr bool ratio_not_equal_v = ratio_not_equal<_R1, _R2>::value; - template - inline constexpr bool ratio_less_v = ratio_less<_R1, _R2>::value; - template - inline constexpr bool ratio_less_equal_v = - ratio_less_equal<_R1, _R2>::value; - template - inline constexpr bool ratio_greater_v = ratio_greater<_R1, _R2>::value; - template - inline constexpr bool ratio_greater_equal_v - = ratio_greater_equal<_R1, _R2>::value; -#endif // C++17 - - /// @cond undocumented - - template= 0), - bool = (_R2::num >= 0), - bool = ratio_less::value, _R1::den>, - ratio<__static_abs<_R2::num>::value, _R2::den> >::value> - struct __ratio_add_impl - { - private: - typedef typename __ratio_add_impl< - ratio<-_R1::num, _R1::den>, - ratio<-_R2::num, _R2::den> >::type __t; - public: - typedef ratio<-__t::num, __t::den> type; - }; - - // True addition of nonnegative numbers. - template - struct __ratio_add_impl<_R1, _R2, true, true, __b> - { - private: - static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; - static constexpr uintmax_t __d2 = _R2::den / __g; - typedef __big_mul<_R1::den, __d2> __d; - typedef __big_mul<_R1::num, _R2::den / __g> __x; - typedef __big_mul<_R2::num, _R1::den / __g> __y; - typedef __big_add<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; - static_assert(__n::__hi >= __x::__hi, "Internal library error"); - typedef __big_div<__n::__hi, __n::__lo, __g> __ng; - static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; - typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; - static_assert(__n_final::__rem == 0, "Internal library error"); - static_assert(__n_final::__quot_hi == 0 && - __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); - typedef __big_mul<_R1::den / __g2, __d2> __d_final; - static_assert(__d_final::__hi == 0 && - __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); - public: - typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; - }; - - template - struct __ratio_add_impl<_R1, _R2, false, true, true> - : __ratio_add_impl<_R2, _R1> - { }; - - // True subtraction of nonnegative numbers yielding a nonnegative result. - template - struct __ratio_add_impl<_R1, _R2, true, false, false> - { - private: - static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; - static constexpr uintmax_t __d2 = _R2::den / __g; - typedef __big_mul<_R1::den, __d2> __d; - typedef __big_mul<_R1::num, _R2::den / __g> __x; - typedef __big_mul<-_R2::num, _R1::den / __g> __y; - typedef __big_sub<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; - typedef __big_div<__n::__hi, __n::__lo, __g> __ng; - static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; - typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; - static_assert(__n_final::__rem == 0, "Internal library error"); - static_assert(__n_final::__quot_hi == 0 && - __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); - typedef __big_mul<_R1::den / __g2, __d2> __d_final; - static_assert(__d_final::__hi == 0 && - __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); - public: - typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; - }; - - template - struct __ratio_add - { - typedef typename __ratio_add_impl<_R1, _R2>::type type; - static constexpr intmax_t num = type::num; - static constexpr intmax_t den = type::den; - }; - - template - constexpr intmax_t __ratio_add<_R1, _R2>::num; - - template - constexpr intmax_t __ratio_add<_R1, _R2>::den; - - /// @endcond - - /// ratio_add - template - using ratio_add = typename __ratio_add<_R1, _R2>::type; - - /// @cond undocumented - - template - struct __ratio_subtract - { - typedef typename __ratio_add< - _R1, - ratio<-_R2::num, _R2::den>>::type type; - - static constexpr intmax_t num = type::num; - static constexpr intmax_t den = type::den; - }; - - template - constexpr intmax_t __ratio_subtract<_R1, _R2>::num; - - template - constexpr intmax_t __ratio_subtract<_R1, _R2>::den; - - /// @endcond - - /// ratio_subtract - template - using ratio_subtract = typename __ratio_subtract<_R1, _R2>::type; - - - typedef ratio<1, 1000000000000000000> atto; - typedef ratio<1, 1000000000000000> femto; - typedef ratio<1, 1000000000000> pico; - typedef ratio<1, 1000000000> nano; - typedef ratio<1, 1000000> micro; - typedef ratio<1, 1000> milli; - typedef ratio<1, 100> centi; - typedef ratio<1, 10> deci; - typedef ratio< 10, 1> deca; - typedef ratio< 100, 1> hecto; - typedef ratio< 1000, 1> kilo; - typedef ratio< 1000000, 1> mega; - typedef ratio< 1000000000, 1> giga; - typedef ratio< 1000000000000, 1> tera; - typedef ratio< 1000000000000000, 1> peta; - typedef ratio< 1000000000000000000, 1> exa; - - // @} group ratio -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 - -#endif //_GLIBCXX_RATIO diff --git a/resources/sources/avr-libstdcpp/include/scoped_allocator b/resources/sources/avr-libstdcpp/include/scoped_allocator deleted file mode 100644 index 969b6d8e8..000000000 --- a/resources/sources/avr-libstdcpp/include/scoped_allocator +++ /dev/null @@ -1,519 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2011-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/scoped_allocator - * This is a Standard C++ Library header. - * @ingroup allocators - */ - -#ifndef _SCOPED_ALLOCATOR -#define _SCOPED_ALLOCATOR 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup allocators - * @{ - */ - - /// @cond undocumented - - template - using __outer_allocator_t - = decltype(std::declval<_Alloc>().outer_allocator()); - - template - struct __outermost_type - { - using type = _Alloc; - static type& _S_outermost(_Alloc& __a) { return __a; } - }; - - template - struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>> - : __outermost_type< - typename remove_reference<__outer_allocator_t<_Alloc>>::type - > - { - using __base = __outermost_type< - typename remove_reference<__outer_allocator_t<_Alloc>>::type - >; - - static typename __base::type& - _S_outermost(_Alloc& __a) - { return __base::_S_outermost(__a.outer_allocator()); } - }; - - /// Implementation of the OUTERMOST pseudofunction - template - inline typename __outermost_type<_Alloc>::type& - __outermost(_Alloc& __a) - { return __outermost_type<_Alloc>::_S_outermost(__a); } - - template - class scoped_allocator_adaptor; - - template - struct __inner_type_impl; - - template - struct __inner_type_impl<_Outer> - { - typedef scoped_allocator_adaptor<_Outer> __type; - - __inner_type_impl() = default; - __inner_type_impl(const __inner_type_impl&) = default; - __inner_type_impl(__inner_type_impl&&) = default; - __inner_type_impl& operator=(const __inner_type_impl&) = default; - __inner_type_impl& operator=(__inner_type_impl&&) = default; - - template - __inner_type_impl(const __inner_type_impl<_Alloc>& __other) - { } - - template - __inner_type_impl(__inner_type_impl<_Alloc>&& __other) - { } - - __type& - _M_get(__type* __p) noexcept { return *__p; } - - const __type& - _M_get(const __type* __p) const noexcept { return *__p; } - - tuple<> - _M_tie() const noexcept { return tuple<>(); } - - bool - operator==(const __inner_type_impl&) const noexcept - { return true; } - }; - - template - struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> - { - typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; - - __inner_type_impl() = default; - __inner_type_impl(const __inner_type_impl&) = default; - __inner_type_impl(__inner_type_impl&&) = default; - __inner_type_impl& operator=(const __inner_type_impl&) = default; - __inner_type_impl& operator=(__inner_type_impl&&) = default; - - template - __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) - : _M_inner(__other._M_inner) { } - - template - __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) - : _M_inner(std::move(__other._M_inner)) { } - - template - explicit - __inner_type_impl(_Args&&... __args) - : _M_inner(std::forward<_Args>(__args)...) { } - - __type& - _M_get(void*) noexcept { return _M_inner; } - - const __type& - _M_get(const void*) const noexcept { return _M_inner; } - - tuple - _M_tie() const noexcept - { return _M_inner._M_tie(); } - - bool - operator==(const __inner_type_impl& __other) const noexcept - { return _M_inner == __other._M_inner; } - - private: - template friend class __inner_type_impl; - template friend class scoped_allocator_adaptor; - - __type _M_inner; - }; - - /// @endcond - - /// An adaptor to recursively pass an allocator to the objects it constructs - template - class scoped_allocator_adaptor - : public _OuterAlloc - { - typedef allocator_traits<_OuterAlloc> __traits; - - typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; - __inner_type _M_inner; - - template - friend class scoped_allocator_adaptor; - - template - friend class __inner_type_impl; - - tuple - _M_tie() const noexcept - { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } - - template - using __outermost_alloc_traits - = allocator_traits::type>; - -#if __cplusplus <= 201703 - template - void - _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) - { - typedef __outermost_alloc_traits _O_traits; - _O_traits::construct(__outermost(*this), __p, - std::forward<_Args>(__args)...); - } - - typedef __uses_alloc1 __uses_alloc1_; - typedef __uses_alloc2 __uses_alloc2_; - - template - void - _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) - { - typedef __outermost_alloc_traits _O_traits; - _O_traits::construct(__outermost(*this), __p, - allocator_arg, inner_allocator(), - std::forward<_Args>(__args)...); - } - - template - void - _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) - { - typedef __outermost_alloc_traits _O_traits; - _O_traits::construct(__outermost(*this), __p, - std::forward<_Args>(__args)..., - inner_allocator()); - } -#endif // C++17 - - template - static _Alloc - _S_select_on_copy(const _Alloc& __a) - { - typedef allocator_traits<_Alloc> __a_traits; - return __a_traits::select_on_container_copy_construction(__a); - } - - template - scoped_allocator_adaptor(tuple __refs, - _Index_tuple<_Indices...>) - : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), - _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) - { } - - // Used to constrain constructors to disallow invalid conversions. - template - using _Constructible = typename enable_if< - is_constructible<_OuterAlloc, _Alloc>::value - >::type; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2975. Missing case for pair construction in scoped [...] allocators - template - struct __not_pair { using type = void; }; - - template - struct __not_pair> { }; - - public: - typedef _OuterAlloc outer_allocator_type; - typedef typename __inner_type::__type inner_allocator_type; - - typedef typename __traits::value_type value_type; - typedef typename __traits::size_type size_type; - typedef typename __traits::difference_type difference_type; - typedef typename __traits::pointer pointer; - typedef typename __traits::const_pointer const_pointer; - typedef typename __traits::void_pointer void_pointer; - typedef typename __traits::const_void_pointer const_void_pointer; - - typedef typename __or_< - typename __traits::propagate_on_container_copy_assignment, - typename allocator_traits<_InnerAllocs>:: - propagate_on_container_copy_assignment...>::type - propagate_on_container_copy_assignment; - - typedef typename __or_< - typename __traits::propagate_on_container_move_assignment, - typename allocator_traits<_InnerAllocs>:: - propagate_on_container_move_assignment...>::type - propagate_on_container_move_assignment; - - typedef typename __or_< - typename __traits::propagate_on_container_swap, - typename allocator_traits<_InnerAllocs>:: - propagate_on_container_swap...>::type - propagate_on_container_swap; - - typedef typename __and_< - typename __traits::is_always_equal, - typename allocator_traits<_InnerAllocs>::is_always_equal...>::type - is_always_equal; - - template - struct rebind - { - typedef scoped_allocator_adaptor< - typename __traits::template rebind_alloc<_Tp>, - _InnerAllocs...> other; - }; - - scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } - - template> - scoped_allocator_adaptor(_Outer2&& __outer, - const _InnerAllocs&... __inner) - : _OuterAlloc(std::forward<_Outer2>(__outer)), - _M_inner(__inner...) - { } - - scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) - : _OuterAlloc(__other.outer_allocator()), - _M_inner(__other._M_inner) - { } - - scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) - : _OuterAlloc(std::move(__other.outer_allocator())), - _M_inner(std::move(__other._M_inner)) - { } - - template> - scoped_allocator_adaptor( - const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) - : _OuterAlloc(__other.outer_allocator()), - _M_inner(__other._M_inner) - { } - - template> - scoped_allocator_adaptor( - scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) - : _OuterAlloc(std::move(__other.outer_allocator())), - _M_inner(std::move(__other._M_inner)) - { } - - scoped_allocator_adaptor& - operator=(const scoped_allocator_adaptor&) = default; - - scoped_allocator_adaptor& - operator=(scoped_allocator_adaptor&&) = default; - - inner_allocator_type& inner_allocator() noexcept - { return _M_inner._M_get(this); } - - const inner_allocator_type& inner_allocator() const noexcept - { return _M_inner._M_get(this); } - - outer_allocator_type& outer_allocator() noexcept - { return static_cast<_OuterAlloc&>(*this); } - - const outer_allocator_type& outer_allocator() const noexcept - { return static_cast(*this); } - - _GLIBCXX_NODISCARD pointer allocate(size_type __n) - { return __traits::allocate(outer_allocator(), __n); } - - _GLIBCXX_NODISCARD pointer allocate(size_type __n, const_void_pointer __hint) - { return __traits::allocate(outer_allocator(), __n, __hint); } - - void deallocate(pointer __p, size_type __n) - { return __traits::deallocate(outer_allocator(), __p, __n); } - - size_type max_size() const - { return __traits::max_size(outer_allocator()); } - -#if __cplusplus <= 201703 - template - typename __not_pair<_Tp>::type - construct(_Tp* __p, _Args&&... __args) - { - auto& __inner = inner_allocator(); - auto __use_tag - = std::__use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); - _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); - } - - template - void - construct(pair<_T1, _T2>* __p, piecewise_construct_t, - tuple<_Args1...> __x, tuple<_Args2...> __y) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2203. wrong argument types for piecewise construction - auto& __inner = inner_allocator(); - auto __x_use_tag - = std::__use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); - auto __y_use_tag - = std::__use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); - typename _Build_index_tuple::__type __x_indices; - typename _Build_index_tuple::__type __y_indices; - typedef __outermost_alloc_traits _O_traits; - _O_traits::construct(__outermost(*this), __p, piecewise_construct, - _M_construct_p(__x_use_tag, __x_indices, __x), - _M_construct_p(__y_use_tag, __y_indices, __y)); - } - - template - void - construct(pair<_T1, _T2>* __p) - { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } - - template - void - construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) - { - construct(__p, piecewise_construct, - std::forward_as_tuple(std::forward<_Up>(__u)), - std::forward_as_tuple(std::forward<_Vp>(__v))); - } - - template - void - construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) - { - construct(__p, piecewise_construct, - std::forward_as_tuple(__x.first), - std::forward_as_tuple(__x.second)); - } - - template - void - construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) - { - construct(__p, piecewise_construct, - std::forward_as_tuple(std::forward<_Up>(__x.first)), - std::forward_as_tuple(std::forward<_Vp>(__x.second))); - } -#else // C++2a - template - __attribute__((__nonnull__)) - void - construct(_Tp* __p, _Args&&... __args) - { - typedef __outermost_alloc_traits _O_traits; - std::apply([__p, this](auto&&... __newargs) { - _O_traits::construct(__outermost(*this), __p, - std::forward(__newargs)...); - }, - uses_allocator_construction_args<_Tp>(inner_allocator(), - std::forward<_Args>(__args)...)); - } -#endif // C++2a - - template - void destroy(_Tp* __p) - { - typedef __outermost_alloc_traits _O_traits; - _O_traits::destroy(__outermost(*this), __p); - } - - scoped_allocator_adaptor - select_on_container_copy_construction() const - { - typedef typename _Build_index_tuple::__type - _Indices; - return scoped_allocator_adaptor(_M_tie(), _Indices()); - } - - template - friend bool - operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, - const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; - - private: -#if __cplusplus <= 201703L - template - tuple<_Args&&...> - _M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) - { return std::move(__t); } - - template - tuple - _M_construct_p(__uses_alloc1_, _Index_tuple<_Ind...>, - tuple<_Args...>& __t) - { - return { allocator_arg, inner_allocator(), - std::get<_Ind>(std::move(__t))... - }; - } - - template - tuple<_Args&&..., inner_allocator_type&> - _M_construct_p(__uses_alloc2_, _Index_tuple<_Ind...>, - tuple<_Args...>& __t) - { - return { std::get<_Ind>(std::move(__t))..., inner_allocator() }; - } -#endif // C++17 - }; - - /// @related std::scoped_allocator_adaptor - template - inline bool - operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, - const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept - { - return __a.outer_allocator() == __b.outer_allocator() - && __a._M_inner == __b._M_inner; - } - -#if __cpp_impl_three_way_comparison < 201907L - /// @related std::scoped_allocator_adaptor - template - inline bool - operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, - const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept - { return !(__a == __b); } -#endif - - /// @} - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++11 - -#endif // _SCOPED_ALLOCATOR diff --git a/resources/sources/avr-libstdcpp/include/set b/resources/sources/avr-libstdcpp/include/set deleted file mode 100644 index 168918346..000000000 --- a/resources/sources/avr-libstdcpp/include/set +++ /dev/null @@ -1,105 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/set - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_SET -#define _GLIBCXX_SET 1 - -#pragma GCC system_header - -#include -#include -#include -#include -#include - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#if __cplusplus >= 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace pmr - { - template class polymorphic_allocator; - template> - using set = std::set<_Key, _Cmp, polymorphic_allocator<_Key>>; - template> - using multiset = std::multiset<_Key, _Cmp, polymorphic_allocator<_Key>>; - } // namespace pmr -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 - -#if __cplusplus > 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - template - inline typename set<_Key, _Compare, _Alloc>::size_type - erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) - { return __detail::__erase_nodes_if(__cont, __pred); } - - template - inline typename multiset<_Key, _Compare, _Alloc>::size_type - erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) - { return __detail::__erase_nodes_if(__cont, __pred); } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 - -#endif /* _GLIBCXX_SET */ diff --git a/resources/sources/avr-libstdcpp/include/shared_mutex b/resources/sources/avr-libstdcpp/include/shared_mutex deleted file mode 100644 index 343886107..000000000 --- a/resources/sources/avr-libstdcpp/include/shared_mutex +++ /dev/null @@ -1,855 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/shared_mutex - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_SHARED_MUTEX -#define _GLIBCXX_SHARED_MUTEX 1 - -#pragma GCC system_header - -#if __cplusplus >= 201402L - -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup mutexes - * @{ - */ - -#ifdef _GLIBCXX_HAS_GTHREADS - -#if __cplusplus >= 201703L -#define __cpp_lib_shared_mutex 201505 - class shared_mutex; -#endif - -#define __cpp_lib_shared_timed_mutex 201402 - class shared_timed_mutex; - - /// @cond undocumented - -#if _GLIBCXX_USE_PTHREAD_RWLOCK_T -#ifdef __gthrw -#define _GLIBCXX_GTHRW(name) \ - __gthrw(pthread_ ## name); \ - static inline int \ - __glibcxx_ ## name (pthread_rwlock_t *__rwlock) \ - { \ - if (__gthread_active_p ()) \ - return __gthrw_(pthread_ ## name) (__rwlock); \ - else \ - return 0; \ - } - _GLIBCXX_GTHRW(rwlock_rdlock) - _GLIBCXX_GTHRW(rwlock_tryrdlock) - _GLIBCXX_GTHRW(rwlock_wrlock) - _GLIBCXX_GTHRW(rwlock_trywrlock) - _GLIBCXX_GTHRW(rwlock_unlock) -# ifndef PTHREAD_RWLOCK_INITIALIZER - _GLIBCXX_GTHRW(rwlock_destroy) - __gthrw(pthread_rwlock_init); - static inline int - __glibcxx_rwlock_init (pthread_rwlock_t *__rwlock) - { - if (__gthread_active_p ()) - return __gthrw_(pthread_rwlock_init) (__rwlock, NULL); - else - return 0; - } -# endif -# if _GTHREAD_USE_MUTEX_TIMEDLOCK - __gthrw(pthread_rwlock_timedrdlock); - static inline int - __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock, - const timespec *__ts) - { - if (__gthread_active_p ()) - return __gthrw_(pthread_rwlock_timedrdlock) (__rwlock, __ts); - else - return 0; - } - __gthrw(pthread_rwlock_timedwrlock); - static inline int - __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock, - const timespec *__ts) - { - if (__gthread_active_p ()) - return __gthrw_(pthread_rwlock_timedwrlock) (__rwlock, __ts); - else - return 0; - } -# endif -#else - static inline int - __glibcxx_rwlock_rdlock (pthread_rwlock_t *__rwlock) - { return pthread_rwlock_rdlock (__rwlock); } - static inline int - __glibcxx_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) - { return pthread_rwlock_tryrdlock (__rwlock); } - static inline int - __glibcxx_rwlock_wrlock (pthread_rwlock_t *__rwlock) - { return pthread_rwlock_wrlock (__rwlock); } - static inline int - __glibcxx_rwlock_trywrlock (pthread_rwlock_t *__rwlock) - { return pthread_rwlock_trywrlock (__rwlock); } - static inline int - __glibcxx_rwlock_unlock (pthread_rwlock_t *__rwlock) - { return pthread_rwlock_unlock (__rwlock); } - static inline int - __glibcxx_rwlock_destroy(pthread_rwlock_t *__rwlock) - { return pthread_rwlock_destroy (__rwlock); } - static inline int - __glibcxx_rwlock_init(pthread_rwlock_t *__rwlock) - { return pthread_rwlock_init (__rwlock, NULL); } -# if _GTHREAD_USE_MUTEX_TIMEDLOCK - static inline int - __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock, - const timespec *__ts) - { return pthread_rwlock_timedrdlock (__rwlock, __ts); } - static inline int - __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock, - const timespec *__ts) - { return pthread_rwlock_timedwrlock (__rwlock, __ts); } -# endif -#endif - - /// A shared mutex type implemented using pthread_rwlock_t. - class __shared_mutex_pthread - { - friend class shared_timed_mutex; - -#ifdef PTHREAD_RWLOCK_INITIALIZER - pthread_rwlock_t _M_rwlock = PTHREAD_RWLOCK_INITIALIZER; - - public: - __shared_mutex_pthread() = default; - ~__shared_mutex_pthread() = default; -#else - pthread_rwlock_t _M_rwlock; - - public: - __shared_mutex_pthread() - { - int __ret = __glibcxx_rwlock_init(&_M_rwlock); - if (__ret == ENOMEM) - __throw_bad_alloc(); - else if (__ret == EAGAIN) - __throw_system_error(int(errc::resource_unavailable_try_again)); - else if (__ret == EPERM) - __throw_system_error(int(errc::operation_not_permitted)); - // Errors not handled: EBUSY, EINVAL - __glibcxx_assert(__ret == 0); - } - - ~__shared_mutex_pthread() - { - int __ret __attribute((__unused__)) = __glibcxx_rwlock_destroy(&_M_rwlock); - // Errors not handled: EBUSY, EINVAL - __glibcxx_assert(__ret == 0); - } -#endif - - __shared_mutex_pthread(const __shared_mutex_pthread&) = delete; - __shared_mutex_pthread& operator=(const __shared_mutex_pthread&) = delete; - - void - lock() - { - int __ret = __glibcxx_rwlock_wrlock(&_M_rwlock); - if (__ret == EDEADLK) - __throw_system_error(int(errc::resource_deadlock_would_occur)); - // Errors not handled: EINVAL - __glibcxx_assert(__ret == 0); - } - - bool - try_lock() - { - int __ret = __glibcxx_rwlock_trywrlock(&_M_rwlock); - if (__ret == EBUSY) return false; - // Errors not handled: EINVAL - __glibcxx_assert(__ret == 0); - return true; - } - - void - unlock() - { - int __ret __attribute((__unused__)) = __glibcxx_rwlock_unlock(&_M_rwlock); - // Errors not handled: EPERM, EBUSY, EINVAL - __glibcxx_assert(__ret == 0); - } - - // Shared ownership - - void - lock_shared() - { - int __ret; - // We retry if we exceeded the maximum number of read locks supported by - // the POSIX implementation; this can result in busy-waiting, but this - // is okay based on the current specification of forward progress - // guarantees by the standard. - do - __ret = __glibcxx_rwlock_rdlock(&_M_rwlock); - while (__ret == EAGAIN); - if (__ret == EDEADLK) - __throw_system_error(int(errc::resource_deadlock_would_occur)); - // Errors not handled: EINVAL - __glibcxx_assert(__ret == 0); - } - - bool - try_lock_shared() - { - int __ret = __glibcxx_rwlock_tryrdlock(&_M_rwlock); - // If the maximum number of read locks has been exceeded, we just fail - // to acquire the lock. Unlike for lock(), we are not allowed to throw - // an exception. - if (__ret == EBUSY || __ret == EAGAIN) return false; - // Errors not handled: EINVAL - __glibcxx_assert(__ret == 0); - return true; - } - - void - unlock_shared() - { - unlock(); - } - - void* native_handle() { return &_M_rwlock; } - }; -#endif - -#if ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) - /// A shared mutex type implemented using std::condition_variable. - class __shared_mutex_cv - { - friend class shared_timed_mutex; - - // Based on Howard Hinnant's reference implementation from N2406. - - // The high bit of _M_state is the write-entered flag which is set to - // indicate a writer has taken the lock or is queuing to take the lock. - // The remaining bits are the count of reader locks. - // - // To take a reader lock, block on gate1 while the write-entered flag is - // set or the maximum number of reader locks is held, then increment the - // reader lock count. - // To release, decrement the count, then if the write-entered flag is set - // and the count is zero then signal gate2 to wake a queued writer, - // otherwise if the maximum number of reader locks was held signal gate1 - // to wake a reader. - // - // To take a writer lock, block on gate1 while the write-entered flag is - // set, then set the write-entered flag to start queueing, then block on - // gate2 while the number of reader locks is non-zero. - // To release, unset the write-entered flag and signal gate1 to wake all - // blocked readers and writers. - // - // This means that when no reader locks are held readers and writers get - // equal priority. When one or more reader locks is held a writer gets - // priority and no more reader locks can be taken while the writer is - // queued. - - // Only locked when accessing _M_state or waiting on condition variables. - mutex _M_mut; - // Used to block while write-entered is set or reader count at maximum. - condition_variable _M_gate1; - // Used to block queued writers while reader count is non-zero. - condition_variable _M_gate2; - // The write-entered flag and reader count. - unsigned _M_state; - - static constexpr unsigned _S_write_entered - = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1); - static constexpr unsigned _S_max_readers = ~_S_write_entered; - - // Test whether the write-entered flag is set. _M_mut must be locked. - bool _M_write_entered() const { return _M_state & _S_write_entered; } - - // The number of reader locks currently held. _M_mut must be locked. - unsigned _M_readers() const { return _M_state & _S_max_readers; } - - public: - __shared_mutex_cv() : _M_state(0) {} - - ~__shared_mutex_cv() - { - __glibcxx_assert( _M_state == 0 ); - } - - __shared_mutex_cv(const __shared_mutex_cv&) = delete; - __shared_mutex_cv& operator=(const __shared_mutex_cv&) = delete; - - // Exclusive ownership - - void - lock() - { - unique_lock __lk(_M_mut); - // Wait until we can set the write-entered flag. - _M_gate1.wait(__lk, [=]{ return !_M_write_entered(); }); - _M_state |= _S_write_entered; - // Then wait until there are no more readers. - _M_gate2.wait(__lk, [=]{ return _M_readers() == 0; }); - } - - bool - try_lock() - { - unique_lock __lk(_M_mut, try_to_lock); - if (__lk.owns_lock() && _M_state == 0) - { - _M_state = _S_write_entered; - return true; - } - return false; - } - - void - unlock() - { - lock_guard __lk(_M_mut); - __glibcxx_assert( _M_write_entered() ); - _M_state = 0; - // call notify_all() while mutex is held so that another thread can't - // lock and unlock the mutex then destroy *this before we make the call. - _M_gate1.notify_all(); - } - - // Shared ownership - - void - lock_shared() - { - unique_lock __lk(_M_mut); - _M_gate1.wait(__lk, [=]{ return _M_state < _S_max_readers; }); - ++_M_state; - } - - bool - try_lock_shared() - { - unique_lock __lk(_M_mut, try_to_lock); - if (!__lk.owns_lock()) - return false; - if (_M_state < _S_max_readers) - { - ++_M_state; - return true; - } - return false; - } - - void - unlock_shared() - { - lock_guard __lk(_M_mut); - __glibcxx_assert( _M_readers() > 0 ); - auto __prev = _M_state--; - if (_M_write_entered()) - { - // Wake the queued writer if there are no more readers. - if (_M_readers() == 0) - _M_gate2.notify_one(); - // No need to notify gate1 because we give priority to the queued - // writer, and that writer will eventually notify gate1 after it - // clears the write-entered flag. - } - else - { - // Wake any thread that was blocked on reader overflow. - if (__prev == _S_max_readers) - _M_gate1.notify_one(); - } - } - }; -#endif - /// @endcond - -#if __cplusplus > 201402L - /// The standard shared mutex type. - class shared_mutex - { - public: - shared_mutex() = default; - ~shared_mutex() = default; - - shared_mutex(const shared_mutex&) = delete; - shared_mutex& operator=(const shared_mutex&) = delete; - - // Exclusive ownership - - void lock() { _M_impl.lock(); } - bool try_lock() { return _M_impl.try_lock(); } - void unlock() { _M_impl.unlock(); } - - // Shared ownership - - void lock_shared() { _M_impl.lock_shared(); } - bool try_lock_shared() { return _M_impl.try_lock_shared(); } - void unlock_shared() { _M_impl.unlock_shared(); } - -#if _GLIBCXX_USE_PTHREAD_RWLOCK_T - typedef void* native_handle_type; - native_handle_type native_handle() { return _M_impl.native_handle(); } - - private: - __shared_mutex_pthread _M_impl; -#else - private: - __shared_mutex_cv _M_impl; -#endif - }; -#endif // C++17 - - /// @cond undocumented -#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK - using __shared_timed_mutex_base = __shared_mutex_pthread; -#else - using __shared_timed_mutex_base = __shared_mutex_cv; -#endif - /// @endcond - - /// The standard shared timed mutex type. - class shared_timed_mutex - : private __shared_timed_mutex_base - { - using _Base = __shared_timed_mutex_base; - - // Must use the same clock as condition_variable for __shared_mutex_cv. -#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK - using __clock_t = chrono::steady_clock; -#else - using __clock_t = chrono::system_clock; -#endif - - public: - shared_timed_mutex() = default; - ~shared_timed_mutex() = default; - - shared_timed_mutex(const shared_timed_mutex&) = delete; - shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; - - // Exclusive ownership - - void lock() { _Base::lock(); } - bool try_lock() { return _Base::try_lock(); } - void unlock() { _Base::unlock(); } - - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) - { - auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime); - if (ratio_greater<__clock_t::period, _Period>()) - ++__rt; - return try_lock_until(__clock_t::now() + __rt); - } - - // Shared ownership - - void lock_shared() { _Base::lock_shared(); } - bool try_lock_shared() { return _Base::try_lock_shared(); } - void unlock_shared() { _Base::unlock_shared(); } - - template - bool - try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rtime) - { - auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime); - if (ratio_greater<__clock_t::period, _Period>()) - ++__rt; - return try_lock_shared_until(__clock_t::now() + __rt); - } - -#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK - - // Exclusive ownership - - template - bool - try_lock_until(const chrono::time_point& __atime) - { - auto __s = chrono::time_point_cast(__atime); - auto __ns = chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = - { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - int __ret = __glibcxx_rwlock_timedwrlock(&_M_rwlock, &__ts); - // On self-deadlock, we just fail to acquire the lock. Technically, - // the program violated the precondition. - if (__ret == ETIMEDOUT || __ret == EDEADLK) - return false; - // Errors not handled: EINVAL - __glibcxx_assert(__ret == 0); - return true; - } - -#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK - template - bool - try_lock_until(const chrono::time_point& __atime) - { - auto __s = chrono::time_point_cast(__atime); - auto __ns = chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = - { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - int __ret = pthread_rwlock_clockwrlock(&_M_rwlock, CLOCK_MONOTONIC, - &__ts); - // On self-deadlock, we just fail to acquire the lock. Technically, - // the program violated the precondition. - if (__ret == ETIMEDOUT || __ret == EDEADLK) - return false; - // Errors not handled: EINVAL - __glibcxx_assert(__ret == 0); - return true; - } -#endif - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) - { -#if __cplusplus > 201703L - static_assert(chrono::is_clock_v<_Clock>); -#endif - // The user-supplied clock may not tick at the same rate as - // steady_clock, so we must loop in order to guarantee that - // the timeout has expired before returning false. - typename _Clock::time_point __now = _Clock::now(); - do { - auto __rtime = __atime - __now; - if (try_lock_for(__rtime)) - return true; - __now = _Clock::now(); - } while (__atime > __now); - return false; - } - - // Shared ownership - - template - bool - try_lock_shared_until(const chrono::time_point& __atime) - { - auto __s = chrono::time_point_cast(__atime); - auto __ns = chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = - { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - int __ret; - // Unlike for lock(), we are not allowed to throw an exception so if - // the maximum number of read locks has been exceeded, or we would - // deadlock, we just try to acquire the lock again (and will time out - // eventually). - // In cases where we would exceed the maximum number of read locks - // throughout the whole time until the timeout, we will fail to - // acquire the lock even if it would be logically free; however, this - // is allowed by the standard, and we made a "strong effort" - // (see C++14 30.4.1.4p26). - // For cases where the implementation detects a deadlock we - // intentionally block and timeout so that an early return isn't - // mistaken for a spurious failure, which might help users realise - // there is a deadlock. - do - __ret = __glibcxx_rwlock_timedrdlock(&_M_rwlock, &__ts); - while (__ret == EAGAIN || __ret == EDEADLK); - if (__ret == ETIMEDOUT) - return false; - // Errors not handled: EINVAL - __glibcxx_assert(__ret == 0); - return true; - } - -#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK - template - bool - try_lock_shared_until(const chrono::time_point& __atime) - { - auto __s = chrono::time_point_cast(__atime); - auto __ns = chrono::duration_cast(__atime - __s); - - __gthread_time_t __ts = - { - static_cast(__s.time_since_epoch().count()), - static_cast(__ns.count()) - }; - - int __ret = pthread_rwlock_clockrdlock(&_M_rwlock, CLOCK_MONOTONIC, - &__ts); - // On self-deadlock, we just fail to acquire the lock. Technically, - // the program violated the precondition. - if (__ret == ETIMEDOUT || __ret == EDEADLK) - return false; - // Errors not handled: EINVAL - __glibcxx_assert(__ret == 0); - return true; - } -#endif - - template - bool - try_lock_shared_until(const chrono::time_point<_Clock, - _Duration>& __atime) - { -#if __cplusplus > 201703L - static_assert(chrono::is_clock_v<_Clock>); -#endif - // The user-supplied clock may not tick at the same rate as - // steady_clock, so we must loop in order to guarantee that - // the timeout has expired before returning false. - typename _Clock::time_point __now = _Clock::now(); - do { - auto __rtime = __atime - __now; - if (try_lock_shared_for(__rtime)) - return true; - __now = _Clock::now(); - } while (__atime > __now); - return false; - } - -#else // ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) - - // Exclusive ownership - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) - { - unique_lock __lk(_M_mut); - if (!_M_gate1.wait_until(__lk, __abs_time, - [=]{ return !_M_write_entered(); })) - { - return false; - } - _M_state |= _S_write_entered; - if (!_M_gate2.wait_until(__lk, __abs_time, - [=]{ return _M_readers() == 0; })) - { - _M_state ^= _S_write_entered; - // Wake all threads blocked while the write-entered flag was set. - _M_gate1.notify_all(); - return false; - } - return true; - } - - // Shared ownership - - template - bool - try_lock_shared_until(const chrono::time_point<_Clock, - _Duration>& __abs_time) - { - unique_lock __lk(_M_mut); - if (!_M_gate1.wait_until(__lk, __abs_time, - [=]{ return _M_state < _S_max_readers; })) - { - return false; - } - ++_M_state; - return true; - } - -#endif // _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK - }; -#endif // _GLIBCXX_HAS_GTHREADS - - /// shared_lock - template - class shared_lock - { - public: - typedef _Mutex mutex_type; - - // Shared locking - - shared_lock() noexcept : _M_pm(nullptr), _M_owns(false) { } - - explicit - shared_lock(mutex_type& __m) - : _M_pm(std::__addressof(__m)), _M_owns(true) - { __m.lock_shared(); } - - shared_lock(mutex_type& __m, defer_lock_t) noexcept - : _M_pm(std::__addressof(__m)), _M_owns(false) { } - - shared_lock(mutex_type& __m, try_to_lock_t) - : _M_pm(std::__addressof(__m)), _M_owns(__m.try_lock_shared()) { } - - shared_lock(mutex_type& __m, adopt_lock_t) - : _M_pm(std::__addressof(__m)), _M_owns(true) { } - - template - shared_lock(mutex_type& __m, - const chrono::time_point<_Clock, _Duration>& __abs_time) - : _M_pm(std::__addressof(__m)), - _M_owns(__m.try_lock_shared_until(__abs_time)) { } - - template - shared_lock(mutex_type& __m, - const chrono::duration<_Rep, _Period>& __rel_time) - : _M_pm(std::__addressof(__m)), - _M_owns(__m.try_lock_shared_for(__rel_time)) { } - - ~shared_lock() - { - if (_M_owns) - _M_pm->unlock_shared(); - } - - shared_lock(shared_lock const&) = delete; - shared_lock& operator=(shared_lock const&) = delete; - - shared_lock(shared_lock&& __sl) noexcept : shared_lock() - { swap(__sl); } - - shared_lock& - operator=(shared_lock&& __sl) noexcept - { - shared_lock(std::move(__sl)).swap(*this); - return *this; - } - - void - lock() - { - _M_lockable(); - _M_pm->lock_shared(); - _M_owns = true; - } - - bool - try_lock() - { - _M_lockable(); - return _M_owns = _M_pm->try_lock_shared(); - } - - template - bool - try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) - { - _M_lockable(); - return _M_owns = _M_pm->try_lock_shared_for(__rel_time); - } - - template - bool - try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) - { - _M_lockable(); - return _M_owns = _M_pm->try_lock_shared_until(__abs_time); - } - - void - unlock() - { - if (!_M_owns) - __throw_system_error(int(errc::resource_deadlock_would_occur)); - _M_pm->unlock_shared(); - _M_owns = false; - } - - // Setters - - void - swap(shared_lock& __u) noexcept - { - std::swap(_M_pm, __u._M_pm); - std::swap(_M_owns, __u._M_owns); - } - - mutex_type* - release() noexcept - { - _M_owns = false; - return std::exchange(_M_pm, nullptr); - } - - // Getters - - bool owns_lock() const noexcept { return _M_owns; } - - explicit operator bool() const noexcept { return _M_owns; } - - mutex_type* mutex() const noexcept { return _M_pm; } - - private: - void - _M_lockable() const - { - if (_M_pm == nullptr) - __throw_system_error(int(errc::operation_not_permitted)); - if (_M_owns) - __throw_system_error(int(errc::resource_deadlock_would_occur)); - - } - - mutex_type* _M_pm; - bool _M_owns; - }; - - /// Swap specialization for shared_lock - /// @relates shared_mutex - template - void - swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) noexcept - { __x.swap(__y); } - - // @} group mutexes -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif // C++14 - -#endif // _GLIBCXX_SHARED_MUTEX diff --git a/resources/sources/avr-libstdcpp/include/span b/resources/sources/avr-libstdcpp/include/span deleted file mode 100644 index 1cdc0589d..000000000 --- a/resources/sources/avr-libstdcpp/include/span +++ /dev/null @@ -1,462 +0,0 @@ -// Components for manipulating non-owning sequences of objects -*- C++ -*- - -// Copyright (C) 2019-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file span - * This is a Standard C++ Library header. - */ - -// -// P0122 span library -// Contributed by ThePhD -// - -#ifndef _GLIBCXX_SPAN -#define _GLIBCXX_SPAN 1 - -#pragma GCC system_header - -#if __cplusplus > 201703L - -#include -#include -#include -#include - -#if __cpp_lib_concepts -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#define __cpp_lib_span 202002L - - inline constexpr size_t dynamic_extent = static_cast(-1); - - template - class span; - - namespace __detail - { - template - struct __is_std_span : false_type { }; - - template - struct __is_std_span> : true_type { }; - - template - struct __is_std_array : false_type { }; - - template - struct __is_std_array<_GLIBCXX_STD_C::array<_Tp, _Num>> : true_type { }; - -#ifdef _GLIBCXX_DEBUG - template - struct __is_std_array<__debug::array<_Tp, _Num>> : true_type { }; -#endif - - template - class __extent_storage - { - public: - constexpr - __extent_storage(size_t) noexcept - { } - - static constexpr size_t - _M_extent() noexcept - { return _Extent; } - }; - - template<> - class __extent_storage - { - public: - constexpr - __extent_storage(size_t __extent) noexcept - : _M_extent_value(__extent) - { } - - constexpr size_t - _M_extent() const noexcept - { return this->_M_extent_value; } - - private: - size_t _M_extent_value; - }; - } // namespace __detail - - template - class span - { - template - static constexpr size_t - _S_subspan_extent() - { - if constexpr (_Count != dynamic_extent) - return _Count; - else if constexpr (extent != dynamic_extent) - return _Extent - _Offset; - else - return dynamic_extent; - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 3255. span's array constructor is too strict - template - requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) - using __is_compatible_array = __is_array_convertible<_Type, _Tp>; - - template - using __is_compatible_ref - = __is_array_convertible<_Type, remove_reference_t<_Ref>>; - - public: - // member types - using element_type = _Type; - using value_type = remove_cv_t<_Type>; - using size_type = size_t; - using difference_type = ptrdiff_t; - using pointer = _Type*; - using const_pointer = const _Type*; - using reference = element_type&; - using const_reference = const element_type&; - using iterator = __gnu_cxx::__normal_iterator; - using reverse_iterator = std::reverse_iterator; - - // member constants - static constexpr size_t extent = _Extent; - - // constructors, copy and assignment - - constexpr - span() noexcept - requires ((_Extent + 1u) <= 1u) - : _M_extent(0), _M_ptr(nullptr) - { } - - template - requires __is_compatible_ref>::value - constexpr explicit(extent != dynamic_extent) - span(_It __first, size_type __count) - noexcept - : _M_extent(__count), _M_ptr(std::to_address(__first)) - { - if constexpr (_Extent != dynamic_extent) - { - __glibcxx_assert(__count == _Extent); - } - } - - template _End> - requires __is_compatible_ref>::value - && (!is_convertible_v<_End, size_type>) - constexpr explicit(extent != dynamic_extent) - span(_It __first, _End __last) - noexcept(noexcept(__last - __first)) - : _M_extent(static_cast(__last - __first)), - _M_ptr(std::to_address(__first)) - { - if constexpr (_Extent != dynamic_extent) - { - __glibcxx_assert((__last - __first) == _Extent); - } - } - - template - requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) - constexpr - span(type_identity_t (&__arr)[_ArrayExtent]) noexcept - : span(static_cast(__arr), _ArrayExtent) - { } - - template - requires __is_compatible_array<_Tp, _ArrayExtent>::value - constexpr - span(array<_Tp, _ArrayExtent>& __arr) noexcept - : span(static_cast(__arr.data()), _ArrayExtent) - { } - - template - requires __is_compatible_array::value - constexpr - span(const array<_Tp, _ArrayExtent>& __arr) noexcept - : span(static_cast(__arr.data()), _ArrayExtent) - { } - - template - requires ranges::contiguous_range<_Range> && ranges::sized_range<_Range> - && (ranges::borrowed_range<_Range> || is_const_v) - && (!__detail::__is_std_span>::value) - && (!__detail::__is_std_array>::value) - && (!is_array_v>) - && __is_compatible_ref>::value - constexpr explicit(extent != dynamic_extent) - span(_Range&& __range) - noexcept(noexcept(ranges::data(__range)) - && noexcept(ranges::size(__range))) - : span(ranges::data(__range), ranges::size(__range)) - { - if constexpr (extent != dynamic_extent) - { - __glibcxx_assert(ranges::size(__range) == extent); - } - } - - constexpr - span(const span&) noexcept = default; - - template - requires (_Extent == dynamic_extent || _OExtent == dynamic_extent - || _Extent == _OExtent) - && (__is_array_convertible<_Type, _OType>::value) - constexpr - explicit(extent != dynamic_extent && _OExtent == dynamic_extent) - span(const span<_OType, _OExtent>& __s) noexcept - : _M_extent(__s.size()), _M_ptr(__s.data()) - { - if constexpr (extent != dynamic_extent) - { - __glibcxx_assert(__s.size() == extent); - } - } - - ~span() noexcept = default; - - constexpr span& - operator=(const span&) noexcept = default; - - // observers - - constexpr size_type - size() const noexcept - { return this->_M_extent._M_extent(); } - - constexpr size_type - size_bytes() const noexcept - { return this->_M_extent._M_extent() * sizeof(element_type); } - - [[nodiscard]] constexpr bool - empty() const noexcept - { return size() == 0; } - - // element access - - constexpr reference - front() const noexcept - { - __glibcxx_assert(!empty()); - return *this->_M_ptr; - } - - constexpr reference - back() const noexcept - { - __glibcxx_assert(!empty()); - return *(this->_M_ptr + (size() - 1)); - } - - constexpr reference - operator[](size_type __idx) const noexcept - { - __glibcxx_assert(__idx < size()); - return *(this->_M_ptr + __idx); - } - - constexpr pointer - data() const noexcept - { return this->_M_ptr; } - - // iterator support - - constexpr iterator - begin() const noexcept - { return iterator(this->_M_ptr); } - - constexpr iterator - end() const noexcept - { return iterator(this->_M_ptr + this->size()); } - - constexpr reverse_iterator - rbegin() const noexcept - { return reverse_iterator(this->end()); } - - constexpr reverse_iterator - rend() const noexcept - { return reverse_iterator(this->begin()); } - - // subviews - - template - constexpr span - first() const noexcept - { - if constexpr (_Extent == dynamic_extent) - __glibcxx_assert(_Count <= size()); - else - static_assert(_Count <= extent); - using _Sp = span; - return _Sp{ this->data(), _Count }; - } - - constexpr span - first(size_type __count) const noexcept - { - __glibcxx_assert(__count <= size()); - return { this->data(), __count }; - } - - template - constexpr span - last() const noexcept - { - if constexpr (_Extent == dynamic_extent) - __glibcxx_assert(_Count <= size()); - else - static_assert(_Count <= extent); - using _Sp = span; - return _Sp{ this->data() + (this->size() - _Count), _Count }; - } - - constexpr span - last(size_type __count) const noexcept - { - __glibcxx_assert(__count <= size()); - return { this->data() + (this->size() - __count), __count }; - } - - template - constexpr auto - subspan() const noexcept - -> span()> - { - if constexpr (_Extent == dynamic_extent) - { - __glibcxx_assert(_Offset <= size()); - } - else - static_assert(_Offset <= extent); - - using _Sp = span()>; - - if constexpr (_Count == dynamic_extent) - return _Sp{ this->data() + _Offset, this->size() - _Offset }; - else - { - if constexpr (_Extent == dynamic_extent) - { - __glibcxx_assert(_Count <= size()); - __glibcxx_assert(_Count <= (size() - _Offset)); - } - else - { - static_assert(_Count <= extent); - static_assert(_Count <= (extent - _Offset)); - } - return _Sp{ this->data() + _Offset, _Count }; - } - } - - constexpr span - subspan(size_type __offset, size_type __count = dynamic_extent) const - noexcept - { - __glibcxx_assert(__offset <= size()); - if (__count == dynamic_extent) - __count = this->size() - __offset; - else - { - __glibcxx_assert(__count <= size()); - __glibcxx_assert(__offset + __count <= size()); - } - return {this->data() + __offset, __count}; - } - - private: - [[no_unique_address]] __detail::__extent_storage _M_extent; - pointer _M_ptr; - }; - - // deduction guides - - template - span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; - - template - span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>; - - template - span(const array<_Type, _ArrayExtent>&) - -> span; - - template - span(_Iter, _End) - -> span>>; - - template - span(_Range &&) - -> span>>; - - template - inline - span - as_bytes(span<_Type, _Extent> __sp) noexcept - { - auto data = reinterpret_cast(__sp.data()); - auto size = __sp.size_bytes(); - constexpr auto extent = _Extent == dynamic_extent - ? dynamic_extent : _Extent * sizeof(_Type); - return span{data, size}; - } - - template - inline - span - as_writable_bytes(span<_Type, _Extent> __sp) noexcept - { - auto data = reinterpret_cast(__sp.data()); - auto size = __sp.size_bytes(); - constexpr auto extent = _Extent == dynamic_extent - ? dynamic_extent : _Extent * sizeof(_Type); - return span{data, size}; - } - - namespace ranges - { - // Opt-in to borrowed_range concept - template - inline constexpr bool - enable_borrowed_range> = true; - - // Opt-in to view concept - template - inline constexpr bool - enable_view> - = _Extent == 0 || _Extent == dynamic_extent; - } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // concepts -#endif // C++20 -#endif // _GLIBCXX_SPAN diff --git a/resources/sources/avr-libstdcpp/include/stack b/resources/sources/avr-libstdcpp/include/stack deleted file mode 100644 index 064b3583a..000000000 --- a/resources/sources/avr-libstdcpp/include/stack +++ /dev/null @@ -1,63 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/stack - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_STACK -#define _GLIBCXX_STACK 1 - -#pragma GCC system_header - -#include -#include - -#endif /* _GLIBCXX_STACK */ diff --git a/resources/sources/avr-libstdcpp/include/stdexcept b/resources/sources/avr-libstdcpp/include/stdexcept new file mode 100644 index 000000000..efeeb30a6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/stdexcept @@ -0,0 +1,4 @@ +// Stub: exceptions not available on AVR +#ifndef _AVR_STDEXCEPT_STUB +#define _AVR_STDEXCEPT_STUB +#endif diff --git a/resources/sources/avr-libstdcpp/include/string b/resources/sources/avr-libstdcpp/include/string new file mode 100644 index 000000000..cb862b18d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/string @@ -0,0 +1,4 @@ +// Stub: std::string not available on AVR (requires heap + exceptions) +#ifndef _AVR_STRING_STUB +#define _AVR_STRING_STUB +#endif diff --git a/resources/sources/avr-libstdcpp/include/string_view b/resources/sources/avr-libstdcpp/include/string_view deleted file mode 100644 index 487088c7e..000000000 --- a/resources/sources/avr-libstdcpp/include/string_view +++ /dev/null @@ -1,758 +0,0 @@ -// Components for manipulating non-owning sequences of characters -*- C++ -*- - -// Copyright (C) 2013-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file string_view - * This is a Standard C++ Library header. - */ - -// -// N3762 basic_string_view library -// - -#ifndef _GLIBCXX_STRING_VIEW -#define _GLIBCXX_STRING_VIEW 1 - -#pragma GCC system_header - -#if __cplusplus >= 201703L - -#include -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -# define __cpp_lib_string_view 201803L -#if __cplusplus > 201703L -# define __cpp_lib_constexpr_string_view 201811L -#endif - - // Helper for basic_string and basic_string_view members. - constexpr size_t - __sv_check(size_t __size, size_t __pos, const char* __s) - { - if (__pos > __size) - __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size " - "(which is %zu)"), __s, __pos, __size); - return __pos; - } - - // Helper for basic_string members. - // NB: __sv_limit doesn't check for a bad __pos value. - constexpr size_t - __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept - { - const bool __testoff = __off < __size - __pos; - return __testoff ? __off : __size - __pos; - } - - /** - * @class basic_string_view - * @brief A non-owning reference to a string. - * - * @ingroup strings - * @ingroup sequences - * - * @tparam _CharT Type of character - * @tparam _Traits Traits for character type, defaults to - * char_traits<_CharT>. - * - * A basic_string_view looks like this: - * - * @code - * _CharT* _M_str - * size_t _M_len - * @endcode - */ - template> - class basic_string_view - { - static_assert(!is_array_v<_CharT>); - static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>); - static_assert(is_same_v<_CharT, typename _Traits::char_type>); - - public: - - // types - using traits_type = _Traits; - using value_type = _CharT; - using pointer = value_type*; - using const_pointer = const value_type*; - using reference = value_type&; - using const_reference = const value_type&; - using const_iterator = const value_type*; - using iterator = const_iterator; - using const_reverse_iterator = std::reverse_iterator; - using reverse_iterator = const_reverse_iterator; - using size_type = size_t; - using difference_type = ptrdiff_t; - static constexpr size_type npos = size_type(-1); - - // [string.view.cons], construction and assignment - - constexpr - basic_string_view() noexcept - : _M_len{0}, _M_str{nullptr} - { } - - constexpr basic_string_view(const basic_string_view&) noexcept = default; - - __attribute__((__nonnull__)) constexpr - basic_string_view(const _CharT* __str) noexcept - : _M_len{traits_type::length(__str)}, - _M_str{__str} - { } - - constexpr - basic_string_view(const _CharT* __str, size_type __len) noexcept - : _M_len{__len}, _M_str{__str} - { } - -#if __cplusplus > 201703L && __cpp_lib_concepts - template _End> - requires same_as, _CharT> - && (!convertible_to<_End, size_type>) - constexpr - basic_string_view(_It __first, _End __last) - : _M_len(__last - __first), _M_str(std::to_address(__first)) - { } -#endif - - constexpr basic_string_view& - operator=(const basic_string_view&) noexcept = default; - - // [string.view.iterators], iterator support - - constexpr const_iterator - begin() const noexcept - { return this->_M_str; } - - constexpr const_iterator - end() const noexcept - { return this->_M_str + this->_M_len; } - - constexpr const_iterator - cbegin() const noexcept - { return this->_M_str; } - - constexpr const_iterator - cend() const noexcept - { return this->_M_str + this->_M_len; } - - constexpr const_reverse_iterator - rbegin() const noexcept - { return const_reverse_iterator(this->end()); } - - constexpr const_reverse_iterator - rend() const noexcept - { return const_reverse_iterator(this->begin()); } - - constexpr const_reverse_iterator - crbegin() const noexcept - { return const_reverse_iterator(this->end()); } - - constexpr const_reverse_iterator - crend() const noexcept - { return const_reverse_iterator(this->begin()); } - - // [string.view.capacity], capacity - - constexpr size_type - size() const noexcept - { return this->_M_len; } - - constexpr size_type - length() const noexcept - { return _M_len; } - - constexpr size_type - max_size() const noexcept - { - return (npos - sizeof(size_type) - sizeof(void*)) - / sizeof(value_type) / 4; - } - - [[nodiscard]] constexpr bool - empty() const noexcept - { return this->_M_len == 0; } - - // [string.view.access], element access - - constexpr const_reference - operator[](size_type __pos) const noexcept - { - __glibcxx_assert(__pos < this->_M_len); - return *(this->_M_str + __pos); - } - - constexpr const_reference - at(size_type __pos) const - { - if (__pos >= _M_len) - __throw_out_of_range_fmt(__N("basic_string_view::at: __pos " - "(which is %zu) >= this->size() " - "(which is %zu)"), __pos, this->size()); - return *(this->_M_str + __pos); - } - - constexpr const_reference - front() const noexcept - { - __glibcxx_assert(this->_M_len > 0); - return *this->_M_str; - } - - constexpr const_reference - back() const noexcept - { - __glibcxx_assert(this->_M_len > 0); - return *(this->_M_str + this->_M_len - 1); - } - - constexpr const_pointer - data() const noexcept - { return this->_M_str; } - - // [string.view.modifiers], modifiers: - - constexpr void - remove_prefix(size_type __n) noexcept - { - __glibcxx_assert(this->_M_len >= __n); - this->_M_str += __n; - this->_M_len -= __n; - } - - constexpr void - remove_suffix(size_type __n) noexcept - { this->_M_len -= __n; } - - constexpr void - swap(basic_string_view& __sv) noexcept - { - auto __tmp = *this; - *this = __sv; - __sv = __tmp; - } - - // [string.view.ops], string operations: - - _GLIBCXX20_CONSTEXPR - size_type - copy(_CharT* __str, size_type __n, size_type __pos = 0) const - { - __glibcxx_requires_string_len(__str, __n); - __pos = std::__sv_check(size(), __pos, "basic_string_view::copy"); - const size_type __rlen = std::min(__n, _M_len - __pos); - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2777. basic_string_view::copy should use char_traits::copy - traits_type::copy(__str, data() + __pos, __rlen); - return __rlen; - } - - constexpr basic_string_view - substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) - { - __pos = std::__sv_check(size(), __pos, "basic_string_view::substr"); - const size_type __rlen = std::min(__n, _M_len - __pos); - return basic_string_view{_M_str + __pos, __rlen}; - } - - constexpr int - compare(basic_string_view __str) const noexcept - { - const size_type __rlen = std::min(this->_M_len, __str._M_len); - int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen); - if (__ret == 0) - __ret = _S_compare(this->_M_len, __str._M_len); - return __ret; - } - - constexpr int - compare(size_type __pos1, size_type __n1, basic_string_view __str) const - { return this->substr(__pos1, __n1).compare(__str); } - - constexpr int - compare(size_type __pos1, size_type __n1, - basic_string_view __str, size_type __pos2, size_type __n2) const - { - return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); - } - - __attribute__((__nonnull__)) constexpr int - compare(const _CharT* __str) const noexcept - { return this->compare(basic_string_view{__str}); } - - __attribute__((__nonnull__)) constexpr int - compare(size_type __pos1, size_type __n1, const _CharT* __str) const - { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } - - constexpr int - compare(size_type __pos1, size_type __n1, - const _CharT* __str, size_type __n2) const noexcept(false) - { - return this->substr(__pos1, __n1) - .compare(basic_string_view(__str, __n2)); - } - -#if __cplusplus > 201703L -#define __cpp_lib_starts_ends_with 201711L - constexpr bool - starts_with(basic_string_view __x) const noexcept - { return this->substr(0, __x.size()) == __x; } - - constexpr bool - starts_with(_CharT __x) const noexcept - { return !this->empty() && traits_type::eq(this->front(), __x); } - - constexpr bool - starts_with(const _CharT* __x) const noexcept - { return this->starts_with(basic_string_view(__x)); } - - constexpr bool - ends_with(basic_string_view __x) const noexcept - { - return this->size() >= __x.size() - && this->compare(this->size() - __x.size(), npos, __x) == 0; - } - - constexpr bool - ends_with(_CharT __x) const noexcept - { return !this->empty() && traits_type::eq(this->back(), __x); } - - constexpr bool - ends_with(const _CharT* __x) const noexcept - { return this->ends_with(basic_string_view(__x)); } -#endif // C++20 - - // [string.view.find], searching - - constexpr size_type - find(basic_string_view __str, size_type __pos = 0) const noexcept - { return this->find(__str._M_str, __pos, __str._M_len); } - - constexpr size_type - find(_CharT __c, size_type __pos = 0) const noexcept; - - constexpr size_type - find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - - __attribute__((__nonnull__)) constexpr size_type - find(const _CharT* __str, size_type __pos = 0) const noexcept - { return this->find(__str, __pos, traits_type::length(__str)); } - - constexpr size_type - rfind(basic_string_view __str, size_type __pos = npos) const noexcept - { return this->rfind(__str._M_str, __pos, __str._M_len); } - - constexpr size_type - rfind(_CharT __c, size_type __pos = npos) const noexcept; - - constexpr size_type - rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; - - __attribute__((__nonnull__)) constexpr size_type - rfind(const _CharT* __str, size_type __pos = npos) const noexcept - { return this->rfind(__str, __pos, traits_type::length(__str)); } - - constexpr size_type - find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept - { return this->find_first_of(__str._M_str, __pos, __str._M_len); } - - constexpr size_type - find_first_of(_CharT __c, size_type __pos = 0) const noexcept - { return this->find(__c, __pos); } - - constexpr size_type - find_first_of(const _CharT* __str, size_type __pos, - size_type __n) const noexcept; - - __attribute__((__nonnull__)) constexpr size_type - find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept - { return this->find_first_of(__str, __pos, traits_type::length(__str)); } - - constexpr size_type - find_last_of(basic_string_view __str, - size_type __pos = npos) const noexcept - { return this->find_last_of(__str._M_str, __pos, __str._M_len); } - - constexpr size_type - find_last_of(_CharT __c, size_type __pos=npos) const noexcept - { return this->rfind(__c, __pos); } - - constexpr size_type - find_last_of(const _CharT* __str, size_type __pos, - size_type __n) const noexcept; - - __attribute__((__nonnull__)) constexpr size_type - find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept - { return this->find_last_of(__str, __pos, traits_type::length(__str)); } - - constexpr size_type - find_first_not_of(basic_string_view __str, - size_type __pos = 0) const noexcept - { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } - - constexpr size_type - find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; - - constexpr size_type - find_first_not_of(const _CharT* __str, - size_type __pos, size_type __n) const noexcept; - - __attribute__((__nonnull__)) constexpr size_type - find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept - { - return this->find_first_not_of(__str, __pos, - traits_type::length(__str)); - } - - constexpr size_type - find_last_not_of(basic_string_view __str, - size_type __pos = npos) const noexcept - { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } - - constexpr size_type - find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; - - constexpr size_type - find_last_not_of(const _CharT* __str, - size_type __pos, size_type __n) const noexcept; - - __attribute__((__nonnull__)) constexpr size_type - find_last_not_of(const _CharT* __str, - size_type __pos = npos) const noexcept - { - return this->find_last_not_of(__str, __pos, - traits_type::length(__str)); - } - - private: - - static constexpr int - _S_compare(size_type __n1, size_type __n2) noexcept - { - const difference_type __diff = __n1 - __n2; - if (__diff > __gnu_cxx::__int_traits::__max) - return __gnu_cxx::__int_traits::__max; - if (__diff < __gnu_cxx::__int_traits::__min) - return __gnu_cxx::__int_traits::__min; - return static_cast(__diff); - } - - size_t _M_len; - const _CharT* _M_str; - }; - -#if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides - template _End> - basic_string_view(_It, _End) -> basic_string_view>; -#endif - - // [string.view.comparison], non-member basic_string_view comparison function - - // Several of these functions use type_identity_t to create a non-deduced - // context, so that only one argument participates in template argument - // deduction and the other argument gets implicitly converted to the deduced - // type (see N3766). - - template - constexpr bool - operator==(basic_string_view<_CharT, _Traits> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.size() == __y.size() && __x.compare(__y) == 0; } - - template - constexpr bool - operator==(basic_string_view<_CharT, _Traits> __x, - __type_identity_t> __y) - noexcept - { return __x.size() == __y.size() && __x.compare(__y) == 0; } - -#if __cpp_lib_three_way_comparison - template - constexpr auto - operator<=>(basic_string_view<_CharT, _Traits> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) - { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } - - template - constexpr auto - operator<=>(basic_string_view<_CharT, _Traits> __x, - __type_identity_t> __y) - noexcept - -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) - { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } -#else - template - constexpr bool - operator==(__type_identity_t> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.size() == __y.size() && __x.compare(__y) == 0; } - - template - constexpr bool - operator!=(basic_string_view<_CharT, _Traits> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return !(__x == __y); } - - template - constexpr bool - operator!=(basic_string_view<_CharT, _Traits> __x, - __type_identity_t> __y) - noexcept - { return !(__x == __y); } - - template - constexpr bool - operator!=(__type_identity_t> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return !(__x == __y); } - - template - constexpr bool - operator< (basic_string_view<_CharT, _Traits> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.compare(__y) < 0; } - - template - constexpr bool - operator< (basic_string_view<_CharT, _Traits> __x, - __type_identity_t> __y) - noexcept - { return __x.compare(__y) < 0; } - - template - constexpr bool - operator< (__type_identity_t> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.compare(__y) < 0; } - - template - constexpr bool - operator> (basic_string_view<_CharT, _Traits> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.compare(__y) > 0; } - - template - constexpr bool - operator> (basic_string_view<_CharT, _Traits> __x, - __type_identity_t> __y) - noexcept - { return __x.compare(__y) > 0; } - - template - constexpr bool - operator> (__type_identity_t> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.compare(__y) > 0; } - - template - constexpr bool - operator<=(basic_string_view<_CharT, _Traits> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.compare(__y) <= 0; } - - template - constexpr bool - operator<=(basic_string_view<_CharT, _Traits> __x, - __type_identity_t> __y) - noexcept - { return __x.compare(__y) <= 0; } - - template - constexpr bool - operator<=(__type_identity_t> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.compare(__y) <= 0; } - - template - constexpr bool - operator>=(basic_string_view<_CharT, _Traits> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.compare(__y) >= 0; } - - template - constexpr bool - operator>=(basic_string_view<_CharT, _Traits> __x, - __type_identity_t> __y) - noexcept - { return __x.compare(__y) >= 0; } - - template - constexpr bool - operator>=(__type_identity_t> __x, - basic_string_view<_CharT, _Traits> __y) noexcept - { return __x.compare(__y) >= 0; } -#endif // three-way comparison - - // basic_string_view typedef names - - using string_view = basic_string_view; -#ifdef _GLIBCXX_USE_WCHAR_T - using wstring_view = basic_string_view; -#endif -#ifdef _GLIBCXX_USE_CHAR8_T - using u8string_view = basic_string_view; -#endif - using u16string_view = basic_string_view; - using u32string_view = basic_string_view; - - // [string.view.hash], hash support: - - template - struct hash; - - template<> - struct hash - : public __hash_base - { - size_t - operator()(const string_view& __str) const noexcept - { return std::_Hash_impl::hash(__str.data(), __str.length()); } - }; - - template<> - struct __is_fast_hash> : std::false_type - { }; - -#ifdef _GLIBCXX_USE_WCHAR_T - template<> - struct hash - : public __hash_base - { - size_t - operator()(const wstring_view& __s) const noexcept - { return std::_Hash_impl::hash(__s.data(), - __s.length() * sizeof(wchar_t)); } - }; - - template<> - struct __is_fast_hash> : std::false_type - { }; -#endif - -#ifdef _GLIBCXX_USE_CHAR8_T - template<> - struct hash - : public __hash_base - { - size_t - operator()(const u8string_view& __str) const noexcept - { return std::_Hash_impl::hash(__str.data(), __str.length()); } - }; - - template<> - struct __is_fast_hash> : std::false_type - { }; -#endif - - template<> - struct hash - : public __hash_base - { - size_t - operator()(const u16string_view& __s) const noexcept - { return std::_Hash_impl::hash(__s.data(), - __s.length() * sizeof(char16_t)); } - }; - - template<> - struct __is_fast_hash> : std::false_type - { }; - - template<> - struct hash - : public __hash_base - { - size_t - operator()(const u32string_view& __s) const noexcept - { return std::_Hash_impl::hash(__s.data(), - __s.length() * sizeof(char32_t)); } - }; - - template<> - struct __is_fast_hash> : std::false_type - { }; - - inline namespace literals - { - inline namespace string_view_literals - { -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wliteral-suffix" - inline constexpr basic_string_view - operator""sv(const char* __str, size_t __len) noexcept - { return basic_string_view{__str, __len}; } - -#ifdef _GLIBCXX_USE_WCHAR_T - inline constexpr basic_string_view - operator""sv(const wchar_t* __str, size_t __len) noexcept - { return basic_string_view{__str, __len}; } -#endif - -#ifdef _GLIBCXX_USE_CHAR8_T - inline constexpr basic_string_view - operator""sv(const char8_t* __str, size_t __len) noexcept - { return basic_string_view{__str, __len}; } -#endif - - inline constexpr basic_string_view - operator""sv(const char16_t* __str, size_t __len) noexcept - { return basic_string_view{__str, __len}; } - - inline constexpr basic_string_view - operator""sv(const char32_t* __str, size_t __len) noexcept - { return basic_string_view{__str, __len}; } - -#pragma GCC diagnostic pop - } // namespace string_literals - } // namespace literals - -#if __cpp_lib_concepts - namespace ranges - { - // Opt-in to borrowed_range concept - template - inline constexpr bool - enable_borrowed_range> = true; - - // Opt-in to view concept - template - inline constexpr bool - enable_view> = true; - } -#endif -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#include - -#endif // __cplusplus <= 201402L - -#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW diff --git a/resources/sources/avr-libstdcpp/include/tuple b/resources/sources/avr-libstdcpp/include/tuple deleted file mode 100644 index 94b9e0335..000000000 --- a/resources/sources/avr-libstdcpp/include/tuple +++ /dev/null @@ -1,1764 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/tuple - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_TUPLE -#define _GLIBCXX_TUPLE 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include -#include -#if __cplusplus > 201703L -# include -# define __cpp_lib_constexpr_tuple 201811L -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup utilities - * @{ - */ - - template - class tuple; - - template - struct __is_empty_non_tuple : is_empty<_Tp> { }; - - // Using EBO for elements that are tuples causes ambiguous base errors. - template - struct __is_empty_non_tuple> : false_type { }; - - // Use the Empty Base-class Optimization for empty, non-final types. - template - using __empty_not_final - = typename conditional<__is_final(_Tp), false_type, - __is_empty_non_tuple<_Tp>>::type; - - template::value> - struct _Head_base; - - template - struct _Head_base<_Idx, _Head, true> - : public _Head - { - constexpr _Head_base() - : _Head() { } - - constexpr _Head_base(const _Head& __h) - : _Head(__h) { } - - constexpr _Head_base(const _Head_base&) = default; - constexpr _Head_base(_Head_base&&) = default; - - template - constexpr _Head_base(_UHead&& __h) - : _Head(std::forward<_UHead>(__h)) { } - - _Head_base(allocator_arg_t, __uses_alloc0) - : _Head() { } - - template - _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) - : _Head(allocator_arg, *__a._M_a) { } - - template - _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) - : _Head(*__a._M_a) { } - - template - _Head_base(__uses_alloc0, _UHead&& __uhead) - : _Head(std::forward<_UHead>(__uhead)) { } - - template - _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) - : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { } - - template - _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) - : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } - - static constexpr _Head& - _M_head(_Head_base& __b) noexcept { return __b; } - - static constexpr const _Head& - _M_head(const _Head_base& __b) noexcept { return __b; } - }; - - template - struct _Head_base<_Idx, _Head, false> - { - constexpr _Head_base() - : _M_head_impl() { } - - constexpr _Head_base(const _Head& __h) - : _M_head_impl(__h) { } - - constexpr _Head_base(const _Head_base&) = default; - constexpr _Head_base(_Head_base&&) = default; - - template - constexpr _Head_base(_UHead&& __h) - : _M_head_impl(std::forward<_UHead>(__h)) { } - - _GLIBCXX20_CONSTEXPR - _Head_base(allocator_arg_t, __uses_alloc0) - : _M_head_impl() { } - - template - _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) - : _M_head_impl(allocator_arg, *__a._M_a) { } - - template - _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) - : _M_head_impl(*__a._M_a) { } - - template - _GLIBCXX20_CONSTEXPR - _Head_base(__uses_alloc0, _UHead&& __uhead) - : _M_head_impl(std::forward<_UHead>(__uhead)) { } - - template - _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) - : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) - { } - - template - _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) - : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } - - static constexpr _Head& - _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } - - static constexpr const _Head& - _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } - - _Head _M_head_impl; - }; - - /** - * Contains the actual implementation of the @c tuple template, stored - * as a recursive inheritance hierarchy from the first element (most - * derived class) to the last (least derived class). The @c Idx - * parameter gives the 0-based index of the element stored at this - * point in the hierarchy; we use it to implement a constant-time - * get() operation. - */ - template - struct _Tuple_impl; - - /** - * Recursive tuple implementation. Here we store the @c Head element - * and derive from a @c Tuple_impl containing the remaining elements - * (which contains the @c Tail). - */ - template - struct _Tuple_impl<_Idx, _Head, _Tail...> - : public _Tuple_impl<_Idx + 1, _Tail...>, - private _Head_base<_Idx, _Head> - { - template friend class _Tuple_impl; - - typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; - typedef _Head_base<_Idx, _Head> _Base; - - static constexpr _Head& - _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } - - static constexpr const _Head& - _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } - - static constexpr _Inherited& - _M_tail(_Tuple_impl& __t) noexcept { return __t; } - - static constexpr const _Inherited& - _M_tail(const _Tuple_impl& __t) noexcept { return __t; } - - constexpr _Tuple_impl() - : _Inherited(), _Base() { } - - explicit - constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) - : _Inherited(__tail...), _Base(__head) { } - - template::type> - explicit - constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail) - : _Inherited(std::forward<_UTail>(__tail)...), - _Base(std::forward<_UHead>(__head)) { } - - constexpr _Tuple_impl(const _Tuple_impl&) = default; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2729. Missing SFINAE on std::pair::operator= - _Tuple_impl& operator=(const _Tuple_impl&) = delete; - - constexpr - _Tuple_impl(_Tuple_impl&& __in) - noexcept(__and_, - is_nothrow_move_constructible<_Inherited>>::value) - : _Inherited(std::move(_M_tail(__in))), - _Base(std::forward<_Head>(_M_head(__in))) { } - - template - constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) - : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), - _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } - - template - constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) - : _Inherited(std::move - (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), - _Base(std::forward<_UHead> - (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) - : _Inherited(__tag, __a), - _Base(__tag, __use_alloc<_Head>(__a)) { } - - template - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - const _Head& __head, const _Tail&... __tail) - : _Inherited(__tag, __a, __tail...), - _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } - - template::type> - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - _UHead&& __head, _UTail&&... __tail) - : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), - _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), - std::forward<_UHead>(__head)) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - const _Tuple_impl& __in) - : _Inherited(__tag, __a, _M_tail(__in)), - _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - _Tuple_impl&& __in) - : _Inherited(__tag, __a, std::move(_M_tail(__in))), - _Base(__use_alloc<_Head, _Alloc, _Head>(__a), - std::forward<_Head>(_M_head(__in))) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - const _Tuple_impl<_Idx, _UHead, _UTails...>& __in) - : _Inherited(__tag, __a, - _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)), - _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), - _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) - : _Inherited(__tag, __a, std::move - (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), - _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), - std::forward<_UHead> - (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } - - template - _GLIBCXX20_CONSTEXPR - void - _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) - { - _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); - _M_tail(*this)._M_assign( - _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)); - } - - template - _GLIBCXX20_CONSTEXPR - void - _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) - { - _M_head(*this) = std::forward<_UHead> - (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); - _M_tail(*this)._M_assign( - std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); - } - - protected: - _GLIBCXX20_CONSTEXPR - void - _M_swap(_Tuple_impl& __in) - { - using std::swap; - swap(_M_head(*this), _M_head(__in)); - _Inherited::_M_swap(_M_tail(__in)); - } - }; - - // Basis case of inheritance recursion. - template - struct _Tuple_impl<_Idx, _Head> - : private _Head_base<_Idx, _Head> - { - template friend class _Tuple_impl; - - typedef _Head_base<_Idx, _Head> _Base; - - static constexpr _Head& - _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } - - static constexpr const _Head& - _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } - - constexpr _Tuple_impl() - : _Base() { } - - explicit - constexpr _Tuple_impl(const _Head& __head) - : _Base(__head) { } - - template - explicit - constexpr _Tuple_impl(_UHead&& __head) - : _Base(std::forward<_UHead>(__head)) { } - - constexpr _Tuple_impl(const _Tuple_impl&) = default; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2729. Missing SFINAE on std::pair::operator= - _Tuple_impl& operator=(const _Tuple_impl&) = delete; - - constexpr - _Tuple_impl(_Tuple_impl&& __in) - noexcept(is_nothrow_move_constructible<_Head>::value) - : _Base(std::forward<_Head>(_M_head(__in))) { } - - template - constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in) - : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } - - template - constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in) - : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) - { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) - : _Base(__tag, __use_alloc<_Head>(__a)) { } - - template - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - const _Head& __head) - : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - _UHead&& __head) - : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), - std::forward<_UHead>(__head)) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - const _Tuple_impl& __in) - : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - _Tuple_impl&& __in) - : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), - std::forward<_Head>(_M_head(__in))) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - const _Tuple_impl<_Idx, _UHead>& __in) - : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), - _Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } - - template - _GLIBCXX20_CONSTEXPR - _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, - _Tuple_impl<_Idx, _UHead>&& __in) - : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), - std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) - { } - - template - _GLIBCXX20_CONSTEXPR - void - _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) - { - _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); - } - - template - _GLIBCXX20_CONSTEXPR - void - _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) - { - _M_head(*this) - = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); - } - - protected: - _GLIBCXX20_CONSTEXPR - void - _M_swap(_Tuple_impl& __in) - { - using std::swap; - swap(_M_head(*this), _M_head(__in)); - } - }; - - // Concept utility functions, reused in conditionally-explicit - // constructors. - template - struct _TupleConstraints - { - // Constraint for a non-explicit constructor. - // True iff each Ti in _Types... can be constructed from Ui in _UTypes... - // and every Ui is implicitly convertible to Ti. - template - static constexpr bool __is_implicitly_constructible() - { - return __and_..., - is_convertible<_UTypes, _Types>... - >::value; - } - - // Constraint for a non-explicit constructor. - // True iff each Ti in _Types... can be constructed from Ui in _UTypes... - // but not every Ui is implicitly convertible to Ti. - template - static constexpr bool __is_explicitly_constructible() - { - return __and_..., - __not_<__and_...>> - >::value; - } - - static constexpr bool __is_implicitly_default_constructible() - { - return __and_... - >::value; - } - - static constexpr bool __is_explicitly_default_constructible() - { - return __and_..., - __not_<__and_< - std::__is_implicitly_default_constructible<_Types>...> - >>::value; - } - }; - - // Partial specialization used when a required precondition isn't met, - // e.g. when sizeof...(_Types) != sizeof...(_UTypes). - template - struct _TupleConstraints - { - template - static constexpr bool __is_implicitly_constructible() - { return false; } - - template - static constexpr bool __is_explicitly_constructible() - { return false; } - }; - - /// Primary class template, tuple - template - class tuple : public _Tuple_impl<0, _Elements...> - { - typedef _Tuple_impl<0, _Elements...> _Inherited; - - template - using _TCC = _TupleConstraints<_Cond, _Elements...>; - - // Constraint for non-explicit default constructor - template - using _ImplicitDefaultCtor = __enable_if_t< - _TCC<_Dummy>::__is_implicitly_default_constructible(), - bool>; - - // Constraint for explicit default constructor - template - using _ExplicitDefaultCtor = __enable_if_t< - _TCC<_Dummy>::__is_explicitly_default_constructible(), - bool>; - - // Constraint for non-explicit constructors - template - using _ImplicitCtor = __enable_if_t< - _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(), - bool>; - - // Constraint for non-explicit constructors - template - using _ExplicitCtor = __enable_if_t< - _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(), - bool>; - - template - static constexpr - __enable_if_t - __assignable() - { return __and_...>::value; } - - // Condition for noexcept-specifier of an assignment operator. - template - static constexpr bool __nothrow_assignable() - { - return - __and_...>::value; - } - - // Condition for noexcept-specifier of a constructor. - template - static constexpr bool __nothrow_constructible() - { - return - __and_...>::value; - } - - // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1. - template - static constexpr bool __valid_args() - { - return sizeof...(_Elements) == 1 - && !is_same>::value; - } - - // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1. - template - static constexpr bool __valid_args() - { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); } - - /* Constraint for constructors with a tuple parameter ensures - * that the constructor is only viable when it would not interfere with - * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&). - * Such constructors are only viable if: - * either sizeof...(Types) != 1, - * or (when Types... expands to T and UTypes... expands to U) - * is_convertible_v, is_constructible_v, - * and is_same_v are all false. - */ - template> - struct _UseOtherCtor - : false_type - { }; - // If TUPLE is convertible to the single element in *this, - // then TUPLE should match tuple(UTypes&&...) instead. - template - struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>> - : __or_, is_constructible<_Tp, _Tuple>> - { }; - // If TUPLE and *this each have a single element of the same type, - // then TUPLE should match a copy/move constructor instead. - template - struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>> - : true_type - { }; - - // Return true iff sizeof...(Types) == 1 && tuple_size_v == 1 - // and the single element in Types can be initialized from TUPLE, - // or is the same type as tuple_element_t<0, TUPLE>. - template - static constexpr bool __use_other_ctor() - { return _UseOtherCtor<_Tuple>::value; } - - public: - template::value> = true> - constexpr - tuple() - noexcept(__and_...>::value) - : _Inherited() { } - - template::value> = false> - explicit constexpr - tuple() - noexcept(__and_...>::value) - : _Inherited() { } - - template= 1), - _ImplicitCtor<_NotEmpty, const _Elements&...> = true> - constexpr - tuple(const _Elements&... __elements) - noexcept(__nothrow_constructible()) - : _Inherited(__elements...) { } - - template= 1), - _ExplicitCtor<_NotEmpty, const _Elements&...> = false> - explicit constexpr - tuple(const _Elements&... __elements) - noexcept(__nothrow_constructible()) - : _Inherited(__elements...) { } - - template(), - _ImplicitCtor<_Valid, _UElements...> = true> - constexpr - tuple(_UElements&&... __elements) - noexcept(__nothrow_constructible<_UElements...>()) - : _Inherited(std::forward<_UElements>(__elements)...) { } - - template(), - _ExplicitCtor<_Valid, _UElements...> = false> - explicit constexpr - tuple(_UElements&&... __elements) - noexcept(__nothrow_constructible<_UElements...>()) - : _Inherited(std::forward<_UElements>(__elements)...) { } - - constexpr tuple(const tuple&) = default; - - constexpr tuple(tuple&&) = default; - - template&>(), - _ImplicitCtor<_Valid, const _UElements&...> = true> - constexpr - tuple(const tuple<_UElements...>& __in) - noexcept(__nothrow_constructible()) - : _Inherited(static_cast&>(__in)) - { } - - template&>(), - _ExplicitCtor<_Valid, const _UElements&...> = false> - explicit constexpr - tuple(const tuple<_UElements...>& __in) - noexcept(__nothrow_constructible()) - : _Inherited(static_cast&>(__in)) - { } - - template&&>(), - _ImplicitCtor<_Valid, _UElements...> = true> - constexpr - tuple(tuple<_UElements...>&& __in) - noexcept(__nothrow_constructible<_UElements...>()) - : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } - - template&&>(), - _ExplicitCtor<_Valid, _UElements...> = false> - explicit constexpr - tuple(tuple<_UElements...>&& __in) - noexcept(__nothrow_constructible<_UElements...>()) - : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } - - // Allocator-extended constructors. - - template::value> = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a) - : _Inherited(__tag, __a) { } - - template= 1), - _ImplicitCtor<_NotEmpty, const _Elements&...> = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - const _Elements&... __elements) - : _Inherited(__tag, __a, __elements...) { } - - template= 1), - _ExplicitCtor<_NotEmpty, const _Elements&...> = false> - _GLIBCXX20_CONSTEXPR - explicit - tuple(allocator_arg_t __tag, const _Alloc& __a, - const _Elements&... __elements) - : _Inherited(__tag, __a, __elements...) { } - - template(), - _ImplicitCtor<_Valid, _UElements...> = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - _UElements&&... __elements) - : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) - { } - - template(), - _ExplicitCtor<_Valid, _UElements...> = false> - _GLIBCXX20_CONSTEXPR - explicit - tuple(allocator_arg_t __tag, const _Alloc& __a, - _UElements&&... __elements) - : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) - { } - - template - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) - : _Inherited(__tag, __a, static_cast(__in)) { } - - template - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) - : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } - - template&>(), - _ImplicitCtor<_Valid, const _UElements&...> = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - const tuple<_UElements...>& __in) - : _Inherited(__tag, __a, - static_cast&>(__in)) - { } - - template&>(), - _ExplicitCtor<_Valid, const _UElements&...> = false> - _GLIBCXX20_CONSTEXPR - explicit - tuple(allocator_arg_t __tag, const _Alloc& __a, - const tuple<_UElements...>& __in) - : _Inherited(__tag, __a, - static_cast&>(__in)) - { } - - template&&>(), - _ImplicitCtor<_Valid, _UElements...> = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - tuple<_UElements...>&& __in) - : _Inherited(__tag, __a, - static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) - { } - - template&&>(), - _ExplicitCtor<_Valid, _UElements...> = false> - _GLIBCXX20_CONSTEXPR - explicit - tuple(allocator_arg_t __tag, const _Alloc& __a, - tuple<_UElements...>&& __in) - : _Inherited(__tag, __a, - static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) - { } - - // tuple assignment - - _GLIBCXX20_CONSTEXPR - tuple& - operator=(typename conditional<__assignable(), - const tuple&, - const __nonesuch&>::type __in) - noexcept(__nothrow_assignable()) - { - this->_M_assign(__in); - return *this; - } - - _GLIBCXX20_CONSTEXPR - tuple& - operator=(typename conditional<__assignable<_Elements...>(), - tuple&&, - __nonesuch&&>::type __in) - noexcept(__nothrow_assignable<_Elements...>()) - { - this->_M_assign(std::move(__in)); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR - __enable_if_t<__assignable(), tuple&> - operator=(const tuple<_UElements...>& __in) - noexcept(__nothrow_assignable()) - { - this->_M_assign(__in); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR - __enable_if_t<__assignable<_UElements...>(), tuple&> - operator=(tuple<_UElements...>&& __in) - noexcept(__nothrow_assignable<_UElements...>()) - { - this->_M_assign(std::move(__in)); - return *this; - } - - // tuple swap - _GLIBCXX20_CONSTEXPR - void - swap(tuple& __in) - noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value) - { _Inherited::_M_swap(__in); } - }; - -#if __cpp_deduction_guides >= 201606 - template - tuple(_UTypes...) -> tuple<_UTypes...>; - template - tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>; - template - tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>; - template - tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>; - template - tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>; -#endif - - // Explicit specialization, zero-element tuple. - template<> - class tuple<> - { - public: - void swap(tuple&) noexcept { /* no-op */ } - // We need the default since we're going to define no-op - // allocator constructors. - tuple() = default; - // No-op allocator constructors. - template - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t, const _Alloc&) noexcept { } - template - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { } - }; - - /// Partial specialization, 2-element tuple. - /// Includes construction and assignment from a pair. - template - class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> - { - typedef _Tuple_impl<0, _T1, _T2> _Inherited; - - // Constraint for non-explicit default constructor - template - using _ImplicitDefaultCtor = __enable_if_t< - _TupleConstraints<_Dummy, _U1, _U2>:: - __is_implicitly_default_constructible(), - bool>; - - // Constraint for explicit default constructor - template - using _ExplicitDefaultCtor = __enable_if_t< - _TupleConstraints<_Dummy, _U1, _U2>:: - __is_explicitly_default_constructible(), - bool>; - - template - using _TCC = _TupleConstraints<_Dummy, _T1, _T2>; - - // Constraint for non-explicit constructors - template - using _ImplicitCtor = __enable_if_t< - _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(), - bool>; - - // Constraint for non-explicit constructors - template - using _ExplicitCtor = __enable_if_t< - _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(), - bool>; - - template - static constexpr bool __assignable() - { - return __and_, - is_assignable<_T2&, _U2>>::value; - } - - template - static constexpr bool __nothrow_assignable() - { - return __and_, - is_nothrow_assignable<_T2&, _U2>>::value; - } - - template - static constexpr bool __nothrow_constructible() - { - return __and_, - is_nothrow_constructible<_T2, _U2>>::value; - } - - static constexpr bool __nothrow_default_constructible() - { - return __and_, - is_nothrow_default_constructible<_T2>>::value; - } - - template - static constexpr bool __is_alloc_arg() - { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; } - - public: - template = true> - constexpr - tuple() - noexcept(__nothrow_default_constructible()) - : _Inherited() { } - - template = false> - explicit constexpr - tuple() - noexcept(__nothrow_default_constructible()) - : _Inherited() { } - - template = true> - constexpr - tuple(const _T1& __a1, const _T2& __a2) - noexcept(__nothrow_constructible()) - : _Inherited(__a1, __a2) { } - - template = false> - explicit constexpr - tuple(const _T1& __a1, const _T2& __a2) - noexcept(__nothrow_constructible()) - : _Inherited(__a1, __a2) { } - - template(), _U1, _U2> = true> - constexpr - tuple(_U1&& __a1, _U2&& __a2) - noexcept(__nothrow_constructible<_U1, _U2>()) - : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } - - template(), _U1, _U2> = false> - explicit constexpr - tuple(_U1&& __a1, _U2&& __a2) - noexcept(__nothrow_constructible<_U1, _U2>()) - : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } - - constexpr tuple(const tuple&) = default; - - constexpr tuple(tuple&&) = default; - - template = true> - constexpr - tuple(const tuple<_U1, _U2>& __in) - noexcept(__nothrow_constructible()) - : _Inherited(static_cast&>(__in)) { } - - template = false> - explicit constexpr - tuple(const tuple<_U1, _U2>& __in) - noexcept(__nothrow_constructible()) - : _Inherited(static_cast&>(__in)) { } - - template = true> - constexpr - tuple(tuple<_U1, _U2>&& __in) - noexcept(__nothrow_constructible<_U1, _U2>()) - : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } - - template = false> - explicit constexpr - tuple(tuple<_U1, _U2>&& __in) - noexcept(__nothrow_constructible<_U1, _U2>()) - : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } - - template = true> - constexpr - tuple(const pair<_U1, _U2>& __in) - noexcept(__nothrow_constructible()) - : _Inherited(__in.first, __in.second) { } - - template = false> - explicit constexpr - tuple(const pair<_U1, _U2>& __in) - noexcept(__nothrow_constructible()) - : _Inherited(__in.first, __in.second) { } - - template = true> - constexpr - tuple(pair<_U1, _U2>&& __in) - noexcept(__nothrow_constructible<_U1, _U2>()) - : _Inherited(std::forward<_U1>(__in.first), - std::forward<_U2>(__in.second)) { } - - template = false> - explicit constexpr - tuple(pair<_U1, _U2>&& __in) - noexcept(__nothrow_constructible<_U1, _U2>()) - : _Inherited(std::forward<_U1>(__in.first), - std::forward<_U2>(__in.second)) { } - - // Allocator-extended constructors. - - template::value, _T1, _T2> = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a) - : _Inherited(__tag, __a) { } - - template = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - const _T1& __a1, const _T2& __a2) - : _Inherited(__tag, __a, __a1, __a2) { } - - template = false> - explicit - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - const _T1& __a1, const _T2& __a2) - : _Inherited(__tag, __a, __a1, __a2) { } - - template = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2) - : _Inherited(__tag, __a, std::forward<_U1>(__a1), - std::forward<_U2>(__a2)) { } - - template = false> - explicit - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - _U1&& __a1, _U2&& __a2) - : _Inherited(__tag, __a, std::forward<_U1>(__a1), - std::forward<_U2>(__a2)) { } - - template - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) - : _Inherited(__tag, __a, static_cast(__in)) { } - - template - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) - : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } - - template = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - const tuple<_U1, _U2>& __in) - : _Inherited(__tag, __a, - static_cast&>(__in)) - { } - - template = false> - explicit - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - const tuple<_U1, _U2>& __in) - : _Inherited(__tag, __a, - static_cast&>(__in)) - { } - - template = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) - : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) - { } - - template = false> - explicit - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) - : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) - { } - - template = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - const pair<_U1, _U2>& __in) - : _Inherited(__tag, __a, __in.first, __in.second) { } - - template = false> - explicit - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, - const pair<_U1, _U2>& __in) - : _Inherited(__tag, __a, __in.first, __in.second) { } - - template = true> - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) - : _Inherited(__tag, __a, std::forward<_U1>(__in.first), - std::forward<_U2>(__in.second)) { } - - template = false> - explicit - _GLIBCXX20_CONSTEXPR - tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) - : _Inherited(__tag, __a, std::forward<_U1>(__in.first), - std::forward<_U2>(__in.second)) { } - - // Tuple assignment. - - _GLIBCXX20_CONSTEXPR - tuple& - operator=(typename conditional<__assignable(), - const tuple&, - const __nonesuch&>::type __in) - noexcept(__nothrow_assignable()) - { - this->_M_assign(__in); - return *this; - } - - _GLIBCXX20_CONSTEXPR - tuple& - operator=(typename conditional<__assignable<_T1, _T2>(), - tuple&&, - __nonesuch&&>::type __in) - noexcept(__nothrow_assignable<_T1, _T2>()) - { - this->_M_assign(std::move(__in)); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR - __enable_if_t<__assignable(), tuple&> - operator=(const tuple<_U1, _U2>& __in) - noexcept(__nothrow_assignable()) - { - this->_M_assign(__in); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR - __enable_if_t<__assignable<_U1, _U2>(), tuple&> - operator=(tuple<_U1, _U2>&& __in) - noexcept(__nothrow_assignable<_U1, _U2>()) - { - this->_M_assign(std::move(__in)); - return *this; - } - - template - _GLIBCXX20_CONSTEXPR - __enable_if_t<__assignable(), tuple&> - operator=(const pair<_U1, _U2>& __in) - noexcept(__nothrow_assignable()) - { - this->_M_head(*this) = __in.first; - this->_M_tail(*this)._M_head(*this) = __in.second; - return *this; - } - - template - _GLIBCXX20_CONSTEXPR - __enable_if_t<__assignable<_U1, _U2>(), tuple&> - operator=(pair<_U1, _U2>&& __in) - noexcept(__nothrow_assignable<_U1, _U2>()) - { - this->_M_head(*this) = std::forward<_U1>(__in.first); - this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); - return *this; - } - - _GLIBCXX20_CONSTEXPR - void - swap(tuple& __in) - noexcept(__and_<__is_nothrow_swappable<_T1>, - __is_nothrow_swappable<_T2>>::value) - { _Inherited::_M_swap(__in); } - }; - - - /// class tuple_size - template - struct tuple_size> - : public integral_constant { }; - -#if __cplusplus > 201402L - template - inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; -#endif - - /** - * Recursive case for tuple_element: strip off the first element in - * the tuple and retrieve the (i-1)th element of the remaining tuple. - */ - template - struct tuple_element<__i, tuple<_Head, _Tail...> > - : tuple_element<__i - 1, tuple<_Tail...> > { }; - - /** - * Basis case for tuple_element: The first element is the one we're seeking. - */ - template - struct tuple_element<0, tuple<_Head, _Tail...> > - { - typedef _Head type; - }; - - /** - * Error case for tuple_element: invalid index. - */ - template - struct tuple_element<__i, tuple<>> - { - static_assert(__i < tuple_size>::value, - "tuple index is in range"); - }; - - template - constexpr _Head& - __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept - { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } - - template - constexpr const _Head& - __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept - { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } - - /// Return a reference to the ith element of a tuple. - template - constexpr __tuple_element_t<__i, tuple<_Elements...>>& - get(tuple<_Elements...>& __t) noexcept - { return std::__get_helper<__i>(__t); } - - /// Return a const reference to the ith element of a const tuple. - template - constexpr const __tuple_element_t<__i, tuple<_Elements...>>& - get(const tuple<_Elements...>& __t) noexcept - { return std::__get_helper<__i>(__t); } - - /// Return an rvalue reference to the ith element of a tuple rvalue. - template - constexpr __tuple_element_t<__i, tuple<_Elements...>>&& - get(tuple<_Elements...>&& __t) noexcept - { - typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; - return std::forward<__element_type&&>(std::get<__i>(__t)); - } - - /// Return a const rvalue reference to the ith element of a const tuple rvalue. - template - constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& - get(const tuple<_Elements...>&& __t) noexcept - { - typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; - return std::forward(std::get<__i>(__t)); - } - -#if __cplusplus >= 201402L - -#define __cpp_lib_tuples_by_type 201304 - - template - constexpr _Head& - __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept - { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } - - template - constexpr const _Head& - __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept - { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } - - /// Return a reference to the unique element of type _Tp of a tuple. - template - constexpr _Tp& - get(tuple<_Types...>& __t) noexcept - { return std::__get_helper2<_Tp>(__t); } - - /// Return a reference to the unique element of type _Tp of a tuple rvalue. - template - constexpr _Tp&& - get(tuple<_Types...>&& __t) noexcept - { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } - - /// Return a const reference to the unique element of type _Tp of a tuple. - template - constexpr const _Tp& - get(const tuple<_Types...>& __t) noexcept - { return std::__get_helper2<_Tp>(__t); } - - /// Return a const reference to the unique element of type _Tp of - /// a const tuple rvalue. - template - constexpr const _Tp&& - get(const tuple<_Types...>&& __t) noexcept - { return std::forward(std::__get_helper2<_Tp>(__t)); } -#endif - - // This class performs the comparison operations on tuples - template - struct __tuple_compare - { - static constexpr bool - __eq(const _Tp& __t, const _Up& __u) - { - return bool(std::get<__i>(__t) == std::get<__i>(__u)) - && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u); - } - - static constexpr bool - __less(const _Tp& __t, const _Up& __u) - { - return bool(std::get<__i>(__t) < std::get<__i>(__u)) - || (!bool(std::get<__i>(__u) < std::get<__i>(__t)) - && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u)); - } - }; - - template - struct __tuple_compare<_Tp, _Up, __size, __size> - { - static constexpr bool - __eq(const _Tp&, const _Up&) { return true; } - - static constexpr bool - __less(const _Tp&, const _Up&) { return false; } - }; - - template - constexpr bool - operator==(const tuple<_TElements...>& __t, - const tuple<_UElements...>& __u) - { - static_assert(sizeof...(_TElements) == sizeof...(_UElements), - "tuple objects can only be compared if they have equal sizes."); - using __compare = __tuple_compare, - tuple<_UElements...>, - 0, sizeof...(_TElements)>; - return __compare::__eq(__t, __u); - } - -#if __cpp_lib_three_way_comparison - template - constexpr _Cat - __tuple_cmp(const _Tp&, const _Up&, index_sequence<>) - { return _Cat::equivalent; } - - template - constexpr _Cat - __tuple_cmp(const _Tp& __t, const _Up& __u, - index_sequence<_Idx0, _Idxs...>) - { - auto __c - = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u)); - if (__c != 0) - return __c; - return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>()); - } - - template - constexpr - common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...> - operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u) - { - using _Cat - = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>; - return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>()); - } -#else - template - constexpr bool - operator<(const tuple<_TElements...>& __t, - const tuple<_UElements...>& __u) - { - static_assert(sizeof...(_TElements) == sizeof...(_UElements), - "tuple objects can only be compared if they have equal sizes."); - using __compare = __tuple_compare, - tuple<_UElements...>, - 0, sizeof...(_TElements)>; - return __compare::__less(__t, __u); - } - - template - constexpr bool - operator!=(const tuple<_TElements...>& __t, - const tuple<_UElements...>& __u) - { return !(__t == __u); } - - template - constexpr bool - operator>(const tuple<_TElements...>& __t, - const tuple<_UElements...>& __u) - { return __u < __t; } - - template - constexpr bool - operator<=(const tuple<_TElements...>& __t, - const tuple<_UElements...>& __u) - { return !(__u < __t); } - - template - constexpr bool - operator>=(const tuple<_TElements...>& __t, - const tuple<_UElements...>& __u) - { return !(__t < __u); } -#endif // three_way_comparison - - // NB: DR 705. - template - constexpr tuple::__type...> - make_tuple(_Elements&&... __args) - { - typedef tuple::__type...> - __result_type; - return __result_type(std::forward<_Elements>(__args)...); - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2275. Why is forward_as_tuple not constexpr? - /// std::forward_as_tuple - template - constexpr tuple<_Elements&&...> - forward_as_tuple(_Elements&&... __args) noexcept - { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } - - template - struct __make_tuple_impl; - - template - struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> - : __make_tuple_impl<_Idx + 1, - tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>, - _Tuple, _Nm> - { }; - - template - struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> - { - typedef tuple<_Tp...> __type; - }; - - template - struct __do_make_tuple - : __make_tuple_impl<0, tuple<>, _Tuple, std::tuple_size<_Tuple>::value> - { }; - - // Returns the std::tuple equivalent of a tuple-like type. - template - struct __make_tuple - : public __do_make_tuple<__remove_cvref_t<_Tuple>> - { }; - - // Combines several std::tuple's into a single one. - template - struct __combine_tuples; - - template<> - struct __combine_tuples<> - { - typedef tuple<> __type; - }; - - template - struct __combine_tuples> - { - typedef tuple<_Ts...> __type; - }; - - template - struct __combine_tuples, tuple<_T2s...>, _Rem...> - { - typedef typename __combine_tuples, - _Rem...>::__type __type; - }; - - // Computes the result type of tuple_cat given a set of tuple-like types. - template - struct __tuple_cat_result - { - typedef typename __combine_tuples - ::__type...>::__type __type; - }; - - // Helper to determine the index set for the first tuple-like - // type of a given set. - template - struct __make_1st_indices; - - template<> - struct __make_1st_indices<> - { - typedef std::_Index_tuple<> __type; - }; - - template - struct __make_1st_indices<_Tp, _Tpls...> - { - typedef typename std::_Build_index_tuple::type>::value>::__type __type; - }; - - // Performs the actual concatenation by step-wise expanding tuple-like - // objects into the elements, which are finally forwarded into the - // result tuple. - template - struct __tuple_concater; - - template - struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> - { - template - static constexpr _Ret - _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) - { - typedef typename __make_1st_indices<_Tpls...>::__type __idx; - typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; - return __next::_S_do(std::forward<_Tpls>(__tps)..., - std::forward<_Us>(__us)..., - std::get<_Is>(std::forward<_Tp>(__tp))...); - } - }; - - template - struct __tuple_concater<_Ret, std::_Index_tuple<>> - { - template - static constexpr _Ret - _S_do(_Us&&... __us) - { - return _Ret(std::forward<_Us>(__us)...); - } - }; - - /// tuple_cat - template...>::value>::type> - constexpr auto - tuple_cat(_Tpls&&... __tpls) - -> typename __tuple_cat_result<_Tpls...>::__type - { - typedef typename __tuple_cat_result<_Tpls...>::__type __ret; - typedef typename __make_1st_indices<_Tpls...>::__type __idx; - typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; - return __concater::_S_do(std::forward<_Tpls>(__tpls)...); - } - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2301. Why is tie not constexpr? - /// tie - template - constexpr tuple<_Elements&...> - tie(_Elements&... __args) noexcept - { return tuple<_Elements&...>(__args...); } - - /// swap - template - _GLIBCXX20_CONSTEXPR - inline -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - // Constrained free swap overload, see p0185r1 - typename enable_if<__and_<__is_swappable<_Elements>...>::value - >::type -#else - void -#endif - swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) - noexcept(noexcept(__x.swap(__y))) - { __x.swap(__y); } - -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 - template - _GLIBCXX20_CONSTEXPR - typename enable_if...>::value>::type - swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete; -#endif - - // A class (and instance) which can be used in 'tie' when an element - // of a tuple is not required. - // _GLIBCXX14_CONSTEXPR - // 2933. PR for LWG 2773 could be clearer - struct _Swallow_assign - { - template - _GLIBCXX14_CONSTEXPR const _Swallow_assign& - operator=(const _Tp&) const - { return *this; } - }; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2773. Making std::ignore constexpr - _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{}; - - /// Partial specialization for tuples - template - struct uses_allocator, _Alloc> : true_type { }; - - // See stl_pair.h... - /** "piecewise construction" using a tuple of arguments for each member. - * - * @param __first Arguments for the first member of the pair. - * @param __second Arguments for the second member of the pair. - * - * The elements of each tuple will be used as the constructor arguments - * for the data members of the pair. - */ - template - template - _GLIBCXX20_CONSTEXPR - inline - pair<_T1, _T2>:: - pair(piecewise_construct_t, - tuple<_Args1...> __first, tuple<_Args2...> __second) - : pair(__first, __second, - typename _Build_index_tuple::__type(), - typename _Build_index_tuple::__type()) - { } - - template - template - _GLIBCXX20_CONSTEXPR inline - pair<_T1, _T2>:: - pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2, - _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>) - : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...), - second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) - { } - -#if __cplusplus >= 201703L - - // Unpack a std::tuple into a type trait and use its value. - // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value. - // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value. - // Otherwise the result is false (because we don't know if std::get throws). - template class _Trait, typename _Tp, typename _Tuple> - inline constexpr bool __unpack_std_tuple = false; - - template class _Trait, typename _Tp, typename... _Up> - inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>> - = _Trait<_Tp, _Up...>::value; - - template class _Trait, typename _Tp, typename... _Up> - inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&> - = _Trait<_Tp, _Up&...>::value; - - template class _Trait, typename _Tp, typename... _Up> - inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>> - = _Trait<_Tp, const _Up...>::value; - - template class _Trait, typename _Tp, typename... _Up> - inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&> - = _Trait<_Tp, const _Up&...>::value; - -# define __cpp_lib_apply 201603 - - template - constexpr decltype(auto) - __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>) - { - return std::__invoke(std::forward<_Fn>(__f), - std::get<_Idx>(std::forward<_Tuple>(__t))...); - } - - template - constexpr decltype(auto) - apply(_Fn&& __f, _Tuple&& __t) - noexcept(__unpack_std_tuple) - { - using _Indices - = make_index_sequence>>; - return std::__apply_impl(std::forward<_Fn>(__f), - std::forward<_Tuple>(__t), - _Indices{}); - } - -#define __cpp_lib_make_from_tuple 201606 - - template - constexpr _Tp - __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) - { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } - - template - constexpr _Tp - make_from_tuple(_Tuple&& __t) - noexcept(__unpack_std_tuple) - { - return __make_from_tuple_impl<_Tp>( - std::forward<_Tuple>(__t), - make_index_sequence>>{}); - } -#endif // C++17 - - /// @} - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++11 - -#endif // _GLIBCXX_TUPLE diff --git a/resources/sources/avr-libstdcpp/include/type_traits b/resources/sources/avr-libstdcpp/include/type_traits index 37ef4238d..04ce31e0c 100644 --- a/resources/sources/avr-libstdcpp/include/type_traits +++ b/resources/sources/avr-libstdcpp/include/type_traits @@ -1,3774 +1,142 @@ -// C++11 -*- C++ -*- +// Minimal for AVR GCC 7.3 (Arduino) +// Provides the subset needed by STruC++ runtime headers. +#ifndef _AVR_TYPE_TRAITS +#define _AVR_TYPE_TRAITS + +namespace std { + +// integral_constant +template struct integral_constant { + static constexpr T value = v; + using value_type = T; + using type = integral_constant; + constexpr operator value_type() const noexcept { return value; } + constexpr value_type operator()() const noexcept { return value; } +}; +using true_type = integral_constant; +using false_type = integral_constant; +template using bool_constant = integral_constant; + +// enable_if +template struct enable_if {}; +template struct enable_if { using type = T; }; +template using enable_if_t = typename enable_if::type; + +// conditional +template struct conditional { using type = T; }; +template struct conditional { using type = F; }; +template using conditional_t = typename conditional::type; + +// is_same +template struct is_same : false_type {}; +template struct is_same : true_type {}; +template inline constexpr bool is_same_v = is_same::value; + +// remove_const / remove_volatile / remove_cv +template struct remove_const { using type = T; }; +template struct remove_const { using type = T; }; +template using remove_const_t = typename remove_const::type; + +template struct remove_volatile { using type = T; }; +template struct remove_volatile { using type = T; }; +template using remove_volatile_t = typename remove_volatile::type; + +template struct remove_cv { + using type = typename remove_volatile::type>::type; +}; +template using remove_cv_t = typename remove_cv::type; + +// remove_reference +template struct remove_reference { using type = T; }; +template struct remove_reference { using type = T; }; +template struct remove_reference { using type = T; }; +template using remove_reference_t = typename remove_reference::type; + +// decay (simplified) +template struct decay { using type = remove_cv_t>; }; +template using decay_t = typename decay::type; + +// is_integral (via explicit specializations -- no __is_integral on GCC 7.3) +template struct _is_integral_impl : false_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template<> struct _is_integral_impl : true_type {}; +template struct is_integral : _is_integral_impl> {}; +template inline constexpr bool is_integral_v = is_integral::value; + +// is_floating_point +template struct _is_fp_impl : false_type {}; +template<> struct _is_fp_impl : true_type {}; +template<> struct _is_fp_impl : true_type {}; +template<> struct _is_fp_impl : true_type {}; +template struct is_floating_point : _is_fp_impl> {}; +template inline constexpr bool is_floating_point_v = is_floating_point::value; + +// is_arithmetic +template struct is_arithmetic : bool_constant || is_floating_point_v> {}; +template inline constexpr bool is_arithmetic_v = is_arithmetic::value; + +// is_signed / is_unsigned +template> struct _is_signed_impl : false_type {}; +template struct _is_signed_impl : bool_constant {}; +template struct is_signed : _is_signed_impl {}; +template inline constexpr bool is_signed_v = is_signed::value; + +template> struct _is_unsigned_impl : false_type {}; +template struct _is_unsigned_impl : bool_constant {}; +template struct is_unsigned : _is_unsigned_impl {}; +template inline constexpr bool is_unsigned_v = is_unsigned::value; + +// is_enum / is_class / is_base_of (GCC builtins available since GCC 4.3) +template struct is_enum : bool_constant<__is_enum(T)> {}; +template inline constexpr bool is_enum_v = is_enum::value; + +template struct is_class : bool_constant<__is_class(T)> {}; +template inline constexpr bool is_class_v = is_class::value; + +template struct is_base_of : bool_constant<__is_base_of(B, D)> {}; +template inline constexpr bool is_base_of_v = is_base_of::value; + +// is_convertible (SFINAE-based) +namespace _detail { + template void _conv_test(T); + template + struct _is_conv : false_type {}; + template + struct _is_conv(static_cast(*(From*)0)), void())> + : true_type {}; +} +template struct is_convertible : _detail::_is_conv {}; +template inline constexpr bool is_convertible_v = is_convertible::value; + +// underlying_type (GCC builtin) +template struct underlying_type { using type = __underlying_type(T); }; +template using underlying_type_t = typename underlying_type::type; + +// is_void +template struct is_void : is_same> {}; +template inline constexpr bool is_void_v = is_void::value; + +// is_pointer (simplified) +template struct is_pointer : false_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +template struct is_pointer : true_type {}; +template inline constexpr bool is_pointer_v = is_pointer::value; + +// declval +template T&& declval() noexcept; -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/type_traits - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_TYPE_TRAITS -#define _GLIBCXX_TYPE_TRAITS 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup metaprogramming Metaprogramming - * @ingroup utilities - * - * Template utilities for compile-time introspection and modification, - * including type classification traits, type property inspection traits - * and type transformation traits. - * - * @{ - */ - - /// integral_constant - template - struct integral_constant - { - static constexpr _Tp value = __v; - typedef _Tp value_type; - typedef integral_constant<_Tp, __v> type; - constexpr operator value_type() const noexcept { return value; } -#if __cplusplus > 201103L - -#define __cpp_lib_integral_constant_callable 201304 - - constexpr value_type operator()() const noexcept { return value; } -#endif - }; - - template - constexpr _Tp integral_constant<_Tp, __v>::value; - - /// The type used as a compile-time boolean with true value. - typedef integral_constant true_type; - - /// The type used as a compile-time boolean with false value. - typedef integral_constant false_type; - - template - using __bool_constant = integral_constant; - -#if __cplusplus > 201402L -# define __cpp_lib_bool_constant 201505 - template - using bool_constant = integral_constant; -#endif - - // Meta programming helper types. - - template - struct conditional; - - template - struct __type_identity - { using type = _Type; }; - - template - using __type_identity_t = typename __type_identity<_Tp>::type; - - template - struct __or_; - - template<> - struct __or_<> - : public false_type - { }; - - template - struct __or_<_B1> - : public _B1 - { }; - - template - struct __or_<_B1, _B2> - : public conditional<_B1::value, _B1, _B2>::type - { }; - - template - struct __or_<_B1, _B2, _B3, _Bn...> - : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type - { }; - - template - struct __and_; - - template<> - struct __and_<> - : public true_type - { }; - - template - struct __and_<_B1> - : public _B1 - { }; - - template - struct __and_<_B1, _B2> - : public conditional<_B1::value, _B2, _B1>::type - { }; - - template - struct __and_<_B1, _B2, _B3, _Bn...> - : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type - { }; - - template - struct __not_ - : public __bool_constant - { }; - -#if __cplusplus >= 201703L - - template - inline constexpr bool __or_v = __or_<_Bn...>::value; - template - inline constexpr bool __and_v = __and_<_Bn...>::value; - -#define __cpp_lib_logical_traits 201510 - - template - struct conjunction - : __and_<_Bn...> - { }; - - template - struct disjunction - : __or_<_Bn...> - { }; - - template - struct negation - : __not_<_Pp> - { }; - - template - inline constexpr bool conjunction_v = conjunction<_Bn...>::value; - - template - inline constexpr bool disjunction_v = disjunction<_Bn...>::value; - - template - inline constexpr bool negation_v = negation<_Pp>::value; - -#endif // C++17 - - // Forward declarations - template - struct is_reference; - template - struct is_function; - template - struct is_void; - template - struct __is_array_unknown_bounds; - - // Helper functions that return false_type for incomplete classes, - // incomplete unions and arrays of known bound from those. - - template - constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>) - { return {}; } - - template - constexpr typename __or_< - is_reference<_NestedType>, - is_function<_NestedType>, - is_void<_NestedType>, - __is_array_unknown_bounds<_NestedType> - >::type __is_complete_or_unbounded(_TypeIdentity) - { return {}; } - - // For several sfinae-friendly trait implementations we transport both the - // result information (as the member type) and the failure information (no - // member type). This is very similar to std::enable_if, but we cannot use - // them, because we need to derive from them as an implementation detail. - - template - struct __success_type - { typedef _Tp type; }; - - struct __failure_type - { }; - - template - struct remove_cv; - - // __remove_cv_t (std::remove_cv_t for C++11). - template - using __remove_cv_t = typename remove_cv<_Tp>::type; - - template - struct is_const; - - // Primary type categories. - - template - struct __is_void_helper - : public false_type { }; - - template<> - struct __is_void_helper - : public true_type { }; - - /// is_void - template - struct is_void - : public __is_void_helper<__remove_cv_t<_Tp>>::type - { }; - - template - struct __is_integral_helper - : public false_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - -#ifdef _GLIBCXX_USE_WCHAR_T - template<> - struct __is_integral_helper - : public true_type { }; -#endif - -#ifdef _GLIBCXX_USE_CHAR8_T - template<> - struct __is_integral_helper - : public true_type { }; -#endif - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; - - // Conditionalizing on __STRICT_ANSI__ here will break any port that - // uses one of these types for size_t. -#if defined(__GLIBCXX_TYPE_INT_N_0) - template<> - struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0> - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) - template<> - struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1> - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) - template<> - struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2> - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_3) - template<> - struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3> - : public true_type { }; - - template<> - struct __is_integral_helper - : public true_type { }; -#endif - - /// is_integral - template - struct is_integral - : public __is_integral_helper<__remove_cv_t<_Tp>>::type - { }; - - template - struct __is_floating_point_helper - : public false_type { }; - - template<> - struct __is_floating_point_helper - : public true_type { }; - - template<> - struct __is_floating_point_helper - : public true_type { }; - - template<> - struct __is_floating_point_helper - : public true_type { }; - -#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) - template<> - struct __is_floating_point_helper<__float128> - : public true_type { }; -#endif - - /// is_floating_point - template - struct is_floating_point - : public __is_floating_point_helper<__remove_cv_t<_Tp>>::type - { }; - - /// is_array - template - struct is_array - : public false_type { }; - - template - struct is_array<_Tp[_Size]> - : public true_type { }; - - template - struct is_array<_Tp[]> - : public true_type { }; - - template - struct __is_pointer_helper - : public false_type { }; - - template - struct __is_pointer_helper<_Tp*> - : public true_type { }; - - /// is_pointer - template - struct is_pointer - : public __is_pointer_helper<__remove_cv_t<_Tp>>::type - { }; - - /// is_lvalue_reference - template - struct is_lvalue_reference - : public false_type { }; - - template - struct is_lvalue_reference<_Tp&> - : public true_type { }; - - /// is_rvalue_reference - template - struct is_rvalue_reference - : public false_type { }; - - template - struct is_rvalue_reference<_Tp&&> - : public true_type { }; - - template - struct __is_member_object_pointer_helper - : public false_type { }; - - template - struct __is_member_object_pointer_helper<_Tp _Cp::*> - : public __not_>::type { }; - - /// is_member_object_pointer - template - struct is_member_object_pointer - : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type - { }; - - template - struct __is_member_function_pointer_helper - : public false_type { }; - - template - struct __is_member_function_pointer_helper<_Tp _Cp::*> - : public is_function<_Tp>::type { }; - - /// is_member_function_pointer - template - struct is_member_function_pointer - : public __is_member_function_pointer_helper<__remove_cv_t<_Tp>>::type - { }; - - /// is_enum - template - struct is_enum - : public integral_constant - { }; - - /// is_union - template - struct is_union - : public integral_constant - { }; - - /// is_class - template - struct is_class - : public integral_constant - { }; - - /// is_function - template - struct is_function - : public __bool_constant::value> { }; - - template - struct is_function<_Tp&> - : public false_type { }; - - template - struct is_function<_Tp&&> - : public false_type { }; - -#define __cpp_lib_is_null_pointer 201309 - - template - struct __is_null_pointer_helper - : public false_type { }; - - template<> - struct __is_null_pointer_helper - : public true_type { }; - - /// is_null_pointer (LWG 2247). - template - struct is_null_pointer - : public __is_null_pointer_helper<__remove_cv_t<_Tp>>::type - { }; - - /// __is_nullptr_t (deprecated extension). - template - struct __is_nullptr_t - : public is_null_pointer<_Tp> - { } _GLIBCXX_DEPRECATED_SUGGEST("std::is_null_pointer"); - - // Composite type categories. - - /// is_reference - template - struct is_reference - : public __or_, - is_rvalue_reference<_Tp>>::type - { }; - - /// is_arithmetic - template - struct is_arithmetic - : public __or_, is_floating_point<_Tp>>::type - { }; - - /// is_fundamental - template - struct is_fundamental - : public __or_, is_void<_Tp>, - is_null_pointer<_Tp>>::type - { }; - - /// is_object - template - struct is_object - : public __not_<__or_, is_reference<_Tp>, - is_void<_Tp>>>::type - { }; - - template - struct is_member_pointer; - - /// is_scalar - template - struct is_scalar - : public __or_, is_enum<_Tp>, is_pointer<_Tp>, - is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type - { }; - - /// is_compound - template - struct is_compound - : public __not_>::type { }; - - template - struct __is_member_pointer_helper - : public false_type { }; - - template - struct __is_member_pointer_helper<_Tp _Cp::*> - : public true_type { }; - - /// is_member_pointer - template - struct is_member_pointer - : public __is_member_pointer_helper<__remove_cv_t<_Tp>>::type - { }; - - template - struct is_same; - - template - using __is_one_of = __or_...>; - - // Check if a type is one of the signed integer types. - template - using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>, - signed char, signed short, signed int, signed long, - signed long long -#if defined(__GLIBCXX_TYPE_INT_N_0) - , signed __GLIBCXX_TYPE_INT_N_0 -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) - , signed __GLIBCXX_TYPE_INT_N_1 -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) - , signed __GLIBCXX_TYPE_INT_N_2 -#endif -#if defined(__GLIBCXX_TYPE_INT_N_3) - , signed __GLIBCXX_TYPE_INT_N_3 -#endif - >; - - // Check if a type is one of the unsigned integer types. - template - using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>, - unsigned char, unsigned short, unsigned int, unsigned long, - unsigned long long -#if defined(__GLIBCXX_TYPE_INT_N_0) - , unsigned __GLIBCXX_TYPE_INT_N_0 -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) - , unsigned __GLIBCXX_TYPE_INT_N_1 -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) - , unsigned __GLIBCXX_TYPE_INT_N_2 -#endif -#if defined(__GLIBCXX_TYPE_INT_N_3) - , unsigned __GLIBCXX_TYPE_INT_N_3 -#endif - >; - - // Check if a type is one of the signed or unsigned integer types. - template - using __is_standard_integer - = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>; - - // __void_t (std::void_t for C++11) - template using __void_t = void; - - // Utility to detect referenceable types ([defns.referenceable]). - - template - struct __is_referenceable - : public false_type - { }; - - template - struct __is_referenceable<_Tp, __void_t<_Tp&>> - : public true_type - { }; - - // Type properties. - - /// is_const - template - struct is_const - : public false_type { }; - - template - struct is_const<_Tp const> - : public true_type { }; - - /// is_volatile - template - struct is_volatile - : public false_type { }; - - template - struct is_volatile<_Tp volatile> - : public true_type { }; - - /// is_trivial - template - struct is_trivial - : public integral_constant - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - // is_trivially_copyable - template - struct is_trivially_copyable - : public integral_constant - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_standard_layout - template - struct is_standard_layout - : public integral_constant - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_pod (deprecated in C++20) - // Could use is_standard_layout && is_trivial instead of the builtin. - template - struct - _GLIBCXX20_DEPRECATED("use is_standard_layout && is_trivial instead") - is_pod - : public integral_constant - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_literal_type - template - struct is_literal_type - : public integral_constant - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_empty - template - struct is_empty - : public integral_constant - { }; - - /// is_polymorphic - template - struct is_polymorphic - : public integral_constant - { }; - -#if __cplusplus >= 201402L -#define __cpp_lib_is_final 201402L - /// is_final - template - struct is_final - : public integral_constant - { }; -#endif - - /// is_abstract - template - struct is_abstract - : public integral_constant - { }; - - template::value> - struct __is_signed_helper - : public false_type { }; - - template - struct __is_signed_helper<_Tp, true> - : public integral_constant - { }; - - /// is_signed - template - struct is_signed - : public __is_signed_helper<_Tp>::type - { }; - - /// is_unsigned - template - struct is_unsigned - : public __and_, __not_>> - { }; - - - // Destructible and constructible type properties. - - /** - * @brief Utility to simplify expressions used in unevaluated operands - * @ingroup utilities - */ - - template - _Up - __declval(int); - - template - _Tp - __declval(long); - - template - auto declval() noexcept -> decltype(__declval<_Tp>(0)); - - template - struct extent; - - template - struct remove_all_extents; - - template - struct __is_array_known_bounds - : public integral_constant::value > 0)> - { }; - - template - struct __is_array_unknown_bounds - : public __and_, __not_>> - { }; - - // In N3290 is_destructible does not say anything about function - // types and abstract types, see LWG 2049. This implementation - // describes function types as non-destructible and all complete - // object types as destructible, iff the explicit destructor - // call expression is wellformed. - struct __do_is_destructible_impl - { - template().~_Tp())> - static true_type __test(int); - - template - static false_type __test(...); - }; - - template - struct __is_destructible_impl - : public __do_is_destructible_impl - { - typedef decltype(__test<_Tp>(0)) type; - }; - - template, - __is_array_unknown_bounds<_Tp>, - is_function<_Tp>>::value, - bool = __or_, is_scalar<_Tp>>::value> - struct __is_destructible_safe; - - template - struct __is_destructible_safe<_Tp, false, false> - : public __is_destructible_impl::type>::type - { }; - - template - struct __is_destructible_safe<_Tp, true, false> - : public false_type { }; - - template - struct __is_destructible_safe<_Tp, false, true> - : public true_type { }; - - /// is_destructible - template - struct is_destructible - : public __is_destructible_safe<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - // is_nothrow_destructible requires that is_destructible is - // satisfied as well. We realize that by mimicing the - // implementation of is_destructible but refer to noexcept(expr) - // instead of decltype(expr). - struct __do_is_nt_destructible_impl - { - template - static __bool_constant().~_Tp())> - __test(int); - - template - static false_type __test(...); - }; - - template - struct __is_nt_destructible_impl - : public __do_is_nt_destructible_impl - { - typedef decltype(__test<_Tp>(0)) type; - }; - - template, - __is_array_unknown_bounds<_Tp>, - is_function<_Tp>>::value, - bool = __or_, is_scalar<_Tp>>::value> - struct __is_nt_destructible_safe; - - template - struct __is_nt_destructible_safe<_Tp, false, false> - : public __is_nt_destructible_impl::type>::type - { }; - - template - struct __is_nt_destructible_safe<_Tp, true, false> - : public false_type { }; - - template - struct __is_nt_destructible_safe<_Tp, false, true> - : public true_type { }; - - /// is_nothrow_destructible - template - struct is_nothrow_destructible - : public __is_nt_destructible_safe<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - -#if __GNUC__ >= 8 - template - struct __is_constructible_impl - : public __bool_constant<__is_constructible(_Tp, _Args...)> - { }; -#else - // Implementation of __is_constructible_impl. - - struct __do_is_default_constructible_impl - { - template - static true_type __test(int); - - template - static false_type __test(...); - }; - - template - struct __is_default_constructible_impl - : public __do_is_default_constructible_impl - { - typedef decltype(__test<_Tp>(0)) type; - }; - - template - struct __is_default_constructible_atom - : public __and_<__not_>, - __is_default_constructible_impl<_Tp>>::type - { }; - - template::value> - struct __is_default_constructible_safe; - - // The following technique is a workaround for a current core language - // restriction, which does not allow for array types to occur in - // functional casts of the form T(). Complete arrays can be default- - // constructed, if the element type is default-constructible, but - // arrays with unknown bounds are not. - template - struct __is_default_constructible_safe<_Tp, true> - : public __and_<__is_array_known_bounds<_Tp>, - __is_default_constructible_atom::type>>::type - { }; - - template - struct __is_default_constructible_safe<_Tp, false> - : public __is_default_constructible_atom<_Tp>::type - { }; - - // The hardest part of this trait is the binary direct-initialization - // case, because we hit into a functional cast of the form T(arg). - // This implementation uses different strategies depending on the - // target type to reduce the test overhead as much as possible: - // - // a) For a reference target type, we use a static_cast expression - // modulo its extra cases. - // - // b) For a non-reference target type we use a ::new expression. - struct __do_is_static_castable_impl - { - template(declval<_From>()))> - static true_type __test(int); - - template - static false_type __test(...); - }; - - template - struct __is_static_castable_impl - : public __do_is_static_castable_impl - { - typedef decltype(__test<_From, _To>(0)) type; - }; - - template - struct __is_static_castable_safe - : public __is_static_castable_impl<_From, _To>::type - { }; - - // __is_static_castable - template - struct __is_static_castable - : public integral_constant::value)> - { }; - - // Implementation for non-reference types. To meet the proper - // variable definition semantics, we also need to test for - // is_destructible in this case. - // This form should be simplified by a single expression: - // ::delete ::new _Tp(declval<_Arg>()), see c++/51222. - struct __do_is_direct_constructible_impl - { - template()))> - static true_type __test(int); - - template - static false_type __test(...); - }; - - template - struct __is_direct_constructible_impl - : public __do_is_direct_constructible_impl - { - typedef decltype(__test<_Tp, _Arg>(0)) type; - }; - - template - struct __is_direct_constructible_new_safe - : public __and_, - __is_direct_constructible_impl<_Tp, _Arg>> - { }; - - template - struct is_same; - - template - struct is_base_of; - - template - struct remove_reference; - - template, - is_function<_From>>>::value> - struct __is_base_to_derived_ref; - - template - struct is_constructible; - - // Detect whether we have a downcast situation during - // reference binding. - template - struct __is_base_to_derived_ref<_From, _To, true> - { - typedef typename remove_cv::type>::type __src_t; - typedef typename remove_cv::type>::type __dst_t; - typedef __and_<__not_>, - is_base_of<__src_t, __dst_t>, - __not_>> type; - static constexpr bool value = type::value; - }; - - template - struct __is_base_to_derived_ref<_From, _To, false> - : public false_type - { }; - - template, - is_rvalue_reference<_To>>::value> - struct __is_lvalue_to_rvalue_ref; - - // Detect whether we have an lvalue of non-function type - // bound to a reference-compatible rvalue-reference. - template - struct __is_lvalue_to_rvalue_ref<_From, _To, true> - { - typedef typename remove_cv::type>::type __src_t; - typedef typename remove_cv::type>::type __dst_t; - typedef __and_<__not_>, - __or_, - is_base_of<__dst_t, __src_t>>> type; - static constexpr bool value = type::value; - }; - - template - struct __is_lvalue_to_rvalue_ref<_From, _To, false> - : public false_type - { }; - - // Here we handle direct-initialization to a reference type as - // equivalent to a static_cast modulo overshooting conversions. - // These are restricted to the following conversions: - // a) A base class value to a derived class reference - // b) An lvalue to an rvalue-reference of reference-compatible - // types that are not functions - template - struct __is_direct_constructible_ref_cast - : public __and_<__is_static_castable<_Arg, _Tp>, - __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>, - __is_lvalue_to_rvalue_ref<_Arg, _Tp> - >>> - { }; - - template - struct __is_direct_constructible_new - : public conditional::value, - __is_direct_constructible_ref_cast<_Tp, _Arg>, - __is_direct_constructible_new_safe<_Tp, _Arg> - >::type - { }; - - template - struct __is_direct_constructible - : public __is_direct_constructible_new<_Tp, _Arg>::type - { }; - - // Since default-construction and binary direct-initialization have - // been handled separately, the implementation of the remaining - // n-ary construction cases is rather straightforward. We can use - // here a functional cast, because array types are excluded anyway - // and this form is never interpreted as a C cast. - struct __do_is_nary_constructible_impl - { - template()...))> - static true_type __test(int); - - template - static false_type __test(...); - }; - - template - struct __is_nary_constructible_impl - : public __do_is_nary_constructible_impl - { - typedef decltype(__test<_Tp, _Args...>(0)) type; - }; - - template - struct __is_nary_constructible - : public __is_nary_constructible_impl<_Tp, _Args...>::type - { - static_assert(sizeof...(_Args) > 1, - "Only useful for > 1 arguments"); - }; - - template - struct __is_constructible_impl - : public __is_nary_constructible<_Tp, _Args...> - { }; - - template - struct __is_constructible_impl<_Tp, _Arg> - : public __is_direct_constructible<_Tp, _Arg> - { }; - - template - struct __is_constructible_impl<_Tp> - : public __is_default_constructible_safe<_Tp>::type - { }; -#endif - - /// is_constructible - template - struct is_constructible - : public __is_constructible_impl<_Tp, _Args...> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_default_constructible - template - struct is_default_constructible - : public __is_constructible_impl<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_copy_constructible_impl; - - template - struct __is_copy_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_copy_constructible_impl<_Tp, true> - : public __is_constructible_impl<_Tp, const _Tp&> - { }; - - /// is_copy_constructible - template - struct is_copy_constructible - : public __is_copy_constructible_impl<_Tp> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_move_constructible_impl; - - template - struct __is_move_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_move_constructible_impl<_Tp, true> - : public __is_constructible_impl<_Tp, _Tp&&> - { }; - - /// is_move_constructible - template - struct is_move_constructible - : public __is_move_constructible_impl<_Tp> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template - struct __is_nt_constructible_impl - : public false_type - { }; - - template - struct __is_nt_constructible_impl - : public __bool_constant()...))> - { }; - - template - struct __is_nt_constructible_impl - : public __bool_constant(std::declval<_Arg>()))> - { }; - - template - struct __is_nt_constructible_impl - : public __bool_constant - { }; - - template - struct __is_nt_constructible_impl - : public __bool_constant::type())> - { }; - -#if __cpp_aggregate_paren_init - template - struct __is_nt_constructible_impl - : public __is_nt_constructible_impl - { }; - - template - struct __is_nt_constructible_impl - : public __and_<__is_nt_constructible_impl...> - { }; -#endif - -#if __GNUC__ >= 8 - template - using __is_nothrow_constructible_impl - = __is_nt_constructible_impl<__is_constructible(_Tp, _Args...), - _Tp, _Args...>; -#else - template - using __is_nothrow_constructible_impl - = __is_nt_constructible_impl<__is_constructible_impl<_Tp, _Args...>::value, - _Tp, _Args...>; -#endif - - /// is_nothrow_constructible - template - struct is_nothrow_constructible - : public __is_nothrow_constructible_impl<_Tp, _Args...>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_nothrow_default_constructible - template - struct is_nothrow_default_constructible - : public __is_nothrow_constructible_impl<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - - template::value> - struct __is_nothrow_copy_constructible_impl; - - template - struct __is_nothrow_copy_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_nothrow_copy_constructible_impl<_Tp, true> - : public __is_nothrow_constructible_impl<_Tp, const _Tp&> - { }; - - /// is_nothrow_copy_constructible - template - struct is_nothrow_copy_constructible - : public __is_nothrow_copy_constructible_impl<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_nothrow_move_constructible_impl; - - template - struct __is_nothrow_move_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_nothrow_move_constructible_impl<_Tp, true> - : public __is_nothrow_constructible_impl<_Tp, _Tp&&> - { }; - - /// is_nothrow_move_constructible - template - struct is_nothrow_move_constructible - : public __is_nothrow_move_constructible_impl<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - -#if __GNUC__ >= 8 - /// is_assignable - template - struct is_assignable - : public __bool_constant<__is_assignable(_Tp, _Up)> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; -#else - template - class __is_assignable_helper - { - template() = declval<_Up1>())> - static true_type - __test(int); - - template - static false_type - __test(...); - - public: - typedef decltype(__test<_Tp, _Up>(0)) type; - }; - - /// is_assignable - template - struct is_assignable - : public __is_assignable_helper<_Tp, _Up>::type - { }; -#endif - - template::value> - struct __is_copy_assignable_impl; - - template - struct __is_copy_assignable_impl<_Tp, false> - : public false_type { }; - -#if __GNUC__ >= 8 - template - struct __is_copy_assignable_impl<_Tp, true> - : public __bool_constant<__is_assignable(_Tp&, const _Tp&)> - { }; -#else - template - struct __is_copy_assignable_impl<_Tp, true> - : public is_assignable<_Tp&, const _Tp&> - { }; -#endif - - /// is_copy_assignable - template - struct is_copy_assignable - : public __is_copy_assignable_impl<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_move_assignable_impl; - - template - struct __is_move_assignable_impl<_Tp, false> - : public false_type { }; - -#if __GNUC__ >= 8 - template - struct __is_move_assignable_impl<_Tp, true> - : public __bool_constant<__is_assignable(_Tp&, _Tp&&)> - { }; -#else - template - struct __is_move_assignable_impl<_Tp, true> - : public is_assignable<_Tp&, _Tp&&> - { }; -#endif - - /// is_move_assignable - template - struct is_move_assignable - : public __is_move_assignable_impl<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template - struct __is_nt_assignable_impl - : public integral_constant() = declval<_Up>())> - { }; - -#if __GNUC__ >= 8 - template - struct __is_nothrow_assignable_impl - : public __and_<__bool_constant<__is_assignable(_Tp, _Up)>, - __is_nt_assignable_impl<_Tp, _Up>> - { }; -#else - template - struct __is_nothrow_assignable_impl - : public __and_, - __is_nt_assignable_impl<_Tp, _Up>> - { }; -#endif - - /// is_nothrow_assignable - template - struct is_nothrow_assignable - : public __is_nothrow_assignable_impl<_Tp, _Up> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_nt_copy_assignable_impl; - - template - struct __is_nt_copy_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_nt_copy_assignable_impl<_Tp, true> - : public __is_nothrow_assignable_impl<_Tp&, const _Tp&> - { }; - - /// is_nothrow_copy_assignable - template - struct is_nothrow_copy_assignable - : public __is_nt_copy_assignable_impl<_Tp> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_nt_move_assignable_impl; - - template - struct __is_nt_move_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_nt_move_assignable_impl<_Tp, true> - : public __is_nothrow_assignable_impl<_Tp&, _Tp&&> - { }; - - /// is_nothrow_move_assignable - template - struct is_nothrow_move_assignable - : public __is_nt_move_assignable_impl<_Tp> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_trivially_constructible - template - struct is_trivially_constructible - : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_trivially_default_constructible - template - struct is_trivially_default_constructible - : public __bool_constant<__is_trivially_constructible(_Tp)> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - struct __do_is_implicitly_default_constructible_impl - { - template - static void __helper(const _Tp&); - - template - static true_type __test(const _Tp&, - decltype(__helper({}))* = 0); - - static false_type __test(...); - }; - - template - struct __is_implicitly_default_constructible_impl - : public __do_is_implicitly_default_constructible_impl - { - typedef decltype(__test(declval<_Tp>())) type; - }; - - template - struct __is_implicitly_default_constructible_safe - : public __is_implicitly_default_constructible_impl<_Tp>::type - { }; - - template - struct __is_implicitly_default_constructible - : public __and_<__is_constructible_impl<_Tp>, - __is_implicitly_default_constructible_safe<_Tp>> - { }; - - template::value> - struct __is_trivially_copy_constructible_impl; - - template - struct __is_trivially_copy_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_trivially_copy_constructible_impl<_Tp, true> - : public __and_<__is_copy_constructible_impl<_Tp>, - integral_constant> - { }; - - /// is_trivially_copy_constructible - template - struct is_trivially_copy_constructible - : public __is_trivially_copy_constructible_impl<_Tp> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_trivially_move_constructible_impl; - - template - struct __is_trivially_move_constructible_impl<_Tp, false> - : public false_type { }; - - template - struct __is_trivially_move_constructible_impl<_Tp, true> - : public __and_<__is_move_constructible_impl<_Tp>, - integral_constant> - { }; - - /// is_trivially_move_constructible - template - struct is_trivially_move_constructible - : public __is_trivially_move_constructible_impl<_Tp> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_trivially_assignable - template - struct is_trivially_assignable - : public __bool_constant<__is_trivially_assignable(_Tp, _Up)> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_trivially_copy_assignable_impl; - - template - struct __is_trivially_copy_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_trivially_copy_assignable_impl<_Tp, true> - : public __bool_constant<__is_trivially_assignable(_Tp&, const _Tp&)> - { }; - - /// is_trivially_copy_assignable - template - struct is_trivially_copy_assignable - : public __is_trivially_copy_assignable_impl<_Tp> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template::value> - struct __is_trivially_move_assignable_impl; - - template - struct __is_trivially_move_assignable_impl<_Tp, false> - : public false_type { }; - - template - struct __is_trivially_move_assignable_impl<_Tp, true> - : public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)> - { }; - - /// is_trivially_move_assignable - template - struct is_trivially_move_assignable - : public __is_trivially_move_assignable_impl<_Tp> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_trivially_destructible - template - struct is_trivially_destructible - : public __and_<__is_destructible_safe<_Tp>, - __bool_constant<__has_trivial_destructor(_Tp)>> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - - /// has_virtual_destructor - template - struct has_virtual_destructor - : public integral_constant - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - - // type property queries. - - /// alignment_of - template - struct alignment_of - : public integral_constant - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// rank - template - struct rank - : public integral_constant { }; - - template - struct rank<_Tp[_Size]> - : public integral_constant::value> { }; - - template - struct rank<_Tp[]> - : public integral_constant::value> { }; - - /// extent - template - struct extent - : public integral_constant { }; - - template - struct extent<_Tp[_Size], _Uint> - : public integral_constant::value> - { }; - - template - struct extent<_Tp[], _Uint> - : public integral_constant::value> - { }; - - - // Type relations. - - /// is_same - template - struct is_same -#ifdef _GLIBCXX_BUILTIN_IS_SAME_AS - : public integral_constant -#else - : public false_type -#endif - { }; - -#ifndef _GLIBCXX_BUILTIN_IS_SAME_AS - template - struct is_same<_Tp, _Tp> - : public true_type - { }; -#endif - - /// is_base_of - template - struct is_base_of - : public integral_constant - { }; - - template, is_function<_To>, - is_array<_To>>::value> - struct __is_convertible_helper - { - typedef typename is_void<_To>::type type; - }; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" - template - class __is_convertible_helper<_From, _To, false> - { - template - static void __test_aux(_To1) noexcept; - - template(std::declval<_From1>()))> - static true_type - __test(int); - - template - static false_type - __test(...); - - public: - typedef decltype(__test<_From, _To>(0)) type; - }; -#pragma GCC diagnostic pop - - /// is_convertible - template - struct is_convertible - : public __is_convertible_helper<_From, _To>::type - { }; - - // helper trait for unique_ptr, shared_ptr, and span - template - using __is_array_convertible - = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>; - -#if __cplusplus >= 202002L -#define __cpp_lib_is_nothrow_convertible 201806L - -#if __has_builtin(__is_nothrow_convertible) - /// is_nothrow_convertible_v - template - inline constexpr bool is_nothrow_convertible_v - = __is_nothrow_convertible(_From, _To); - - /// is_nothrow_convertible - template - struct is_nothrow_convertible - : public bool_constant> - { }; -#else - template, is_function<_To>, - is_array<_To>>::value> - struct __is_nt_convertible_helper - : is_void<_To> - { }; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" - template - class __is_nt_convertible_helper<_From, _To, false> - { - template - static void __test_aux(_To1) noexcept; - - template - static - __bool_constant(std::declval<_From1>()))> - __test(int); - - template - static false_type - __test(...); - - public: - using type = decltype(__test<_From, _To>(0)); - }; -#pragma GCC diagnostic pop - - /// is_nothrow_convertible - template - struct is_nothrow_convertible - : public __is_nt_convertible_helper<_From, _To>::type - { }; - - /// is_nothrow_convertible_v - template - inline constexpr bool is_nothrow_convertible_v - = is_nothrow_convertible<_From, _To>::value; -#endif -#endif // C++2a - - // Const-volatile modifications. - - /// remove_const - template - struct remove_const - { typedef _Tp type; }; - - template - struct remove_const<_Tp const> - { typedef _Tp type; }; - - /// remove_volatile - template - struct remove_volatile - { typedef _Tp type; }; - - template - struct remove_volatile<_Tp volatile> - { typedef _Tp type; }; - - /// remove_cv - template - struct remove_cv - { using type = _Tp; }; - - template - struct remove_cv - { using type = _Tp; }; - - template - struct remove_cv - { using type = _Tp; }; - - template - struct remove_cv - { using type = _Tp; }; - - /// add_const - template - struct add_const - { typedef _Tp const type; }; - - /// add_volatile - template - struct add_volatile - { typedef _Tp volatile type; }; - - /// add_cv - template - struct add_cv - { - typedef typename - add_const::type>::type type; - }; - -#if __cplusplus > 201103L - -#define __cpp_lib_transformation_trait_aliases 201304 - - /// Alias template for remove_const - template - using remove_const_t = typename remove_const<_Tp>::type; - - /// Alias template for remove_volatile - template - using remove_volatile_t = typename remove_volatile<_Tp>::type; - - /// Alias template for remove_cv - template - using remove_cv_t = typename remove_cv<_Tp>::type; - - /// Alias template for add_const - template - using add_const_t = typename add_const<_Tp>::type; - - /// Alias template for add_volatile - template - using add_volatile_t = typename add_volatile<_Tp>::type; - - /// Alias template for add_cv - template - using add_cv_t = typename add_cv<_Tp>::type; -#endif - - // Reference transformations. - - /// remove_reference - template - struct remove_reference - { typedef _Tp type; }; - - template - struct remove_reference<_Tp&> - { typedef _Tp type; }; - - template - struct remove_reference<_Tp&&> - { typedef _Tp type; }; - - template::value> - struct __add_lvalue_reference_helper - { typedef _Tp type; }; - - template - struct __add_lvalue_reference_helper<_Tp, true> - { typedef _Tp& type; }; - - /// add_lvalue_reference - template - struct add_lvalue_reference - : public __add_lvalue_reference_helper<_Tp> - { }; - - template::value> - struct __add_rvalue_reference_helper - { typedef _Tp type; }; - - template - struct __add_rvalue_reference_helper<_Tp, true> - { typedef _Tp&& type; }; - - /// add_rvalue_reference - template - struct add_rvalue_reference - : public __add_rvalue_reference_helper<_Tp> - { }; - -#if __cplusplus > 201103L - /// Alias template for remove_reference - template - using remove_reference_t = typename remove_reference<_Tp>::type; - - /// Alias template for add_lvalue_reference - template - using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type; - - /// Alias template for add_rvalue_reference - template - using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type; -#endif - - // Sign modifications. - - // Utility for constructing identically cv-qualified types. - template - struct __cv_selector; - - template - struct __cv_selector<_Unqualified, false, false> - { typedef _Unqualified __type; }; - - template - struct __cv_selector<_Unqualified, false, true> - { typedef volatile _Unqualified __type; }; - - template - struct __cv_selector<_Unqualified, true, false> - { typedef const _Unqualified __type; }; - - template - struct __cv_selector<_Unqualified, true, true> - { typedef const volatile _Unqualified __type; }; - - template::value, - bool _IsVol = is_volatile<_Qualified>::value> - class __match_cv_qualifiers - { - typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match; - - public: - typedef typename __match::__type __type; - }; - - // Utility for finding the unsigned versions of signed integral types. - template - struct __make_unsigned - { typedef _Tp __type; }; - - template<> - struct __make_unsigned - { typedef unsigned char __type; }; - - template<> - struct __make_unsigned - { typedef unsigned char __type; }; - - template<> - struct __make_unsigned - { typedef unsigned short __type; }; - - template<> - struct __make_unsigned - { typedef unsigned int __type; }; - - template<> - struct __make_unsigned - { typedef unsigned long __type; }; - - template<> - struct __make_unsigned - { typedef unsigned long long __type; }; - -#if defined(__GLIBCXX_TYPE_INT_N_0) - template<> - struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0> - { typedef unsigned __GLIBCXX_TYPE_INT_N_0 __type; }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) - template<> - struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1> - { typedef unsigned __GLIBCXX_TYPE_INT_N_1 __type; }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) - template<> - struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2> - { typedef unsigned __GLIBCXX_TYPE_INT_N_2 __type; }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_3) - template<> - struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3> - { typedef unsigned __GLIBCXX_TYPE_INT_N_3 __type; }; -#endif - - // Select between integral and enum: not possible to be both. - template::value, - bool _IsEnum = is_enum<_Tp>::value> - class __make_unsigned_selector; - - template - class __make_unsigned_selector<_Tp, true, false> - { - using __unsigned_type - = typename __make_unsigned<__remove_cv_t<_Tp>>::__type; - - public: - using __type - = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; - }; - - class __make_unsigned_selector_base - { - protected: - template struct _List { }; - - template - struct _List<_Tp, _Up...> : _List<_Up...> - { static constexpr size_t __size = sizeof(_Tp); }; - - template - struct __select; - - template - struct __select<_Sz, _List<_Uint, _UInts...>, true> - { using __type = _Uint; }; - - template - struct __select<_Sz, _List<_Uint, _UInts...>, false> - : __select<_Sz, _List<_UInts...>> - { }; - }; - - // Choose unsigned integer type with the smallest rank and same size as _Tp - template - class __make_unsigned_selector<_Tp, false, true> - : __make_unsigned_selector_base - { - // With -fshort-enums, an enum may be as small as a char. - using _UInts = _List; - - using __unsigned_type = typename __select::__type; - - public: - using __type - = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; - }; - - // wchar_t, char8_t, char16_t and char32_t are integral types but are - // neither signed integer types nor unsigned integer types, so must be - // transformed to the unsigned integer type with the smallest rank. - // Use the partial specialization for enumeration types to do that. -#if defined(_GLIBCXX_USE_WCHAR_T) - template<> - struct __make_unsigned - { - using __type - = typename __make_unsigned_selector::__type; - }; -#endif - -#ifdef _GLIBCXX_USE_CHAR8_T - template<> - struct __make_unsigned - { - using __type - = typename __make_unsigned_selector::__type; - }; -#endif - - template<> - struct __make_unsigned - { - using __type - = typename __make_unsigned_selector::__type; - }; - - template<> - struct __make_unsigned - { - using __type - = typename __make_unsigned_selector::__type; - }; - - // Given an integral/enum type, return the corresponding unsigned - // integer type. - // Primary template. - /// make_unsigned - template - struct make_unsigned - { typedef typename __make_unsigned_selector<_Tp>::__type type; }; - - // Integral, but don't define. - template<> - struct make_unsigned; - - - // Utility for finding the signed versions of unsigned integral types. - template - struct __make_signed - { typedef _Tp __type; }; - - template<> - struct __make_signed - { typedef signed char __type; }; - - template<> - struct __make_signed - { typedef signed char __type; }; - - template<> - struct __make_signed - { typedef signed short __type; }; - - template<> - struct __make_signed - { typedef signed int __type; }; - - template<> - struct __make_signed - { typedef signed long __type; }; - - template<> - struct __make_signed - { typedef signed long long __type; }; - -#if defined(__GLIBCXX_TYPE_INT_N_0) - template<> - struct __make_signed - { typedef __GLIBCXX_TYPE_INT_N_0 __type; }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_1) - template<> - struct __make_signed - { typedef __GLIBCXX_TYPE_INT_N_1 __type; }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_2) - template<> - struct __make_signed - { typedef __GLIBCXX_TYPE_INT_N_2 __type; }; -#endif -#if defined(__GLIBCXX_TYPE_INT_N_3) - template<> - struct __make_signed - { typedef __GLIBCXX_TYPE_INT_N_3 __type; }; -#endif - - // Select between integral and enum: not possible to be both. - template::value, - bool _IsEnum = is_enum<_Tp>::value> - class __make_signed_selector; - - template - class __make_signed_selector<_Tp, true, false> - { - using __signed_type - = typename __make_signed<__remove_cv_t<_Tp>>::__type; - - public: - using __type - = typename __match_cv_qualifiers<_Tp, __signed_type>::__type; - }; - - // Choose signed integer type with the smallest rank and same size as _Tp - template - class __make_signed_selector<_Tp, false, true> - { - typedef typename __make_unsigned_selector<_Tp>::__type __unsigned_type; - - public: - typedef typename __make_signed_selector<__unsigned_type>::__type __type; - }; - - // wchar_t, char16_t and char32_t are integral types but are neither - // signed integer types nor unsigned integer types, so must be - // transformed to the signed integer type with the smallest rank. - // Use the partial specialization for enumeration types to do that. -#if defined(_GLIBCXX_USE_WCHAR_T) - template<> - struct __make_signed - { - using __type - = typename __make_signed_selector::__type; - }; -#endif - -#if defined(_GLIBCXX_USE_CHAR8_T) - template<> - struct __make_signed - { - using __type - = typename __make_signed_selector::__type; - }; -#endif - - template<> - struct __make_signed - { - using __type - = typename __make_signed_selector::__type; - }; - - template<> - struct __make_signed - { - using __type - = typename __make_signed_selector::__type; - }; - - // Given an integral/enum type, return the corresponding signed - // integer type. - // Primary template. - /// make_signed - template - struct make_signed - { typedef typename __make_signed_selector<_Tp>::__type type; }; - - // Integral, but don't define. - template<> - struct make_signed; - -#if __cplusplus > 201103L - /// Alias template for make_signed - template - using make_signed_t = typename make_signed<_Tp>::type; - - /// Alias template for make_unsigned - template - using make_unsigned_t = typename make_unsigned<_Tp>::type; -#endif - - // Array modifications. - - /// remove_extent - template - struct remove_extent - { typedef _Tp type; }; - - template - struct remove_extent<_Tp[_Size]> - { typedef _Tp type; }; - - template - struct remove_extent<_Tp[]> - { typedef _Tp type; }; - - /// remove_all_extents - template - struct remove_all_extents - { typedef _Tp type; }; - - template - struct remove_all_extents<_Tp[_Size]> - { typedef typename remove_all_extents<_Tp>::type type; }; - - template - struct remove_all_extents<_Tp[]> - { typedef typename remove_all_extents<_Tp>::type type; }; - -#if __cplusplus > 201103L - /// Alias template for remove_extent - template - using remove_extent_t = typename remove_extent<_Tp>::type; - - /// Alias template for remove_all_extents - template - using remove_all_extents_t = typename remove_all_extents<_Tp>::type; -#endif - - // Pointer modifications. - - template - struct __remove_pointer_helper - { typedef _Tp type; }; - - template - struct __remove_pointer_helper<_Tp, _Up*> - { typedef _Up type; }; - - /// remove_pointer - template - struct remove_pointer - : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>> - { }; - - /// add_pointer - template, - is_void<_Tp>>::value> - struct __add_pointer_helper - { typedef _Tp type; }; - - template - struct __add_pointer_helper<_Tp, true> - { typedef typename remove_reference<_Tp>::type* type; }; - - template - struct add_pointer - : public __add_pointer_helper<_Tp> - { }; - -#if __cplusplus > 201103L - /// Alias template for remove_pointer - template - using remove_pointer_t = typename remove_pointer<_Tp>::type; - - /// Alias template for add_pointer - template - using add_pointer_t = typename add_pointer<_Tp>::type; -#endif - - template - struct __aligned_storage_msa - { - union __type - { - unsigned char __data[_Len]; - struct __attribute__((__aligned__)) { } __align; - }; - }; - - /** - * @brief Alignment type. - * - * The value of _Align is a default-alignment which shall be the - * most stringent alignment requirement for any C++ object type - * whose size is no greater than _Len (3.9). The member typedef - * type shall be a POD type suitable for use as uninitialized - * storage for any object whose size is at most _Len and whose - * alignment is a divisor of _Align. - */ - template::__type)> - struct aligned_storage - { - union type - { - unsigned char __data[_Len]; - struct __attribute__((__aligned__((_Align)))) { } __align; - }; - }; - - template - struct __strictest_alignment - { - static const size_t _S_alignment = 0; - static const size_t _S_size = 0; - }; - - template - struct __strictest_alignment<_Tp, _Types...> - { - static const size_t _S_alignment = - alignof(_Tp) > __strictest_alignment<_Types...>::_S_alignment - ? alignof(_Tp) : __strictest_alignment<_Types...>::_S_alignment; - static const size_t _S_size = - sizeof(_Tp) > __strictest_alignment<_Types...>::_S_size - ? sizeof(_Tp) : __strictest_alignment<_Types...>::_S_size; - }; - - /** - * @brief Provide aligned storage for types. - * - * [meta.trans.other] - * - * Provides aligned storage for any of the provided types of at - * least size _Len. - * - * @see aligned_storage - */ - template - struct aligned_union - { - private: - static_assert(sizeof...(_Types) != 0, "At least one type is required"); - - using __strictest = __strictest_alignment<_Types...>; - static const size_t _S_len = _Len > __strictest::_S_size - ? _Len : __strictest::_S_size; - public: - /// The value of the strictest alignment of _Types. - static const size_t alignment_value = __strictest::_S_alignment; - /// The storage. - typedef typename aligned_storage<_S_len, alignment_value>::type type; - }; - - template - const size_t aligned_union<_Len, _Types...>::alignment_value; - - // Decay trait for arrays and functions, used for perfect forwarding - // in make_pair, make_tuple, etc. - template::value, - bool _IsFunction = is_function<_Up>::value> - struct __decay_selector; - - // NB: DR 705. - template - struct __decay_selector<_Up, false, false> - { typedef __remove_cv_t<_Up> __type; }; - - template - struct __decay_selector<_Up, true, false> - { typedef typename remove_extent<_Up>::type* __type; }; - - template - struct __decay_selector<_Up, false, true> - { typedef typename add_pointer<_Up>::type __type; }; - - /// decay - template - class decay - { - typedef typename remove_reference<_Tp>::type __remove_type; - - public: - typedef typename __decay_selector<__remove_type>::__type type; - }; - - // __decay_t (std::decay_t for C++11). - template - using __decay_t = typename decay<_Tp>::type; - - template - class reference_wrapper; - - // Helper which adds a reference to a type when given a reference_wrapper - template - struct __strip_reference_wrapper - { - typedef _Tp __type; - }; - - template - struct __strip_reference_wrapper > - { - typedef _Tp& __type; - }; - - template - using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>; - - - // Primary template. - /// Define a member typedef @c type only if a boolean constant is true. - template - struct enable_if - { }; - - // Partial specialization for true. - template - struct enable_if - { typedef _Tp type; }; - - // __enable_if_t (std::enable_if_t for C++11) - template - using __enable_if_t = typename enable_if<_Cond, _Tp>::type; - - template - using _Require = __enable_if_t<__and_<_Cond...>::value>; - - // Primary template. - /// Define a member typedef @c type to one of two argument types. - template - struct conditional - { typedef _Iftrue type; }; - - // Partial specialization for false. - template - struct conditional - { typedef _Iffalse type; }; - - // __remove_cvref_t (std::remove_cvref_t for C++11). - template - using __remove_cvref_t - = typename remove_cv::type>::type; - - /// common_type - template - struct common_type; - - // Sfinae-friendly common_type implementation: - - struct __do_common_type_impl - { - template - using __cond_t - = decltype(true ? std::declval<_Tp>() : std::declval<_Up>()); - - // if decay_t() : declval())> - // denotes a valid type, let C denote that type. - template - static __success_type<__decay_t<__cond_t<_Tp, _Up>>> - _S_test(int); - -#if __cplusplus > 201703L - // Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type, - // let C denote the type decay_t. - template - static __success_type<__remove_cvref_t<__cond_t>> - _S_test_2(int); -#endif - - template - static __failure_type - _S_test_2(...); - - template - static decltype(_S_test_2<_Tp, _Up>(0)) - _S_test(...); - }; - - // If sizeof...(T) is zero, there shall be no member type. - template<> - struct common_type<> - { }; - - // If sizeof...(T) is one, the same type, if any, as common_type_t. - template - struct common_type<_Tp0> - : public common_type<_Tp0, _Tp0> - { }; - - // If sizeof...(T) is two, ... - template, typename _Dp2 = __decay_t<_Tp2>> - struct __common_type_impl - { - // If is_same_v is false or is_same_v is false, - // let C denote the same type, if any, as common_type_t. - using type = common_type<_Dp1, _Dp2>; - }; - - template - struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2> - : private __do_common_type_impl - { - // Otherwise, if decay_t() : declval())> - // denotes a valid type, let C denote that type. - using type = decltype(_S_test<_Tp1, _Tp2>(0)); - }; - - // If sizeof...(T) is two, ... - template - struct common_type<_Tp1, _Tp2> - : public __common_type_impl<_Tp1, _Tp2>::type - { }; - - template - struct __common_type_pack - { }; - - template - struct __common_type_fold; - - // If sizeof...(T) is greater than two, ... - template - struct common_type<_Tp1, _Tp2, _Rp...> - : public __common_type_fold, - __common_type_pack<_Rp...>> - { }; - - // Let C denote the same type, if any, as common_type_t. - // If there is such a type C, type shall denote the same type, if any, - // as common_type_t. - template - struct __common_type_fold<_CTp, __common_type_pack<_Rp...>, - __void_t> - : public common_type - { }; - - // Otherwise, there shall be no member type. - template - struct __common_type_fold<_CTp, _Rp, void> - { }; - - template::value> - struct __underlying_type_impl - { - using type = __underlying_type(_Tp); - }; - - template - struct __underlying_type_impl<_Tp, false> - { }; - - /// The underlying type of an enum. - template - struct underlying_type - : public __underlying_type_impl<_Tp> - { }; - - template - struct __declval_protector - { - static const bool __stop = false; - }; - - template - auto declval() noexcept -> decltype(__declval<_Tp>(0)) - { - static_assert(__declval_protector<_Tp>::__stop, - "declval() must not be used!"); - return __declval<_Tp>(0); - } - - /// result_of - template - class result_of; - - // Sfinae-friendly result_of implementation: - -#define __cpp_lib_result_of_sfinae 201210 - - struct __invoke_memfun_ref { }; - struct __invoke_memfun_deref { }; - struct __invoke_memobj_ref { }; - struct __invoke_memobj_deref { }; - struct __invoke_other { }; - - // Associate a tag type with a specialization of __success_type. - template - struct __result_of_success : __success_type<_Tp> - { using __invoke_type = _Tag; }; - - // [func.require] paragraph 1 bullet 1: - struct __result_of_memfun_ref_impl - { - template - static __result_of_success().*std::declval<_Fp>())(std::declval<_Args>()...) - ), __invoke_memfun_ref> _S_test(int); - - template - static __failure_type _S_test(...); - }; - - template - struct __result_of_memfun_ref - : private __result_of_memfun_ref_impl - { - typedef decltype(_S_test<_MemPtr, _Arg, _Args...>(0)) type; - }; - - // [func.require] paragraph 1 bullet 2: - struct __result_of_memfun_deref_impl - { - template - static __result_of_success()).*std::declval<_Fp>())(std::declval<_Args>()...) - ), __invoke_memfun_deref> _S_test(int); - - template - static __failure_type _S_test(...); - }; - - template - struct __result_of_memfun_deref - : private __result_of_memfun_deref_impl - { - typedef decltype(_S_test<_MemPtr, _Arg, _Args...>(0)) type; - }; - - // [func.require] paragraph 1 bullet 3: - struct __result_of_memobj_ref_impl - { - template - static __result_of_success().*std::declval<_Fp>() - ), __invoke_memobj_ref> _S_test(int); - - template - static __failure_type _S_test(...); - }; - - template - struct __result_of_memobj_ref - : private __result_of_memobj_ref_impl - { - typedef decltype(_S_test<_MemPtr, _Arg>(0)) type; - }; - - // [func.require] paragraph 1 bullet 4: - struct __result_of_memobj_deref_impl - { - template - static __result_of_success()).*std::declval<_Fp>() - ), __invoke_memobj_deref> _S_test(int); - - template - static __failure_type _S_test(...); - }; - - template - struct __result_of_memobj_deref - : private __result_of_memobj_deref_impl - { - typedef decltype(_S_test<_MemPtr, _Arg>(0)) type; - }; - - template - struct __result_of_memobj; - - template - struct __result_of_memobj<_Res _Class::*, _Arg> - { - typedef __remove_cvref_t<_Arg> _Argval; - typedef _Res _Class::* _MemPtr; - typedef typename conditional<__or_, - is_base_of<_Class, _Argval>>::value, - __result_of_memobj_ref<_MemPtr, _Arg>, - __result_of_memobj_deref<_MemPtr, _Arg> - >::type::type type; - }; - - template - struct __result_of_memfun; - - template - struct __result_of_memfun<_Res _Class::*, _Arg, _Args...> - { - typedef typename remove_reference<_Arg>::type _Argval; - typedef _Res _Class::* _MemPtr; - typedef typename conditional::value, - __result_of_memfun_ref<_MemPtr, _Arg, _Args...>, - __result_of_memfun_deref<_MemPtr, _Arg, _Args...> - >::type::type type; - }; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2219. INVOKE-ing a pointer to member with a reference_wrapper - // as the object expression - - // Used by result_of, invoke etc. to unwrap a reference_wrapper. - template> - struct __inv_unwrap - { - using type = _Tp; - }; - - template - struct __inv_unwrap<_Tp, reference_wrapper<_Up>> - { - using type = _Up&; - }; - - template - struct __result_of_impl - { - typedef __failure_type type; - }; - - template - struct __result_of_impl - : public __result_of_memobj<__decay_t<_MemPtr>, - typename __inv_unwrap<_Arg>::type> - { }; - - template - struct __result_of_impl - : public __result_of_memfun<__decay_t<_MemPtr>, - typename __inv_unwrap<_Arg>::type, _Args...> - { }; - - // [func.require] paragraph 1 bullet 5: - struct __result_of_other_impl - { - template - static __result_of_success()(std::declval<_Args>()...) - ), __invoke_other> _S_test(int); - - template - static __failure_type _S_test(...); - }; - - template - struct __result_of_impl - : private __result_of_other_impl - { - typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type; - }; - - // __invoke_result (std::invoke_result for C++11) - template - struct __invoke_result - : public __result_of_impl< - is_member_object_pointer< - typename remove_reference<_Functor>::type - >::value, - is_member_function_pointer< - typename remove_reference<_Functor>::type - >::value, - _Functor, _ArgTypes... - >::type - { }; - - template - struct result_of<_Functor(_ArgTypes...)> - : public __invoke_result<_Functor, _ArgTypes...> - { }; - -#if __cplusplus >= 201402L - /// Alias template for aligned_storage - template::__type)> - using aligned_storage_t = typename aligned_storage<_Len, _Align>::type; - - template - using aligned_union_t = typename aligned_union<_Len, _Types...>::type; - - /// Alias template for decay - template - using decay_t = typename decay<_Tp>::type; - - /// Alias template for enable_if - template - using enable_if_t = typename enable_if<_Cond, _Tp>::type; - - /// Alias template for conditional - template - using conditional_t = typename conditional<_Cond, _Iftrue, _Iffalse>::type; - - /// Alias template for common_type - template - using common_type_t = typename common_type<_Tp...>::type; - - /// Alias template for underlying_type - template - using underlying_type_t = typename underlying_type<_Tp>::type; - - /// Alias template for result_of - template - using result_of_t = typename result_of<_Tp>::type; -#endif // C++14 - -#if __cplusplus >= 201703L || !defined(__STRICT_ANSI__) // c++17 or gnu++11 -#define __cpp_lib_void_t 201411 - /// A metafunction that always yields void, used for detecting valid types. - template using void_t = void; -#endif - - /// Implementation of the detection idiom (negative case). - template class _Op, typename... _Args> - struct __detector - { - using value_t = false_type; - using type = _Default; - }; - - /// Implementation of the detection idiom (positive case). - template class _Op, - typename... _Args> - struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...> - { - using value_t = true_type; - using type = _Op<_Args...>; - }; - - // Detect whether _Op<_Args...> is a valid type, use _Default if not. - template class _Op, - typename... _Args> - using __detected_or = __detector<_Default, void, _Op, _Args...>; - - // _Op<_Args...> if that is a valid type, otherwise _Default. - template class _Op, - typename... _Args> - using __detected_or_t - = typename __detected_or<_Default, _Op, _Args...>::type; - - /// @} group metaprogramming - - /** - * Use SFINAE to determine if the type _Tp has a publicly-accessible - * member type _NTYPE. - */ -#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE) \ - template> \ - struct __has_##_NTYPE \ - : false_type \ - { }; \ - template \ - struct __has_##_NTYPE<_Tp, __void_t> \ - : true_type \ - { }; - - template - struct __is_swappable; - - template - struct __is_nothrow_swappable; - - template - class tuple; - - template - struct __is_tuple_like_impl : false_type - { }; - - template - struct __is_tuple_like_impl> : true_type - { }; - - // Internal type trait that allows us to sfinae-protect tuple_cat. - template - struct __is_tuple_like - : public __is_tuple_like_impl<__remove_cvref_t<_Tp>>::type - { }; - - template - _GLIBCXX20_CONSTEXPR - inline - _Require<__not_<__is_tuple_like<_Tp>>, - is_move_constructible<_Tp>, - is_move_assignable<_Tp>> - swap(_Tp&, _Tp&) - noexcept(__and_, - is_nothrow_move_assignable<_Tp>>::value); - - template - _GLIBCXX20_CONSTEXPR - inline - __enable_if_t<__is_swappable<_Tp>::value> - swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) - noexcept(__is_nothrow_swappable<_Tp>::value); - - namespace __swappable_details { - using std::swap; - - struct __do_is_swappable_impl - { - template(), std::declval<_Tp&>()))> - static true_type __test(int); - - template - static false_type __test(...); - }; - - struct __do_is_nothrow_swappable_impl - { - template - static __bool_constant< - noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())) - > __test(int); - - template - static false_type __test(...); - }; - - } // namespace __swappable_details - - template - struct __is_swappable_impl - : public __swappable_details::__do_is_swappable_impl - { - typedef decltype(__test<_Tp>(0)) type; - }; - - template - struct __is_nothrow_swappable_impl - : public __swappable_details::__do_is_nothrow_swappable_impl - { - typedef decltype(__test<_Tp>(0)) type; - }; - - template - struct __is_swappable - : public __is_swappable_impl<_Tp>::type - { }; - - template - struct __is_nothrow_swappable - : public __is_nothrow_swappable_impl<_Tp>::type - { }; - -#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 -#define __cpp_lib_is_swappable 201603 - /// Metafunctions used for detecting swappable types: p0185r1 - - /// is_swappable - template - struct is_swappable - : public __is_swappable_impl<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - /// is_nothrow_swappable - template - struct is_nothrow_swappable - : public __is_nothrow_swappable_impl<_Tp>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - -#if __cplusplus >= 201402L - /// is_swappable_v - template - _GLIBCXX17_INLINE constexpr bool is_swappable_v = - is_swappable<_Tp>::value; - - /// is_nothrow_swappable_v - template - _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_v = - is_nothrow_swappable<_Tp>::value; -#endif // __cplusplus >= 201402L - - namespace __swappable_with_details { - using std::swap; - - struct __do_is_swappable_with_impl - { - template(), std::declval<_Up>())), - typename - = decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))> - static true_type __test(int); - - template - static false_type __test(...); - }; - - struct __do_is_nothrow_swappable_with_impl - { - template - static __bool_constant< - noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) - && - noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())) - > __test(int); - - template - static false_type __test(...); - }; - - } // namespace __swappable_with_details - - template - struct __is_swappable_with_impl - : public __swappable_with_details::__do_is_swappable_with_impl - { - typedef decltype(__test<_Tp, _Up>(0)) type; - }; - - // Optimization for the homogenous lvalue case, not required: - template - struct __is_swappable_with_impl<_Tp&, _Tp&> - : public __swappable_details::__do_is_swappable_impl - { - typedef decltype(__test<_Tp&>(0)) type; - }; - - template - struct __is_nothrow_swappable_with_impl - : public __swappable_with_details::__do_is_nothrow_swappable_with_impl - { - typedef decltype(__test<_Tp, _Up>(0)) type; - }; - - // Optimization for the homogenous lvalue case, not required: - template - struct __is_nothrow_swappable_with_impl<_Tp&, _Tp&> - : public __swappable_details::__do_is_nothrow_swappable_impl - { - typedef decltype(__test<_Tp&>(0)) type; - }; - - /// is_swappable_with - template - struct is_swappable_with - : public __is_swappable_with_impl<_Tp, _Up>::type - { }; - - /// is_nothrow_swappable_with - template - struct is_nothrow_swappable_with - : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type - { }; - -#if __cplusplus >= 201402L - /// is_swappable_with_v - template - _GLIBCXX17_INLINE constexpr bool is_swappable_with_v = - is_swappable_with<_Tp, _Up>::value; - - /// is_nothrow_swappable_with_v - template - _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_with_v = - is_nothrow_swappable_with<_Tp, _Up>::value; -#endif // __cplusplus >= 201402L - -#endif// c++1z or gnu++11 - - // __is_invocable (std::is_invocable for C++11) - - // The primary template is used for invalid INVOKE expressions. - template::value, typename = void> - struct __is_invocable_impl : false_type { }; - - // Used for valid INVOKE and INVOKE expressions. - template - struct __is_invocable_impl<_Result, _Ret, - /* is_void<_Ret> = */ true, - __void_t> - : true_type - { }; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" - // Used for INVOKE expressions to check the implicit conversion to R. - template - struct __is_invocable_impl<_Result, _Ret, - /* is_void<_Ret> = */ false, - __void_t> - { - private: - // The type of the INVOKE expression. - // Unlike declval, this doesn't add_rvalue_reference. - static typename _Result::type _S_get(); - - template - static void _S_conv(_Tp); - - // This overload is viable if INVOKE(f, args...) can convert to _Tp. - template(_S_get()))> - static true_type - _S_test(int); - - template - static false_type - _S_test(...); - - public: - using type = decltype(_S_test<_Ret>(1)); - }; -#pragma GCC diagnostic pop - - template - struct __is_invocable - : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type - { }; - - template - constexpr bool __call_is_nt(__invoke_memfun_ref) - { - using _Up = typename __inv_unwrap<_Tp>::type; - return noexcept((std::declval<_Up>().*std::declval<_Fn>())( - std::declval<_Args>()...)); - } - - template - constexpr bool __call_is_nt(__invoke_memfun_deref) - { - return noexcept(((*std::declval<_Tp>()).*std::declval<_Fn>())( - std::declval<_Args>()...)); - } - - template - constexpr bool __call_is_nt(__invoke_memobj_ref) - { - using _Up = typename __inv_unwrap<_Tp>::type; - return noexcept(std::declval<_Up>().*std::declval<_Fn>()); - } - - template - constexpr bool __call_is_nt(__invoke_memobj_deref) - { - return noexcept((*std::declval<_Tp>()).*std::declval<_Fn>()); - } - - template - constexpr bool __call_is_nt(__invoke_other) - { - return noexcept(std::declval<_Fn>()(std::declval<_Args>()...)); - } - - template - struct __call_is_nothrow - : __bool_constant< - std::__call_is_nt<_Fn, _Args...>(typename _Result::__invoke_type{}) - > - { }; - - template - using __call_is_nothrow_ - = __call_is_nothrow<__invoke_result<_Fn, _Args...>, _Fn, _Args...>; - - // __is_nothrow_invocable (std::is_nothrow_invocable for C++11) - template - struct __is_nothrow_invocable - : __and_<__is_invocable<_Fn, _Args...>, - __call_is_nothrow_<_Fn, _Args...>>::type - { }; - -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" - struct __nonesuchbase {}; - struct __nonesuch : private __nonesuchbase { - ~__nonesuch() = delete; - __nonesuch(__nonesuch const&) = delete; - void operator=(__nonesuch const&) = delete; - }; -#pragma GCC diagnostic pop - -#if __cplusplus >= 201703L -# define __cpp_lib_is_invocable 201703 - - /// std::invoke_result - template - struct invoke_result - : public __invoke_result<_Functor, _ArgTypes...> - { }; - - /// std::invoke_result_t - template - using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; - - /// std::is_invocable - template - struct is_invocable - : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), - "_Fn must be a complete class or an unbounded array"); - }; - - /// std::is_invocable_r - template - struct is_invocable_r - : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), - "_Fn must be a complete class or an unbounded array"); - }; - - /// std::is_nothrow_invocable - template - struct is_nothrow_invocable - : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>, - __call_is_nothrow_<_Fn, _ArgTypes...>>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), - "_Fn must be a complete class or an unbounded array"); - }; - - /// @cond undocumented - // This checks that the INVOKE expression is well-formed and that the - // conversion to R does not throw. It does *not* check whether the INVOKE - // expression itself can throw. That is done by __call_is_nothrow_ instead. - template - using __is_nt_invocable_impl - = typename __is_invocable_impl<_Result, _Ret>::__nothrow_conv; - /// @endcond - - /// std::is_nothrow_invocable_r - template - struct is_nothrow_invocable_r - : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>, - __call_is_nothrow_<_Fn, _ArgTypes...>>::type - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), - "_Fn must be a complete class or an unbounded array"); - static_assert((std::__is_complete_or_unbounded( - __type_identity<_ArgTypes>{}) && ...), - "each argument type must be a complete class or an unbounded array"); - static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}), - "_Ret must be a complete class or an unbounded array"); - }; - - /// std::is_invocable_v - template - inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; - - /// std::is_nothrow_invocable_v - template - inline constexpr bool is_nothrow_invocable_v - = is_nothrow_invocable<_Fn, _Args...>::value; - - /// std::is_invocable_r_v - template - inline constexpr bool is_invocable_r_v - = is_invocable_r<_Ret, _Fn, _Args...>::value; - - /// std::is_nothrow_invocable_r_v - template - inline constexpr bool is_nothrow_invocable_r_v - = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; -#endif // C++17 - -#if __cplusplus >= 201703L -# define __cpp_lib_type_trait_variable_templates 201510L -template - inline constexpr bool is_void_v = is_void<_Tp>::value; -template - inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value; -template - inline constexpr bool is_integral_v = is_integral<_Tp>::value; -template - inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; -template - inline constexpr bool is_array_v = is_array<_Tp>::value; -template - inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; -template - inline constexpr bool is_lvalue_reference_v = - is_lvalue_reference<_Tp>::value; -template - inline constexpr bool is_rvalue_reference_v = - is_rvalue_reference<_Tp>::value; -template - inline constexpr bool is_member_object_pointer_v = - is_member_object_pointer<_Tp>::value; -template - inline constexpr bool is_member_function_pointer_v = - is_member_function_pointer<_Tp>::value; -template - inline constexpr bool is_enum_v = is_enum<_Tp>::value; -template - inline constexpr bool is_union_v = is_union<_Tp>::value; -template - inline constexpr bool is_class_v = is_class<_Tp>::value; -template - inline constexpr bool is_function_v = is_function<_Tp>::value; -template - inline constexpr bool is_reference_v = is_reference<_Tp>::value; -template - inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; -template - inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value; -template - inline constexpr bool is_object_v = is_object<_Tp>::value; -template - inline constexpr bool is_scalar_v = is_scalar<_Tp>::value; -template - inline constexpr bool is_compound_v = is_compound<_Tp>::value; -template - inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; -template - inline constexpr bool is_const_v = is_const<_Tp>::value; -template - inline constexpr bool is_volatile_v = is_volatile<_Tp>::value; -template - inline constexpr bool is_trivial_v = is_trivial<_Tp>::value; -template - inline constexpr bool is_trivially_copyable_v = - is_trivially_copyable<_Tp>::value; -template - inline constexpr bool is_standard_layout_v = is_standard_layout<_Tp>::value; -#pragma GCC diagnostic push -#pragma GCC diagnostic ignored "-Wdeprecated-declarations" -template - _GLIBCXX20_DEPRECATED("use is_standard_layout_v && is_trivial_v instead") - inline constexpr bool is_pod_v = is_pod<_Tp>::value; -#pragma GCC diagnostic pop -template - inline constexpr bool is_literal_type_v = is_literal_type<_Tp>::value; -template - inline constexpr bool is_empty_v = is_empty<_Tp>::value; -template - inline constexpr bool is_polymorphic_v = is_polymorphic<_Tp>::value; -template - inline constexpr bool is_abstract_v = is_abstract<_Tp>::value; -template - inline constexpr bool is_final_v = is_final<_Tp>::value; -template - inline constexpr bool is_signed_v = is_signed<_Tp>::value; -template - inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; -template - inline constexpr bool is_constructible_v = - is_constructible<_Tp, _Args...>::value; -template - inline constexpr bool is_default_constructible_v = - is_default_constructible<_Tp>::value; -template - inline constexpr bool is_copy_constructible_v = - is_copy_constructible<_Tp>::value; -template - inline constexpr bool is_move_constructible_v = - is_move_constructible<_Tp>::value; -template - inline constexpr bool is_assignable_v = is_assignable<_Tp, _Up>::value; -template - inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; -template - inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value; -template - inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; -template - inline constexpr bool is_trivially_constructible_v = - is_trivially_constructible<_Tp, _Args...>::value; -template - inline constexpr bool is_trivially_default_constructible_v = - is_trivially_default_constructible<_Tp>::value; -template - inline constexpr bool is_trivially_copy_constructible_v = - is_trivially_copy_constructible<_Tp>::value; -template - inline constexpr bool is_trivially_move_constructible_v = - is_trivially_move_constructible<_Tp>::value; -template - inline constexpr bool is_trivially_assignable_v = - is_trivially_assignable<_Tp, _Up>::value; -template - inline constexpr bool is_trivially_copy_assignable_v = - is_trivially_copy_assignable<_Tp>::value; -template - inline constexpr bool is_trivially_move_assignable_v = - is_trivially_move_assignable<_Tp>::value; -template - inline constexpr bool is_trivially_destructible_v = - is_trivially_destructible<_Tp>::value; -template - inline constexpr bool is_nothrow_constructible_v = - is_nothrow_constructible<_Tp, _Args...>::value; -template - inline constexpr bool is_nothrow_default_constructible_v = - is_nothrow_default_constructible<_Tp>::value; -template - inline constexpr bool is_nothrow_copy_constructible_v = - is_nothrow_copy_constructible<_Tp>::value; -template - inline constexpr bool is_nothrow_move_constructible_v = - is_nothrow_move_constructible<_Tp>::value; -template - inline constexpr bool is_nothrow_assignable_v = - is_nothrow_assignable<_Tp, _Up>::value; -template - inline constexpr bool is_nothrow_copy_assignable_v = - is_nothrow_copy_assignable<_Tp>::value; -template - inline constexpr bool is_nothrow_move_assignable_v = - is_nothrow_move_assignable<_Tp>::value; -template - inline constexpr bool is_nothrow_destructible_v = - is_nothrow_destructible<_Tp>::value; -template - inline constexpr bool has_virtual_destructor_v = - has_virtual_destructor<_Tp>::value; -template - inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; -template - inline constexpr size_t rank_v = rank<_Tp>::value; -template - inline constexpr size_t extent_v = extent<_Tp, _Idx>::value; -#ifdef _GLIBCXX_BUILTIN_IS_SAME_AS -template - inline constexpr bool is_same_v = _GLIBCXX_BUILTIN_IS_SAME_AS(_Tp, _Up); -#else -template - inline constexpr bool is_same_v = std::is_same<_Tp, _Up>::value; -#endif -template - inline constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value; -template - inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; - -#ifdef _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP -# define __cpp_lib_has_unique_object_representations 201606 - /// has_unique_object_representations - template - struct has_unique_object_representations - : bool_constant<__has_unique_object_representations( - remove_cv_t> - )> - { - static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), - "template argument must be a complete class or an unbounded array"); - }; - - template - inline constexpr bool has_unique_object_representations_v - = has_unique_object_representations<_Tp>::value; -#endif - -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE -# define __cpp_lib_is_aggregate 201703 - /// is_aggregate - template - struct is_aggregate - : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> - { }; - - /// is_aggregate_v - template - inline constexpr bool is_aggregate_v = is_aggregate<_Tp>::value; -#endif -#endif // C++17 - -#if __cplusplus > 201703L -#define __cpp_lib_remove_cvref 201711L - - /// Remove references and cv-qualifiers. - template - struct remove_cvref - { - using type = __remove_cvref_t<_Tp>; - }; - - template - using remove_cvref_t = __remove_cvref_t<_Tp>; - -#define __cpp_lib_type_identity 201806L - /// Identity metafunction. - template - struct type_identity { using type = _Tp; }; - - template - using type_identity_t = typename type_identity<_Tp>::type; - -#define __cpp_lib_unwrap_ref 201811L - - /// Unwrap a reference_wrapper - template - struct unwrap_reference { using type = _Tp; }; - - template - struct unwrap_reference> { using type = _Tp&; }; - - template - using unwrap_reference_t = typename unwrap_reference<_Tp>::type; - - /// Decay type and if it's a reference_wrapper, unwrap it - template - struct unwrap_ref_decay { using type = unwrap_reference_t>; }; - - template - using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; - -#define __cpp_lib_bounded_array_traits 201902L - - /// True for a type that is an array of known bound. - template - struct is_bounded_array - : public __is_array_known_bounds<_Tp> - { }; - - /// True for a type that is an array of unknown bound. - template - struct is_unbounded_array - : public __is_array_unknown_bounds<_Tp> - { }; - - template - inline constexpr bool is_bounded_array_v - = is_bounded_array<_Tp>::value; - - template - inline constexpr bool is_unbounded_array_v - = is_unbounded_array<_Tp>::value; - -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED - -#define __cpp_lib_is_constant_evaluated 201811L - - constexpr inline bool - is_constant_evaluated() noexcept - { return __builtin_is_constant_evaluated(); } -#endif - - template - using __copy_cv = typename __match_cv_qualifiers<_From, _To>::__type; - - template - using __cond_res - = decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()()); - - template - struct __common_ref_impl - { }; - - // [meta.trans.other], COMMON-REF(A, B) - template - using __common_ref = typename __common_ref_impl<_Ap, _Bp>::type; - - // If A and B are both lvalue reference types, ... - template - struct __common_ref_impl<_Xp&, _Yp&, - __void_t<__cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>>> - { using type = __cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>; }; - - // let C be remove_reference_t&& - template - using __common_ref_C = remove_reference_t<__common_ref<_Xp&, _Yp&>>&&; - - // If A and B are both rvalue reference types, ... - template - struct __common_ref_impl<_Xp&&, _Yp&&, - _Require>, - is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp>>>> - { using type = __common_ref_C<_Xp, _Yp>; }; - - // let D be COMMON-REF(const X&, Y&) - template - using __common_ref_D = __common_ref; - - // If A is an rvalue reference and B is an lvalue reference, ... - template - struct __common_ref_impl<_Xp&&, _Yp&, - _Require>>> - { using type = __common_ref_D<_Xp, _Yp>; }; - - // If A is an lvalue reference and B is an rvalue reference, ... - template - struct __common_ref_impl<_Xp&, _Yp&&> - : __common_ref_impl<_Yp&&, _Xp&> - { }; - - template class _TQual, template class _UQual> - struct basic_common_reference - { }; - - template - struct __xref - { template using __type = __copy_cv<_Tp, _Up>; }; - - template - struct __xref<_Tp&> - { template using __type = __copy_cv<_Tp, _Up>&; }; - - template - struct __xref<_Tp&&> - { template using __type = __copy_cv<_Tp, _Up>&&; }; - - template - using __basic_common_ref - = typename basic_common_reference, - remove_cvref_t<_Tp2>, - __xref<_Tp1>::template __type, - __xref<_Tp2>::template __type>::type; - - template - struct common_reference; - - template - using common_reference_t = typename common_reference<_Tp...>::type; - - // If sizeof...(T) is zero, there shall be no member type. - template<> - struct common_reference<> - { }; - - // If sizeof...(T) is one ... - template - struct common_reference<_Tp0> - { using type = _Tp0; }; - - template - struct __common_reference_impl - : __common_reference_impl<_Tp1, _Tp2, _Bullet + 1> - { }; - - // If sizeof...(T) is two ... - template - struct common_reference<_Tp1, _Tp2> - : __common_reference_impl<_Tp1, _Tp2> - { }; - - // If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ... - template - struct __common_reference_impl<_Tp1&, _Tp2&, 1, - void_t<__common_ref<_Tp1&, _Tp2&>>> - { using type = __common_ref<_Tp1&, _Tp2&>; }; - - template - struct __common_reference_impl<_Tp1&&, _Tp2&&, 1, - void_t<__common_ref<_Tp1&&, _Tp2&&>>> - { using type = __common_ref<_Tp1&&, _Tp2&&>; }; - - template - struct __common_reference_impl<_Tp1&, _Tp2&&, 1, - void_t<__common_ref<_Tp1&, _Tp2&&>>> - { using type = __common_ref<_Tp1&, _Tp2&&>; }; - - template - struct __common_reference_impl<_Tp1&&, _Tp2&, 1, - void_t<__common_ref<_Tp1&&, _Tp2&>>> - { using type = __common_ref<_Tp1&&, _Tp2&>; }; - - // Otherwise, if basic_common_reference<...>::type is well-formed, ... - template - struct __common_reference_impl<_Tp1, _Tp2, 2, - void_t<__basic_common_ref<_Tp1, _Tp2>>> - { using type = __basic_common_ref<_Tp1, _Tp2>; }; - - // Otherwise, if COND-RES(T1, T2) is well-formed, ... - template - struct __common_reference_impl<_Tp1, _Tp2, 3, - void_t<__cond_res<_Tp1, _Tp2>>> - { using type = __cond_res<_Tp1, _Tp2>; }; - - // Otherwise, if common_type_t is well-formed, ... - template - struct __common_reference_impl<_Tp1, _Tp2, 4, - void_t>> - { using type = common_type_t<_Tp1, _Tp2>; }; - - // Otherwise, there shall be no member type. - template - struct __common_reference_impl<_Tp1, _Tp2, 5, void> - { }; - - // Otherwise, if sizeof...(T) is greater than two, ... - template - struct common_reference<_Tp1, _Tp2, _Rest...> - : __common_type_fold, - __common_type_pack<_Rest...>> - { }; - - // Reuse __common_type_fold for common_reference - template - struct __common_type_fold, - __common_type_pack<_Rest...>, - void_t>> - : public common_reference, _Rest...> - { }; - -#endif // C++2a - -_GLIBCXX_END_NAMESPACE_VERSION } // namespace std -#endif // C++11 - -#endif // _GLIBCXX_TYPE_TRAITS +#endif // _AVR_TYPE_TRAITS diff --git a/resources/sources/avr-libstdcpp/include/unordered_map b/resources/sources/avr-libstdcpp/include/unordered_map deleted file mode 100644 index e05238fe9..000000000 --- a/resources/sources/avr-libstdcpp/include/unordered_map +++ /dev/null @@ -1,101 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/unordered_map - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_UNORDERED_MAP -#define _GLIBCXX_UNORDERED_MAP 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include -#include -#include -#include -#include // equal_to, _Identity, _Select1st -#include -#include -#include -#include -#include - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#if __cplusplus >= 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace pmr - { - template class polymorphic_allocator; - template, - typename _Pred = std::equal_to<_Key>> - using unordered_map - = std::unordered_map<_Key, _Tp, _Hash, _Pred, - polymorphic_allocator>>; - template, - typename _Pred = std::equal_to<_Key>> - using unordered_multimap - = std::unordered_multimap<_Key, _Tp, _Hash, _Pred, - polymorphic_allocator>>; - } // namespace pmr -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 - -#if __cplusplus > 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - template - inline typename unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>::size_type - erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, - _Predicate __pred) - { return __detail::__erase_nodes_if(__cont, __pred); } - - template - inline typename unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>:: - size_type - erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, - _Predicate __pred) - { return __detail::__erase_nodes_if(__cont, __pred); } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 - -#endif // C++11 - -#endif // _GLIBCXX_UNORDERED_MAP diff --git a/resources/sources/avr-libstdcpp/include/unordered_set b/resources/sources/avr-libstdcpp/include/unordered_set deleted file mode 100644 index 6cbd242ff..000000000 --- a/resources/sources/avr-libstdcpp/include/unordered_set +++ /dev/null @@ -1,100 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2007-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/unordered_set - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_UNORDERED_SET -#define _GLIBCXX_UNORDERED_SET 1 - -#pragma GCC system_header - -#if __cplusplus < 201103L -# include -#else - -#include -#include -#include -#include -#include -#include -#include // equal_to, _Identity, _Select1st -#include -#include -#include -#include -#include - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#if __cplusplus >= 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace pmr - { - template class polymorphic_allocator; - template, - typename _Pred = std::equal_to<_Key>> - using unordered_set - = std::unordered_set<_Key, _Hash, _Pred, - polymorphic_allocator<_Key>>; - template, - typename _Pred = std::equal_to<_Key>> - using unordered_multiset - = std::unordered_multiset<_Key, _Hash, _Pred, - polymorphic_allocator<_Key>>; - } // namespace pmr -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 - -#if __cplusplus > 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - template - inline typename unordered_set<_Key, _Hash, _CPred, _Alloc>::size_type - erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont, - _Predicate __pred) - { return __detail::__erase_nodes_if(__cont, __pred); } - - template - inline typename unordered_multiset<_Key, _Hash, _CPred, _Alloc>::size_type - erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont, - _Predicate __pred) - { return __detail::__erase_nodes_if(__cont, __pred); } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 - -#endif // C++11 - -#endif // _GLIBCXX_UNORDERED_SET diff --git a/resources/sources/avr-libstdcpp/include/utility b/resources/sources/avr-libstdcpp/include/utility index f7533d5a5..daa16ae36 100644 --- a/resources/sources/avr-libstdcpp/include/utility +++ b/resources/sources/avr-libstdcpp/include/utility @@ -1,538 +1,20 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996,1997 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/utility - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_UTILITY -#define _GLIBCXX_UTILITY 1 - -#pragma GCC system_header - -/** - * @defgroup utilities Utilities - * - * Components deemed generally useful. Includes pair, tuple, - * forward/move helpers, ratio, function object, metaprogramming and - * type traits, time, date, and memory functions. - */ - -#include -#include -#include - -#if __cplusplus >= 201103L - +// Minimal for AVR +#ifndef _AVR_UTILITY +#define _AVR_UTILITY #include -#include -#include - -#if __cplusplus > 201703L -#include -#endif -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /// Finds the size of a given tuple type. - template - struct tuple_size; - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 2313. tuple_size should always derive from integral_constant - // 2770. tuple_size specialization is not SFINAE compatible - - template::type, - typename = typename enable_if::value>::type, - size_t = tuple_size<_Tp>::value> - using __enable_if_has_tuple_size = _Tp; - - template - struct tuple_size> - : public tuple_size<_Tp> { }; - - template - struct tuple_size> - : public tuple_size<_Tp> { }; - - template - struct tuple_size> - : public tuple_size<_Tp> { }; - - /// Gives the type of the ith element of a given tuple type. - template - struct tuple_element; - - // Duplicate of C++14's tuple_element_t for internal use in C++11 mode - template - using __tuple_element_t = typename tuple_element<__i, _Tp>::type; - - template - struct tuple_element<__i, const _Tp> - { - typedef typename add_const<__tuple_element_t<__i, _Tp>>::type type; - }; - - template - struct tuple_element<__i, volatile _Tp> - { - typedef typename add_volatile<__tuple_element_t<__i, _Tp>>::type type; - }; - - template - struct tuple_element<__i, const volatile _Tp> - { - typedef typename add_cv<__tuple_element_t<__i, _Tp>>::type type; - }; - -#if __cplusplus >= 201402L -// The standard says this macro and alias template should be in -// but we define them here, to be available when the partial specializations -// of tuple_element> and tuple_element> are defined. -#define __cpp_lib_tuple_element_t 201402L - - template - using tuple_element_t = typename tuple_element<__i, _Tp>::type; +namespace std { + template constexpr remove_reference_t&& move(T&& t) noexcept { + return static_cast&&>(t); + } + template constexpr T&& forward(remove_reference_t& t) noexcept { + return static_cast(t); + } + template constexpr T&& forward(remove_reference_t&& t) noexcept { + return static_cast(t); + } + template void swap(T& a, T& b) noexcept { + T tmp = move(a); a = move(b); b = move(tmp); + } +} #endif - - // Various functions which give std::pair a tuple-like interface. - - /// Partial specialization for std::pair - template - struct __is_tuple_like_impl> : true_type - { }; - - /// Partial specialization for std::pair - template - struct tuple_size> - : public integral_constant { }; - - /// Partial specialization for std::pair - template - struct tuple_element<0, std::pair<_Tp1, _Tp2>> - { typedef _Tp1 type; }; - - /// Partial specialization for std::pair - template - struct tuple_element<1, std::pair<_Tp1, _Tp2>> - { typedef _Tp2 type; }; - - template - struct __pair_get; - - template<> - struct __pair_get<0> - { - template - static constexpr _Tp1& - __get(std::pair<_Tp1, _Tp2>& __pair) noexcept - { return __pair.first; } - - template - static constexpr _Tp1&& - __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept - { return std::forward<_Tp1>(__pair.first); } - - template - static constexpr const _Tp1& - __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept - { return __pair.first; } - - template - static constexpr const _Tp1&& - __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept - { return std::forward(__pair.first); } - }; - - template<> - struct __pair_get<1> - { - template - static constexpr _Tp2& - __get(std::pair<_Tp1, _Tp2>& __pair) noexcept - { return __pair.second; } - - template - static constexpr _Tp2&& - __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept - { return std::forward<_Tp2>(__pair.second); } - - template - static constexpr const _Tp2& - __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept - { return __pair.second; } - - template - static constexpr const _Tp2&& - __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept - { return std::forward(__pair.second); } - }; - - template - constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& - get(std::pair<_Tp1, _Tp2>& __in) noexcept - { return __pair_get<_Int>::__get(__in); } - - template - constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& - get(std::pair<_Tp1, _Tp2>&& __in) noexcept - { return __pair_get<_Int>::__move_get(std::move(__in)); } - - template - constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& - get(const std::pair<_Tp1, _Tp2>& __in) noexcept - { return __pair_get<_Int>::__const_get(__in); } - - template - constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& - get(const std::pair<_Tp1, _Tp2>&& __in) noexcept - { return __pair_get<_Int>::__const_move_get(std::move(__in)); } - -#if __cplusplus >= 201402L - -#define __cpp_lib_tuples_by_type 201304 - - template - constexpr _Tp& - get(pair<_Tp, _Up>& __p) noexcept - { return __p.first; } - - template - constexpr const _Tp& - get(const pair<_Tp, _Up>& __p) noexcept - { return __p.first; } - - template - constexpr _Tp&& - get(pair<_Tp, _Up>&& __p) noexcept - { return std::move(__p.first); } - - template - constexpr const _Tp&& - get(const pair<_Tp, _Up>&& __p) noexcept - { return std::move(__p.first); } - - template - constexpr _Tp& - get(pair<_Up, _Tp>& __p) noexcept - { return __p.second; } - - template - constexpr const _Tp& - get(const pair<_Up, _Tp>& __p) noexcept - { return __p.second; } - - template - constexpr _Tp&& - get(pair<_Up, _Tp>&& __p) noexcept - { return std::move(__p.second); } - - template - constexpr const _Tp&& - get(const pair<_Up, _Tp>&& __p) noexcept - { return std::move(__p.second); } - -#define __cpp_lib_exchange_function 201304 - - /// Assign @p __new_val to @p __obj and return its previous value. - template - _GLIBCXX20_CONSTEXPR - inline _Tp - exchange(_Tp& __obj, _Up&& __new_val) - { return std::__exchange(__obj, std::forward<_Up>(__new_val)); } - -#endif // C++14 - - // Stores a tuple of indices. Used by tuple and pair, and by bind() to - // extract the elements in a tuple. - template struct _Index_tuple { }; - -#if __GNUC__ >= 8 - -#ifdef __has_builtin -# if __has_builtin(__make_integer_seq) -# define _GLIBCXX_USE_MAKE_INTEGER_SEQ 1 -# endif -#endif - - // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. - template - struct _Build_index_tuple - { -#if _GLIBCXX_USE_MAKE_INTEGER_SEQ - template - using _IdxTuple = _Index_tuple<_Indices...>; - - using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; -#else - using __type = _Index_tuple<__integer_pack(_Num)...>; -#endif - }; -#else // __GNUC__ < 8 - // Concatenates two _Index_tuples. - template struct _Itup_cat; - - template - struct _Itup_cat<_Index_tuple<_Ind1...>, _Index_tuple<_Ind2...>> - { - using __type = _Index_tuple<_Ind1..., (_Ind2 + sizeof...(_Ind1))...>; - }; - - // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. - template - struct _Build_index_tuple - : _Itup_cat::__type, - typename _Build_index_tuple<_Num - _Num / 2>::__type> - { }; - - template<> - struct _Build_index_tuple<1> - { - typedef _Index_tuple<0> __type; - }; - - template<> - struct _Build_index_tuple<0> - { - typedef _Index_tuple<> __type; - }; -#endif // __GNUC__ < 8 - -#if __cplusplus > 201103L - -#define __cpp_lib_integer_sequence 201304 - -#if __GNUC__ >= 8 - /// Class template integer_sequence - template - struct integer_sequence - { - typedef _Tp value_type; - static constexpr size_t size() noexcept { return sizeof...(_Idx); } - }; - - /// Alias template make_integer_sequence - template - using make_integer_sequence -#if _GLIBCXX_USE_MAKE_INTEGER_SEQ - = __make_integer_seq; -#else - = integer_sequence<_Tp, __integer_pack(_Num)...>; -#endif - -#undef _GLIBCXX_USE_MAKE_INTEGER_SEQ - -#else // __GNUC__ < 8 - /// Class template integer_sequence - template - struct integer_sequence - { - typedef _Tp value_type; - static constexpr size_t size() { return sizeof...(_Idx); } - }; - - template::__type> - struct _Make_integer_sequence; - - template - struct _Make_integer_sequence<_Tp, _Num, _Index_tuple<_Idx...>> - { - static_assert( _Num >= 0, - "Cannot make integer sequence of negative length" ); - - typedef integer_sequence<_Tp, static_cast<_Tp>(_Idx)...> __type; - }; - - /// Alias template make_integer_sequence - template - using make_integer_sequence - = typename _Make_integer_sequence<_Tp, _Num>::__type; -#endif // __GNUC__ < 8 - - /// Alias template index_sequence - template - using index_sequence = integer_sequence; - - /// Alias template make_index_sequence - template - using make_index_sequence = make_integer_sequence; - - /// Alias template index_sequence_for - template - using index_sequence_for = make_index_sequence; -#endif - -#if __cplusplus > 201402L - - struct in_place_t { - explicit in_place_t() = default; - }; - - inline constexpr in_place_t in_place{}; - - template struct in_place_type_t - { - explicit in_place_type_t() = default; - }; - - template - inline constexpr in_place_type_t<_Tp> in_place_type{}; - - template struct in_place_index_t - { - explicit in_place_index_t() = default; - }; - - template - inline constexpr in_place_index_t<_Idx> in_place_index{}; - - template - struct __is_in_place_type_impl : false_type - { }; - - template - struct __is_in_place_type_impl> : true_type - { }; - - template - struct __is_in_place_type - : public __is_in_place_type_impl<_Tp> - { }; - -#define __cpp_lib_as_const 201510 - template - constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; } - - template - void as_const(const _Tp&&) = delete; - -#if __cplusplus > 201703L -#define __cpp_lib_integer_comparison_functions 202002L - - template - constexpr bool - cmp_equal(_Tp __t, _Up __u) noexcept - { - static_assert(__is_standard_integer<_Tp>::value); - static_assert(__is_standard_integer<_Up>::value); - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) - return __t == __u; - else if constexpr (is_signed_v<_Tp>) - return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; - else - return __u >= 0 && __t == make_unsigned_t<_Up>(__u); - } - - template - constexpr bool - cmp_not_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_equal(__t, __u); } - - template - constexpr bool - cmp_less(_Tp __t, _Up __u) noexcept - { - static_assert(__is_standard_integer<_Tp>::value); - static_assert(__is_standard_integer<_Up>::value); - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) - return __t < __u; - else if constexpr (is_signed_v<_Tp>) - return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; - else - return __u >= 0 && __t < make_unsigned_t<_Up>(__u); - } - - template - constexpr bool - cmp_greater(_Tp __t, _Up __u) noexcept - { return std::cmp_less(__u, __t); } - - template - constexpr bool - cmp_less_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_less(__u, __t); } - - template - constexpr bool - cmp_greater_equal(_Tp __t, _Up __u) noexcept - { return !std::cmp_less(__t, __u); } - - template - constexpr bool - in_range(_Tp __t) noexcept - { - static_assert(__is_standard_integer<_Up>::value); - static_assert(__is_standard_integer<_Tp>::value); - using __gnu_cxx::__int_traits; - - if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) - return __int_traits<_Up>::__min <= __t - && __t <= __int_traits<_Up>::__max; - else if constexpr (is_signed_v<_Tp>) - return __t >= 0 - && make_unsigned_t<_Tp>(__t) <= __int_traits<_Up>::__max; - else - return __t <= make_unsigned_t<_Up>(__int_traits<_Up>::__max); - } -#endif // C++20 -#endif // C++17 - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif - -#endif /* _GLIBCXX_UTILITY */ diff --git a/resources/sources/avr-libstdcpp/include/valarray b/resources/sources/avr-libstdcpp/include/valarray deleted file mode 100644 index be2e70dc0..000000000 --- a/resources/sources/avr-libstdcpp/include/valarray +++ /dev/null @@ -1,1253 +0,0 @@ -// The template and inlines for the -*- C++ -*- valarray class. - -// Copyright (C) 1997-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file include/valarray - * This is a Standard C++ Library header. - */ - -// Written by Gabriel Dos Reis - -#ifndef _GLIBCXX_VALARRAY -#define _GLIBCXX_VALARRAY 1 - -#pragma GCC system_header - -#include -#include -#include -#include -#if __cplusplus >= 201103L -#include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - template - class _Expr; - - template - class _ValArray; - -namespace __detail -{ - template class _Meta, class _Dom> - struct _UnClos; - - template class _Meta1, - template class _Meta2, - class _Dom1, class _Dom2> - class _BinClos; - - template class _Meta, class _Dom> - class _SClos; - - template class _Meta, class _Dom> - class _GClos; - - template class _Meta, class _Dom> - class _IClos; - - template class _Meta, class _Dom> - class _ValFunClos; - - template class _Meta, class _Dom> - class _RefFunClos; -} // namespace __detail - - using __detail::_UnClos; - using __detail::_BinClos; - using __detail::_SClos; - using __detail::_GClos; - using __detail::_IClos; - using __detail::_ValFunClos; - using __detail::_RefFunClos; - - template class valarray; // An array of type _Tp - class slice; // BLAS-like slice out of an array - template class slice_array; - class gslice; // generalized slice out of an array - template class gslice_array; - template class mask_array; // masked array - template class indirect_array; // indirected array - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @defgroup numeric_arrays Numeric Arrays - * @ingroup numerics - * - * Classes and functions for representing and manipulating arrays of elements. - * @{ - */ - - /** - * @brief Smart array designed to support numeric processing. - * - * A valarray is an array that provides constraints intended to allow for - * effective optimization of numeric array processing by reducing the - * aliasing that can result from pointer representations. It represents a - * one-dimensional array from which different multidimensional subsets can - * be accessed and modified. - * - * @tparam _Tp Type of object in the array. - */ - template - class valarray - { - template - struct _UnaryOp - { - typedef typename __fun<_Op, _Tp>::result_type __rt; - typedef _Expr<_UnClos<_Op, _ValArray, _Tp>, __rt> _Rt; - }; - public: - typedef _Tp value_type; - - // _lib.valarray.cons_ construct/destroy: - /// Construct an empty array. - valarray(); - - /// Construct an array with @a n elements. - explicit valarray(size_t); - - /// Construct an array with @a n elements initialized to @a t. - valarray(const _Tp&, size_t); - - /// Construct an array initialized to the first @a n elements of @a t. - valarray(const _Tp* __restrict__, size_t); - - /// Copy constructor. - valarray(const valarray&); - -#if __cplusplus >= 201103L - /// Move constructor. - valarray(valarray&&) noexcept; -#endif - - /// Construct an array with the same size and values in @a sa. - valarray(const slice_array<_Tp>&); - - /// Construct an array with the same size and values in @a ga. - valarray(const gslice_array<_Tp>&); - - /// Construct an array with the same size and values in @a ma. - valarray(const mask_array<_Tp>&); - - /// Construct an array with the same size and values in @a ia. - valarray(const indirect_array<_Tp>&); - -#if __cplusplus >= 201103L - /// Construct an array with an initializer_list of values. - valarray(initializer_list<_Tp>); -#endif - - template - valarray(const _Expr<_Dom, _Tp>& __e); - - ~valarray() _GLIBCXX_NOEXCEPT; - - // _lib.valarray.assign_ assignment: - /** - * @brief Assign elements to an array. - * - * Assign elements of array to values in @a v. - * - * @param __v Valarray to get values from. - */ - valarray<_Tp>& operator=(const valarray<_Tp>& __v); - -#if __cplusplus >= 201103L - /** - * @brief Move assign elements to an array. - * - * Move assign elements of array to values in @a v. - * - * @param __v Valarray to get values from. - */ - valarray<_Tp>& operator=(valarray<_Tp>&& __v) noexcept; -#endif - - /** - * @brief Assign elements to a value. - * - * Assign all elements of array to @a t. - * - * @param __t Value for elements. - */ - valarray<_Tp>& operator=(const _Tp& __t); - - /** - * @brief Assign elements to an array subset. - * - * Assign elements of array to values in @a sa. Results are undefined - * if @a sa does not have the same size as this array. - * - * @param __sa Array slice to get values from. - */ - valarray<_Tp>& operator=(const slice_array<_Tp>& __sa); - - /** - * @brief Assign elements to an array subset. - * - * Assign elements of array to values in @a ga. Results are undefined - * if @a ga does not have the same size as this array. - * - * @param __ga Array slice to get values from. - */ - valarray<_Tp>& operator=(const gslice_array<_Tp>& __ga); - - /** - * @brief Assign elements to an array subset. - * - * Assign elements of array to values in @a ma. Results are undefined - * if @a ma does not have the same size as this array. - * - * @param __ma Array slice to get values from. - */ - valarray<_Tp>& operator=(const mask_array<_Tp>& __ma); - - /** - * @brief Assign elements to an array subset. - * - * Assign elements of array to values in @a ia. Results are undefined - * if @a ia does not have the same size as this array. - * - * @param __ia Array slice to get values from. - */ - valarray<_Tp>& operator=(const indirect_array<_Tp>& __ia); - -#if __cplusplus >= 201103L - /** - * @brief Assign elements to an initializer_list. - * - * Assign elements of array to values in @a __l. Results are undefined - * if @a __l does not have the same size as this array. - * - * @param __l initializer_list to get values from. - */ - valarray& operator=(initializer_list<_Tp> __l); -#endif - - template valarray<_Tp>& - operator= (const _Expr<_Dom, _Tp>&); - - // _lib.valarray.access_ element access: - /** - * Return a reference to the i'th array element. - * - * @param __i Index of element to return. - * @return Reference to the i'th element. - */ - _Tp& operator[](size_t __i); - - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 389. Const overload of valarray::operator[] returns by value. - const _Tp& operator[](size_t) const; - - // _lib.valarray.sub_ subset operations: - /** - * @brief Return an array subset. - * - * Returns a new valarray containing the elements of the array - * indicated by the slice argument. The new valarray has the same size - * as the input slice. @see slice. - * - * @param __s The source slice. - * @return New valarray containing elements in @a __s. - */ - _Expr<_SClos<_ValArray, _Tp>, _Tp> operator[](slice __s) const; - - /** - * @brief Return a reference to an array subset. - * - * Returns a new valarray containing the elements of the array - * indicated by the slice argument. The new valarray has the same size - * as the input slice. @see slice. - * - * @param __s The source slice. - * @return New valarray containing elements in @a __s. - */ - slice_array<_Tp> operator[](slice __s); - - /** - * @brief Return an array subset. - * - * Returns a slice_array referencing the elements of the array - * indicated by the slice argument. @see gslice. - * - * @param __s The source slice. - * @return Slice_array referencing elements indicated by @a __s. - */ - _Expr<_GClos<_ValArray, _Tp>, _Tp> operator[](const gslice& __s) const; - - /** - * @brief Return a reference to an array subset. - * - * Returns a new valarray containing the elements of the array - * indicated by the gslice argument. The new valarray has - * the same size as the input gslice. @see gslice. - * - * @param __s The source gslice. - * @return New valarray containing elements in @a __s. - */ - gslice_array<_Tp> operator[](const gslice& __s); - - /** - * @brief Return an array subset. - * - * Returns a new valarray containing the elements of the array - * indicated by the argument. The input is a valarray of bool which - * represents a bitmask indicating which elements should be copied into - * the new valarray. Each element of the array is added to the return - * valarray if the corresponding element of the argument is true. - * - * @param __m The valarray bitmask. - * @return New valarray containing elements indicated by @a __m. - */ - valarray<_Tp> operator[](const valarray& __m) const; - - /** - * @brief Return a reference to an array subset. - * - * Returns a new mask_array referencing the elements of the array - * indicated by the argument. The input is a valarray of bool which - * represents a bitmask indicating which elements are part of the - * subset. Elements of the array are part of the subset if the - * corresponding element of the argument is true. - * - * @param __m The valarray bitmask. - * @return New valarray containing elements indicated by @a __m. - */ - mask_array<_Tp> operator[](const valarray& __m); - - /** - * @brief Return an array subset. - * - * Returns a new valarray containing the elements of the array - * indicated by the argument. The elements in the argument are - * interpreted as the indices of elements of this valarray to copy to - * the return valarray. - * - * @param __i The valarray element index list. - * @return New valarray containing elements in @a __s. - */ - _Expr<_IClos<_ValArray, _Tp>, _Tp> - operator[](const valarray& __i) const; - - /** - * @brief Return a reference to an array subset. - * - * Returns an indirect_array referencing the elements of the array - * indicated by the argument. The elements in the argument are - * interpreted as the indices of elements of this valarray to include - * in the subset. The returned indirect_array refers to these - * elements. - * - * @param __i The valarray element index list. - * @return Indirect_array referencing elements in @a __i. - */ - indirect_array<_Tp> operator[](const valarray& __i); - - // _lib.valarray.unary_ unary operators: - /// Return a new valarray by applying unary + to each element. - typename _UnaryOp<__unary_plus>::_Rt operator+() const; - - /// Return a new valarray by applying unary - to each element. - typename _UnaryOp<__negate>::_Rt operator-() const; - - /// Return a new valarray by applying unary ~ to each element. - typename _UnaryOp<__bitwise_not>::_Rt operator~() const; - - /// Return a new valarray by applying unary ! to each element. - typename _UnaryOp<__logical_not>::_Rt operator!() const; - - // _lib.valarray.cassign_ computed assignment: - /// Multiply each element of array by @a t. - valarray<_Tp>& operator*=(const _Tp&); - - /// Divide each element of array by @a t. - valarray<_Tp>& operator/=(const _Tp&); - - /// Set each element e of array to e % @a t. - valarray<_Tp>& operator%=(const _Tp&); - - /// Add @a t to each element of array. - valarray<_Tp>& operator+=(const _Tp&); - - /// Subtract @a t to each element of array. - valarray<_Tp>& operator-=(const _Tp&); - - /// Set each element e of array to e ^ @a t. - valarray<_Tp>& operator^=(const _Tp&); - - /// Set each element e of array to e & @a t. - valarray<_Tp>& operator&=(const _Tp&); - - /// Set each element e of array to e | @a t. - valarray<_Tp>& operator|=(const _Tp&); - - /// Left shift each element e of array by @a t bits. - valarray<_Tp>& operator<<=(const _Tp&); - - /// Right shift each element e of array by @a t bits. - valarray<_Tp>& operator>>=(const _Tp&); - - /// Multiply elements of array by corresponding elements of @a v. - valarray<_Tp>& operator*=(const valarray<_Tp>&); - - /// Divide elements of array by corresponding elements of @a v. - valarray<_Tp>& operator/=(const valarray<_Tp>&); - - /// Modulo elements of array by corresponding elements of @a v. - valarray<_Tp>& operator%=(const valarray<_Tp>&); - - /// Add corresponding elements of @a v to elements of array. - valarray<_Tp>& operator+=(const valarray<_Tp>&); - - /// Subtract corresponding elements of @a v from elements of array. - valarray<_Tp>& operator-=(const valarray<_Tp>&); - - /// Logical xor corresponding elements of @a v with elements of array. - valarray<_Tp>& operator^=(const valarray<_Tp>&); - - /// Logical or corresponding elements of @a v with elements of array. - valarray<_Tp>& operator|=(const valarray<_Tp>&); - - /// Logical and corresponding elements of @a v with elements of array. - valarray<_Tp>& operator&=(const valarray<_Tp>&); - - /// Left shift elements of array by corresponding elements of @a v. - valarray<_Tp>& operator<<=(const valarray<_Tp>&); - - /// Right shift elements of array by corresponding elements of @a v. - valarray<_Tp>& operator>>=(const valarray<_Tp>&); - - template - valarray<_Tp>& operator*=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator/=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator%=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator+=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator-=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator^=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator|=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator&=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator<<=(const _Expr<_Dom, _Tp>&); - template - valarray<_Tp>& operator>>=(const _Expr<_Dom, _Tp>&); - - // _lib.valarray.members_ member functions: -#if __cplusplus >= 201103L - /// Swap. - void swap(valarray<_Tp>& __v) noexcept; -#endif - - /// Return the number of elements in array. - size_t size() const; - - /** - * @brief Return the sum of all elements in the array. - * - * Accumulates the sum of all elements into a Tp using +=. The order - * of adding the elements is unspecified. - */ - _Tp sum() const; - - /// Return the minimum element using operator<(). - _Tp min() const; - - /// Return the maximum element using operator<(). - _Tp max() const; - - /** - * @brief Return a shifted array. - * - * A new valarray is constructed as a copy of this array with elements - * in shifted positions. For an element with index i, the new position - * is i - n. The new valarray has the same size as the current one. - * New elements without a value are set to 0. Elements whose new - * position is outside the bounds of the array are discarded. - * - * Positive arguments shift toward index 0, discarding elements [0, n). - * Negative arguments discard elements from the top of the array. - * - * @param __n Number of element positions to shift. - * @return New valarray with elements in shifted positions. - */ - valarray<_Tp> shift (int __n) const; - - /** - * @brief Return a rotated array. - * - * A new valarray is constructed as a copy of this array with elements - * in shifted positions. For an element with index i, the new position - * is (i - n) % size(). The new valarray has the same size as the - * current one. Elements that are shifted beyond the array bounds are - * shifted into the other end of the array. No elements are lost. - * - * Positive arguments shift toward index 0, wrapping around the top. - * Negative arguments shift towards the top, wrapping around to 0. - * - * @param __n Number of element positions to rotate. - * @return New valarray with elements in shifted positions. - */ - valarray<_Tp> cshift(int __n) const; - - /** - * @brief Apply a function to the array. - * - * Returns a new valarray with elements assigned to the result of - * applying func to the corresponding element of this array. The new - * array has the same size as this one. - * - * @param func Function of Tp returning Tp to apply. - * @return New valarray with transformed elements. - */ - _Expr<_ValFunClos<_ValArray, _Tp>, _Tp> apply(_Tp func(_Tp)) const; - - /** - * @brief Apply a function to the array. - * - * Returns a new valarray with elements assigned to the result of - * applying func to the corresponding element of this array. The new - * array has the same size as this one. - * - * @param func Function of const Tp& returning Tp to apply. - * @return New valarray with transformed elements. - */ - _Expr<_RefFunClos<_ValArray, _Tp>, _Tp> apply(_Tp func(const _Tp&)) const; - - /** - * @brief Resize array. - * - * Resize this array to @a size and set all elements to @a c. All - * references and iterators are invalidated. - * - * @param __size New array size. - * @param __c New value for all elements. - */ - void resize(size_t __size, _Tp __c = _Tp()); - - private: - size_t _M_size; - _Tp* __restrict__ _M_data; - - friend class _Array<_Tp>; - }; - -#if __cpp_deduction_guides >= 201606 - template - valarray(const _Tp(&)[_Nm], size_t) -> valarray<_Tp>; -#endif - - template - inline const _Tp& - valarray<_Tp>::operator[](size_t __i) const - { - __glibcxx_requires_subscript(__i); - return _M_data[__i]; - } - - template - inline _Tp& - valarray<_Tp>::operator[](size_t __i) - { - __glibcxx_requires_subscript(__i); - return _M_data[__i]; - } - - // @} group numeric_arrays - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#include -#include -#include -#include -#include -#include - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - - /** - * @addtogroup numeric_arrays - * @{ - */ - - template - inline - valarray<_Tp>::valarray() : _M_size(0), _M_data(0) {} - - template - inline - valarray<_Tp>::valarray(size_t __n) - : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) - { std::__valarray_default_construct(_M_data, _M_data + __n); } - - template - inline - valarray<_Tp>::valarray(const _Tp& __t, size_t __n) - : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) - { std::__valarray_fill_construct(_M_data, _M_data + __n, __t); } - - template - inline - valarray<_Tp>::valarray(const _Tp* __restrict__ __p, size_t __n) - : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) - { - __glibcxx_assert(__p != 0 || __n == 0); - std::__valarray_copy_construct(__p, __p + __n, _M_data); - } - - template - inline - valarray<_Tp>::valarray(const valarray<_Tp>& __v) - : _M_size(__v._M_size), _M_data(__valarray_get_storage<_Tp>(__v._M_size)) - { std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size, - _M_data); } - -#if __cplusplus >= 201103L - template - inline - valarray<_Tp>::valarray(valarray<_Tp>&& __v) noexcept - : _M_size(__v._M_size), _M_data(__v._M_data) - { - __v._M_size = 0; - __v._M_data = 0; - } -#endif - - template - inline - valarray<_Tp>::valarray(const slice_array<_Tp>& __sa) - : _M_size(__sa._M_sz), _M_data(__valarray_get_storage<_Tp>(__sa._M_sz)) - { - std::__valarray_copy_construct - (__sa._M_array, __sa._M_sz, __sa._M_stride, _Array<_Tp>(_M_data)); - } - - template - inline - valarray<_Tp>::valarray(const gslice_array<_Tp>& __ga) - : _M_size(__ga._M_index.size()), - _M_data(__valarray_get_storage<_Tp>(_M_size)) - { - std::__valarray_copy_construct - (__ga._M_array, _Array(__ga._M_index), - _Array<_Tp>(_M_data), _M_size); - } - - template - inline - valarray<_Tp>::valarray(const mask_array<_Tp>& __ma) - : _M_size(__ma._M_sz), _M_data(__valarray_get_storage<_Tp>(__ma._M_sz)) - { - std::__valarray_copy_construct - (__ma._M_array, __ma._M_mask, _Array<_Tp>(_M_data), _M_size); - } - - template - inline - valarray<_Tp>::valarray(const indirect_array<_Tp>& __ia) - : _M_size(__ia._M_sz), _M_data(__valarray_get_storage<_Tp>(__ia._M_sz)) - { - std::__valarray_copy_construct - (__ia._M_array, __ia._M_index, _Array<_Tp>(_M_data), _M_size); - } - -#if __cplusplus >= 201103L - template - inline - valarray<_Tp>::valarray(initializer_list<_Tp> __l) - : _M_size(__l.size()), _M_data(__valarray_get_storage<_Tp>(__l.size())) - { std::__valarray_copy_construct(__l.begin(), __l.end(), _M_data); } -#endif - - template template - inline - valarray<_Tp>::valarray(const _Expr<_Dom, _Tp>& __e) - : _M_size(__e.size()), _M_data(__valarray_get_storage<_Tp>(_M_size)) - { std::__valarray_copy_construct(__e, _M_size, _Array<_Tp>(_M_data)); } - - template - inline - valarray<_Tp>::~valarray() _GLIBCXX_NOEXCEPT - { - std::__valarray_destroy_elements(_M_data, _M_data + _M_size); - std::__valarray_release_memory(_M_data); - } - - template - inline valarray<_Tp>& - valarray<_Tp>::operator=(const valarray<_Tp>& __v) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 630. arrays of valarray. - if (_M_size == __v._M_size) - std::__valarray_copy(__v._M_data, _M_size, _M_data); - else - { - if (_M_data) - { - std::__valarray_destroy_elements(_M_data, _M_data + _M_size); - std::__valarray_release_memory(_M_data); - } - _M_size = __v._M_size; - _M_data = __valarray_get_storage<_Tp>(_M_size); - std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size, - _M_data); - } - return *this; - } - -#if __cplusplus >= 201103L - template - inline valarray<_Tp>& - valarray<_Tp>::operator=(valarray<_Tp>&& __v) noexcept - { - if (_M_data) - { - std::__valarray_destroy_elements(_M_data, _M_data + _M_size); - std::__valarray_release_memory(_M_data); - } - _M_size = __v._M_size; - _M_data = __v._M_data; - __v._M_size = 0; - __v._M_data = 0; - return *this; - } - - template - inline valarray<_Tp>& - valarray<_Tp>::operator=(initializer_list<_Tp> __l) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 630. arrays of valarray. - if (_M_size == __l.size()) - std::__valarray_copy(__l.begin(), __l.size(), _M_data); - else - { - if (_M_data) - { - std::__valarray_destroy_elements(_M_data, _M_data + _M_size); - std::__valarray_release_memory(_M_data); - } - _M_size = __l.size(); - _M_data = __valarray_get_storage<_Tp>(_M_size); - std::__valarray_copy_construct(__l.begin(), __l.begin() + _M_size, - _M_data); - } - return *this; - } -#endif - - template - inline valarray<_Tp>& - valarray<_Tp>::operator=(const _Tp& __t) - { - std::__valarray_fill(_M_data, _M_size, __t); - return *this; - } - - template - inline valarray<_Tp>& - valarray<_Tp>::operator=(const slice_array<_Tp>& __sa) - { - __glibcxx_assert(_M_size == __sa._M_sz); - std::__valarray_copy(__sa._M_array, __sa._M_sz, - __sa._M_stride, _Array<_Tp>(_M_data)); - return *this; - } - - template - inline valarray<_Tp>& - valarray<_Tp>::operator=(const gslice_array<_Tp>& __ga) - { - __glibcxx_assert(_M_size == __ga._M_index.size()); - std::__valarray_copy(__ga._M_array, _Array(__ga._M_index), - _Array<_Tp>(_M_data), _M_size); - return *this; - } - - template - inline valarray<_Tp>& - valarray<_Tp>::operator=(const mask_array<_Tp>& __ma) - { - __glibcxx_assert(_M_size == __ma._M_sz); - std::__valarray_copy(__ma._M_array, __ma._M_mask, - _Array<_Tp>(_M_data), _M_size); - return *this; - } - - template - inline valarray<_Tp>& - valarray<_Tp>::operator=(const indirect_array<_Tp>& __ia) - { - __glibcxx_assert(_M_size == __ia._M_sz); - std::__valarray_copy(__ia._M_array, __ia._M_index, - _Array<_Tp>(_M_data), _M_size); - return *this; - } - - template template - inline valarray<_Tp>& - valarray<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) - { - // _GLIBCXX_RESOLVE_LIB_DEFECTS - // 630. arrays of valarray. - if (_M_size == __e.size()) - std::__valarray_copy(__e, _M_size, _Array<_Tp>(_M_data)); - else - { - if (_M_data) - { - std::__valarray_destroy_elements(_M_data, _M_data + _M_size); - std::__valarray_release_memory(_M_data); - } - _M_size = __e.size(); - _M_data = __valarray_get_storage<_Tp>(_M_size); - std::__valarray_copy_construct(__e, _M_size, _Array<_Tp>(_M_data)); - } - return *this; - } - - template - inline _Expr<_SClos<_ValArray,_Tp>, _Tp> - valarray<_Tp>::operator[](slice __s) const - { - typedef _SClos<_ValArray,_Tp> _Closure; - return _Expr<_Closure, _Tp>(_Closure (_Array<_Tp>(_M_data), __s)); - } - - template - inline slice_array<_Tp> - valarray<_Tp>::operator[](slice __s) - { return slice_array<_Tp>(_Array<_Tp>(_M_data), __s); } - - template - inline _Expr<_GClos<_ValArray,_Tp>, _Tp> - valarray<_Tp>::operator[](const gslice& __gs) const - { - typedef _GClos<_ValArray,_Tp> _Closure; - return _Expr<_Closure, _Tp> - (_Closure(_Array<_Tp>(_M_data), __gs._M_index->_M_index)); - } - - template - inline gslice_array<_Tp> - valarray<_Tp>::operator[](const gslice& __gs) - { - return gslice_array<_Tp> - (_Array<_Tp>(_M_data), __gs._M_index->_M_index); - } - - template - inline valarray<_Tp> - valarray<_Tp>::operator[](const valarray& __m) const - { - size_t __s = 0; - size_t __e = __m.size(); - for (size_t __i=0; __i<__e; ++__i) - if (__m[__i]) ++__s; - return valarray<_Tp>(mask_array<_Tp>(_Array<_Tp>(_M_data), __s, - _Array (__m))); - } - - template - inline mask_array<_Tp> - valarray<_Tp>::operator[](const valarray& __m) - { - size_t __s = 0; - size_t __e = __m.size(); - for (size_t __i=0; __i<__e; ++__i) - if (__m[__i]) ++__s; - return mask_array<_Tp>(_Array<_Tp>(_M_data), __s, _Array(__m)); - } - - template - inline _Expr<_IClos<_ValArray,_Tp>, _Tp> - valarray<_Tp>::operator[](const valarray& __i) const - { - typedef _IClos<_ValArray,_Tp> _Closure; - return _Expr<_Closure, _Tp>(_Closure(*this, __i)); - } - - template - inline indirect_array<_Tp> - valarray<_Tp>::operator[](const valarray& __i) - { - return indirect_array<_Tp>(_Array<_Tp>(_M_data), __i.size(), - _Array(__i)); - } - -#if __cplusplus >= 201103L - template - inline void - valarray<_Tp>::swap(valarray<_Tp>& __v) noexcept - { - std::swap(_M_size, __v._M_size); - std::swap(_M_data, __v._M_data); - } -#endif - - template - inline size_t - valarray<_Tp>::size() const - { return _M_size; } - - template - inline _Tp - valarray<_Tp>::sum() const - { - __glibcxx_assert(_M_size > 0); - return std::__valarray_sum(_M_data, _M_data + _M_size); - } - - template - inline valarray<_Tp> - valarray<_Tp>::shift(int __n) const - { - valarray<_Tp> __ret; - - if (_M_size == 0) - return __ret; - - _Tp* __restrict__ __tmp_M_data = - std::__valarray_get_storage<_Tp>(_M_size); - - if (__n == 0) - std::__valarray_copy_construct(_M_data, - _M_data + _M_size, __tmp_M_data); - else if (__n > 0) // shift left - { - if (size_t(__n) > _M_size) - __n = int(_M_size); - - std::__valarray_copy_construct(_M_data + __n, - _M_data + _M_size, __tmp_M_data); - std::__valarray_default_construct(__tmp_M_data + _M_size - __n, - __tmp_M_data + _M_size); - } - else // shift right - { - if (-size_t(__n) > _M_size) - __n = -int(_M_size); - - std::__valarray_copy_construct(_M_data, _M_data + _M_size + __n, - __tmp_M_data - __n); - std::__valarray_default_construct(__tmp_M_data, - __tmp_M_data - __n); - } - - __ret._M_size = _M_size; - __ret._M_data = __tmp_M_data; - return __ret; - } - - template - inline valarray<_Tp> - valarray<_Tp>::cshift(int __n) const - { - valarray<_Tp> __ret; - - if (_M_size == 0) - return __ret; - - _Tp* __restrict__ __tmp_M_data = - std::__valarray_get_storage<_Tp>(_M_size); - - if (__n == 0) - std::__valarray_copy_construct(_M_data, - _M_data + _M_size, __tmp_M_data); - else if (__n > 0) // cshift left - { - if (size_t(__n) > _M_size) - __n = int(__n % _M_size); - - std::__valarray_copy_construct(_M_data, _M_data + __n, - __tmp_M_data + _M_size - __n); - std::__valarray_copy_construct(_M_data + __n, _M_data + _M_size, - __tmp_M_data); - } - else // cshift right - { - if (-size_t(__n) > _M_size) - __n = -int(-size_t(__n) % _M_size); - - std::__valarray_copy_construct(_M_data + _M_size + __n, - _M_data + _M_size, __tmp_M_data); - std::__valarray_copy_construct(_M_data, _M_data + _M_size + __n, - __tmp_M_data - __n); - } - - __ret._M_size = _M_size; - __ret._M_data = __tmp_M_data; - return __ret; - } - - template - inline void - valarray<_Tp>::resize(size_t __n, _Tp __c) - { - // This complication is so to make valarray > work - // even though it is not required by the standard. Nobody should - // be saying valarray > anyway. See the specs. - std::__valarray_destroy_elements(_M_data, _M_data + _M_size); - if (_M_size != __n) - { - std::__valarray_release_memory(_M_data); - _M_size = __n; - _M_data = __valarray_get_storage<_Tp>(__n); - } - std::__valarray_fill_construct(_M_data, _M_data + __n, __c); - } - - template - inline _Tp - valarray<_Tp>::min() const - { - __glibcxx_assert(_M_size > 0); - return *std::min_element(_M_data, _M_data + _M_size); - } - - template - inline _Tp - valarray<_Tp>::max() const - { - __glibcxx_assert(_M_size > 0); - return *std::max_element(_M_data, _M_data + _M_size); - } - - template - inline _Expr<_ValFunClos<_ValArray, _Tp>, _Tp> - valarray<_Tp>::apply(_Tp func(_Tp)) const - { - typedef _ValFunClos<_ValArray, _Tp> _Closure; - return _Expr<_Closure, _Tp>(_Closure(*this, func)); - } - - template - inline _Expr<_RefFunClos<_ValArray, _Tp>, _Tp> - valarray<_Tp>::apply(_Tp func(const _Tp &)) const - { - typedef _RefFunClos<_ValArray, _Tp> _Closure; - return _Expr<_Closure, _Tp>(_Closure(*this, func)); - } - -#define _DEFINE_VALARRAY_UNARY_OPERATOR(_Op, _Name) \ - template \ - inline typename valarray<_Tp>::template _UnaryOp<_Name>::_Rt \ - valarray<_Tp>::operator _Op() const \ - { \ - typedef _UnClos<_Name, _ValArray, _Tp> _Closure; \ - typedef typename __fun<_Name, _Tp>::result_type _Rt; \ - return _Expr<_Closure, _Rt>(_Closure(*this)); \ - } - - _DEFINE_VALARRAY_UNARY_OPERATOR(+, __unary_plus) - _DEFINE_VALARRAY_UNARY_OPERATOR(-, __negate) - _DEFINE_VALARRAY_UNARY_OPERATOR(~, __bitwise_not) - _DEFINE_VALARRAY_UNARY_OPERATOR (!, __logical_not) - -#undef _DEFINE_VALARRAY_UNARY_OPERATOR - -#define _DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(_Op, _Name) \ - template \ - inline valarray<_Tp>& \ - valarray<_Tp>::operator _Op##=(const _Tp &__t) \ - { \ - _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, __t); \ - return *this; \ - } \ - \ - template \ - inline valarray<_Tp>& \ - valarray<_Tp>::operator _Op##=(const valarray<_Tp> &__v) \ - { \ - __glibcxx_assert(_M_size == __v._M_size); \ - _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, \ - _Array<_Tp>(__v._M_data)); \ - return *this; \ - } - -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(+, __plus) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(-, __minus) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(*, __multiplies) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(/, __divides) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(%, __modulus) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(^, __bitwise_xor) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(&, __bitwise_and) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(|, __bitwise_or) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(<<, __shift_left) -_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(>>, __shift_right) - -#undef _DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT - -#define _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(_Op, _Name) \ - template template \ - inline valarray<_Tp>& \ - valarray<_Tp>::operator _Op##=(const _Expr<_Dom, _Tp>& __e) \ - { \ - _Array_augmented_##_Name(_Array<_Tp>(_M_data), __e, _M_size); \ - return *this; \ - } - -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(+, __plus) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(-, __minus) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(*, __multiplies) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(/, __divides) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(%, __modulus) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(^, __bitwise_xor) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(&, __bitwise_and) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(|, __bitwise_or) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(<<, __shift_left) -_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(>>, __shift_right) - -#undef _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT - - -#define _DEFINE_BINARY_OPERATOR(_Op, _Name) \ - template \ - inline _Expr<_BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp>, \ - typename __fun<_Name, _Tp>::result_type> \ - operator _Op(const valarray<_Tp>& __v, const valarray<_Tp>& __w) \ - { \ - __glibcxx_assert(__v.size() == __w.size()); \ - typedef _BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp> _Closure; \ - typedef typename __fun<_Name, _Tp>::result_type _Rt; \ - return _Expr<_Closure, _Rt>(_Closure(__v, __w)); \ - } \ - \ - template \ - inline _Expr<_BinClos<_Name, _ValArray,_Constant, _Tp, _Tp>, \ - typename __fun<_Name, _Tp>::result_type> \ - operator _Op(const valarray<_Tp>& __v, \ - const typename valarray<_Tp>::value_type& __t) \ - { \ - typedef _BinClos<_Name, _ValArray, _Constant, _Tp, _Tp> _Closure; \ - typedef typename __fun<_Name, _Tp>::result_type _Rt; \ - return _Expr<_Closure, _Rt>(_Closure(__v, __t)); \ - } \ - \ - template \ - inline _Expr<_BinClos<_Name, _Constant, _ValArray, _Tp, _Tp>, \ - typename __fun<_Name, _Tp>::result_type> \ - operator _Op(const typename valarray<_Tp>::value_type& __t, \ - const valarray<_Tp>& __v) \ - { \ - typedef _BinClos<_Name, _Constant, _ValArray, _Tp, _Tp> _Closure; \ - typedef typename __fun<_Name, _Tp>::result_type _Rt; \ - return _Expr<_Closure, _Rt>(_Closure(__t, __v)); \ - } - -_DEFINE_BINARY_OPERATOR(+, __plus) -_DEFINE_BINARY_OPERATOR(-, __minus) -_DEFINE_BINARY_OPERATOR(*, __multiplies) -_DEFINE_BINARY_OPERATOR(/, __divides) -_DEFINE_BINARY_OPERATOR(%, __modulus) -_DEFINE_BINARY_OPERATOR(^, __bitwise_xor) -_DEFINE_BINARY_OPERATOR(&, __bitwise_and) -_DEFINE_BINARY_OPERATOR(|, __bitwise_or) -_DEFINE_BINARY_OPERATOR(<<, __shift_left) -_DEFINE_BINARY_OPERATOR(>>, __shift_right) -_DEFINE_BINARY_OPERATOR(&&, __logical_and) -_DEFINE_BINARY_OPERATOR(||, __logical_or) -_DEFINE_BINARY_OPERATOR(==, __equal_to) -_DEFINE_BINARY_OPERATOR(!=, __not_equal_to) -_DEFINE_BINARY_OPERATOR(<, __less) -_DEFINE_BINARY_OPERATOR(>, __greater) -_DEFINE_BINARY_OPERATOR(<=, __less_equal) -_DEFINE_BINARY_OPERATOR(>=, __greater_equal) - -#undef _DEFINE_BINARY_OPERATOR - -#if __cplusplus >= 201103L - /** - * @brief Return an iterator pointing to the first element of - * the valarray. - * @param __va valarray. - */ - template - inline _Tp* - begin(valarray<_Tp>& __va) - { return std::__addressof(__va[0]); } - - /** - * @brief Return an iterator pointing to the first element of - * the const valarray. - * @param __va valarray. - */ - template - inline const _Tp* - begin(const valarray<_Tp>& __va) - { return std::__addressof(__va[0]); } - - /** - * @brief Return an iterator pointing to one past the last element of - * the valarray. - * @param __va valarray. - */ - template - inline _Tp* - end(valarray<_Tp>& __va) - { return std::__addressof(__va[0]) + __va.size(); } - - /** - * @brief Return an iterator pointing to one past the last element of - * the const valarray. - * @param __va valarray. - */ - template - inline const _Tp* - end(const valarray<_Tp>& __va) - { return std::__addressof(__va[0]) + __va.size(); } -#endif // C++11 - - // @} group numeric_arrays - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace - -#endif /* _GLIBCXX_VALARRAY */ diff --git a/resources/sources/avr-libstdcpp/include/variant b/resources/sources/avr-libstdcpp/include/variant deleted file mode 100644 index 3a0d1c1ce..000000000 --- a/resources/sources/avr-libstdcpp/include/variant +++ /dev/null @@ -1,1775 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2016-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file variant - * This is the C++ Library header. - */ - -#ifndef _GLIBCXX_VARIANT -#define _GLIBCXX_VARIANT 1 - -#pragma GCC system_header - -#if __cplusplus >= 201703L - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#if __cplusplus > 201703L -# include -#endif - -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -namespace __detail -{ -namespace __variant -{ - template - struct _Nth_type; - - template - struct _Nth_type<_Np, _First, _Rest...> - : _Nth_type<_Np-1, _Rest...> { }; - - template - struct _Nth_type<0, _First, _Rest...> - { using type = _First; }; - -} // namespace __variant -} // namespace __detail - -#define __cpp_lib_variant 201606L - - template class tuple; - template class variant; - template struct hash; - - template - struct variant_size; - - template - struct variant_size : variant_size<_Variant> {}; - - template - struct variant_size : variant_size<_Variant> {}; - - template - struct variant_size : variant_size<_Variant> {}; - - template - struct variant_size> - : std::integral_constant {}; - - template - inline constexpr size_t variant_size_v = variant_size<_Variant>::value; - - template - struct variant_alternative; - - template - struct variant_alternative<_Np, variant<_First, _Rest...>> - : variant_alternative<_Np-1, variant<_Rest...>> {}; - - template - struct variant_alternative<0, variant<_First, _Rest...>> - { using type = _First; }; - - template - using variant_alternative_t = - typename variant_alternative<_Np, _Variant>::type; - - template - struct variant_alternative<_Np, const _Variant> - { using type = add_const_t>; }; - - template - struct variant_alternative<_Np, volatile _Variant> - { using type = add_volatile_t>; }; - - template - struct variant_alternative<_Np, const volatile _Variant> - { using type = add_cv_t>; }; - - inline constexpr size_t variant_npos = -1; - - template - constexpr variant_alternative_t<_Np, variant<_Types...>>& - get(variant<_Types...>&); - - template - constexpr variant_alternative_t<_Np, variant<_Types...>>&& - get(variant<_Types...>&&); - - template - constexpr variant_alternative_t<_Np, variant<_Types...>> const& - get(const variant<_Types...>&); - - template - constexpr variant_alternative_t<_Np, variant<_Types...>> const&& - get(const variant<_Types...>&&); - - template - constexpr decltype(auto) - __do_visit(_Visitor&& __visitor, _Variants&&... __variants); - - template - decltype(auto) - __variant_cast(_Tp&& __rhs) - { - if constexpr (is_lvalue_reference_v<_Tp>) - { - if constexpr (is_const_v>) - return static_cast&>(__rhs); - else - return static_cast&>(__rhs); - } - else - return static_cast&&>(__rhs); - } - -namespace __detail -{ -namespace __variant -{ - // Returns the first appearence of _Tp in _Types. - // Returns sizeof...(_Types) if _Tp is not in _Types. - template - struct __index_of : std::integral_constant {}; - - template - inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value; - - template - struct __index_of<_Tp, _First, _Rest...> : - std::integral_constant - ? 0 : __index_of_v<_Tp, _Rest...> + 1> {}; - - // used for raw visitation - struct __variant_cookie {}; - // used for raw visitation with indices passed in - struct __variant_idx_cookie { using type = __variant_idx_cookie; }; - // Used to enable deduction (and same-type checking) for std::visit: - template struct __deduce_visit_result { }; - - // Visit variants that might be valueless. - template - constexpr void - __raw_visit(_Visitor&& __visitor, _Variants&&... __variants) - { - std::__do_visit<__variant_cookie>(std::forward<_Visitor>(__visitor), - std::forward<_Variants>(__variants)...); - } - - // Visit variants that might be valueless, passing indices to the visitor. - template - constexpr void - __raw_idx_visit(_Visitor&& __visitor, _Variants&&... __variants) - { - std::__do_visit<__variant_idx_cookie>(std::forward<_Visitor>(__visitor), - std::forward<_Variants>(__variants)...); - } - - // _Uninitialized is guaranteed to be a trivially destructible type, - // even if T is not. - template> - struct _Uninitialized; - - template - struct _Uninitialized<_Type, true> - { - template - constexpr - _Uninitialized(in_place_index_t<0>, _Args&&... __args) - : _M_storage(std::forward<_Args>(__args)...) - { } - - constexpr const _Type& _M_get() const & noexcept - { return _M_storage; } - - constexpr _Type& _M_get() & noexcept - { return _M_storage; } - - constexpr const _Type&& _M_get() const && noexcept - { return std::move(_M_storage); } - - constexpr _Type&& _M_get() && noexcept - { return std::move(_M_storage); } - - _Type _M_storage; - }; - - template - struct _Uninitialized<_Type, false> - { - template - constexpr - _Uninitialized(in_place_index_t<0>, _Args&&... __args) - { - ::new ((void*)std::addressof(_M_storage)) - _Type(std::forward<_Args>(__args)...); - } - - const _Type& _M_get() const & noexcept - { return *_M_storage._M_ptr(); } - - _Type& _M_get() & noexcept - { return *_M_storage._M_ptr(); } - - const _Type&& _M_get() const && noexcept - { return std::move(*_M_storage._M_ptr()); } - - _Type&& _M_get() && noexcept - { return std::move(*_M_storage._M_ptr()); } - - __gnu_cxx::__aligned_membuf<_Type> _M_storage; - }; - - template - constexpr decltype(auto) - __get(in_place_index_t<0>, _Union&& __u) noexcept - { return std::forward<_Union>(__u)._M_first._M_get(); } - - template - constexpr decltype(auto) - __get(in_place_index_t<_Np>, _Union&& __u) noexcept - { - return __variant::__get(in_place_index<_Np-1>, - std::forward<_Union>(__u)._M_rest); - } - - // Returns the typed storage for __v. - template - constexpr decltype(auto) - __get(_Variant&& __v) noexcept - { - return __variant::__get(std::in_place_index<_Np>, - std::forward<_Variant>(__v)._M_u); - } - - template - struct _Traits - { - static constexpr bool _S_default_ctor = - is_default_constructible_v::type>; - static constexpr bool _S_copy_ctor = - (is_copy_constructible_v<_Types> && ...); - static constexpr bool _S_move_ctor = - (is_move_constructible_v<_Types> && ...); - static constexpr bool _S_copy_assign = - _S_copy_ctor - && (is_copy_assignable_v<_Types> && ...); - static constexpr bool _S_move_assign = - _S_move_ctor - && (is_move_assignable_v<_Types> && ...); - - static constexpr bool _S_trivial_dtor = - (is_trivially_destructible_v<_Types> && ...); - static constexpr bool _S_trivial_copy_ctor = - (is_trivially_copy_constructible_v<_Types> && ...); - static constexpr bool _S_trivial_move_ctor = - (is_trivially_move_constructible_v<_Types> && ...); - static constexpr bool _S_trivial_copy_assign = - _S_trivial_dtor && _S_trivial_copy_ctor - && (is_trivially_copy_assignable_v<_Types> && ...); - static constexpr bool _S_trivial_move_assign = - _S_trivial_dtor && _S_trivial_move_ctor - && (is_trivially_move_assignable_v<_Types> && ...); - - // The following nothrow traits are for non-trivial SMFs. Trivial SMFs - // are always nothrow. - static constexpr bool _S_nothrow_default_ctor = - is_nothrow_default_constructible_v< - typename _Nth_type<0, _Types...>::type>; - static constexpr bool _S_nothrow_copy_ctor = false; - static constexpr bool _S_nothrow_move_ctor = - (is_nothrow_move_constructible_v<_Types> && ...); - static constexpr bool _S_nothrow_copy_assign = false; - static constexpr bool _S_nothrow_move_assign = - _S_nothrow_move_ctor - && (is_nothrow_move_assignable_v<_Types> && ...); - }; - - // Defines members and ctors. - template - union _Variadic_union { }; - - template - union _Variadic_union<_First, _Rest...> - { - constexpr _Variadic_union() : _M_rest() { } - - template - constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args) - : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) - { } - - template - constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) - : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) - { } - - _Uninitialized<_First> _M_first; - _Variadic_union<_Rest...> _M_rest; - }; - - // _Never_valueless_alt is true for variant alternatives that can - // always be placed in a variant without it becoming valueless. - - // For suitably-small, trivially copyable types we can create temporaries - // on the stack and then memcpy them into place. - template - struct _Never_valueless_alt - : __and_, is_trivially_copyable<_Tp>> - { }; - - // Specialize _Never_valueless_alt for other types which have a - // non-throwing and cheap move construction and move assignment operator, - // so that emplacing the type will provide the strong exception-safety - // guarantee, by creating and moving a temporary. - // Whether _Never_valueless_alt is true or not affects the ABI of a - // variant using that alternative, so we can't change the value later! - - // True if every alternative in _Types... can be emplaced in a variant - // without it becoming valueless. If this is true, variant<_Types...> - // can never be valueless, which enables some minor optimizations. - template - constexpr bool __never_valueless() - { - return _Traits<_Types...>::_S_move_assign - && (_Never_valueless_alt<_Types>::value && ...); - } - - // Defines index and the dtor, possibly trivial. - template - struct _Variant_storage; - - template - using __select_index = - typename __select_int::_Select_int_base::type::value_type; - - template - struct _Variant_storage - { - constexpr - _Variant_storage() - : _M_index(static_cast<__index_type>(variant_npos)) - { } - - template - constexpr - _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) - : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), - _M_index{_Np} - { } - - void _M_reset() - { - if (!_M_valid()) [[unlikely]] - return; - - std::__do_visit([](auto&& __this_mem) mutable - { - std::_Destroy(std::__addressof(__this_mem)); - }, __variant_cast<_Types...>(*this)); - - _M_index = static_cast<__index_type>(variant_npos); - } - - ~_Variant_storage() - { _M_reset(); } - - void* - _M_storage() const noexcept - { - return const_cast(static_cast( - std::addressof(_M_u))); - } - - constexpr bool - _M_valid() const noexcept - { - if constexpr (__variant::__never_valueless<_Types...>()) - return true; - return this->_M_index != __index_type(variant_npos); - } - - _Variadic_union<_Types...> _M_u; - using __index_type = __select_index<_Types...>; - __index_type _M_index; - }; - - template - struct _Variant_storage - { - constexpr - _Variant_storage() - : _M_index(static_cast<__index_type>(variant_npos)) - { } - - template - constexpr - _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) - : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), - _M_index{_Np} - { } - - void _M_reset() noexcept - { _M_index = static_cast<__index_type>(variant_npos); } - - void* - _M_storage() const noexcept - { - return const_cast(static_cast( - std::addressof(_M_u))); - } - - constexpr bool - _M_valid() const noexcept - { - if constexpr (__variant::__never_valueless<_Types...>()) - return true; - return this->_M_index != static_cast<__index_type>(variant_npos); - } - - _Variadic_union<_Types...> _M_u; - using __index_type = __select_index<_Types...>; - __index_type _M_index; - }; - - template - using _Variant_storage_alias = - _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>; - - template - void __variant_construct_single(_Tp&& __lhs, _Up&& __rhs_mem) - { - void* __storage = std::addressof(__lhs._M_u); - using _Type = remove_reference_t; - if constexpr (!is_same_v<_Type, __variant_cookie>) - ::new (__storage) - _Type(std::forward(__rhs_mem)); - } - - template - void __variant_construct(_Tp&& __lhs, _Up&& __rhs) - { - __lhs._M_index = __rhs._M_index; - __variant::__raw_visit([&__lhs](auto&& __rhs_mem) mutable - { - __variant_construct_single(std::forward<_Tp>(__lhs), - std::forward(__rhs_mem)); - }, __variant_cast<_Types...>(std::forward<_Up>(__rhs))); - } - - // The following are (Copy|Move) (ctor|assign) layers for forwarding - // triviality and handling non-trivial SMF behaviors. - - template - struct _Copy_ctor_base : _Variant_storage_alias<_Types...> - { - using _Base = _Variant_storage_alias<_Types...>; - using _Base::_Base; - - _Copy_ctor_base(const _Copy_ctor_base& __rhs) - noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor) - { - __variant_construct<_Types...>(*this, __rhs); - } - - _Copy_ctor_base(_Copy_ctor_base&&) = default; - _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default; - _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default; - }; - - template - struct _Copy_ctor_base : _Variant_storage_alias<_Types...> - { - using _Base = _Variant_storage_alias<_Types...>; - using _Base::_Base; - }; - - template - using _Copy_ctor_alias = - _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>; - - template - struct _Move_ctor_base : _Copy_ctor_alias<_Types...> - { - using _Base = _Copy_ctor_alias<_Types...>; - using _Base::_Base; - - _Move_ctor_base(_Move_ctor_base&& __rhs) - noexcept(_Traits<_Types...>::_S_nothrow_move_ctor) - { - __variant_construct<_Types...>(*this, std::move(__rhs)); - } - - template - void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs) - { - this->_M_reset(); - __variant_construct_single(*this, std::forward<_Up>(__rhs)); - this->_M_index = __rhs_index; - } - - template - void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs) - { - this->_M_reset(); - __variant_construct_single(*this, __rhs); - this->_M_index = __rhs_index; - } - - _Move_ctor_base(const _Move_ctor_base&) = default; - _Move_ctor_base& operator=(const _Move_ctor_base&) = default; - _Move_ctor_base& operator=(_Move_ctor_base&&) = default; - }; - - template - struct _Move_ctor_base : _Copy_ctor_alias<_Types...> - { - using _Base = _Copy_ctor_alias<_Types...>; - using _Base::_Base; - - template - void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs) - { - this->_M_reset(); - __variant_construct_single(*this, std::forward<_Up>(__rhs)); - this->_M_index = __rhs_index; - } - - template - void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs) - { - this->_M_reset(); - __variant_construct_single(*this, __rhs); - this->_M_index = __rhs_index; - } - }; - - template - using _Move_ctor_alias = - _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>; - - template - struct _Copy_assign_base : _Move_ctor_alias<_Types...> - { - using _Base = _Move_ctor_alias<_Types...>; - using _Base::_Base; - - _Copy_assign_base& - operator=(const _Copy_assign_base& __rhs) - noexcept(_Traits<_Types...>::_S_nothrow_copy_assign) - { - __variant::__raw_idx_visit( - [this](auto&& __rhs_mem, auto __rhs_index) mutable - { - if constexpr (__rhs_index != variant_npos) - { - if (this->_M_index == __rhs_index) - __variant::__get<__rhs_index>(*this) = __rhs_mem; - else - { - using __rhs_type = __remove_cvref_t; - if constexpr (is_nothrow_copy_constructible_v<__rhs_type> - || !is_nothrow_move_constructible_v<__rhs_type>) - // The standard says this->emplace<__rhs_type>(__rhs_mem) - // should be used here, but _M_destructive_copy is - // equivalent in this case. Either copy construction - // doesn't throw, so _M_destructive_copy gives strong - // exception safety guarantee, or both copy construction - // and move construction can throw, so emplace only gives - // basic exception safety anyway. - this->_M_destructive_copy(__rhs_index, __rhs_mem); - else - __variant_cast<_Types...>(*this) - = variant<_Types...>(std::in_place_index<__rhs_index>, - __rhs_mem); - } - } - else - this->_M_reset(); - }, __variant_cast<_Types...>(__rhs)); - return *this; - } - - _Copy_assign_base(const _Copy_assign_base&) = default; - _Copy_assign_base(_Copy_assign_base&&) = default; - _Copy_assign_base& operator=(_Copy_assign_base&&) = default; - }; - - template - struct _Copy_assign_base : _Move_ctor_alias<_Types...> - { - using _Base = _Move_ctor_alias<_Types...>; - using _Base::_Base; - }; - - template - using _Copy_assign_alias = - _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, _Types...>; - - template - struct _Move_assign_base : _Copy_assign_alias<_Types...> - { - using _Base = _Copy_assign_alias<_Types...>; - using _Base::_Base; - - _Move_assign_base& - operator=(_Move_assign_base&& __rhs) - noexcept(_Traits<_Types...>::_S_nothrow_move_assign) - { - __variant::__raw_idx_visit( - [this](auto&& __rhs_mem, auto __rhs_index) mutable - { - if constexpr (__rhs_index != variant_npos) - { - if (this->_M_index == __rhs_index) - __variant::__get<__rhs_index>(*this) = std::move(__rhs_mem); - else - __variant_cast<_Types...>(*this) - .template emplace<__rhs_index>(std::move(__rhs_mem)); - } - else - this->_M_reset(); - }, __variant_cast<_Types...>(__rhs)); - return *this; - } - - _Move_assign_base(const _Move_assign_base&) = default; - _Move_assign_base(_Move_assign_base&&) = default; - _Move_assign_base& operator=(const _Move_assign_base&) = default; - }; - - template - struct _Move_assign_base : _Copy_assign_alias<_Types...> - { - using _Base = _Copy_assign_alias<_Types...>; - using _Base::_Base; - }; - - template - using _Move_assign_alias = - _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>; - - template - struct _Variant_base : _Move_assign_alias<_Types...> - { - using _Base = _Move_assign_alias<_Types...>; - - constexpr - _Variant_base() - noexcept(_Traits<_Types...>::_S_nothrow_default_ctor) - : _Variant_base(in_place_index<0>) { } - - template - constexpr explicit - _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args) - : _Base(__i, std::forward<_Args>(__args)...) - { } - - _Variant_base(const _Variant_base&) = default; - _Variant_base(_Variant_base&&) = default; - _Variant_base& operator=(const _Variant_base&) = default; - _Variant_base& operator=(_Variant_base&&) = default; - }; - - // For how many times does _Tp appear in _Tuple? - template - struct __tuple_count; - - template - inline constexpr size_t __tuple_count_v = - __tuple_count<_Tp, _Tuple>::value; - - template - struct __tuple_count<_Tp, tuple<_Types...>> - : integral_constant { }; - - template - struct __tuple_count<_Tp, tuple<_First, _Rest...>> - : integral_constant< - size_t, - __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { }; - - // TODO: Reuse this in ? - template - inline constexpr bool __exactly_once = - __tuple_count_v<_Tp, tuple<_Types...>> == 1; - - // Helper used to check for valid conversions that don't involve narrowing. - template struct _Arr { _Ti _M_x[1]; }; - - // Build an imaginary function FUN(Ti) for each alternative type Ti - template, bool>, - typename = void> - struct _Build_FUN - { - // This function means 'using _Build_FUN::_S_fun;' is valid, - // but only static functions will be considered in the call below. - void _S_fun(); - }; - - // ... for which Ti x[] = {std::forward(t)}; is well-formed, - template - struct _Build_FUN<_Ind, _Tp, _Ti, false, - void_t{{std::declval<_Tp>()}})>> - { - // This is the FUN function for type _Ti, with index _Ind - static integral_constant _S_fun(_Ti); - }; - - // ... and if Ti is cv bool, remove_cvref_t is bool. - template - struct _Build_FUN<_Ind, _Tp, _Ti, true, - enable_if_t, bool>>> - { - // This is the FUN function for when _Ti is cv bool, with index _Ind - static integral_constant _S_fun(_Ti); - }; - - template>> - struct _Build_FUNs; - - template - struct _Build_FUNs<_Tp, variant<_Ti...>, index_sequence<_Ind...>> - : _Build_FUN<_Ind, _Tp, _Ti>... - { - using _Build_FUN<_Ind, _Tp, _Ti>::_S_fun...; - }; - - // The index j of the overload FUN(Tj) selected by overload resolution - // for FUN(std::forward<_Tp>(t)) - template - using _FUN_type - = decltype(_Build_FUNs<_Tp, _Variant>::_S_fun(std::declval<_Tp>())); - - // The index selected for FUN(std::forward(t)), or variant_npos if none. - template - struct __accepted_index - : integral_constant - { }; - - template - struct __accepted_index<_Tp, _Variant, void_t<_FUN_type<_Tp, _Variant>>> - : _FUN_type<_Tp, _Variant> - { }; - - // Returns the raw storage for __v. - template - void* __get_storage(_Variant&& __v) noexcept - { return __v._M_storage(); } - - template - struct _Extra_visit_slot_needed - { - template struct _Variant_never_valueless; - - template - struct _Variant_never_valueless> - : bool_constant<__variant::__never_valueless<_Types...>()> {}; - - static constexpr bool value = - (is_same_v<_Maybe_variant_cookie, __variant_cookie> - || is_same_v<_Maybe_variant_cookie, __variant_idx_cookie>) - && !_Variant_never_valueless<__remove_cvref_t<_Variant>>::value; - }; - - // Used for storing a multi-dimensional vtable. - template - struct _Multi_array; - - // Partial specialization with rank zero, stores a single _Tp element. - template - struct _Multi_array<_Tp> - { - template - struct __untag_result - : false_type - { using element_type = _Tp; }; - - template - struct __untag_result - : false_type - { using element_type = void(*)(_Args...); }; - - template - struct __untag_result<__variant_cookie(*)(_Args...)> - : false_type - { using element_type = void(*)(_Args...); }; - - template - struct __untag_result<__variant_idx_cookie(*)(_Args...)> - : false_type - { using element_type = void(*)(_Args...); }; - - template - struct __untag_result<__deduce_visit_result<_Res>(*)(_Args...)> - : true_type - { using element_type = _Res(*)(_Args...); }; - - using __result_is_deduced = __untag_result<_Tp>; - - constexpr const typename __untag_result<_Tp>::element_type& - _M_access() const - { return _M_data; } - - typename __untag_result<_Tp>::element_type _M_data; - }; - - // Partial specialization with rank >= 1. - template - struct _Multi_array<_Ret(*)(_Visitor, _Variants...), __first, __rest...> - { - static constexpr size_t __index = - sizeof...(_Variants) - sizeof...(__rest) - 1; - - using _Variant = typename _Nth_type<__index, _Variants...>::type; - - static constexpr int __do_cookie = - _Extra_visit_slot_needed<_Ret, _Variant>::value ? 1 : 0; - - using _Tp = _Ret(*)(_Visitor, _Variants...); - - template - constexpr decltype(auto) - _M_access(size_t __first_index, _Args... __rest_indices) const - { - return _M_arr[__first_index + __do_cookie] - ._M_access(__rest_indices...); - } - - _Multi_array<_Tp, __rest...> _M_arr[__first + __do_cookie]; - }; - - // Creates a multi-dimensional vtable recursively. - // - // For example, - // visit([](auto, auto){}, - // variant(), // typedef'ed as V1 - // variant()) // typedef'ed as V2 - // will trigger instantiations of: - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<>> - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<0>> - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<0, 0>> - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<0, 1>> - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<0, 2>> - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<1>> - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<1, 0>> - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<1, 1>> - // __gen_vtable_impl<_Multi_array, - // tuple, std::index_sequence<1, 2>> - // The returned multi-dimensional vtable can be fast accessed by the visitor - // using index calculation. - template - struct __gen_vtable_impl; - - // Defines the _S_apply() member that returns a _Multi_array populated - // with function pointers that perform the visitation expressions e(m) - // for each valid pack of indexes into the variant types _Variants. - // - // This partial specialization builds up the index sequences by recursively - // calling _S_apply() on the next specialization of __gen_vtable_impl. - // The base case of the recursion defines the actual function pointers. - template - struct __gen_vtable_impl< - _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>, - std::index_sequence<__indices...>> - { - using _Next = - remove_reference_t::type>; - using _Array_type = - _Multi_array<_Result_type (*)(_Visitor, _Variants...), - __dimensions...>; - - static constexpr _Array_type - _S_apply() - { - _Array_type __vtable{}; - _S_apply_all_alts( - __vtable, make_index_sequence>()); - return __vtable; - } - - template - static constexpr void - _S_apply_all_alts(_Array_type& __vtable, - std::index_sequence<__var_indices...>) - { - if constexpr (_Extra_visit_slot_needed<_Result_type, _Next>::value) - (_S_apply_single_alt( - __vtable._M_arr[__var_indices + 1], - &(__vtable._M_arr[0])), ...); - else - (_S_apply_single_alt( - __vtable._M_arr[__var_indices]), ...); - } - - template - static constexpr void - _S_apply_single_alt(_Tp& __element, _Tp* __cookie_element = nullptr) - { - if constexpr (__do_cookie) - { - __element = __gen_vtable_impl< - _Tp, - std::index_sequence<__indices..., __index>>::_S_apply(); - *__cookie_element = __gen_vtable_impl< - _Tp, - std::index_sequence<__indices..., variant_npos>>::_S_apply(); - } - else - { - __element = __gen_vtable_impl< - remove_reference_t, - std::index_sequence<__indices..., __index>>::_S_apply(); - } - } - }; - - // This partial specialization is the base case for the recursion. - // It populates a _Multi_array element with the address of a function - // that invokes the visitor with the alternatives specified by __indices. - template - struct __gen_vtable_impl< - _Multi_array<_Result_type (*)(_Visitor, _Variants...)>, - std::index_sequence<__indices...>> - { - using _Array_type = - _Multi_array<_Result_type (*)(_Visitor, _Variants...)>; - - template - static constexpr decltype(auto) - __element_by_index_or_cookie(_Variant&& __var) noexcept - { - if constexpr (__index != variant_npos) - return __variant::__get<__index>(std::forward<_Variant>(__var)); - else - return __variant_cookie{}; - } - - static constexpr decltype(auto) - __visit_invoke(_Visitor&& __visitor, _Variants... __vars) - { - if constexpr (is_same_v<_Result_type, __variant_idx_cookie>) - // For raw visitation using indices, pass the indices to the visitor - // and discard the return value: - std::__invoke(std::forward<_Visitor>(__visitor), - __element_by_index_or_cookie<__indices>( - std::forward<_Variants>(__vars))..., - integral_constant()...); - else if constexpr (is_same_v<_Result_type, __variant_cookie>) - // For raw visitation without indices, and discard the return value: - std::__invoke(std::forward<_Visitor>(__visitor), - __element_by_index_or_cookie<__indices>( - std::forward<_Variants>(__vars))...); - else if constexpr (_Array_type::__result_is_deduced::value) - // For the usual std::visit case deduce the return value: - return std::__invoke(std::forward<_Visitor>(__visitor), - __element_by_index_or_cookie<__indices>( - std::forward<_Variants>(__vars))...); - else // for std::visit use INVOKE - return std::__invoke_r<_Result_type>( - std::forward<_Visitor>(__visitor), - __variant::__get<__indices>(std::forward<_Variants>(__vars))...); - } - - static constexpr auto - _S_apply() - { return _Array_type{&__visit_invoke}; } - }; - - template - struct __gen_vtable - { - using _Array_type = - _Multi_array<_Result_type (*)(_Visitor, _Variants...), - variant_size_v>...>; - - static constexpr _Array_type _S_vtable - = __gen_vtable_impl<_Array_type, std::index_sequence<>>::_S_apply(); - }; - - template - struct _Base_dedup : public _Tp { }; - - template - struct _Variant_hash_base; - - template - struct _Variant_hash_base, - std::index_sequence<__indices...>> - : _Base_dedup<__indices, __poison_hash>>... { }; - -} // namespace __variant -} // namespace __detail - - template - void __variant_construct_by_index(_Variant& __v, _Args&&... __args) - { - __v._M_index = _Np; - auto&& __storage = __detail::__variant::__get<_Np>(__v); - ::new ((void*)std::addressof(__storage)) - remove_reference_t - (std::forward<_Args>(__args)...); - } - - template - constexpr bool - holds_alternative(const variant<_Types...>& __v) noexcept - { - static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, - "T must occur exactly once in alternatives"); - return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>; - } - - template - constexpr _Tp& get(variant<_Types...>& __v) - { - static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, - "T must occur exactly once in alternatives"); - static_assert(!is_void_v<_Tp>, "_Tp must not be void"); - return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); - } - - template - constexpr _Tp&& get(variant<_Types...>&& __v) - { - static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, - "T must occur exactly once in alternatives"); - static_assert(!is_void_v<_Tp>, "_Tp must not be void"); - return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( - std::move(__v)); - } - - template - constexpr const _Tp& get(const variant<_Types...>& __v) - { - static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, - "T must occur exactly once in alternatives"); - static_assert(!is_void_v<_Tp>, "_Tp must not be void"); - return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); - } - - template - constexpr const _Tp&& get(const variant<_Types...>&& __v) - { - static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, - "T must occur exactly once in alternatives"); - static_assert(!is_void_v<_Tp>, "_Tp must not be void"); - return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( - std::move(__v)); - } - - template - constexpr add_pointer_t>> - get_if(variant<_Types...>* __ptr) noexcept - { - using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; - static_assert(_Np < sizeof...(_Types), - "The index must be in [0, number of alternatives)"); - static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void"); - if (__ptr && __ptr->index() == _Np) - return std::addressof(__detail::__variant::__get<_Np>(*__ptr)); - return nullptr; - } - - template - constexpr - add_pointer_t>> - get_if(const variant<_Types...>* __ptr) noexcept - { - using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; - static_assert(_Np < sizeof...(_Types), - "The index must be in [0, number of alternatives)"); - static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void"); - if (__ptr && __ptr->index() == _Np) - return std::addressof(__detail::__variant::__get<_Np>(*__ptr)); - return nullptr; - } - - template - constexpr add_pointer_t<_Tp> - get_if(variant<_Types...>* __ptr) noexcept - { - static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, - "T must occur exactly once in alternatives"); - static_assert(!is_void_v<_Tp>, "_Tp must not be void"); - return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( - __ptr); - } - - template - constexpr add_pointer_t - get_if(const variant<_Types...>* __ptr) noexcept - { - static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, - "T must occur exactly once in alternatives"); - static_assert(!is_void_v<_Tp>, "_Tp must not be void"); - return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( - __ptr); - } - - struct monostate { }; - -#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ - template \ - constexpr bool operator __OP(const variant<_Types...>& __lhs, \ - const variant<_Types...>& __rhs) \ - { \ - bool __ret = true; \ - __detail::__variant::__raw_idx_visit( \ - [&__ret, &__lhs] (auto&& __rhs_mem, auto __rhs_index) mutable \ - { \ - if constexpr (__rhs_index != variant_npos) \ - { \ - if (__lhs.index() == __rhs_index) \ - { \ - auto& __this_mem = std::get<__rhs_index>(__lhs); \ - __ret = __this_mem __OP __rhs_mem; \ - } \ - else \ - __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ - } \ - else \ - __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ - }, __rhs); \ - return __ret; \ - } - - _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) - _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) - _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) - _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) - _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) - _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) - -#undef _VARIANT_RELATION_FUNCTION_TEMPLATE - - constexpr bool operator==(monostate, monostate) noexcept { return true; } - -#ifdef __cpp_lib_three_way_comparison - template - requires (three_way_comparable<_Types> && ...) - constexpr - common_comparison_category_t...> - operator<=>(const variant<_Types...>& __v, const variant<_Types...>& __w) - { - common_comparison_category_t...> __ret - = strong_ordering::equal; - - __detail::__variant::__raw_idx_visit( - [&__ret, &__v] (auto&& __w_mem, auto __w_index) mutable - { - if constexpr (__w_index != variant_npos) - { - if (__v.index() == __w_index) - { - auto& __this_mem = std::get<__w_index>(__v); - __ret = __this_mem <=> __w_mem; - return; - } - } - __ret = (__v.index() + 1) <=> (__w_index + 1); - }, __w); - return __ret; - } - - constexpr strong_ordering - operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; } -#else - constexpr bool operator!=(monostate, monostate) noexcept { return false; } - constexpr bool operator<(monostate, monostate) noexcept { return false; } - constexpr bool operator>(monostate, monostate) noexcept { return false; } - constexpr bool operator<=(monostate, monostate) noexcept { return true; } - constexpr bool operator>=(monostate, monostate) noexcept { return true; } -#endif - - template - constexpr decltype(auto) visit(_Visitor&&, _Variants&&...); - - template - inline enable_if_t<(is_move_constructible_v<_Types> && ...) - && (is_swappable_v<_Types> && ...)> - swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs) - noexcept(noexcept(__lhs.swap(__rhs))) - { __lhs.swap(__rhs); } - - template - enable_if_t && ...) - && (is_swappable_v<_Types> && ...))> - swap(variant<_Types...>&, variant<_Types...>&) = delete; - - inline void - __throw_bad_variant_access(bool __valueless __attribute__((unused))) - { - __throw_bad_variant_access(""); - } - - template - class variant - : private __detail::__variant::_Variant_base<_Types...>, - private _Enable_default_constructor< - __detail::__variant::_Traits<_Types...>::_S_default_ctor, - variant<_Types...>>, - private _Enable_copy_move< - __detail::__variant::_Traits<_Types...>::_S_copy_ctor, - __detail::__variant::_Traits<_Types...>::_S_copy_assign, - __detail::__variant::_Traits<_Types...>::_S_move_ctor, - __detail::__variant::_Traits<_Types...>::_S_move_assign, - variant<_Types...>> - { - private: - template - friend decltype(auto) __variant_cast(_Tp&&); - template - friend void __variant_construct_by_index(_Variant& __v, - _Args&&... __args); - - static_assert(sizeof...(_Types) > 0, - "variant must have at least one alternative"); - static_assert(!(std::is_reference_v<_Types> || ...), - "variant must have no reference alternative"); - static_assert(!(std::is_void_v<_Types> || ...), - "variant must have no void alternative"); - - using _Base = __detail::__variant::_Variant_base<_Types...>; - using _Default_ctor_enabler = - _Enable_default_constructor< - __detail::__variant::_Traits<_Types...>::_S_default_ctor, - variant<_Types...>>; - - template - static constexpr bool __not_self - = !is_same_v<__remove_cvref_t<_Tp>, variant>; - - template - static constexpr bool - __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>; - - template - static constexpr size_t __accepted_index - = __detail::__variant::__accepted_index<_Tp, variant>::value; - - template> - using __to_type = variant_alternative_t<_Np, variant>; - - template>> - using __accepted_type = __to_type<__accepted_index<_Tp>>; - - template - static constexpr size_t __index_of = - __detail::__variant::__index_of_v<_Tp, _Types...>; - - using _Traits = __detail::__variant::_Traits<_Types...>; - - template - struct __is_in_place_tag : false_type { }; - template - struct __is_in_place_tag> : true_type { }; - template - struct __is_in_place_tag> : true_type { }; - - template - static constexpr bool __not_in_place_tag - = !__is_in_place_tag<__remove_cvref_t<_Tp>>::value; - - public: - variant() = default; - variant(const variant& __rhs) = default; - variant(variant&&) = default; - variant& operator=(const variant&) = default; - variant& operator=(variant&&) = default; - ~variant() = default; - - template, - typename = enable_if_t<__not_in_place_tag<_Tp>>, - typename _Tj = __accepted_type<_Tp&&>, - typename = enable_if_t<__exactly_once<_Tj> - && is_constructible_v<_Tj, _Tp>>> - constexpr - variant(_Tp&& __t) - noexcept(is_nothrow_constructible_v<_Tj, _Tp>) - : variant(in_place_index<__accepted_index<_Tp>>, - std::forward<_Tp>(__t)) - { } - - template - && is_constructible_v<_Tp, _Args...>>> - constexpr explicit - variant(in_place_type_t<_Tp>, _Args&&... __args) - : variant(in_place_index<__index_of<_Tp>>, - std::forward<_Args>(__args)...) - { } - - template - && is_constructible_v<_Tp, - initializer_list<_Up>&, _Args...>>> - constexpr explicit - variant(in_place_type_t<_Tp>, initializer_list<_Up> __il, - _Args&&... __args) - : variant(in_place_index<__index_of<_Tp>>, __il, - std::forward<_Args>(__args)...) - { } - - template, - typename = enable_if_t>> - constexpr explicit - variant(in_place_index_t<_Np>, _Args&&... __args) - : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...), - _Default_ctor_enabler(_Enable_default_constructor_tag{}) - { } - - template, - typename = enable_if_t&, - _Args...>>> - constexpr explicit - variant(in_place_index_t<_Np>, initializer_list<_Up> __il, - _Args&&... __args) - : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...), - _Default_ctor_enabler(_Enable_default_constructor_tag{}) - { } - - template - enable_if_t<__exactly_once<__accepted_type<_Tp&&>> - && is_constructible_v<__accepted_type<_Tp&&>, _Tp> - && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>, - variant&> - operator=(_Tp&& __rhs) - noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp> - && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>) - { - constexpr auto __index = __accepted_index<_Tp>; - if (index() == __index) - std::get<__index>(*this) = std::forward<_Tp>(__rhs); - else - { - using _Tj = __accepted_type<_Tp&&>; - if constexpr (is_nothrow_constructible_v<_Tj, _Tp> - || !is_nothrow_move_constructible_v<_Tj>) - this->emplace<__index>(std::forward<_Tp>(__rhs)); - else - operator=(variant(std::forward<_Tp>(__rhs))); - } - return *this; - } - - template - enable_if_t && __exactly_once<_Tp>, - _Tp&> - emplace(_Args&&... __args) - { - constexpr size_t __index = __index_of<_Tp>; - return this->emplace<__index>(std::forward<_Args>(__args)...); - } - - template - enable_if_t&, _Args...> - && __exactly_once<_Tp>, - _Tp&> - emplace(initializer_list<_Up> __il, _Args&&... __args) - { - constexpr size_t __index = __index_of<_Tp>; - return this->emplace<__index>(__il, std::forward<_Args>(__args)...); - } - - template - enable_if_t, - _Args...>, - variant_alternative_t<_Np, variant>&> - emplace(_Args&&... __args) - { - static_assert(_Np < sizeof...(_Types), - "The index must be in [0, number of alternatives)"); - using type = variant_alternative_t<_Np, variant>; - // Provide the strong exception-safety guarantee when possible, - // to avoid becoming valueless. - if constexpr (is_nothrow_constructible_v) - { - this->_M_reset(); - __variant_construct_by_index<_Np>(*this, - std::forward<_Args>(__args)...); - } - else if constexpr (is_scalar_v) - { - // This might invoke a potentially-throwing conversion operator: - const type __tmp(std::forward<_Args>(__args)...); - // But these steps won't throw: - this->_M_reset(); - __variant_construct_by_index<_Np>(*this, __tmp); - } - else if constexpr (__detail::__variant::_Never_valueless_alt() - && _Traits::_S_move_assign) - { - // This construction might throw: - variant __tmp(in_place_index<_Np>, - std::forward<_Args>(__args)...); - // But _Never_valueless_alt means this won't: - *this = std::move(__tmp); - } - else - { - // This case only provides the basic exception-safety guarantee, - // i.e. the variant can become valueless. - this->_M_reset(); - __try - { - __variant_construct_by_index<_Np>(*this, - std::forward<_Args>(__args)...); - } - __catch (...) - { - this->_M_index = variant_npos; - __throw_exception_again; - } - } - return std::get<_Np>(*this); - } - - template - enable_if_t, - initializer_list<_Up>&, _Args...>, - variant_alternative_t<_Np, variant>&> - emplace(initializer_list<_Up> __il, _Args&&... __args) - { - static_assert(_Np < sizeof...(_Types), - "The index must be in [0, number of alternatives)"); - using type = variant_alternative_t<_Np, variant>; - // Provide the strong exception-safety guarantee when possible, - // to avoid becoming valueless. - if constexpr (is_nothrow_constructible_v&, - _Args...>) - { - this->_M_reset(); - __variant_construct_by_index<_Np>(*this, __il, - std::forward<_Args>(__args)...); - } - else if constexpr (__detail::__variant::_Never_valueless_alt() - && _Traits::_S_move_assign) - { - // This construction might throw: - variant __tmp(in_place_index<_Np>, __il, - std::forward<_Args>(__args)...); - // But _Never_valueless_alt means this won't: - *this = std::move(__tmp); - } - else - { - // This case only provides the basic exception-safety guarantee, - // i.e. the variant can become valueless. - this->_M_reset(); - __try - { - __variant_construct_by_index<_Np>(*this, __il, - std::forward<_Args>(__args)...); - } - __catch (...) - { - this->_M_index = variant_npos; - __throw_exception_again; - } - } - return std::get<_Np>(*this); - } - - constexpr bool valueless_by_exception() const noexcept - { return !this->_M_valid(); } - - constexpr size_t index() const noexcept - { - using __index_type = typename _Base::__index_type; - if constexpr (__detail::__variant::__never_valueless<_Types...>()) - return this->_M_index; - else if constexpr (sizeof...(_Types) <= __index_type(-1) / 2) - return make_signed_t<__index_type>(this->_M_index); - else - return size_t(__index_type(this->_M_index + 1)) - 1; - } - - void - swap(variant& __rhs) - noexcept((__is_nothrow_swappable<_Types>::value && ...) - && is_nothrow_move_constructible_v) - { - __detail::__variant::__raw_idx_visit( - [this, &__rhs](auto&& __rhs_mem, auto __rhs_index) mutable - { - if constexpr (__rhs_index != variant_npos) - { - if (this->index() == __rhs_index) - { - auto& __this_mem = - std::get<__rhs_index>(*this); - using std::swap; - swap(__this_mem, __rhs_mem); - } - else - { - if (!this->valueless_by_exception()) [[__likely__]] - { - auto __tmp(std::move(__rhs_mem)); - __rhs = std::move(*this); - this->_M_destructive_move(__rhs_index, - std::move(__tmp)); - } - else - { - this->_M_destructive_move(__rhs_index, - std::move(__rhs_mem)); - __rhs._M_reset(); - } - } - } - else - { - if (!this->valueless_by_exception()) [[__likely__]] - { - __rhs = std::move(*this); - this->_M_reset(); - } - } - }, __rhs); - } - - private: - -#if defined(__clang__) && __clang_major__ <= 7 - public: - using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852 - private: -#endif - - template - friend constexpr decltype(auto) - __detail::__variant::__get(_Vp&& __v) noexcept; - - template - friend void* - __detail::__variant::__get_storage(_Vp&& __v) noexcept; - -#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \ - template \ - friend constexpr bool \ - operator __OP(const variant<_Tp...>& __lhs, \ - const variant<_Tp...>& __rhs); - - _VARIANT_RELATION_FUNCTION_TEMPLATE(<) - _VARIANT_RELATION_FUNCTION_TEMPLATE(<=) - _VARIANT_RELATION_FUNCTION_TEMPLATE(==) - _VARIANT_RELATION_FUNCTION_TEMPLATE(!=) - _VARIANT_RELATION_FUNCTION_TEMPLATE(>=) - _VARIANT_RELATION_FUNCTION_TEMPLATE(>) - -#undef _VARIANT_RELATION_FUNCTION_TEMPLATE - }; - - template - constexpr variant_alternative_t<_Np, variant<_Types...>>& - get(variant<_Types...>& __v) - { - static_assert(_Np < sizeof...(_Types), - "The index must be in [0, number of alternatives)"); - if (__v.index() != _Np) - __throw_bad_variant_access(__v.valueless_by_exception()); - return __detail::__variant::__get<_Np>(__v); - } - - template - constexpr variant_alternative_t<_Np, variant<_Types...>>&& - get(variant<_Types...>&& __v) - { - static_assert(_Np < sizeof...(_Types), - "The index must be in [0, number of alternatives)"); - if (__v.index() != _Np) - __throw_bad_variant_access(__v.valueless_by_exception()); - return __detail::__variant::__get<_Np>(std::move(__v)); - } - - template - constexpr const variant_alternative_t<_Np, variant<_Types...>>& - get(const variant<_Types...>& __v) - { - static_assert(_Np < sizeof...(_Types), - "The index must be in [0, number of alternatives)"); - if (__v.index() != _Np) - __throw_bad_variant_access(__v.valueless_by_exception()); - return __detail::__variant::__get<_Np>(__v); - } - - template - constexpr const variant_alternative_t<_Np, variant<_Types...>>&& - get(const variant<_Types...>&& __v) - { - static_assert(_Np < sizeof...(_Types), - "The index must be in [0, number of alternatives)"); - if (__v.index() != _Np) - __throw_bad_variant_access(__v.valueless_by_exception()); - return __detail::__variant::__get<_Np>(std::move(__v)); - } - - template - constexpr decltype(auto) - __do_visit(_Visitor&& __visitor, _Variants&&... __variants) - { - constexpr auto& __vtable = __detail::__variant::__gen_vtable< - _Result_type, _Visitor&&, _Variants&&...>::_S_vtable; - - auto __func_ptr = __vtable._M_access(__variants.index()...); - return (*__func_ptr)(std::forward<_Visitor>(__visitor), - std::forward<_Variants>(__variants)...); - } - - template - constexpr decltype(auto) - visit(_Visitor&& __visitor, _Variants&&... __variants) - { - if ((__variants.valueless_by_exception() || ...)) - __throw_bad_variant_access("std::visit: variant is valueless"); - - using _Result_type = std::invoke_result_t<_Visitor, - decltype(std::get<0>(std::declval<_Variants>()))...>; - - using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>; - - return std::__do_visit<_Tag>(std::forward<_Visitor>(__visitor), - std::forward<_Variants>(__variants)...); - } - -#if __cplusplus > 201703L - template - constexpr _Res - visit(_Visitor&& __visitor, _Variants&&... __variants) - { - if ((__variants.valueless_by_exception() || ...)) - __throw_bad_variant_access("std::visit: variant is valueless"); - - return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor), - std::forward<_Variants>(__variants)...); - } -#endif - - template - struct __variant_hash_call_base_impl - { - size_t - operator()(const variant<_Types...>& __t) const - noexcept((is_nothrow_invocable_v>, _Types> && ...)) - { - size_t __ret; - __detail::__variant::__raw_visit( - [&__t, &__ret](auto&& __t_mem) mutable - { - using _Type = __remove_cvref_t; - if constexpr (!is_same_v<_Type, - __detail::__variant::__variant_cookie>) - __ret = std::hash{}(__t.index()) - + std::hash<_Type>{}(__t_mem); - else - __ret = std::hash{}(__t.index()); - }, __t); - return __ret; - } - }; - - template - struct __variant_hash_call_base_impl {}; - - template - using __variant_hash_call_base = - __variant_hash_call_base_impl<(__poison_hash>:: - __enable_hash_call &&...), _Types...>; - - template - struct hash> - : private __detail::__variant::_Variant_hash_base< - variant<_Types...>, std::index_sequence_for<_Types...>>, - public __variant_hash_call_base<_Types...> - { - using result_type [[__deprecated__]] = size_t; - using argument_type [[__deprecated__]] = variant<_Types...>; - }; - - template<> - struct hash - { - using result_type [[__deprecated__]] = size_t; - using argument_type [[__deprecated__]] = monostate; - - size_t - operator()(const monostate&) const noexcept - { - constexpr size_t __magic_monostate_hash = -7777; - return __magic_monostate_hash; - } - }; - - template - struct __is_fast_hash>> - : bool_constant<(__is_fast_hash<_Types>::value && ...)> - { }; - -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std - -#endif // C++17 - -#endif // _GLIBCXX_VARIANT diff --git a/resources/sources/avr-libstdcpp/include/vector b/resources/sources/avr-libstdcpp/include/vector deleted file mode 100644 index 6f587a82a..000000000 --- a/resources/sources/avr-libstdcpp/include/vector +++ /dev/null @@ -1,129 +0,0 @@ -// -*- C++ -*- - -// Copyright (C) 2001-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/* - * - * Copyright (c) 1994 - * Hewlett-Packard Company - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Hewlett-Packard Company makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - * - * - * Copyright (c) 1996 - * Silicon Graphics Computer Systems, Inc. - * - * Permission to use, copy, modify, distribute and sell this software - * and its documentation for any purpose is hereby granted without fee, - * provided that the above copyright notice appear in all copies and - * that both that copyright notice and this permission notice appear - * in supporting documentation. Silicon Graphics makes no - * representations about the suitability of this software for any - * purpose. It is provided "as is" without express or implied warranty. - */ - -/** @file include/vector - * This is a Standard C++ Library header. - */ - -#ifndef _GLIBCXX_VECTOR -#define _GLIBCXX_VECTOR 1 - -#pragma GCC system_header - -#include -#if __cplusplus > 201703L -# include // For remove and remove_if -#endif // C++20 -#include -#include -#include -#include -#include -#include - -#ifndef _GLIBCXX_EXPORT_TEMPLATE -# include -#endif - -#ifdef _GLIBCXX_DEBUG -# include -#endif - -#if __cplusplus >= 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - namespace pmr { - template class polymorphic_allocator; - template - using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>; - } // namespace pmr -# ifdef _GLIBCXX_DEBUG - namespace _GLIBCXX_STD_C::pmr { - template - using vector - = _GLIBCXX_STD_C::vector<_Tp, std::pmr::polymorphic_allocator<_Tp>>; - } // namespace _GLIBCXX_STD_C::pmr -# endif -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++17 - -#if __cplusplus > 201703L -namespace std _GLIBCXX_VISIBILITY(default) -{ -_GLIBCXX_BEGIN_NAMESPACE_VERSION - -#define __cpp_lib_erase_if 202002L - - template - inline typename vector<_Tp, _Alloc>::size_type - erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred) - { - const auto __osz = __cont.size(); - __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred), - __cont.end()); - return __osz - __cont.size(); - } - - template - inline typename vector<_Tp, _Alloc>::size_type - erase(vector<_Tp, _Alloc>& __cont, const _Up& __value) - { - const auto __osz = __cont.size(); - __cont.erase(std::remove(__cont.begin(), __cont.end(), __value), - __cont.end()); - return __osz - __cont.size(); - } -_GLIBCXX_END_NAMESPACE_VERSION -} // namespace std -#endif // C++20 - -#endif /* _GLIBCXX_VECTOR */ diff --git a/resources/sources/avr-libstdcpp/include/version b/resources/sources/avr-libstdcpp/include/version deleted file mode 100644 index 1e98be3ce..000000000 --- a/resources/sources/avr-libstdcpp/include/version +++ /dev/null @@ -1,231 +0,0 @@ -// -*- C++ -*- Libstdc++ version details header. - -// Copyright (C) 2018-2020 Free Software Foundation, Inc. -// -// This file is part of the GNU ISO C++ Library. This library is free -// software; you can redistribute it and/or modify it under the -// terms of the GNU General Public License as published by the -// Free Software Foundation; either version 3, or (at your option) -// any later version. - -// This library is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. - -// Under Section 7 of GPL version 3, you are granted additional -// permissions described in the GCC Runtime Library Exception, version -// 3.1, as published by the Free Software Foundation. - -// You should have received a copy of the GNU General Public License and -// a copy of the GCC Runtime Library Exception along with this program; -// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -// . - -/** @file version - * This is a Standard C++ Library file. You should @c \#include this file - * in your programs, rather than any of the @a *.h implementation files. - */ - -#ifndef _GLIBCXX_VERSION_INCLUDED -#define _GLIBCXX_VERSION_INCLUDED - -#pragma GCC system_header - -#include - -// c++03 -#if _GLIBCXX_HOSTED -# define __cpp_lib_incomplete_container_elements 201505 -#endif - -#if !defined(__STRICT_ANSI__) -// gnu++03 -# define __cpp_lib_uncaught_exceptions 201411L -#endif - -#if __cplusplus >= 201103L -// c++11 -#define __cpp_lib_is_null_pointer 201309 -#define __cpp_lib_result_of_sfinae 201210 - -#if _GLIBCXX_HOSTED -# define __cpp_lib_allocator_traits_is_always_equal 201411 -# define __cpp_lib_shared_ptr_arrays 201611L -#endif - -#if !defined(__STRICT_ANSI__) -// gnu++11 -# define __cpp_lib_is_swappable 201603 -# define __cpp_lib_void_t 201411 -# if _GLIBCXX_HOSTED -# define __cpp_lib_enable_shared_from_this 201603 -# endif -#endif - -// For C++11 and later we support ISO/IEC 29124 Mathematical Special Functions -#define __STDCPP_MATH_SPEC_FUNCS__ 201003L - -#if __cplusplus >= 201402L -// c++14 -#if __cpp_impl_coroutine -# define __cpp_lib_coroutine 201902L -#endif -#define __cpp_lib_integral_constant_callable 201304 -#define __cpp_lib_is_final 201402L -#define __cpp_lib_transformation_trait_aliases 201304 - -#if _GLIBCXX_HOSTED -# define __cpp_lib_chrono_udls 201304 -# define __cpp_lib_complex_udls 201309 -# define __cpp_lib_exchange_function 201304 -# define __cpp_lib_generic_associative_lookup 201304 -# define __cpp_lib_integer_sequence 201304 -# define __cpp_lib_make_reverse_iterator 201402 -# define __cpp_lib_make_unique 201304 -# ifndef _GLIBCXX_DEBUG // PR libstdc++/70303 -# define __cpp_lib_null_iterators 201304L -# endif -# define __cpp_lib_quoted_string_io 201304 -# define __cpp_lib_robust_nonmodifying_seq_ops 201304 -# ifdef _GLIBCXX_HAS_GTHREADS -# define __cpp_lib_shared_timed_mutex 201402 -# endif -# define __cpp_lib_string_udls 201304 -# define __cpp_lib_transparent_operators 201510 -# define __cpp_lib_tuple_element_t 201402L -# define __cpp_lib_tuples_by_type 201304 -#endif - -#if __cplusplus >= 201703L -// c++17 -#define __cpp_lib_addressof_constexpr 201603 -#define __cpp_lib_atomic_is_always_lock_free 201603 -#define __cpp_lib_bool_constant 201505 -#define __cpp_lib_byte 201603 -#ifdef _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP -# define __cpp_lib_has_unique_object_representations 201606 -#endif -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE -# define __cpp_lib_is_aggregate 201703 -#endif -#define __cpp_lib_is_invocable 201703 -#define __cpp_lib_is_swappable 201603 -#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER -# define __cpp_lib_launder 201606 -#endif -#define __cpp_lib_logical_traits 201510 -#define __cpp_lib_type_trait_variable_templates 201510L -#define __cpp_lib_uncaught_exceptions 201411L -#define __cpp_lib_void_t 201411 - -#if _GLIBCXX_HOSTED -#define __cpp_lib_any 201606L -#define __cpp_lib_apply 201603 -#define __cpp_lib_array_constexpr 201803L -#define __cpp_lib_as_const 201510 -#define __cpp_lib_boyer_moore_searcher 201603 -#define __cpp_lib_chrono 201611 -#define __cpp_lib_clamp 201603 -#define __cpp_lib_constexpr_char_traits 201611 -#define __cpp_lib_enable_shared_from_this 201603 -#define __cpp_lib_execution 201902L // FIXME: should be 201603L -#define __cpp_lib_filesystem 201703 -#define __cpp_lib_gcd 201606 -#define __cpp_lib_gcd_lcm 201606 -#define __cpp_lib_hypot 201603 -#define __cpp_lib_invoke 201411L -#define __cpp_lib_lcm 201606 -#define __cpp_lib_make_from_tuple 201606 -#define __cpp_lib_map_try_emplace 201411 -#define __cpp_lib_math_special_functions 201603L -#ifdef _GLIBCXX_HAS_GTHREADS -# define __cpp_lib_memory_resource 201603 -#else -# define __cpp_lib_memory_resource 1 -#endif -#define __cpp_lib_node_extract 201606 -#define __cpp_lib_nonmember_container_access 201411 -#define __cpp_lib_not_fn 201603 -#define __cpp_lib_optional 201606L -#define __cpp_lib_raw_memory_algorithms 201606L -#define __cpp_lib_sample 201603 -#ifdef _GLIBCXX_HAS_GTHREADS -# define __cpp_lib_scoped_lock 201703 -# define __cpp_lib_shared_mutex 201505 -#endif -#define __cpp_lib_shared_ptr_weak_type 201606 -#define __cpp_lib_string_view 201803L -// #define __cpp_lib_to_chars 201611L -#define __cpp_lib_unordered_map_try_emplace 201411 -#define __cpp_lib_variant 201606L -#endif - -#if __cplusplus > 201703L -// c++2a -#define __cpp_lib_atomic_float 201711L -#define __cpp_lib_atomic_ref 201806L -#define __cpp_lib_atomic_value_initialization 201911L -#define __cpp_lib_bitops 201907L -#define __cpp_lib_bounded_array_traits 201902L -// __cpp_lib_char8_t is defined in -#if __cpp_concepts >= 201907L -# define __cpp_lib_concepts 202002L -#endif -#if __cpp_impl_destroying_delete -# define __cpp_lib_destroying_delete 201806L -#endif -#define __cpp_lib_endian 201907L -#define __cpp_lib_int_pow2 202002L -#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED -# define __cpp_lib_is_constant_evaluated 201811L -#endif -#define __cpp_lib_is_nothrow_convertible 201806L -#define __cpp_lib_remove_cvref 201711L -#if __cpp_impl_three_way_comparison >= 201907L && __cpp_lib_concepts -# define __cpp_lib_three_way_comparison 201907L -#endif -#define __cpp_lib_type_identity 201806L -#define __cpp_lib_unwrap_ref 201811L - -#if _GLIBCXX_HOSTED -#undef __cpp_lib_array_constexpr -#define __cpp_lib_array_constexpr 201811L -#define __cpp_lib_assume_aligned 201811L -#define __cpp_lib_bind_front 201907L -// FIXME: #define __cpp_lib_execution 201902L -#define __cpp_lib_integer_comparison_functions 202002L -#define __cpp_lib_constexpr_algorithms 201806L -#define __cpp_lib_constexpr_complex 201711L -#define __cpp_lib_constexpr_dynamic_alloc 201907L -#define __cpp_lib_constexpr_functional 201907L -# define __cpp_lib_constexpr_iterator 201811L -#define __cpp_lib_constexpr_memory 201811L -#define __cpp_lib_constexpr_numeric 201911L -#define __cpp_lib_constexpr_string_view 201811L -#define __cpp_lib_constexpr_tuple 201811L -#define __cpp_lib_constexpr_utility 201811L -#define __cpp_lib_erase_if 202002L -#define __cpp_lib_interpolate 201902L -#ifdef _GLIBCXX_HAS_GTHREADS -# define __cpp_lib_jthread 201911L -#endif -#define __cpp_lib_list_remove_return_type 201806L -#define __cpp_lib_math_constants 201907L -#define __cpp_lib_polymorphic_allocator 201902L -#if __cpp_lib_concepts -# define __cpp_lib_ranges 201911L -#endif -#define __cpp_lib_shift 201806L -#define __cpp_lib_span 202002L -#define __cpp_lib_ssize 201902L -#define __cpp_lib_starts_ends_with 201711L -#define __cpp_lib_to_address 201711L -#define __cpp_lib_to_array 201907L -#endif -#endif // C++2a -#endif // C++17 -#endif // C++14 -#endif // C++11 - -#endif // _GLIBCXX_VERSION_INCLUDED diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index be269a3f2..1a96c3dc1 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -972,7 +972,7 @@ class CompilerModule { // Add avr-libstdcpp headers so STruC++ runtime compiles on AVR targets. const avrLibStdCppPath = join(this.sourceDirectoryPath, 'avr-libstdcpp', 'include') if (boardHalsContent['core']?.startsWith('arduino:avr')) { - cxxFlags.push(`-isystem "${avrLibStdCppPath}"`) + cxxFlags.push(`-I "${avrLibStdCppPath}"`) } buildProjectFlags = [ ...buildProjectFlags, From d0e9284f8e98c838a25817a9b9f3e41b8b08fdad Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Wed, 15 Apr 2026 00:34:19 -0400 Subject: [PATCH 027/296] fix: complete AVR compilation support for STruC++ Editor-side fixes for successful Arduino Mega compilation: Baremetal.ino: - #undef Arduino macros (min/max/abs/round/TIMER*) before STruC++ includes - Include openplc.h before generated.hpp to avoid IEC type ambiguity - Use ::IEC_BOOL etc. (global scope) in casts to disambiguate from strucpp:: - Configuration_CONFIG0 (STruC++ uppercases configuration names) - Define I/O buffer arrays (previously in MatIEC glueVars.c) - Provide sized operator delete stub (AVR virtual destructors need it) - Define __CURRENT_TIME_NS global for STruC++ time operations - Renamed to Baremetal.ino (Arduino requires filename = directory name) openplc.h: - Wrap HAL functions in extern "C" for proper C/C++ linkage avr-libstdcpp: - Add make_unsigned/make_signed, common_type to type_traits - Add std::nullptr_t to cstddef - Add strtoll/strtoull stubs to cstdlib (AVR libc lacks 64-bit strtol) - Add missing C functions to cstring and cstdlib - Add abs/trunc/log10 overloads to cmath compiler-module.ts: - Use -I (not -isystem) for avr-libstdcpp (GCC 7.3 treats -isystem as C linkage) Bump strucpp to v0.2.8 (AVR runtime header compatibility). Co-Authored-By: Claude Opus 4.6 (1M context) --- binary-versions.json | 2 +- .../sources/StrucppBaremetal/Baremetal.ino | 74 +++++++++++++++---- resources/sources/arduino/openplc.h | 8 +- resources/sources/avr-libstdcpp/include/cmath | 9 ++- .../sources/avr-libstdcpp/include/cstddef | 7 +- .../sources/avr-libstdcpp/include/cstdlib | 17 ++++- .../sources/avr-libstdcpp/include/cstring | 1 + .../sources/avr-libstdcpp/include/type_traits | 42 +++++++++++ 8 files changed, 141 insertions(+), 19 deletions(-) diff --git a/binary-versions.json b/binary-versions.json index 5ad810810..68fdab108 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -4,7 +4,7 @@ "repository": "Autonomy-Logic/xml2st" }, "strucpp": { - "version": "v0.2.7", + "version": "v0.2.8", "repository": "Autonomy-Logic/STruCpp" } } diff --git a/resources/sources/StrucppBaremetal/Baremetal.ino b/resources/sources/StrucppBaremetal/Baremetal.ino index 27f4edf60..117c67981 100644 --- a/resources/sources/StrucppBaremetal/Baremetal.ino +++ b/resources/sources/StrucppBaremetal/Baremetal.ino @@ -7,15 +7,40 @@ // - Computes GCD of task intervals for the scan cycle base tick // - Schedules programs round-robin with per-task divisors -// Arduino.h defines min/max as macros which conflict with std::min/std::max -// and numeric_limits::min()/max(). Undefine them before including STruC++ headers. +// Arduino.h defines several macros that conflict with C++ standard library +// and STruC++ runtime headers. Undefine them before including anything. #undef min #undef max - -#include "generated.hpp" +#undef abs +#undef round +// Arduino timer macros conflict with user variable names (STruC++ uppercases identifiers) +#undef TIMER0A +#undef TIMER0B +#undef TIMER1A +#undef TIMER1B +#undef TIMER1C +#undef TIMER2 +#undef TIMER2A +#undef TIMER2B +#undef TIMER3A +#undef TIMER3B +#undef TIMER3C +#undef TIMER4A +#undef TIMER4B +#undef TIMER4C +#undef TIMER4D +#undef TIMER5A +#undef TIMER5B +#undef TIMER5C + +// Include openplc.h FIRST (defines IEC_BOOL etc. as plain typedefs) #include "openplc.h" #include "defines.h" +// STruC++ headers define IEC_BOOL etc. inside namespace strucpp. +// Avoid "using namespace strucpp" globally to prevent ambiguity with openplc.h types. +#include "generated.hpp" + #ifdef MODBUS_ENABLED #include "ModbusSlave.h" #endif @@ -30,9 +55,32 @@ #endif // --------------------------------------------------------------------------- -// STruC++ Configuration instance (always Config0 in OpenPLC) +// AVR: provide sized operator delete (virtual destructors generate this) +// --------------------------------------------------------------------------- +void operator delete(void* ptr, unsigned int) { free(ptr); } + +// --------------------------------------------------------------------------- +// STruC++ time variable (used by generated code for TIME operations) +// --------------------------------------------------------------------------- +int64_t __CURRENT_TIME_NS = 0; + +// --------------------------------------------------------------------------- +// I/O Buffer definitions (declared extern in openplc.h, must be defined here) +// --------------------------------------------------------------------------- +IEC_BOOL *bool_input[MAX_DIGITAL_INPUT/8][8] = {}; +IEC_BOOL *bool_output[MAX_DIGITAL_OUTPUT/8][8] = {}; +IEC_UINT *int_input[MAX_ANALOG_INPUT] = {}; +IEC_UINT *int_output[MAX_ANALOG_OUTPUT] = {}; +#if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) +IEC_UINT *int_memory[MAX_MEMORY_WORD] = {}; +IEC_UDINT *dint_memory[MAX_MEMORY_DWORD] = {}; +IEC_ULINT *lint_memory[MAX_MEMORY_LWORD] = {}; +#endif + +// --------------------------------------------------------------------------- +// STruC++ Configuration instance (always CONFIG0 in OpenPLC) // --------------------------------------------------------------------------- -static strucpp::Configuration_Config0 g_config; +static strucpp::Configuration_CONFIG0 g_config; // --------------------------------------------------------------------------- // Task scheduling state (populated by discoverTasks) @@ -85,10 +133,10 @@ void bindLocatedVars() { case LocatedArea::Input: switch (lv.size) { case LocatedSize::Bit: - bool_input[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; + bool_input[lv.byte_index][lv.bit_index] = (::IEC_BOOL*)lv.pointer; break; case LocatedSize::Word: - int_input[lv.byte_index] = (IEC_UINT*)lv.pointer; + int_input[lv.byte_index] = (::IEC_UINT*)lv.pointer; break; #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) case LocatedSize::DWord: @@ -105,10 +153,10 @@ void bindLocatedVars() { case LocatedArea::Output: switch (lv.size) { case LocatedSize::Bit: - bool_output[lv.byte_index][lv.bit_index] = (IEC_BOOL*)lv.pointer; + bool_output[lv.byte_index][lv.bit_index] = (::IEC_BOOL*)lv.pointer; break; case LocatedSize::Word: - int_output[lv.byte_index] = (IEC_UINT*)lv.pointer; + int_output[lv.byte_index] = (::IEC_UINT*)lv.pointer; break; #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) case LocatedSize::DWord: @@ -126,13 +174,13 @@ void bindLocatedVars() { #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) switch (lv.size) { case LocatedSize::Word: - int_memory[lv.byte_index] = (IEC_UINT*)lv.pointer; + int_memory[lv.byte_index] = (::IEC_UINT*)lv.pointer; break; case LocatedSize::DWord: - dint_memory[lv.byte_index] = (IEC_UDINT*)lv.pointer; + dint_memory[lv.byte_index] = (::IEC_UDINT*)lv.pointer; break; case LocatedSize::LWord: - lint_memory[lv.byte_index] = (IEC_ULINT*)lv.pointer; + lint_memory[lv.byte_index] = (::IEC_ULINT*)lv.pointer; break; default: break; } diff --git a/resources/sources/arduino/openplc.h b/resources/sources/arduino/openplc.h index b82032b52..2f398ba56 100644 --- a/resources/sources/arduino/openplc.h +++ b/resources/sources/arduino/openplc.h @@ -63,9 +63,15 @@ extern IEC_ULINT *lint_memory[MAX_MEMORY_LWORD]; #endif -//Hardware Layer +//Hardware Layer (implemented in arduino.cpp HAL file, compiled as extern "C") +#ifdef __cplusplus +extern "C" { +#endif void hardwareInit(); void updateInputBuffers(); void updateOutputBuffers(); +#ifdef __cplusplus +} +#endif #endif diff --git a/resources/sources/avr-libstdcpp/include/cmath b/resources/sources/avr-libstdcpp/include/cmath index 7fb85d0ac..b83cba2e6 100644 --- a/resources/sources/avr-libstdcpp/include/cmath +++ b/resources/sources/avr-libstdcpp/include/cmath @@ -2,12 +2,19 @@ #ifndef _AVR_CMATH #define _AVR_CMATH #include +#include namespace std { using ::fabs; using ::fabsf; using ::fmod; using ::fmodf; using ::sqrt; using ::sqrtf; using ::floor; using ::floorf; using ::ceil; using ::ceilf; using ::round; using ::roundf; - using ::pow; using ::powf; using ::log; using ::logf; + using ::pow; using ::powf; using ::log; using ::logf; using ::log10; using ::exp; using ::expf; using ::sin; using ::cos; using ::tan; using ::asin; using ::acos; using ::atan; using ::atan2; + using ::trunc; + // abs overloads for float/double (Arduino's abs macro handles int only) + inline float abs(float x) { return fabsf(x); } + inline double abs(double x) { return fabs(x); } + inline long abs(long x) { return x < 0 ? -x : x; } + inline long long abs(long long x) { return x < 0 ? -x : x; } } #endif diff --git a/resources/sources/avr-libstdcpp/include/cstddef b/resources/sources/avr-libstdcpp/include/cstddef index bf7d1f85b..90cd0b111 100644 --- a/resources/sources/avr-libstdcpp/include/cstddef +++ b/resources/sources/avr-libstdcpp/include/cstddef @@ -2,6 +2,9 @@ #ifndef _AVR_CSTDDEF #define _AVR_CSTDDEF #include -namespace std { using ::size_t; using ::ptrdiff_t; } -using nullptr_t = decltype(nullptr); +namespace std { + using ::size_t; + using ::ptrdiff_t; + using nullptr_t = decltype(nullptr); +} #endif diff --git a/resources/sources/avr-libstdcpp/include/cstdlib b/resources/sources/avr-libstdcpp/include/cstdlib index 767b873d4..740e04d46 100644 --- a/resources/sources/avr-libstdcpp/include/cstdlib +++ b/resources/sources/avr-libstdcpp/include/cstdlib @@ -2,5 +2,20 @@ #ifndef _AVR_CSTDLIB #define _AVR_CSTDLIB #include -namespace std { using ::malloc; using ::free; using ::abort; using ::abs; using ::atoi; using ::atol; } + +// AVR libc doesn't have strtoll/strtoull -- provide minimal implementations +#ifdef __AVR__ +inline long long strtoll(const char* s, char** endp, int base) { + return (long long)strtol(s, endp, base); // truncated to 32-bit on AVR +} +inline unsigned long long strtoull(const char* s, char** endp, int base) { + return (unsigned long long)strtoul(s, endp, base); +} +#endif + +namespace std { + using ::malloc; using ::free; using ::abort; using ::abs; + using ::atoi; using ::atol; using ::strtol; using ::strtoul; + using ::strtod; using ::strtoll; using ::strtoull; +} #endif diff --git a/resources/sources/avr-libstdcpp/include/cstring b/resources/sources/avr-libstdcpp/include/cstring index 36aa916bc..1f3191134 100644 --- a/resources/sources/avr-libstdcpp/include/cstring +++ b/resources/sources/avr-libstdcpp/include/cstring @@ -5,5 +5,6 @@ namespace std { using ::memcpy; using ::memset; using ::memmove; using ::memcmp; using ::strlen; using ::strcmp; using ::strncmp; using ::strcpy; using ::strncpy; + using ::strstr; using ::strchr; using ::strrchr; using ::strcat; using ::strncat; } #endif diff --git a/resources/sources/avr-libstdcpp/include/type_traits b/resources/sources/avr-libstdcpp/include/type_traits index 04ce31e0c..1f6a99e24 100644 --- a/resources/sources/avr-libstdcpp/include/type_traits +++ b/resources/sources/avr-libstdcpp/include/type_traits @@ -134,9 +134,51 @@ template struct is_pointer : true_type {}; template struct is_pointer : true_type {}; template inline constexpr bool is_pointer_v = is_pointer::value; +// make_unsigned / make_signed +template struct make_unsigned; +template<> struct make_unsigned { using type = unsigned char; }; +template<> struct make_unsigned { using type = unsigned char; }; +template<> struct make_unsigned { using type = unsigned char; }; +template<> struct make_unsigned { using type = unsigned short; }; +template<> struct make_unsigned { using type = unsigned short; }; +template<> struct make_unsigned { using type = unsigned int; }; +template<> struct make_unsigned { using type = unsigned int; }; +template<> struct make_unsigned { using type = unsigned long; }; +template<> struct make_unsigned { using type = unsigned long; }; +template<> struct make_unsigned { using type = unsigned long long; }; +template<> struct make_unsigned { using type = unsigned long long; }; +template using make_unsigned_t = typename make_unsigned::type; + +template struct make_signed; +template<> struct make_signed { using type = signed char; }; +template<> struct make_signed { using type = signed char; }; +template<> struct make_signed { using type = signed char; }; +template<> struct make_signed { using type = short; }; +template<> struct make_signed { using type = short; }; +template<> struct make_signed { using type = int; }; +template<> struct make_signed { using type = int; }; +template<> struct make_signed { using type = long; }; +template<> struct make_signed { using type = long; }; +template<> struct make_signed { using type = long long; }; +template<> struct make_signed { using type = long long; }; +template using make_signed_t = typename make_signed::type; + // declval template T&& declval() noexcept; +// common_type (simplified: binary case using ternary operator type deduction) +template struct common_type; +template struct common_type { using type = decay_t; }; +template +struct common_type { + using type = decay_t() : declval())>; +}; +template +struct common_type { + using type = typename common_type::type, Rest...>::type; +}; +template using common_type_t = typename common_type::type; + } // namespace std #endif // _AVR_TYPE_TRAITS From 69d51a073373cfba0c61e18005ad970c599b486a Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Wed, 15 Apr 2026 00:39:54 -0400 Subject: [PATCH 028/296] fix: clean build directory before compilation Remove the board-specific build directory before recreating it to prevent stale files from previous builds causing duplicate symbol errors (e.g., old StrucppBaremetal.ino alongside new Baremetal.ino). Co-Authored-By: Claude Opus 4.6 (1M context) --- src/backend/editor/compiler/compiler-module.ts | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index 1a96c3dc1..ce5b108c3 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -320,15 +320,15 @@ class CompilerModule { projectFolderPath: string, boardTarget: string, ): Promise> { - // INFO: We don't need to check if the directories already exist, as mkdir with { recursive: true } will handle that. - // INFO: We will create a build directory (if it does not exist), a board-specific directory, and a source directory within the board directory. let result: MethodsResult = { success: false } const buildDirectory = join(projectFolderPath, 'build') const boardDirectory = join(buildDirectory, boardTarget) const sourceDirectory = join(boardDirectory, 'src') - // Create the directories recursively. - // INFO: We don't have to create the build directory separately + // Clean the board directory to remove stale files from previous builds + await fs.rm(boardDirectory, { recursive: true, force: true }) + + // Recreate the directories const results = await Promise.all([ mkdir(boardDirectory, { recursive: true }), mkdir(sourceDirectory, { recursive: true }), From 09f88b9a01bb8ffc92ba94700049142ad9c90c3c Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Wed, 15 Apr 2026 00:42:33 -0400 Subject: [PATCH 029/296] fix: include Arduino support files in StrucppBaremetal and remove stale lib path Copy arduino_libs.h, ModbusSlave.h/cpp, modules/, hal_conf_extra.h, and c_blocks_code.cpp into StrucppBaremetal/ so they're available alongside the sketch after build directory cleanup. Remove --library flag for src/lib (MatIEC lib directory no longer exists). Co-Authored-By: Claude Opus 4.6 (1M context) --- .../sources/StrucppBaremetal/ModbusSlave.cpp | 1337 ++++++++++++++ .../sources/StrucppBaremetal/ModbusSlave.h | 234 +++ .../sources/StrucppBaremetal/arduino_libs.h | 39 + .../StrucppBaremetal/c_blocks_code.cpp | 43 + .../sources/StrucppBaremetal/hal_conf_extra.h | 1 + .../StrucppBaremetal/modules/arduino_cloud.c | 47 + .../StrucppBaremetal/modules/arduinocan.c | 74 + .../StrucppBaremetal/modules/ds18b20.c | 51 + .../sources/StrucppBaremetal/modules/mqtt.c | 221 +++ .../sources/StrucppBaremetal/modules/p1am.c | 32 + .../modules/simulator_stubs.c | 399 +++++ .../StrucppBaremetal/modules/sm_cards.c | 1550 +++++++++++++++++ .../StrucppBaremetal/modules/stm32can.c | 105 ++ .../editor/compiler/compiler-module.ts | 4 +- 14 files changed, 4134 insertions(+), 3 deletions(-) create mode 100644 resources/sources/StrucppBaremetal/ModbusSlave.cpp create mode 100644 resources/sources/StrucppBaremetal/ModbusSlave.h create mode 100644 resources/sources/StrucppBaremetal/arduino_libs.h create mode 100644 resources/sources/StrucppBaremetal/c_blocks_code.cpp create mode 100644 resources/sources/StrucppBaremetal/hal_conf_extra.h create mode 100644 resources/sources/StrucppBaremetal/modules/arduino_cloud.c create mode 100644 resources/sources/StrucppBaremetal/modules/arduinocan.c create mode 100644 resources/sources/StrucppBaremetal/modules/ds18b20.c create mode 100644 resources/sources/StrucppBaremetal/modules/mqtt.c create mode 100644 resources/sources/StrucppBaremetal/modules/p1am.c create mode 100644 resources/sources/StrucppBaremetal/modules/simulator_stubs.c create mode 100644 resources/sources/StrucppBaremetal/modules/sm_cards.c create mode 100644 resources/sources/StrucppBaremetal/modules/stm32can.c diff --git a/resources/sources/StrucppBaremetal/ModbusSlave.cpp b/resources/sources/StrucppBaremetal/ModbusSlave.cpp new file mode 100644 index 000000000..0f1834c51 --- /dev/null +++ b/resources/sources/StrucppBaremetal/ModbusSlave.cpp @@ -0,0 +1,1337 @@ +/* +ModbusSlave.cpp - Source for Modbus Slave Library +Copyright (C) 2022 OpenPLC - Thiago Alves +*/ + +#include "ModbusSlave.h" + +//Global Modbus vars +struct MBinfo modbus; +uint8_t mb_frame[MAX_MB_FRAME]; +uint16_t mb_frame_len; +Stream* mb_serialport; +int8_t mb_txpin; +uint16_t mb_t15; // inter character time out +uint16_t mb_t35; // frame delay + +#ifdef MBTCP_ETHERNET +#ifdef BOARD_ESP32 + WiFiServer mb_server(502); + WiFiClient mb_serverClients[MAX_SRV_CLIENTS]; +#else + EthernetServer mb_server(502); +#endif + uint8_t mb_mbap[MBAP_SIZE]; +#ifdef BOARD_PORTENTA + EthernetClient mb_serverClients[MAX_SRV_CLIENTS]; +#endif +#endif + +#ifdef MBTCP_WIFI + WiFiServer mb_server(502); + uint8_t mb_mbap[MBAP_SIZE]; +#if defined(BOARD_ESP8266) || defined(BOARD_ESP32) || defined(BOARD_PORTENTA) || defined(BOARD_PICOW) + WiFiClient mb_serverClients[MAX_SRV_CLIENTS]; +#endif +#endif + +bool init_mbregs(uint8_t size_holding, uint8_t size_dint_memory, uint8_t size_lint_memory, uint8_t size_coils, uint8_t size_inputregs, uint8_t size_inputstatus) +{ + //Save sizes + modbus.holding_size = size_holding; + modbus.dint_memory_size = size_dint_memory; + modbus.lint_memory_size = size_lint_memory; + modbus.coils_size = size_coils; + modbus.input_regs_size = size_inputregs; + modbus.input_status_size = size_inputstatus; + + //round discrete regs sizes + if (size_coils % 8 > 0) + size_coils = (size_coils / 8) + 1; + else + size_coils = size_coils / 8; + if (size_inputstatus % 8 > 0) + size_inputstatus = (size_inputstatus / 8) + 1; + else + size_inputstatus = (size_inputstatus / 8); + + modbus.coils = (uint8_t *)malloc(size_coils * sizeof(uint8_t)); + if (modbus.coils == NULL) return false; + memset(modbus.coils, 0, size_coils * sizeof(uint8_t)); + + modbus.holding = (uint16_t *)malloc(size_holding * sizeof(uint16_t)); + if (modbus.holding == NULL) return false; + memset(modbus.holding, 0, size_holding * sizeof(uint16_t)); + + if (size_dint_memory > 0) + { + modbus.dint_memory = (uint32_t *)malloc(size_dint_memory * sizeof(uint32_t)); + if (modbus.dint_memory == NULL) return false; + memset(modbus.dint_memory, 0, size_dint_memory * sizeof(uint32_t)); + } + + if (size_lint_memory > 0) + { + modbus.lint_memory = (uint64_t *)malloc(size_lint_memory * sizeof(uint64_t)); + if (modbus.lint_memory == NULL) return false; + memset(modbus.lint_memory, 0, size_lint_memory * sizeof(uint64_t)); + } + + modbus.input_status = (uint8_t *)malloc(size_inputstatus * sizeof(uint8_t)); + if (modbus.input_status == NULL) return false; + memset(modbus.input_status, 0, size_inputstatus * sizeof(uint8_t)); + + modbus.input_regs = (uint16_t *)malloc(size_inputregs * sizeof(uint16_t)); + if (modbus.input_regs == NULL) return false; + memset(modbus.input_regs, 0, size_inputregs * sizeof(uint16_t)); + + return true; +} + +bool get_discrete(uint16_t addr, bool regtype) +{ + uint8_t byte_addr = addr / 8; + uint8_t bit_addr = addr % 8; + if (regtype == COILS) + return bitRead(modbus.coils[byte_addr], bit_addr); + else + return bitRead(modbus.input_status[byte_addr], bit_addr); +} + +void write_discrete(uint16_t addr, bool regtype, bool value) +{ + uint8_t byte_addr = addr / 8; + uint8_t bit_addr = addr % 8; + if (regtype == COILS) + bitWrite(modbus.coils[byte_addr], bit_addr, value); + else + bitWrite(modbus.input_status[byte_addr], bit_addr, value); +} + +void mbconfig_serial_iface(Stream* port, long baud, int txPin) +{ + mb_serialport = port; + mb_txpin = txPin; + //(*port).begin(baud); //Initialization already happened on main .ino file + + //RS-485 control + if (txPin >= 0) + { + pinMode(txPin, OUTPUT); + digitalWrite(txPin, LOW); + } + + #if defined(CONTROLLINO_MAXI) || defined(CONTROLLINO_MEGA) + if (mb_serialport == &Serial3) + Controllino_RS485Init(); + #elif defined(CONTROLLINO_MICRO) + if (mb_serialport == &Serial2) { + pinMode(CUSTOM_RS485_DEFAULT_DE_PIN, OUTPUT); + pinMode(CUSTOM_RS485_DEFAULT_RE_PIN, OUTPUT); + digitalWrite(CUSTOM_RS485_DEFAULT_DE_PIN, LOW); + digitalWrite(CUSTOM_RS485_DEFAULT_RE_PIN, HIGH); + } + #endif + + // Modbus states that a baud rate higher than 19200 must use a fixed 750 us + // for inter character time out. For baud rates below 19200 the timing + // is more critical and has to be calculated. + // E.g. 9600 baud in a 11 bit packet is 9600/11 = 872 characters per second + // In milliseconds this will be 872 characters per 1000ms. So for 1 character + // 1000ms/872 characters is 1.14583ms per character. Finally modbus states + // an inter-character must be 1.5T or 1.5 times longer than a character. Thus + // 1.5T = 1.14583ms * 1.5 = 1.71875ms. + // Thus the formula is T1.5(us) = (1000ms * 1000(us) * 1.5 * 11bits)/baud + // 1000ms * 1000(us) * 1.5 * 11bits = 16500000 can be calculated as a constant + + if (baud > 19200) + mb_t15 = 750; + else + mb_t15 = 16500000/baud; // 1T * 1.5 = T1.5 + + /* The modbus definition of a frame delay is a waiting period of 3.5 character times + between packets.*/ + + mb_t35 = mb_t15 * 3.5; +} + + +#ifdef MBTCP +void mbconfig_ethernet_iface(uint8_t *mac, uint8_t *ip, uint8_t *dns, uint8_t *gateway, uint8_t *subnet) +{ + #ifdef MBTCP_ETHERNET + #ifdef BOARD_ESP32 + + ETH.begin(); + + if (ip != NULL && subnet != NULL && gateway != NULL) + (ETH.config(ip, gateway, subnet, dns)); + + #else + if (ip == NULL) + Ethernet.begin(mac); + else if (dns == NULL) + Ethernet.begin(mac, IPAddress(ip)); + else if (gateway == NULL) + Ethernet.begin(mac, IPAddress(ip), IPAddress(dns)); + else if (subnet == NULL) + Ethernet.begin(mac, IPAddress(ip), IPAddress(dns), IPAddress(gateway)); + else + Ethernet.begin(mac, IPAddress(ip), IPAddress(dns), IPAddress(gateway), IPAddress(subnet)); + #endif + +// int num_tries = 0; +// while (!ETH.linkUp()) +// { +// delay(500); +// num_tries++; +// if (num_tries == 20) break; +// } + + #endif + #ifdef MBTCP_WIFI + #if defined(BOARD_ESP8266) || defined(BOARD_ESP32) + if (ip != NULL && gateway != NULL && subnet != NULL && dns != NULL) + { + uint8_t secondaryDNS[] = {8, 8, 8, 8}; + WiFi.config(IPAddress(ip), IPAddress(gateway), IPAddress(subnet), IPAddress(dns), IPAddress(secondaryDNS)); + } + mb_server.setNoDelay(true); + #elif defined(BOARD_PORTENTA) + if (ip != NULL && subnet != NULL && gateway != NULL) + { + WiFi.config(IPAddress(ip), IPAddress(subnet), IPAddress(gateway)); + } + #else + if (ip != NULL) + { + if (dns == NULL) + WiFi.config(IPAddress(ip)); + else if (gateway == NULL) + WiFi.config(IPAddress(ip), IPAddress(dns)); + else if (subnet == NULL) + WiFi.config(IPAddress(ip), IPAddress(dns), IPAddress(gateway)); + else + WiFi.config(IPAddress(ip), IPAddress(dns), IPAddress(gateway), IPAddress(subnet)); + } + #endif + WiFi.begin(MBTCP_SSID, MBTCP_PWD); + int num_tries = 0; + while (WiFi.status() != WL_CONNECTED) + { + delay(500); + num_tries++; + if (num_tries == 10) break; + } + #endif + + mb_server.begin(); + +} +#endif + +void mbtask() +{ + #ifdef MBTCP + handle_tcp(); + #endif + #ifdef MBSERIAL + handle_serial(); + #endif +} + +#ifdef MBTCP +void handle_tcp() +{ + #ifdef MBTCP_ETHERNET + #ifdef BOARD_ESP32 + WiFiClient client = mb_server.available(); + #else + EthernetClient client = mb_server.available(); + #endif + #endif + + #if defined(MBTCP_WIFI) && !defined(BOARD_ESP8266) && !defined(BOARD_ESP32) + WiFiClient client = mb_server.available(); + #endif + + //ESP and Portenta boards have a slightly different implementation of the WiFi/Ethernet API - therefore their specific + //code lies below + #if (defined(BOARD_ESP8266) || defined(BOARD_ESP32) || defined(BOARD_PORTENTA)) || defined(BOARD_PICOW) && (defined(MBTCP_WIFI) || defined(MBTCP_ETHERNET)) + + + #if defined(BOARD_PORTENTA) || defined(BOARD_PICOW) || (defined(BOARD_ESP32) && defined(MBTCP_ETHERNET)) + if (client) + #else + if (mb_server.hasClient()) + #endif + { + for (int i = 0; i < MAX_SRV_CLIENTS; i++) + { + if (!mb_serverClients[i]) //equivalent to !serverClients[i].connected() + { + #if defined(BOARD_PORTENTA) || defined(BOARD_PICOW) || defined(BOARD_ESP32) && defined(MBTCP_ETHERNET) + mb_serverClients[i] = client; + #else + mb_serverClients[i] = mb_server.available(); + #endif + break; + } + } + } + + //search all clients for data + for (int i = 0; i < MAX_SRV_CLIENTS; i++) + { + int j = 0; + + + if (mb_serverClients[i].connected() && mb_serverClients[i].available()) + + { + //Read packet + + + while (mb_serverClients[i].available()) + { + mb_mbap[j] = mb_serverClients[i].read(); + j++; + if (j==MBAP_SIZE) break; //MBAP has 6 bytes (we use UnitID as SlaveID) + } + + mb_frame_len = mb_mbap[4] << 8 | mb_mbap[5]; + + if (mb_mbap[2] !=0 || mb_mbap[3] !=0) return; //Not a MODBUSIP packet + if (mb_frame_len < 6 || mb_frame_len > MAX_MB_FRAME) return; //Packet is too small or too big + + j = 0; + while (mb_serverClients[i].available()) + { + mb_frame[j] = mb_serverClients[i].read(); + j++; + if (j==mb_frame_len) break; + } + + //Safety check - discard packages that lie about their size + if (j != mb_frame_len) return; + + //Process packet and write back + process_mbpacket(); + //Calculate packet length for MBAP header (mb_frame_len + 1) + mb_mbap[4] = (mb_frame_len) >> 8; + mb_mbap[5] = (mb_frame_len) & 0x00FF; + + uint8_t sendbuffer[mb_frame_len + MBAP_SIZE]; + + //MBAP + for (j = 0 ; j < MBAP_SIZE ; j++) + sendbuffer[j] = mb_mbap[j]; + + //PDU Frame + for (j = 0 ; j < mb_frame_len ; j++) + sendbuffer[j+MBAP_SIZE] = mb_frame[j]; + + //Write back + mb_serverClients[i].write(sendbuffer, mb_frame_len + MBAP_SIZE); + } + } + + //If this is not an ESP board or Portenta board, then here is the default code + #else + if (client) + { + if (client.connected()) + { + int i = 0; + while (client.available()) + { + mb_mbap[i] = client.read(); + i++; + if (i==MBAP_SIZE) break; //MBAP has 6 bytes (we use UnitID as SlaveID) + } + + mb_frame_len = mb_mbap[4] << 8 | mb_mbap[5]; + + if (mb_mbap[2] !=0 || mb_mbap[3] !=0) return; //Not a MODBUSIP packet + if (mb_frame_len < 6 || mb_frame_len > MAX_MB_FRAME) return; //Packet is too small or too big + + i = 0; + while (client.available()) + { + mb_frame[i] = client.read(); + i++; + if (i==mb_frame_len || i==MAX_MB_FRAME) break; + } + + //Safety check - discard packages that lie about their size + if (i != mb_frame_len) return; + + //Process packet and write back + process_mbpacket(); + //Calculate packet length for MBAP header (mb_frame_len + 1) + mb_mbap[4] = (mb_frame_len) >> 8; + mb_mbap[5] = (mb_frame_len) & 0x00FF; + + uint8_t sendbuffer[mb_frame_len + MBAP_SIZE]; + + //MBAP + for (i = 0 ; i < MBAP_SIZE ; i++) + sendbuffer[i] = mb_mbap[i]; + + //PDU Frame + for (i = 0 ; i < mb_frame_len ; i++) + sendbuffer[i+MBAP_SIZE] = mb_frame[i]; + + //Write back + client.write(sendbuffer, mb_frame_len + MBAP_SIZE); + } + } + #endif +} +#endif + +#ifdef MBSERIAL +void handle_serial() +{ + mb_frame_len = 0; + + if ((*mb_serialport).available() == 0) + return; + + while ((*mb_serialport).available() > mb_frame_len) + { + mb_frame_len = (*mb_serialport).available(); + delayMicroseconds(mb_t15); + } + + //Check if packet is too big or too small + if ((*mb_serialport).available() > MAX_MB_FRAME || (*mb_serialport).available() < 6) + { + //(*mb_serialport).println("Packet too big"); + //(*mb_serialport).flush(); + return; + } + + //Read packet + for (uint16_t i = 0; i < mb_frame_len; i++) + { + mb_frame[i] = (*mb_serialport).read(); + } + + //Validate crc + uint16_t packet_crc; + //Ignore CRC errors when using debugger functions + if (mb_frame[1] != MB_FC_DEBUG_INFO && mb_frame[1] != MB_FC_DEBUG_SET && mb_frame[1] != MB_FC_DEBUG_GET && mb_frame[1] != MB_FC_DEBUG_GET_LIST && mb_frame[1] != MB_FC_DEBUG_GET_MD5) + { + packet_crc = ((mb_frame[mb_frame_len - 2] << 8) | mb_frame[mb_frame_len - 1]); + if (packet_crc != calcCrc()) + { + /* DEBUG + char buffer[100]; + (*mb_serialport).println("Invalid CRC for packet: "); + int offset = 0; // Initialize offset for buffer + for (int i = 0; i < mb_frame_len; i++) + { + offset += sprintf(buffer + offset, "%02X ", mb_frame[i]); + } + (*mb_serialport).println(buffer); + (*mb_serialport).print("Packet_crc: "); + (*mb_serialport).println(packet_crc); + (*mb_serialport).print("Calc CRC: "); + (*mb_serialport).println(calcCrc()); + (*mb_serialport).flush(); + */ + return; + } + } + + //Validate SlaveID + if (mb_frame[0] != modbus.slaveid) + { + (*mb_serialport).flush(); + return; + } + + //Remove CRC (must do that before processing packet) + mb_frame_len -= 2; + + //Process packet and write back + process_mbpacket(); + + //Add CRC + //Check if response message is too big for this device + if (mb_frame_len + 2 > MAX_MB_FRAME) exceptionResponse(mb_frame[1], MB_EX_SLAVE_FAILURE); + mb_frame_len += 2; //increase frame length by two bytes to acomodate CRC + packet_crc = calcCrc(); //calculate CRC of the new packet + mb_frame[mb_frame_len - 2] = (uint8_t)(packet_crc >> 8); + mb_frame[mb_frame_len - 1] = (uint8_t)(packet_crc & 0x00FF); + + if (mb_txpin >= 0) + { + digitalWrite(mb_txpin, HIGH); + delayMicroseconds(mb_t35); + } + + #if defined(CONTROLLINO_MAXI) || defined(CONTROLLINO_MEGA) + if (mb_serialport == &Serial3) // RS485 serial port + Controllino_RS485TxEnable(); // Enable RS485 chip to transmit + #elif defined(CONTROLLINO_MICRO) + if (mb_serialport == &Serial2) { + digitalWrite(CUSTOM_RS485_DEFAULT_DE_PIN, HIGH); + digitalWrite(CUSTOM_RS485_DEFAULT_RE_PIN, HIGH); + } + #endif + + (*mb_serialport).write(mb_frame, mb_frame_len); + (*mb_serialport).flush(); + delayMicroseconds(mb_t35); + + if (mb_txpin >= 0) + digitalWrite(mb_txpin, LOW); + + #if defined(CONTROLLINO_MAXI) || defined(CONTROLLINO_MEGA) + if (mb_serialport == &Serial3) // RS485 serial port + Controllino_RS485RxEnable(); // Go back to receive mode after transmitted data + #elif defined(CONTROLLINO_MICRO) + if (mb_serialport == &Serial2) { + digitalWrite(CUSTOM_RS485_DEFAULT_DE_PIN, LOW); + digitalWrite(CUSTOM_RS485_DEFAULT_RE_PIN, LOW); + } + #endif +} +#endif + + +void process_mbpacket() +{ + uint8_t fcode = mb_frame[1]; + uint16_t field1 = (uint16_t)mb_frame[2] << 8 | (uint16_t)mb_frame[3]; + uint16_t field2 = (uint16_t)mb_frame[4] << 8 | (uint16_t)mb_frame[5]; + uint8_t flag = mb_frame[4]; + uint16_t len = (uint16_t)mb_frame[5] << 8 | (uint16_t)mb_frame[6]; + void *value = &mb_frame[7]; + void *endianness_check = &mb_frame[2]; + + switch (fcode) + { + case MB_FC_WRITE_REG: + //field1 = reg, field2 = value + writeSingleRegister(field1, field2); + break; + + case MB_FC_READ_REGS: + //field1 = startreg, field2 = numregs + readRegisters(field1, field2); + break; + + case MB_FC_WRITE_REGS: + //field1 = startreg, field2 = status + writeMultipleRegisters(field1, field2, mb_frame[6]); + break; + + case MB_FC_READ_COILS: + //field1 = startreg, field2 = numregs + readCoils(field1, field2); + break; + + case MB_FC_READ_INPUT_STAT: + //field1 = startreg, field2 = numregs + readInputStatus(field1, field2); + break; + + case MB_FC_READ_INPUT_REGS: + //field1 = startreg, field2 = numregs + readInputRegisters(field1, field2); + break; + + case MB_FC_WRITE_COIL: + //field1 = reg, field2 = status + writeSingleCoil(field1, field2); + break; + + case MB_FC_WRITE_COILS: + //field1 = startreg, field2 = numoutputs + writeMultipleCoils(field1, field2, mb_frame[6]); + break; + + case MB_FC_DEBUG_INFO: + debugInfo(); + break; + + case MB_FC_DEBUG_GET: + //field1 = startidx, field2 = endidx + debugGetTrace(field1, field2); + break; + + case MB_FC_DEBUG_GET_LIST: + //field1 = numIndexes + debugGetTraceList(field1, &mb_frame[4]); + break; + + case MB_FC_DEBUG_SET: + //field1 = varidx + debugSetTrace(field1, flag, len, value); + break; + + case MB_FC_DEBUG_GET_MD5: + debugGetMd5(endianness_check); + break; + + default: + exceptionResponse(fcode, MB_EX_ILLEGAL_FUNCTION); + } +} + + +//Modbus handling functions +void readRegisters(uint16_t startreg, uint16_t numregs) +{ + //Check value (numregs) + if (numregs < 0x0001 || numregs > 0x007D) + { + exceptionResponse(MB_FC_READ_REGS, MB_EX_ILLEGAL_VALUE); + return; + } + + //Check Address + if ((startreg+numregs) >= (modbus.holding_size + (2*modbus.dint_memory_size) + (4*modbus.lint_memory_size))) + { + exceptionResponse(MB_FC_READ_REGS, MB_EX_ILLEGAL_ADDRESS); + return; + } + + //calculate the query reply message length + mb_frame_len = 3 + (numregs * 2); + if (mb_frame_len > MAX_MB_FRAME) + { + //Response message is too big for this device + exceptionResponse(MB_FC_READ_REGS, MB_EX_SLAVE_FAILURE); + return; + } + + //Clean frame buffer (leave only SlaveID) + for (int i = 1; i < mb_frame_len; i++) mb_frame[i] = 0; + + mb_frame[1] = MB_FC_READ_REGS; + mb_frame[2] = mb_frame_len - 3; //byte count + + uint16_t val; + uint16_t i = 0; + uint8_t pos = 0; + while(numregs--) + { + if ((startreg + i) < modbus.holding_size) + { + //retrieve the value from the register bank for the current register + val = modbus.holding[startreg + i]; + } + else if ((startreg + i) < (modbus.holding_size + (2*modbus.dint_memory_size))) //32-bit registers + { + if ((startreg + i) % 2 == 0) //first word + { + pos = ((startreg + i) - modbus.holding_size) / 2; + val = (uint16_t)(modbus.dint_memory[pos] >> 16); + } + else //second word + { + pos = ((startreg + i) - modbus.holding_size - 1) / 2; + val = (uint16_t)(modbus.dint_memory[pos] & 0xffff); + } + } + else //64-bit registers + { + if ((startreg + i) % 4 == 0) //first word + { + pos = ((startreg + i) - (modbus.holding_size + (2*modbus.dint_memory_size))) / 4; + val = (uint16_t)(modbus.lint_memory[pos] >> 48); + } + else if ((startreg + i) % 4 == 1) //second word + { + pos = ((startreg + i) - (modbus.holding_size + (2*modbus.dint_memory_size) - 1)) / 4; + val = (uint16_t)((modbus.lint_memory[pos] >> 32) & 0xffff); + } + else if ((startreg + i) % 4 == 2) //third word + { + pos = ((startreg + i) - (modbus.holding_size + (2*modbus.dint_memory_size) - 2)) / 4; + val = (uint16_t)((modbus.lint_memory[pos] >> 16) & 0xffff); + } + else //fourth word + { + pos = ((startreg + i) - (modbus.holding_size + (2*modbus.dint_memory_size) - 3)) / 4; + val = (uint16_t)(modbus.lint_memory[pos] & 0xffff); + } + } + + //write the high byte of the register value + mb_frame[3 + (i * 2)] = val >> 8; + //write the low byte of the register value + mb_frame[4 + (i * 2)] = val & 0xFF; + i++; + } +} + +void writeSingleRegister(uint16_t reg, uint16_t value) +{ + if (reg >= (modbus.holding_size + (2*modbus.dint_memory_size) + (4*modbus.lint_memory_size))) + { + exceptionResponse(MB_FC_WRITE_REG, MB_EX_ILLEGAL_ADDRESS); + return; + } + + uint8_t pos = 0; + + if (reg < modbus.holding_size) + { + modbus.holding[reg] = value; + } + else if (reg < (modbus.holding_size + (2*modbus.dint_memory_size))) //32-bit registers + { + if (reg % 2 == 0) //first word + { + pos = (reg - modbus.holding_size) / 2; + modbus.dint_memory[pos] = modbus.dint_memory[pos] & 0x0000ffff; //zeroed first word + modbus.dint_memory[pos] = modbus.dint_memory[pos] | ((uint32_t)value << 16); //insert first word + } + else //second word + { + pos = (reg - modbus.holding_size - 1) / 2; + modbus.dint_memory[pos] = modbus.dint_memory[pos] & 0xffff0000; + modbus.dint_memory[pos] = modbus.dint_memory[pos] | value; + } + + } + else //64-bit registers + { + if (reg % 4 == 0) //first word + { + pos = (reg - (modbus.holding_size + (2*modbus.dint_memory_size))) / 4; + modbus.lint_memory[pos] = modbus.lint_memory[pos] & 0x0000ffffffffffff; //zeroed first word + modbus.lint_memory[pos] = modbus.lint_memory[pos] | ((uint64_t)value << 48); //insert first word + } + else if (reg % 4 == 1) //second word + { + pos = (reg - (modbus.holding_size + (2*modbus.dint_memory_size) - 1)) / 4; + modbus.lint_memory[pos] = modbus.lint_memory[pos] & 0xffff0000ffffffff; + modbus.lint_memory[pos] = modbus.lint_memory[pos] | ((uint64_t)value << 32); + } + else if (reg % 4 == 2) //third word + { + pos = (reg - (modbus.holding_size + (2*modbus.dint_memory_size) - 2)) / 4; + modbus.lint_memory[pos] = modbus.lint_memory[pos] & 0xffffffff0000ffff; + modbus.lint_memory[pos] = modbus.lint_memory[pos] | ((uint64_t)value << 16); + } + else //fourth word + { + pos = (reg - (modbus.holding_size + (2*modbus.dint_memory_size) - 3)) / 4; + modbus.lint_memory[pos] = modbus.lint_memory[pos] & 0xffffffffffff0000; + modbus.lint_memory[pos] = modbus.lint_memory[pos] | value; + } + } +} + +void writeMultipleRegisters(uint16_t startreg, uint16_t numoutputs, uint8_t bytecount) +{ + //Check value + if (numoutputs < 0x0001 || numoutputs > 0x007B || bytecount != 2 * numoutputs) + { + exceptionResponse(MB_FC_WRITE_REGS, MB_EX_ILLEGAL_VALUE); + return; + } + + //Check Address (startreg...startreg + numregs) + if ((startreg + numoutputs) >= (modbus.holding_size + (2*modbus.dint_memory_size) + (4*modbus.lint_memory_size))) + { + exceptionResponse(MB_FC_WRITE_REGS, MB_EX_ILLEGAL_ADDRESS); + return; + } + + //Prepare answer frame buffer + mb_frame_len = 6; + mb_frame[1] = MB_FC_WRITE_REGS; + mb_frame[2] = startreg >> 8; + mb_frame[3] = startreg & 0x00FF; + mb_frame[4] = numoutputs >> 8; + mb_frame[5] = numoutputs & 0x00FF; + + uint16_t value; + uint16_t i = 0; + uint8_t pos = 0; + while(numoutputs--) + { + value = (uint16_t)mb_frame[7+i*2] << 8 | (uint16_t)mb_frame[8+i*2]; + + if ((startreg + i) < modbus.holding_size) + { + modbus.holding[(startreg + i)] = value; + } + else if ((startreg + i) < (modbus.holding_size + (2*modbus.dint_memory_size))) //32-bit registers + { + if ((startreg + i) % 2 == 0) //first word + { + pos = ((startreg + i) - modbus.holding_size) / 2; + modbus.dint_memory[pos] = modbus.dint_memory[pos] & 0x0000ffff; //zeroed first word + modbus.dint_memory[pos] = modbus.dint_memory[pos] | ((uint32_t)value << 16); //insert first word + } + else //second word + { + pos = ((startreg + i) - modbus.holding_size - 1) / 2; + modbus.dint_memory[pos] = modbus.dint_memory[pos] & 0xffff0000; + modbus.dint_memory[pos] = modbus.dint_memory[pos] | value; + } + + } + else //64-bit registers + { + if ((startreg + i) % 4 == 0) //first word + { + pos = ((startreg + i) - (modbus.holding_size + (2*modbus.dint_memory_size))) / 4; + modbus.lint_memory[pos] = modbus.lint_memory[pos] & 0x0000ffffffffffff; //zeroed first word + modbus.lint_memory[pos] = modbus.lint_memory[pos] | ((uint64_t)value << 48); //insert first word + } + else if ((startreg + i) % 4 == 1) //second word + { + pos = ((startreg + i) - (modbus.holding_size + (2*modbus.dint_memory_size) - 1)) / 4; + modbus.lint_memory[pos] = modbus.lint_memory[pos] & 0xffff0000ffffffff; + modbus.lint_memory[pos] = modbus.lint_memory[pos] | ((uint64_t)value << 32); + } + else if ((startreg + i) % 4 == 2) //third word + { + pos = ((startreg + i) - (modbus.holding_size + (2*modbus.dint_memory_size) - 2)) / 4; + modbus.lint_memory[pos] = modbus.lint_memory[pos] & 0xffffffff0000ffff; + modbus.lint_memory[pos] = modbus.lint_memory[pos] | ((uint64_t)value << 16); + } + else //fourth word + { + pos = ((startreg + i) - (modbus.holding_size + (2*modbus.dint_memory_size) - 3)) / 4; + modbus.lint_memory[pos] = modbus.lint_memory[pos] & 0xffffffffffff0000; + modbus.lint_memory[pos] = modbus.lint_memory[pos] | value; + } + } + + i++; + } +} + +void exceptionResponse(uint16_t fcode, uint16_t excode) +{ + //Clean frame buffer (leave only SlaveID) + mb_frame_len = 3; + for (int i = 0; i < mb_frame_len; i++) mb_frame[i] = 0; + mb_frame[0] = modbus.slaveid; + mb_frame[1] = fcode + 0x80; + mb_frame[2] = excode; +} + +void readCoils(uint16_t startreg, uint16_t numregs) +{ + //Check value (numregs) + if (numregs < 0x0001 || numregs > 0x07D0) + { + exceptionResponse(MB_FC_READ_COILS, MB_EX_ILLEGAL_VALUE); + return; + } + + //Check Address + if (startreg + numregs > modbus.coils_size) + { + exceptionResponse(MB_FC_READ_COILS, MB_EX_ILLEGAL_ADDRESS); + return; + } + + //Determine the message length = slaveid + function type + byte count and + //for each group of 8 registers the message length increases by 1 + mb_frame_len = 3 + numregs/8; + if (numregs%8) mb_frame_len++; //Add 1 to the message length for the partial byte. + if (mb_frame_len > MAX_MB_FRAME) + { + //Response message is too big for this device + exceptionResponse(MB_FC_READ_COILS, MB_EX_SLAVE_FAILURE); + return; + } + + //Clean frame buffer (leave only SlaveID) + for (int i = 1; i < mb_frame_len; i++) mb_frame[i] = 0; + + mb_frame[1] = MB_FC_READ_COILS; + mb_frame[2] = mb_frame_len - 3; //byte count (mb_frame_len - slave id, function code and byte count) + + uint8_t bitn = 0; + uint16_t totregs = numregs; + uint16_t i; + while (numregs) + { + i = (totregs - numregs--) / 8; + if (get_discrete((uint8_t)startreg, COILS)) + bitSet(mb_frame[3+i], bitn); + else + bitClear(mb_frame[3+i], bitn); + + //increment the bit index + bitn++; + if (bitn == 8) bitn = 0; + //increment the register + startreg++; + } +} + +void readInputStatus(uint16_t startreg, uint16_t numregs) +{ + //Check value (numregs) + if (numregs < 0x0001 || numregs > 0x07D0) + { + exceptionResponse(MB_FC_READ_INPUT_STAT, MB_EX_ILLEGAL_VALUE); + return; + } + + //Check Address + if ((startreg + numregs) > modbus.input_status_size) + { + exceptionResponse(MB_FC_READ_INPUT_STAT, MB_EX_ILLEGAL_ADDRESS); + return; + } + + //Determine the message length = function type, byte count and + //for each group of 8 registers the message length increases by 1 + mb_frame_len = 3 + numregs/8; + if (numregs%8) mb_frame_len++; //Add 1 to the message length for the partial byte. + if (mb_frame_len > MAX_MB_FRAME) + { + //Response message is too big for this device + exceptionResponse(MB_FC_READ_INPUT_STAT, MB_EX_SLAVE_FAILURE); + return; + } + + //Clean frame buffer (leave only SlaveID) + for (int i = 1; i < mb_frame_len; i++) mb_frame[i] = 0; + + mb_frame[1] = MB_FC_READ_INPUT_STAT; + mb_frame[2] = mb_frame_len - 3; + + byte bitn = 0; + uint16_t totregs = numregs; + uint16_t i; + while (numregs) + { + i = (totregs - numregs--) / 8; + if (get_discrete(startreg, INPUTSTATUS)) + bitSet(mb_frame[3+i], bitn); + else + bitClear(mb_frame[3+i], bitn); + //increment the bit index + bitn++; + if (bitn == 8) bitn = 0; + //increment the register + startreg++; + } +} + +void readInputRegisters(uint16_t startreg, uint16_t numregs) +{ + //Check value (numregs) + if (numregs < 0x0001 || numregs > 0x007D) + { + exceptionResponse(MB_FC_READ_INPUT_REGS, MB_EX_ILLEGAL_VALUE); + return; + } + + //Check Address + if ((startreg + numregs) > modbus.input_regs_size) + { + exceptionResponse(MB_FC_READ_INPUT_REGS, MB_EX_ILLEGAL_ADDRESS); + return; + } + + //calculate the query reply message length + //for each register queried add 2 bytes + mb_frame_len = 3 + (numregs * 2); + if (mb_frame_len > MAX_MB_FRAME) + { + //Response message is too big for this device + exceptionResponse(MB_FC_READ_INPUT_REGS, MB_EX_SLAVE_FAILURE); + return; + } + + //Clean frame buffer (leave only SlaveID) + for (int i = 1; i < mb_frame_len; i++) mb_frame[i] = 0; + + mb_frame[1] = MB_FC_READ_INPUT_REGS; + mb_frame[2] = mb_frame_len - 3; + + uint16_t val; + uint16_t i = 0; + while(numregs--) + { + //retrieve the value from the register bank for the current register + val = modbus.input_regs[startreg + i]; + //write the high byte of the register value + mb_frame[3 + (i * 2)] = val >> 8; + //write the low byte of the register value + mb_frame[4 + (i * 2)] = val & 0xFF; + i++; + } +} + +void writeSingleCoil(uint16_t reg, uint16_t status) +{ + //Check value (status) + if (status != 0xFF00 && status != 0x0000) + { + exceptionResponse(MB_FC_WRITE_COIL, MB_EX_ILLEGAL_VALUE); + return; + } + + //Check Address + if (reg > (modbus.coils_size - 1)) + { + exceptionResponse(MB_FC_WRITE_COIL, MB_EX_ILLEGAL_ADDRESS); + return; + } + + //Execute + write_discrete(reg, COILS, status == 0xFF00 ? true : false); +} + +void writeMultipleCoils(uint16_t startreg, uint16_t numoutputs, uint16_t bytecount) +{ + //Check value + uint8_t bytecount_calc = numoutputs / 8; + if (numoutputs%8) bytecount_calc++; + if (numoutputs < 0x0001 || numoutputs > 0x07B0 || bytecount != bytecount_calc) + { + exceptionResponse(MB_FC_WRITE_COILS, MB_EX_ILLEGAL_VALUE); + return; + } + + //Check Address (startreg...startreg + numregs) + if ((startreg + numoutputs) > modbus.coils_size) + { + exceptionResponse(MB_FC_WRITE_COILS, MB_EX_ILLEGAL_ADDRESS); + return; + } + + //Prepare answer frame buffer + mb_frame_len = 6; + mb_frame[1] = MB_FC_WRITE_COILS; + mb_frame[2] = startreg >> 8; + mb_frame[3] = startreg & 0x00FF; + mb_frame[4] = numoutputs >> 8; + mb_frame[5] = numoutputs & 0x00FF; + + //Execute + uint8_t bitn = 0; + uint16_t totoutputs = numoutputs; + uint16_t i; + while (numoutputs) + { + i = (totoutputs - numoutputs--) / 8; + write_discrete(startreg, COILS, bitRead(mb_frame[7+i], bitn)); + //increment the bit index + bitn++; + if (bitn == 8) bitn = 0; + //increment the register + startreg++; + } +} + +/** + * @brief Sends a Modbus response frame for the DEBUG_INFO function code. + * + * This function constructs a Modbus response frame for the DEBUG_INFO function code. + * The response frame includes the number of variables defined in the PLC program. + * + * Modbus Response Frame (DEBUG_INFO): + * +-----+-------+-------+ + * | MB | Count | Count | + * | FC | | | + * +-----+-------+-------+ + * |0x41 | High | Low | + * | | Byte | Byte | + * | | | | + * +-----+-------+-------+ + * + * @return void + */ +void debugInfo() +{ + uint16_t variableCount = get_var_count(); + mb_frame_len = 4; + mb_frame[1] = MB_FC_DEBUG_INFO; + mb_frame[2] = (uint8_t)(variableCount >> 8); // High byte + mb_frame[3] = (uint8_t)(variableCount & 0xFF); // Low byte +} + +/** + * @brief Sends a Modbus response frame for the DEBUG_SET function code. + * + * This function constructs a Modbus response frame for the DEBUG_SET function code. + * The response frame indicates whether the set trace command was successful or if + * there was an error, such as an out-of-bounds index. + * + * Modbus Response Frame (DEBUG_SET): + * +-----+------+ + * | MB | Resp.| + * | FC | Code | + * +-----+------+ + * |0x42 | Code | + * +-----+------+ + * + * @param varidx The index of the variable to set trace for. + * @param flag The trace flag. + * @param len The length of the trace data. + * @param value Pointer to the trace data. + * + * @return void + */ +void debugSetTrace(uint16_t varidx, uint8_t flag, uint16_t len, void *value) +{ + uint16_t variableCount = get_var_count(); + if (varidx >= variableCount || len > (MAX_MB_FRAME - 7)) + { + // Respond with an error indicating that the index is out of range + mb_frame_len = 3; + mb_frame[1] = MB_FC_DEBUG_SET; + mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; + return; + } + + // Execute set trace command + set_trace((size_t)varidx, (bool)flag, value); + + // Response + mb_frame_len = 3; + mb_frame[1] = MB_FC_DEBUG_SET; + mb_frame[2] = MB_DEBUG_SUCCESS; +} + +/** + * @brief Sends a Modbus response frame for the DEBUG_GET function code. + * + * This function constructs a Modbus response frame for the DEBUG_GET function code. + * The response frame includes the trace data for variables within the specified index range. + * + * Modbus Response Frame (DEBUG_GET): + * +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+ + * | MB | Resp. | Last | Last | Tick | Tick | Tick | Tick | Resp. | Resp.| Data | + * | FC | Code | Index | Index | | | | | Size | Size | Bytes | + * +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+ + * |0x44 | Code | High | Low | High | Mid | Mid | Low | High | Low | Data | + * | | | Byte | Byte | Byte | Byte | Byte | Byte | Byte | Byte | Bytes | + * +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+ + * + * @param startidx The start index of the variables to get trace for. + * @param endidx The end index of the variables to get trace for. + * + * @return void + */ +void debugGetTrace(uint16_t startidx, uint16_t endidx) +{ + uint16_t variableCount = get_var_count(); + // Verify that startidx and endidx fall within the valid range of variables + if (startidx >= variableCount || endidx >= variableCount || startidx > endidx) + { + // Respond with an error indicating that the indices are out of range + mb_frame_len = 3; + mb_frame[1] = MB_FC_DEBUG_GET; + mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; + return; + } + + uint16_t lastVarIdx = startidx; + size_t responseSize = 0; + uint8_t *responsePtr = &(mb_frame[11]); // Start of response data + + for (uint16_t varidx = startidx; varidx <= endidx; varidx++) + { + size_t varSize = get_var_size(varidx); + if ((responseSize + 11) + varSize <= MAX_MB_FRAME) // Make sure the response fits + { + void *varAddr = get_var_addr(varidx); + + // Copy the variable value to the response buffer + memcpy(responsePtr, varAddr, varSize); + + // Update response pointer and size + responsePtr += varSize; + responseSize += varSize; + + // Update the lastVarIdx + lastVarIdx = varidx; + } + else + { + // Response buffer is full, break the loop + break; + } + } + + mb_frame_len = 7 + responseSize; // Update response length + mb_frame[1] = MB_FC_DEBUG_GET; + mb_frame[2] = MB_DEBUG_SUCCESS; + mb_frame[3] = (uint8_t)(lastVarIdx >> 8); // High byte + mb_frame[4] = (uint8_t)(lastVarIdx & 0xFF); // Low byte + mb_frame[5] = (uint8_t)((__tick >> 24) & 0xFF); // Highest byte + mb_frame[6] = (uint8_t)((__tick >> 16) & 0xFF); // Second highest byte + mb_frame[7] = (uint8_t)((__tick >> 8) & 0xFF); // Second lowest byte + mb_frame[8] = (uint8_t)(__tick & 0xFF); // Lowest byte + mb_frame[9] = (uint8_t)(responseSize >> 8); // High byte + mb_frame[10] = (uint8_t)(responseSize & 0xFF); // Low byte +} + +/** + * @brief Sends a Modbus response frame for the DEBUG_GET_LIST function code. + * + * This function constructs a Modbus response frame for the DEBUG_GET_LIST function code. + * The response frame includes the trace data for variables specified in the provided index list. + * + * Modbus Response Frame (DEBUG_GET_LIST): + * +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+ + * | MB | Resp. | Last | Last | Tick | Tick | Tick | Tick | Resp. | Resp.| Data | + * | FC | Code | Index | Index | | | | | Size | Size | Bytes | + * +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+ + * |0x44 | Code | High | Low | High | Mid | Mid | Low | High | Low | Data | + * | | | Byte | Byte | Byte | Byte | Byte | Byte | Byte | Byte | Bytes | + * +-----+-------+-------+-------+-------+-------+-------+-------+-------+------+-------+ + * + * @param numIndexes The number of indexes requested. + * @param indexArray Pointer to the array containing variable indexes. + * + * @return void + */ +void debugGetTraceList(uint16_t numIndexes, uint8_t *indexArray) +{ + uint16_t response_idx = 11; // Start of response data in the response buffer + uint16_t responseSize = 0; + uint16_t lastVarIdx = 0; + uint16_t variableCount = get_var_count(); + + #ifdef MBSERIAL + #define VARIDX_SIZE 20 + #else + #define VARIDX_SIZE 60 + #endif + + uint16_t varidx_array[VARIDX_SIZE]; + + // Validate if buffer has space for all indexes + if (numIndexes > VARIDX_SIZE) + { + // Respond with a memory error + mb_frame_len = 3; + mb_frame[1] = MB_FC_DEBUG_GET_LIST; + mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_MEMORY; + return; + } + + // Copy all indexes to array + for (uint16_t i = 0; i < numIndexes; i++) + { + varidx_array[i] = (uint16_t)indexArray[i * 2] << 8 | indexArray[i * 2 + 1]; + } + + // Validate if all requested indexes are in range + for (uint16_t i = 0; i < numIndexes; i++) + { + if (varidx_array[i] >= variableCount) + { + // Respond with an error indicating that the index is out of range + mb_frame_len = 3; + mb_frame[1] = MB_FC_DEBUG_GET_LIST; + mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; + return; + } + + // Add requested indexes and their traces to the response buffer + size_t varSize = get_var_size(varidx_array[i]); + + // Make sure there is enough space in the response buffer + if (response_idx + varSize <= MAX_MB_FRAME) + { + // Add variable data to the response buffer + void *varAddr = get_var_addr(varidx_array[i]); + memcpy(&mb_frame[response_idx], varAddr, varSize); + response_idx += varSize; + responseSize += varSize; + + // Update the lastVarIdx + lastVarIdx = varidx_array[i]; + } + else + { + // Response buffer is full, break the loop + break; + } + } + + // Update response length, lastVarIdx, and response size + mb_frame_len = response_idx; + mb_frame[1] = MB_FC_DEBUG_GET_LIST; + mb_frame[2] = MB_DEBUG_SUCCESS; + mb_frame[3] = (uint8_t)(lastVarIdx >> 8); // High byte + mb_frame[4] = (uint8_t)(lastVarIdx & 0xFF); // Low byte + mb_frame[5] = (uint8_t)((__tick >> 24) & 0xFF); // Highest byte + mb_frame[6] = (uint8_t)((__tick >> 16) & 0xFF); // Second highest byte + mb_frame[7] = (uint8_t)((__tick >> 8) & 0xFF); // Second lowest byte + mb_frame[8] = (uint8_t)(__tick & 0xFF); // Lowest byte + mb_frame[9] = (uint8_t)(responseSize >> 8); // High byte + mb_frame[10] = (uint8_t)(responseSize & 0xFF); // Low byte +} + +void debugGetMd5(void *endianness) +{ + // Check endianness + uint16_t endian_check = 0; + memcpy(&endian_check, endianness, 2); + if (endian_check == 0xDEAD) + { + set_endianness(SAME_ENDIANNESS); + } + else if (endian_check == 0xADDE) + { + set_endianness(REVERSE_ENDIANNESS); + } + else + { + // Respond with an error indicating that the argument is wrong + mb_frame_len = 3; + mb_frame[1] = MB_FC_DEBUG_GET_MD5; + mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; + //return; + } + + mb_frame[1] = MB_FC_DEBUG_GET_MD5; + mb_frame[2] = MB_DEBUG_SUCCESS; + + // Copy MD5 string byte by byte to mb_frame starting from index 3 + const char md5[] = PROGRAM_MD5; + int md5_len = 0; + for (md5_len = 0; md5[md5_len] != '\0'; md5_len++) + { + mb_frame[md5_len + 3] = md5[md5_len]; + } + + // Calculate mb_frame_len (MD5 string length + 3) + mb_frame_len = md5_len + 3; +} + +uint16_t calcCrc() +{ + uint8_t CRCHi = 0xFF, CRCLo = 0x0FF, Index; + + int i = 0; + Index = CRCHi ^ mb_frame[i]; + CRCHi = CRCLo ^ _auchCRCHi[Index]; + CRCLo = _auchCRCLo[Index]; + i++; + + while (i < (mb_frame_len - 2)) + { + Index = CRCHi ^ mb_frame[i]; + i++; + CRCHi = CRCLo ^ _auchCRCHi[Index]; + CRCLo = _auchCRCLo[Index]; + } + + return ((uint16_t)CRCHi << 8) | (uint16_t)CRCLo; +} + + diff --git a/resources/sources/StrucppBaremetal/ModbusSlave.h b/resources/sources/StrucppBaremetal/ModbusSlave.h new file mode 100644 index 000000000..74d1129e6 --- /dev/null +++ b/resources/sources/StrucppBaremetal/ModbusSlave.h @@ -0,0 +1,234 @@ +/* +ModbusSlave.h - Header for Modbus Slave Library +Copyright (C) 2022 OpenPLC - Thiago Alves +*/ + +#ifndef MODBUSSLAVE_H +#define MODBUSSLAVE_H + +#include +#include "defines.h" + +#ifndef bitRead + #define bitRead(value, bit) (((value) >> (bit)) & 0x01) +#endif +//#define bitSet(value, bit) ((value) |= (1UL << (bit))) +//#define bitClear(value, bit) ((value) &= ~(1UL << (bit))) +#ifndef bitWrite + #define bitWrite(value, bit, bitvalue) (bitvalue ? bitSet(value, bit) : bitClear(value, bit)) +#endif +#define COILS 0 +#define INPUTSTATUS 1 +#if defined(__AVR_ATmega328P__) || defined(__AVR_ATmega168__) || defined(__AVR_ATmega32U4__) || defined(__AVR_ATmega16U4__) + #define MAX_MB_FRAME 128 +#else + #define MAX_MB_FRAME 256 +#endif +#define MAX_SRV_CLIENTS 3 //how many clients should be able to connect to TCP server at the same time +#define MBAP_SIZE 6 + +//Platform specific defines and includes +#ifdef MBTCP_ETHERNET +#include +#ifdef BOARD_ESP32 + // I²C-address of Ethernet PHY (0 or 1 for LAN8720, 31 for TLK110) + #define ETH_PHY_ADDR 0 // DEFAULT VALUE IS 0 YOU CAN OMIT IT + // Type of the Ethernet PHY (LAN8720 or TLK110) + #define ETH_PHY_TYPE ETH_PHY_LAN8720 // DEFAULT VALUE YOU CAN OMIT IT + // Pin# of the enable signal for the external crystal oscillator (-1 to disable for internal APLL source) + #define ETH_PHY_POWER -1 // DEFAULT VALUE YOU CAN OMIT IT + // Pin# of the I²C clock signal for the Ethernet PHY + #define ETH_PHY_MDC 23 // DEFAULT VALUE YOU CAN OMIT IT + // Pin# of the I²C IO signal for the Ethernet PHY + #define ETH_PHY_MDIO 18 // DEFAULT VALUE YOU CAN OMIT IT + // External clock from crystal oscillator + #define ETH_CLK_MODE ETH_CLOCK_GPIO0_IN // DEFAULT VALUE YOU CAN OMIT IT + #include + #include +#else + #include +#endif +#endif + +#ifdef MBTCP_WIFI +#if defined(BOARD_ESP8266) +#include +#elif defined(BOARD_ESP32) +#include +#elif defined(BOARD_WIFININA) +#include +#else +#include +#include +#endif +#endif + +#if defined(CONTROLLINO_MAXI) || defined(CONTROLLINO_MEGA) +#include "Controllino.h" +#endif + +// Debugger functions +extern "C" uint16_t get_var_count(void); +extern "C" size_t get_var_size(size_t);// {return 0;} +extern "C" void *get_var_addr(size_t);// {return 0;} +extern "C" void force_var(size_t, bool, void *);// {} +extern "C" void set_trace(size_t, bool, void *);// {} +extern "C" void trace_reset(void);// {} +extern "C" void set_endianness(uint8_t value); +extern uint32_t __tick; + +#define MB_DEBUG_SUCCESS 0x7E +#define MB_DEBUG_ERROR_OUT_OF_BOUNDS 0x81 +#define MB_DEBUG_ERROR_OUT_OF_MEMORY 0x82 +#define SAME_ENDIANNESS 0 +#define REVERSE_ENDIANNESS 1 + +//Modbus registers struct +struct MBinfo { + uint8_t slaveid; + uint16_t *holding; + uint8_t holding_size; + uint32_t *dint_memory; + uint8_t dint_memory_size; + uint64_t *lint_memory; + uint8_t lint_memory_size; + uint8_t *coils; + uint8_t coils_size; + uint16_t *input_regs; + uint8_t input_regs_size; + uint8_t *input_status; + uint8_t input_status_size; +}; + +//Function Codes +enum { + MB_FC_READ_COILS = 0x01, // Read Coils (Output) Status 0xxxx + MB_FC_READ_INPUT_STAT = 0x02, // Read Input Status (Discrete Inputs) 1xxxx + MB_FC_READ_REGS = 0x03, // Read Holding Registers 4xxxx + MB_FC_READ_INPUT_REGS = 0x04, // Read Input Registers 3xxxx + MB_FC_WRITE_COIL = 0x05, // Write Single Coil (Output) 0xxxx + MB_FC_WRITE_REG = 0x06, // Preset Single Register 4xxxx + MB_FC_WRITE_COILS = 0x0F, // Write Multiple Coils (Outputs) 0xxxx + MB_FC_WRITE_REGS = 0x10, // Write block of contiguous registers 4xxxx + MB_FC_DEBUG_INFO = 0x41, // Request debug variables count + MB_FC_DEBUG_SET = 0x42, // Debug set trace (force variable) + MB_FC_DEBUG_GET = 0x43, // Debug get trace (read variables) + MB_FC_DEBUG_GET_LIST = 0x44, // Debug get trace list (read list of variables) + MB_FC_DEBUG_GET_MD5 = 0x45, // Debug get current program MD5 +}; + +//Exception Codes +enum { + MB_EX_ILLEGAL_FUNCTION = 0x01, // Function Code not Supported + MB_EX_ILLEGAL_ADDRESS = 0x02, // Output Address not exists + MB_EX_ILLEGAL_VALUE = 0x03, // Output Value not in Range + MB_EX_SLAVE_FAILURE = 0x04, // Slave Device Fails to process request +}; + +//Global Modbus vars +extern struct MBinfo modbus; +extern uint8_t mb_frame[MAX_MB_FRAME]; +extern uint16_t mb_frame_len; +extern Stream* mb_serialport; +extern int8_t mb_txpin; +extern uint16_t mb_t15; // inter character time out +extern uint16_t mb_t35; // frame delay + +#ifdef MBTCP_ETHERNET +#ifdef BOARD_ESP32 + extern WiFiServer mb_server; +#else + extern EthernetServer mb_server; +#endif + extern uint8_t mb_mbap[MBAP_SIZE]; +#ifdef BOARD_PORTENTA + extern EthernetClient mb_serverClients[MAX_SRV_CLIENTS]; +#endif +#endif + +#ifdef MBTCP_WIFI + extern WiFiServer mb_server; + extern uint8_t mb_mbap[MBAP_SIZE]; +#if defined(BOARD_ESP8266) || defined(BOARD_ESP32) || defined(BOARD_PORTENTA) || defined(BOARD_PICOW) + extern WiFiClient mb_serverClients[MAX_SRV_CLIENTS]; +#endif +#endif + +bool init_mbregs(uint8_t size_holding, uint8_t size_dint_memory, uint8_t size_lint_memory, uint8_t size_coils, uint8_t size_inputregs, uint8_t size_inputstatus); +bool get_discrete(uint16_t addr, bool regtype); +void write_discrete(uint16_t addr, bool regtype, bool value); +void mbconfig_serial_iface(Stream* port, long baud, int txPin); +#ifdef MBTCP +void mbconfig_ethernet_iface(uint8_t *mac, uint8_t *ip, uint8_t *dns, uint8_t *gateway, uint8_t *subnet); +#endif +void mbtask(); +#ifdef MBTCP +void handle_tcp(); +#endif +#ifdef MBSERIAL +void handle_serial(); +#endif +void process_mbpacket(); +uint16_t calcCrc(); + +//Modbus handling functions +void readRegisters(uint16_t startreg, uint16_t numregs); +void writeSingleRegister(uint16_t reg, uint16_t value); +void writeMultipleRegisters(uint16_t startreg, uint16_t numoutputs, uint8_t bytecount); +void exceptionResponse(uint16_t fcode, uint16_t excode); +void readCoils(uint16_t startreg, uint16_t numregs); +void readInputStatus(uint16_t startreg, uint16_t numregs); +void readInputRegisters(uint16_t startreg, uint16_t numregs); +void writeSingleCoil(uint16_t reg, uint16_t status); +void writeMultipleCoils(uint16_t startreg, uint16_t numoutputs, uint16_t bytecount); +void debugInfo(void); +void debugSetTrace(uint16_t varidx, uint8_t flag, uint16_t len, void *value); +void debugGetTrace(uint16_t startidx, uint16_t endidx); +void debugGetTraceList(uint16_t numIndexes, uint8_t *indexArray); +void debugGetMd5(void *endianness); + + +/* Table of CRC values for high-order byte */ +const byte _auchCRCHi[] = { + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, + 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, + 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, + 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, + 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, + 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, 0x40, 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, + 0x00, 0xC1, 0x81, 0x40, 0x01, 0xC0, 0x80, 0x41, 0x01, 0xC0, 0x80, 0x41, 0x00, 0xC1, 0x81, + 0x40}; + +/* Table of CRC values for low-order byte */ +const byte _auchCRCLo[] = { + 0x00, 0xC0, 0xC1, 0x01, 0xC3, 0x03, 0x02, 0xC2, 0xC6, 0x06, 0x07, 0xC7, 0x05, 0xC5, 0xC4, + 0x04, 0xCC, 0x0C, 0x0D, 0xCD, 0x0F, 0xCF, 0xCE, 0x0E, 0x0A, 0xCA, 0xCB, 0x0B, 0xC9, 0x09, + 0x08, 0xC8, 0xD8, 0x18, 0x19, 0xD9, 0x1B, 0xDB, 0xDA, 0x1A, 0x1E, 0xDE, 0xDF, 0x1F, 0xDD, + 0x1D, 0x1C, 0xDC, 0x14, 0xD4, 0xD5, 0x15, 0xD7, 0x17, 0x16, 0xD6, 0xD2, 0x12, 0x13, 0xD3, + 0x11, 0xD1, 0xD0, 0x10, 0xF0, 0x30, 0x31, 0xF1, 0x33, 0xF3, 0xF2, 0x32, 0x36, 0xF6, 0xF7, + 0x37, 0xF5, 0x35, 0x34, 0xF4, 0x3C, 0xFC, 0xFD, 0x3D, 0xFF, 0x3F, 0x3E, 0xFE, 0xFA, 0x3A, + 0x3B, 0xFB, 0x39, 0xF9, 0xF8, 0x38, 0x28, 0xE8, 0xE9, 0x29, 0xEB, 0x2B, 0x2A, 0xEA, 0xEE, + 0x2E, 0x2F, 0xEF, 0x2D, 0xED, 0xEC, 0x2C, 0xE4, 0x24, 0x25, 0xE5, 0x27, 0xE7, 0xE6, 0x26, + 0x22, 0xE2, 0xE3, 0x23, 0xE1, 0x21, 0x20, 0xE0, 0xA0, 0x60, 0x61, 0xA1, 0x63, 0xA3, 0xA2, + 0x62, 0x66, 0xA6, 0xA7, 0x67, 0xA5, 0x65, 0x64, 0xA4, 0x6C, 0xAC, 0xAD, 0x6D, 0xAF, 0x6F, + 0x6E, 0xAE, 0xAA, 0x6A, 0x6B, 0xAB, 0x69, 0xA9, 0xA8, 0x68, 0x78, 0xB8, 0xB9, 0x79, 0xBB, + 0x7B, 0x7A, 0xBA, 0xBE, 0x7E, 0x7F, 0xBF, 0x7D, 0xBD, 0xBC, 0x7C, 0xB4, 0x74, 0x75, 0xB5, + 0x77, 0xB7, 0xB6, 0x76, 0x72, 0xB2, 0xB3, 0x73, 0xB1, 0x71, 0x70, 0xB0, 0x50, 0x90, 0x91, + 0x51, 0x93, 0x53, 0x52, 0x92, 0x96, 0x56, 0x57, 0x97, 0x55, 0x95, 0x94, 0x54, 0x9C, 0x5C, + 0x5D, 0x9D, 0x5F, 0x9F, 0x9E, 0x5E, 0x5A, 0x9A, 0x9B, 0x5B, 0x99, 0x59, 0x58, 0x98, 0x88, + 0x48, 0x49, 0x89, 0x4B, 0x8B, 0x8A, 0x4A, 0x4E, 0x8E, 0x8F, 0x4F, 0x8D, 0x4D, 0x4C, 0x8C, + 0x44, 0x84, 0x85, 0x45, 0x87, 0x47, 0x46, 0x86, 0x82, 0x42, 0x43, 0x83, 0x41, 0x81, 0x80, + 0x40}; + + +#endif diff --git a/resources/sources/StrucppBaremetal/arduino_libs.h b/resources/sources/StrucppBaremetal/arduino_libs.h new file mode 100644 index 000000000..cf8717081 --- /dev/null +++ b/resources/sources/StrucppBaremetal/arduino_libs.h @@ -0,0 +1,39 @@ +//disable pins +//uint8_t disabled_pins[11] = {1, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255}; //10 pins max. First array position is used as index +extern uint8_t pinMask_DIN[]; +extern uint8_t pinMask_AIN[]; +extern uint8_t pinMask_DOUT[]; +extern uint8_t pinMask_AOUT[]; + +#ifdef SIMULATOR_MODE + // Simulator: no-op stubs for all hardware modules (no platform headers needed) + #include "modules/simulator_stubs.c" +#else + #ifdef USE_DS18B20_BLOCK + #include "modules/ds18b20.c" + #endif + + #ifdef USE_P1AM_BLOCKS + #include "modules/p1am.c" + #endif + + #ifdef USE_CLOUD_BLOCKS + #include "modules/arduino_cloud.c" + #endif + + #ifdef USE_MQTT_BLOCKS + #include "modules/mqtt.c" + #endif + + #ifdef USE_SM_BLOCKS + #include "modules/sm_cards.c" + #endif + + #ifdef USE_ARDUINOCAN_BLOCK + #include "modules/arduinocan.c" + #endif + + #ifdef USE_STM32CAN_BLOCK + #include "modules/stm32can.c" + #endif +#endif diff --git a/resources/sources/StrucppBaremetal/c_blocks_code.cpp b/resources/sources/StrucppBaremetal/c_blocks_code.cpp new file mode 100644 index 000000000..21ad6f671 --- /dev/null +++ b/resources/sources/StrucppBaremetal/c_blocks_code.cpp @@ -0,0 +1,43 @@ +#include + +#ifdef ARDUINO +#include +#endif + +/*********************/ +/* IEC Types defs */ +/*********************/ + +typedef uint8_t IEC_BOOL; + +typedef int8_t IEC_SINT; +typedef int16_t IEC_INT; +typedef int32_t IEC_DINT; +typedef int64_t IEC_LINT; + +typedef uint8_t IEC_USINT; +typedef uint16_t IEC_UINT; +typedef uint32_t IEC_UDINT; +typedef uint64_t IEC_ULINT; + +typedef uint8_t IEC_BYTE; +typedef uint16_t IEC_WORD; +typedef uint32_t IEC_DWORD; +typedef uint64_t IEC_LWORD; + +typedef float IEC_REAL; +typedef double IEC_LREAL; + +#ifndef STR_MAX_LEN +#define STR_MAX_LEN 126 +#endif + +#ifndef STR_LEN_TYPE +#define STR_LEN_TYPE int8_t +#endif + +typedef STR_LEN_TYPE __strlen_t; +typedef struct { + __strlen_t len; + uint8_t body[STR_MAX_LEN]; +} IEC_STRING; diff --git a/resources/sources/StrucppBaremetal/hal_conf_extra.h b/resources/sources/StrucppBaremetal/hal_conf_extra.h new file mode 100644 index 000000000..7266ff681 --- /dev/null +++ b/resources/sources/StrucppBaremetal/hal_conf_extra.h @@ -0,0 +1 @@ +#define HAL_CAN_MODULE_ENABLED diff --git a/resources/sources/StrucppBaremetal/modules/arduino_cloud.c b/resources/sources/StrucppBaremetal/modules/arduino_cloud.c new file mode 100644 index 000000000..a48717222 --- /dev/null +++ b/resources/sources/StrucppBaremetal/modules/arduino_cloud.c @@ -0,0 +1,47 @@ +#include +#include + +extern "C" void cloud_begin(char *, char *, char *); +extern "C" void cloud_add_bool(char *, int *); +extern "C" void cloud_add_int(char *, int *); +extern "C" void cloud_add_float(char *, float *); +extern "C" void cloud_update(); + +bool first_update = true; + +WiFiConnectionHandler *ArduinoIoTPreferredConnection; + +void cloud_begin(char *thing_id, char *str_ssid, char *str_pass) +{ + ArduinoIoTPreferredConnection = new WiFiConnectionHandler(str_ssid, str_pass); + ArduinoCloud.setThingId(thing_id); +} + +void cloud_update() +{ + if (first_update) + { + first_update = false; + ArduinoCloud.begin(*ArduinoIoTPreferredConnection); + + //Temporary + setDebugMessageLevel(4); + ArduinoCloud.printDebugInfo(); + } + ArduinoCloud.update(); +} + +void cloud_add_bool(char *var_name, int *bool_var) +{ + ArduinoCloud.addPropertyReal(*bool_var, String(var_name)); +} + +void cloud_add_int(char *var_name, int *int_var) +{ + ArduinoCloud.addPropertyReal(*int_var, String(var_name)); +} + +void cloud_add_float(char *var_name, float *float_var) +{ + ArduinoCloud.addPropertyReal(*float_var, String(var_name)); +} \ No newline at end of file diff --git a/resources/sources/StrucppBaremetal/modules/arduinocan.c b/resources/sources/StrucppBaremetal/modules/arduinocan.c new file mode 100644 index 000000000..35ecb63b5 --- /dev/null +++ b/resources/sources/StrucppBaremetal/modules/arduinocan.c @@ -0,0 +1,74 @@ +#include + +extern "C" void *init_arduinocan(uint8_t,int); +extern "C" bool write_arduinocan(uint32_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t); +extern "C" bool write_arduinocan_word(uint32_t,uint64_t); +extern "C" uint64_t read_arduinocan(); + +void *init_arduinocan(uint8_t pin_en, int baudrate) +{ +#ifdef PIN_CAN0_STBY + if(PIN_CAN0_STBY > -1) { + pinMode(PIN_CAN0_STBY, OUTPUT); + digitalWrite(PIN_CAN0_STBY, LOW); + } else { + pinMode(pin_en, OUTPUT); + digitalWrite(pin_en, LOW); + } +#elif + pinMode(pin_en, OUTPUT); + digitalWrite(pin_en, LOW); +#endif + if (!CAN.begin((CanBitRate)baudrate)) + { + Serial.println("CAN.begin(...) failed."); + for (;;) {} + } +} + +bool write_arduinocan(uint32_t id ,uint8_t d0, uint8_t d1 ,uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, + uint8_t d6, uint8_t d7) +{ + //uint8_t data[4] = {d1, d2, d3, d4}; + uint8_t const msg_data[] = {d0, d1, d2, d3, d4, d5, d6, d7}; + //memcpy((void *)(msg_data + 4), &data, sizeof(data)); + CanMsg msg(id, sizeof(msg_data), msg_data); + + /* Transmit the CAN message, capture and display an + * error core in case of failure. + */ + if (int const rc = CAN.write(msg); rc < 0) + { + return 0; + } + return 1; +} + +bool write_arduinocan_word(uint32_t id , uint64_t data) +{ + + uint32_t const msg_data[2] = {0,0}; + memcpy((void *)(msg_data), &data, sizeof(data)); + CanMsg msg(id, sizeof(msg_data), (uint8_t *)&msg_data); + + if (int const rc = CAN.write(msg); rc < 0) + { + return 0; + } + return 1; +} + +uint64_t read_arduinocan() +{ + uint64_t data = 0; + if (CAN.available()) + { + CanMsg const msg = CAN.read(); + uint8_t payload[8] = {0}; + for(int i = 0; i < msg.data_length || i < 8; i++) { + payload[i] = msg.data[i]; + } + memcpy((void *)(&data), &payload, sizeof(payload)); + } + return data; +} \ No newline at end of file diff --git a/resources/sources/StrucppBaremetal/modules/ds18b20.c b/resources/sources/StrucppBaremetal/modules/ds18b20.c new file mode 100644 index 000000000..4d06cf5b0 --- /dev/null +++ b/resources/sources/StrucppBaremetal/modules/ds18b20.c @@ -0,0 +1,51 @@ +#include +#include + +extern "C" void *init_ds18b20(uint8_t); +extern "C" void request_ds18b20_temperatures(void *); +extern "C" float read_ds18b20(void *, uint8_t); + +void *init_ds18b20(uint8_t pin) +{ + //Disable pin + //disabled_pins[disabled_pins[0]] = pin; + //if (disabled_pins[0] < 10) disabled_pins[0]++; + + for (int i = 0; i < NUM_DISCRETE_INPUT; i++) + { + if (pinMask_DIN[i] == pin) + pinMask_DIN[i] = 255; + } + for (int i = 0; i < NUM_ANALOG_INPUT; i++) + { + if (pinMask_AIN[i] == pin) + pinMask_AIN[i] = 255; + } + for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++) + { + if (pinMask_DOUT[i] == pin) + pinMask_DOUT[i] = 255; + } + for (int i = 0; i < NUM_ANALOG_OUTPUT; i++) + { + if (pinMask_AOUT[i] == pin) + pinMask_AOUT[i] = 255; + } + + OneWire *oneWire; + DallasTemperature *sensors; + oneWire = new OneWire(pin); + sensors = new DallasTemperature(oneWire); + sensors->begin(); + return sensors; +} +void request_ds18b20_temperatures(void *class_pointer) +{ + DallasTemperature *sensors = (DallasTemperature *)class_pointer; + sensors->requestTemperatures(); +} +float read_ds18b20(void *class_pointer, uint8_t index) +{ + DallasTemperature *sensors = (DallasTemperature *)class_pointer; + return sensors->getTempCByIndex(index); +} \ No newline at end of file diff --git a/resources/sources/StrucppBaremetal/modules/mqtt.c b/resources/sources/StrucppBaremetal/modules/mqtt.c new file mode 100644 index 000000000..46c9efaae --- /dev/null +++ b/resources/sources/StrucppBaremetal/modules/mqtt.c @@ -0,0 +1,221 @@ +/* +#include + +WiFiClient wifiClient; +MqttClient mqttClient(wifiClient); + +extern "C" uint8_t connect_mqtt(char *broker, uint16_t port); +extern "C" uint8_t mqtt_send(char *topic, char *message); + +uint8_t connect_mqtt(char *broker, uint16_t port) +{ + return mqttClient.connect(broker, port); +} + +uint8_t mqtt_send(char *topic, char *message) +{ + mqttClient.beginMessage(topic); + mqttClient.print(message); + mqttClient.endMessage(); + + return 1; +} +*/ + +#include +//Reference: https://www.hivemq.com/blog/mqtt-client-library-encyclopedia-arduino-pubsubclient/ + +#ifdef MBTCP_ETHERNET +#ifdef BOARD_ESP32 + WiFiClient wifiClient; +#else + EthernetClient wifiClient; +#endif +#else + WiFiClient wifiClient; +#endif +PubSubClient mqttClient(wifiClient); + +extern "C" uint8_t connect_mqtt(char *broker, uint16_t port); +extern "C" uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password); +extern "C" uint8_t mqtt_send(char *topic, char *message); +extern "C" uint8_t mqtt_receive(char *topic, char *message); +extern "C" uint8_t mqtt_subscribe(char *topic); +extern "C" uint8_t mqtt_unsubscribe(char *topic); +extern "C" uint8_t mqtt_disconnect(); +extern "C" void mqtt_loop(); + +#define STR_MAX_LEN 126 +#define POOL_INCREMENT 2 +#define MAX_POOL_SIZE 10 + +struct MQTTpool { + char mqtt_msg[STR_MAX_LEN]; + char mqtt_topic[STR_MAX_LEN]; + uint8_t is_free = true; +}; + +uint8_t pool_size = 0; +struct MQTTpool **msg_pool = NULL; + +void add_message_to_pool(char *topic, char *msg) +{ + // Initialize array + if (pool_size == 0) + { + pool_size += POOL_INCREMENT; + msg_pool = (struct MQTTpool **)malloc(pool_size * sizeof(struct MQTTpool *)); + + if (msg_pool == NULL) + { + // Allocation failed! Nothing to do here + return; + } + + // Allocate memory for each pool item + for (int i = 0; i < POOL_INCREMENT; i++) + { + msg_pool[i] = (struct MQTTpool *)malloc(sizeof(struct MQTTpool)); + if (msg_pool[i] == NULL) + { + // Allocation failed! Nothing to do here + return; + } + } + } + + // Add message to the pool + uint8_t message_added = false; + while (!message_added) + { + for (int i = 0; i < pool_size; i++) + { + if (msg_pool[i]->is_free) + { + strncpy(msg_pool[i]->mqtt_topic, topic, STR_MAX_LEN); + msg_pool[i]->mqtt_topic[STR_MAX_LEN - 1] = '\0'; // Safe termination + strncpy(msg_pool[i]->mqtt_msg, msg, STR_MAX_LEN); + msg_pool[i]->mqtt_msg[STR_MAX_LEN - 1] = '\0'; // Safe termination + msg_pool[i]->is_free = false; + message_added = true; + break; + } + } + + // Pool is full + if (!message_added) + { + // Increase pool size + pool_size += POOL_INCREMENT; + if (pool_size > MAX_POOL_SIZE) + { + // This is bad! No more space left. We must remove one of the messages + pool_size -= POOL_INCREMENT; + msg_pool[0]->is_free = true; + } + else + { + // Reallocate new size + msg_pool = (struct MQTTpool **)realloc(msg_pool, pool_size * sizeof(struct MQTTpool *)); + + if (msg_pool == NULL) + { + // This is VERY bad!! Let's ignore this message, remove everything and start over + pool_size = 0; + return; + } + + // Allocate memory for each pool item + for (int i = (pool_size - POOL_INCREMENT); i < pool_size; i++) + { + msg_pool[i] = (struct MQTTpool *)malloc(sizeof(struct MQTTpool)); + if (msg_pool[i] == NULL) + { + // Allocation failed! Nothing to do here + return; + } + msg_pool[i]->is_free = true; + } + } + } + } +} + +void callback(char* topic, byte* payload, unsigned int length) +{ + if (length > (STR_MAX_LEN - 1)) + { + length = (STR_MAX_LEN - 1); // truncate string to max size + } + payload[length] = 0; // make sure string is NULL terminated + + add_message_to_pool(topic, (char *)payload); +} + +void mqtt_loop() +{ + mqttClient.loop(); +} + +uint8_t connect_mqtt(char *broker, uint16_t port) +{ + mqttClient.setServer(broker, port); + mqttClient.setCallback(callback); + return mqttClient.connect("openplc-client"); +} + +uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password) +{ + mqttClient.setServer(broker, port); + mqttClient.setCallback(callback); + return mqttClient.connect("openplc-client", user, password); +} + +uint8_t mqtt_send(char *topic, char *message) +{ + /* + mqttClient.beginMessage(topic); + mqttClient.print(message); + mqttClient.endMessage(); + + return 1; + */ + + return mqttClient.publish(topic, message); +} + +uint8_t mqtt_subscribe(char *topic) +{ + return (uint8_t)mqttClient.subscribe(topic); +} + +uint8_t mqtt_receive(char *topic, char *message) +{ + // Return the first message in the pool that matches topic + for (int i = 0; i < pool_size; i++) + { + // Check if there are messages in the pool + if (!msg_pool[i]->is_free) + { + if (!strncmp(topic, msg_pool[i]->mqtt_topic, STR_MAX_LEN)) + { + strncpy(message, msg_pool[i]->mqtt_msg, STR_MAX_LEN); + msg_pool[i]->is_free = true; + return strlen(message); + } + } + } + + return 0; +} + +uint8_t mqtt_unsubscribe(char *topic) +{ + return (uint8_t)mqttClient.unsubscribe(topic); +} + +uint8_t mqtt_disconnect() +{ + mqttClient.disconnect(); + return 1; +} diff --git a/resources/sources/StrucppBaremetal/modules/p1am.c b/resources/sources/StrucppBaremetal/modules/p1am.c new file mode 100644 index 000000000..cd5f7db6c --- /dev/null +++ b/resources/sources/StrucppBaremetal/modules/p1am.c @@ -0,0 +1,32 @@ +#include +extern "C" uint8_t p1am_init(); +extern "C" void p1am_writeDiscrete(uint32_t, uint8_t, uint8_t); +extern "C" uint32_t p1am_readDiscrete(uint8_t, uint8_t); +extern "C" uint16_t p1am_readAnalog(uint8_t, uint8_t); + +uint8_t modules_initialized = 0; + +uint8_t p1am_init() +{ + if (modules_initialized == 0) + { + modules_initialized = P1.init(); + } + + return modules_initialized; +} + +void p1am_writeDiscrete(uint32_t data, uint8_t slot, uint8_t channel) +{ + P1.writeDiscrete(data, slot, channel); +} + +uint32_t p1am_readDiscrete(uint8_t slot, uint8_t channel) +{ + return P1.readDiscrete(slot, channel); +} + +uint16_t p1am_readAnalog(uint8_t slot, uint8_t channel) +{ + return (uint16_t)P1.readAnalog(slot, channel); +} diff --git a/resources/sources/StrucppBaremetal/modules/simulator_stubs.c b/resources/sources/StrucppBaremetal/modules/simulator_stubs.c new file mode 100644 index 000000000..1af06ef57 --- /dev/null +++ b/resources/sources/StrucppBaremetal/modules/simulator_stubs.c @@ -0,0 +1,399 @@ +/* + * Simulator stub implementations for hardware-dependent function blocks. + * + * When compiling for the AVR simulator (SIMULATOR_MODE), this file provides + * no-op implementations of every extern "C" function from the hardware module + * files (p1am, mqtt, ds18b20, arduinocan, stm32can, sm_cards, arduino_cloud) + * plus the TCP communication functions from MatIEC. + * + * No platform-specific headers are needed — only stdint.h and stddef.h. + */ + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* ======================================================================== + * P1AM module stubs (p1am.c) + * ======================================================================== */ + +uint8_t p1am_init() { + return 0; +} + +void p1am_writeDiscrete(uint32_t data, uint8_t slot, uint8_t channel) { + (void)data; (void)slot; (void)channel; +} + +uint32_t p1am_readDiscrete(uint8_t slot, uint8_t channel) { + (void)slot; (void)channel; + return 0; +} + +uint16_t p1am_readAnalog(uint8_t slot, uint8_t channel) { + (void)slot; (void)channel; + return 0; +} + +/* ======================================================================== + * MQTT module stubs (mqtt.c) + * ======================================================================== */ + +uint8_t connect_mqtt(char *broker, uint16_t port) { + (void)broker; (void)port; + return 0; +} + +uint8_t connect_mqtt_auth(char *broker, uint16_t port, char *user, char *password) { + (void)broker; (void)port; (void)user; (void)password; + return 0; +} + +uint8_t mqtt_send(char *topic, char *message) { + (void)topic; (void)message; + return 0; +} + +uint8_t mqtt_receive(char *topic, char *message) { + (void)topic; (void)message; + return 0; +} + +uint8_t mqtt_subscribe(char *topic) { + (void)topic; + return 0; +} + +uint8_t mqtt_unsubscribe(char *topic) { + (void)topic; + return 0; +} + +uint8_t mqtt_disconnect() { + return 0; +} + +void mqtt_loop() { +} + +/* ======================================================================== + * DS18B20 module stubs (ds18b20.c) + * ======================================================================== */ + +void *init_ds18b20(uint8_t pin) { + (void)pin; + return NULL; +} + +void request_ds18b20_temperatures(void *class_pointer) { + (void)class_pointer; +} + +float read_ds18b20(void *class_pointer, uint8_t index) { + (void)class_pointer; (void)index; + return 0.0f; +} + +/* ======================================================================== + * Arduino CAN module stubs (arduinocan.c) + * ======================================================================== */ + +void *init_arduinocan(uint8_t pin_en, int baudrate) { + (void)pin_en; (void)baudrate; + return NULL; +} + +uint8_t write_arduinocan(uint32_t id, uint8_t d0, uint8_t d1, uint8_t d2, + uint8_t d3, uint8_t d4, uint8_t d5, uint8_t d6, uint8_t d7) { + (void)id; (void)d0; (void)d1; (void)d2; + (void)d3; (void)d4; (void)d5; (void)d6; (void)d7; + return 0; +} + +uint8_t write_arduinocan_word(uint32_t id, uint64_t data) { + (void)id; (void)data; + return 0; +} + +uint64_t read_arduinocan() { + return 0; +} + +/* ======================================================================== + * STM32 CAN module stubs (stm32can.c) + * ======================================================================== */ + +uint8_t init_stm32can(int baudrate) { + (void)baudrate; + return 0; +} + +uint8_t write_stm32can(uint8_t ch, uint32_t id, uint8_t d0, uint8_t d1, + uint8_t d2, uint8_t d3, uint8_t d4, uint8_t d5, + uint8_t d6, uint8_t d7) { + (void)ch; (void)id; (void)d0; (void)d1; + (void)d2; (void)d3; (void)d4; (void)d5; + (void)d6; (void)d7; + return 0; +} + +uint8_t read_stm32can(uint32_t *id, uint8_t *d0, uint8_t *d1, uint8_t *d2, + uint8_t *d3, uint8_t *d4, uint8_t *d5, uint8_t *d6, + uint8_t *d7) { + (void)id; (void)d0; (void)d1; (void)d2; + (void)d3; (void)d4; (void)d5; (void)d6; (void)d7; + return 0; +} + +/* ======================================================================== + * Sequent Microsystems cards stubs (sm_cards.c) + * ======================================================================== */ + +/* 8-Relay Card */ +int relay8Init(int stack) { + (void)stack; + return 0; +} + +int relays8Set(uint8_t stack, uint8_t val) { + (void)stack; (void)val; + return 0; +} + +/* 16-Relay Card */ +int relay16Init(int stack) { + (void)stack; + return 0; +} + +int relay16Set(uint8_t stack, uint16_t val) { + (void)stack; (void)val; + return 0; +} + +/* 8 Digital Inputs Card */ +int digIn8Init(int stack) { + (void)stack; + return 0; +} + +int digIn8Get(uint8_t stack, uint8_t *val) { + (void)stack; (void)val; + return 0; +} + +/* 16 Digital Inputs Card */ +int digIn16Init(int stack) { + (void)stack; + return 0; +} + +int digIn16Get(uint8_t stack, uint16_t *val) { + (void)stack; (void)val; + return 0; +} + +/* 4-Relay 4-Input Card (r4i4) */ +int r4i4SetRelays(uint8_t stack, uint8_t value) { + (void)stack; (void)value; + return 0; +} + +int r4i4GetOptoInputs(uint8_t stack, uint8_t *val) { + (void)stack; (void)val; + return 0; +} + +int r4i4GetACInputs(uint8_t stack, uint8_t *val) { + (void)stack; (void)val; + return 0; +} + +int r4i4GetButton(uint8_t stack, uint8_t *button) { + (void)stack; (void)button; + return 0; +} + +int r4i4GetPWMInFill(uint8_t stack, uint8_t channel, uint16_t *value) { + (void)stack; (void)channel; (void)value; + return 0; +} + +int r4i4GetPWMInFreq(uint8_t stack, uint8_t channel, uint16_t *value) { + (void)stack; (void)channel; (void)value; + return 0; +} + +/* RTD Temperature Card */ +int rtdGetTemp(uint8_t stack, uint8_t channel, float *value) { + (void)stack; (void)channel; (void)value; + return 0; +} + +/* Industrial Automation Card */ +int indSetLeds(uint8_t stack, uint8_t value) { + (void)stack; (void)value; + return 0; +} + +int indGetOptoInputs(uint8_t stack, uint8_t *val) { + (void)stack; (void)val; + return 0; +} + +int indGet0_10Vin(uint8_t stack, uint8_t channel, float *val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int indGet4_20mAin(uint8_t stack, uint8_t channel, float *val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int indGet1WbTemp(uint8_t stack, uint8_t channel, float *val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int indSet0_10Vout(uint8_t stack, uint8_t channel, float val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int indSet4_20mAout(uint8_t stack, uint8_t channel, float val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int indSetPWMout(uint8_t stack, uint8_t channel, float val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +/* Building Automation Card */ +int basSetLeds(uint8_t stack, uint8_t value) { + (void)stack; (void)value; + return 0; +} + +int basSetTriacs(uint8_t stack, uint8_t value) { + (void)stack; (void)value; + return 0; +} + +int basSet0_10Vout(uint8_t stack, uint8_t channel, float val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int basGetDryContacts(uint8_t stack, uint8_t *val) { + (void)stack; (void)val; + return 0; +} + +int basGetUniversalIn(uint8_t stack, uint8_t channel, uint8_t type, float *val) { + (void)stack; (void)channel; (void)type; (void)val; + return 0; +} + +int basGet1WbTemp(uint8_t stack, uint8_t channel, float *val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +/* Home Automation Card */ +int homeSetRelays(uint8_t stack, uint8_t value) { + (void)stack; (void)value; + return 0; +} + +int homeSet0_10Vout(uint8_t stack, uint8_t channel, float val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int homeSetOD(uint8_t stack, uint8_t channel, float val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int homeGetOpto(uint8_t stack, uint8_t *val) { + (void)stack; (void)val; + return 0; +} + +int homeGetADC(uint8_t stack, uint8_t channel, float *val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +int homeGet1WbTemp(uint8_t stack, uint8_t channel, float *val) { + (void)stack; (void)channel; (void)val; + return 0; +} + +/* 8-MOSFET Card */ +int mosfet8Init(int stack) { + (void)stack; + return 0; +} + +int mosfets8Set(uint8_t stack, uint8_t val) { + (void)stack; (void)val; + return 0; +} + +/* ======================================================================== + * Arduino Cloud module stubs (arduino_cloud.c) + * ======================================================================== */ + +void cloud_begin(char *thing_id, char *str_ssid, char *str_pass) { + (void)thing_id; (void)str_ssid; (void)str_pass; +} + +void cloud_add_bool(char *var_name, int *bool_var) { + (void)var_name; (void)bool_var; +} + +void cloud_add_int(char *var_name, int *int_var) { + (void)var_name; (void)int_var; +} + +void cloud_add_float(char *var_name, float *float_var) { + (void)var_name; (void)float_var; +} + +void cloud_update() { +} + +/* ======================================================================== + * TCP communication stubs (MatIEC communication.h) + * ======================================================================== */ + +int connect_to_tcp_server(uint8_t *ip_address, uint16_t port, int method) { + (void)ip_address; (void)port; (void)method; + return -1; +} + +int send_tcp_message(uint8_t *msg, size_t msg_size, int socket_id) { + (void)msg; (void)msg_size; (void)socket_id; + return 0; +} + +int receive_tcp_message(uint8_t *msg_buffer, size_t buffer_size, int socket_id) { + (void)msg_buffer; (void)buffer_size; (void)socket_id; + return 0; +} + +int close_tcp_connection(int socket_id) { + (void)socket_id; + return 0; +} + +#ifdef __cplusplus +} +#endif diff --git a/resources/sources/StrucppBaremetal/modules/sm_cards.c b/resources/sources/StrucppBaremetal/modules/sm_cards.c new file mode 100644 index 000000000..78169dc66 --- /dev/null +++ b/resources/sources/StrucppBaremetal/modules/sm_cards.c @@ -0,0 +1,1550 @@ +#include +#include "Arduino.h" +#include "Wire.h" + +#define OK 0 +#define ERROR -1 + +extern "C" int relay8Init(int); +extern "C" int relays8Set(uint8_t, uint8_t); + +int i2cMemRead(uint8_t hwAddr, uint8_t memAddr, uint8_t* buff, uint8_t size) +{ + if(buff == NULL) + { + return ERROR; + } + Wire.begin(); + Wire.beginTransmission(hwAddr); + Wire.write(memAddr); + if (Wire.endTransmission() != 0) + { + return ERROR; + } + + Wire.requestFrom(hwAddr, (uint8_t)size); + while (Wire.available()) + { + *buff = Wire.read(); + buff++; + } + + return OK; +} + +int i2cMemWrite(uint8_t hwAddr, uint8_t memAddr, uint8_t* buff, uint8_t size) +{ + uint8_t byteCount = 0; + + if(buff == NULL) + { + return ERROR; + } + Wire.begin(); + Wire.beginTransmission(hwAddr); + Wire.write(memAddr); + while(byteCount < size) + { + Wire.write(*buff); + buff ++; + byteCount++; + } + return Wire.endTransmission(); +} + +#define RELAY8_HW_I2C_BASE_ADD 0x20 +#define RELAY8_HW_I2C_BASE_ALT_ADD 0x38 +#define RELAY8_INPORT_REG_ADD 0x00 +#define RELAY8_OUTPORT_REG_ADD 0x01 +#define RELAY8_POLINV_REG_ADD 0x02 +#define RELAY8_CFG_REG_ADD 0x03 +#define RELAY8_REG_COUNT 0x04 +#define STACK_LEVELS 8 +uint8_t relay8_presence = 0; + +const uint8_t relay8MaskRemap[8] = {0x01, 0x04, 0x40, 0x10, 0x20, 0x80, 0x08, + 0x02}; + +uint8_t relay8ToIO(uint8_t relay) +{ + uint8_t i; + uint8_t val = 0; + for (i = 0; i < 8; i++) + { + if ( (relay & (1 << i)) != 0) + val += relay8MaskRemap[i]; + } + return val; +} + +int relay8CardCheck(int stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + return ERROR; + } + add = (stack + RELAY8_HW_I2C_BASE_ADD) ^ 0x07; + return add; +} + +int relay8Init(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + + dev = relay8CardCheck(stack); + if (dev <= 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, RELAY8_CFG_REG_ADD, buff, 1)) + { + return ERROR; + } + if (OK == i2cMemRead(dev, RELAY8_REG_COUNT, buff, 1)) //16 bits I/O expander found + { + return ERROR; + } + if (buff[0] != 0) //non initialized I/O Expander + { + // make all I/O pins output + buff[0] = 0; + if (OK > i2cMemWrite(dev, RELAY8_CFG_REG_ADD, buff, 1)) + { + return ERROR; + } + // put all pins in 0-logic state + buff[0] = 0; + if (OK > i2cMemWrite(dev, RELAY8_OUTPORT_REG_ADD, buff, 1)) + { + return ERROR; + } + } + relay8_presence |= 1 << stack; + return OK; +} + +int relays8Set(uint8_t stack, uint8_t val) +{ + uint8_t buff[2]; + int dev = -1; + static uint8_t relaysOldVal[STACK_LEVELS] = {0, 0, 0, 0, 0, 0, 0, 0}; + + if (stack >= 8) + { + return ERROR; + } + + if (relaysOldVal[stack] == val) + { + return OK; + } + dev = relay8CardCheck(stack); + if (dev <= 0) + { + return ERROR; + } + + buff[0] = relay8ToIO(val); + + if (OK != i2cMemWrite(dev, RELAY8_OUTPORT_REG_ADD, buff, 1)) + { + return ERROR; + } + relaysOldVal[stack] = val; + return OK; +} + +// --------------------- 16RELAYS -------------------------------------- + +extern "C" int relay16Init(int); +extern "C" int relay16Set(uint8_t, uint16_t); + +#define RELAY16_CHANNELS 16 +#define RELAY16_HW_I2C_BASE_ADD 0x20 +#define RELAY16_INPORT_REG_ADD 0x00 +#define RELAY16_OUTPORT_REG_ADD 0x02 +#define RELAY16_POLINV_REG_ADD 0x04 +#define RELAY16_CFG_REG_ADD 0x06 + +#define RELAY16_X_PLC_OFFSET 64 +#define RELAY16_STACK_MIN 0 +#define RELAY16_STACK_LEVELS 4 + +const uint16_t relayMaskRemap16[RELAY16_CHANNELS] = {0x8000, 0x4000, 0x2000, + 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, + 0x1}; + +uint16_t relayToIO16(uint16_t relay) +{ + uint8_t i; + uint16_t val = 0; + for (i = 0; i < 16; i++) + { + if ( (relay & (1 << i)) != 0) + val += relayMaskRemap16[i]; + } + return val; +} + +uint16_t IOToRelay16(uint16_t io) +{ + uint8_t i; + uint16_t val = 0; + for (i = 0; i < 16; i++) + { + if ( (io & relayMaskRemap16[i]) != 0) + { + val += 1 << i; + } + } + return val; +} + +int relay16CardCheck(uint8_t stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + return ERROR; + } + add = (stack + RELAY16_HW_I2C_BASE_ADD) ^ 0x07; + return add; +} + +int relay16Init(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + uint16_t val = 0; + + dev = relay16CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, RELAY16_CFG_REG_ADD, buff, 2)) // 16 bits IO expander found + { + return ERROR; + } + memcpy(&val, buff, 2); + if (val != 0) //non initialized I/O Expander + { + // make all I/O pins output + val = 0; + memcpy(buff, &val, 2); + if (OK > i2cMemWrite(dev, RELAY16_CFG_REG_ADD, buff, 2)) + { + return ERROR; + } + // put all pins in 0-logic state + if (OK > i2cMemWrite(dev, RELAY16_OUTPORT_REG_ADD, buff, 2)) + { + return ERROR; + } + } + return OK; +} + +int relay16Set(uint8_t stack, uint16_t val) +{ + static uint16_t relaysOldVal[STACK_LEVELS] = {0, 0, 0, 0, 0, 0, 0, 0}; + uint8_t buff[2]; + uint16_t rVal = 0; + int dev = -1; + + if (stack >= STACK_LEVELS) + { + return ERROR; + } + if (relaysOldVal[stack] == val) + { + return OK; + } + dev = relay16CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + rVal = relayToIO16(val); + memcpy(buff, &rVal, 2); + + if (OK == i2cMemWrite(dev, RELAY16_OUTPORT_REG_ADD, buff, 2)) + { + relaysOldVal[stack] = val; + return OK; + } + return ERROR; +} + + +//----------------------------------------------------------------------------- +// Eight High Voltage Digital Inputs 8-Layer Stackable HAT for Raspberry Pi +//----------------------------------------------------------------------------- + +extern "C" int digIn8Get(uint8_t, uint8_t*); +extern "C" int digIn8Init(int ); + +#define DIG_IN8_CHANNELS 8 +#define DIG_IN8_HW_I2C_BASE_ADD 0x20 +#define DIG_IN8_INPORT_REG_ADD 0x00 +#define DIG_IN8_OUTPORT_REG_ADD 0x01 +#define DIG_IN8_POLINV_REG_ADD 0x02 +#define DIG_IN8_CFG_REG_ADD 0x03 + +const uint8_t inputsMaskRemap8[DIG_IN8_CHANNELS] ={0x08, 0x04, 0x02, 0x01, 0x10, 0x20, 0x40, 0x80}; + +int digIn8CardCheck(uint8_t stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + //printf("Invalid stack level [0..7]!"); + return ERROR; + } + add = (stack + DIG_IN8_HW_I2C_BASE_ADD) ^ 0x07; + return add; +} + +int digIn8Init(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + uint8_t val = 0; + + dev = digIn8CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, DIG_IN8_CFG_REG_ADD, buff, 1)) + { + return ERROR; + } + + if (buff[0] != 0xff) //non initialized I/O Expander + { + // make all I/O pins inputs + buff[0] = 0xff; + if (OK != i2cMemWrite(dev, RELAY8_CFG_REG_ADD, buff, 1)) + { + return ERROR; + } + } + return OK; +} + +int digIn8Get(uint8_t stack, uint8_t *val) +{ + int dev = -1; + uint8_t buff[2]; + uint8_t raw = 0; + uint8_t i = 0; + + if (stack >= STACK_LEVELS || val == NULL) + { + return ERROR; + } + dev = digIn8CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (OK != i2cMemRead(dev, DIG_IN8_INPORT_REG_ADD, buff, 1)) + { + return ERROR; + } + raw = 0xff & (~buff[0]); + *val = 0; + for (i = 0; i < 8; i++) + { + if (raw & inputsMaskRemap8[i]) + { + *val += 1 << i; + } + } + return OK; +} + + + +//------------------------------------------------------------------------------ +// Sixteen Digital Inputs 8-Layer Stackable HAT for Raspberry Pi +//------------------------------------------------------------------------------ + +extern "C" int digIn16Get(uint8_t, uint16_t*); +extern "C" int digIn16Init(int ); + +#define DIG_IN16_CHANNELS 16 +#define DIG_IN16_HW_I2C_BASE_ADD 0x20 +#define DIG_IN16_INPORT_REG_ADD 0x00 +#define DIG_IN16_OUTPORT_REG_ADD 0x02 +#define DIG_IN16_POLINV_REG_ADD 0x04 +#define DIG_IN16_CFG_REG_ADD 0x06 + +#define DIG_IN16_X_PLC_OFFSET 0 + +#define DIG_IN16_STACK_MIN 4 +#define DIG_IN16_STACK_LEVELS 4 + +const uint16_t inputsMaskRemap16[DIG_IN16_CHANNELS] = {0x8000, 0x4000, 0x2000, + 0x1000, 0x800, 0x400, 0x200, 0x100, 0x80, 0x40, 0x20, 0x10, 0x8, 0x4, 0x2, + 0x1}; + +int digIn16CardCheck(uint8_t stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + //printf("Invalid stack level [0..7]!"); + return ERROR; + } + add = (stack + DIG_IN16_HW_I2C_BASE_ADD) ^ 0x07; + return add; +} + +int digIn16Init(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + uint16_t val = 0; + + dev = digIn16CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, DIG_IN16_CFG_REG_ADD, buff, 2)) + { + return ERROR; + } + memcpy(&val, buff, 2); + if (val != 0xffff) //non initialized I/O Expander + { + // make all I/O pins inputs + val = 0xffff; + memcpy(buff, &val, 2); + if (OK != i2cMemWrite(dev, RELAY16_CFG_REG_ADD, buff, 2)) + { + return ERROR; + } + } + return OK; +} + +int digIn16Get(uint8_t stack, uint16_t *val) +{ + int dev = -1; + uint8_t buff[2]; + uint16_t raw = 0; + uint8_t i = 0; + + if (stack >= STACK_LEVELS || val == NULL) + { + return ERROR; + } + dev = digIn16CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (OK != i2cMemRead(dev, DIG_IN16_INPORT_REG_ADD, buff, 2)) + { + return ERROR; + } + raw = (0xff & (~buff[0])) + ( (0xff & (~buff[1])) << 8); + *val = 0; + for (i = 0; i < 16; i++) + { + if (raw & inputsMaskRemap16[i]) + { + *val += 1 << i; + } + } + return OK; +} + + +//------------------------------------------------------------------------------ +// Four Relays four HV Inputs 8-Layer Stackable HAT for Raspberry Pi +//------------------------------------------------------------------------------- + +extern "C" int r4i4SetRelays(uint8_t, uint8_t); +extern "C" int r4i4GetOptoInputs(uint8_t, uint8_t*); +extern "C" int r4i4GetACInputs(uint8_t, uint8_t*); +extern "C" int r4i4GetButton(uint8_t, uint8_t*); +extern "C" int r4i4GetPWMInFill(uint8_t, uint8_t, uint16_t*); +extern "C" int r4i4GetPWMInFreq(uint8_t, uint8_t, uint16_t*); + +#define I2C_REL4_IN4_ADDRESS_BASE 0x0e + +#define R4I4_I2C_MEM_RELAY_VAL 0//reserved 4 bits for open-drain and 4 bits for leds +#define R4I4_I2C_MEM_DIG_IN 3 +#define R4I4_I2C_MEM_AC_IN 4 +#define R4I4_I2C_MEM_PWM_IN_FILL 45 +#define R4I4_I2C_MEM_IN_FREQENCY 53 +#define R4I4_I2C_MEM_BUTTON 71 +#define R4I4_I2C_MEM_REVISION_MAJOR_ADD 120 + +#define R4I4_CHANNEL_NR_MIN 1 + +#define R4I4_OPTO_CH_NR_MAX 4 +#define R4I4_REL_CH_NR_MAX 4 + +#define R4I4_REL_PLC_OFFSET_BITS 0 +#define R4I4_OPTO_IN_PLC_OFFSET_BITS 0 +#define R4I4_AC_IN_PLC_OFFSET_BITS 4 +#define R4I4_PWM_IN_FILL_PLC_OFFSET 0 +#define R4I4_PWM_IN_FREQ_PLC_OFFSET 4 +#define R4I4_BUTTON_PLC_OFFSET 9 + +int r4i4CardCheck(uint8_t stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + return ERROR; + } + add = stack + I2C_REL4_IN4_ADDRESS_BASE; + return add; +} + +int r4i4Init(int stack) +{ + int dev = -1; + uint8_t buff[2]; + uint16_t val = 0; + + dev = r4i4CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, R4I4_I2C_MEM_REVISION_MAJOR_ADD, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int r4i4SetRelays(uint8_t stack, uint8_t value) +{ + static uint8_t prevRelays[STACK_LEVELS] = {0, 0, 0, 0, 0, 0, 0, 0}; + int dev = -1; + + if (stack >= STACK_LEVELS) + { + return ERROR; + } + if (prevRelays[stack] == value) + { + return OK; // prevent usless transactions on I2C bus + } + dev = r4i4CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemWrite(dev, R4I4_I2C_MEM_RELAY_VAL, &value, 1)) + { + return ERROR; + } + prevRelays[stack] = value; + return OK; +} + +int r4i4GetOptoInputs(uint8_t stack, uint8_t *val) +{ + int dev = -1; + + if (val == NULL) + { + return ERROR; + } + dev = r4i4CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + return i2cMemRead(dev, R4I4_I2C_MEM_DIG_IN, val, 1); +} + +int r4i4GetACInputs(uint8_t stack, uint8_t *val) +{ + int dev = -1; + + if (val == NULL) + { + return ERROR; + } + dev = r4i4CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + return i2cMemRead(dev, R4I4_I2C_MEM_AC_IN, val, 1); +} + +int r4i4GetButton(uint8_t stack, uint8_t *button) +{ + int dev = -1; + uint8_t val; + + if (button == NULL) + { + return ERROR; + } + dev = r4i4CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + if (OK != i2cMemRead(dev, R4I4_I2C_MEM_BUTTON, &val, 1)) + { + return ERROR; + } + *button = 0x01 & val; + return OK; +} + +int r4i4GetPWMInFill(uint8_t stack, uint8_t channel, uint16_t *value) +{ + int dev = -1; + uint8_t buff[2]; + + if (channel >= R4I4_OPTO_CH_NR_MAX || value == NULL) + { + return ERROR; + } + + dev = r4i4CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + if (OK != i2cMemRead(dev, R4I4_I2C_MEM_PWM_IN_FILL + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(value, buff, 2); + return OK; +} + +int r4i4GetPWMInFreq(uint8_t stack, uint8_t channel, uint16_t *value) +{ + int dev = -1; + uint8_t buff[2]; + + if (channel >= R4I4_OPTO_CH_NR_MAX || value == NULL) + { + return ERROR; + } + + dev = r4i4CardCheck(stack); + if (dev < 0) + { + return ERROR; + } + if (OK != i2cMemRead(dev, R4I4_I2C_MEM_IN_FREQENCY + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(value, buff, 2); + return OK; +} + +//------------------------------------------------------------------------------ +// RTD Data Acquisition 8-Layer Stackable HAT for Raspberry Pi +//------------------------------------------------------------------------------ + +extern "C" int rtdGetTemp(uint8_t, uint8_t, float*); + +#define I2C_RTD_ADDRESS_BASE 0x40 + +#define RTD_I2C_VAL1_ADD 0//reserved 4 bits for open-drain and 4 bits for leds +#define RTD_I2C_MEM_REVISION_MAJOR_ADD 57 + +#define RTD_CHANNEL_NR_MIN 1 +#define RTD_CH_NR_MAX 8 + +#define RTD_TEMP_SIZE 4 + +#define RTD_TEMP_PLC_SCALE_FACTOR ((float)10) +#define RTD_TEMP_PLC_OFFSET ((float)200) + +#define RTD_TEMP_IW_ADDR_OFFSET 0 +#define RTD_IW_PER_CARD 12 + +int rtdCardCheck(uint8_t stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + return ERROR; + } + add = stack + I2C_RTD_ADDRESS_BASE; + return add; +} + +int rtdInit(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + uint16_t val = 0; + + dev = rtdCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, RTD_I2C_MEM_REVISION_MAJOR_ADD, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int rtdGetTemp(uint8_t stack, uint8_t channel, float *value) +{ + int dev = -1; + uint8_t buff[4]; + + if (channel >= RTD_CH_NR_MAX || value == NULL) + { + return ERROR; + } + + dev = rtdCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + if (OK != i2cMemRead(dev, RTD_I2C_VAL1_ADD + 4 * channel, buff, 4)) + { + return ERROR; + } + memcpy(value, buff, 4); + return OK; +} + + +//------------------------------------------------------------------------------ +// Industrial Automation 8-Layer Stackable HAT for Raspberry Pi +//------------------------------------------------------------------------------ + +extern "C" int indSetLeds(uint8_t, uint8_t); +extern "C" int indGetOptoInputs(uint8_t, uint8_t*); +extern "C" int indGet0_10Vin(uint8_t, uint8_t, float*); +extern "C" int indGet4_20mAin(uint8_t, uint8_t, float*); +extern "C" int indGet1WbTemp(uint8_t, uint8_t, float*); +extern "C" int indSet0_10Vout(uint8_t, uint8_t, float); +extern "C" int indSet4_20mAout(uint8_t, uint8_t, float); +extern "C" int indSetPWMout(uint8_t, uint8_t, float); + +#define I2C_IND_ADDRESS_BASE 0x50 + +#define IND_I2C_MEM_RELAY_VAL 0//reserved 4 bits for open-drain and 4 bits for leds +#define IND_I2C_MEM_OPTO_IN_VAL 3 +#define IND_I2C_MEM_U0_10_OUT_VAL 4 +#define IND_I2C_MEM_I4_20_OUT_VAL 12 +#define IND_I2C_MEM_OD_PWM 20 +#define IND_I2C_MEM_U0_10_IN_VAL 28 +#define IND_I2C_MEM_U_PM_10_IN_VAL 36 +#define IND_I2C_MEM_I4_20_IN_VAL 44 +#define IND_I2C_MEM_REVISION_MAJOR 0x78 +#define IND_I2C_MEM_1WB_START_SEARCH 173 +#define IND_I2C_MEM_1WB_T1 174 + +#define CHANNEL_NR_MIN 1 + +#define IND_OPTO_CH_NR_MAX 4 +#define IND_OD_CH_NR_MAX 4 +#define IND_I_OUT_CH_NR_MAX 4 +#define IND_U_OUT_CH_NR_MAX 4 +#define IND_U_IN_CH_NR_MAX 4 +#define IND_I_IN_CH_NR_MAX 4 +#define IND_LED_CH_NR_MAX 4 +#define IND_OWB_CH_MAX 4 // (4/16) limit PLC variable alocation + +#define IND_0_10V_RAW_MAX 10000 +#define IND_4_20MA_RAW_MIN 4000 +#define IND_4_20MA_RAW_MAX 20000 +#define IND_OD_PWM_VAL_MAX 10000 + +#define IND_LED_PLC_OFFSET_BITS 0 +#define IND_OPTO_IN_PLC_OFFSET_BITS 0 +#define IND_U_IN_PLC_OFFSET 0 +#define IND_I_IN_PLC_OFFSET 4 +#define IND_T_PLC_OFFSET 8 +#define IND_U_OUT_PLC_OFFSET 0 +#define IND_I_OUT_PLC_OFFSET 4 +#define IND_PWM_OUT_PLC_OFFSET 8 + +#define VOLT_TO_MILIVOLT ((float)1000) +#define MILI_TO_MICRO ((float)1000) +#define OWB_TEMP_SCALE ((float)100) +#define PWM_SCALE ((float)100) + +int indCardCheck(uint8_t stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + return ERROR; + } + add = stack + I2C_IND_ADDRESS_BASE; + return add; +} + +int indInit(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + uint16_t val = 0; + + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, IND_I2C_MEM_REVISION_MAJOR, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int indSetLeds(uint8_t stack, uint8_t value) +{ + static uint8_t prevLeds[STACK_LEVELS] = {0, 0, 0, 0, 0, 0, 0, 0}; + int dev = -1; + uint8_t buff[2]; + if (stack >= STACK_LEVELS) + { + return ERROR; + } + if (prevLeds[stack] == value) + { + return OK; // prevent usless transactions on I2C bus + } + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + buff[0] = 0xf0 & (value << 4); + if (ERROR == i2cMemWrite(dev, IND_I2C_MEM_RELAY_VAL, buff, 1)) + { + return ERROR; + } + prevLeds[stack] = value; + return OK; +} + +int indGetOptoInputs(uint8_t stack, uint8_t *val) +{ + int dev = -1; + + if (val == NULL) + { + return ERROR; + } + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + return i2cMemRead(dev, IND_I2C_MEM_OPTO_IN_VAL, val, 1); +} + +int indGet0_10Vin(uint8_t stack, uint8_t channel, float *val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + if (channel > IND_U_IN_CH_NR_MAX || NULL == val) + { + return ERROR; + } + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (OK != i2cMemRead(dev, IND_I2C_MEM_U0_10_IN_VAL + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(&aux16, buff, 2); + *val = (float)aux16 / VOLT_TO_MILIVOLT; + return OK; +} + +int indGet4_20mAin(uint8_t stack, uint8_t channel, float *val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + if (channel > IND_I_IN_CH_NR_MAX || NULL == val) + { + return ERROR; + } + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (OK != i2cMemRead(dev, IND_I2C_MEM_I4_20_IN_VAL + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(&aux16, buff, 2); + *val = (float)aux16 / MILI_TO_MICRO; + return OK; +} + +int indGet1WbTemp(uint8_t stack, uint8_t channel, float *val) +{ + uint8_t buff[2]; + int dev = -1; + int16_t aux16 = 0; + + if (channel > IND_OWB_CH_MAX || NULL == val) + { + return ERROR; + } + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + if (OK != i2cMemRead(dev, IND_I2C_MEM_1WB_T1 + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(&aux16, buff, 2); + *val = (float)aux16 / OWB_TEMP_SCALE; + return OK; +} + +int indSet0_10Vout(uint8_t stack, uint8_t channel, float val) +{ + //static uint16_t prevVout[IND_U_OUT_CH_NR_MAX] = {0, 0, 0, 0}; + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + if (channel > IND_U_OUT_CH_NR_MAX || val > IND_0_10V_RAW_MAX) + { + return ERROR; + } + aux16 = (uint16_t)(val * VOLT_TO_MILIVOLT); + //if(aux16 == ) + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + memcpy(buff, &aux16, 2); + if (OK + != i2cMemWrite(dev, IND_I2C_MEM_U0_10_OUT_VAL + 2 * channel, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int indSet4_20mAout(uint8_t stack, uint8_t channel, float val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + val *= MILI_TO_MICRO; + if (channel > IND_I_OUT_CH_NR_MAX || val > IND_4_20MA_RAW_MAX + || val < IND_4_20MA_RAW_MIN) + { + return ERROR; + //return ERROR; + } + aux16 = (uint16_t)val; + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + memcpy(buff, &aux16, 2); + if (OK + != i2cMemWrite(dev, IND_I2C_MEM_I4_20_OUT_VAL + 2 * channel, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int indSetPWMout(uint8_t stack, uint8_t channel, float val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + + if (channel > IND_OD_CH_NR_MAX || val > 100 || val < 0) + { + return ERROR; + } + aux16 = (uint16_t)(val * PWM_SCALE); + dev = indCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + memcpy(buff, &aux16, 2); + if (OK != i2cMemWrite(dev, IND_I2C_MEM_OD_PWM + 2 * channel, buff, 2)) + { + return ERROR; + } + + return OK; +} +//#endif + + + +//------------------------------------------------------------------------------ +// Building Automation 8-Layer Stackable HAT for Raspberry Pi +//------------------------------------------------------------------------------ + +extern "C" int basSetLeds(uint8_t, uint8_t); +extern "C" int basSetTriacs(uint8_t, uint8_t); +extern "C" int basSet0_10Vout(uint8_t, uint8_t, float); +extern "C" int basGetDryContacts(uint8_t, uint8_t*); +extern "C" int basGetUniversalIn(uint8_t, uint8_t, uint8_t, float*); +extern "C" int basGet1WbTemp(uint8_t, uint8_t, float*); + +#define I2C_BAS_ADDRESS_BASE 0x48 + +#define BAS_I2C_TRIACS_VAL_ADD 0 +#define BAS_I2C_DRY_CONTACT_VAL_ADD 3 +#define BAS_I2C_U0_10_OUT_VAL1_ADD 4 +#define BAS_I2C_U0_10_IN_VAL1_ADD 12 +#define BAS_I2C_R_1K_CH1 28 +#define BAS_I2C_R_10K_CH1 44 +#define BAS_I2C_MEM_1WB_T1 174 +#define BAS_I2C_REVISION_MAJOR_MEM_ADD 122 + +#define BAS_U_IN_CH_NR_MAX 8 +#define BAS_U_OUT_CH_NR_MAX 4 +#define BAS_VOLT_MAX 10 + + + +int basCardCheck(uint8_t stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + return ERROR; + } + add = stack + I2C_BAS_ADDRESS_BASE; + return add; +} + +int basInit(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + uint16_t val = 0; + + dev = basCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, BAS_I2C_REVISION_MAJOR_MEM_ADD, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int basSetTriacs(uint8_t stack, uint8_t value) +{ + static uint8_t prevTriacs[STACK_LEVELS] = {0, 0, 0, 0, 0, 0, 0, 0}; + int dev = -1; + uint8_t buff[2]; + if (stack >= STACK_LEVELS) + { + return ERROR; + } + if (prevTriacs[stack] == value) + { + return OK; // prevent usless transactions on I2C bus + } + dev = basCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + buff[0] = 0x0f & value ; + if (ERROR == i2cMemWrite(dev, BAS_I2C_TRIACS_VAL_ADD, buff, 1)) + { + return ERROR; + } + prevTriacs[stack] = value; + return OK; +} + +int basGetDryContacts(uint8_t stack, uint8_t *val) +{ + int dev = -1; + + if (val == NULL) + { + return ERROR; + } + dev = basCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + return i2cMemRead(dev, BAS_I2C_DRY_CONTACT_VAL_ADD, val, 1); +} + +int basGetUniversalIn(uint8_t stack, uint8_t channel, uint8_t type, float *val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + uint8_t address = BAS_I2C_U0_10_IN_VAL1_ADD; + float scaleFactor = VOLT_TO_MILIVOLT; + + if (channel >= IND_U_IN_CH_NR_MAX || NULL == val) + { + return ERROR; + } + dev = basCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + switch( type) //default reads 0-10V inputs + { + case 1: //1k resistor + address = BAS_I2C_R_1K_CH1; + scaleFactor = 1; + break; + case 2: //10k resistor + address = BAS_I2C_R_10K_CH1; + scaleFactor = 1; + break; + } + + if (OK != i2cMemRead(dev, address + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(&aux16, buff, 2); + *val = (float)aux16 / scaleFactor; + return OK; +} + +int basSet0_10Vout(uint8_t stack, uint8_t channel, float val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + if (channel >= BAS_U_OUT_CH_NR_MAX || val > BAS_VOLT_MAX) + { + return ERROR; + } + aux16 = (uint16_t)(val * VOLT_TO_MILIVOLT); + dev = basCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + memcpy(buff, &aux16, 2); + if (OK + != i2cMemWrite(dev, BAS_I2C_U0_10_OUT_VAL1_ADD + 2 * channel, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int basGet1WbTemp(uint8_t stack, uint8_t channel, float *val) +{ + uint8_t buff[2]; + int dev = -1; + int16_t aux16 = 0; + + if (channel > IND_OWB_CH_MAX || NULL == val) + { + return ERROR; + } + dev = basCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + if (OK != i2cMemRead(dev, BAS_I2C_MEM_1WB_T1 + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(&aux16, buff, 2); + *val = (float)aux16 / OWB_TEMP_SCALE; + return OK; +} + + +//------------------------------------------------------------------------------ +// Home Automation 8-Layer Stackable HAT for Raspberry Pi +//------------------------------------------------------------------------------ + +extern "C" int homeSetRelays(uint8_t, uint8_t); +extern "C" int homeSet0_10Vout(uint8_t, uint8_t, float); +extern "C" int homeSetOD(uint8_t, uint8_t, float); +extern "C" int homeGetOpto(uint8_t, uint8_t*); +extern "C" int homeGetADC(uint8_t, uint8_t, float*); +extern "C" int homeGet1WbTemp(uint8_t, uint8_t, float*); + +#define I2C_HOME_ADDRESS_BASE 0x28 + +#define HOME_I2C_RELAY_ADD 0x00 +#define HOME_I2C_0_10V_OUT_ADD 40 +#define HOME_I2C_OD_ADD 48 +#define HOME_I2C_OPTO_ADD 3 +#define HOME_I2C_ADC_ADD 24 +#define HOME_I2C_1W_TEMP_ADD 222 +#define HOME_I2C_REVISION_MAJOR_ADD 122 + +#define HOME_ADC_CH_NO 8 +#define HOME_DAC_CH_NO 4 + + +int homeCardCheck(uint8_t stack) +{ + uint8_t add = 0; + + if ( (stack < 0) || (stack > 7)) + { + return ERROR; + } + add = stack + I2C_HOME_ADDRESS_BASE; + return add; +} + +int homeInit(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + uint16_t val = 0; + + dev = homeCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, HOME_I2C_REVISION_MAJOR_ADD, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int homeSetRelays(uint8_t stack, uint8_t value) +{ + static uint8_t prevRelays[STACK_LEVELS] = {0, 0, 0, 0, 0, 0, 0, 0}; + int dev = -1; + uint8_t buff[2]; + if (stack >= STACK_LEVELS) + { + return ERROR; + } + if (prevRelays[stack] == value) + { + return OK; // prevent usless transactions on I2C bus + } + dev = homeCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + + buff[0] = value ; + if (ERROR == i2cMemWrite(dev, HOME_I2C_RELAY_ADD, buff, 1)) + { + return ERROR; + } + prevRelays[stack] = value; + return OK; +} + + +int homeSet0_10Vout(uint8_t stack, uint8_t channel, float val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + if (channel >= HOME_DAC_CH_NO || val > BAS_VOLT_MAX) + { + return ERROR; + } + aux16 = (uint16_t)(val * VOLT_TO_MILIVOLT); + dev = homeCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + memcpy(buff, &aux16, 2); + if (OK + != i2cMemWrite(dev, HOME_I2C_0_10V_OUT_ADD + 2 * channel, buff, 2)) + { + return ERROR; + } + + return OK; +} + +int homeSetOD(uint8_t stack, uint8_t channel, float val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + if (channel >= HOME_DAC_CH_NO || val > 100 || val < 0) + { + return ERROR; + } + aux16 = (uint16_t)(val * 100); + dev = homeCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + memcpy(buff, &aux16, 2); + if (OK + != i2cMemWrite(dev, HOME_I2C_OD_ADD + 2 * channel, buff, 2)) + { + return ERROR; + } + return OK; +} + +int homeGetOpto(uint8_t stack, uint8_t* val) +{ + int dev = -1; + + if (val == NULL) + { + return ERROR; + } + dev = homeCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + return i2cMemRead(dev, HOME_I2C_OPTO_ADD, val, 1); +} + +int homeGetADC(uint8_t stack, uint8_t channel, float* val) +{ + uint8_t buff[2]; + int dev = -1; + uint16_t aux16 = 0; + + if (channel >= HOME_ADC_CH_NO || NULL == val) + { + return ERROR; + } + dev = homeCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + if (OK != i2cMemRead(dev, HOME_I2C_ADC_ADD + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(&aux16, buff, 2); + + *val = (float)aux16/ VOLT_TO_MILIVOLT; + + return OK; +} + +int homeGet1WbTemp(uint8_t stack, uint8_t channel, float *val) +{ + uint8_t buff[2]; + int dev = -1; + int16_t aux16 = 0; + + if (channel > IND_OWB_CH_MAX || NULL == val) + { + return ERROR; + } + dev = homeCardCheck(stack); + if (dev < 0) + { + return ERROR; + } + if (OK != i2cMemRead(dev, HOME_I2C_1W_TEMP_ADD + 2 * channel, buff, 2)) + { + return ERROR; + } + memcpy(&aux16, buff, 2); + *val = (float)aux16 / OWB_TEMP_SCALE; + return OK; +} + + +//--------------------------------------------------------------------------------------- +extern "C" int mosfet8Init(int); +extern "C" int mosfets8Set(uint8_t, uint8_t); + +const uint8_t mosfet8MaskRemap[8] = {0x01, 0x02, 0x04, 0x08, 0x10, 0x20, 0x40, + 0x80}; + +uint8_t mosfet8ToIO(uint8_t relay) +{ + uint8_t i; + uint8_t val = 0; + for (i = 0; i < 8; i++) + { + if ( (relay & (1 << i)) != 0) + val += mosfet8MaskRemap[i]; + } + return val; +} + +int mosfet8CardCheck(int stack) +{ + uint8_t add = 0; + uint8_t buff[2]; + + if ( (stack < 0) || (stack > 7)) + { + return ERROR; + } + add = (stack + RELAY8_HW_I2C_BASE_ADD) ^ 0x07; + if(OK != i2cMemRead(add, RELAY8_CFG_REG_ADD, buff, 1)) + { + add = (stack + RELAY8_HW_I2C_BASE_ALT_ADD) ^ 0x07; + } + return add; +} + +int mosfet8Init(int stack) +{ + int dev = -1; + uint8_t add = 0; + uint8_t buff[2]; + + dev = mosfet8CardCheck(stack); + if (dev <= 0) + { + return ERROR; + } + + if (ERROR == i2cMemRead(dev, RELAY8_CFG_REG_ADD, buff, 1)) + { + return ERROR; + } + if (OK == i2cMemRead(dev, RELAY8_REG_COUNT, buff, 1)) //16 bits I/O expander found + { + return ERROR; + } + if (buff[0] != 0) //non initialized I/O Expander + { + // make all I/O pins output + buff[0] = 0; + if (OK > i2cMemWrite(dev, RELAY8_CFG_REG_ADD, buff, 1)) + { + return ERROR; + } + // put all pins in 0-logic state + buff[0] = 0; + if (OK > i2cMemWrite(dev, RELAY8_OUTPORT_REG_ADD, buff, 1)) + { + return ERROR; + } + } + return OK; +} + +int mosfets8Set(uint8_t stack, uint8_t val) +{ + uint8_t buff[2]; + int dev = -1; + static uint8_t mosfetsOldVal[STACK_LEVELS] = {0, 0, 0, 0, 0, 0, 0, 0}; + + if (stack >= 8) + { + return ERROR; + } + + if (mosfetsOldVal[stack] == val) + { + return OK; + } + dev = mosfet8CardCheck(stack); + if (dev <= 0) + { + return ERROR; + } + + buff[0] = mosfet8ToIO(val); + + if (OK != i2cMemWrite(dev, RELAY8_OUTPORT_REG_ADD, buff, 1)) + { + return ERROR; + } + mosfetsOldVal[stack] = val; + return OK; +} \ No newline at end of file diff --git a/resources/sources/StrucppBaremetal/modules/stm32can.c b/resources/sources/StrucppBaremetal/modules/stm32can.c new file mode 100644 index 000000000..ecdd013c6 --- /dev/null +++ b/resources/sources/StrucppBaremetal/modules/stm32can.c @@ -0,0 +1,105 @@ +#include "STM32_CAN.h" + +extern "C" uint8_t init_stm32can(int); +extern "C" uint8_t write_stm32can(uint8_t,uint32_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t, uint8_t); +extern "C" uint8_t read_stm32can(uint32_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*, uint8_t*); + +STM32_CAN Can( CAN1, ALT_2 ); //Use PD0/1 pins for CAN1. +//STM32_CAN Can1( CAN1, DEF ); //Use PA11/12 pins for CAN1. +//STM32_CAN Can( CAN1, ALT ); //Use PB8/9 pins for CAN1. +//STM32_CAN Can( CAN2, DEF ); //Use PB12/13 pins for CAN2. +//STM32_CAN Can( CAN2, ALT ); //Use PB5/6 pins for CAN2 +//STM32_CAN Can( CAN3, DEF ); //Use PA8/15 pins for CAN3. +//STM32_CAN Can( CAN3, ALT ); //Use PB3/4 pins for CAN3 + +CAN_message_t CAN1_TX_msg; +CAN_message_t CAN2_TX_msg; +CAN_message_t CAN_RX_msg; + +uint8_t init_stm32can(int baudrate) +{ + + Can.begin(); + Can.setBaudRate(baudrate); + //Can1.begin(); + //Can1.setBaudRate(baudrate); + return 1; +} + +uint8_t write_stm32can( uint8_t ch, + uint32_t id, + uint8_t d0, + uint8_t d1, + uint8_t d2, + uint8_t d3, + uint8_t d4, + uint8_t d5, + uint8_t d6, + uint8_t d7) +{ + if(ch == 1){ + CAN1_TX_msg.id = id; + CAN1_TX_msg.flags.extended = 1; // To enable extended ID. + CAN1_TX_msg.len = 8; + CAN1_TX_msg.buf[0] = d0; + CAN1_TX_msg.buf[1] = d1; + CAN1_TX_msg.buf[2] = d2; + CAN1_TX_msg.buf[3] = d3; + CAN1_TX_msg.buf[4] = d4; + CAN1_TX_msg.buf[5] = d5; + CAN1_TX_msg.buf[6] = d6; + CAN1_TX_msg.buf[7] = d7; + + if (!Can.write(CAN1_TX_msg)) + { + return 0; + } + } + + if(ch == 2){ + CAN2_TX_msg.id = id; + CAN2_TX_msg.flags.extended = 1; // To enable extended ID. + CAN2_TX_msg.len = 8; + CAN2_TX_msg.buf[0] = d0; + CAN2_TX_msg.buf[1] = d1; + CAN2_TX_msg.buf[2] = d2; + CAN2_TX_msg.buf[3] = d3; + CAN2_TX_msg.buf[4] = d4; + CAN2_TX_msg.buf[5] = d5; + CAN2_TX_msg.buf[6] = d6; + CAN2_TX_msg.buf[7] = d7; + + /*if (!Can1.write(CAN2_TX_msg)) + { + return 0; + }*/ + } + return 1; + +} + +uint8_t read_stm32can(uint32_t* id, + uint8_t* d0, + uint8_t* d1, + uint8_t* d2, + uint8_t* d3, + uint8_t* d4, + uint8_t* d5, + uint8_t* d6, + uint8_t* d7) +{ + if (Can.read(CAN_RX_msg)) { + // Assuming id is a pointer to a uint32_t, and CAN_RX_msg.id is uint32_t + *id = CAN_RX_msg.id; + *d0 = CAN_RX_msg.buf[0]; + *d1 = CAN_RX_msg.buf[1]; + *d2 = CAN_RX_msg.buf[2]; + *d3 = CAN_RX_msg.buf[3]; + *d4 = CAN_RX_msg.buf[4]; + *d5 = CAN_RX_msg.buf[5]; + *d6 = CAN_RX_msg.buf[6]; + *d7 = CAN_RX_msg.buf[7]; + return 1; + } + return 0; +} diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index ce5b108c3..a243bbf54 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -992,9 +992,7 @@ class CompilerModule { buildProjectFlags = [ ...buildProjectFlags, '--library', - `${join(compilationPath, 'src')}`, // Basic libraries - '--library', - `${join(compilationPath, 'src', 'lib')}`, // Arduino libraries + `${join(compilationPath, 'src')}`, // STruC++ generated code + runtime headers '--export-binaries', // Export binaries '-b', boardHalsContent['platform'], // Board target From 469658da840e2049be57ca4595431ce5aaaaf753 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 11:29:13 -0400 Subject: [PATCH 030/296] refactor: replace custom AVR C++ headers with modm-io/avr-libstdcpp fork MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use the proven modm-io/avr-libstdcpp library (GPLv3, GCC 10-based) instead of our hand-rolled minimal headers. Upstream already provides complete implementations of type_traits, utility, algorithm, array, cstdint, cstddef, cstring, cstdlib, cmath, initializer_list, new, and dozens more headers — all tested with avr-gcc 7 through 15. The earlier "template with C linkage" errors that led me to build custom headers were actually caused by using -isystem (treated as C linkage by AVR GCC 7.3), not by avr-libstdcpp itself. Switching to -I fixed it and modm-io works perfectly. Only two small additions to upstream (documented in OPENPLC_MODIFICATIONS.md): 1. Add empty stub: STruC++ generated code emits #include unconditionally but never uses std::string (uses its own IECString). Upstream excludes intentionally. 2. Add strtoll/strtoull shims in cstdlib: AVR libc lacks 64-bit string conversion. STruC++ iec_string.hpp uses std::strtoll/strtoull for LINT/ULINT parsing. Shims fall back to 32-bit strtol/strtoul inside #ifdef __AVR__. Verified: simple project and STRING-using project both compile cleanly. Sketch size: 7622 bytes flash (3%), 756 bytes RAM (9%) on Arduino Mega. Co-Authored-By: Claude Opus 4.6 (1M context) --- resources/sources/avr-libstdcpp/.gitignore | 2 + resources/sources/avr-libstdcpp/COPYING.MPLv2 | 373 ++ resources/sources/avr-libstdcpp/COPYING3 | 674 ++ .../avr-libstdcpp/OPENPLC_MODIFICATIONS.md | 35 + resources/sources/avr-libstdcpp/README.md | 359 + .../sources/avr-libstdcpp/include/algorithm | 104 +- resources/sources/avr-libstdcpp/include/any | 626 ++ resources/sources/avr-libstdcpp/include/array | 486 +- .../sources/avr-libstdcpp/include/atomic | 1552 +++++ .../include/backward/backward_warning.h | 56 + .../avr-libstdcpp/include/backward/binders.h | 182 + .../avr-libstdcpp/include/backward/hash_fun.h | 170 + .../avr-libstdcpp/include/backward/hash_map | 599 ++ .../avr-libstdcpp/include/backward/hash_set | 569 ++ .../include/backward/hashtable.h | 1166 ++++ resources/sources/avr-libstdcpp/include/bit | 371 ++ .../avr-libstdcpp/include/bits/algorithmfwd.h | 963 +++ .../avr-libstdcpp/include/bits/alloc_traits.h | 743 +++ .../include/bits/allocated_ptr.h | 104 + .../avr-libstdcpp/include/bits/allocator.h | 323 + .../avr-libstdcpp/include/bits/atomic_base.h | 1724 +++++ .../include/bits/atomic_lockfree_defines.h | 66 + .../include/bits/boost_concept_check.h | 794 +++ .../include/bits/c++0x_warning.h | 37 + .../avr-libstdcpp/include/bits/c++allocator.h | 59 + .../avr-libstdcpp/include/bits/c++config.h | 2074 ++++++ .../avr-libstdcpp/include/bits/char_traits.h | 943 +++ .../avr-libstdcpp/include/bits/charconv.h | 106 + .../include/bits/concept_check.h | 81 + .../include/bits/cpp_type_traits.h | 551 ++ .../include/bits/cxxabi_forced.h | 60 + .../include/bits/cxxabi_init_exception.h | 80 + .../avr-libstdcpp/include/bits/deque.tcc | 1216 ++++ .../include/bits/enable_special_members.h | 312 + .../avr-libstdcpp/include/bits/erase_if.h | 72 + .../include/bits/error_constants.h | 180 + .../include/bits/exception_defines.h | 47 + .../avr-libstdcpp/include/bits/forward_list.h | 1514 +++++ .../include/bits/forward_list.tcc | 517 ++ .../avr-libstdcpp/include/bits/functexcept.h | 114 + .../include/bits/functional_hash.h | 280 + .../avr-libstdcpp/include/bits/gslice.h | 185 + .../avr-libstdcpp/include/bits/gslice_array.h | 223 + .../avr-libstdcpp/include/bits/hash_bytes.h | 59 + .../avr-libstdcpp/include/bits/hashtable.h | 2228 +++++++ .../include/bits/hashtable_policy.h | 2107 ++++++ .../include/bits/indirect_array.h | 212 + .../avr-libstdcpp/include/bits/invoke.h | 163 + .../include/bits/iterator_concepts.h | 911 +++ .../avr-libstdcpp/include/bits/list.tcc | 633 ++ .../avr-libstdcpp/include/bits/mask_array.h | 213 + .../avr-libstdcpp/include/bits/memoryfwd.h | 82 + .../sources/avr-libstdcpp/include/bits/move.h | 224 + .../avr-libstdcpp/include/bits/node_handle.h | 299 + .../include/bits/parse_numbers.h | 294 + .../avr-libstdcpp/include/bits/postypes.h | 253 + .../include/bits/predefined_ops.h | 405 ++ .../avr-libstdcpp/include/bits/ptr_traits.h | 211 + .../avr-libstdcpp/include/bits/random.h | 5183 +++++++++++++++ .../avr-libstdcpp/include/bits/random.tcc | 2193 ++++++ .../avr-libstdcpp/include/bits/range_access.h | 1148 ++++ .../avr-libstdcpp/include/bits/range_cmp.h | 195 + .../avr-libstdcpp/include/bits/ranges_algo.h | 3792 +++++++++++ .../include/bits/ranges_algobase.h | 597 ++ .../include/bits/ranges_uninitialized.h | 574 ++ .../avr-libstdcpp/include/bits/refwrap.h | 401 ++ .../avr-libstdcpp/include/bits/slice_array.h | 284 + .../avr-libstdcpp/include/bits/std_abs.h | 111 + .../avr-libstdcpp/include/bits/std_function.h | 728 ++ .../avr-libstdcpp/include/bits/std_mutex.h | 176 + .../avr-libstdcpp/include/bits/stl_algo.h | 5884 +++++++++++++++++ .../avr-libstdcpp/include/bits/stl_algobase.h | 1959 ++++++ .../avr-libstdcpp/include/bits/stl_bvector.h | 1363 ++++ .../include/bits/stl_construct.h | 256 + .../avr-libstdcpp/include/bits/stl_deque.h | 2330 +++++++ .../avr-libstdcpp/include/bits/stl_function.h | 1395 ++++ .../avr-libstdcpp/include/bits/stl_heap.h | 583 ++ .../avr-libstdcpp/include/bits/stl_iterator.h | 2238 +++++++ .../include/bits/stl_iterator_base_funcs.h | 239 + .../include/bits/stl_iterator_base_types.h | 271 + .../avr-libstdcpp/include/bits/stl_list.h | 2127 ++++++ .../avr-libstdcpp/include/bits/stl_map.h | 1568 +++++ .../avr-libstdcpp/include/bits/stl_multimap.h | 1233 ++++ .../avr-libstdcpp/include/bits/stl_multiset.h | 1075 +++ .../avr-libstdcpp/include/bits/stl_numeric.h | 413 ++ .../avr-libstdcpp/include/bits/stl_pair.h | 586 ++ .../avr-libstdcpp/include/bits/stl_queue.h | 753 +++ .../include/bits/stl_raw_storage_iter.h | 123 + .../avr-libstdcpp/include/bits/stl_relops.h | 133 + .../avr-libstdcpp/include/bits/stl_set.h | 1086 +++ .../avr-libstdcpp/include/bits/stl_stack.h | 392 ++ .../avr-libstdcpp/include/bits/stl_tempbuf.h | 284 + .../avr-libstdcpp/include/bits/stl_tree.h | 2644 ++++++++ .../include/bits/stl_uninitialized.h | 1041 +++ .../avr-libstdcpp/include/bits/stl_vector.h | 1985 ++++++ .../include/bits/string_view.tcc | 229 + .../include/bits/uniform_int_dist.h | 395 ++ .../avr-libstdcpp/include/bits/unique_lock.h | 243 + .../avr-libstdcpp/include/bits/unique_ptr.h | 995 +++ .../include/bits/unordered_map.h | 2171 ++++++ .../include/bits/unordered_set.h | 1783 +++++ .../include/bits/uses_allocator.h | 195 + .../include/bits/valarray_after.h | 556 ++ .../include/bits/valarray_array.h | 677 ++ .../include/bits/valarray_array.tcc | 244 + .../include/bits/valarray_before.h | 758 +++ .../avr-libstdcpp/include/bits/vector.tcc | 1008 +++ .../sources/avr-libstdcpp/include/bitset | 1245 ++++ .../sources/avr-libstdcpp/include/cassert | 44 + .../sources/avr-libstdcpp/include/ccomplex | 42 + .../sources/avr-libstdcpp/include/cctype | 94 + .../sources/avr-libstdcpp/include/cerrno | 52 + resources/sources/avr-libstdcpp/include/cfenv | 84 + .../sources/avr-libstdcpp/include/cfloat | 56 + .../sources/avr-libstdcpp/include/chrono | 1131 ++++ .../sources/avr-libstdcpp/include/cinttypes | 55 + .../sources/avr-libstdcpp/include/ciso646 | 38 + .../sources/avr-libstdcpp/include/climits | 59 + resources/sources/avr-libstdcpp/include/cmath | 1940 +++++- .../sources/avr-libstdcpp/include/compare | 919 +++ .../sources/avr-libstdcpp/include/complex | 1931 ++++++ .../sources/avr-libstdcpp/include/concepts | 367 + .../sources/avr-libstdcpp/include/coroutine | 303 + .../sources/avr-libstdcpp/include/csetjmp | 61 + .../sources/avr-libstdcpp/include/csignal | 57 + .../sources/avr-libstdcpp/include/cstdalign | 44 + .../sources/avr-libstdcpp/include/cstdarg | 58 + .../sources/avr-libstdcpp/include/cstdbool | 44 + .../sources/avr-libstdcpp/include/cstddef | 185 +- .../sources/avr-libstdcpp/include/cstdint | 103 +- .../sources/avr-libstdcpp/include/cstdio | 194 +- .../sources/avr-libstdcpp/include/cstdlib | 225 +- .../sources/avr-libstdcpp/include/cstring | 132 +- .../sources/avr-libstdcpp/include/ctgmath | 44 + resources/sources/avr-libstdcpp/include/ctime | 84 + .../sources/avr-libstdcpp/include/cuchar | 77 + .../sources/avr-libstdcpp/include/cwchar | 306 + .../sources/avr-libstdcpp/include/cwctype | 110 + .../avr-libstdcpp/include/debug/assertions.h | 68 + .../avr-libstdcpp/include/debug/debug.h | 137 + .../avr-libstdcpp/include/debug/formatter.h | 593 ++ .../avr-libstdcpp/include/debug/functions.h | 470 ++ .../include/debug/helper_functions.h | 315 + .../avr-libstdcpp/include/debug/macros.h | 471 ++ .../avr-libstdcpp/include/decimal/decimal | 494 ++ .../avr-libstdcpp/include/decimal/decimal.h | 469 ++ resources/sources/avr-libstdcpp/include/deque | 119 + .../avr-libstdcpp/include/ext/algorithm | 596 ++ .../include/ext/aligned_buffer.h | 125 + .../avr-libstdcpp/include/ext/alloc_traits.h | 171 + .../avr-libstdcpp/include/ext/atomicity.h | 116 + .../sources/avr-libstdcpp/include/ext/cmath | 152 + .../avr-libstdcpp/include/ext/functional | 422 ++ .../avr-libstdcpp/include/ext/hash_map | 599 ++ .../avr-libstdcpp/include/ext/hash_set | 569 ++ .../avr-libstdcpp/include/ext/iterator | 116 + .../include/ext/malloc_allocator.h | 199 + .../sources/avr-libstdcpp/include/ext/memory | 200 + .../avr-libstdcpp/include/ext/new_allocator.h | 198 + .../sources/avr-libstdcpp/include/ext/numeric | 152 + .../include/ext/numeric_traits.h | 148 + .../include/ext/pod_char_traits.h | 198 + .../sources/avr-libstdcpp/include/ext/rb_tree | 93 + .../sources/avr-libstdcpp/include/ext/slist | 1082 +++ .../avr-libstdcpp/include/ext/type_traits.h | 221 + .../avr-libstdcpp/include/ext/typelist.h | 538 ++ .../avr-libstdcpp/include/forward_list | 87 + .../sources/avr-libstdcpp/include/functional | 1280 ++++ .../avr-libstdcpp/include/initializer_list | 132 +- .../sources/avr-libstdcpp/include/iterator | 70 + .../sources/avr-libstdcpp/include/limits | 1893 ++++++ resources/sources/avr-libstdcpp/include/list | 109 + resources/sources/avr-libstdcpp/include/map | 109 + .../sources/avr-libstdcpp/include/memory | 404 ++ resources/sources/avr-libstdcpp/include/mutex | 746 +++ resources/sources/avr-libstdcpp/include/new | 196 +- .../sources/avr-libstdcpp/include/numbers | 208 + .../sources/avr-libstdcpp/include/numeric | 699 ++ .../sources/avr-libstdcpp/include/optional | 1238 ++++ .../sources/avr-libstdcpp/include/ostream | 4 - resources/sources/avr-libstdcpp/include/queue | 66 + .../sources/avr-libstdcpp/include/random | 54 + .../sources/avr-libstdcpp/include/ranges | 3561 ++++++++++ resources/sources/avr-libstdcpp/include/ratio | 576 ++ .../avr-libstdcpp/include/scoped_allocator | 519 ++ resources/sources/avr-libstdcpp/include/set | 105 + .../avr-libstdcpp/include/shared_mutex | 855 +++ resources/sources/avr-libstdcpp/include/span | 462 ++ resources/sources/avr-libstdcpp/include/stack | 63 + .../sources/avr-libstdcpp/include/stdexcept | 4 - .../sources/avr-libstdcpp/include/string | 20 +- .../sources/avr-libstdcpp/include/string_view | 758 +++ resources/sources/avr-libstdcpp/include/tuple | 1764 +++++ .../sources/avr-libstdcpp/include/type_traits | 3952 ++++++++++- .../avr-libstdcpp/include/unordered_map | 101 + .../avr-libstdcpp/include/unordered_set | 100 + .../sources/avr-libstdcpp/include/utility | 552 +- .../sources/avr-libstdcpp/include/valarray | 1253 ++++ .../sources/avr-libstdcpp/include/variant | 1775 +++++ .../sources/avr-libstdcpp/include/vector | 129 + .../sources/avr-libstdcpp/include/version | 231 + 201 files changed, 128396 insertions(+), 377 deletions(-) create mode 100644 resources/sources/avr-libstdcpp/.gitignore create mode 100644 resources/sources/avr-libstdcpp/COPYING.MPLv2 create mode 100644 resources/sources/avr-libstdcpp/COPYING3 create mode 100644 resources/sources/avr-libstdcpp/OPENPLC_MODIFICATIONS.md create mode 100644 resources/sources/avr-libstdcpp/README.md create mode 100644 resources/sources/avr-libstdcpp/include/any create mode 100644 resources/sources/avr-libstdcpp/include/atomic create mode 100644 resources/sources/avr-libstdcpp/include/backward/backward_warning.h create mode 100644 resources/sources/avr-libstdcpp/include/backward/binders.h create mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_fun.h create mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_map create mode 100644 resources/sources/avr-libstdcpp/include/backward/hash_set create mode 100644 resources/sources/avr-libstdcpp/include/backward/hashtable.h create mode 100644 resources/sources/avr-libstdcpp/include/bit create mode 100644 resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/alloc_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/atomic_base.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/c++allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/c++config.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/char_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/charconv.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/concept_check.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/deque.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/enable_special_members.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/erase_if.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/error_constants.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/exception_defines.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/forward_list.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/forward_list.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/functexcept.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/functional_hash.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/gslice.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/gslice_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/hash_bytes.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/hashtable.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/indirect_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/invoke.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/list.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/mask_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/memoryfwd.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/move.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/node_handle.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/parse_numbers.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/postypes.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/predefined_ops.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/ptr_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/random.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/random.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/range_access.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/range_cmp.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_algo.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/refwrap.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/slice_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/std_abs.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/std_function.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/std_mutex.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_algo.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_algobase.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_bvector.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_construct.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_deque.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_function.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_heap.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_list.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_map.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_multimap.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_multiset.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_numeric.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_pair.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_queue.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_relops.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_set.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_stack.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_tree.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/stl_vector.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/string_view.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/unique_lock.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/unique_ptr.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/unordered_map.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/unordered_set.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/uses_allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_after.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_array.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bits/valarray_before.h create mode 100644 resources/sources/avr-libstdcpp/include/bits/vector.tcc create mode 100644 resources/sources/avr-libstdcpp/include/bitset create mode 100644 resources/sources/avr-libstdcpp/include/cassert create mode 100644 resources/sources/avr-libstdcpp/include/ccomplex create mode 100644 resources/sources/avr-libstdcpp/include/cctype create mode 100644 resources/sources/avr-libstdcpp/include/cerrno create mode 100644 resources/sources/avr-libstdcpp/include/cfenv create mode 100644 resources/sources/avr-libstdcpp/include/cfloat create mode 100644 resources/sources/avr-libstdcpp/include/chrono create mode 100644 resources/sources/avr-libstdcpp/include/cinttypes create mode 100644 resources/sources/avr-libstdcpp/include/ciso646 create mode 100644 resources/sources/avr-libstdcpp/include/climits create mode 100644 resources/sources/avr-libstdcpp/include/compare create mode 100644 resources/sources/avr-libstdcpp/include/complex create mode 100644 resources/sources/avr-libstdcpp/include/concepts create mode 100644 resources/sources/avr-libstdcpp/include/coroutine create mode 100644 resources/sources/avr-libstdcpp/include/csetjmp create mode 100644 resources/sources/avr-libstdcpp/include/csignal create mode 100644 resources/sources/avr-libstdcpp/include/cstdalign create mode 100644 resources/sources/avr-libstdcpp/include/cstdarg create mode 100644 resources/sources/avr-libstdcpp/include/cstdbool create mode 100644 resources/sources/avr-libstdcpp/include/ctgmath create mode 100644 resources/sources/avr-libstdcpp/include/ctime create mode 100644 resources/sources/avr-libstdcpp/include/cuchar create mode 100644 resources/sources/avr-libstdcpp/include/cwchar create mode 100644 resources/sources/avr-libstdcpp/include/cwctype create mode 100644 resources/sources/avr-libstdcpp/include/debug/assertions.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/debug.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/formatter.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/functions.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/helper_functions.h create mode 100644 resources/sources/avr-libstdcpp/include/debug/macros.h create mode 100644 resources/sources/avr-libstdcpp/include/decimal/decimal create mode 100644 resources/sources/avr-libstdcpp/include/decimal/decimal.h create mode 100644 resources/sources/avr-libstdcpp/include/deque create mode 100644 resources/sources/avr-libstdcpp/include/ext/algorithm create mode 100644 resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/alloc_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/atomicity.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/cmath create mode 100644 resources/sources/avr-libstdcpp/include/ext/functional create mode 100644 resources/sources/avr-libstdcpp/include/ext/hash_map create mode 100644 resources/sources/avr-libstdcpp/include/ext/hash_set create mode 100644 resources/sources/avr-libstdcpp/include/ext/iterator create mode 100644 resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/memory create mode 100644 resources/sources/avr-libstdcpp/include/ext/new_allocator.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/numeric create mode 100644 resources/sources/avr-libstdcpp/include/ext/numeric_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/rb_tree create mode 100644 resources/sources/avr-libstdcpp/include/ext/slist create mode 100644 resources/sources/avr-libstdcpp/include/ext/type_traits.h create mode 100644 resources/sources/avr-libstdcpp/include/ext/typelist.h create mode 100644 resources/sources/avr-libstdcpp/include/forward_list create mode 100644 resources/sources/avr-libstdcpp/include/functional create mode 100644 resources/sources/avr-libstdcpp/include/iterator create mode 100644 resources/sources/avr-libstdcpp/include/limits create mode 100644 resources/sources/avr-libstdcpp/include/list create mode 100644 resources/sources/avr-libstdcpp/include/map create mode 100644 resources/sources/avr-libstdcpp/include/memory create mode 100644 resources/sources/avr-libstdcpp/include/mutex create mode 100644 resources/sources/avr-libstdcpp/include/numbers create mode 100644 resources/sources/avr-libstdcpp/include/numeric create mode 100644 resources/sources/avr-libstdcpp/include/optional delete mode 100644 resources/sources/avr-libstdcpp/include/ostream create mode 100644 resources/sources/avr-libstdcpp/include/queue create mode 100644 resources/sources/avr-libstdcpp/include/random create mode 100644 resources/sources/avr-libstdcpp/include/ranges create mode 100644 resources/sources/avr-libstdcpp/include/ratio create mode 100644 resources/sources/avr-libstdcpp/include/scoped_allocator create mode 100644 resources/sources/avr-libstdcpp/include/set create mode 100644 resources/sources/avr-libstdcpp/include/shared_mutex create mode 100644 resources/sources/avr-libstdcpp/include/span create mode 100644 resources/sources/avr-libstdcpp/include/stack delete mode 100644 resources/sources/avr-libstdcpp/include/stdexcept create mode 100644 resources/sources/avr-libstdcpp/include/string_view create mode 100644 resources/sources/avr-libstdcpp/include/tuple create mode 100644 resources/sources/avr-libstdcpp/include/unordered_map create mode 100644 resources/sources/avr-libstdcpp/include/unordered_set create mode 100644 resources/sources/avr-libstdcpp/include/valarray create mode 100644 resources/sources/avr-libstdcpp/include/variant create mode 100644 resources/sources/avr-libstdcpp/include/vector create mode 100644 resources/sources/avr-libstdcpp/include/version diff --git a/resources/sources/avr-libstdcpp/.gitignore b/resources/sources/avr-libstdcpp/.gitignore new file mode 100644 index 000000000..886e04000 --- /dev/null +++ b/resources/sources/avr-libstdcpp/.gitignore @@ -0,0 +1,2 @@ +examples/**/build + diff --git a/resources/sources/avr-libstdcpp/COPYING.MPLv2 b/resources/sources/avr-libstdcpp/COPYING.MPLv2 new file mode 100644 index 000000000..d0a1fa148 --- /dev/null +++ b/resources/sources/avr-libstdcpp/COPYING.MPLv2 @@ -0,0 +1,373 @@ +Mozilla Public License Version 2.0 +================================== + +1. Definitions +-------------- + +1.1. "Contributor" + means each individual or legal entity that creates, contributes to + the creation of, or owns Covered Software. + +1.2. "Contributor Version" + means the combination of the Contributions of others (if any) used + by a Contributor and that particular Contributor's Contribution. + +1.3. "Contribution" + means Covered Software of a particular Contributor. + +1.4. "Covered Software" + means Source Code Form to which the initial Contributor has attached + the notice in Exhibit A, the Executable Form of such Source Code + Form, and Modifications of such Source Code Form, in each case + including portions thereof. + +1.5. "Incompatible With Secondary Licenses" + means + + (a) that the initial Contributor has attached the notice described + in Exhibit B to the Covered Software; or + + (b) that the Covered Software was made available under the terms of + version 1.1 or earlier of the License, but not also under the + terms of a Secondary License. + +1.6. "Executable Form" + means any form of the work other than Source Code Form. + +1.7. "Larger Work" + means a work that combines Covered Software with other material, in + a separate file or files, that is not Covered Software. + +1.8. "License" + means this document. + +1.9. "Licensable" + means having the right to grant, to the maximum extent possible, + whether at the time of the initial grant or subsequently, any and + all of the rights conveyed by this License. + +1.10. "Modifications" + means any of the following: + + (a) any file in Source Code Form that results from an addition to, + deletion from, or modification of the contents of Covered + Software; or + + (b) any new file in Source Code Form that contains any Covered + Software. + +1.11. "Patent Claims" of a Contributor + means any patent claim(s), including without limitation, method, + process, and apparatus claims, in any patent Licensable by such + Contributor that would be infringed, but for the grant of the + License, by the making, using, selling, offering for sale, having + made, import, or transfer of either its Contributions or its + Contributor Version. + +1.12. "Secondary License" + means either the GNU General Public License, Version 2.0, the GNU + Lesser General Public License, Version 2.1, the GNU Affero General + Public License, Version 3.0, or any later versions of those + licenses. + +1.13. "Source Code Form" + means the form of the work preferred for making modifications. + +1.14. "You" (or "Your") + means an individual or a legal entity exercising rights under this + License. For legal entities, "You" includes any entity that + controls, is controlled by, or is under common control with You. For + purposes of this definition, "control" means (a) the power, direct + or indirect, to cause the direction or management of such entity, + whether by contract or otherwise, or (b) ownership of more than + fifty percent (50%) of the outstanding shares or beneficial + ownership of such entity. + +2. License Grants and Conditions +-------------------------------- + +2.1. Grants + +Each Contributor hereby grants You a world-wide, royalty-free, +non-exclusive license: + +(a) under intellectual property rights (other than patent or trademark) + Licensable by such Contributor to use, reproduce, make available, + modify, display, perform, distribute, and otherwise exploit its + Contributions, either on an unmodified basis, with Modifications, or + as part of a Larger Work; and + +(b) under Patent Claims of such Contributor to make, use, sell, offer + for sale, have made, import, and otherwise transfer either its + Contributions or its Contributor Version. + +2.2. Effective Date + +The licenses granted in Section 2.1 with respect to any Contribution +become effective for each Contribution on the date the Contributor first +distributes such Contribution. + +2.3. Limitations on Grant Scope + +The licenses granted in this Section 2 are the only rights granted under +this License. No additional rights or licenses will be implied from the +distribution or licensing of Covered Software under this License. +Notwithstanding Section 2.1(b) above, no patent license is granted by a +Contributor: + +(a) for any code that a Contributor has removed from Covered Software; + or + +(b) for infringements caused by: (i) Your and any other third party's + modifications of Covered Software, or (ii) the combination of its + Contributions with other software (except as part of its Contributor + Version); or + +(c) under Patent Claims infringed by Covered Software in the absence of + its Contributions. + +This License does not grant any rights in the trademarks, service marks, +or logos of any Contributor (except as may be necessary to comply with +the notice requirements in Section 3.4). + +2.4. Subsequent Licenses + +No Contributor makes additional grants as a result of Your choice to +distribute the Covered Software under a subsequent version of this +License (see Section 10.2) or under the terms of a Secondary License (if +permitted under the terms of Section 3.3). + +2.5. Representation + +Each Contributor represents that the Contributor believes its +Contributions are its original creation(s) or it has sufficient rights +to grant the rights to its Contributions conveyed by this License. + +2.6. Fair Use + +This License is not intended to limit any rights You have under +applicable copyright doctrines of fair use, fair dealing, or other +equivalents. + +2.7. Conditions + +Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted +in Section 2.1. + +3. Responsibilities +------------------- + +3.1. Distribution of Source Form + +All distribution of Covered Software in Source Code Form, including any +Modifications that You create or to which You contribute, must be under +the terms of this License. You must inform recipients that the Source +Code Form of the Covered Software is governed by the terms of this +License, and how they can obtain a copy of this License. You may not +attempt to alter or restrict the recipients' rights in the Source Code +Form. + +3.2. Distribution of Executable Form + +If You distribute Covered Software in Executable Form then: + +(a) such Covered Software must also be made available in Source Code + Form, as described in Section 3.1, and You must inform recipients of + the Executable Form how they can obtain a copy of such Source Code + Form by reasonable means in a timely manner, at a charge no more + than the cost of distribution to the recipient; and + +(b) You may distribute such Executable Form under the terms of this + License, or sublicense it under different terms, provided that the + license for the Executable Form does not attempt to limit or alter + the recipients' rights in the Source Code Form under this License. + +3.3. Distribution of a Larger Work + +You may create and distribute a Larger Work under terms of Your choice, +provided that You also comply with the requirements of this License for +the Covered Software. If the Larger Work is a combination of Covered +Software with a work governed by one or more Secondary Licenses, and the +Covered Software is not Incompatible With Secondary Licenses, this +License permits You to additionally distribute such Covered Software +under the terms of such Secondary License(s), so that the recipient of +the Larger Work may, at their option, further distribute the Covered +Software under the terms of either this License or such Secondary +License(s). + +3.4. Notices + +You may not remove or alter the substance of any license notices +(including copyright notices, patent notices, disclaimers of warranty, +or limitations of liability) contained within the Source Code Form of +the Covered Software, except that You may alter any license notices to +the extent required to remedy known factual inaccuracies. + +3.5. Application of Additional Terms + +You may choose to offer, and to charge a fee for, warranty, support, +indemnity or liability obligations to one or more recipients of Covered +Software. However, You may do so only on Your own behalf, and not on +behalf of any Contributor. You must make it absolutely clear that any +such warranty, support, indemnity, or liability obligation is offered by +You alone, and You hereby agree to indemnify every Contributor for any +liability incurred by such Contributor as a result of warranty, support, +indemnity or liability terms You offer. You may include additional +disclaimers of warranty and limitations of liability specific to any +jurisdiction. + +4. Inability to Comply Due to Statute or Regulation +--------------------------------------------------- + +If it is impossible for You to comply with any of the terms of this +License with respect to some or all of the Covered Software due to +statute, judicial order, or regulation then You must: (a) comply with +the terms of this License to the maximum extent possible; and (b) +describe the limitations and the code they affect. Such description must +be placed in a text file included with all distributions of the Covered +Software under this License. Except to the extent prohibited by statute +or regulation, such description must be sufficiently detailed for a +recipient of ordinary skill to be able to understand it. + +5. Termination +-------------- + +5.1. The rights granted under this License will terminate automatically +if You fail to comply with any of its terms. However, if You become +compliant, then the rights granted under this License from a particular +Contributor are reinstated (a) provisionally, unless and until such +Contributor explicitly and finally terminates Your grants, and (b) on an +ongoing basis, if such Contributor fails to notify You of the +non-compliance by some reasonable means prior to 60 days after You have +come back into compliance. Moreover, Your grants from a particular +Contributor are reinstated on an ongoing basis if such Contributor +notifies You of the non-compliance by some reasonable means, this is the +first time You have received notice of non-compliance with this License +from such Contributor, and You become compliant prior to 30 days after +Your receipt of the notice. + +5.2. If You initiate litigation against any entity by asserting a patent +infringement claim (excluding declaratory judgment actions, +counter-claims, and cross-claims) alleging that a Contributor Version +directly or indirectly infringes any patent, then the rights granted to +You by any and all Contributors for the Covered Software under Section +2.1 of this License shall terminate. + +5.3. In the event of termination under Sections 5.1 or 5.2 above, all +end user license agreements (excluding distributors and resellers) which +have been validly granted by You or Your distributors under this License +prior to termination shall survive termination. + +************************************************************************ +* * +* 6. Disclaimer of Warranty * +* ------------------------- * +* * +* Covered Software is provided under this License on an "as is" * +* basis, without warranty of any kind, either expressed, implied, or * +* statutory, including, without limitation, warranties that the * +* Covered Software is free of defects, merchantable, fit for a * +* particular purpose or non-infringing. The entire risk as to the * +* quality and performance of the Covered Software is with You. * +* Should any Covered Software prove defective in any respect, You * +* (not any Contributor) assume the cost of any necessary servicing, * +* repair, or correction. This disclaimer of warranty constitutes an * +* essential part of this License. No use of any Covered Software is * +* authorized under this License except under this disclaimer. * +* * +************************************************************************ + +************************************************************************ +* * +* 7. Limitation of Liability * +* -------------------------- * +* * +* Under no circumstances and under no legal theory, whether tort * +* (including negligence), contract, or otherwise, shall any * +* Contributor, or anyone who distributes Covered Software as * +* permitted above, be liable to You for any direct, indirect, * +* special, incidental, or consequential damages of any character * +* including, without limitation, damages for lost profits, loss of * +* goodwill, work stoppage, computer failure or malfunction, or any * +* and all other commercial damages or losses, even if such party * +* shall have been informed of the possibility of such damages. This * +* limitation of liability shall not apply to liability for death or * +* personal injury resulting from such party's negligence to the * +* extent applicable law prohibits such limitation. Some * +* jurisdictions do not allow the exclusion or limitation of * +* incidental or consequential damages, so this exclusion and * +* limitation may not apply to You. * +* * +************************************************************************ + +8. Litigation +------------- + +Any litigation relating to this License may be brought only in the +courts of a jurisdiction where the defendant maintains its principal +place of business and such litigation shall be governed by laws of that +jurisdiction, without reference to its conflict-of-law provisions. +Nothing in this Section shall prevent a party's ability to bring +cross-claims or counter-claims. + +9. Miscellaneous +---------------- + +This License represents the complete agreement concerning the subject +matter hereof. If any provision of this License is held to be +unenforceable, such provision shall be reformed only to the extent +necessary to make it enforceable. Any law or regulation which provides +that the language of a contract shall be construed against the drafter +shall not be used to construe this License against a Contributor. + +10. Versions of the License +--------------------------- + +10.1. New Versions + +Mozilla Foundation is the license steward. Except as provided in Section +10.3, no one other than the license steward has the right to modify or +publish new versions of this License. Each version will be given a +distinguishing version number. + +10.2. Effect of New Versions + +You may distribute the Covered Software under the terms of the version +of the License under which You originally received the Covered Software, +or under the terms of any subsequent version published by the license +steward. + +10.3. Modified Versions + +If you create software not governed by this License, and you want to +create a new license for such software, you may create and use a +modified version of this License if you rename the license and remove +any references to the name of the license steward (except to note that +such modified license differs from this License). + +10.4. Distributing Source Code Form that is Incompatible With Secondary +Licenses + +If You choose to distribute Source Code Form that is Incompatible With +Secondary Licenses under the terms of this version of the License, the +notice described in Exhibit B of this License must be attached. + +Exhibit A - Source Code Form License Notice +------------------------------------------- + + This Source Code Form is subject to the terms of the Mozilla Public + License, v. 2.0. If a copy of the MPL was not distributed with this + file, You can obtain one at https://mozilla.org/MPL/2.0/. + +If it is not possible or desirable to put the notice in a particular +file, then You may include the notice in a location (such as a LICENSE +file in a relevant directory) where a recipient would be likely to look +for such a notice. + +You may add additional accurate notices of copyright ownership. + +Exhibit B - "Incompatible With Secondary Licenses" Notice +--------------------------------------------------------- + + This Source Code Form is "Incompatible With Secondary Licenses", as + defined by the Mozilla Public License, v. 2.0. diff --git a/resources/sources/avr-libstdcpp/COPYING3 b/resources/sources/avr-libstdcpp/COPYING3 new file mode 100644 index 000000000..f288702d2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/COPYING3 @@ -0,0 +1,674 @@ + GNU GENERAL PUBLIC LICENSE + Version 3, 29 June 2007 + + Copyright (C) 2007 Free Software Foundation, Inc. + Everyone is permitted to copy and distribute verbatim copies + of this license document, but changing it is not allowed. + + Preamble + + The GNU General Public License is a free, copyleft license for +software and other kinds of works. + + The licenses for most software and other practical works are designed +to take away your freedom to share and change the works. By contrast, +the GNU General Public License is intended to guarantee your freedom to +share and change all versions of a program--to make sure it remains free +software for all its users. We, the Free Software Foundation, use the +GNU General Public License for most of our software; it applies also to +any other work released this way by its authors. You can apply it to +your programs, too. + + When we speak of free software, we are referring to freedom, not +price. Our General Public Licenses are designed to make sure that you +have the freedom to distribute copies of free software (and charge for +them if you wish), that you receive source code or can get it if you +want it, that you can change the software or use pieces of it in new +free programs, and that you know you can do these things. + + To protect your rights, we need to prevent others from denying you +these rights or asking you to surrender the rights. Therefore, you have +certain responsibilities if you distribute copies of the software, or if +you modify it: responsibilities to respect the freedom of others. + + For example, if you distribute copies of such a program, whether +gratis or for a fee, you must pass on to the recipients the same +freedoms that you received. You must make sure that they, too, receive +or can get the source code. And you must show them these terms so they +know their rights. + + Developers that use the GNU GPL protect your rights with two steps: +(1) assert copyright on the software, and (2) offer you this License +giving you legal permission to copy, distribute and/or modify it. + + For the developers' and authors' protection, the GPL clearly explains +that there is no warranty for this free software. For both users' and +authors' sake, the GPL requires that modified versions be marked as +changed, so that their problems will not be attributed erroneously to +authors of previous versions. + + Some devices are designed to deny users access to install or run +modified versions of the software inside them, although the manufacturer +can do so. This is fundamentally incompatible with the aim of +protecting users' freedom to change the software. The systematic +pattern of such abuse occurs in the area of products for individuals to +use, which is precisely where it is most unacceptable. Therefore, we +have designed this version of the GPL to prohibit the practice for those +products. If such problems arise substantially in other domains, we +stand ready to extend this provision to those domains in future versions +of the GPL, as needed to protect the freedom of users. + + Finally, every program is threatened constantly by software patents. +States should not allow patents to restrict development and use of +software on general-purpose computers, but in those that do, we wish to +avoid the special danger that patents applied to a free program could +make it effectively proprietary. To prevent this, the GPL assures that +patents cannot be used to render the program non-free. + + The precise terms and conditions for copying, distribution and +modification follow. + + TERMS AND CONDITIONS + + 0. Definitions. + + "This License" refers to version 3 of the GNU General Public License. + + "Copyright" also means copyright-like laws that apply to other kinds of +works, such as semiconductor masks. + + "The Program" refers to any copyrightable work licensed under this +License. Each licensee is addressed as "you". "Licensees" and +"recipients" may be individuals or organizations. + + To "modify" a work means to copy from or adapt all or part of the work +in a fashion requiring copyright permission, other than the making of an +exact copy. The resulting work is called a "modified version" of the +earlier work or a work "based on" the earlier work. + + A "covered work" means either the unmodified Program or a work based +on the Program. + + To "propagate" a work means to do anything with it that, without +permission, would make you directly or secondarily liable for +infringement under applicable copyright law, except executing it on a +computer or modifying a private copy. Propagation includes copying, +distribution (with or without modification), making available to the +public, and in some countries other activities as well. + + To "convey" a work means any kind of propagation that enables other +parties to make or receive copies. Mere interaction with a user through +a computer network, with no transfer of a copy, is not conveying. + + An interactive user interface displays "Appropriate Legal Notices" +to the extent that it includes a convenient and prominently visible +feature that (1) displays an appropriate copyright notice, and (2) +tells the user that there is no warranty for the work (except to the +extent that warranties are provided), that licensees may convey the +work under this License, and how to view a copy of this License. If +the interface presents a list of user commands or options, such as a +menu, a prominent item in the list meets this criterion. + + 1. Source Code. + + The "source code" for a work means the preferred form of the work +for making modifications to it. "Object code" means any non-source +form of a work. + + A "Standard Interface" means an interface that either is an official +standard defined by a recognized standards body, or, in the case of +interfaces specified for a particular programming language, one that +is widely used among developers working in that language. + + The "System Libraries" of an executable work include anything, other +than the work as a whole, that (a) is included in the normal form of +packaging a Major Component, but which is not part of that Major +Component, and (b) serves only to enable use of the work with that +Major Component, or to implement a Standard Interface for which an +implementation is available to the public in source code form. A +"Major Component", in this context, means a major essential component +(kernel, window system, and so on) of the specific operating system +(if any) on which the executable work runs, or a compiler used to +produce the work, or an object code interpreter used to run it. + + The "Corresponding Source" for a work in object code form means all +the source code needed to generate, install, and (for an executable +work) run the object code and to modify the work, including scripts to +control those activities. However, it does not include the work's +System Libraries, or general-purpose tools or generally available free +programs which are used unmodified in performing those activities but +which are not part of the work. For example, Corresponding Source +includes interface definition files associated with source files for +the work, and the source code for shared libraries and dynamically +linked subprograms that the work is specifically designed to require, +such as by intimate data communication or control flow between those +subprograms and other parts of the work. + + The Corresponding Source need not include anything that users +can regenerate automatically from other parts of the Corresponding +Source. + + The Corresponding Source for a work in source code form is that +same work. + + 2. Basic Permissions. + + All rights granted under this License are granted for the term of +copyright on the Program, and are irrevocable provided the stated +conditions are met. This License explicitly affirms your unlimited +permission to run the unmodified Program. The output from running a +covered work is covered by this License only if the output, given its +content, constitutes a covered work. This License acknowledges your +rights of fair use or other equivalent, as provided by copyright law. + + You may make, run and propagate covered works that you do not +convey, without conditions so long as your license otherwise remains +in force. You may convey covered works to others for the sole purpose +of having them make modifications exclusively for you, or provide you +with facilities for running those works, provided that you comply with +the terms of this License in conveying all material for which you do +not control copyright. Those thus making or running the covered works +for you must do so exclusively on your behalf, under your direction +and control, on terms that prohibit them from making any copies of +your copyrighted material outside their relationship with you. + + Conveying under any other circumstances is permitted solely under +the conditions stated below. Sublicensing is not allowed; section 10 +makes it unnecessary. + + 3. Protecting Users' Legal Rights From Anti-Circumvention Law. + + No covered work shall be deemed part of an effective technological +measure under any applicable law fulfilling obligations under article +11 of the WIPO copyright treaty adopted on 20 December 1996, or +similar laws prohibiting or restricting circumvention of such +measures. + + When you convey a covered work, you waive any legal power to forbid +circumvention of technological measures to the extent such circumvention +is effected by exercising rights under this License with respect to +the covered work, and you disclaim any intention to limit operation or +modification of the work as a means of enforcing, against the work's +users, your or third parties' legal rights to forbid circumvention of +technological measures. + + 4. Conveying Verbatim Copies. + + You may convey verbatim copies of the Program's source code as you +receive it, in any medium, provided that you conspicuously and +appropriately publish on each copy an appropriate copyright notice; +keep intact all notices stating that this License and any +non-permissive terms added in accord with section 7 apply to the code; +keep intact all notices of the absence of any warranty; and give all +recipients a copy of this License along with the Program. + + You may charge any price or no price for each copy that you convey, +and you may offer support or warranty protection for a fee. + + 5. Conveying Modified Source Versions. + + You may convey a work based on the Program, or the modifications to +produce it from the Program, in the form of source code under the +terms of section 4, provided that you also meet all of these conditions: + + a) The work must carry prominent notices stating that you modified + it, and giving a relevant date. + + b) The work must carry prominent notices stating that it is + released under this License and any conditions added under section + 7. This requirement modifies the requirement in section 4 to + "keep intact all notices". + + c) You must license the entire work, as a whole, under this + License to anyone who comes into possession of a copy. This + License will therefore apply, along with any applicable section 7 + additional terms, to the whole of the work, and all its parts, + regardless of how they are packaged. This License gives no + permission to license the work in any other way, but it does not + invalidate such permission if you have separately received it. + + d) If the work has interactive user interfaces, each must display + Appropriate Legal Notices; however, if the Program has interactive + interfaces that do not display Appropriate Legal Notices, your + work need not make them do so. + + A compilation of a covered work with other separate and independent +works, which are not by their nature extensions of the covered work, +and which are not combined with it such as to form a larger program, +in or on a volume of a storage or distribution medium, is called an +"aggregate" if the compilation and its resulting copyright are not +used to limit the access or legal rights of the compilation's users +beyond what the individual works permit. Inclusion of a covered work +in an aggregate does not cause this License to apply to the other +parts of the aggregate. + + 6. Conveying Non-Source Forms. + + You may convey a covered work in object code form under the terms +of sections 4 and 5, provided that you also convey the +machine-readable Corresponding Source under the terms of this License, +in one of these ways: + + a) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by the + Corresponding Source fixed on a durable physical medium + customarily used for software interchange. + + b) Convey the object code in, or embodied in, a physical product + (including a physical distribution medium), accompanied by a + written offer, valid for at least three years and valid for as + long as you offer spare parts or customer support for that product + model, to give anyone who possesses the object code either (1) a + copy of the Corresponding Source for all the software in the + product that is covered by this License, on a durable physical + medium customarily used for software interchange, for a price no + more than your reasonable cost of physically performing this + conveying of source, or (2) access to copy the + Corresponding Source from a network server at no charge. + + c) Convey individual copies of the object code with a copy of the + written offer to provide the Corresponding Source. This + alternative is allowed only occasionally and noncommercially, and + only if you received the object code with such an offer, in accord + with subsection 6b. + + d) Convey the object code by offering access from a designated + place (gratis or for a charge), and offer equivalent access to the + Corresponding Source in the same way through the same place at no + further charge. You need not require recipients to copy the + Corresponding Source along with the object code. If the place to + copy the object code is a network server, the Corresponding Source + may be on a different server (operated by you or a third party) + that supports equivalent copying facilities, provided you maintain + clear directions next to the object code saying where to find the + Corresponding Source. Regardless of what server hosts the + Corresponding Source, you remain obligated to ensure that it is + available for as long as needed to satisfy these requirements. + + e) Convey the object code using peer-to-peer transmission, provided + you inform other peers where the object code and Corresponding + Source of the work are being offered to the general public at no + charge under subsection 6d. + + A separable portion of the object code, whose source code is excluded +from the Corresponding Source as a System Library, need not be +included in conveying the object code work. + + A "User Product" is either (1) a "consumer product", which means any +tangible personal property which is normally used for personal, family, +or household purposes, or (2) anything designed or sold for incorporation +into a dwelling. In determining whether a product is a consumer product, +doubtful cases shall be resolved in favor of coverage. For a particular +product received by a particular user, "normally used" refers to a +typical or common use of that class of product, regardless of the status +of the particular user or of the way in which the particular user +actually uses, or expects or is expected to use, the product. A product +is a consumer product regardless of whether the product has substantial +commercial, industrial or non-consumer uses, unless such uses represent +the only significant mode of use of the product. + + "Installation Information" for a User Product means any methods, +procedures, authorization keys, or other information required to install +and execute modified versions of a covered work in that User Product from +a modified version of its Corresponding Source. The information must +suffice to ensure that the continued functioning of the modified object +code is in no case prevented or interfered with solely because +modification has been made. + + If you convey an object code work under this section in, or with, or +specifically for use in, a User Product, and the conveying occurs as +part of a transaction in which the right of possession and use of the +User Product is transferred to the recipient in perpetuity or for a +fixed term (regardless of how the transaction is characterized), the +Corresponding Source conveyed under this section must be accompanied +by the Installation Information. But this requirement does not apply +if neither you nor any third party retains the ability to install +modified object code on the User Product (for example, the work has +been installed in ROM). + + The requirement to provide Installation Information does not include a +requirement to continue to provide support service, warranty, or updates +for a work that has been modified or installed by the recipient, or for +the User Product in which it has been modified or installed. Access to a +network may be denied when the modification itself materially and +adversely affects the operation of the network or violates the rules and +protocols for communication across the network. + + Corresponding Source conveyed, and Installation Information provided, +in accord with this section must be in a format that is publicly +documented (and with an implementation available to the public in +source code form), and must require no special password or key for +unpacking, reading or copying. + + 7. Additional Terms. + + "Additional permissions" are terms that supplement the terms of this +License by making exceptions from one or more of its conditions. +Additional permissions that are applicable to the entire Program shall +be treated as though they were included in this License, to the extent +that they are valid under applicable law. If additional permissions +apply only to part of the Program, that part may be used separately +under those permissions, but the entire Program remains governed by +this License without regard to the additional permissions. + + When you convey a copy of a covered work, you may at your option +remove any additional permissions from that copy, or from any part of +it. (Additional permissions may be written to require their own +removal in certain cases when you modify the work.) You may place +additional permissions on material, added by you to a covered work, +for which you have or can give appropriate copyright permission. + + Notwithstanding any other provision of this License, for material you +add to a covered work, you may (if authorized by the copyright holders of +that material) supplement the terms of this License with terms: + + a) Disclaiming warranty or limiting liability differently from the + terms of sections 15 and 16 of this License; or + + b) Requiring preservation of specified reasonable legal notices or + author attributions in that material or in the Appropriate Legal + Notices displayed by works containing it; or + + c) Prohibiting misrepresentation of the origin of that material, or + requiring that modified versions of such material be marked in + reasonable ways as different from the original version; or + + d) Limiting the use for publicity purposes of names of licensors or + authors of the material; or + + e) Declining to grant rights under trademark law for use of some + trade names, trademarks, or service marks; or + + f) Requiring indemnification of licensors and authors of that + material by anyone who conveys the material (or modified versions of + it) with contractual assumptions of liability to the recipient, for + any liability that these contractual assumptions directly impose on + those licensors and authors. + + All other non-permissive additional terms are considered "further +restrictions" within the meaning of section 10. If the Program as you +received it, or any part of it, contains a notice stating that it is +governed by this License along with a term that is a further +restriction, you may remove that term. If a license document contains +a further restriction but permits relicensing or conveying under this +License, you may add to a covered work material governed by the terms +of that license document, provided that the further restriction does +not survive such relicensing or conveying. + + If you add terms to a covered work in accord with this section, you +must place, in the relevant source files, a statement of the +additional terms that apply to those files, or a notice indicating +where to find the applicable terms. + + Additional terms, permissive or non-permissive, may be stated in the +form of a separately written license, or stated as exceptions; +the above requirements apply either way. + + 8. Termination. + + You may not propagate or modify a covered work except as expressly +provided under this License. Any attempt otherwise to propagate or +modify it is void, and will automatically terminate your rights under +this License (including any patent licenses granted under the third +paragraph of section 11). + + However, if you cease all violation of this License, then your +license from a particular copyright holder is reinstated (a) +provisionally, unless and until the copyright holder explicitly and +finally terminates your license, and (b) permanently, if the copyright +holder fails to notify you of the violation by some reasonable means +prior to 60 days after the cessation. + + Moreover, your license from a particular copyright holder is +reinstated permanently if the copyright holder notifies you of the +violation by some reasonable means, this is the first time you have +received notice of violation of this License (for any work) from that +copyright holder, and you cure the violation prior to 30 days after +your receipt of the notice. + + Termination of your rights under this section does not terminate the +licenses of parties who have received copies or rights from you under +this License. If your rights have been terminated and not permanently +reinstated, you do not qualify to receive new licenses for the same +material under section 10. + + 9. Acceptance Not Required for Having Copies. + + You are not required to accept this License in order to receive or +run a copy of the Program. Ancillary propagation of a covered work +occurring solely as a consequence of using peer-to-peer transmission +to receive a copy likewise does not require acceptance. However, +nothing other than this License grants you permission to propagate or +modify any covered work. These actions infringe copyright if you do +not accept this License. Therefore, by modifying or propagating a +covered work, you indicate your acceptance of this License to do so. + + 10. Automatic Licensing of Downstream Recipients. + + Each time you convey a covered work, the recipient automatically +receives a license from the original licensors, to run, modify and +propagate that work, subject to this License. You are not responsible +for enforcing compliance by third parties with this License. + + An "entity transaction" is a transaction transferring control of an +organization, or substantially all assets of one, or subdividing an +organization, or merging organizations. If propagation of a covered +work results from an entity transaction, each party to that +transaction who receives a copy of the work also receives whatever +licenses to the work the party's predecessor in interest had or could +give under the previous paragraph, plus a right to possession of the +Corresponding Source of the work from the predecessor in interest, if +the predecessor has it or can get it with reasonable efforts. + + You may not impose any further restrictions on the exercise of the +rights granted or affirmed under this License. For example, you may +not impose a license fee, royalty, or other charge for exercise of +rights granted under this License, and you may not initiate litigation +(including a cross-claim or counterclaim in a lawsuit) alleging that +any patent claim is infringed by making, using, selling, offering for +sale, or importing the Program or any portion of it. + + 11. Patents. + + A "contributor" is a copyright holder who authorizes use under this +License of the Program or a work on which the Program is based. The +work thus licensed is called the contributor's "contributor version". + + A contributor's "essential patent claims" are all patent claims +owned or controlled by the contributor, whether already acquired or +hereafter acquired, that would be infringed by some manner, permitted +by this License, of making, using, or selling its contributor version, +but do not include claims that would be infringed only as a +consequence of further modification of the contributor version. For +purposes of this definition, "control" includes the right to grant +patent sublicenses in a manner consistent with the requirements of +this License. + + Each contributor grants you a non-exclusive, worldwide, royalty-free +patent license under the contributor's essential patent claims, to +make, use, sell, offer for sale, import and otherwise run, modify and +propagate the contents of its contributor version. + + In the following three paragraphs, a "patent license" is any express +agreement or commitment, however denominated, not to enforce a patent +(such as an express permission to practice a patent or covenant not to +sue for patent infringement). To "grant" such a patent license to a +party means to make such an agreement or commitment not to enforce a +patent against the party. + + If you convey a covered work, knowingly relying on a patent license, +and the Corresponding Source of the work is not available for anyone +to copy, free of charge and under the terms of this License, through a +publicly available network server or other readily accessible means, +then you must either (1) cause the Corresponding Source to be so +available, or (2) arrange to deprive yourself of the benefit of the +patent license for this particular work, or (3) arrange, in a manner +consistent with the requirements of this License, to extend the patent +license to downstream recipients. "Knowingly relying" means you have +actual knowledge that, but for the patent license, your conveying the +covered work in a country, or your recipient's use of the covered work +in a country, would infringe one or more identifiable patents in that +country that you have reason to believe are valid. + + If, pursuant to or in connection with a single transaction or +arrangement, you convey, or propagate by procuring conveyance of, a +covered work, and grant a patent license to some of the parties +receiving the covered work authorizing them to use, propagate, modify +or convey a specific copy of the covered work, then the patent license +you grant is automatically extended to all recipients of the covered +work and works based on it. + + A patent license is "discriminatory" if it does not include within +the scope of its coverage, prohibits the exercise of, or is +conditioned on the non-exercise of one or more of the rights that are +specifically granted under this License. You may not convey a covered +work if you are a party to an arrangement with a third party that is +in the business of distributing software, under which you make payment +to the third party based on the extent of your activity of conveying +the work, and under which the third party grants, to any of the +parties who would receive the covered work from you, a discriminatory +patent license (a) in connection with copies of the covered work +conveyed by you (or copies made from those copies), or (b) primarily +for and in connection with specific products or compilations that +contain the covered work, unless you entered into that arrangement, +or that patent license was granted, prior to 28 March 2007. + + Nothing in this License shall be construed as excluding or limiting +any implied license or other defenses to infringement that may +otherwise be available to you under applicable patent law. + + 12. No Surrender of Others' Freedom. + + If conditions are imposed on you (whether by court order, agreement or +otherwise) that contradict the conditions of this License, they do not +excuse you from the conditions of this License. If you cannot convey a +covered work so as to satisfy simultaneously your obligations under this +License and any other pertinent obligations, then as a consequence you may +not convey it at all. For example, if you agree to terms that obligate you +to collect a royalty for further conveying from those to whom you convey +the Program, the only way you could satisfy both those terms and this +License would be to refrain entirely from conveying the Program. + + 13. Use with the GNU Affero General Public License. + + Notwithstanding any other provision of this License, you have +permission to link or combine any covered work with a work licensed +under version 3 of the GNU Affero General Public License into a single +combined work, and to convey the resulting work. The terms of this +License will continue to apply to the part which is the covered work, +but the special requirements of the GNU Affero General Public License, +section 13, concerning interaction through a network will apply to the +combination as such. + + 14. Revised Versions of this License. + + The Free Software Foundation may publish revised and/or new versions of +the GNU General Public License from time to time. Such new versions will +be similar in spirit to the present version, but may differ in detail to +address new problems or concerns. + + Each version is given a distinguishing version number. If the +Program specifies that a certain numbered version of the GNU General +Public License "or any later version" applies to it, you have the +option of following the terms and conditions either of that numbered +version or of any later version published by the Free Software +Foundation. If the Program does not specify a version number of the +GNU General Public License, you may choose any version ever published +by the Free Software Foundation. + + If the Program specifies that a proxy can decide which future +versions of the GNU General Public License can be used, that proxy's +public statement of acceptance of a version permanently authorizes you +to choose that version for the Program. + + Later license versions may give you additional or different +permissions. However, no additional obligations are imposed on any +author or copyright holder as a result of your choosing to follow a +later version. + + 15. Disclaimer of Warranty. + + THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY +APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT +HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY +OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, +THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR +PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM +IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF +ALL NECESSARY SERVICING, REPAIR OR CORRECTION. + + 16. Limitation of Liability. + + IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING +WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS +THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY +GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE +USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF +DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD +PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS), +EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF +SUCH DAMAGES. + + 17. Interpretation of Sections 15 and 16. + + If the disclaimer of warranty and limitation of liability provided +above cannot be given local legal effect according to their terms, +reviewing courts shall apply local law that most closely approximates +an absolute waiver of all civil liability in connection with the +Program, unless a warranty or assumption of liability accompanies a +copy of the Program in return for a fee. + + END OF TERMS AND CONDITIONS + + How to Apply These Terms to Your New Programs + + If you develop a new program, and you want it to be of the greatest +possible use to the public, the best way to achieve this is to make it +free software which everyone can redistribute and change under these terms. + + To do so, attach the following notices to the program. It is safest +to attach them to the start of each source file to most effectively +state the exclusion of warranty; and each file should have at least +the "copyright" line and a pointer to where the full notice is found. + + + Copyright (C) + + This program is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . + +Also add information on how to contact you by electronic and paper mail. + + If the program does terminal interaction, make it output a short +notice like this when it starts in an interactive mode: + + Copyright (C) + This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. + This is free software, and you are welcome to redistribute it + under certain conditions; type `show c' for details. + +The hypothetical commands `show w' and `show c' should show the appropriate +parts of the General Public License. Of course, your program's commands +might be different; for a GUI interface, you would use an "about box". + + You should also get your employer (if you work as a programmer) or school, +if any, to sign a "copyright disclaimer" for the program, if necessary. +For more information on this, and how to apply and follow the GNU GPL, see +. + + The GNU General Public License does not permit incorporating your program +into proprietary programs. If your program is a subroutine library, you +may consider it more useful to permit linking proprietary applications with +the library. If this is what you want to do, use the GNU Lesser General +Public License instead of this License. But first, please read +. diff --git a/resources/sources/avr-libstdcpp/OPENPLC_MODIFICATIONS.md b/resources/sources/avr-libstdcpp/OPENPLC_MODIFICATIONS.md new file mode 100644 index 000000000..13c5863a9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/OPENPLC_MODIFICATIONS.md @@ -0,0 +1,35 @@ +# OpenPLC Editor fork of modm-io/avr-libstdcpp + +This is a vendored copy of [modm-io/avr-libstdcpp](https://github.com/modm-io/avr-libstdcpp) +with two small additions required for STruC++ generated code to compile on Arduino's +AVR GCC 7.3 toolchain. + +## Upstream + +- Repository: https://github.com/modm-io/avr-libstdcpp +- License: GPLv3 with GCC Runtime Library Exception (see `COPYING3` and `COPYING.MPLv2`) +- Clone date: kept in sync with STruC++ runtime requirements + +## Modifications + +### 1. Added `include/string` (stub) + +Upstream intentionally excludes `` because `std::string` requires heap + exceptions, +neither appropriate for AVR. STruC++ generated code `#include`s `` unconditionally +in its header preamble but never actually uses `std::string` (it uses its own stack-allocated +`IECString` template). The stub file is empty — it just satisfies the include directive. + +### 2. Added `strtoll` / `strtoull` shims in `include/cstdlib` + +AVR libc does not provide 64-bit string conversion functions. STruC++'s `iec_string.hpp` +uses `std::strtoll`/`std::strtoull` for IEC `LINT`/`ULINT` STRING conversions. Added inline +shims inside `namespace std` that fall back to 32-bit `strtol`/`strtoul`. See the `#ifdef +__AVR__` block at the end of `cstdlib`. + +## Usage + +Added to the compiler's include path via `-I` (NOT `-isystem`) when compiling for AVR +boards. The Arduino AVR GCC 7.3 preprocessor has a bug where `-isystem` headers are +treated as C-linkage, causing "template with C linkage" errors. Using `-I` avoids this. + +See `src/backend/editor/compiler/compiler-module.ts` `handleCompileArduinoProgram()`. diff --git a/resources/sources/avr-libstdcpp/README.md b/resources/sources/avr-libstdcpp/README.md new file mode 100644 index 000000000..0fff5319b --- /dev/null +++ b/resources/sources/avr-libstdcpp/README.md @@ -0,0 +1,359 @@ +# avr-libstdcpp: libstdc++ port for avr-gcc +[![Build Status](https://github.com/modm-io/avr-libstdcpp/actions/workflows/compile_examples.yml/badge.svg)](https://github.com/modm-io/avr-libstdcpp/actions) +================== + +`avr-libstdcpp` is a partial, non-fully-tested +implementation of the C++ standard library and its STL. +It is intended to be used with `avr-gcc`. + +Many features of modern C++11,14,17 and 20 are supported. + +`avr-gcc` does not have a complete C++ standard library nor does it include an STL implementation. +The `avr-libstdcpp` port (even though not-fully-tested +and only partially full/complete) will, nonetheless, +be useful for those interested in making more comprehensive utilization +of C++, including its standard library, with a modern `avr-gcc` compiler. + +## Historical origins + +The `avr-libstdcpp` library traces its own origins to existing +GNU/GCC C++ standard library implementation(s), themselves targeting +embedded systems. This work is essentially an even-more +_embedded_-_friendly_ adaptation of the aforementioned work. + +The `avr-libstdcpp` port began in 2018 with an initial import +of a GNU/GCC-based C++ standard library from GCC 8. +A second import of a GNU/GCC-based C++ standard library from GCC 10 +in 2020 modernized the port to include many contemporary C++20 features. + +## Using the library + +- Add the `avr-libstdcpp/include` path to the standard `-isystem` (or `-I`) include path(s) of the compiler on the command line. +- Upon doing this, include standard library headers in the usual way (i.e., `#include `, `#include `, `#include `, etc.). +- There are also several source files located in the [src directory](./src). Some of these may potentially be needed. +- For instance, when doing floating-point mathematical calculations with the `` library, the file [`math.cc`](./src/math.cc) located [here](./src) needs to be added as a normal source file to your project. + + +For straightforward header-only use, for example, +simply add the `-isystem` (or alternatively the `-I`) include path +to your particular location of `avr-libstdcpp/include` on the command line... + +```sh +avr-g++ -O2 -x c++ -isystem /my_path/avr-libstdcpp/include -mmcu=atmega328p test.cpp -o test.elf +``` + +... and seamlessly use standard library headers in your code. + +```cpp +#include +#include + +std::array a { 1, 2, 3 }; + +int main() +{ + // 6 + auto sum = std::accumulate(a.cbegin(), a.cend(), 0); + + static_cast(sum); +} +``` + +Additional straightforward code samples exercising standard library usage +can be found in the [examples](./examples) folder. + +## Using the library with MICROCHIP's ATMEL Studio + +`avr-libstdcpp` can be successfully used with MICROCHIP's ATMEL Studio. +The include path of the headers needs to be added to the project settings in the normal way. +Add also any of the necessary source files, as described in the section above. + +This is an advanced use of `avr-libstdcpp` in combination with MICROCHIP's ATMEL Studio +because the underlying GCC compiler used with ATMEL Studio also needs to be +upgraded to a much more modern one than the `avr-gcc` 5 +delivered in the standard installation of this studio. + +An [informative thread](https://github.com/modm-io/avr-libstdcpp/issues/17#issuecomment-1098241768) +provides a few more details on how to use `avr-libstdcpp` with MICROCHIP's ATMEL Studio. + +## Guidance for tiny bare-metal systems + +### Very helpful go-to libraries + +In general the C++ standard library is intended +to be written and implemented in a resource-sensitive +fashion. This includes efforts to save on both +memory as well as run-time. +In fact, C++ standard library functions and algorithms +have, in general, been specifically written and tuned by +the library authors with efficiency aspects in mind. +In particular, library components compile reliably and quickly +and also lend themselves well to compiler optimization. + +Some library components, however, are particularly well-suited +for bare-metal microcontroller programming. +These can be exceptionally helpful when used properly and sensibly +in tiny bare-metal microcontroller environments. + +A subjective list of these the libraries/headers +and their main uses includes, but is not limited to,: + +- `` for containers having known, fixed size. +- `` for standard algorithms such as sorting, minimax, sequential operations, etc. +- `` for projects requiring floating-point mathematical functions such as `std::sin()`, `std::exp()`, `std::frexp()` and many more. For some mathematical uses, it might be necessary to include [`math.cc`](./src/math.cc) in your project. This source file is located [here](./src). +- `` which defines integral types having specified widths residing within `namespace std` like `std::uint8_t`. +- `` offering compile-time query of numeric limits of built-in types. +- `` featuring a collection of useful numeric algorithms such as `std::accumulate()`, etc. +- `` for compile-time decisions based on types. + +With these libraries alone, the entire project can benefit +from a great deal of the standard library's power without compromising +in any way on performance or sleek memory footprint. +This is because these libaries are typically lean, fast and require no additional storage. + +The following non-trivial, real-world example, for instance, +wraps instances of an overly-simplified LED class abstraction +as object-references in an `std::array`. +Once stored, the application exercises the LED's toggle +function in an algorithmic loop with `toggle()`-method call +expressed via lambda function. + +```cpp +#include +#include +#include + +class led +{ +public: + led() = default; + + auto toggle() -> void { } +}; + +led led0; +led led1; +led led2; + +using led_ref_type = std::reference_wrapper; + +std::array led_refs = +{ + led0, + led1, + led2 +}; + +int main() +{ + for(;;) + { + std::for_each(led_refs.begin(), + led_refs.end(), + [](led& lr) { lr.toggle(); }); + } +} +``` + +This nifty little example is terse, expressive and powerful. +It makes use of parts of ``, `` and `` +to greatly simplify the programming within a non-trivial +microcontroller situation. + +This example is key because it combines the domains +of object-oriented programming with the templated +algorithms and wrappers of the STL to assist +in our microcontroller world. + +### Libraries requiring more design considerations + +Some C++ library and STL artifacts, however, +require more careful design considerations +regarding memory allocation and management. + +Consider, for instance, `std::vector` from the `` library. +Vector creates a flexibly-sized array-like collection +of items of any kind, depending on the template parameter. + +For instance: + +```cpp +#include + +// A vector of 3 integers. +std::vector v { 1, 2, 3 }; +``` + +See also the [main.cpp](./examples/vector/main.cpp) file +in the [./examples/vector](./examples/vector) directory. + +This vector requires storage for three integers which, +on the `avr-gcc` platform is 6 bytes. The storage is managed +through vector's _second_, less well-known template parameter. +In other words, + +```cpp +namespace std { + +// Forward declaration of the vector template class. +template> +class vector; + +} +``` + +Using containers requires memory allocation with a so-called allocator. +If none is specified, as in our code snippet, the default allocator +from namespace `std` for the templated type `T` of the vector is +automatically selected. + +Good embeddable self-written custom allocators are essential for +using such containers so that memory could be managed with +a self-written memory pool, an off-chip memory device, etc. +A common selection is a pool of static memory creating a so-called +_ring_ _allocator_. This is an intermetiate/advanced topic +which will refine STL use _on_ _the_ _metal_ and +also allow for flexible template use in these resource-sensitive +realms. + +## Notable adaptions and limitations + +Some parts of the C++ standard library are not well suited for +tiny bare-metal systems. These include some memory-intensive +and/or hardware-intensive library artifacts. + +`avr-libstdcpp` has the following known adaptions and limitations. + +- **I/O streaming and RTTI:** I/O streaming and run-time type information (RTTI) are known +to be resource-intensive and could be disruptive on tiny +embedded platforms. An effort has been made to essentially +remove both these library dependencies and their +associated codes. + +- **exceptions:** Exceptions are also difficult to efficiently +implement on tiny embedded platforms and this library port avoids using exceptions. +The headers `` and ``, their dependencies, +and their directly relevant code sequences have been removed. +Simple mechanisms such as those found in `` +and ``, however, remain mostly available. + +- **``:** The `` library is being handled +specifically in the draft of +[avr-libstdcpp/pull/36](https://github.com/modm-io/avr-libstdcpp/pull/36). + +- **``:** There is no source of entropy whatsoever on these platforms +in their standard configuration. So `std::random_device` +has been removed. + +- **Hashing:** Hashing has been optimized for tiny architectures and uses a rudimentary 16-bit CRC algorithm. + +- **``:** Only certain judiciously selected clock functions from the `` library are implemented. +These include `std::chrono::high_resolution_clock` and `std::chrono::steady_clock`. When using +these clocks, it is required to implement the clock's static method +`now()` in a project-specific fashion. This is because +the library's authors can not in a generic way implement any +microcontroller-specific clock(s) since this requires detailed knowledge +of the underlying microcontroller peripherie. + +- **`int`, `size_t`, `ptrdiff_t` and the like:** Data types such as +`int`, and `size_t` and `ptrdiff_t` (which are aliased to +`unsigned`/`signed` versions of `int`) +are generally limited to 16-bits in width +on tiny `avr-gcc` platforms. Although this is a compiler attribute, +it has strong influence on the library (particularly the STL) +implementation because these data types are used copiously therein. +This compiler attribute limits ranges, indexes, etc. to 16-bits. +With the compiler switch `-mint8`, the built-in type `int` +is only 8 bits wide and extreme range limitations +are expected to make STL use tricky. + +- **``:** In `avr-gcc` 10 and higher, the built-in data types +`double` and `long double` can be either 32 or 64 bits in width. +The widths depend on the compiler command line options `-mdouble=32` +(alternatively `-mdouble=64`) and/or `-mlong-double=32` +(alternatively `-mlong-double=64`). Standard floating-point +`` functions such as `std::sin()`, `std::cos()`, +`std::exp()` and the like will, therefore, have input and output +widths according to these command line options. + +## C++20 `constexpr` support + +The following is a rather advanced, highly useful topic. +When using C++20, `constexpr` construction, assignment and evaluation +of various algorithms can and often will be generally +compile-time constant (i.e, via consistent use of C++20 `constexpr`-ness). + +As a result of this, STL algorithms that use compile-time constant inputs are, in fact, +evaluated at compile time in C++20. This lets us perform a strong, +purposeful shift of algorithmic complexity _to_-_the_-_left_. +In other words, we shift algorithmic complexity _into_ the compile-time +stage of code development and _away from_ the precious RAM-ROM-space/cycles +of the compiled running code. + +In the following code, for instance, we revisit the `std::array`/`` +example from above. The variation below exhibits complete compile-time +evaluation of the algorithmic result. + +To take the deep dive in this topic, follow all the useful compile-time +preprocessor symbols such as +`__cpp_lib_constexpr_algorithms`, `__cpp_lib_constexpr_numeric`, and many more +in [feature testing](https://en.cppreference.com/w/cpp/feature_test). + +```cpp +#include +#include + +#if (defined(__cpp_lib_constexpr_numeric) && (__cpp_lib_constexpr_numeric>=201911L)) +#define MODM_CONSTEXPR constexpr +#define MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR 1 +#else +#define MODM_CONSTEXPR +#define MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR 0 +#endif + +MODM_CONSTEXPR std::array a { 1, 2, 3 }; + +int main() +{ + // 6 + auto MODM_CONSTEXPR sum = std::accumulate(a.cbegin(), a.cend(), 0); + + #if (MODM_CONSTEXPR_NUMERIC_IS_CONSTEXPR == 1) + static_assert(sum == 6, "Error: Unexpected std::accumulate result!"); + #endif + + return (sum == 6 ? 0 : -1); +} +``` + +See also the [numeric.cpp](./examples/numeric/numeric.cpp) file +in the [/examples/numeric](./examples/numeric) directory. + +## Additional details + +`avr-libstdcpp` is intended for a modern `avr-gcc` +such as the port available in the [modm-io project](https://github.com/modm-io/avr-gcc) +repository. Tests show usability for `avr-gcc` 7 through 15. + +This library has been checked for compatibility on `avr-gcc` +with language standards C++11,14,17,20,23 and 2c. + +Using the port way back to `avr-gcc` 5 does not work +at the moment with today's form of the checked-in library, +and `avr-gcc` 7 or higher is required. +This is because the very old compiler lexical parsers are not capable +of properly handling some of the library's template code. +See also [avr-libstdcpp/issues/15](https://github.com/modm-io/avr-libstdcpp/issues/15) +which is closed and includes justification for its closure. + +## Licensing + +The library source files in [`src/`](./src/) +and the library include files in [`include/` and its subfolders](./include/) +(with two exceptions for the sources, as mentioned below) +are licensed under [GNU General Public License Version 3](./COPYING3) or higher. + +All of the [example codes](./examples/) and also two library source files +(namely `functexcept.cc` and `math.cc` in [`src/`](./src/)) +are subject to the terms of the [Mozilla Public License Version 2.0](./COPYING.MPLv2). diff --git a/resources/sources/avr-libstdcpp/include/algorithm b/resources/sources/avr-libstdcpp/include/algorithm index d0e7e3974..8000e3218 100644 --- a/resources/sources/avr-libstdcpp/include/algorithm +++ b/resources/sources/avr-libstdcpp/include/algorithm @@ -1,39 +1,67 @@ -// Minimal for AVR -#ifndef _AVR_ALGORITHM -#define _AVR_ALGORITHM - -namespace std { - template constexpr const T& min(const T& a, const T& b) { return (b < a) ? b : a; } - template constexpr const T& max(const T& a, const T& b) { return (a < b) ? b : a; } - - template constexpr T min(std::initializer_list ilist) { - const T* p = ilist.begin(); - T m = *p; - for (++p; p != ilist.end(); ++p) if (*p < m) m = *p; - return m; - } - template constexpr T max(std::initializer_list ilist) { - const T* p = ilist.begin(); - T m = *p; - for (++p; p != ilist.end(); ++p) if (*p > m) m = *p; - return m; - } - - template - InputIt find(InputIt first, InputIt last, const T& value) { - for (; first != last; ++first) if (*first == value) return first; - return last; - } - - template - OutputIt copy(InputIt first, InputIt last, OutputIt d_first) { - for (; first != last; ++first, ++d_first) *d_first = *first; - return d_first; - } - - template - void fill(ForwardIt first, ForwardIt last, const T& value) { - for (; first != last; ++first) *first = value; - } -} +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/algorithm + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ALGORITHM +#define _GLIBCXX_ALGORITHM 1 + +#pragma GCC system_header + +#include // UK-300. +#include +#include +#if __cplusplus > 201703L +# include #endif + +#endif /* _GLIBCXX_ALGORITHM */ diff --git a/resources/sources/avr-libstdcpp/include/any b/resources/sources/avr-libstdcpp/include/any new file mode 100644 index 000000000..39fc77082 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/any @@ -0,0 +1,626 @@ +// -*- C++ -*- + +// Copyright (C) 2014-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/any + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ANY +#define _GLIBCXX_ANY 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#if __cpp_rtti +#include +#else +namespace std +{ + class type_info; +} +#endif // __cpp_rtti + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + +#define __cpp_lib_any 201606L + + /** + * @brief A type-safe container of any type. + * + * An @c any object's state is either empty or it stores a contained object + * of CopyConstructible type. + */ + class any + { + // Holds either pointer to a heap object or the contained object itself. + union _Storage + { + constexpr _Storage() : _M_ptr{nullptr} {} + + // Prevent trivial copies of this type, buffer might hold a non-POD. + _Storage(const _Storage&) = delete; + _Storage& operator=(const _Storage&) = delete; + + void* _M_ptr; + aligned_storage::type _M_buffer; + }; + + template, + bool _Fits = (sizeof(_Tp) <= sizeof(_Storage)) + && (alignof(_Tp) <= alignof(_Storage))> + using _Internal = std::integral_constant; + + template + struct _Manager_internal; // uses small-object optimization + + template + struct _Manager_external; // creates contained object on the heap + + template + using _Manager = conditional_t<_Internal<_Tp>::value, + _Manager_internal<_Tp>, + _Manager_external<_Tp>>; + + template> + using _Decay_if_not_any = enable_if_t, _VTp>; + + /// Emplace with an object created from @p __args as the contained object. + template > + void __do_emplace(_Args&&... __args) + { + reset(); + _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); + _M_manager = &_Mgr::_S_manage; + } + + /// Emplace with an object created from @p __il and @p __args as + /// the contained object. + template > + void __do_emplace(initializer_list<_Up> __il, _Args&&... __args) + { + reset(); + _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); + _M_manager = &_Mgr::_S_manage; + } + + template + using __any_constructible + = enable_if<__and_, + is_constructible<_Tp, _Args...>>::value, + _Res>; + + template + using __any_constructible_t + = typename __any_constructible::type; + + template + using __emplace_t + = typename __any_constructible<_VTp&, _VTp, _Args...>::type; + + public: + // construct/destruct + + /// Default constructor, creates an empty object. + constexpr any() noexcept : _M_manager(nullptr) { } + + /// Copy constructor, copies the state of @p __other + any(const any& __other) + { + if (!__other.has_value()) + _M_manager = nullptr; + else + { + _Arg __arg; + __arg._M_any = this; + __other._M_manager(_Op_clone, &__other, &__arg); + } + } + + /** + * @brief Move constructor, transfer the state from @p __other + * + * @post @c !__other.has_value() (this postcondition is a GNU extension) + */ + any(any&& __other) noexcept + { + if (!__other.has_value()) + _M_manager = nullptr; + else + { + _Arg __arg; + __arg._M_any = this; + __other._M_manager(_Op_xfer, &__other, &__arg); + } + } + + /// Construct with a copy of @p __value as the contained object. + template , + typename _Mgr = _Manager<_VTp>, + enable_if_t::value + && !__is_in_place_type<_VTp>::value, bool> = true> + any(_Tp&& __value) + : _M_manager(&_Mgr::_S_manage) + { + _Mgr::_S_create(_M_storage, std::forward<_Tp>(__value)); + } + + /// Construct with an object created from @p __args as the contained object. + template , + typename _Mgr = _Manager<_VTp>, + __any_constructible_t<_VTp, _Args&&...> = false> + explicit + any(in_place_type_t<_Tp>, _Args&&... __args) + : _M_manager(&_Mgr::_S_manage) + { + _Mgr::_S_create(_M_storage, std::forward<_Args>(__args)...); + } + + /// Construct with an object created from @p __il and @p __args as + /// the contained object. + template , typename _Mgr = _Manager<_VTp>, + __any_constructible_t<_VTp, initializer_list<_Up>, + _Args&&...> = false> + explicit + any(in_place_type_t<_Tp>, initializer_list<_Up> __il, _Args&&... __args) + : _M_manager(&_Mgr::_S_manage) + { + _Mgr::_S_create(_M_storage, __il, std::forward<_Args>(__args)...); + } + + /// Destructor, calls @c reset() + ~any() { reset(); } + + // assignments + + /// Copy the state of another object. + any& + operator=(const any& __rhs) + { + *this = any(__rhs); + return *this; + } + + /** + * @brief Move assignment operator + * + * @post @c !__rhs.has_value() (not guaranteed for other implementations) + */ + any& + operator=(any&& __rhs) noexcept + { + if (!__rhs.has_value()) + reset(); + else if (this != &__rhs) + { + reset(); + _Arg __arg; + __arg._M_any = this; + __rhs._M_manager(_Op_xfer, &__rhs, &__arg); + } + return *this; + } + + /// Store a copy of @p __rhs as the contained object. + template + enable_if_t>::value, any&> + operator=(_Tp&& __rhs) + { + *this = any(std::forward<_Tp>(__rhs)); + return *this; + } + + /// Emplace with an object created from @p __args as the contained object. + template + __emplace_t, _Args...> + emplace(_Args&&... __args) + { + using _VTp = decay_t<_Tp>; + __do_emplace<_VTp>(std::forward<_Args>(__args)...); + any::_Arg __arg; + this->_M_manager(any::_Op_access, this, &__arg); + return *static_cast<_VTp*>(__arg._M_obj); + } + + /// Emplace with an object created from @p __il and @p __args as + /// the contained object. + template + __emplace_t, initializer_list<_Up>, _Args&&...> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + using _VTp = decay_t<_Tp>; + __do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...); + any::_Arg __arg; + this->_M_manager(any::_Op_access, this, &__arg); + return *static_cast<_VTp*>(__arg._M_obj); + } + + // modifiers + + /// If not empty, destroy the contained object. + void reset() noexcept + { + if (has_value()) + { + _M_manager(_Op_destroy, this, nullptr); + _M_manager = nullptr; + } + } + + /// Exchange state with another object. + void swap(any& __rhs) noexcept + { + if (!has_value() && !__rhs.has_value()) + return; + + if (has_value() && __rhs.has_value()) + { + if (this == &__rhs) + return; + + any __tmp; + _Arg __arg; + __arg._M_any = &__tmp; + __rhs._M_manager(_Op_xfer, &__rhs, &__arg); + __arg._M_any = &__rhs; + _M_manager(_Op_xfer, this, &__arg); + __arg._M_any = this; + __tmp._M_manager(_Op_xfer, &__tmp, &__arg); + } + else + { + any* __empty = !has_value() ? this : &__rhs; + any* __full = !has_value() ? &__rhs : this; + _Arg __arg; + __arg._M_any = __empty; + __full->_M_manager(_Op_xfer, __full, &__arg); + } + } + + // observers + + /// Reports whether there is a contained object or not. + bool has_value() const noexcept { return _M_manager != nullptr; } + +#if __cpp_rtti + /// The @c typeid of the contained object, or @c typeid(void) if empty. + const type_info& type() const noexcept + { + if (!has_value()) + return typeid(void); + _Arg __arg; + _M_manager(_Op_get_type_info, this, &__arg); + return *__arg._M_typeinfo; + } +#endif + + template + static constexpr bool __is_valid_cast() + { return __or_, is_copy_constructible<_Tp>>::value; } + + private: + enum _Op { + _Op_access, _Op_get_type_info, _Op_clone, _Op_destroy, _Op_xfer + }; + + union _Arg + { + void* _M_obj; + const std::type_info* _M_typeinfo; + any* _M_any; + }; + + void (*_M_manager)(_Op, const any*, _Arg*); + _Storage _M_storage; + + template + friend void* __any_caster(const any* __any); + + // Manage in-place contained object. + template + struct _Manager_internal + { + static void + _S_manage(_Op __which, const any* __anyp, _Arg* __arg); + + template + static void + _S_create(_Storage& __storage, _Up&& __value) + { + void* __addr = &__storage._M_buffer; + ::new (__addr) _Tp(std::forward<_Up>(__value)); + } + + template + static void + _S_create(_Storage& __storage, _Args&&... __args) + { + void* __addr = &__storage._M_buffer; + ::new (__addr) _Tp(std::forward<_Args>(__args)...); + } + }; + + // Manage external contained object. + template + struct _Manager_external + { + static void + _S_manage(_Op __which, const any* __anyp, _Arg* __arg); + + template + static void + _S_create(_Storage& __storage, _Up&& __value) + { + __storage._M_ptr = new _Tp(std::forward<_Up>(__value)); + } + template + static void + _S_create(_Storage& __storage, _Args&&... __args) + { + __storage._M_ptr = new _Tp(std::forward<_Args>(__args)...); + } + }; + }; + + /// Exchange the states of two @c any objects. + inline void swap(any& __x, any& __y) noexcept { __x.swap(__y); } + + /// Create an any holding a @c _Tp constructed from @c __args. + template + any make_any(_Args&&... __args) + { + return any(in_place_type<_Tp>, std::forward<_Args>(__args)...); + } + + /// Create an any holding a @c _Tp constructed from @c __il and @c __args. + template + any make_any(initializer_list<_Up> __il, _Args&&... __args) + { + return any(in_place_type<_Tp>, __il, std::forward<_Args>(__args)...); + } + + /** + * @brief Access the contained object. + * + * @tparam _ValueType A const-reference or CopyConstructible type. + * @param __any The object to access. + * @return The contained object. + * @throw bad_any_cast If + * __any.type() != typeid(remove_reference_t<_ValueType>) + * + */ + template + inline _ValueType any_cast(const any& __any) + { + using _Up = __remove_cvref_t<_ValueType>; + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + static_assert(is_constructible_v<_ValueType, const _Up&>, + "Template argument must be constructible from a const value."); + auto __p = any_cast<_Up>(&__any); + if (__p) + return static_cast<_ValueType>(*__p); + __throw_bad_any_cast(); + } + + /** + * @brief Access the contained object. + * + * @tparam _ValueType A reference or CopyConstructible type. + * @param __any The object to access. + * @return The contained object. + * @throw bad_any_cast If + * __any.type() != typeid(remove_reference_t<_ValueType>) + * + * + * @{ + */ + template + inline _ValueType any_cast(any& __any) + { + using _Up = __remove_cvref_t<_ValueType>; + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + static_assert(is_constructible_v<_ValueType, _Up&>, + "Template argument must be constructible from an lvalue."); + auto __p = any_cast<_Up>(&__any); + if (__p) + return static_cast<_ValueType>(*__p); + __throw_bad_any_cast(); + } + + template + inline _ValueType any_cast(any&& __any) + { + using _Up = __remove_cvref_t<_ValueType>; + static_assert(any::__is_valid_cast<_ValueType>(), + "Template argument must be a reference or CopyConstructible type"); + static_assert(is_constructible_v<_ValueType, _Up>, + "Template argument must be constructible from an rvalue."); + auto __p = any_cast<_Up>(&__any); + if (__p) + return static_cast<_ValueType>(std::move(*__p)); + __throw_bad_any_cast(); + } + // @} + + /// @cond undocumented + template + void* __any_caster(const any* __any) + { + // any_cast returns non-null if __any->type() == typeid(T) and + // typeid(T) ignores cv-qualifiers so remove them: + using _Up = remove_cv_t<_Tp>; + // The contained value has a decayed type, so if decay_t is not U, + // then it's not possible to have a contained value of type U: + if constexpr (!is_same_v, _Up>) + return nullptr; + // Only copy constructible types can be used for contained values: + else if constexpr (!is_copy_constructible_v<_Up>) + return nullptr; + // First try comparing function addresses, which works without RTTI + else if (__any->_M_manager == &any::_Manager<_Up>::_S_manage +#if __cpp_rtti + || __any->type() == typeid(_Tp) +#endif + ) + { + any::_Arg __arg; + __any->_M_manager(any::_Op_access, __any, &__arg); + return __arg._M_obj; + } + return nullptr; + } + /// @endcond + + /** + * @brief Access the contained object. + * + * @tparam _ValueType The type of the contained object. + * @param __any A pointer to the object to access. + * @return The address of the contained object if + * __any != nullptr && __any.type() == typeid(_ValueType) + * , otherwise a null pointer. + * + * @{ + */ + template + inline const _ValueType* any_cast(const any* __any) noexcept + { + if constexpr (is_object_v<_ValueType>) + if (__any) + return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); + return nullptr; + } + + template + inline _ValueType* any_cast(any* __any) noexcept + { + if constexpr (is_object_v<_ValueType>) + if (__any) + return static_cast<_ValueType*>(__any_caster<_ValueType>(__any)); + return nullptr; + } + // @} + + template + void + any::_Manager_internal<_Tp>:: + _S_manage(_Op __which, const any* __any, _Arg* __arg) + { + // The contained object is in _M_storage._M_buffer + auto __ptr = reinterpret_cast(&__any->_M_storage._M_buffer); + switch (__which) + { + case _Op_access: + __arg->_M_obj = const_cast<_Tp*>(__ptr); + break; + case _Op_get_type_info: +#if __cpp_rtti + __arg->_M_typeinfo = &typeid(_Tp); +#endif + break; + case _Op_clone: + ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp(*__ptr); + __arg->_M_any->_M_manager = __any->_M_manager; + break; + case _Op_destroy: + __ptr->~_Tp(); + break; + case _Op_xfer: + ::new(&__arg->_M_any->_M_storage._M_buffer) _Tp + (std::move(*const_cast<_Tp*>(__ptr))); + __ptr->~_Tp(); + __arg->_M_any->_M_manager = __any->_M_manager; + const_cast(__any)->_M_manager = nullptr; + break; + } + } + + template + void + any::_Manager_external<_Tp>:: + _S_manage(_Op __which, const any* __any, _Arg* __arg) + { + // The contained object is *_M_storage._M_ptr + auto __ptr = static_cast(__any->_M_storage._M_ptr); + switch (__which) + { + case _Op_access: + __arg->_M_obj = const_cast<_Tp*>(__ptr); + break; + case _Op_get_type_info: +#if __cpp_rtti + __arg->_M_typeinfo = &typeid(_Tp); +#endif + break; + case _Op_clone: + __arg->_M_any->_M_storage._M_ptr = new _Tp(*__ptr); + __arg->_M_any->_M_manager = __any->_M_manager; + break; + case _Op_destroy: + delete __ptr; + break; + case _Op_xfer: + __arg->_M_any->_M_storage._M_ptr = __any->_M_storage._M_ptr; + __arg->_M_any->_M_manager = __any->_M_manager; + const_cast(__any)->_M_manager = nullptr; + break; + } + } + + /// @} + + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing an + // any into a variant. + template<> + struct _Never_valueless_alt + : std::true_type + { }; + } // namespace __detail::__variant + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 +#endif // _GLIBCXX_ANY diff --git a/resources/sources/avr-libstdcpp/include/array b/resources/sources/avr-libstdcpp/include/array index c96fc5c01..3bb6f48c4 100644 --- a/resources/sources/avr-libstdcpp/include/array +++ b/resources/sources/avr-libstdcpp/include/array @@ -1,37 +1,451 @@ -// Minimal for AVR -#ifndef _AVR_ARRAY -#define _AVR_ARRAY -#include - -namespace std { - template - struct array { - T _data[N]; - - using value_type = T; - using size_type = size_t; - using reference = T&; - using const_reference = const T&; - using iterator = T*; - using const_iterator = const T*; - - constexpr reference operator[](size_type i) noexcept { return _data[i]; } - constexpr const_reference operator[](size_type i) const noexcept { return _data[i]; } - constexpr reference at(size_type i) { return _data[i]; } - constexpr const_reference at(size_type i) const { return _data[i]; } - constexpr reference front() noexcept { return _data[0]; } - constexpr const_reference front() const noexcept { return _data[0]; } - constexpr reference back() noexcept { return _data[N - 1]; } - constexpr const_reference back() const noexcept { return _data[N - 1]; } - constexpr T* data() noexcept { return _data; } - constexpr const T* data() const noexcept { return _data; } - constexpr iterator begin() noexcept { return _data; } - constexpr const_iterator begin() const noexcept { return _data; } - constexpr iterator end() noexcept { return _data + N; } - constexpr const_iterator end() const noexcept { return _data + N; } - constexpr size_type size() const noexcept { return N; } - constexpr bool empty() const noexcept { return N == 0; } - void fill(const T& value) { for (size_type i = 0; i < N; ++i) _data[i] = value; } - }; -} +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/array + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ARRAY +#define _GLIBCXX_ARRAY 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + struct __array_traits + { + typedef _Tp _Type[_Nm]; + typedef __is_swappable<_Tp> _Is_swappable; + typedef __is_nothrow_swappable<_Tp> _Is_nothrow_swappable; + + static constexpr _Tp& + _S_ref(const _Type& __t, std::size_t __n) noexcept + { return const_cast<_Tp&>(__t[__n]); } + + static constexpr _Tp* + _S_ptr(const _Type& __t) noexcept + { return const_cast<_Tp*>(__t); } + }; + + template + struct __array_traits<_Tp, 0> + { + struct _Type { }; + typedef true_type _Is_swappable; + typedef true_type _Is_nothrow_swappable; + + static constexpr _Tp& + _S_ref(const _Type&, std::size_t) noexcept + { return *static_cast<_Tp*>(nullptr); } + + static constexpr _Tp* + _S_ptr(const _Type&) noexcept + { return nullptr; } + }; + + /** + * @brief A standard container for storing a fixed size sequence of elements. + * + * @ingroup sequences + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence. + * + * Sets support random access iterators. + * + * @tparam Tp Type of element. Required to be a complete type. + * @tparam Nm Number of elements. + */ + template + struct array + { + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef value_type* iterator; + typedef const value_type* const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + + // Support for zero-sized arrays mandatory. + typedef _GLIBCXX_STD_C::__array_traits<_Tp, _Nm> _AT_Type; + typename _AT_Type::_Type _M_elems; + + // No explicit construct/copy/destroy for aggregate type. + + // DR 776. + _GLIBCXX20_CONSTEXPR void + fill(const value_type& __u) + { std::fill_n(begin(), size(), __u); } + + _GLIBCXX20_CONSTEXPR void + swap(array& __other) + noexcept(_AT_Type::_Is_nothrow_swappable::value) + { std::swap_ranges(begin(), end(), __other.begin()); } + + // Iterators. + _GLIBCXX17_CONSTEXPR iterator + begin() noexcept + { return iterator(data()); } + + _GLIBCXX17_CONSTEXPR const_iterator + begin() const noexcept + { return const_iterator(data()); } + + _GLIBCXX17_CONSTEXPR iterator + end() noexcept + { return iterator(data() + _Nm); } + + _GLIBCXX17_CONSTEXPR const_iterator + end() const noexcept + { return const_iterator(data() + _Nm); } + + _GLIBCXX17_CONSTEXPR reverse_iterator + rbegin() noexcept + { return reverse_iterator(end()); } + + _GLIBCXX17_CONSTEXPR const_reverse_iterator + rbegin() const noexcept + { return const_reverse_iterator(end()); } + + _GLIBCXX17_CONSTEXPR reverse_iterator + rend() noexcept + { return reverse_iterator(begin()); } + + _GLIBCXX17_CONSTEXPR const_reverse_iterator + rend() const noexcept + { return const_reverse_iterator(begin()); } + + _GLIBCXX17_CONSTEXPR const_iterator + cbegin() const noexcept + { return const_iterator(data()); } + + _GLIBCXX17_CONSTEXPR const_iterator + cend() const noexcept + { return const_iterator(data() + _Nm); } + + _GLIBCXX17_CONSTEXPR const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + _GLIBCXX17_CONSTEXPR const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } + + // Capacity. + constexpr size_type + size() const noexcept { return _Nm; } + + constexpr size_type + max_size() const noexcept { return _Nm; } + + _GLIBCXX_NODISCARD constexpr bool + empty() const noexcept { return size() == 0; } + + // Element access. + _GLIBCXX17_CONSTEXPR reference + operator[](size_type __n) noexcept + { return _AT_Type::_S_ref(_M_elems, __n); } + + constexpr const_reference + operator[](size_type __n) const noexcept + { return _AT_Type::_S_ref(_M_elems, __n); } + + _GLIBCXX17_CONSTEXPR reference + at(size_type __n) + { + if (__n >= _Nm) + std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " + ">= _Nm (which is %zu)"), + __n, _Nm); + return _AT_Type::_S_ref(_M_elems, __n); + } + + constexpr const_reference + at(size_type __n) const + { + // Result of conditional expression must be an lvalue so use + // boolean ? lvalue : (throw-expr, lvalue) + return __n < _Nm ? _AT_Type::_S_ref(_M_elems, __n) + : (std::__throw_out_of_range_fmt(__N("array::at: __n (which is %zu) " + ">= _Nm (which is %zu)"), + __n, _Nm), + _AT_Type::_S_ref(_M_elems, 0)); + } + + _GLIBCXX17_CONSTEXPR reference + front() noexcept + { return *begin(); } + + constexpr const_reference + front() const noexcept + { return _AT_Type::_S_ref(_M_elems, 0); } + + _GLIBCXX17_CONSTEXPR reference + back() noexcept + { return _Nm ? *(end() - 1) : *end(); } + + constexpr const_reference + back() const noexcept + { + return _Nm ? _AT_Type::_S_ref(_M_elems, _Nm - 1) + : _AT_Type::_S_ref(_M_elems, 0); + } + + _GLIBCXX17_CONSTEXPR pointer + data() noexcept + { return _AT_Type::_S_ptr(_M_elems); } + + _GLIBCXX17_CONSTEXPR const_pointer + data() const noexcept + { return _AT_Type::_S_ptr(_M_elems); } + }; + +#if __cpp_deduction_guides >= 201606 + template + array(_Tp, _Up...) + -> array && ...), _Tp>, + 1 + sizeof...(_Up)>; +#endif + + // Array comparisons. + template + _GLIBCXX20_CONSTEXPR + inline bool + operator==(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return std::equal(__one.begin(), __one.end(), __two.begin()); } + +#if __cpp_lib_three_way_comparison && __cpp_lib_concepts + template + constexpr __detail::__synth3way_t<_Tp> + operator<=>(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) + { +#ifdef __cpp_lib_is_constant_evaluated + if constexpr (_Nm && __is_memcmp_ordered<_Tp>::__value) + if (!std::is_constant_evaluated()) + { + constexpr size_t __n = _Nm * sizeof(_Tp); + return __builtin_memcmp(__a.data(), __b.data(), __n) <=> 0; + } +#endif + + for (size_t __i = 0; __i < _Nm; ++__i) + { + auto __c = __detail::__synth3way(__a[__i], __b[__i]); + if (__c != 0) + return __c; + } + return strong_ordering::equal; + } +#else + template + _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one == __two); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator<(const array<_Tp, _Nm>& __a, const array<_Tp, _Nm>& __b) + { + return std::lexicographical_compare(__a.begin(), __a.end(), + __b.begin(), __b.end()); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator>(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return __two < __one; } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator<=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one > __two); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator>=(const array<_Tp, _Nm>& __one, const array<_Tp, _Nm>& __two) + { return !(__one < __two); } +#endif // three_way_comparison && concepts + + // Specialized algorithms. + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if< + _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value + >::type +#else + void +#endif + swap(array<_Tp, _Nm>& __one, array<_Tp, _Nm>& __two) + noexcept(noexcept(__one.swap(__two))) + { __one.swap(__two); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + typename enable_if< + !_GLIBCXX_STD_C::__array_traits<_Tp, _Nm>::_Is_swappable::value>::type + swap(array<_Tp, _Nm>&, array<_Tp, _Nm>&) = delete; +#endif + + template + constexpr _Tp& + get(array<_Tp, _Nm>& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: + _S_ref(__arr._M_elems, _Int); + } + + template + constexpr _Tp&& + get(array<_Tp, _Nm>&& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); + } + + template + constexpr const _Tp& + get(const array<_Tp, _Nm>& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return _GLIBCXX_STD_C::__array_traits<_Tp, _Nm>:: + _S_ref(__arr._M_elems, _Int); + } + + template + constexpr const _Tp&& + get(const array<_Tp, _Nm>&& __arr) noexcept + { + static_assert(_Int < _Nm, "array index is within bounds"); + return std::move(_GLIBCXX_STD_C::get<_Int>(__arr)); + } + +#if __cplusplus > 201703L +#define __cpp_lib_to_array 201907L + + template + constexpr array, sizeof...(_Idx)> + __to_array(_Tp (&__a)[sizeof...(_Idx)], index_sequence<_Idx...>) + { + if constexpr (_Move) + return {{std::move(__a[_Idx])...}}; + else + return {{__a[_Idx]...}}; + } + + template + constexpr array, _Nm> + to_array(_Tp (&__a)[_Nm]) + noexcept(is_nothrow_constructible_v<_Tp, _Tp&>) + { + static_assert(!is_array_v<_Tp>); + static_assert(is_constructible_v<_Tp, _Tp&>); + if constexpr (is_constructible_v<_Tp, _Tp&>) + return _GLIBCXX_STD_C::__to_array(__a, make_index_sequence<_Nm>{}); + __builtin_unreachable(); // FIXME: see PR c++/91388 + } + + template + constexpr array, _Nm> + to_array(_Tp (&&__a)[_Nm]) + noexcept(is_nothrow_move_constructible_v<_Tp>) + { + static_assert(!is_array_v<_Tp>); + static_assert(is_move_constructible_v<_Tp>); + if constexpr (is_move_constructible_v<_Tp>) + return _GLIBCXX_STD_C::__to_array<1>(__a, make_index_sequence<_Nm>{}); + __builtin_unreachable(); // FIXME: see PR c++/91388 + } +#endif // C++20 + +_GLIBCXX_END_NAMESPACE_CONTAINER +} // namespace std + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Tuple interface to class template array. + + /// tuple_size + template + struct tuple_size; + + /// Partial specialization for std::array + template + struct tuple_size<_GLIBCXX_STD_C::array<_Tp, _Nm>> + : public integral_constant { }; + + /// tuple_element + template + struct tuple_element; + + /// Partial specialization for std::array + template + struct tuple_element<_Int, _GLIBCXX_STD_C::array<_Tp, _Nm>> + { + static_assert(_Int < _Nm, "index is out of bounds"); + typedef _Tp type; + }; + + template + struct __is_tuple_like_impl<_GLIBCXX_STD_C::array<_Tp, _Nm>> : true_type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#ifdef _GLIBCXX_DEBUG +# include #endif + +#endif // C++11 + +#endif // _GLIBCXX_ARRAY diff --git a/resources/sources/avr-libstdcpp/include/atomic b/resources/sources/avr-libstdcpp/include/atomic new file mode 100644 index 000000000..a455286a7 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/atomic @@ -0,0 +1,1552 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/atomic + * This is a Standard C++ Library header. + */ + +// Based on "C++ Atomic Types and Operations" by Hans Boehm and Lawrence Crowl. +// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2007/n2427.html + +#ifndef _GLIBCXX_ATOMIC +#define _GLIBCXX_ATOMIC 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup atomics + * @{ + */ + +#if __cplusplus >= 201703L +# define __cpp_lib_atomic_is_always_lock_free 201603 +#endif + + template + struct atomic; + + /// atomic + // NB: No operators or fetch-operations for this type. + template<> + struct atomic + { + using value_type = bool; + + private: + __atomic_base _M_base; + + public: + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(bool __i) noexcept : _M_base(__i) { } + + bool + operator=(bool __i) noexcept + { return _M_base.operator=(__i); } + + bool + operator=(bool __i) volatile noexcept + { return _M_base.operator=(__i); } + + operator bool() const noexcept + { return _M_base.load(); } + + operator bool() const volatile noexcept + { return _M_base.load(); } + + bool + is_lock_free() const noexcept { return _M_base.is_lock_free(); } + + bool + is_lock_free() const volatile noexcept { return _M_base.is_lock_free(); } + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_BOOL_LOCK_FREE == 2; +#endif + + void + store(bool __i, memory_order __m = memory_order_seq_cst) noexcept + { _M_base.store(__i, __m); } + + void + store(bool __i, memory_order __m = memory_order_seq_cst) volatile noexcept + { _M_base.store(__i, __m); } + + bool + load(memory_order __m = memory_order_seq_cst) const noexcept + { return _M_base.load(__m); } + + bool + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return _M_base.load(__m); } + + bool + exchange(bool __i, memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.exchange(__i, __m); } + + bool + exchange(bool __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.exchange(__i, __m); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m); } + + bool + compare_exchange_weak(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.compare_exchange_weak(__i1, __i2, __m); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m1, __m2); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m); } + + bool + compare_exchange_strong(bool& __i1, bool __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_base.compare_exchange_strong(__i1, __i2, __m); } + }; + +#if __cplusplus <= 201703L +# define _GLIBCXX20_INIT(I) +#else +# define _GLIBCXX20_INIT(I) = I +#endif + + /** + * @brief Generic atomic type, primary class template. + * + * @tparam _Tp Type to be made atomic, must be trivially copyable. + */ + template + struct atomic + { + using value_type = _Tp; + + private: + // Align 1/2/4/8/16-byte types to at least their size. + static constexpr int _S_min_alignment + = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 + ? 0 : sizeof(_Tp); + + static constexpr int _S_alignment + = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); + + alignas(_S_alignment) _Tp _M_i _GLIBCXX20_INIT(_Tp()); + + static_assert(__is_trivially_copyable(_Tp), + "std::atomic requires a trivially copyable type"); + + static_assert(sizeof(_Tp) > 0, + "Incomplete or zero-sized types are not supported"); + + public: + atomic() = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(_Tp __i) noexcept : _M_i(__i) { } + + operator _Tp() const noexcept + { return load(); } + + operator _Tp() const volatile noexcept + { return load(); } + + _Tp + operator=(_Tp __i) noexcept + { store(__i); return __i; } + + _Tp + operator=(_Tp __i) volatile noexcept + { store(__i); return __i; } + + bool + is_lock_free() const noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + bool + is_lock_free() const volatile noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_M_i), 0); +#endif + + void + store(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept + { __atomic_store(std::__addressof(_M_i), std::__addressof(__i), int(__m)); } + + void + store(_Tp __i, memory_order __m = memory_order_seq_cst) volatile noexcept + { __atomic_store(std::__addressof(_M_i), std::__addressof(__i), int(__m)); } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); + return *__ptr; + } + + _Tp + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_load(std::__addressof(_M_i), __ptr, int(__m)); + return *__ptr; + } + + _Tp + exchange(_Tp __i, memory_order __m = memory_order_seq_cst) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_exchange(std::__addressof(_M_i), std::__addressof(__i), + __ptr, int(__m)); + return *__ptr; + } + + _Tp + exchange(_Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + _Tp* __ptr = reinterpret_cast<_Tp*>(__buf); + __atomic_exchange(std::__addressof(_M_i), std::__addressof(__i), + __ptr, int(__m)); + return *__ptr; + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) noexcept + { + return __atomic_compare_exchange(std::__addressof(_M_i), + std::__addressof(__e), + std::__addressof(__i), + true, int(__s), int(__f)); + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) volatile noexcept + { + return __atomic_compare_exchange(std::__addressof(_M_i), + std::__addressof(__e), + std::__addressof(__i), + true, int(__s), int(__f)); + } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) noexcept + { return compare_exchange_weak(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_weak(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return compare_exchange_weak(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) noexcept + { + return __atomic_compare_exchange(std::__addressof(_M_i), + std::__addressof(__e), + std::__addressof(__i), + false, int(__s), int(__f)); + } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, memory_order __s, + memory_order __f) volatile noexcept + { + return __atomic_compare_exchange(std::__addressof(_M_i), + std::__addressof(__e), + std::__addressof(__i), + false, int(__s), int(__f)); + } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) noexcept + { return compare_exchange_strong(__e, __i, __m, + __cmpexch_failure_order(__m)); } + + bool + compare_exchange_strong(_Tp& __e, _Tp __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return compare_exchange_strong(__e, __i, __m, + __cmpexch_failure_order(__m)); } + }; +#undef _GLIBCXX20_INIT + + /// Partial specialization for pointer types. + template + struct atomic<_Tp*> + { + using value_type = _Tp*; + using difference_type = ptrdiff_t; + + typedef _Tp* __pointer_type; + typedef __atomic_base<_Tp*> __base_type; + __base_type _M_b; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__pointer_type __p) noexcept : _M_b(__p) { } + + operator __pointer_type() const noexcept + { return __pointer_type(_M_b); } + + operator __pointer_type() const volatile noexcept + { return __pointer_type(_M_b); } + + __pointer_type + operator=(__pointer_type __p) noexcept + { return _M_b.operator=(__p); } + + __pointer_type + operator=(__pointer_type __p) volatile noexcept + { return _M_b.operator=(__p); } + + __pointer_type + operator++(int) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b++; + } + + __pointer_type + operator++(int) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b++; + } + + __pointer_type + operator--(int) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b--; + } + + __pointer_type + operator--(int) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b--; + } + + __pointer_type + operator++() noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return ++_M_b; + } + + __pointer_type + operator++() volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return ++_M_b; + } + + __pointer_type + operator--() noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return --_M_b; + } + + __pointer_type + operator--() volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return --_M_b; + } + + __pointer_type + operator+=(ptrdiff_t __d) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator+=(__d); + } + + __pointer_type + operator+=(ptrdiff_t __d) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator+=(__d); + } + + __pointer_type + operator-=(ptrdiff_t __d) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator-=(__d); + } + + __pointer_type + operator-=(ptrdiff_t __d) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.operator-=(__d); + } + + bool + is_lock_free() const noexcept + { return _M_b.is_lock_free(); } + + bool + is_lock_free() const volatile noexcept + { return _M_b.is_lock_free(); } + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; +#endif + + void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_b.store(__p, __m); } + + void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_b.store(__p, __m); } + + __pointer_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { return _M_b.load(__m); } + + __pointer_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return _M_b.load(__m); } + + __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { return _M_b.exchange(__p, __m); } + + __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return _M_b.exchange(__p, __m); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, memory_order __m2) noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_weak(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_weak(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_weak(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, memory_order __m2) noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { return _M_b.compare_exchange_strong(__p1, __p2, __m1, __m2); } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) noexcept + { + return _M_b.compare_exchange_strong(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return _M_b.compare_exchange_strong(__p1, __p2, __m, + __cmpexch_failure_order(__m)); + } + + __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_add(__d, __m); + } + + __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_add(__d, __m); + } + + __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_sub(__d, __m); + } + + __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { +#if __cplusplus >= 201703L + static_assert( is_object<_Tp>::value, "pointer to object type" ); +#endif + return _M_b.fetch_sub(__d, __m); + } + }; + + + /// Explicit specialization for char. + template<> + struct atomic : __atomic_base + { + typedef char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for signed char. + template<> + struct atomic : __atomic_base + { + typedef signed char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept= default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned char. + template<> + struct atomic : __atomic_base + { + typedef unsigned char __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept= default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for short. + template<> + struct atomic : __atomic_base + { + typedef short __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned short. + template<> + struct atomic : __atomic_base + { + typedef unsigned short __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_SHORT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for int. + template<> + struct atomic : __atomic_base + { + typedef int __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned int. + template<> + struct atomic : __atomic_base + { + typedef unsigned int __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_INT_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for long. + template<> + struct atomic : __atomic_base + { + typedef long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned long. + template<> + struct atomic : __atomic_base + { + typedef unsigned long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_LONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for long long. + template<> + struct atomic : __atomic_base + { + typedef long long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for unsigned long long. + template<> + struct atomic : __atomic_base + { + typedef unsigned long long __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_LLONG_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for wchar_t. + template<> + struct atomic : __atomic_base + { + typedef wchar_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_WCHAR_T_LOCK_FREE == 2; +#endif + }; + +#ifdef _GLIBCXX_USE_CHAR8_T + /// Explicit specialization for char8_t. + template<> + struct atomic : __atomic_base + { + typedef char8_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus > 201402L + static constexpr bool is_always_lock_free = ATOMIC_CHAR8_T_LOCK_FREE == 2; +#endif + }; +#endif + + /// Explicit specialization for char16_t. + template<> + struct atomic : __atomic_base + { + typedef char16_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR16_T_LOCK_FREE == 2; +#endif + }; + + /// Explicit specialization for char32_t. + template<> + struct atomic : __atomic_base + { + typedef char32_t __integral_type; + typedef __atomic_base __base_type; + + atomic() noexcept = default; + ~atomic() noexcept = default; + atomic(const atomic&) = delete; + atomic& operator=(const atomic&) = delete; + atomic& operator=(const atomic&) volatile = delete; + + constexpr atomic(__integral_type __i) noexcept : __base_type(__i) { } + + using __base_type::operator __integral_type; + using __base_type::operator=; + +#if __cplusplus >= 201703L + static constexpr bool is_always_lock_free = ATOMIC_CHAR32_T_LOCK_FREE == 2; +#endif + }; + + + /// atomic_bool + typedef atomic atomic_bool; + + /// atomic_char + typedef atomic atomic_char; + + /// atomic_schar + typedef atomic atomic_schar; + + /// atomic_uchar + typedef atomic atomic_uchar; + + /// atomic_short + typedef atomic atomic_short; + + /// atomic_ushort + typedef atomic atomic_ushort; + + /// atomic_int + typedef atomic atomic_int; + + /// atomic_uint + typedef atomic atomic_uint; + + /// atomic_long + typedef atomic atomic_long; + + /// atomic_ulong + typedef atomic atomic_ulong; + + /// atomic_llong + typedef atomic atomic_llong; + + /// atomic_ullong + typedef atomic atomic_ullong; + + /// atomic_wchar_t + typedef atomic atomic_wchar_t; + +#ifdef _GLIBCXX_USE_CHAR8_T + /// atomic_char8_t + typedef atomic atomic_char8_t; +#endif + + /// atomic_char16_t + typedef atomic atomic_char16_t; + + /// atomic_char32_t + typedef atomic atomic_char32_t; + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2441. Exact-width atomic typedefs should be provided + + /// atomic_int8_t + typedef atomic atomic_int8_t; + + /// atomic_uint8_t + typedef atomic atomic_uint8_t; + + /// atomic_int16_t + typedef atomic atomic_int16_t; + + /// atomic_uint16_t + typedef atomic atomic_uint16_t; + + /// atomic_int32_t + typedef atomic atomic_int32_t; + + /// atomic_uint32_t + typedef atomic atomic_uint32_t; + + /// atomic_int64_t + typedef atomic atomic_int64_t; + + /// atomic_uint64_t + typedef atomic atomic_uint64_t; + + + /// atomic_int_least8_t + typedef atomic atomic_int_least8_t; + + /// atomic_uint_least8_t + typedef atomic atomic_uint_least8_t; + + /// atomic_int_least16_t + typedef atomic atomic_int_least16_t; + + /// atomic_uint_least16_t + typedef atomic atomic_uint_least16_t; + + /// atomic_int_least32_t + typedef atomic atomic_int_least32_t; + + /// atomic_uint_least32_t + typedef atomic atomic_uint_least32_t; + + /// atomic_int_least64_t + typedef atomic atomic_int_least64_t; + + /// atomic_uint_least64_t + typedef atomic atomic_uint_least64_t; + + + /// atomic_int_fast8_t + typedef atomic atomic_int_fast8_t; + + /// atomic_uint_fast8_t + typedef atomic atomic_uint_fast8_t; + + /// atomic_int_fast16_t + typedef atomic atomic_int_fast16_t; + + /// atomic_uint_fast16_t + typedef atomic atomic_uint_fast16_t; + + /// atomic_int_fast32_t + typedef atomic atomic_int_fast32_t; + + /// atomic_uint_fast32_t + typedef atomic atomic_uint_fast32_t; + + /// atomic_int_fast64_t + typedef atomic atomic_int_fast64_t; + + /// atomic_uint_fast64_t + typedef atomic atomic_uint_fast64_t; +#endif + + + /// atomic_intptr_t + typedef atomic atomic_intptr_t; + + /// atomic_uintptr_t + typedef atomic atomic_uintptr_t; + + /// atomic_size_t + typedef atomic atomic_size_t; + + /// atomic_ptrdiff_t + typedef atomic atomic_ptrdiff_t; + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + /// atomic_intmax_t + typedef atomic atomic_intmax_t; + + /// atomic_uintmax_t + typedef atomic atomic_uintmax_t; +#endif + + // Function definitions, atomic_flag operations. + inline bool + atomic_flag_test_and_set_explicit(atomic_flag* __a, + memory_order __m) noexcept + { return __a->test_and_set(__m); } + + inline bool + atomic_flag_test_and_set_explicit(volatile atomic_flag* __a, + memory_order __m) noexcept + { return __a->test_and_set(__m); } + + inline void + atomic_flag_clear_explicit(atomic_flag* __a, memory_order __m) noexcept + { __a->clear(__m); } + + inline void + atomic_flag_clear_explicit(volatile atomic_flag* __a, + memory_order __m) noexcept + { __a->clear(__m); } + + inline bool + atomic_flag_test_and_set(atomic_flag* __a) noexcept + { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } + + inline bool + atomic_flag_test_and_set(volatile atomic_flag* __a) noexcept + { return atomic_flag_test_and_set_explicit(__a, memory_order_seq_cst); } + + inline void + atomic_flag_clear(atomic_flag* __a) noexcept + { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } + + inline void + atomic_flag_clear(volatile atomic_flag* __a) noexcept + { atomic_flag_clear_explicit(__a, memory_order_seq_cst); } + + + template + using __atomic_val_t = typename atomic<_Tp>::value_type; + template + using __atomic_diff_t = typename atomic<_Tp>::difference_type; + + // [atomics.nonmembers] Non-member functions. + // Function templates generally applicable to atomic types. + template + inline bool + atomic_is_lock_free(const atomic<_ITp>* __a) noexcept + { return __a->is_lock_free(); } + + template + inline bool + atomic_is_lock_free(const volatile atomic<_ITp>* __a) noexcept + { return __a->is_lock_free(); } + + template + inline void + atomic_init(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { __a->store(__i, memory_order_relaxed); } + + template + inline void + atomic_init(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { __a->store(__i, memory_order_relaxed); } + + template + inline void + atomic_store_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { __a->store(__i, __m); } + + template + inline void + atomic_store_explicit(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { __a->store(__i, __m); } + + template + inline _ITp + atomic_load_explicit(const atomic<_ITp>* __a, memory_order __m) noexcept + { return __a->load(__m); } + + template + inline _ITp + atomic_load_explicit(const volatile atomic<_ITp>* __a, + memory_order __m) noexcept + { return __a->load(__m); } + + template + inline _ITp + atomic_exchange_explicit(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->exchange(__i, __m); } + + template + inline _ITp + atomic_exchange_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->exchange(__i, __m); } + + template + inline bool + atomic_compare_exchange_weak_explicit(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_weak_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_weak(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_strong_explicit(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } + + template + inline bool + atomic_compare_exchange_strong_explicit(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2, + memory_order __m1, + memory_order __m2) noexcept + { return __a->compare_exchange_strong(*__i1, __i2, __m1, __m2); } + + + template + inline void + atomic_store(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { atomic_store_explicit(__a, __i, memory_order_seq_cst); } + + template + inline void + atomic_store(volatile atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { atomic_store_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_load(const atomic<_ITp>* __a) noexcept + { return atomic_load_explicit(__a, memory_order_seq_cst); } + + template + inline _ITp + atomic_load(const volatile atomic<_ITp>* __a) noexcept + { return atomic_load_explicit(__a, memory_order_seq_cst); } + + template + inline _ITp + atomic_exchange(atomic<_ITp>* __a, __atomic_val_t<_ITp> __i) noexcept + { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_exchange(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_exchange_explicit(__a, __i, memory_order_seq_cst); } + + template + inline bool + atomic_compare_exchange_weak(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_weak(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_weak_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_strong(atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + template + inline bool + atomic_compare_exchange_strong(volatile atomic<_ITp>* __a, + __atomic_val_t<_ITp>* __i1, + __atomic_val_t<_ITp> __i2) noexcept + { + return atomic_compare_exchange_strong_explicit(__a, __i1, __i2, + memory_order_seq_cst, + memory_order_seq_cst); + } + + // Function templates for atomic_integral and atomic_pointer operations only. + // Some operations (and, or, xor) are only available for atomic integrals, + // which is implemented by taking a parameter of type __atomic_base<_ITp>*. + + template + inline _ITp + atomic_fetch_add_explicit(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_add(__i, __m); } + + template + inline _ITp + atomic_fetch_add_explicit(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_add(__i, __m); } + + template + inline _ITp + atomic_fetch_sub_explicit(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_sub(__i, __m); } + + template + inline _ITp + atomic_fetch_sub_explicit(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_sub(__i, __m); } + + template + inline _ITp + atomic_fetch_and_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_and(__i, __m); } + + template + inline _ITp + atomic_fetch_and_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_and(__i, __m); } + + template + inline _ITp + atomic_fetch_or_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_or(__i, __m); } + + template + inline _ITp + atomic_fetch_or_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_or(__i, __m); } + + template + inline _ITp + atomic_fetch_xor_explicit(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_xor(__i, __m); } + + template + inline _ITp + atomic_fetch_xor_explicit(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i, + memory_order __m) noexcept + { return __a->fetch_xor(__i, __m); } + + template + inline _ITp + atomic_fetch_add(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_add(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_add_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_sub(atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_sub(volatile atomic<_ITp>* __a, + __atomic_diff_t<_ITp> __i) noexcept + { return atomic_fetch_sub_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_and(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_and(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_and_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_or(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_or(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_or_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_xor(__atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } + + template + inline _ITp + atomic_fetch_xor(volatile __atomic_base<_ITp>* __a, + __atomic_val_t<_ITp> __i) noexcept + { return atomic_fetch_xor_explicit(__a, __i, memory_order_seq_cst); } + +#if __cplusplus > 201703L +#define __cpp_lib_atomic_float 201711L + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(float __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; + + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(double __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; + + template<> + struct atomic : __atomic_float + { + atomic() noexcept = default; + + constexpr + atomic(long double __fp) noexcept : __atomic_float(__fp) + { } + + atomic& operator=(const atomic&) volatile = delete; + atomic& operator=(const atomic&) = delete; + + using __atomic_float::operator=; + }; + +#define __cpp_lib_atomic_ref 201806L + + /// Class template to provide atomic operations on a non-atomic variable. + template + struct atomic_ref : __atomic_ref<_Tp> + { + explicit + atomic_ref(_Tp& __t) noexcept : __atomic_ref<_Tp>(__t) + { } + + atomic_ref& operator=(const atomic_ref&) = delete; + + atomic_ref(const atomic_ref&) = default; + + using __atomic_ref<_Tp>::operator=; + }; + +#endif // C++2a + + // @} group atomics + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _GLIBCXX_ATOMIC diff --git a/resources/sources/avr-libstdcpp/include/backward/backward_warning.h b/resources/sources/avr-libstdcpp/include/backward/backward_warning.h new file mode 100644 index 000000000..94347de40 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/backward_warning.h @@ -0,0 +1,56 @@ +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file backward/backward_warning.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _BACKWARD_BACKWARD_WARNING_H +#define _BACKWARD_BACKWARD_WARNING_H 1 + +#ifdef __DEPRECATED +#warning \ + This file includes at least one deprecated or antiquated header which \ + may be removed without further notice at a future date. Please use a \ + non-deprecated interface with equivalent functionality instead. For a \ + listing of replacement headers and interfaces, consult the file \ + backward_warning.h. To disable this warning use -Wno-deprecated. + +/* + A list of valid replacements is as follows: + + Use: Instead of: + , unordered_set , hash_set + , unordered_multiset , hash_multiset + , unordered_map , hash_map + , unordered_multimap , hash_multimap + , bind , binder1st + , bind , binder2nd + , bind , bind1st + , bind , bind2nd + , unique_ptr , auto_ptr +*/ + +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/binders.h b/resources/sources/avr-libstdcpp/include/backward/binders.h new file mode 100644 index 000000000..8c2c00d78 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/binders.h @@ -0,0 +1,182 @@ +// Functor implementations -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file backward/binders.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _BACKWARD_BINDERS_H +#define _BACKWARD_BINDERS_H 1 + +// Suppress deprecated warning for this file. +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // 20.3.6 binders + /** @defgroup binders Binder Classes + * @ingroup functors + * + * Binders turn functions/functors with two arguments into functors + * with a single argument, storing an argument to be applied later. + * For example, a variable @c B of type @c binder1st is constructed + * from a functor @c f and an argument @c x. Later, B's @c + * operator() is called with a single argument @c y. The return + * value is the value of @c f(x,y). @c B can be @a called with + * various arguments (y1, y2, ...) and will in turn call @c + * f(x,y1), @c f(x,y2), ... + * + * The function @c bind1st is provided to save some typing. It takes the + * function and an argument as parameters, and returns an instance of + * @c binder1st. + * + * The type @c binder2nd and its creator function @c bind2nd do the same + * thing, but the stored argument is passed as the second parameter instead + * of the first, e.g., @c bind2nd(std::minus(),1.3) will create a + * functor whose @c operator() accepts a floating-point number, subtracts + * 1.3 from it, and returns the result. (If @c bind1st had been used, + * the functor would perform 1.3 - x instead. + * + * Creator-wrapper functions like @c bind1st are intended to be used in + * calling algorithms. Their return values will be temporary objects. + * (The goal is to not require you to type names like + * @c std::binder1st> for declaring a variable to hold the + * return value from @c bind1st(std::plus(),5). + * + * These become more useful when combined with the composition functions. + * + * These functions are deprecated in C++11 and can be replaced by + * @c std::bind (or @c std::tr1::bind) which is more powerful and flexible, + * supporting functions with any number of arguments. Uses of @c bind1st + * can be replaced by @c std::bind(f, x, std::placeholders::_1) and + * @c bind2nd by @c std::bind(f, std::placeholders::_1, x). + * @{ + */ + /// One of the @link binders binder functors@endlink. + template + class binder1st + : public unary_function + { + protected: + _Operation op; + typename _Operation::first_argument_type value; + + public: + binder1st(const _Operation& __x, + const typename _Operation::first_argument_type& __y) + : op(__x), value(__y) { } + + typename _Operation::result_type + operator()(const typename _Operation::second_argument_type& __x) const + { return op(value, __x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 109. Missing binders for non-const sequence elements + typename _Operation::result_type + operator()(typename _Operation::second_argument_type& __x) const + { return op(value, __x); } + } _GLIBCXX_DEPRECATED; + + /// One of the @link binders binder functors@endlink. + template + inline binder1st<_Operation> + bind1st(const _Operation& __fn, const _Tp& __x) + { + typedef typename _Operation::first_argument_type _Arg1_type; + return binder1st<_Operation>(__fn, _Arg1_type(__x)); + } + + /// One of the @link binders binder functors@endlink. + template + class binder2nd + : public unary_function + { + protected: + _Operation op; + typename _Operation::second_argument_type value; + + public: + binder2nd(const _Operation& __x, + const typename _Operation::second_argument_type& __y) + : op(__x), value(__y) { } + + typename _Operation::result_type + operator()(const typename _Operation::first_argument_type& __x) const + { return op(__x, value); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 109. Missing binders for non-const sequence elements + typename _Operation::result_type + operator()(typename _Operation::first_argument_type& __x) const + { return op(__x, value); } + } _GLIBCXX_DEPRECATED; + + /// One of the @link binders binder functors@endlink. + template + inline binder2nd<_Operation> + bind2nd(const _Operation& __fn, const _Tp& __x) + { + typedef typename _Operation::second_argument_type _Arg2_type; + return binder2nd<_Operation>(__fn, _Arg2_type(__x)); + } + /** @} */ + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#pragma GCC diagnostic pop + +#endif /* _BACKWARD_BINDERS_H */ diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_fun.h b/resources/sources/avr-libstdcpp/include/backward/hash_fun.h new file mode 100644 index 000000000..5d19f979a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/hash_fun.h @@ -0,0 +1,170 @@ +// 'struct hash' from SGI -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_fun.h + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_FUN_H +#define _BACKWARD_HASH_FUN_H 1 + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::size_t; + + template + struct hash { }; + + inline size_t + __stl_hash_string(const char* __s) + { + unsigned long __h = 0; + for ( ; *__s; ++__s) + __h = 5 * __h + *__s; + return size_t(__h); + } + + template<> + struct hash + { + size_t + operator()(const char* __s) const + { return __stl_hash_string(__s); } + }; + + template<> + struct hash + { + size_t + operator()(const char* __s) const + { return __stl_hash_string(__s); } + }; + + template<> + struct hash + { + size_t + operator()(char __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned char __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned char __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(short __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned short __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(int __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned int __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(long __x) const + { return __x; } + }; + + template<> + struct hash + { + size_t + operator()(unsigned long __x) const + { return __x; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_map b/resources/sources/avr-libstdcpp/include/backward/hash_map new file mode 100644 index 000000000..93db70d56 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/hash_map @@ -0,0 +1,599 @@ +// Hashing map implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_map + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_MAP +#define _BACKWARD_HASH_MAP 1 + +#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH +#include +#endif + +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::equal_to; + using std::allocator; + using std::pair; + using std::_Select1st; + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> > + class hash_map + { + private: + typedef hashtable,_Key, _HashFn, + _Select1st >, + _EqualKey, _Alloc> _Ht; + + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_map() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_map(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_map(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_map(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_map& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&, + const hash_map<_K1, _T1, _HF, _EqK, _Al>&); + + iterator + begin() + { return _M_ht.begin(); } + + iterator + end() + { return _M_ht.end(); } + + const_iterator + begin() const + { return _M_ht.begin(); } + + const_iterator + end() const + { return _M_ht.end(); } + + pair + insert(const value_type& __obj) + { return _M_ht.insert_unique(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f, __l); } + + pair + insert_noresize(const value_type& __obj) + { return _M_ht.insert_unique_noresize(__obj); } + + iterator + find(const key_type& __key) + { return _M_ht.find(__key); } + + const_iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + _Tp& + operator[](const key_type& __key) + { return _M_ht.find_or_insert(value_type(__key, _Tp())).second; } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + {return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { return __hm1._M_ht == __hm2._M_ht; } + + template + inline bool + operator!=(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { return !(__hm1 == __hm2); } + + template + inline void + swap(hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { __hm1.swap(__hm2); } + + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Key>, + class _Alloc = allocator<_Tp> > + class hash_multimap + { + // concept requirements + __glibcxx_class_requires(_Key, _SGIAssignableConcept) + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFn, size_t, _Key, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Key, _Key, _BinaryPredicateConcept) + + private: + typedef hashtable, _Key, _HashFn, + _Select1st >, _EqualKey, _Alloc> + _Ht; + + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_multimap() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_multimap(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_multimap(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_multimap(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_multimap& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator==(const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&, + const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&); + + iterator + begin() + { return _M_ht.begin(); } + + iterator + end() + { return _M_ht.end(); } + + const_iterator + begin() const + { return _M_ht.begin(); } + + const_iterator + end() const + { return _M_ht.end(); } + + iterator + insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } + + iterator + insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator + find(const key_type& __key) + { return _M_ht.find(__key); } + + const_iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + { return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, + const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) + { return __hm1._M_ht == __hm2._M_ht; } + + template + inline bool + operator!=(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, + const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) + { return !(__hm1 == __hm2); } + + template + inline void + swap(hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { __hm1.swap(__hm2); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that it will work for hash_map + // and hash_multimap. + template + class insert_iterator<__gnu_cxx::hash_map<_Key, _Tp, _HashFn, + _EqKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc> + _Container; + _Container* container; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + + template + class insert_iterator<__gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, + _EqKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc> + _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hash_set b/resources/sources/avr-libstdcpp/include/backward/hash_set new file mode 100644 index 000000000..0b99302af --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/hash_set @@ -0,0 +1,569 @@ +// Hashing set implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_set + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_SET +#define _BACKWARD_HASH_SET 1 + +#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH +#include +#endif + +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::equal_to; + using std::allocator; + using std::pair; + using std::_Identity; + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Value>, + class _Alloc = allocator<_Value> > + class hash_set + { + // concept requirements + __glibcxx_class_requires(_Value, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) + + typedef __alloc_traits<_Alloc> _Alloc_traits; + + private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_set() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_set(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_set(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_set(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_set& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator==(const hash_set<_Val, _HF, _EqK, _Al>&, + const hash_set<_Val, _HF, _EqK, _Al>&); + + iterator + begin() const + { return _M_ht.begin(); } + + iterator + end() const + { return _M_ht.end(); } + + pair + insert(const value_type& __obj) + { + pair __p = _M_ht.insert_unique(__obj); + return pair(__p.first, __p.second); + } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f, __l); } + + pair + insert_noresize(const value_type& __obj) + { + pair __p + = _M_ht.insert_unique_noresize(__obj); + return pair(__p.first, __p.second); + } + + iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + {return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return __hs1._M_ht == __hs2._M_ht; } + + template + inline bool + operator!=(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return !(__hs1 == __hs2); } + + template + inline void + swap(hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { __hs1.swap(__hs2); } + + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Value>, + class _Alloc = allocator<_Value> > + class hash_multiset + { + // concept requirements + __glibcxx_class_requires(_Value, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) + + private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_multiset() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_multiset(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_multiset(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_multiset(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_multiset& hs) + { _M_ht.swap(hs._M_ht); } + + template + friend bool + operator==(const hash_multiset<_Val, _HF, _EqK, _Al>&, + const hash_multiset<_Val, _HF, _EqK, _Al>&); + + iterator + begin() const + { return _M_ht.begin(); } + + iterator + end() const + { return _M_ht.end(); } + + iterator + insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } + + iterator + insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + { return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return __hs1._M_ht == __hs2._M_ht; } + + template + inline bool + operator!=(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return !(__hs1 == __hs2); } + + template + inline void + swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { __hs1.swap(__hs2); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that it will work for hash_set + // and hash_multiset. + template + class insert_iterator<__gnu_cxx::hash_set<_Value, _HashFcn, + _EqualKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc> + _Container; + _Container* container; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + + template + class insert_iterator<__gnu_cxx::hash_multiset<_Value, _HashFcn, + _EqualKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_multiset<_Value, _HashFcn, _EqualKey, _Alloc> + _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/backward/hashtable.h b/resources/sources/avr-libstdcpp/include/backward/hashtable.h new file mode 100644 index 000000000..1779fa44d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/backward/hashtable.h @@ -0,0 +1,1166 @@ +// Hashtable implementation used by containers -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hashtable.h + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASHTABLE_H +#define _BACKWARD_HASHTABLE_H 1 + +// Hashtable class, used to implement the hashed associative containers +// hash_set, hash_map, hash_multiset, and hash_multimap. + +#include +#include +#include +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + struct _Hashtable_node + { + _Hashtable_node* _M_next; + _Val _M_val; + }; + + template > + class hashtable; + + template + struct _Hashtable_iterator; + + template + struct _Hashtable_const_iterator; + + template + struct _Hashtable_iterator + { + typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> + _Hashtable; + typedef _Hashtable_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + const_iterator; + typedef _Hashtable_node<_Val> _Node; + typedef std::forward_iterator_tag iterator_category; + typedef _Val value_type; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef _Val& reference; + typedef _Val* pointer; + + _Node* _M_cur; + _Hashtable* _M_ht; + + _Hashtable_iterator(_Node* __n, _Hashtable* __tab) + : _M_cur(__n), _M_ht(__tab) { } + + _Hashtable_iterator() { } + + reference + operator*() const + { return _M_cur->_M_val; } + + pointer + operator->() const + { return &(operator*()); } + + iterator& + operator++(); + + iterator + operator++(int); + + bool + operator==(const iterator& __it) const + { return _M_cur == __it._M_cur; } + + bool + operator!=(const iterator& __it) const + { return _M_cur != __it._M_cur; } + }; + + template + struct _Hashtable_const_iterator + { + typedef hashtable<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc> + _Hashtable; + typedef _Hashtable_iterator<_Val,_Key,_HashFcn, + _ExtractKey,_EqualKey,_Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, + _ExtractKey, _EqualKey, _Alloc> + const_iterator; + typedef _Hashtable_node<_Val> _Node; + + typedef std::forward_iterator_tag iterator_category; + typedef _Val value_type; + typedef std::ptrdiff_t difference_type; + typedef std::size_t size_type; + typedef const _Val& reference; + typedef const _Val* pointer; + + const _Node* _M_cur; + const _Hashtable* _M_ht; + + _Hashtable_const_iterator(const _Node* __n, const _Hashtable* __tab) + : _M_cur(__n), _M_ht(__tab) { } + + _Hashtable_const_iterator() { } + + _Hashtable_const_iterator(const iterator& __it) + : _M_cur(__it._M_cur), _M_ht(__it._M_ht) { } + + reference + operator*() const + { return _M_cur->_M_val; } + + pointer + operator->() const + { return &(operator*()); } + + const_iterator& + operator++(); + + const_iterator + operator++(int); + + bool + operator==(const const_iterator& __it) const + { return _M_cur == __it._M_cur; } + + bool + operator!=(const const_iterator& __it) const + { return _M_cur != __it._M_cur; } + }; + + // Note: assumes long is at least 32 bits. + enum { _S_num_primes = 29 }; + + template + struct _Hashtable_prime_list + { + static const _PrimeType __stl_prime_list[_S_num_primes]; + + static const _PrimeType* + _S_get_prime_list(); + }; + + template const _PrimeType + _Hashtable_prime_list<_PrimeType>::__stl_prime_list[_S_num_primes] = + { + 5ul, 53ul, 97ul, 193ul, 389ul, + 769ul, 1543ul, 3079ul, 6151ul, 12289ul, + 24593ul, 49157ul, 98317ul, 196613ul, 393241ul, + 786433ul, 1572869ul, 3145739ul, 6291469ul, 12582917ul, + 25165843ul, 50331653ul, 100663319ul, 201326611ul, 402653189ul, + 805306457ul, 1610612741ul, 3221225473ul, 4294967291ul + }; + + template inline const _PrimeType* + _Hashtable_prime_list<_PrimeType>::_S_get_prime_list() + { + return __stl_prime_list; + } + + inline unsigned long + __stl_next_prime(unsigned long __n) + { + const unsigned long* __first = _Hashtable_prime_list::_S_get_prime_list(); + const unsigned long* __last = __first + (int)_S_num_primes; + const unsigned long* pos = std::lower_bound(__first, __last, __n); + return pos == __last ? *(__last - 1) : *pos; + } + + // Forward declaration of operator==. + template + class hashtable; + + template + bool + operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, + const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2); + + // Hashtables handle allocators a bit differently than other + // containers do. If we're using standard-conforming allocators, then + // a hashtable unconditionally has a member variable to hold its + // allocator, even if it so happens that all instances of the + // allocator type are identical. This is because, for hashtables, + // this extra storage is negligible. Additionally, a base class + // wouldn't serve any other purposes; it wouldn't, for example, + // simplify the exception-handling code. + template + class hashtable + { + public: + typedef _Key key_type; + typedef _Val value_type; + typedef _HashFcn hasher; + typedef _EqualKey key_equal; + + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + hasher + hash_funct() const + { return _M_hash; } + + key_equal + key_eq() const + { return _M_equals; } + + private: + typedef _Hashtable_node<_Val> _Node; + + public: + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind::other allocator_type; + + allocator_type + get_allocator() const + { return _M_node_allocator; } + + private: + typedef __gnu_cxx::__alloc_traits _Alloc_traits; + typedef typename _Alloc_traits::template rebind<_Node>::other + _Node_Alloc; + typedef typename _Alloc_traits::template rebind<_Node*>::other + _Nodeptr_Alloc; + typedef std::vector<_Node*, _Nodeptr_Alloc> _Vector_type; + + _Node_Alloc _M_node_allocator; + + _Node* + _M_get_node() + { return _M_node_allocator.allocate(1); } + + void + _M_put_node(_Node* __p) + { _M_node_allocator.deallocate(__p, 1); } + + private: + hasher _M_hash; + key_equal _M_equals; + _ExtractKey _M_get_key; + _Vector_type _M_buckets; + size_type _M_num_elements; + + public: + typedef _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, + _EqualKey, _Alloc> + iterator; + typedef _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, + _EqualKey, _Alloc> + const_iterator; + + friend struct + _Hashtable_iterator<_Val, _Key, _HashFcn, _ExtractKey, _EqualKey, _Alloc>; + + friend struct + _Hashtable_const_iterator<_Val, _Key, _HashFcn, _ExtractKey, + _EqualKey, _Alloc>; + + public: + hashtable(size_type __n, const _HashFcn& __hf, + const _EqualKey& __eql, const _ExtractKey& __ext, + const allocator_type& __a = allocator_type()) + : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), + _M_get_key(__ext), _M_buckets(__a), _M_num_elements(0) + { _M_initialize_buckets(__n); } + + hashtable(size_type __n, const _HashFcn& __hf, + const _EqualKey& __eql, + const allocator_type& __a = allocator_type()) + : _M_node_allocator(__a), _M_hash(__hf), _M_equals(__eql), + _M_get_key(_ExtractKey()), _M_buckets(__a), _M_num_elements(0) + { _M_initialize_buckets(__n); } + + hashtable(const hashtable& __ht) + : _M_node_allocator(__ht.get_allocator()), _M_hash(__ht._M_hash), + _M_equals(__ht._M_equals), _M_get_key(__ht._M_get_key), + _M_buckets(__ht.get_allocator()), _M_num_elements(0) + { _M_copy_from(__ht); } + + hashtable& + operator= (const hashtable& __ht) + { + if (&__ht != this) + { + clear(); + _M_hash = __ht._M_hash; + _M_equals = __ht._M_equals; + _M_get_key = __ht._M_get_key; + _M_copy_from(__ht); + } + return *this; + } + + ~hashtable() + { clear(); } + + size_type + size() const + { return _M_num_elements; } + + size_type + max_size() const + { return size_type(-1); } + + _GLIBCXX_NODISCARD bool + empty() const + { return size() == 0; } + + void + swap(hashtable& __ht) + { + std::swap(_M_hash, __ht._M_hash); + std::swap(_M_equals, __ht._M_equals); + std::swap(_M_get_key, __ht._M_get_key); + _M_buckets.swap(__ht._M_buckets); + std::swap(_M_num_elements, __ht._M_num_elements); + } + + iterator + begin() + { + for (size_type __n = 0; __n < _M_buckets.size(); ++__n) + if (_M_buckets[__n]) + return iterator(_M_buckets[__n], this); + return end(); + } + + iterator + end() + { return iterator(0, this); } + + const_iterator + begin() const + { + for (size_type __n = 0; __n < _M_buckets.size(); ++__n) + if (_M_buckets[__n]) + return const_iterator(_M_buckets[__n], this); + return end(); + } + + const_iterator + end() const + { return const_iterator(0, this); } + + template + friend bool + operator==(const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&, + const hashtable<_Vl, _Ky, _HF, _Ex, _Eq, _Al>&); + + public: + size_type + bucket_count() const + { return _M_buckets.size(); } + + size_type + max_bucket_count() const + { return _Hashtable_prime_list:: + _S_get_prime_list()[(int)_S_num_primes - 1]; + } + + size_type + elems_in_bucket(size_type __bucket) const + { + size_type __result = 0; + for (_Node* __n = _M_buckets[__bucket]; __n; __n = __n->_M_next) + __result += 1; + return __result; + } + + std::pair + insert_unique(const value_type& __obj) + { + resize(_M_num_elements + 1); + return insert_unique_noresize(__obj); + } + + iterator + insert_equal(const value_type& __obj) + { + resize(_M_num_elements + 1); + return insert_equal_noresize(__obj); + } + + std::pair + insert_unique_noresize(const value_type& __obj); + + iterator + insert_equal_noresize(const value_type& __obj); + + template + void + insert_unique(_InputIterator __f, _InputIterator __l) + { insert_unique(__f, __l, std::__iterator_category(__f)); } + + template + void + insert_equal(_InputIterator __f, _InputIterator __l) + { insert_equal(__f, __l, std::__iterator_category(__f)); } + + template + void + insert_unique(_InputIterator __f, _InputIterator __l, + std::input_iterator_tag) + { + for ( ; __f != __l; ++__f) + insert_unique(*__f); + } + + template + void + insert_equal(_InputIterator __f, _InputIterator __l, + std::input_iterator_tag) + { + for ( ; __f != __l; ++__f) + insert_equal(*__f); + } + + template + void + insert_unique(_ForwardIterator __f, _ForwardIterator __l, + std::forward_iterator_tag) + { + size_type __n = std::distance(__f, __l); + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_unique_noresize(*__f); + } + + template + void + insert_equal(_ForwardIterator __f, _ForwardIterator __l, + std::forward_iterator_tag) + { + size_type __n = std::distance(__f, __l); + resize(_M_num_elements + __n); + for ( ; __n > 0; --__n, ++__f) + insert_equal_noresize(*__f); + } + + reference + find_or_insert(const value_type& __obj); + + iterator + find(const key_type& __key) + { + size_type __n = _M_bkt_num_key(__key); + _Node* __first; + for (__first = _M_buckets[__n]; + __first && !_M_equals(_M_get_key(__first->_M_val), __key); + __first = __first->_M_next) + { } + return iterator(__first, this); + } + + const_iterator + find(const key_type& __key) const + { + size_type __n = _M_bkt_num_key(__key); + const _Node* __first; + for (__first = _M_buckets[__n]; + __first && !_M_equals(_M_get_key(__first->_M_val), __key); + __first = __first->_M_next) + { } + return const_iterator(__first, this); + } + + size_type + count(const key_type& __key) const + { + const size_type __n = _M_bkt_num_key(__key); + size_type __result = 0; + + for (const _Node* __cur = _M_buckets[__n]; __cur; + __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), __key)) + ++__result; + return __result; + } + + std::pair + equal_range(const key_type& __key); + + std::pair + equal_range(const key_type& __key) const; + + size_type + erase(const key_type& __key); + + void + erase(const iterator& __it); + + void + erase(iterator __first, iterator __last); + + void + erase(const const_iterator& __it); + + void + erase(const_iterator __first, const_iterator __last); + + void + resize(size_type __num_elements_hint); + + void + clear(); + + private: + size_type + _M_next_size(size_type __n) const + { return __stl_next_prime(__n); } + + void + _M_initialize_buckets(size_type __n) + { + const size_type __n_buckets = _M_next_size(__n); + _M_buckets.reserve(__n_buckets); + _M_buckets.insert(_M_buckets.end(), __n_buckets, (_Node*) 0); + _M_num_elements = 0; + } + + size_type + _M_bkt_num_key(const key_type& __key) const + { return _M_bkt_num_key(__key, _M_buckets.size()); } + + size_type + _M_bkt_num(const value_type& __obj) const + { return _M_bkt_num_key(_M_get_key(__obj)); } + + size_type + _M_bkt_num_key(const key_type& __key, std::size_t __n) const + { return _M_hash(__key) % __n; } + + size_type + _M_bkt_num(const value_type& __obj, std::size_t __n) const + { return _M_bkt_num_key(_M_get_key(__obj), __n); } + + _Node* + _M_new_node(const value_type& __obj) + { + _Node* __n = _M_get_node(); + __n->_M_next = 0; + __try + { + allocator_type __a = this->get_allocator(); + _Alloc_traits::construct(__a, &__n->_M_val, __obj); + return __n; + } + __catch(...) + { + _M_put_node(__n); + __throw_exception_again; + } + } + + void + _M_delete_node(_Node* __n) + { + allocator_type __a = this->get_allocator(); + _Alloc_traits::destroy(__a, &__n->_M_val); + _M_put_node(__n); + } + + void + _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last); + + void + _M_erase_bucket(const size_type __n, _Node* __last); + + void + _M_copy_from(const hashtable& __ht); + }; + + template + _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& + _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: + operator++() + { + const _Node* __old = _M_cur; + _M_cur = _M_cur->_M_next; + if (!_M_cur) + { + size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); + while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) + _M_cur = _M_ht->_M_buckets[__bucket]; + } + return *this; + } + + template + inline _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> + _Hashtable_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: + operator++(int) + { + iterator __tmp = *this; + ++*this; + return __tmp; + } + + template + _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>& + _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: + operator++() + { + const _Node* __old = _M_cur; + _M_cur = _M_cur->_M_next; + if (!_M_cur) + { + size_type __bucket = _M_ht->_M_bkt_num(__old->_M_val); + while (!_M_cur && ++__bucket < _M_ht->_M_buckets.size()) + _M_cur = _M_ht->_M_buckets[__bucket]; + } + return *this; + } + + template + inline _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All> + _Hashtable_const_iterator<_Val, _Key, _HF, _ExK, _EqK, _All>:: + operator++(int) + { + const_iterator __tmp = *this; + ++*this; + return __tmp; + } + + template + bool + operator==(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, + const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) + { + typedef typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::_Node _Node; + + if (__ht1._M_buckets.size() != __ht2._M_buckets.size()) + return false; + + for (std::size_t __n = 0; __n < __ht1._M_buckets.size(); ++__n) + { + _Node* __cur1 = __ht1._M_buckets[__n]; + _Node* __cur2 = __ht2._M_buckets[__n]; + // Check same length of lists + for (; __cur1 && __cur2; + __cur1 = __cur1->_M_next, __cur2 = __cur2->_M_next) + { } + if (__cur1 || __cur2) + return false; + // Now check one's elements are in the other + for (__cur1 = __ht1._M_buckets[__n] ; __cur1; + __cur1 = __cur1->_M_next) + { + bool _found__cur1 = false; + for (__cur2 = __ht2._M_buckets[__n]; + __cur2; __cur2 = __cur2->_M_next) + { + if (__cur1->_M_val == __cur2->_M_val) + { + _found__cur1 = true; + break; + } + } + if (!_found__cur1) + return false; + } + } + return true; + } + + template + inline bool + operator!=(const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht1, + const hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>& __ht2) + { return !(__ht1 == __ht2); } + + template + inline void + swap(hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht1, + hashtable<_Val, _Key, _HF, _Extract, _EqKey, _All>& __ht2) + { __ht1.swap(__ht2); } + + template + std::pair::iterator, + bool> + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + insert_unique_noresize(const value_type& __obj) + { + const size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) + return std::pair(iterator(__cur, this), false); + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return std::pair(iterator(__tmp, this), true); + } + + template + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + insert_equal_noresize(const value_type& __obj) + { + const size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) + { + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __cur->_M_next; + __cur->_M_next = __tmp; + ++_M_num_elements; + return iterator(__tmp, this); + } + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return iterator(__tmp, this); + } + + template + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::reference + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + find_or_insert(const value_type& __obj) + { + resize(_M_num_elements + 1); + + size_type __n = _M_bkt_num(__obj); + _Node* __first = _M_buckets[__n]; + + for (_Node* __cur = __first; __cur; __cur = __cur->_M_next) + if (_M_equals(_M_get_key(__cur->_M_val), _M_get_key(__obj))) + return __cur->_M_val; + + _Node* __tmp = _M_new_node(__obj); + __tmp->_M_next = __first; + _M_buckets[__n] = __tmp; + ++_M_num_elements; + return __tmp->_M_val; + } + + template + std::pair::iterator, + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::iterator> + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + equal_range(const key_type& __key) + { + typedef std::pair _Pii; + const size_type __n = _M_bkt_num_key(__key); + + for (_Node* __first = _M_buckets[__n]; __first; + __first = __first->_M_next) + if (_M_equals(_M_get_key(__first->_M_val), __key)) + { + for (_Node* __cur = __first->_M_next; __cur; + __cur = __cur->_M_next) + if (!_M_equals(_M_get_key(__cur->_M_val), __key)) + return _Pii(iterator(__first, this), iterator(__cur, this)); + for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) + if (_M_buckets[__m]) + return _Pii(iterator(__first, this), + iterator(_M_buckets[__m], this)); + return _Pii(iterator(__first, this), end()); + } + return _Pii(end(), end()); + } + + template + std::pair< + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator, + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::const_iterator> + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + equal_range(const key_type& __key) const + { + typedef std::pair _Pii; + const size_type __n = _M_bkt_num_key(__key); + + for (const _Node* __first = _M_buckets[__n]; __first; + __first = __first->_M_next) + { + if (_M_equals(_M_get_key(__first->_M_val), __key)) + { + for (const _Node* __cur = __first->_M_next; __cur; + __cur = __cur->_M_next) + if (!_M_equals(_M_get_key(__cur->_M_val), __key)) + return _Pii(const_iterator(__first, this), + const_iterator(__cur, this)); + for (size_type __m = __n + 1; __m < _M_buckets.size(); ++__m) + if (_M_buckets[__m]) + return _Pii(const_iterator(__first, this), + const_iterator(_M_buckets[__m], this)); + return _Pii(const_iterator(__first, this), end()); + } + } + return _Pii(end(), end()); + } + + template + typename hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>::size_type + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(const key_type& __key) + { + const size_type __n = _M_bkt_num_key(__key); + _Node* __first = _M_buckets[__n]; + _Node* __saved_slot = 0; + size_type __erased = 0; + + if (__first) + { + _Node* __cur = __first; + _Node* __next = __cur->_M_next; + while (__next) + { + if (_M_equals(_M_get_key(__next->_M_val), __key)) + { + if (&_M_get_key(__next->_M_val) != &__key) + { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + __next = __cur->_M_next; + ++__erased; + --_M_num_elements; + } + else + { + __saved_slot = __cur; + __cur = __next; + __next = __cur->_M_next; + } + } + else + { + __cur = __next; + __next = __cur->_M_next; + } + } + bool __delete_first = _M_equals(_M_get_key(__first->_M_val), __key); + if (__saved_slot) + { + __next = __saved_slot->_M_next; + __saved_slot->_M_next = __next->_M_next; + _M_delete_node(__next); + ++__erased; + --_M_num_elements; + } + if (__delete_first) + { + _M_buckets[__n] = __first->_M_next; + _M_delete_node(__first); + ++__erased; + --_M_num_elements; + } + } + return __erased; + } + + template + void hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(const iterator& __it) + { + _Node* __p = __it._M_cur; + if (__p) + { + const size_type __n = _M_bkt_num(__p->_M_val); + _Node* __cur = _M_buckets[__n]; + + if (__cur == __p) + { + _M_buckets[__n] = __cur->_M_next; + _M_delete_node(__cur); + --_M_num_elements; + } + else + { + _Node* __next = __cur->_M_next; + while (__next) + { + if (__next == __p) + { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + --_M_num_elements; + break; + } + else + { + __cur = __next; + __next = __cur->_M_next; + } + } + } + } + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(iterator __first, iterator __last) + { + size_type __f_bucket = __first._M_cur ? _M_bkt_num(__first._M_cur->_M_val) + : _M_buckets.size(); + + size_type __l_bucket = __last._M_cur ? _M_bkt_num(__last._M_cur->_M_val) + : _M_buckets.size(); + + if (__first._M_cur == __last._M_cur) + return; + else if (__f_bucket == __l_bucket) + _M_erase_bucket(__f_bucket, __first._M_cur, __last._M_cur); + else + { + _M_erase_bucket(__f_bucket, __first._M_cur, 0); + for (size_type __n = __f_bucket + 1; __n < __l_bucket; ++__n) + _M_erase_bucket(__n, 0); + if (__l_bucket != _M_buckets.size()) + _M_erase_bucket(__l_bucket, __last._M_cur); + } + } + + template + inline void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(const_iterator __first, const_iterator __last) + { + erase(iterator(const_cast<_Node*>(__first._M_cur), + const_cast(__first._M_ht)), + iterator(const_cast<_Node*>(__last._M_cur), + const_cast(__last._M_ht))); + } + + template + inline void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + erase(const const_iterator& __it) + { erase(iterator(const_cast<_Node*>(__it._M_cur), + const_cast(__it._M_ht))); } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + resize(size_type __num_elements_hint) + { + const size_type __old_n = _M_buckets.size(); + if (__num_elements_hint > __old_n) + { + const size_type __n = _M_next_size(__num_elements_hint); + if (__n > __old_n) + { + _Vector_type __tmp(__n, (_Node*)(0), _M_buckets.get_allocator()); + __try + { + for (size_type __bucket = 0; __bucket < __old_n; ++__bucket) + { + _Node* __first = _M_buckets[__bucket]; + while (__first) + { + size_type __new_bucket = _M_bkt_num(__first->_M_val, + __n); + _M_buckets[__bucket] = __first->_M_next; + __first->_M_next = __tmp[__new_bucket]; + __tmp[__new_bucket] = __first; + __first = _M_buckets[__bucket]; + } + } + _M_buckets.swap(__tmp); + } + __catch(...) + { + for (size_type __bucket = 0; __bucket < __tmp.size(); + ++__bucket) + { + while (__tmp[__bucket]) + { + _Node* __next = __tmp[__bucket]->_M_next; + _M_delete_node(__tmp[__bucket]); + __tmp[__bucket] = __next; + } + } + __throw_exception_again; + } + } + } + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + _M_erase_bucket(const size_type __n, _Node* __first, _Node* __last) + { + _Node* __cur = _M_buckets[__n]; + if (__cur == __first) + _M_erase_bucket(__n, __last); + else + { + _Node* __next; + for (__next = __cur->_M_next; + __next != __first; + __cur = __next, __next = __cur->_M_next) + ; + while (__next != __last) + { + __cur->_M_next = __next->_M_next; + _M_delete_node(__next); + __next = __cur->_M_next; + --_M_num_elements; + } + } + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + _M_erase_bucket(const size_type __n, _Node* __last) + { + _Node* __cur = _M_buckets[__n]; + while (__cur != __last) + { + _Node* __next = __cur->_M_next; + _M_delete_node(__cur); + __cur = __next; + _M_buckets[__n] = __cur; + --_M_num_elements; + } + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + clear() + { + if (_M_num_elements == 0) + return; + + for (size_type __i = 0; __i < _M_buckets.size(); ++__i) + { + _Node* __cur = _M_buckets[__i]; + while (__cur != 0) + { + _Node* __next = __cur->_M_next; + _M_delete_node(__cur); + __cur = __next; + } + _M_buckets[__i] = 0; + } + _M_num_elements = 0; + } + + template + void + hashtable<_Val, _Key, _HF, _Ex, _Eq, _All>:: + _M_copy_from(const hashtable& __ht) + { + _M_buckets.clear(); + _M_buckets.reserve(__ht._M_buckets.size()); + _M_buckets.insert(_M_buckets.end(), __ht._M_buckets.size(), (_Node*) 0); + __try + { + for (size_type __i = 0; __i < __ht._M_buckets.size(); ++__i) { + const _Node* __cur = __ht._M_buckets[__i]; + if (__cur) + { + _Node* __local_copy = _M_new_node(__cur->_M_val); + _M_buckets[__i] = __local_copy; + + for (_Node* __next = __cur->_M_next; + __next; + __cur = __next, __next = __cur->_M_next) + { + __local_copy->_M_next = _M_new_node(__next->_M_val); + __local_copy = __local_copy->_M_next; + } + } + } + _M_num_elements = __ht._M_num_elements; + } + __catch(...) + { + clear(); + __throw_exception_again; + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bit b/resources/sources/avr-libstdcpp/include/bit new file mode 100644 index 000000000..f4344820d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bit @@ -0,0 +1,371 @@ +// -*- C++ -*- + +// Copyright (C) 2018-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bit + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_BIT +#define _GLIBCXX_BIT 1 + +#pragma GCC system_header + +#if __cplusplus >= 201402L + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup bit_manip Bit manipulation + * @ingroup numerics + * + * Utilities for examining and manipulating individual bits. + * + * @{ + */ + + /// @cond undoc + + template + constexpr _Tp + __rotl(_Tp __x, int __s) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x << __r) | (__x >> ((_Nd - __r) % _Nd)); + else + return (__x >> -__r) | (__x << ((_Nd + __r) % _Nd)); // rotr(x, -r) + } + + template + constexpr _Tp + __rotr(_Tp __x, int __s) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + const int __r = __s % _Nd; + if (__r == 0) + return __x; + else if (__r > 0) + return (__x >> __r) | (__x << ((_Nd - __r) % _Nd)); + else + return (__x << -__r) | (__x >> ((_Nd + __r) % _Nd)); // rotl(x, -r) + } + + template + constexpr int + __countl_zero(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + if (__x == 0) + return _Nd; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + { + constexpr int __diff = _Nd_u - _Nd; + return __builtin_clz(__x) - __diff; + } + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + { + constexpr int __diff = _Nd_ul - _Nd; + return __builtin_clzl(__x) - __diff; + } + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + { + constexpr int __diff = _Nd_ull - _Nd; + return __builtin_clzll(__x) - __diff; + } + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + unsigned long long __high = __x >> _Nd_ull; + if (__high != 0) + { + constexpr int __diff = (2 * _Nd_ull) - _Nd; + return __builtin_clzll(__high) - __diff; + } + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + return (_Nd - _Nd_ull) + __builtin_clzll(__low); + } + } + + template + constexpr int + __countl_one(_Tp __x) noexcept + { + if (__x == __gnu_cxx::__int_traits<_Tp>::__max) + return __gnu_cxx::__int_traits<_Tp>::__digits; + return std::__countl_zero<_Tp>((_Tp)~__x); + } + + template + constexpr int + __countr_zero(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + if (__x == 0) + return _Nd; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + return __builtin_ctz(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + return __builtin_ctzl(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + return __builtin_ctzll(__x); + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + if (__low != 0) + return __builtin_ctzll(__low); + unsigned long long __high = __x >> _Nd_ull; + return __builtin_ctzll(__high) + _Nd_ull; + } + } + + template + constexpr int + __countr_one(_Tp __x) noexcept + { + if (__x == __gnu_cxx::__int_traits<_Tp>::__max) + return __gnu_cxx::__int_traits<_Tp>::__digits; + return std::__countr_zero((_Tp)~__x); + } + + template + constexpr int + __popcount(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + + if (__x == 0) + return 0; + + constexpr auto _Nd_ull = __int_traits::__digits; + constexpr auto _Nd_ul = __int_traits::__digits; + constexpr auto _Nd_u = __int_traits::__digits; + + if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_u) + return __builtin_popcount(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ul) + return __builtin_popcountl(__x); + else if _GLIBCXX17_CONSTEXPR (_Nd <= _Nd_ull) + return __builtin_popcountll(__x); + else // (_Nd > _Nd_ull) + { + static_assert(_Nd <= (2 * _Nd_ull), + "Maximum supported integer size is 128-bit"); + + constexpr auto __max_ull = __int_traits::__max; + unsigned long long __low = __x & __max_ull; + unsigned long long __high = __x >> _Nd_ull; + return __builtin_popcountll(__low) + __builtin_popcountll(__high); + } + } + + template + constexpr bool + __has_single_bit(_Tp __x) noexcept + { return std::__popcount(__x) == 1; } + + template + constexpr _Tp + __bit_ceil(_Tp __x) noexcept + { + using __gnu_cxx::__int_traits; + constexpr auto _Nd = __int_traits<_Tp>::__digits; + if (__x == 0 || __x == 1) + return 1; + auto __shift_exponent = _Nd - std::__countl_zero((_Tp)(__x - 1u)); + // If the shift exponent equals _Nd then the correct result is not + // representable as a value of _Tp, and so the result is undefined. + // Want that undefined behaviour to be detected in constant expressions, + // by UBSan, and by debug assertions. +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (!__builtin_is_constant_evaluated()) + { + __glibcxx_assert( __shift_exponent != __int_traits<_Tp>::__digits ); + } +#endif + using __promoted_type = decltype(__x << 1); + if _GLIBCXX17_CONSTEXPR (!is_same<__promoted_type, _Tp>::value) + { + // If __x undergoes integral promotion then shifting by _Nd is + // not undefined. In order to make the shift undefined, so that + // it is diagnosed in constant expressions and by UBsan, we also + // need to "promote" the shift exponent to be too large for the + // promoted type. + const int __extra_exp = sizeof(__promoted_type) / sizeof(_Tp) / 2; + __shift_exponent |= (__shift_exponent & _Nd) << __extra_exp; + } + return (_Tp)1u << __shift_exponent; + } + + template + constexpr _Tp + __bit_floor(_Tp __x) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + if (__x == 0) + return 0; + return (_Tp)1u << (_Nd - std::__countl_zero((_Tp)(__x >> 1))); + } + + template + constexpr _Tp + __bit_width(_Tp __x) noexcept + { + constexpr auto _Nd = __gnu_cxx::__int_traits<_Tp>::__digits; + return _Nd - std::__countl_zero(__x); + } + + /// @endcond + +#if __cplusplus > 201703L + +#define __cpp_lib_bitops 201907L + + /// @cond undoc + template + using _If_is_unsigned_integer + = enable_if_t<__is_unsigned_integer<_Tp>::value, _Up>; + /// @endcond + + // [bit.rot], rotating + + /// Rotate `x` to the left by `s` bits. + template + [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> + rotl(_Tp __x, int __s) noexcept + { return std::__rotl(__x, __s); } + + /// Rotate `x` to the right by `s` bits. + template + [[nodiscard]] constexpr _If_is_unsigned_integer<_Tp> + rotr(_Tp __x, int __s) noexcept + { return std::__rotr(__x, __s); } + + // [bit.count], counting + + /// The number of contiguous zero bits, starting from the highest bit. + template + constexpr _If_is_unsigned_integer<_Tp, int> + countl_zero(_Tp __x) noexcept + { return std::__countl_zero(__x); } + + /// The number of contiguous one bits, starting from the highest bit. + template + constexpr _If_is_unsigned_integer<_Tp, int> + countl_one(_Tp __x) noexcept + { return std::__countl_one(__x); } + + /// The number of contiguous zero bits, starting from the lowest bit. + template + constexpr _If_is_unsigned_integer<_Tp, int> + countr_zero(_Tp __x) noexcept + { return std::__countr_zero(__x); } + + /// The number of contiguous one bits, starting from the lowest bit. + template + constexpr _If_is_unsigned_integer<_Tp, int> + countr_one(_Tp __x) noexcept + { return std::__countr_one(__x); } + + /// The number of bits set in `x`. + template + constexpr _If_is_unsigned_integer<_Tp, int> + popcount(_Tp __x) noexcept + { return std::__popcount(__x); } + + // [bit.pow.two], integral powers of 2 + +#define __cpp_lib_int_pow2 202002L + + /// True if `x` is a power of two, false otherwise. + template + constexpr _If_is_unsigned_integer<_Tp, bool> + has_single_bit(_Tp __x) noexcept + { return std::__has_single_bit(__x); } + + /// The smallest power-of-two not less than `x`. + template + constexpr _If_is_unsigned_integer<_Tp> + bit_ceil(_Tp __x) noexcept + { return std::__bit_ceil(__x); } + + /// The largest power-of-two not greater than `x`. + template + constexpr _If_is_unsigned_integer<_Tp> + bit_floor(_Tp __x) noexcept + { return std::__bit_floor(__x); } + + /// The smallest integer greater than the base-2 logarithm of `x`. + template + constexpr _If_is_unsigned_integer<_Tp> + bit_width(_Tp __x) noexcept + { return std::__bit_width(__x); } + +#define __cpp_lib_endian 201907L + + /// Byte order + enum class endian + { + little = __ORDER_LITTLE_ENDIAN__, + big = __ORDER_BIG_ENDIAN__, + native = __BYTE_ORDER__ + }; +#endif // C++2a + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 +#endif // _GLIBCXX_BIT diff --git a/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h b/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h new file mode 100644 index 000000000..de0bd44f6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/algorithmfwd.h @@ -0,0 +1,963 @@ +// Forward declarations -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/algorithmfwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _GLIBCXX_ALGORITHMFWD_H +#define _GLIBCXX_ALGORITHMFWD_H 1 + +#pragma GCC system_header + +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /* + adjacent_find + all_of (C++11) + any_of (C++11) + binary_search + clamp (C++17) + copy + copy_backward + copy_if (C++11) + copy_n (C++11) + count + count_if + equal + equal_range + fill + fill_n + find + find_end + find_first_of + find_if + find_if_not (C++11) + for_each + generate + generate_n + includes + inplace_merge + is_heap (C++11) + is_heap_until (C++11) + is_partitioned (C++11) + is_sorted (C++11) + is_sorted_until (C++11) + iter_swap + lexicographical_compare + lower_bound + make_heap + max + max_element + merge + min + min_element + minmax (C++11) + minmax_element (C++11) + mismatch + next_permutation + none_of (C++11) + nth_element + partial_sort + partial_sort_copy + partition + partition_copy (C++11) + partition_point (C++11) + pop_heap + prev_permutation + push_heap + random_shuffle + remove + remove_copy + remove_copy_if + remove_if + replace + replace_copy + replace_copy_if + replace_if + reverse + reverse_copy + rotate + rotate_copy + search + search_n + set_difference + set_intersection + set_symmetric_difference + set_union + shuffle (C++11) + sort + sort_heap + stable_partition + stable_sort + swap + swap_ranges + transform + unique + unique_copy + upper_bound + */ + + /** + * @defgroup algorithms Algorithms + * + * Components for performing algorithmic operations. Includes + * non-modifying sequence, modifying (mutating) sequence, sorting, + * searching, merge, partition, heap, set, minima, maxima, and + * permutation operations. + */ + + /** + * @defgroup mutating_algorithms Mutating + * @ingroup algorithms + */ + + /** + * @defgroup non_mutating_algorithms Non-Mutating + * @ingroup algorithms + */ + + /** + * @defgroup sorting_algorithms Sorting + * @ingroup algorithms + */ + + /** + * @defgroup set_algorithms Set Operations + * @ingroup sorting_algorithms + * + * These algorithms are common set operations performed on sequences + * that are already sorted. The number of comparisons will be + * linear. + */ + + /** + * @defgroup binary_search_algorithms Binary Search + * @ingroup sorting_algorithms + * + * These algorithms are variations of a classic binary search, and + * all assume that the sequence being searched is already sorted. + * + * The number of comparisons will be logarithmic (and as few as + * possible). The number of steps through the sequence will be + * logarithmic for random-access iterators (e.g., pointers), and + * linear otherwise. + * + * The LWG has passed Defect Report 270, which notes: The + * proposed resolution reinterprets binary search. Instead of + * thinking about searching for a value in a sorted range, we view + * that as an important special case of a more general algorithm: + * searching for the partition point in a partitioned range. We + * also add a guarantee that the old wording did not: we ensure that + * the upper bound is no earlier than the lower bound, that the pair + * returned by equal_range is a valid range, and that the first part + * of that pair is the lower bound. + * + * The actual effect of the first sentence is that a comparison + * functor passed by the user doesn't necessarily need to induce a + * strict weak ordering relation. Rather, it partitions the range. + */ + + // adjacent_find + +#if __cplusplus > 201703L +# define __cpp_lib_constexpr_algorithms 201806L +#endif + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + all_of(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + any_of(_IIter, _IIter, _Predicate); +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_FIter, _FIter, const _Tp&, _Compare); + +#if __cplusplus > 201402L + template + _GLIBCXX14_CONSTEXPR + const _Tp& + clamp(const _Tp&, const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + clamp(const _Tp&, const _Tp&, const _Tp&, _Compare); +#endif + + template + _GLIBCXX20_CONSTEXPR + _OIter + copy(_IIter, _IIter, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _BIter2 + copy_backward(_BIter1, _BIter1, _BIter2); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + _OIter + copy_if(_IIter, _IIter, _OIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + copy_n(_IIter, _Size, _OIter); +#endif + + // count + // count_if + + template + _GLIBCXX20_CONSTEXPR + pair<_FIter, _FIter> + equal_range(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + pair<_FIter, _FIter> + equal_range(_FIter, _FIter, const _Tp&, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + fill(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + fill_n(_OIter, _Size, const _Tp&); + + // find + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_end(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_end(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + // find_first_of + // find_if + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + _IIter + find_if_not(_IIter, _IIter, _Predicate); +#endif + + // for_each + // generate + // generate_n + + template + _GLIBCXX20_CONSTEXPR + bool + includes(_IIter1, _IIter1, _IIter2, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + includes(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); + + template + void + inplace_merge(_BIter, _BIter, _BIter); + + template + void + inplace_merge(_BIter, _BIter, _BIter, _Compare); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + is_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + bool + is_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + is_heap_until(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + is_heap_until(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + bool + is_partitioned(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + is_permutation(_FIter1, _FIter1, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + is_permutation(_FIter1, _FIter1, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + bool + is_sorted(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + bool + is_sorted(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _FIter + is_sorted_until(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + is_sorted_until(_FIter, _FIter, _Compare); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + iter_swap(_FIter1, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter + lower_bound(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + lower_bound(_FIter, _FIter, const _Tp&, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + make_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + make_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + max(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + max(const _Tp&, const _Tp&, _Compare); + + // max_element + // merge + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + min(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + const _Tp& + min(const _Tp&, const _Tp&, _Compare); + + // min_element + +#if __cplusplus >= 201103L + template + _GLIBCXX14_CONSTEXPR + pair + minmax(const _Tp&, const _Tp&); + + template + _GLIBCXX14_CONSTEXPR + pair + minmax(const _Tp&, const _Tp&, _Compare); + + template + _GLIBCXX14_CONSTEXPR + pair<_FIter, _FIter> + minmax_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + pair<_FIter, _FIter> + minmax_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _Tp + min(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + _Tp + min(initializer_list<_Tp>, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _Tp + max(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + _Tp + max(initializer_list<_Tp>, _Compare); + + template + _GLIBCXX14_CONSTEXPR + pair<_Tp, _Tp> + minmax(initializer_list<_Tp>); + + template + _GLIBCXX14_CONSTEXPR + pair<_Tp, _Tp> + minmax(initializer_list<_Tp>, _Compare); +#endif + + // mismatch + + template + _GLIBCXX20_CONSTEXPR + bool + next_permutation(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + bool + next_permutation(_BIter, _BIter, _Compare); + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + none_of(_IIter, _IIter, _Predicate); +#endif + + // nth_element + // partial_sort + + template + _GLIBCXX20_CONSTEXPR + _RAIter + partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + _RAIter + partial_sort_copy(_IIter, _IIter, _RAIter, _RAIter, _Compare); + + // partition + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + pair<_OIter1, _OIter2> + partition_copy(_IIter, _IIter, _OIter1, _OIter2, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _FIter + partition_point(_FIter, _FIter, _Predicate); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + pop_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + pop_heap(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + bool + prev_permutation(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + bool + prev_permutation(_BIter, _BIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + push_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + push_heap(_RAIter, _RAIter, _Compare); + + // random_shuffle + + template + _GLIBCXX20_CONSTEXPR + _FIter + remove(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + remove_if(_FIter, _FIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + remove_copy(_IIter, _IIter, _OIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + remove_copy_if(_IIter, _IIter, _OIter, _Predicate); + + // replace + + template + _GLIBCXX20_CONSTEXPR + _OIter + replace_copy(_IIter, _IIter, _OIter, const _Tp&, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _OIter + replace_copy_if(_Iter, _Iter, _OIter, _Predicate, const _Tp&); + + // replace_if + + template + _GLIBCXX20_CONSTEXPR + void + reverse(_BIter, _BIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + reverse_copy(_BIter, _BIter, _OIter); + + inline namespace _V2 + { + template + _GLIBCXX20_CONSTEXPR + _FIter + rotate(_FIter, _FIter, _FIter); + } + + template + _GLIBCXX20_CONSTEXPR + _OIter + rotate_copy(_FIter, _FIter, _FIter, _OIter); + + // search + // search_n + // set_difference + // set_intersection + // set_symmetric_difference + // set_union + +#if (__cplusplus >= 201103L) && defined(_GLIBCXX_USE_C99_STDINT_TR1) + template + void + shuffle(_RAIter, _RAIter, _UGenerator&&); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + sort_heap(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + sort_heap(_RAIter, _RAIter, _Compare); + + template + _BIter + stable_partition(_BIter, _BIter, _Predicate); + +#if __cplusplus < 201103L + // For C++11 swap() is declared in . + + template + _GLIBCXX20_CONSTEXPR + inline void + swap(_Tp& __a, _Tp& __b); + + template + _GLIBCXX20_CONSTEXPR + inline void + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]); +#endif + + template + _GLIBCXX20_CONSTEXPR + _FIter2 + swap_ranges(_FIter1, _FIter1, _FIter2); + + // transform + + template + _GLIBCXX20_CONSTEXPR + _FIter + unique(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + unique(_FIter, _FIter, _BinaryPredicate); + + // unique_copy + + template + _GLIBCXX20_CONSTEXPR + _FIter + upper_bound(_FIter, _FIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + upper_bound(_FIter, _FIter, const _Tp&, _Compare); + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + template + _GLIBCXX20_CONSTEXPR + _FIter + adjacent_find(_FIter, _FIter); + + template + _GLIBCXX20_CONSTEXPR + _FIter + adjacent_find(_FIter, _FIter, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_IIter>::difference_type + count(_IIter, _IIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_IIter>::difference_type + count_if(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + bool + equal(_IIter1, _IIter1, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + equal(_IIter1, _IIter1, _IIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _IIter + find(_IIter, _IIter, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_first_of(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + find_first_of(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _IIter + find_if(_IIter, _IIter, _Predicate); + + template + _GLIBCXX20_CONSTEXPR + _Funct + for_each(_IIter, _IIter, _Funct); + + template + _GLIBCXX20_CONSTEXPR + void + generate(_FIter, _FIter, _Generator); + + template + _GLIBCXX20_CONSTEXPR + _OIter + generate_n(_OIter, _Size, _Generator); + + template + _GLIBCXX20_CONSTEXPR + bool + lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + bool + lexicographical_compare(_IIter1, _IIter1, _IIter2, _IIter2, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _FIter + max_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + _FIter + max_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + merge(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX14_CONSTEXPR + _FIter + min_element(_FIter, _FIter); + + template + _GLIBCXX14_CONSTEXPR + _FIter + min_element(_FIter, _FIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + pair<_IIter1, _IIter2> + mismatch(_IIter1, _IIter1, _IIter2); + + template + _GLIBCXX20_CONSTEXPR + pair<_IIter1, _IIter2> + mismatch(_IIter1, _IIter1, _IIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + void + nth_element(_RAIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + nth_element(_RAIter, _RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + partial_sort(_RAIter, _RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + partial_sort(_RAIter, _RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _BIter + partition(_BIter, _BIter, _Predicate); + + template + void + random_shuffle(_RAIter, _RAIter); + + template + void + random_shuffle(_RAIter, _RAIter, +#if __cplusplus >= 201103L + _Generator&&); +#else + _Generator&); +#endif + + template + _GLIBCXX20_CONSTEXPR + void + replace(_FIter, _FIter, const _Tp&, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + void + replace_if(_FIter, _FIter, _Predicate, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + search(_FIter1, _FIter1, _FIter2, _FIter2); + + template + _GLIBCXX20_CONSTEXPR + _FIter1 + search(_FIter1, _FIter1, _FIter2, _FIter2, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _FIter + search_n(_FIter, _FIter, _Size, const _Tp&); + + template + _GLIBCXX20_CONSTEXPR + _FIter + search_n(_FIter, _FIter, _Size, const _Tp&, _BinaryPredicate); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_intersection(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_symmetric_difference(_IIter1, _IIter1, _IIter2, _IIter2, + _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + set_union(_IIter1, _IIter1, _IIter2, _IIter2, _OIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + void + sort(_RAIter, _RAIter); + + template + _GLIBCXX20_CONSTEXPR + void + sort(_RAIter, _RAIter, _Compare); + + template + void + stable_sort(_RAIter, _RAIter); + + template + void + stable_sort(_RAIter, _RAIter, _Compare); + + template + _GLIBCXX20_CONSTEXPR + _OIter + transform(_IIter, _IIter, _OIter, _UnaryOperation); + + template + _GLIBCXX20_CONSTEXPR + _OIter + transform(_IIter1, _IIter1, _IIter2, _OIter, _BinaryOperation); + + template + _GLIBCXX20_CONSTEXPR + _OIter + unique_copy(_IIter, _IIter, _OIter); + + template + _GLIBCXX20_CONSTEXPR + _OIter + unique_copy(_IIter, _IIter, _OIter, _BinaryPredicate); + +_GLIBCXX_END_NAMESPACE_ALGO +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h b/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h new file mode 100644 index 000000000..86d8ed221 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/alloc_traits.h @@ -0,0 +1,743 @@ +// Allocator traits -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/alloc_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOC_TRAITS_H +#define _ALLOC_TRAITS_H 1 + +#include +#include +#if __cplusplus >= 201103L +# include +# include +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201103L +#define __cpp_lib_allocator_traits_is_always_equal 201411 + + struct __allocator_traits_base + { + template + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + + template + struct __rebind<_Tp, _Up, + __void_t::other>> + { using type = typename _Tp::template rebind<_Up>::other; }; + + protected: + template + using __pointer = typename _Tp::pointer; + template + using __c_pointer = typename _Tp::const_pointer; + template + using __v_pointer = typename _Tp::void_pointer; + template + using __cv_pointer = typename _Tp::const_void_pointer; + template + using __pocca = typename _Tp::propagate_on_container_copy_assignment; + template + using __pocma = typename _Tp::propagate_on_container_move_assignment; + template + using __pocs = typename _Tp::propagate_on_container_swap; + template + using __equal = typename _Tp::is_always_equal; + }; + + template + using __alloc_rebind + = typename __allocator_traits_base::template __rebind<_Alloc, _Up>::type; + + /** + * @brief Uniform interface to all allocator types. + * @ingroup allocators + */ + template + struct allocator_traits : __allocator_traits_base + { + /// The allocator type + typedef _Alloc allocator_type; + /// The allocated type + typedef typename _Alloc::value_type value_type; + + /** + * @brief The allocator's pointer type. + * + * @c Alloc::pointer if that type exists, otherwise @c value_type* + */ + using pointer = __detected_or_t; + + private: + // Select _Func<_Alloc> or pointer_traits::rebind<_Tp> + template class _Func, typename _Tp, typename = void> + struct _Ptr + { + using type = typename pointer_traits::template rebind<_Tp>; + }; + + template class _Func, typename _Tp> + struct _Ptr<_Func, _Tp, __void_t<_Func<_Alloc>>> + { + using type = _Func<_Alloc>; + }; + + // Select _A2::difference_type or pointer_traits<_Ptr>::difference_type + template + struct _Diff + { using type = typename pointer_traits<_PtrT>::difference_type; }; + + template + struct _Diff<_A2, _PtrT, __void_t> + { using type = typename _A2::difference_type; }; + + // Select _A2::size_type or make_unsigned<_DiffT>::type + template + struct _Size : make_unsigned<_DiffT> { }; + + template + struct _Size<_A2, _DiffT, __void_t> + { using type = typename _A2::size_type; }; + + public: + /** + * @brief The allocator's const pointer type. + * + * @c Alloc::const_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using const_pointer = typename _Ptr<__c_pointer, const value_type>::type; + + /** + * @brief The allocator's void pointer type. + * + * @c Alloc::void_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using void_pointer = typename _Ptr<__v_pointer, void>::type; + + /** + * @brief The allocator's const void pointer type. + * + * @c Alloc::const_void_pointer if that type exists, otherwise + * pointer_traits::rebind + */ + using const_void_pointer = typename _Ptr<__cv_pointer, const void>::type; + + /** + * @brief The allocator's difference type + * + * @c Alloc::difference_type if that type exists, otherwise + * pointer_traits::difference_type + */ + using difference_type = typename _Diff<_Alloc, pointer>::type; + + /** + * @brief The allocator's size type + * + * @c Alloc::size_type if that type exists, otherwise + * make_unsigned::type + */ + using size_type = typename _Size<_Alloc, difference_type>::type; + + /** + * @brief How the allocator is propagated on copy assignment + * + * @c Alloc::propagate_on_container_copy_assignment if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_copy_assignment + = __detected_or_t; + + /** + * @brief How the allocator is propagated on move assignment + * + * @c Alloc::propagate_on_container_move_assignment if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_move_assignment + = __detected_or_t; + + /** + * @brief How the allocator is propagated on swap + * + * @c Alloc::propagate_on_container_swap if that type exists, + * otherwise @c false_type + */ + using propagate_on_container_swap + = __detected_or_t; + + /** + * @brief Whether all instances of the allocator type compare equal. + * + * @c Alloc::is_always_equal if that type exists, + * otherwise @c is_empty::type + */ + using is_always_equal + = __detected_or_t::type, __equal, _Alloc>; + + template + using rebind_alloc = __alloc_rebind<_Alloc, _Tp>; + template + using rebind_traits = allocator_traits>; + + private: + template + static constexpr auto + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer __hint, int) + -> decltype(__a.allocate(__n, __hint)) + { return __a.allocate(__n, __hint); } + + template + static constexpr pointer + _S_allocate(_Alloc2& __a, size_type __n, const_void_pointer, ...) + { return __a.allocate(__n); } + + template + struct __construct_helper + { + template()->construct( + std::declval<_Tp*>(), std::declval<_Args>()...))> + static true_type __test(int); + + template + static false_type __test(...); + + using type = decltype(__test<_Alloc>(0)); + }; + + template + using __has_construct + = typename __construct_helper<_Tp, _Args...>::type; + + template + static _GLIBCXX14_CONSTEXPR _Require<__has_construct<_Tp, _Args...>> + _S_construct(_Alloc& __a, _Tp* __p, _Args&&... __args) + noexcept(noexcept(__a.construct(__p, std::forward<_Args>(__args)...))) + { __a.construct(__p, std::forward<_Args>(__args)...); } + + template + static _GLIBCXX14_CONSTEXPR + _Require<__and_<__not_<__has_construct<_Tp, _Args...>>, + is_constructible<_Tp, _Args...>>> + _S_construct(_Alloc&, _Tp* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Tp, _Args...>::value) + { +#if __cplusplus <= 201703L + ::new((void*)__p) _Tp(std::forward<_Args>(__args)...); +#else + std::construct_at(__p, std::forward<_Args>(__args)...); +#endif + } + + template + static _GLIBCXX14_CONSTEXPR auto + _S_destroy(_Alloc2& __a, _Tp* __p, int) + noexcept(noexcept(__a.destroy(__p))) + -> decltype(__a.destroy(__p)) + { __a.destroy(__p); } + + template + static _GLIBCXX14_CONSTEXPR void + _S_destroy(_Alloc2&, _Tp* __p, ...) + noexcept(std::is_nothrow_destructible<_Tp>::value) + { std::_Destroy(__p); } + + template + static constexpr auto + _S_max_size(_Alloc2& __a, int) + -> decltype(__a.max_size()) + { return __a.max_size(); } + + template + static constexpr size_type + _S_max_size(_Alloc2&, ...) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2466. allocator_traits::max_size() default behavior is incorrect + return __gnu_cxx::__numeric_traits::__max + / sizeof(value_type); + } + + template + static constexpr auto + _S_select(_Alloc2& __a, int) + -> decltype(__a.select_on_container_copy_construction()) + { return __a.select_on_container_copy_construction(); } + + template + static constexpr _Alloc2 + _S_select(_Alloc2& __a, ...) + { return __a; } + + public: + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * + * Calls @c a.allocate(n) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(_Alloc& __a, size_type __n) + { return __a.allocate(__n); } + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * @param __hint Aid to locality. + * @return Memory of suitable size and alignment for @a n objects + * of type @c value_type + * + * Returns a.allocate(n, hint) if that expression is + * well-formed, otherwise returns @c a.allocate(n) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(_Alloc& __a, size_type __n, const_void_pointer __hint) + { return _S_allocate(__a, __n, __hint, 0); } + + /** + * @brief Deallocate memory. + * @param __a An allocator. + * @param __p Pointer to the memory to deallocate. + * @param __n The number of objects space was allocated for. + * + * Calls a.deallocate(p, n) + */ + static _GLIBCXX20_CONSTEXPR void + deallocate(_Alloc& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + /** + * @brief Construct an object of type @a _Tp + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for Tp + * @param __args Constructor arguments. + * + * Calls __a.construct(__p, std::forward(__args)...) + * if that expression is well-formed, otherwise uses placement-new + * to construct an object of type @a _Tp at location @a __p from the + * arguments @a __args... + */ + template + static _GLIBCXX20_CONSTEXPR auto + construct(_Alloc& __a, _Tp* __p, _Args&&... __args) + noexcept(noexcept(_S_construct(__a, __p, + std::forward<_Args>(__args)...))) + -> decltype(_S_construct(__a, __p, std::forward<_Args>(__args)...)) + { _S_construct(__a, __p, std::forward<_Args>(__args)...); } + + /** + * @brief Destroy an object of type @a _Tp + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Calls @c __a.destroy(__p) if that expression is well-formed, + * otherwise calls @c __p->~_Tp() + */ + template + static _GLIBCXX20_CONSTEXPR void + destroy(_Alloc& __a, _Tp* __p) + noexcept(noexcept(_S_destroy(__a, __p, 0))) + { _S_destroy(__a, __p, 0); } + + /** + * @brief The maximum supported allocation size + * @param __a An allocator. + * @return @c __a.max_size() or @c numeric_limits::max() + * + * Returns @c __a.max_size() if that expression is well-formed, + * otherwise returns @c numeric_limits::max() + */ + static _GLIBCXX20_CONSTEXPR size_type + max_size(const _Alloc& __a) noexcept + { return _S_max_size(__a, 0); } + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return @c __rhs.select_on_container_copy_construction() or @a __rhs + * + * Returns @c __rhs.select_on_container_copy_construction() if that + * expression is well-formed, otherwise returns @a __rhs + */ + static _GLIBCXX20_CONSTEXPR _Alloc + select_on_container_copy_construction(const _Alloc& __rhs) + { return _S_select(__rhs, 0); } + }; + +#if __cplusplus > 201703L +# define __cpp_lib_constexpr_dynamic_alloc 201907L +#endif + + /// Partial specialization for std::allocator. + template + struct allocator_traits> + { + /// The allocator type + using allocator_type = allocator<_Tp>; + + /// The allocated type + using value_type = _Tp; + + /// The allocator's pointer type. + using pointer = _Tp*; + + /// The allocator's const pointer type. + using const_pointer = const _Tp*; + + /// The allocator's void pointer type. + using void_pointer = void*; + + /// The allocator's const void pointer type. + using const_void_pointer = const void*; + + /// The allocator's difference type + using difference_type = std::ptrdiff_t; + + /// The allocator's size type + using size_type = std::size_t; + + /// How the allocator is propagated on copy assignment + using propagate_on_container_copy_assignment = false_type; + + /// How the allocator is propagated on move assignment + using propagate_on_container_move_assignment = true_type; + + /// How the allocator is propagated on swap + using propagate_on_container_swap = false_type; + + /// Whether all instances of the allocator type compare equal. + using is_always_equal = true_type; + + template + using rebind_alloc = allocator<_Up>; + + template + using rebind_traits = allocator_traits>; + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * + * Calls @c a.allocate(n) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(allocator_type& __a, size_type __n) + { return __a.allocate(__n); } + + /** + * @brief Allocate memory. + * @param __a An allocator. + * @param __n The number of objects to allocate space for. + * @param __hint Aid to locality. + * @return Memory of suitable size and alignment for @a n objects + * of type @c value_type + * + * Returns a.allocate(n, hint) + */ + _GLIBCXX_NODISCARD static _GLIBCXX20_CONSTEXPR pointer + allocate(allocator_type& __a, size_type __n, const_void_pointer __hint) + { +#if __cplusplus <= 201703L + return __a.allocate(__n, __hint); +#else + return __a.allocate(__n); +#endif + } + + /** + * @brief Deallocate memory. + * @param __a An allocator. + * @param __p Pointer to the memory to deallocate. + * @param __n The number of objects space was allocated for. + * + * Calls a.deallocate(p, n) + */ + static _GLIBCXX20_CONSTEXPR void + deallocate(allocator_type& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + /** + * @brief Construct an object of type `_Up` + * @param __a An allocator. + * @param __p Pointer to memory of suitable size and alignment for + * an object of type `_Up`. + * @param __args Constructor arguments. + * + * Calls `__a.construct(__p, std::forward<_Args>(__args)...)` + * in C++11, C++14 and C++17. Changed in C++20 to call + * `std::construct_at(__p, std::forward<_Args>(__args)...)` instead. + */ + template + static _GLIBCXX20_CONSTEXPR void + construct(allocator_type& __a __attribute__((__unused__)), _Up* __p, + _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { +#if __cplusplus <= 201703L + __a.construct(__p, std::forward<_Args>(__args)...); +#else + std::construct_at(__p, std::forward<_Args>(__args)...); +#endif + } + + /** + * @brief Destroy an object of type @a _Up + * @param __a An allocator. + * @param __p Pointer to the object to destroy + * + * Calls @c __a.destroy(__p). + */ + template + static _GLIBCXX20_CONSTEXPR void + destroy(allocator_type& __a __attribute__((__unused__)), _Up* __p) + noexcept(is_nothrow_destructible<_Up>::value) + { +#if __cplusplus <= 201703L + __a.destroy(__p); +#else + std::destroy_at(__p); +#endif + } + + /** + * @brief The maximum supported allocation size + * @param __a An allocator. + * @return @c __a.max_size() + */ + static _GLIBCXX20_CONSTEXPR size_type + max_size(const allocator_type& __a __attribute__((__unused__))) noexcept + { +#if __cplusplus <= 201703L + return __a.max_size(); +#else + return size_t(-1) / sizeof(value_type); +#endif + } + + /** + * @brief Obtain an allocator to use when copying a container. + * @param __rhs An allocator. + * @return @c __rhs + */ + static _GLIBCXX20_CONSTEXPR allocator_type + select_on_container_copy_construction(const allocator_type& __rhs) + { return __rhs; } + }; + +#if __cplusplus < 201703L + template + inline void + __do_alloc_on_copy(_Alloc& __one, const _Alloc& __two, true_type) + { __one = __two; } + + template + inline void + __do_alloc_on_copy(_Alloc&, const _Alloc&, false_type) + { } +#endif + + template + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_copy(_Alloc& __one, const _Alloc& __two) + { + typedef allocator_traits<_Alloc> __traits; + typedef typename __traits::propagate_on_container_copy_assignment __pocca; +#if __cplusplus >= 201703L + if constexpr (__pocca::value) + __one = __two; +#else + __do_alloc_on_copy(__one, __two, __pocca()); +#endif + } + + template + constexpr _Alloc + __alloc_on_copy(const _Alloc& __a) + { + typedef allocator_traits<_Alloc> __traits; + return __traits::select_on_container_copy_construction(__a); + } + +#if __cplusplus < 201703L + template + inline void __do_alloc_on_move(_Alloc& __one, _Alloc& __two, true_type) + { __one = std::move(__two); } + + template + inline void __do_alloc_on_move(_Alloc&, _Alloc&, false_type) + { } +#endif + + template + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_move(_Alloc& __one, _Alloc& __two) + { + typedef allocator_traits<_Alloc> __traits; + typedef typename __traits::propagate_on_container_move_assignment __pocma; +#if __cplusplus >= 201703L + if constexpr (__pocma::value) + __one = std::move(__two); +#else + __do_alloc_on_move(__one, __two, __pocma()); +#endif + } + +#if __cplusplus < 201703L + template + inline void __do_alloc_on_swap(_Alloc& __one, _Alloc& __two, true_type) + { + using std::swap; + swap(__one, __two); + } + + template + inline void __do_alloc_on_swap(_Alloc&, _Alloc&, false_type) + { } +#endif + + template + _GLIBCXX14_CONSTEXPR inline void + __alloc_on_swap(_Alloc& __one, _Alloc& __two) + { + typedef allocator_traits<_Alloc> __traits; + typedef typename __traits::propagate_on_container_swap __pocs; +#if __cplusplus >= 201703L + if constexpr (__pocs::value) + { + using std::swap; + swap(__one, __two); + } +#else + __do_alloc_on_swap(__one, __two, __pocs()); +#endif + } + + template, + typename = void> + struct __is_alloc_insertable_impl + : false_type + { }; + + template + struct __is_alloc_insertable_impl<_Alloc, _Tp, _ValueT, + __void_t::construct( + std::declval<_Alloc&>(), std::declval<_ValueT*>(), + std::declval<_Tp>()))>> + : true_type + { }; + + // true if _Alloc::value_type is CopyInsertable into containers using _Alloc + // (might be wrong if _Alloc::construct exists but is not constrained, + // i.e. actually trying to use it would still be invalid. Use with caution.) + template + struct __is_copy_insertable + : __is_alloc_insertable_impl<_Alloc, + typename _Alloc::value_type const&>::type + { }; + + // std::allocator<_Tp> just requires CopyConstructible + template + struct __is_copy_insertable> + : is_copy_constructible<_Tp> + { }; + + // true if _Alloc::value_type is MoveInsertable into containers using _Alloc + // (might be wrong if _Alloc::construct exists but is not constrained, + // i.e. actually trying to use it would still be invalid. Use with caution.) + template + struct __is_move_insertable + : __is_alloc_insertable_impl<_Alloc, typename _Alloc::value_type>::type + { }; + + // std::allocator<_Tp> just requires MoveConstructible + template + struct __is_move_insertable> + : is_move_constructible<_Tp> + { }; + + // Trait to detect Allocator-like types. + template + struct __is_allocator : false_type { }; + + template + struct __is_allocator<_Alloc, + __void_t().allocate(size_t{}))>> + : true_type { }; + + template + using _RequireAllocator + = typename enable_if<__is_allocator<_Alloc>::value, _Alloc>::type; + + template + using _RequireNotAllocator + = typename enable_if::value, _Alloc>::type; +#endif // C++11 + + /** + * Destroy a range of objects using the supplied allocator. For + * non-default allocators we do not optimize away invocation of + * destroy() even if _Tp has a trivial destructor. + */ + + template + void + _Destroy(_ForwardIterator __first, _ForwardIterator __last, + _Allocator& __alloc) + { + for (; __first != __last; ++__first) +#if __cplusplus < 201103L + __alloc.destroy(std::__addressof(*__first)); +#else + allocator_traits<_Allocator>::destroy(__alloc, + std::__addressof(*__first)); +#endif + } + + template + inline void + _Destroy(_ForwardIterator __first, _ForwardIterator __last, + allocator<_Tp>&) + { + _Destroy(__first, __last); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // _ALLOC_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h b/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h new file mode 100644 index 000000000..5058ab084 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/allocated_ptr.h @@ -0,0 +1,104 @@ +// Guarded Allocation -*- C++ -*- + +// Copyright (C) 2014-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/allocated_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOCATED_PTR_H +#define _ALLOCATED_PTR_H 1 + +#if __cplusplus < 201103L +# include +#else +# include +# include +# include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Non-standard RAII type for managing pointers obtained from allocators. + template + struct __allocated_ptr + { + using pointer = typename allocator_traits<_Alloc>::pointer; + using value_type = typename allocator_traits<_Alloc>::value_type; + + /// Take ownership of __ptr + __allocated_ptr(_Alloc& __a, pointer __ptr) noexcept + : _M_alloc(std::__addressof(__a)), _M_ptr(__ptr) + { } + + /// Convert __ptr to allocator's pointer type and take ownership of it + template>> + __allocated_ptr(_Alloc& __a, _Ptr __ptr) + : _M_alloc(std::__addressof(__a)), + _M_ptr(pointer_traits::pointer_to(*__ptr)) + { } + + /// Transfer ownership of the owned pointer + __allocated_ptr(__allocated_ptr&& __gd) noexcept + : _M_alloc(__gd._M_alloc), _M_ptr(__gd._M_ptr) + { __gd._M_ptr = nullptr; } + + /// Deallocate the owned pointer + ~__allocated_ptr() + { + if (_M_ptr != nullptr) + std::allocator_traits<_Alloc>::deallocate(*_M_alloc, _M_ptr, 1); + } + + /// Release ownership of the owned pointer + __allocated_ptr& + operator=(std::nullptr_t) noexcept + { + _M_ptr = nullptr; + return *this; + } + + /// Get the address that the owned pointer refers to. + value_type* get() { return std::__to_address(_M_ptr); } + + private: + _Alloc* _M_alloc; + pointer _M_ptr; + }; + + /// Allocate space for a single object using __a + template + __allocated_ptr<_Alloc> + __allocate_guarded(_Alloc& __a) + { + return { __a, std::allocator_traits<_Alloc>::allocate(__a, 1) }; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/allocator.h b/resources/sources/avr-libstdcpp/include/bits/allocator.h new file mode 100644 index 000000000..d224aa3ec --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/allocator.h @@ -0,0 +1,323 @@ +// Allocators -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/allocator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _ALLOCATOR_H +#define _ALLOCATOR_H 1 + +#include // Define the base class to std::allocator. +#include +#if __cplusplus >= 201103L +#include +#endif + +#define __cpp_lib_incomplete_container_elements 201505 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup allocators + * @{ + */ + + /// allocator specialization. + template<> + class allocator + { + public: + typedef void value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; +#if __cplusplus <= 201703L + typedef void* pointer; + typedef const void* const_pointer; + + template + struct rebind + { typedef allocator<_Tp1> other; }; +#else + allocator() = default; + + template + constexpr + allocator(const allocator<_Up>&) { } +#endif // ! C++20 + +#if __cplusplus >= 201103L && __cplusplus <= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. std::allocator propagate_on_container_move_assignment + typedef true_type propagate_on_container_move_assignment; + + typedef true_type is_always_equal; + + template + void + construct(_Up* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } + + template + void + destroy(_Up* __p) + noexcept(std::is_nothrow_destructible<_Up>::value) + { __p->~_Up(); } +#endif // C++11 to C++17 + }; + + /** + * @brief The @a standard allocator, as per [20.4]. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/memory.html#std.util.memory.allocator + * for further details. + * + * @tparam _Tp Type of allocated object. + */ + template + class allocator : public __allocator_base<_Tp> + { + public: + typedef _Tp value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; +#if __cplusplus <= 201703L + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + + template + struct rebind + { typedef allocator<_Tp1> other; }; +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. std::allocator propagate_on_container_move_assignment + typedef true_type propagate_on_container_move_assignment; + + typedef true_type is_always_equal; +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3035. std::allocator's constructors should be constexpr + _GLIBCXX20_CONSTEXPR + allocator() _GLIBCXX_NOTHROW { } + + _GLIBCXX20_CONSTEXPR + allocator(const allocator& __a) _GLIBCXX_NOTHROW + : __allocator_base<_Tp>(__a) { } + +#if __cplusplus >= 201103L + // Avoid implicit deprecation. + allocator& operator=(const allocator&) = default; +#endif + + template + _GLIBCXX20_CONSTEXPR + allocator(const allocator<_Tp1>&) _GLIBCXX_NOTHROW { } + +#if __cpp_constexpr_dynamic_alloc + constexpr +#endif + ~allocator() _GLIBCXX_NOTHROW { } + +#if __cplusplus > 201703L + [[nodiscard,__gnu__::__always_inline__]] + constexpr _Tp* + allocate(size_t __n) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); +#endif + return __allocator_base<_Tp>::allocate(__n, 0); + } + + [[__gnu__::__always_inline__]] + constexpr void + deallocate(_Tp* __p, size_t __n) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + ::operator delete(__p); + return; + } +#endif + __allocator_base<_Tp>::deallocate(__p, __n); + } +#endif // C++20 + + friend _GLIBCXX20_CONSTEXPR bool + operator==(const allocator&, const allocator&) _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + friend _GLIBCXX20_CONSTEXPR bool + operator!=(const allocator&, const allocator&) _GLIBCXX_NOTHROW + { return false; } +#endif + + // Inherit everything else. + }; + + template + inline _GLIBCXX20_CONSTEXPR bool + operator==(const allocator<_T1>&, const allocator<_T2>&) + _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline _GLIBCXX20_CONSTEXPR bool + operator!=(const allocator<_T1>&, const allocator<_T2>&) + _GLIBCXX_NOTHROW + { return false; } +#endif + + // Invalid allocator partial specializations. + // allocator_traits::rebind_alloc can be used to form a valid allocator type. + template + class allocator + { + public: + typedef _Tp value_type; + template allocator(const allocator<_Up>&) { } + }; + + template + class allocator + { + public: + typedef _Tp value_type; + template allocator(const allocator<_Up>&) { } + }; + + template + class allocator + { + public: + typedef _Tp value_type; + template allocator(const allocator<_Up>&) { } + }; + + /// @} group allocator + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. +#if _GLIBCXX_EXTERN_TEMPLATE + extern template class allocator; + extern template class allocator; +#endif + + // Undefine. +#undef __allocator_base + + // To implement Option 3 of DR 431. + template + struct __alloc_swap + { static void _S_do_it(_Alloc&, _Alloc&) _GLIBCXX_NOEXCEPT { } }; + + template + struct __alloc_swap<_Alloc, false> + { + static void + _S_do_it(_Alloc& __one, _Alloc& __two) _GLIBCXX_NOEXCEPT + { + // Precondition: swappable allocators. + if (__one != __two) + swap(__one, __two); + } + }; + + // Optimize for stateless allocators. + template + struct __alloc_neq + { + static bool + _S_do_it(const _Alloc&, const _Alloc&) + { return false; } + }; + + template + struct __alloc_neq<_Alloc, false> + { + static bool + _S_do_it(const _Alloc& __one, const _Alloc& __two) + { return __one != __two; } + }; + +#if __cplusplus >= 201103L + template, + is_nothrow_move_constructible>::value> + struct __shrink_to_fit_aux + { static bool _S_do_it(_Tp&) noexcept { return false; } }; + + template + struct __shrink_to_fit_aux<_Tp, true> + { + static bool + _S_do_it(_Tp& __c) noexcept + { +#if __cpp_exceptions + try + { + _Tp(__make_move_if_noexcept_iterator(__c.begin()), + __make_move_if_noexcept_iterator(__c.end()), + __c.get_allocator()).swap(__c); + return true; + } + catch(...) + { return false; } +#else + return false; +#endif + } + }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/atomic_base.h b/resources/sources/avr-libstdcpp/include/bits/atomic_base.h new file mode 100644 index 000000000..b11de1edf --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/atomic_base.h @@ -0,0 +1,1724 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/atomic_base.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{atomic} + */ + +#ifndef _GLIBCXX_ATOMIC_BASE_H +#define _GLIBCXX_ATOMIC_BASE_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include + +#ifndef _GLIBCXX_ALWAYS_INLINE +#define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup atomics Atomics + * + * Components for performing atomic operations. + * @{ + */ + + /// Enumeration for memory_order +#if __cplusplus > 201703L + enum class memory_order : int + { + relaxed, + consume, + acquire, + release, + acq_rel, + seq_cst + }; + + inline constexpr memory_order memory_order_relaxed = memory_order::relaxed; + inline constexpr memory_order memory_order_consume = memory_order::consume; + inline constexpr memory_order memory_order_acquire = memory_order::acquire; + inline constexpr memory_order memory_order_release = memory_order::release; + inline constexpr memory_order memory_order_acq_rel = memory_order::acq_rel; + inline constexpr memory_order memory_order_seq_cst = memory_order::seq_cst; +#else + typedef enum memory_order + { + memory_order_relaxed, + memory_order_consume, + memory_order_acquire, + memory_order_release, + memory_order_acq_rel, + memory_order_seq_cst + } memory_order; +#endif + + enum __memory_order_modifier + { + __memory_order_mask = 0x0ffff, + __memory_order_modifier_mask = 0xffff0000, + __memory_order_hle_acquire = 0x10000, + __memory_order_hle_release = 0x20000 + }; + + constexpr memory_order + operator|(memory_order __m, __memory_order_modifier __mod) + { + return memory_order(int(__m) | int(__mod)); + } + + constexpr memory_order + operator&(memory_order __m, __memory_order_modifier __mod) + { + return memory_order(int(__m) & int(__mod)); + } + + // Drop release ordering as per [atomics.types.operations.req]/21 + constexpr memory_order + __cmpexch_failure_order2(memory_order __m) noexcept + { + return __m == memory_order_acq_rel ? memory_order_acquire + : __m == memory_order_release ? memory_order_relaxed : __m; + } + + constexpr memory_order + __cmpexch_failure_order(memory_order __m) noexcept + { + return memory_order(__cmpexch_failure_order2(__m & __memory_order_mask) + | __memory_order_modifier(__m & __memory_order_modifier_mask)); + } + + _GLIBCXX_ALWAYS_INLINE void + atomic_thread_fence(memory_order __m) noexcept + { __atomic_thread_fence(int(__m)); } + + _GLIBCXX_ALWAYS_INLINE void + atomic_signal_fence(memory_order __m) noexcept + { __atomic_signal_fence(int(__m)); } + + /// kill_dependency + template + inline _Tp + kill_dependency(_Tp __y) noexcept + { + _Tp __ret(__y); + return __ret; + } + + + // Base types for atomics. + template + struct __atomic_base; + +#if __cplusplus <= 201703L +# define _GLIBCXX20_INIT(I) +#else +# define __cpp_lib_atomic_value_initialization 201911L +# define _GLIBCXX20_INIT(I) = I +#endif + +#define ATOMIC_VAR_INIT(_VI) { _VI } + + template + struct atomic; + + template + struct atomic<_Tp*>; + + /* The target's "set" value for test-and-set may not be exactly 1. */ +#if __GCC_ATOMIC_TEST_AND_SET_TRUEVAL == 1 + typedef bool __atomic_flag_data_type; +#else + typedef unsigned char __atomic_flag_data_type; +#endif + + /** + * @brief Base type for atomic_flag. + * + * Base type is POD with data, allowing atomic_flag to derive from + * it and meet the standard layout type requirement. In addition to + * compatibility with a C interface, this allows different + * implementations of atomic_flag to use the same atomic operation + * functions, via a standard conversion to the __atomic_flag_base + * argument. + */ + _GLIBCXX_BEGIN_EXTERN_C + + struct __atomic_flag_base + { + __atomic_flag_data_type _M_i _GLIBCXX20_INIT({}); + }; + + _GLIBCXX_END_EXTERN_C + +#define ATOMIC_FLAG_INIT { 0 } + + /// atomic_flag + struct atomic_flag : public __atomic_flag_base + { + atomic_flag() noexcept = default; + ~atomic_flag() noexcept = default; + atomic_flag(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) = delete; + atomic_flag& operator=(const atomic_flag&) volatile = delete; + + // Conversion to ATOMIC_FLAG_INIT. + constexpr atomic_flag(bool __i) noexcept + : __atomic_flag_base{ _S_init(__i) } + { } + + _GLIBCXX_ALWAYS_INLINE bool + test_and_set(memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_test_and_set (&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + test_and_set(memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_test_and_set (&_M_i, int(__m)); + } + +#if __cplusplus > 201703L +#define __cpp_lib_atomic_flag_test 201907L + + _GLIBCXX_ALWAYS_INLINE bool + test(memory_order __m = memory_order_seq_cst) const noexcept + { + __atomic_flag_data_type __v; + __atomic_load(&_M_i, &__v, int(__m)); + return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; + } + + _GLIBCXX_ALWAYS_INLINE bool + test(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + __atomic_flag_data_type __v; + __atomic_load(&_M_i, &__v, int(__m)); + return __v == __GCC_ATOMIC_TEST_AND_SET_TRUEVAL; + } + +#endif // C++20 + + _GLIBCXX_ALWAYS_INLINE void + clear(memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_consume); + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + + __atomic_clear (&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + clear(memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_consume); + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + + __atomic_clear (&_M_i, int(__m)); + } + + private: + static constexpr __atomic_flag_data_type + _S_init(bool __i) + { return __i ? __GCC_ATOMIC_TEST_AND_SET_TRUEVAL : 0; } + }; + + + /// Base class for atomic integrals. + // + // For each of the integral types, define atomic_[integral type] struct + // + // atomic_bool bool + // atomic_char char + // atomic_schar signed char + // atomic_uchar unsigned char + // atomic_short short + // atomic_ushort unsigned short + // atomic_int int + // atomic_uint unsigned int + // atomic_long long + // atomic_ulong unsigned long + // atomic_llong long long + // atomic_ullong unsigned long long + // atomic_char8_t char8_t + // atomic_char16_t char16_t + // atomic_char32_t char32_t + // atomic_wchar_t wchar_t + // + // NB: Assuming _ITp is an integral scalar type that is 1, 2, 4, or + // 8 bytes, since that is what GCC built-in functions for atomic + // memory access expect. + template + struct __atomic_base + { + using value_type = _ITp; + using difference_type = value_type; + + private: + typedef _ITp __int_type; + + static constexpr int _S_alignment = + sizeof(_ITp) > alignof(_ITp) ? sizeof(_ITp) : alignof(_ITp); + + alignas(_S_alignment) __int_type _M_i _GLIBCXX20_INIT(0); + + public: + __atomic_base() noexcept = default; + ~__atomic_base() noexcept = default; + __atomic_base(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) volatile = delete; + + // Requires __int_type convertible to _M_i. + constexpr __atomic_base(__int_type __i) noexcept : _M_i (__i) { } + + operator __int_type() const noexcept + { return load(); } + + operator __int_type() const volatile noexcept + { return load(); } + + __int_type + operator=(__int_type __i) noexcept + { + store(__i); + return __i; + } + + __int_type + operator=(__int_type __i) volatile noexcept + { + store(__i); + return __i; + } + + __int_type + operator++(int) noexcept + { return fetch_add(1); } + + __int_type + operator++(int) volatile noexcept + { return fetch_add(1); } + + __int_type + operator--(int) noexcept + { return fetch_sub(1); } + + __int_type + operator--(int) volatile noexcept + { return fetch_sub(1); } + + __int_type + operator++() noexcept + { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator++() volatile noexcept + { return __atomic_add_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator--() noexcept + { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator--() volatile noexcept + { return __atomic_sub_fetch(&_M_i, 1, int(memory_order_seq_cst)); } + + __int_type + operator+=(__int_type __i) noexcept + { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator+=(__int_type __i) volatile noexcept + { return __atomic_add_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator-=(__int_type __i) noexcept + { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator-=(__int_type __i) volatile noexcept + { return __atomic_sub_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator&=(__int_type __i) noexcept + { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator&=(__int_type __i) volatile noexcept + { return __atomic_and_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator|=(__int_type __i) noexcept + { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator|=(__int_type __i) volatile noexcept + { return __atomic_or_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator^=(__int_type __i) noexcept + { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + __int_type + operator^=(__int_type __i) volatile noexcept + { return __atomic_xor_fetch(&_M_i, __i, int(memory_order_seq_cst)); } + + bool + is_lock_free() const noexcept + { + // Use a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + bool + is_lock_free() const volatile noexcept + { + // Use a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_i), + reinterpret_cast(-_S_alignment)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__int_type __i, memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + exchange(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_exchange_n(&_M_i, __i, int(__m)); + } + + + _GLIBCXX_ALWAYS_INLINE __int_type + exchange(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_exchange_n(&_M_i, __i, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m1, memory_order __m2) noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 1, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_weak(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_weak(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m1, memory_order __m2) noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_i, &__i1, __i2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) noexcept + { + return compare_exchange_strong(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__int_type& __i1, __int_type __i2, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return compare_exchange_strong(__i1, __i2, __m, + __cmpexch_failure_order(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_add(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_add(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_add(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_add(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_sub(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_sub(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_sub(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_and(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_and(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_and(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_and(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_or(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_or(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_or(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_or(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_xor(__int_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __int_type + fetch_xor(__int_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_xor(&_M_i, __i, int(__m)); } + }; + + + /// Partial specialization for pointer types. + template + struct __atomic_base<_PTp*> + { + private: + typedef _PTp* __pointer_type; + + __pointer_type _M_p _GLIBCXX20_INIT(nullptr); + + // Factored out to facilitate explicit specialization. + constexpr ptrdiff_t + _M_type_size(ptrdiff_t __d) const { return __d * sizeof(_PTp); } + + constexpr ptrdiff_t + _M_type_size(ptrdiff_t __d) const volatile { return __d * sizeof(_PTp); } + + public: + __atomic_base() noexcept = default; + ~__atomic_base() noexcept = default; + __atomic_base(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) = delete; + __atomic_base& operator=(const __atomic_base&) volatile = delete; + + // Requires __pointer_type convertible to _M_p. + constexpr __atomic_base(__pointer_type __p) noexcept : _M_p (__p) { } + + operator __pointer_type() const noexcept + { return load(); } + + operator __pointer_type() const volatile noexcept + { return load(); } + + __pointer_type + operator=(__pointer_type __p) noexcept + { + store(__p); + return __p; + } + + __pointer_type + operator=(__pointer_type __p) volatile noexcept + { + store(__p); + return __p; + } + + __pointer_type + operator++(int) noexcept + { return fetch_add(1); } + + __pointer_type + operator++(int) volatile noexcept + { return fetch_add(1); } + + __pointer_type + operator--(int) noexcept + { return fetch_sub(1); } + + __pointer_type + operator--(int) volatile noexcept + { return fetch_sub(1); } + + __pointer_type + operator++() noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator++() volatile noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator--() noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator--() volatile noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(1), + int(memory_order_seq_cst)); } + + __pointer_type + operator+=(ptrdiff_t __d) noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator+=(ptrdiff_t __d) volatile noexcept + { return __atomic_add_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator-=(ptrdiff_t __d) noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + __pointer_type + operator-=(ptrdiff_t __d) volatile noexcept + { return __atomic_sub_fetch(&_M_p, _M_type_size(__d), + int(memory_order_seq_cst)); } + + bool + is_lock_free() const noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_p), + reinterpret_cast(-__alignof(_M_p))); + } + + bool + is_lock_free() const volatile noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(sizeof(_M_p), + reinterpret_cast(-__alignof(_M_p))); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { + memory_order __b = __m & __memory_order_mask; + + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE void + store(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_acquire); + __glibcxx_assert(__b != memory_order_acq_rel); + __glibcxx_assert(__b != memory_order_consume); + + __atomic_store_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + load(memory_order __m = memory_order_seq_cst) const noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { + memory_order __b = __m & __memory_order_mask; + __glibcxx_assert(__b != memory_order_release); + __glibcxx_assert(__b != memory_order_acq_rel); + + return __atomic_load_n(&_M_p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) noexcept + { + return __atomic_exchange_n(&_M_p, __p, int(__m)); + } + + + _GLIBCXX_ALWAYS_INLINE __pointer_type + exchange(__pointer_type __p, + memory_order __m = memory_order_seq_cst) volatile noexcept + { + return __atomic_exchange_n(&_M_p, __p, int(__m)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(__pointer_type& __p1, __pointer_type __p2, + memory_order __m1, + memory_order __m2) volatile noexcept + { + memory_order __b2 = __m2 & __memory_order_mask; + memory_order __b1 = __m1 & __memory_order_mask; + + __glibcxx_assert(__b2 != memory_order_release); + __glibcxx_assert(__b2 != memory_order_acq_rel); + __glibcxx_assert(__b2 <= __b1); + + return __atomic_compare_exchange_n(&_M_p, &__p1, __p2, 0, + int(__m1), int(__m2)); + } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_add(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_add(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } + + _GLIBCXX_ALWAYS_INLINE __pointer_type + fetch_sub(ptrdiff_t __d, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_fetch_sub(&_M_p, _M_type_size(__d), int(__m)); } + }; + +#if __cplusplus > 201703L + // Implementation details of atomic_ref and atomic. + namespace __atomic_impl + { + // Remove volatile and create a non-deduced context for value arguments. + template + using _Val = remove_volatile_t<_Tp>; + + // As above, but for difference_type arguments. + template + using _Diff = conditional_t, ptrdiff_t, _Val<_Tp>>; + + template + _GLIBCXX_ALWAYS_INLINE bool + is_lock_free() noexcept + { + // Produce a fake, minimally aligned pointer. + return __atomic_is_lock_free(_Size, reinterpret_cast(-_Align)); + } + + template + _GLIBCXX_ALWAYS_INLINE void + store(_Tp* __ptr, _Val<_Tp> __t, memory_order __m) noexcept + { __atomic_store(__ptr, std::__addressof(__t), int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Val<_Tp> + load(const _Tp* __ptr, memory_order __m) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); + __atomic_load(__ptr, __dest, int(__m)); + return *__dest; + } + + template + _GLIBCXX_ALWAYS_INLINE _Val<_Tp> + exchange(_Tp* __ptr, _Val<_Tp> __desired, memory_order __m) noexcept + { + alignas(_Tp) unsigned char __buf[sizeof(_Tp)]; + auto* __dest = reinterpret_cast<_Val<_Tp>*>(__buf); + __atomic_exchange(__ptr, std::__addressof(__desired), __dest, int(__m)); + return *__dest; + } + + template + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_weak(_Tp* __ptr, _Val<_Tp>& __expected, + _Val<_Tp> __desired, memory_order __success, + memory_order __failure) noexcept + { + return __atomic_compare_exchange(__ptr, std::__addressof(__expected), + std::__addressof(__desired), true, + int(__success), int(__failure)); + } + + template + _GLIBCXX_ALWAYS_INLINE bool + compare_exchange_strong(_Tp* __ptr, _Val<_Tp>& __expected, + _Val<_Tp> __desired, memory_order __success, + memory_order __failure) noexcept + { + return __atomic_compare_exchange(__ptr, std::__addressof(__expected), + std::__addressof(__desired), false, + int(__success), int(__failure)); + } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_add(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_add(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_sub(_Tp* __ptr, _Diff<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_sub(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_and(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_and(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_or(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_or(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + fetch_xor(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { return __atomic_fetch_xor(__ptr, __i, int(__m)); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __add_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept + { return __atomic_add_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __sub_fetch(_Tp* __ptr, _Diff<_Tp> __i) noexcept + { return __atomic_sub_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __and_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_and_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __or_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_or_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _GLIBCXX_ALWAYS_INLINE _Tp + __xor_fetch(_Tp* __ptr, _Val<_Tp> __i) noexcept + { return __atomic_xor_fetch(__ptr, __i, __ATOMIC_SEQ_CST); } + + template + _Tp + __fetch_add_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval + __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, + memory_order_relaxed)) + __newval = __oldval + __i; + return __oldval; + } + + template + _Tp + __fetch_sub_flt(_Tp* __ptr, _Val<_Tp> __i, memory_order __m) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval - __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, __m, + memory_order_relaxed)) + __newval = __oldval - __i; + return __oldval; + } + + template + _Tp + __add_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval + __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, + memory_order_seq_cst, + memory_order_relaxed)) + __newval = __oldval + __i; + return __newval; + } + + template + _Tp + __sub_fetch_flt(_Tp* __ptr, _Val<_Tp> __i) noexcept + { + _Val<_Tp> __oldval = load(__ptr, memory_order_relaxed); + _Val<_Tp> __newval = __oldval - __i; + while (!compare_exchange_weak(__ptr, __oldval, __newval, + memory_order_seq_cst, + memory_order_relaxed)) + __newval = __oldval - __i; + return __newval; + } + } // namespace __atomic_impl + + // base class for atomic + template + struct __atomic_float + { + static_assert(is_floating_point_v<_Fp>); + + static constexpr size_t _S_alignment = __alignof__(_Fp); + + public: + using value_type = _Fp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Fp), 0); + + __atomic_float() = default; + + constexpr + __atomic_float(_Fp __t) : _M_fp(__t) + { } + + __atomic_float(const __atomic_float&) = delete; + __atomic_float& operator=(const __atomic_float&) = delete; + __atomic_float& operator=(const __atomic_float&) volatile = delete; + + _Fp + operator=(_Fp __t) volatile noexcept + { + this->store(__t); + return __t; + } + + _Fp + operator=(_Fp __t) noexcept + { + this->store(__t); + return __t; + } + + bool + is_lock_free() const volatile noexcept + { return __atomic_impl::is_lock_free(); } + + bool + is_lock_free() const noexcept + { return __atomic_impl::is_lock_free(); } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) volatile noexcept + { __atomic_impl::store(&_M_fp, __t, __m); } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) noexcept + { __atomic_impl::store(&_M_fp, __t, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const volatile noexcept + { return __atomic_impl::load(&_M_fp, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(&_M_fp, __m); } + + operator _Fp() const volatile noexcept { return this->load(); } + operator _Fp() const noexcept { return this->load(); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::exchange(&_M_fp, __desired, __m); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::exchange(&_M_fp, __desired, __m); } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) noexcept + { + return __atomic_impl::compare_exchange_weak(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) volatile noexcept + { + return __atomic_impl::compare_exchange_weak(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) noexcept + { + return __atomic_impl::compare_exchange_strong(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) volatile noexcept + { + return __atomic_impl::compare_exchange_strong(&_M_fp, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + volatile noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + volatile noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::__fetch_add_flt(&_M_fp, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) noexcept + { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) volatile noexcept + { return __atomic_impl::__fetch_sub_flt(&_M_fp, __i, __m); } + + value_type + operator+=(value_type __i) noexcept + { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } + + value_type + operator+=(value_type __i) volatile noexcept + { return __atomic_impl::__add_fetch_flt(&_M_fp, __i); } + + value_type + operator-=(value_type __i) noexcept + { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } + + value_type + operator-=(value_type __i) volatile noexcept + { return __atomic_impl::__sub_fetch_flt(&_M_fp, __i); } + + private: + alignas(_S_alignment) _Fp _M_fp _GLIBCXX20_INIT(0); + }; +#undef _GLIBCXX20_INIT + + template, bool = is_floating_point_v<_Tp>> + struct __atomic_ref; + + // base class for non-integral, non-floating-point, non-pointer types + template + struct __atomic_ref<_Tp, false, false> + { + static_assert(is_trivially_copyable_v<_Tp>); + + // 1/2/4/8/16-byte types must be aligned to at least their size. + static constexpr int _S_min_alignment + = (sizeof(_Tp) & (sizeof(_Tp) - 1)) || sizeof(_Tp) > 16 + ? 0 : sizeof(_Tp); + + public: + using value_type = _Tp; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Tp), 0); + + static constexpr size_t required_alignment + = _S_min_alignment > alignof(_Tp) ? _S_min_alignment : alignof(_Tp); + + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp& __t) : _M_ptr(std::__addressof(__t)) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp + operator=(_Tp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { return __atomic_impl::is_lock_free(); } + + void + store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp + exchange(_Tp __desired, memory_order __m = memory_order_seq_cst) + const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + private: + _Tp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Tp, true, false> + { + static_assert(is_integral_v<_Tp>); + + public: + using value_type = _Tp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Tp), 0); + + static constexpr size_t required_alignment + = sizeof(_Tp) > alignof(_Tp) ? sizeof(_Tp) : alignof(_Tp); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp& __t) : _M_ptr(&__t) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp + operator=(_Tp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Tp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp + exchange(_Tp __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp& __expected, _Tp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_add(_M_ptr, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_sub(_M_ptr, __i, __m); } + + value_type + fetch_and(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_and(_M_ptr, __i, __m); } + + value_type + fetch_or(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_or(_M_ptr, __i, __m); } + + value_type + fetch_xor(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_xor(_M_ptr, __i, __m); } + + _GLIBCXX_ALWAYS_INLINE value_type + operator++(int) const noexcept + { return fetch_add(1); } + + _GLIBCXX_ALWAYS_INLINE value_type + operator--(int) const noexcept + { return fetch_sub(1); } + + value_type + operator++() const noexcept + { return __atomic_impl::__add_fetch(_M_ptr, value_type(1)); } + + value_type + operator--() const noexcept + { return __atomic_impl::__sub_fetch(_M_ptr, value_type(1)); } + + value_type + operator+=(value_type __i) const noexcept + { return __atomic_impl::__add_fetch(_M_ptr, __i); } + + value_type + operator-=(value_type __i) const noexcept + { return __atomic_impl::__sub_fetch(_M_ptr, __i); } + + value_type + operator&=(value_type __i) const noexcept + { return __atomic_impl::__and_fetch(_M_ptr, __i); } + + value_type + operator|=(value_type __i) const noexcept + { return __atomic_impl::__or_fetch(_M_ptr, __i); } + + value_type + operator^=(value_type __i) const noexcept + { return __atomic_impl::__xor_fetch(_M_ptr, __i); } + + private: + _Tp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Fp, false, true> + { + static_assert(is_floating_point_v<_Fp>); + + public: + using value_type = _Fp; + using difference_type = value_type; + + static constexpr bool is_always_lock_free + = __atomic_always_lock_free(sizeof(_Fp), 0); + + static constexpr size_t required_alignment = __alignof__(_Fp); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Fp& __t) : _M_ptr(&__t) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Fp + operator=(_Fp __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Fp() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Fp __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Fp + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Fp + exchange(_Fp __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Fp& __expected, _Fp __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + value_type + fetch_add(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::__fetch_add_flt(_M_ptr, __i, __m); } + + value_type + fetch_sub(value_type __i, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::__fetch_sub_flt(_M_ptr, __i, __m); } + + value_type + operator+=(value_type __i) const noexcept + { return __atomic_impl::__add_fetch_flt(_M_ptr, __i); } + + value_type + operator-=(value_type __i) const noexcept + { return __atomic_impl::__sub_fetch_flt(_M_ptr, __i); } + + private: + _Fp* _M_ptr; + }; + + // base class for atomic_ref + template + struct __atomic_ref<_Tp*, false, false> + { + public: + using value_type = _Tp*; + using difference_type = ptrdiff_t; + + static constexpr bool is_always_lock_free = ATOMIC_POINTER_LOCK_FREE == 2; + + static constexpr size_t required_alignment = __alignof__(_Tp*); + + __atomic_ref() = delete; + __atomic_ref& operator=(const __atomic_ref&) = delete; + + explicit + __atomic_ref(_Tp*& __t) : _M_ptr(std::__addressof(__t)) + { __glibcxx_assert(((uintptr_t)_M_ptr % required_alignment) == 0); } + + __atomic_ref(const __atomic_ref&) noexcept = default; + + _Tp* + operator=(_Tp* __t) const noexcept + { + this->store(__t); + return __t; + } + + operator _Tp*() const noexcept { return this->load(); } + + bool + is_lock_free() const noexcept + { + return __atomic_impl::is_lock_free(); + } + + void + store(_Tp* __t, memory_order __m = memory_order_seq_cst) const noexcept + { __atomic_impl::store(_M_ptr, __t, __m); } + + _Tp* + load(memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::load(_M_ptr, __m); } + + _Tp* + exchange(_Tp* __desired, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::exchange(_M_ptr, __desired, __m); } + + bool + compare_exchange_weak(_Tp*& __expected, _Tp* __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_weak(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_strong(_Tp*& __expected, _Tp* __desired, + memory_order __success, + memory_order __failure) const noexcept + { + return __atomic_impl::compare_exchange_strong(_M_ptr, + __expected, __desired, + __success, __failure); + } + + bool + compare_exchange_weak(_Tp*& __expected, _Tp* __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_weak(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + bool + compare_exchange_strong(_Tp*& __expected, _Tp* __desired, + memory_order __order = memory_order_seq_cst) + const noexcept + { + return compare_exchange_strong(__expected, __desired, __order, + __cmpexch_failure_order(__order)); + } + + _GLIBCXX_ALWAYS_INLINE value_type + fetch_add(difference_type __d, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_add(_M_ptr, _S_type_size(__d), __m); } + + _GLIBCXX_ALWAYS_INLINE value_type + fetch_sub(difference_type __d, + memory_order __m = memory_order_seq_cst) const noexcept + { return __atomic_impl::fetch_sub(_M_ptr, _S_type_size(__d), __m); } + + value_type + operator++(int) const noexcept + { return fetch_add(1); } + + value_type + operator--(int) const noexcept + { return fetch_sub(1); } + + value_type + operator++() const noexcept + { + return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(1)); + } + + value_type + operator--() const noexcept + { + return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(1)); + } + + value_type + operator+=(difference_type __d) const noexcept + { + return __atomic_impl::__add_fetch(_M_ptr, _S_type_size(__d)); + } + + value_type + operator-=(difference_type __d) const noexcept + { + return __atomic_impl::__sub_fetch(_M_ptr, _S_type_size(__d)); + } + + private: + static constexpr ptrdiff_t + _S_type_size(ptrdiff_t __d) noexcept + { + static_assert(is_object_v<_Tp>); + return __d * sizeof(_Tp); + } + + _Tp** _M_ptr; + }; + +#endif // C++2a + + // @} group atomics + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h b/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h new file mode 100644 index 000000000..f0b57aeee --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/atomic_lockfree_defines.h @@ -0,0 +1,66 @@ +// -*- C++ -*- header. + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/atomic_lockfree_defines.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{atomic} + */ + +#ifndef _GLIBCXX_ATOMIC_LOCK_FREE_H +#define _GLIBCXX_ATOMIC_LOCK_FREE_H 1 + +#pragma GCC system_header + +/** + * @addtogroup atomics + * @{ + */ + +/** + * Lock-free property. + * + * 0 indicates that the types are never lock-free. + * 1 indicates that the types are sometimes lock-free. + * 2 indicates that the types are always lock-free. + */ + +#if __cplusplus >= 201103L +#define ATOMIC_BOOL_LOCK_FREE __GCC_ATOMIC_BOOL_LOCK_FREE +#define ATOMIC_CHAR_LOCK_FREE __GCC_ATOMIC_CHAR_LOCK_FREE +#define ATOMIC_WCHAR_T_LOCK_FREE __GCC_ATOMIC_WCHAR_T_LOCK_FREE +#ifdef _GLIBCXX_USE_CHAR8_T +#define ATOMIC_CHAR8_T_LOCK_FREE __GCC_ATOMIC_CHAR8_T_LOCK_FREE +#endif +#define ATOMIC_CHAR16_T_LOCK_FREE __GCC_ATOMIC_CHAR16_T_LOCK_FREE +#define ATOMIC_CHAR32_T_LOCK_FREE __GCC_ATOMIC_CHAR32_T_LOCK_FREE +#define ATOMIC_SHORT_LOCK_FREE __GCC_ATOMIC_SHORT_LOCK_FREE +#define ATOMIC_INT_LOCK_FREE __GCC_ATOMIC_INT_LOCK_FREE +#define ATOMIC_LONG_LOCK_FREE __GCC_ATOMIC_LONG_LOCK_FREE +#define ATOMIC_LLONG_LOCK_FREE __GCC_ATOMIC_LLONG_LOCK_FREE +#define ATOMIC_POINTER_LOCK_FREE __GCC_ATOMIC_POINTER_LOCK_FREE +#endif + +// @} group atomics + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h b/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h new file mode 100644 index 000000000..f12c1bdc2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/boost_concept_check.h @@ -0,0 +1,794 @@ +// -*- C++ -*- + +// Copyright (C) 2004-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// (C) Copyright Jeremy Siek 2000. Permission to copy, use, modify, +// sell and distribute this software is granted provided this +// copyright notice appears in all copies. This software is provided +// "as is" without express or implied warranty, and with no claim as +// to its suitability for any purpose. +// + +/** @file bits/boost_concept_check.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +// GCC Note: based on version 1.12.0 of the Boost library. + +#ifndef _BOOST_CONCEPT_CHECK_H +#define _BOOST_CONCEPT_CHECK_H 1 + +#pragma GCC system_header + +#include +#include // for traits and tags + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wunused-local-typedefs" + +#define _IsUnused __attribute__ ((__unused__)) + +// When the C-C code is in use, we would like this function to do as little +// as possible at runtime, use as few resources as possible, and hopefully +// be elided out of existence... hmmm. +template +_GLIBCXX14_CONSTEXPR inline void __function_requires() +{ + void (_Concept::*__x)() _IsUnused = &_Concept::__constraints; +} + +// No definition: if this is referenced, there's a problem with +// the instantiating type not being one of the required integer types. +// Unfortunately, this results in a link-time error, not a compile-time error. +void __error_type_must_be_an_integer_type(); +void __error_type_must_be_an_unsigned_integer_type(); +void __error_type_must_be_a_signed_integer_type(); + +// ??? Should the "concept_checking*" structs begin with more than _ ? +#define _GLIBCXX_CLASS_REQUIRES(_type_var, _ns, _concept) \ + typedef void (_ns::_concept <_type_var>::* _func##_type_var##_concept)(); \ + template <_func##_type_var##_concept _Tp1> \ + struct _concept_checking##_type_var##_concept { }; \ + typedef _concept_checking##_type_var##_concept< \ + &_ns::_concept <_type_var>::__constraints> \ + _concept_checking_typedef##_type_var##_concept + +#define _GLIBCXX_CLASS_REQUIRES2(_type_var1, _type_var2, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2>::* _func##_type_var1##_type_var2##_concept)(); \ + template <_func##_type_var1##_type_var2##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_concept< \ + &_ns::_concept <_type_var1,_type_var2>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_concept + +#define _GLIBCXX_CLASS_REQUIRES3(_type_var1, _type_var2, _type_var3, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3>::* _func##_type_var1##_type_var2##_type_var3##_concept)(); \ + template <_func##_type_var1##_type_var2##_type_var3##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_type_var3##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_type_var3##_concept< \ + &_ns::_concept <_type_var1,_type_var2,_type_var3>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_concept + +#define _GLIBCXX_CLASS_REQUIRES4(_type_var1, _type_var2, _type_var3, _type_var4, _ns, _concept) \ + typedef void (_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::* _func##_type_var1##_type_var2##_type_var3##_type_var4##_concept)(); \ + template <_func##_type_var1##_type_var2##_type_var3##_type_var4##_concept _Tp1> \ + struct _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept { }; \ + typedef _concept_checking##_type_var1##_type_var2##_type_var3##_type_var4##_concept< \ + &_ns::_concept <_type_var1,_type_var2,_type_var3,_type_var4>::__constraints> \ + _concept_checking_typedef##_type_var1##_type_var2##_type_var3##_type_var4##_concept + + +template +struct _Aux_require_same { }; + +template +struct _Aux_require_same<_Tp,_Tp> { typedef _Tp _Type; }; + + template + struct _SameTypeConcept + { + void __constraints() { + typedef typename _Aux_require_same<_Tp1, _Tp2>::_Type _Required; + } + }; + + template + struct _IntegerConcept { + void __constraints() { + __error_type_must_be_an_integer_type(); + } + }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints(){} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept { void __constraints() {} }; + template <> struct _IntegerConcept + { void __constraints() {} }; + + template + struct _SignedIntegerConcept { + void __constraints() { + __error_type_must_be_a_signed_integer_type(); + } + }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints() {} }; + template <> struct _SignedIntegerConcept { void __constraints(){}}; + + template + struct _UnsignedIntegerConcept { + void __constraints() { + __error_type_must_be_an_unsigned_integer_type(); + } + }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + template <> struct _UnsignedIntegerConcept + { void __constraints() {} }; + + //=========================================================================== + // Basic Concepts + + template + struct _DefaultConstructibleConcept + { + void __constraints() { + _Tp __a _IsUnused; // require default constructor + } + }; + + template + struct _AssignableConcept + { + void __constraints() { + __a = __a; // require assignment operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __b) { + __a = __b; // const required for argument to assignment + } + _Tp __a; + // possibly should be "Tp* a;" and then dereference "a" in constraint + // functions? present way would require a default ctor, i think... + }; + + template + struct _CopyConstructibleConcept + { + void __constraints() { + _Tp __a(__b); // require copy constructor + _Tp* __ptr _IsUnused = &__a; // require address of operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __a) { + _Tp __c _IsUnused(__a); // require const copy constructor + const _Tp* __ptr _IsUnused = &__a; // require const address of operator + } + _Tp __b; + }; + + // The SGI STL version of Assignable requires copy constructor and operator= + template + struct _SGIAssignableConcept + { + void __constraints() { + _Tp __b _IsUnused(__a); + __a = __a; // require assignment operator + __const_constraints(__a); + } + void __const_constraints(const _Tp& __b) { + _Tp __c _IsUnused(__b); + __a = __b; // const required for argument to assignment + } + _Tp __a; + }; + + template + struct _ConvertibleConcept + { + void __constraints() { + _To __y _IsUnused = __x; + } + _From __x; + }; + + // The C++ standard requirements for many concepts talk about return + // types that must be "convertible to bool". The problem with this + // requirement is that it leaves the door open for evil proxies that + // define things like operator|| with strange return types. Two + // possible solutions are: + // 1) require the return type to be exactly bool + // 2) stay with convertible to bool, and also + // specify stuff about all the logical operators. + // For now we just test for convertible to bool. + template + void __aux_require_boolean_expr(const _Tp& __t) { + bool __x _IsUnused = __t; + } + +// FIXME + template + struct _EqualityComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a == __b); + } + _Tp __a, __b; + }; + + template + struct _LessThanComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a < __b); + } + _Tp __a, __b; + }; + + // This is equivalent to SGI STL's LessThanComparable. + template + struct _ComparableConcept + { + void __constraints() { + __aux_require_boolean_expr(__a < __b); + __aux_require_boolean_expr(__a > __b); + __aux_require_boolean_expr(__a <= __b); + __aux_require_boolean_expr(__a >= __b); + } + _Tp __a, __b; + }; + +#define _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(_OP,_NAME) \ + template \ + struct _NAME { \ + void __constraints() { (void)__constraints_(); } \ + bool __constraints_() { \ + return __a _OP __b; \ + } \ + _First __a; \ + _Second __b; \ + } + +#define _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(_OP,_NAME) \ + template \ + struct _NAME { \ + void __constraints() { (void)__constraints_(); } \ + _Ret __constraints_() { \ + return __a _OP __b; \ + } \ + _First __a; \ + _Second __b; \ + } + + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(==, _EqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(!=, _NotEqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<, _LessThanOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(<=, _LessEqualOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>, _GreaterThanOpConcept); + _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT(>=, _GreaterEqualOpConcept); + + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(+, _PlusOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(*, _TimesOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(/, _DivideOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(-, _SubtractOpConcept); + _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT(%, _ModOpConcept); + +#undef _GLIBCXX_DEFINE_BINARY_PREDICATE_OP_CONSTRAINT +#undef _GLIBCXX_DEFINE_BINARY_OPERATOR_CONSTRAINT + + //=========================================================================== + // Function Object Concepts + + template + struct _GeneratorConcept + { + void __constraints() { + const _Return& __r _IsUnused = __f();// require operator() member function + } + _Func __f; + }; + + + template + struct _GeneratorConcept<_Func,void> + { + void __constraints() { + __f(); // require operator() member function + } + _Func __f; + }; + + template + struct _UnaryFunctionConcept + { + void __constraints() { + __r = __f(__arg); // require operator() + } + _Func __f; + _Arg __arg; + _Return __r; + }; + + template + struct _UnaryFunctionConcept<_Func, void, _Arg> { + void __constraints() { + __f(__arg); // require operator() + } + _Func __f; + _Arg __arg; + }; + + template + struct _BinaryFunctionConcept + { + void __constraints() { + __r = __f(__first, __second); // require operator() + } + _Func __f; + _First __first; + _Second __second; + _Return __r; + }; + + template + struct _BinaryFunctionConcept<_Func, void, _First, _Second> + { + void __constraints() { + __f(__first, __second); // require operator() + } + _Func __f; + _First __first; + _Second __second; + }; + + template + struct _UnaryPredicateConcept + { + void __constraints() { + __aux_require_boolean_expr(__f(__arg)); // require op() returning bool + } + _Func __f; + _Arg __arg; + }; + + template + struct _BinaryPredicateConcept + { + void __constraints() { + __aux_require_boolean_expr(__f(__a, __b)); // require op() returning bool + } + _Func __f; + _First __a; + _Second __b; + }; + + // use this when functor is used inside a container class like std::set + template + struct _Const_BinaryPredicateConcept { + void __constraints() { + __const_constraints(__f); + } + void __const_constraints(const _Func& __fun) { + __function_requires<_BinaryPredicateConcept<_Func, _First, _Second> >(); + // operator() must be a const member function + __aux_require_boolean_expr(__fun(__a, __b)); + } + _Func __f; + _First __a; + _Second __b; + }; + + //=========================================================================== + // Iterator Concepts + + template + struct _TrivialIteratorConcept + { + void __constraints() { +// __function_requires< _DefaultConstructibleConcept<_Tp> >(); + __function_requires< _AssignableConcept<_Tp> >(); + __function_requires< _EqualityComparableConcept<_Tp> >(); +// typedef typename std::iterator_traits<_Tp>::value_type _V; + (void)*__i; // require dereference operator + } + _Tp __i; + }; + + template + struct _Mutable_TrivialIteratorConcept + { + void __constraints() { + __function_requires< _TrivialIteratorConcept<_Tp> >(); + *__i = *__j; // require dereference and assignment + } + _Tp __i, __j; + }; + + template + struct _InputIteratorConcept + { + void __constraints() { + __function_requires< _TrivialIteratorConcept<_Tp> >(); + // require iterator_traits typedef's + typedef typename std::iterator_traits<_Tp>::difference_type _Diff; +// __function_requires< _SignedIntegerConcept<_Diff> >(); + typedef typename std::iterator_traits<_Tp>::reference _Ref; + typedef typename std::iterator_traits<_Tp>::pointer _Pt; + typedef typename std::iterator_traits<_Tp>::iterator_category _Cat; + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::input_iterator_tag> >(); + ++__i; // require preincrement operator + __i++; // require postincrement operator + } + _Tp __i; + }; + + template + struct _OutputIteratorConcept + { + void __constraints() { + __function_requires< _AssignableConcept<_Tp> >(); + ++__i; // require preincrement operator + __i++; // require postincrement operator + *__i++ = __t; // require postincrement and assignment + } + _Tp __i; + _ValueT __t; + }; + + template + struct _ForwardIteratorConcept + { + void __constraints() { + __function_requires< _InputIteratorConcept<_Tp> >(); + __function_requires< _DefaultConstructibleConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::forward_iterator_tag> >(); + typedef typename std::iterator_traits<_Tp>::reference _Ref; + _Ref __r _IsUnused = *__i; + } + _Tp __i; + }; + + template + struct _Mutable_ForwardIteratorConcept + { + void __constraints() { + __function_requires< _ForwardIteratorConcept<_Tp> >(); + *__i++ = *__i; // require postincrement and assignment + } + _Tp __i; + }; + + template + struct _BidirectionalIteratorConcept + { + void __constraints() { + __function_requires< _ForwardIteratorConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::bidirectional_iterator_tag> >(); + --__i; // require predecrement operator + __i--; // require postdecrement operator + } + _Tp __i; + }; + + template + struct _Mutable_BidirectionalIteratorConcept + { + void __constraints() { + __function_requires< _BidirectionalIteratorConcept<_Tp> >(); + __function_requires< _Mutable_ForwardIteratorConcept<_Tp> >(); + *__i-- = *__i; // require postdecrement and assignment + } + _Tp __i; + }; + + + template + struct _RandomAccessIteratorConcept + { + void __constraints() { + __function_requires< _BidirectionalIteratorConcept<_Tp> >(); + __function_requires< _ComparableConcept<_Tp> >(); + __function_requires< _ConvertibleConcept< + typename std::iterator_traits<_Tp>::iterator_category, + std::random_access_iterator_tag> >(); + // ??? We don't use _Ref, are we just checking for "referenceability"? + typedef typename std::iterator_traits<_Tp>::reference _Ref; + + __i += __n; // require assignment addition operator + __i = __i + __n; __i = __n + __i; // require addition with difference type + __i -= __n; // require assignment subtraction op + __i = __i - __n; // require subtraction with + // difference type + __n = __i - __j; // require difference operator + (void)__i[__n]; // require element access operator + } + _Tp __a, __b; + _Tp __i, __j; + typename std::iterator_traits<_Tp>::difference_type __n; + }; + + template + struct _Mutable_RandomAccessIteratorConcept + { + void __constraints() { + __function_requires< _RandomAccessIteratorConcept<_Tp> >(); + __function_requires< _Mutable_BidirectionalIteratorConcept<_Tp> >(); + __i[__n] = *__i; // require element access and assignment + } + _Tp __i; + typename std::iterator_traits<_Tp>::difference_type __n; + }; + + //=========================================================================== + // Container Concepts + + template + struct _ContainerConcept + { + typedef typename _Container::value_type _Value_type; + typedef typename _Container::difference_type _Difference_type; + typedef typename _Container::size_type _Size_type; + typedef typename _Container::const_reference _Const_reference; + typedef typename _Container::const_pointer _Const_pointer; + typedef typename _Container::const_iterator _Const_iterator; + + void __constraints() { + __function_requires< _InputIteratorConcept<_Const_iterator> >(); + __function_requires< _AssignableConcept<_Container> >(); + const _Container __c; + __i = __c.begin(); + __i = __c.end(); + __n = __c.size(); + __n = __c.max_size(); + __b = __c.empty(); + } + bool __b; + _Const_iterator __i; + _Size_type __n; + }; + + template + struct _Mutable_ContainerConcept + { + typedef typename _Container::value_type _Value_type; + typedef typename _Container::reference _Reference; + typedef typename _Container::iterator _Iterator; + typedef typename _Container::pointer _Pointer; + + void __constraints() { + __function_requires< _ContainerConcept<_Container> >(); + __function_requires< _AssignableConcept<_Value_type> >(); + __function_requires< _InputIteratorConcept<_Iterator> >(); + + __i = __c.begin(); + __i = __c.end(); + __c.swap(__c2); + } + _Iterator __i; + _Container __c, __c2; + }; + + template + struct _ForwardContainerConcept + { + void __constraints() { + __function_requires< _ContainerConcept<_ForwardContainer> >(); + typedef typename _ForwardContainer::const_iterator _Const_iterator; + __function_requires< _ForwardIteratorConcept<_Const_iterator> >(); + } + }; + + template + struct _Mutable_ForwardContainerConcept + { + void __constraints() { + __function_requires< _ForwardContainerConcept<_ForwardContainer> >(); + __function_requires< _Mutable_ContainerConcept<_ForwardContainer> >(); + typedef typename _ForwardContainer::iterator _Iterator; + __function_requires< _Mutable_ForwardIteratorConcept<_Iterator> >(); + } + }; + + template + struct _ReversibleContainerConcept + { + typedef typename _ReversibleContainer::const_iterator _Const_iterator; + typedef typename _ReversibleContainer::const_reverse_iterator + _Const_reverse_iterator; + + void __constraints() { + __function_requires< _ForwardContainerConcept<_ReversibleContainer> >(); + __function_requires< _BidirectionalIteratorConcept<_Const_iterator> >(); + __function_requires< + _BidirectionalIteratorConcept<_Const_reverse_iterator> >(); + + const _ReversibleContainer __c; + _Const_reverse_iterator __i = __c.rbegin(); + __i = __c.rend(); + } + }; + + template + struct _Mutable_ReversibleContainerConcept + { + typedef typename _ReversibleContainer::iterator _Iterator; + typedef typename _ReversibleContainer::reverse_iterator _Reverse_iterator; + + void __constraints() { + __function_requires<_ReversibleContainerConcept<_ReversibleContainer> >(); + __function_requires< + _Mutable_ForwardContainerConcept<_ReversibleContainer> >(); + __function_requires<_Mutable_BidirectionalIteratorConcept<_Iterator> >(); + __function_requires< + _Mutable_BidirectionalIteratorConcept<_Reverse_iterator> >(); + + _Reverse_iterator __i = __c.rbegin(); + __i = __c.rend(); + } + _ReversibleContainer __c; + }; + + template + struct _RandomAccessContainerConcept + { + typedef typename _RandomAccessContainer::size_type _Size_type; + typedef typename _RandomAccessContainer::const_reference _Const_reference; + typedef typename _RandomAccessContainer::const_iterator _Const_iterator; + typedef typename _RandomAccessContainer::const_reverse_iterator + _Const_reverse_iterator; + + void __constraints() { + __function_requires< + _ReversibleContainerConcept<_RandomAccessContainer> >(); + __function_requires< _RandomAccessIteratorConcept<_Const_iterator> >(); + __function_requires< + _RandomAccessIteratorConcept<_Const_reverse_iterator> >(); + + const _RandomAccessContainer __c; + _Const_reference __r _IsUnused = __c[__n]; + } + _Size_type __n; + }; + + template + struct _Mutable_RandomAccessContainerConcept + { + typedef typename _RandomAccessContainer::size_type _Size_type; + typedef typename _RandomAccessContainer::reference _Reference; + typedef typename _RandomAccessContainer::iterator _Iterator; + typedef typename _RandomAccessContainer::reverse_iterator _Reverse_iterator; + + void __constraints() { + __function_requires< + _RandomAccessContainerConcept<_RandomAccessContainer> >(); + __function_requires< + _Mutable_ReversibleContainerConcept<_RandomAccessContainer> >(); + __function_requires< _Mutable_RandomAccessIteratorConcept<_Iterator> >(); + __function_requires< + _Mutable_RandomAccessIteratorConcept<_Reverse_iterator> >(); + + _Reference __r _IsUnused = __c[__i]; + } + _Size_type __i; + _RandomAccessContainer __c; + }; + + // A Sequence is inherently mutable + template + struct _SequenceConcept + { + typedef typename _Sequence::reference _Reference; + typedef typename _Sequence::const_reference _Const_reference; + + void __constraints() { + // Matt Austern's book puts DefaultConstructible here, the C++ + // standard places it in Container + // function_requires< DefaultConstructible >(); + __function_requires< _Mutable_ForwardContainerConcept<_Sequence> >(); + __function_requires< _DefaultConstructibleConcept<_Sequence> >(); + + _Sequence + __c _IsUnused(__n, __t), + __c2 _IsUnused(__first, __last); + + __c.insert(__p, __t); + __c.insert(__p, __n, __t); + __c.insert(__p, __first, __last); + + __c.erase(__p); + __c.erase(__p, __q); + + _Reference __r _IsUnused = __c.front(); + + __const_constraints(__c); + } + void __const_constraints(const _Sequence& __c) { + _Const_reference __r _IsUnused = __c.front(); + } + typename _Sequence::value_type __t; + typename _Sequence::size_type __n; + typename _Sequence::value_type *__first, *__last; + typename _Sequence::iterator __p, __q; + }; + + template + struct _FrontInsertionSequenceConcept + { + void __constraints() { + __function_requires< _SequenceConcept<_FrontInsertionSequence> >(); + + __c.push_front(__t); + __c.pop_front(); + } + _FrontInsertionSequence __c; + typename _FrontInsertionSequence::value_type __t; + }; + + template + struct _BackInsertionSequenceConcept + { + typedef typename _BackInsertionSequence::reference _Reference; + typedef typename _BackInsertionSequence::const_reference _Const_reference; + + void __constraints() { + __function_requires< _SequenceConcept<_BackInsertionSequence> >(); + + __c.push_back(__t); + __c.pop_back(); + _Reference __r _IsUnused = __c.back(); + } + void __const_constraints(const _BackInsertionSequence& __c) { + _Const_reference __r _IsUnused = __c.back(); + }; + _BackInsertionSequence __c; + typename _BackInsertionSequence::value_type __t; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#pragma GCC diagnostic pop +#undef _IsUnused + +#endif // _GLIBCXX_BOOST_CONCEPT_CHECK + + diff --git a/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h b/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h new file mode 100644 index 000000000..83dc80c34 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/c++0x_warning.h @@ -0,0 +1,37 @@ +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++0x_warning.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +#ifndef _CXX0X_WARNING_H +#define _CXX0X_WARNING_H 1 + +#if __cplusplus < 201103L +#error This file requires compiler and library support \ +for the ISO C++ 2011 standard. This support must be enabled \ +with the -std=c++11 or -std=gnu++11 compiler options. +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/c++allocator.h b/resources/sources/avr-libstdcpp/include/bits/c++allocator.h new file mode 100644 index 000000000..6392d2207 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/c++allocator.h @@ -0,0 +1,59 @@ +// Base to std::allocator -*- C++ -*- + +// Copyright (C) 2004-2018 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++allocator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _GLIBCXX_CXX_ALLOCATOR_H +#define _GLIBCXX_CXX_ALLOCATOR_H 1 + +#include + +#if __cplusplus >= 201103L +namespace std +{ + /** + * @brief An alias to the base class for std::allocator. + * @ingroup allocators + * + * Used to set the std::allocator base class to + * __gnu_cxx::new_allocator. + * + * @tparam _Tp Type of allocated object. + */ + template + using __allocator_base = __gnu_cxx::new_allocator<_Tp>; +} +#else +// Define new_allocator as the base class to std::allocator. +# define __allocator_base __gnu_cxx::new_allocator +#endif + +#if defined(__SANITIZE_ADDRESS__) && !defined(_GLIBCXX_SANITIZE_STD_ALLOCATOR) +# define _GLIBCXX_SANITIZE_STD_ALLOCATOR 1 +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/c++config.h b/resources/sources/avr-libstdcpp/include/bits/c++config.h new file mode 100644 index 000000000..29b3eb2f0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/c++config.h @@ -0,0 +1,2074 @@ +// Predefined symbols and macros -*- C++ -*- + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/c++config.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{version} + */ + +#ifndef _GLIBCXX_CXX_CONFIG_H +#define _GLIBCXX_CXX_CONFIG_H 1 + +// The major release number for the GCC release the C++ library belongs to. +#define _GLIBCXX_RELEASE 10 + +// The datestamp of the C++ library in compressed ISO date format. +#define __GLIBCXX__ 20201103 + +// Macros for various attributes. +// _GLIBCXX_PURE +// _GLIBCXX_CONST +// _GLIBCXX_NORETURN +// _GLIBCXX_NOTHROW +// _GLIBCXX_VISIBILITY +#ifndef _GLIBCXX_PURE +# define _GLIBCXX_PURE __attribute__ ((__pure__)) +#endif + +#ifndef _GLIBCXX_CONST +# define _GLIBCXX_CONST __attribute__ ((__const__)) +#endif + +#ifndef _GLIBCXX_NORETURN +# define _GLIBCXX_NORETURN __attribute__ ((__noreturn__)) +#endif + +// See below for C++ +#ifndef _GLIBCXX_NOTHROW +# ifndef __cplusplus +# define _GLIBCXX_NOTHROW __attribute__((__nothrow__)) +# endif +#endif + +// Macros for visibility attributes. +// _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY +// _GLIBCXX_VISIBILITY +#define _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY + +#ifdef _GLIBCXX_HAVE_ATTRIBUTE_VISIBILITY +# define _GLIBCXX_VISIBILITY(V) __attribute__ ((__visibility__ (#V))) +#else +// If this is not supplied by the OS-specific or CPU-specific +// headers included below, it will be defined to an empty default. +# define _GLIBCXX_VISIBILITY(V) _GLIBCXX_PSEUDO_VISIBILITY(V) +#endif + +// Macros for deprecated attributes. +// _GLIBCXX_USE_DEPRECATED +// _GLIBCXX_DEPRECATED +// _GLIBCXX_DEPRECATED_SUGGEST +// _GLIBCXX17_DEPRECATED +// _GLIBCXX20_DEPRECATED( string-literal ) +#ifndef _GLIBCXX_USE_DEPRECATED +# define _GLIBCXX_USE_DEPRECATED 1 +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 201103L) +# define _GLIBCXX_DEPRECATED __attribute__ ((__deprecated__)) +# define _GLIBCXX_DEPRECATED_SUGGEST(ALT) \ + __attribute__ ((__deprecated__ ("use '" ALT "' instead"))) +#else +# define _GLIBCXX_DEPRECATED +# define _GLIBCXX_DEPRECATED_SUGGEST(ALT) +#endif + +#if defined(__DEPRECATED) && (__cplusplus >= 201703L) +# define _GLIBCXX17_DEPRECATED [[__deprecated__]] +#else +# define _GLIBCXX17_DEPRECATED +#endif + +#if defined(__DEPRECATED) && (__cplusplus > 201703L) +# define _GLIBCXX20_DEPRECATED(MSG) [[deprecated(MSG)]] +#else +# define _GLIBCXX20_DEPRECATED(MSG) +#endif + +// Macros for ABI tag attributes. +#ifndef _GLIBCXX_ABI_TAG_CXX11 +# define _GLIBCXX_ABI_TAG_CXX11 __attribute ((__abi_tag__ ("cxx11"))) +#endif + +// Macro to warn about unused results. +#if __cplusplus >= 201703L +# define _GLIBCXX_NODISCARD [[__nodiscard__]] +#else +# define _GLIBCXX_NODISCARD +#endif + + + +#ifdef __cplusplus + +// Macro for constexpr, to support in mixed 03/0x mode. +#ifndef _GLIBCXX_CONSTEXPR +# if __cplusplus >= 201103L +# define _GLIBCXX_CONSTEXPR constexpr +# define _GLIBCXX_USE_CONSTEXPR constexpr +# else +# define _GLIBCXX_CONSTEXPR +# define _GLIBCXX_USE_CONSTEXPR const +# endif +#endif + +#ifndef _GLIBCXX14_CONSTEXPR +# if __cplusplus >= 201402L +# define _GLIBCXX14_CONSTEXPR constexpr +# else +# define _GLIBCXX14_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX17_CONSTEXPR +# if __cplusplus >= 201703L +# define _GLIBCXX17_CONSTEXPR constexpr +# else +# define _GLIBCXX17_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX20_CONSTEXPR +# if __cplusplus > 201703L +# define _GLIBCXX20_CONSTEXPR constexpr +# else +# define _GLIBCXX20_CONSTEXPR +# endif +#endif + +#ifndef _GLIBCXX17_INLINE +# if __cplusplus >= 201703L +# define _GLIBCXX17_INLINE inline +# else +# define _GLIBCXX17_INLINE +# endif +#endif + +// Macro for noexcept, to support in mixed 03/0x mode. +#ifndef _GLIBCXX_NOEXCEPT +# if __cplusplus >= 201103L +# define _GLIBCXX_NOEXCEPT noexcept +# define _GLIBCXX_NOEXCEPT_IF(...) noexcept(__VA_ARGS__) +# define _GLIBCXX_USE_NOEXCEPT noexcept +# define _GLIBCXX_THROW(_EXC) +# else +# define _GLIBCXX_NOEXCEPT +# define _GLIBCXX_NOEXCEPT_IF(...) +# define _GLIBCXX_USE_NOEXCEPT throw() +# define _GLIBCXX_THROW(_EXC) throw(_EXC) +# endif +#endif + +#ifndef _GLIBCXX_NOTHROW +# define _GLIBCXX_NOTHROW _GLIBCXX_USE_NOEXCEPT +#endif + +#ifndef _GLIBCXX_THROW_OR_ABORT +# ifdef __cpp_exceptions +# define _GLIBCXX_THROW_OR_ABORT(_EXC) (throw (_EXC)) +# else +# define _GLIBCXX_THROW_OR_ABORT(_EXC) (__builtin_abort()) +# endif +#endif + +#ifdef __cpp_noexcept_function_type +#define _GLIBCXX_NOEXCEPT_PARM , bool _NE +#define _GLIBCXX_NOEXCEPT_QUAL noexcept (_NE) +#else +#define _GLIBCXX_NOEXCEPT_PARM +#define _GLIBCXX_NOEXCEPT_QUAL +#endif + +// Macro for extern template, ie controlling template linkage via use +// of extern keyword on template declaration. As documented in the g++ +// manual, it inhibits all implicit instantiations and is used +// throughout the library to avoid multiple weak definitions for +// required types that are already explicitly instantiated in the +// library binary. This substantially reduces the binary size of +// resulting executables. +// Special case: _GLIBCXX_EXTERN_TEMPLATE == -1 disallows extern +// templates only in basic_string, thus activating its debug-mode +// checks even at -O0. +# define _GLIBCXX_EXTERN_TEMPLATE 1 + +/* + Outline of libstdc++ namespaces. + + namespace std + { + namespace __debug { } + namespace __parallel { } + namespace __cxx1998 { } + + namespace __detail { + namespace __variant { } // C++17 + } + + namespace rel_ops { } + + namespace tr1 + { + namespace placeholders { } + namespace regex_constants { } + namespace __detail { } + } + + namespace tr2 { } + + namespace decimal { } + + namespace chrono { } // C++11 + namespace placeholders { } // C++11 + namespace regex_constants { } // C++11 + namespace this_thread { } // C++11 + inline namespace literals { // C++14 + inline namespace chrono_literals { } // C++14 + inline namespace complex_literals { } // C++14 + inline namespace string_literals { } // C++14 + inline namespace string_view_literals { } // C++17 + } + } + + namespace abi { } + + namespace __gnu_cxx + { + namespace __detail { } + } + + For full details see: + http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/namespaces.html +*/ +namespace std +{ + typedef __SIZE_TYPE__ size_t; + typedef __PTRDIFF_TYPE__ ptrdiff_t; + +#if __cplusplus >= 201103L + typedef decltype(nullptr) nullptr_t; +#endif +} + +# define _GLIBCXX_USE_DUAL_ABI 1 + +#ifndef _GLIBCXX_USE_DUAL_ABI +// Ignore any pre-defined value of _GLIBCXX_USE_CXX11_ABI +# undef _GLIBCXX_USE_CXX11_ABI +#endif + +#ifndef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_USE_CXX11_ABI 1 +#endif + +#ifdef _GLIBCXX_USE_CXX11_ABI +namespace std +{ + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +} +namespace __gnu_cxx +{ + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +} +# define _GLIBCXX_NAMESPACE_CXX11 __cxx11:: +# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 namespace __cxx11 { +# define _GLIBCXX_END_NAMESPACE_CXX11 } +# define _GLIBCXX_DEFAULT_ABI_TAG _GLIBCXX_ABI_TAG_CXX11 +#else +# define _GLIBCXX_NAMESPACE_CXX11 +# define _GLIBCXX_BEGIN_NAMESPACE_CXX11 +# define _GLIBCXX_END_NAMESPACE_CXX11 +# define _GLIBCXX_DEFAULT_ABI_TAG +#endif + +// Defined if inline namespaces are used for versioning. +//#define _GLIBCXX_INLINE_VERSION + +// Inline namespace for symbol versioning. +#ifdef _GLIBCXX_INLINE_VERSION +# define _GLIBCXX_BEGIN_NAMESPACE_VERSION namespace __8 { +# define _GLIBCXX_END_NAMESPACE_VERSION } + +namespace std +{ +inline _GLIBCXX_BEGIN_NAMESPACE_VERSION +#if __cplusplus >= 201402L + inline namespace literals { + inline namespace chrono_literals { } + inline namespace complex_literals { } + inline namespace string_literals { } +#if __cplusplus > 201402L + inline namespace string_view_literals { } +#endif // C++17 + } +#endif // C++14 +_GLIBCXX_END_NAMESPACE_VERSION +} + +namespace __gnu_cxx +{ +inline _GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_END_NAMESPACE_VERSION +} + +#else +# define _GLIBCXX_BEGIN_NAMESPACE_VERSION +# define _GLIBCXX_END_NAMESPACE_VERSION +#endif + +// Inline namespaces for special modes: debug, parallel. +#if defined(_GLIBCXX_DEBUG) || defined(_GLIBCXX_PARALLEL) +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Non-inline namespace for components replaced by alternates in active mode. + namespace __cxx1998 + { +# if _GLIBCXX_USE_CXX11_ABI + inline namespace __cxx11 __attribute__((__abi_tag__ ("cxx11"))) { } +# endif + } + +_GLIBCXX_END_NAMESPACE_VERSION + + // Inline namespace for debug mode. +# ifdef _GLIBCXX_DEBUG + inline namespace __debug { } +# endif + + // Inline namespaces for parallel mode. +# ifdef _GLIBCXX_PARALLEL + inline namespace __parallel { } +# endif +} + +// Check for invalid usage and unsupported mixed-mode use. +# if defined(_GLIBCXX_DEBUG) && defined(_GLIBCXX_PARALLEL) +# error illegal use of multiple inlined namespaces +# endif + +// Check for invalid use due to lack for weak symbols. +# if __NO_INLINE__ && !__GXX_WEAK__ +# warning currently using inlined namespace mode which may fail \ + without inlining due to lack of weak symbols +# endif +#endif + +// Macros for namespace scope. Either namespace std:: or the name +// of some nested namespace within it corresponding to the active mode. +// _GLIBCXX_STD_A +// _GLIBCXX_STD_C +// +// Macros for opening/closing conditional namespaces. +// _GLIBCXX_BEGIN_NAMESPACE_ALGO +// _GLIBCXX_END_NAMESPACE_ALGO +// _GLIBCXX_BEGIN_NAMESPACE_CONTAINER +// _GLIBCXX_END_NAMESPACE_CONTAINER +#if defined(_GLIBCXX_DEBUG) +# define _GLIBCXX_STD_C __cxx1998 +# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER \ + namespace _GLIBCXX_STD_C { +# define _GLIBCXX_END_NAMESPACE_CONTAINER } +#else +# define _GLIBCXX_STD_C std +# define _GLIBCXX_BEGIN_NAMESPACE_CONTAINER +# define _GLIBCXX_END_NAMESPACE_CONTAINER +#endif + +#ifdef _GLIBCXX_PARALLEL +# define _GLIBCXX_STD_A __cxx1998 +# define _GLIBCXX_BEGIN_NAMESPACE_ALGO \ + namespace _GLIBCXX_STD_A { +# define _GLIBCXX_END_NAMESPACE_ALGO } +#else +# define _GLIBCXX_STD_A std +# define _GLIBCXX_BEGIN_NAMESPACE_ALGO +# define _GLIBCXX_END_NAMESPACE_ALGO +#endif + +// GLIBCXX_ABI Deprecated +// Define if compatibility should be provided for -mlong-double-64. +#undef _GLIBCXX_LONG_DOUBLE_COMPAT + +// Inline namespace for long double 128 mode. +#if defined _GLIBCXX_LONG_DOUBLE_COMPAT && defined __LONG_DOUBLE_128__ +namespace std +{ + inline namespace __gnu_cxx_ldbl128 { } +} +# define _GLIBCXX_NAMESPACE_LDBL __gnu_cxx_ldbl128:: +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL namespace __gnu_cxx_ldbl128 { +# define _GLIBCXX_END_NAMESPACE_LDBL } +#else +# define _GLIBCXX_NAMESPACE_LDBL +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL +# define _GLIBCXX_END_NAMESPACE_LDBL +#endif +#ifdef _GLIBCXX_USE_CXX11_ABI +# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_CXX11 +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_CXX11 +# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_CXX11 +#else +# define _GLIBCXX_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_NAMESPACE_LDBL +# define _GLIBCXX_BEGIN_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_BEGIN_NAMESPACE_LDBL +# define _GLIBCXX_END_NAMESPACE_LDBL_OR_CXX11 _GLIBCXX_END_NAMESPACE_LDBL +#endif + +// Debug Mode implies checking assertions. +#if defined(_GLIBCXX_DEBUG) && !defined(_GLIBCXX_ASSERTIONS) +# define _GLIBCXX_ASSERTIONS 1 +#endif + +// Disable std::string explicit instantiation declarations in order to assert. +#ifdef _GLIBCXX_ASSERTIONS +# undef _GLIBCXX_EXTERN_TEMPLATE +# define _GLIBCXX_EXTERN_TEMPLATE -1 +#endif + +// Assert. +#if defined(_GLIBCXX_ASSERTIONS) \ + || defined(_GLIBCXX_PARALLEL) || defined(_GLIBCXX_PARALLEL_ASSERTIONS) +namespace std +{ + // Avoid the use of assert, because we're trying to keep the + // include out of the mix. + extern "C++" inline void + __replacement_assert(const char* __file, int __line, + const char* __function, const char* __condition) + { + __builtin_printf("%s:%d: %s: Assertion '%s' failed.\n", __file, __line, + __function, __condition); + __builtin_abort(); + } +} +#define __glibcxx_assert_impl(_Condition) \ + do \ + { \ + if (! (_Condition)) \ + std::__replacement_assert(__FILE__, __LINE__, __PRETTY_FUNCTION__, \ + #_Condition); \ + } while (false) +#endif + +#if defined(_GLIBCXX_ASSERTIONS) +# define __glibcxx_assert(_Condition) __glibcxx_assert_impl(_Condition) +#else +# define __glibcxx_assert(_Condition) +#endif + +// Macros for race detectors. +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) and +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) should be used to explain +// atomic (lock-free) synchronization to race detectors: +// the race detector will infer a happens-before arc from the former to the +// latter when they share the same argument pointer. +// +// The most frequent use case for these macros (and the only case in the +// current implementation of the library) is atomic reference counting: +// void _M_remove_reference() +// { +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(&this->_M_refcount); +// if (__gnu_cxx::__exchange_and_add_dispatch(&this->_M_refcount, -1) <= 0) +// { +// _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(&this->_M_refcount); +// _M_destroy(__a); +// } +// } +// The annotations in this example tell the race detector that all memory +// accesses occurred when the refcount was positive do not race with +// memory accesses which occurred after the refcount became zero. +#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE +# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_BEFORE(A) +#endif +#ifndef _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER +# define _GLIBCXX_SYNCHRONIZATION_HAPPENS_AFTER(A) +#endif + +// Macros for C linkage: define extern "C" linkage only when using C++. +# define _GLIBCXX_BEGIN_EXTERN_C extern "C" { +# define _GLIBCXX_END_EXTERN_C } + +# define _GLIBCXX_USE_ALLOCATOR_NEW 1 + +#else // !__cplusplus +# define _GLIBCXX_BEGIN_EXTERN_C +# define _GLIBCXX_END_EXTERN_C +#endif + + +// First includes. + +// Pick up any OS-specific definitions. +//#include + +// Pick up any CPU-specific definitions. +//#include + +// If platform uses neither visibility nor psuedo-visibility, +// specify empty default for namespace annotation macros. +#ifndef _GLIBCXX_PSEUDO_VISIBILITY +# define _GLIBCXX_PSEUDO_VISIBILITY(V) +#endif + +// Certain function definitions that are meant to be overridable from +// user code are decorated with this macro. For some targets, this +// macro causes these definitions to be weak. +#ifndef _GLIBCXX_WEAK_DEFINITION +# define _GLIBCXX_WEAK_DEFINITION +#endif + +// By default, we assume that __GXX_WEAK__ also means that there is support +// for declaring functions as weak while not defining such functions. This +// allows for referring to functions provided by other libraries (e.g., +// libitm) without depending on them if the respective features are not used. +#ifndef _GLIBCXX_USE_WEAK_REF +# define _GLIBCXX_USE_WEAK_REF __GXX_WEAK__ +#endif + +// Conditionally enable annotations for the Transactional Memory TS on C++11. +// Most of the following conditions are due to limitations in the current +// implementation. +/*#if __cplusplus >= 201103L && _GLIBCXX_USE_CXX11_ABI \ + && _GLIBCXX_USE_DUAL_ABI && __cpp_transactional_memory >= 201505L \ + && !_GLIBCXX_FULLY_DYNAMIC_STRING && _GLIBCXX_USE_WEAK_REF \ + && _GLIBCXX_USE_ALLOCATOR_NEW +#define _GLIBCXX_TXN_SAFE transaction_safe +#define _GLIBCXX_TXN_SAFE_DYN transaction_safe_dynamic*/ +//#else +#define _GLIBCXX_TXN_SAFE +#define _GLIBCXX_TXN_SAFE_DYN +//#endif + +#if __cplusplus > 201402L +// In C++17 mathematical special functions are in namespace std. +# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 +#elif __cplusplus >= 201103L && __STDCPP_WANT_MATH_SPEC_FUNCS__ != 0 +// For C++11 and C++14 they are in namespace std when requested. +# define _GLIBCXX_USE_STD_SPEC_FUNCS 1 +#endif + +// The remainder of the prewritten config is automatic; all the +// user hooks are listed above. + +// Create a boolean flag to be used to determine if --fast-math is set. +#ifdef __FAST_MATH__ +# define _GLIBCXX_FAST_MATH 1 +#else +# define _GLIBCXX_FAST_MATH 0 +#endif + +// This marks string literals in header files to be extracted for eventual +// translation. It is primarily used for messages in thrown exceptions; see +// src/functexcept.cc. We use __N because the more traditional _N is used +// for something else under certain OSes (see BADNAMES). + +// modm avr port: remove exception strings to save RAM +#define __N(msgid) ("") + +// For example, is known to #define min and max as macros... +#undef min +#undef max + +// N.B. these _GLIBCXX_USE_C99_XXX macros are defined unconditionally +// so they should be tested with #if not with #ifdef. +#if __cplusplus >= 201103L +# ifndef _GLIBCXX_USE_C99_MATH +# define _GLIBCXX_USE_C99_MATH _GLIBCXX11_USE_C99_MATH +# endif +# ifndef _GLIBCXX_USE_C99_COMPLEX +# define _GLIBCXX_USE_C99_COMPLEX _GLIBCXX11_USE_C99_COMPLEX +# endif +# ifndef _GLIBCXX_USE_C99_STDIO +# define _GLIBCXX_USE_C99_STDIO _GLIBCXX11_USE_C99_STDIO +# endif +# ifndef _GLIBCXX_USE_C99_STDLIB +# define _GLIBCXX_USE_C99_STDLIB _GLIBCXX11_USE_C99_STDLIB +# endif +# ifndef _GLIBCXX_USE_C99_WCHAR +# define _GLIBCXX_USE_C99_WCHAR _GLIBCXX11_USE_C99_WCHAR +# endif +#else +# ifndef _GLIBCXX_USE_C99_MATH +# define _GLIBCXX_USE_C99_MATH _GLIBCXX98_USE_C99_MATH +# endif +# ifndef _GLIBCXX_USE_C99_COMPLEX +# define _GLIBCXX_USE_C99_COMPLEX _GLIBCXX98_USE_C99_COMPLEX +# endif +# ifndef _GLIBCXX_USE_C99_STDIO +# define _GLIBCXX_USE_C99_STDIO _GLIBCXX98_USE_C99_STDIO +# endif +# ifndef _GLIBCXX_USE_C99_STDLIB +# define _GLIBCXX_USE_C99_STDLIB _GLIBCXX98_USE_C99_STDLIB +# endif +# ifndef _GLIBCXX_USE_C99_WCHAR +# define _GLIBCXX_USE_C99_WCHAR _GLIBCXX98_USE_C99_WCHAR +# endif +#endif + +// Unless explicitly specified, enable char8_t extensions only if the core +// language char8_t feature macro is defined. +#ifndef _GLIBCXX_USE_CHAR8_T +# ifdef __cpp_char8_t +# define _GLIBCXX_USE_CHAR8_T 1 +# endif +#endif +#ifdef _GLIBCXX_USE_CHAR8_T +# define __cpp_lib_char8_t 201907L +#endif + +/* Define if __float128 is supported on this host. */ +#if defined(__FLOAT128__) || defined(__SIZEOF_FLOAT128__) +#undef _GLIBCXX_USE_FLOAT128 +#endif + +#if __GNUC__ >= 7 +// Assume these are available if the compiler claims to be a recent GCC: +# define _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP 1 +# define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 +# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 +# define _GLIBCXX_BUILTIN_IS_SAME_AS(T, U) __is_same_as(T, U) +# if __GNUC__ >= 9 +# define _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 1 +# endif +#elif defined(__is_identifier) && defined(__has_builtin) +// For non-GNU compilers: +# if ! __is_identifier(__has_unique_object_representations) +# define _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP 1 +# endif +# if ! __is_identifier(__is_aggregate) +# define _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE 1 +# endif +# if __has_builtin(__builtin_launder) +# define _GLIBCXX_HAVE_BUILTIN_LAUNDER 1 +# endif +# if __has_builtin(__builtin_is_constant_evaluated) +# define _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED 1 +# endif +# if ! __is_identifier(__is_same) +# define _GLIBCXX_BUILTIN_IS_SAME_AS(T, U) __is_same(T, U) +# endif +#endif // GCC + +// PSTL configuration + +#if __cplusplus >= 201703L +// This header is not installed for freestanding: +#if __has_include() +// Preserved here so we have some idea which version of upstream we've pulled in +// #define PSTL_VERSION 9000 + +// For now this defaults to being based on the presence of Thread Building Blocks +# ifndef _GLIBCXX_USE_TBB_PAR_BACKEND +# define _GLIBCXX_USE_TBB_PAR_BACKEND __has_include() +# endif +// This section will need some rework when a new (default) backend type is added +# if _GLIBCXX_USE_TBB_PAR_BACKEND +# define _PSTL_PAR_BACKEND_TBB +# else +# define _PSTL_PAR_BACKEND_SERIAL +# endif + +# define _PSTL_ASSERT(_Condition) __glibcxx_assert(_Condition) +# define _PSTL_ASSERT_MSG(_Condition, _Message) __glibcxx_assert(_Condition) + +#include +#endif // __has_include +#endif // C++17 + +// End of prewritten config; the settings discovered at configure time follow. +/* config.h. Generated from config.h.in by configure. */ +/* config.h.in. Generated from configure.ac by autoheader. */ + +/* Define to 1 if you have the `acosf' function. */ +#define _GLIBCXX_HAVE_ACOSF 1 + +/* Define to 1 if you have the `acosl' function. */ +/* #undef _GLIBCXX_HAVE_ACOSL */ + +/* Define to 1 if you have the `aligned_alloc' function. */ +/* #undef _GLIBCXX_HAVE_ALIGNED_ALLOC */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_ARPA_INET_H */ + +/* Define to 1 if you have the `asinf' function. */ +#define _GLIBCXX_HAVE_ASINF 1 + +/* Define to 1 if you have the `asinl' function. */ +/* #undef _GLIBCXX_HAVE_ASINL */ + +/* Define to 1 if the target assembler supports .symver directive. */ +#define _GLIBCXX_HAVE_AS_SYMVER_DIRECTIVE 1 + +/* Define to 1 if you have the `atan2f' function. */ +#define _GLIBCXX_HAVE_ATAN2F 1 + +/* Define to 1 if you have the `atan2l' function. */ +/* #undef _GLIBCXX_HAVE_ATAN2L */ + +/* Define to 1 if you have the `atanf' function. */ +#define _GLIBCXX_HAVE_ATANF 1 + +/* Define to 1 if you have the `atanl' function. */ +/* #undef _GLIBCXX_HAVE_ATANL */ + +/* Defined if shared_ptr reference counting should use atomic operations. */ +/* #undef _GLIBCXX_HAVE_ATOMIC_LOCK_POLICY */ + +/* Define to 1 if you have the `at_quick_exit' function. */ +/* #undef _GLIBCXX_HAVE_AT_QUICK_EXIT */ + +/* Define to 1 if the target assembler supports thread-local storage. */ +/* #undef _GLIBCXX_HAVE_CC_TLS */ + +/* Define to 1 if you have the `ceilf' function. */ +#define _GLIBCXX_HAVE_CEILF 1 + +/* Define to 1 if you have the `ceill' function. */ +/* #undef _GLIBCXX_HAVE_CEILL */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_COMPLEX_H 1 + +/* Define to 1 if you have the `cosf' function. */ +#define _GLIBCXX_HAVE_COSF 1 + +/* Define to 1 if you have the `coshf' function. */ +#define _GLIBCXX_HAVE_COSHF 1 + +/* Define to 1 if you have the `coshl' function. */ +/* #undef _GLIBCXX_HAVE_COSHL */ + +/* Define to 1 if you have the `cosl' function. */ +/* #undef _GLIBCXX_HAVE_COSL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_DIRENT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_DLFCN_H */ + +/* Define if EBADMSG exists. */ +//#define _GLIBCXX_HAVE_EBADMSG 1 + +/* Define if ECANCELED exists. */ +//#define _GLIBCXX_HAVE_ECANCELED 1 + +/* Define if ECHILD exists. */ +//#define _GLIBCXX_HAVE_ECHILD 1 + +/* Define if EIDRM exists. */ +//#define _GLIBCXX_HAVE_EIDRM 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_ENDIAN_H */ + +/* Define if ENODATA exists. */ +//#define _GLIBCXX_HAVE_ENODATA 1 + +/* Define if ENOLINK exists. */ +//#define _GLIBCXX_HAVE_ENOLINK 1 + +/* Define if ENOSPC exists. */ +//#define _GLIBCXX_HAVE_ENOSPC 1 + +/* Define if ENOSR exists. */ +//#define _GLIBCXX_HAVE_ENOSR 1 + +/* Define if ENOSTR exists. */ +//#define _GLIBCXX_HAVE_ENOSTR 1 + +/* Define if ENOTRECOVERABLE exists. */ +//#define _GLIBCXX_HAVE_ENOTRECOVERABLE 1 + +/* Define if ENOTSUP exists. */ +//#define _GLIBCXX_HAVE_ENOTSUP 1 + +/* Define if EOVERFLOW exists. */ +//#define _GLIBCXX_HAVE_EOVERFLOW 1 + +/* Define if EOWNERDEAD exists. */ +//#define _GLIBCXX_HAVE_EOWNERDEAD 1 + +/* Define if EPERM exists. */ +//#define _GLIBCXX_HAVE_EPERM 1 + +/* Define if EPROTO exists. */ +//#define _GLIBCXX_HAVE_EPROTO 1 + +/* Define if ETIME exists. */ +//#define _GLIBCXX_HAVE_ETIME 1 + +/* Define if ETIMEDOUT exists. */ +//#define _GLIBCXX_HAVE_ETIMEDOUT 1 + +/* Define if ETXTBSY exists. */ +//#define _GLIBCXX_HAVE_ETXTBSY 1 + +/* Define if EWOULDBLOCK exists. */ +//#define _GLIBCXX_HAVE_EWOULDBLOCK 1 + +/* Define to 1 if GCC 4.6 supported std::exception_ptr for the target */ +/* #undef _GLIBCXX_HAVE_EXCEPTION_PTR_SINCE_GCC46 */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_EXECINFO_H */ + +/* Define to 1 if you have the `expf' function. */ +#define _GLIBCXX_HAVE_EXPF 1 + +/* Define to 1 if you have the `expl' function. */ +/* #undef _GLIBCXX_HAVE_EXPL */ + +/* Define to 1 if you have the `fabsf' function. */ +#define _GLIBCXX_HAVE_FABSF 1 + +/* Define to 1 if you have the `fabsl' function. */ +/* #undef _GLIBCXX_HAVE_FABSL */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_FCNTL_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_FENV_H */ + +/* Define to 1 if you have the `finite' function. */ +/* #undef _GLIBCXX_HAVE_FINITE */ + +/* Define to 1 if you have the `finitef' function. */ +/* #undef _GLIBCXX_HAVE_FINITEF */ + +/* Define to 1 if you have the `finitel' function. */ +/* #undef _GLIBCXX_HAVE_FINITEL */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_FLOAT_H 1 + +/* Define to 1 if you have the `floorf' function. */ +#define _GLIBCXX_HAVE_FLOORF 1 + +/* Define to 1 if you have the `floorl' function. */ +/* #undef _GLIBCXX_HAVE_FLOORL */ + +/* Define to 1 if you have the `fmodf' function. */ +#define _GLIBCXX_HAVE_FMODF 1 + +/* Define to 1 if you have the `fmodl' function. */ +/* #undef _GLIBCXX_HAVE_FMODL */ + +/* Define to 1 if you have the `fpclass' function. */ +/* #undef _GLIBCXX_HAVE_FPCLASS */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_FP_H */ + +/* Define to 1 if you have the `frexpf' function. */ +#define _GLIBCXX_HAVE_FREXPF 1 + +/* Define to 1 if you have the `frexpl' function. */ +/* #undef _GLIBCXX_HAVE_FREXPL */ + +/* Define if _Unwind_GetIPInfo is available. */ +//#define _GLIBCXX_HAVE_GETIPINFO 1 + +/* Define if gets is available in before C++14. */ +#define _GLIBCXX_HAVE_GETS 1 + +/* Define to 1 if you have the `hypot' function. */ +#define _GLIBCXX_HAVE_HYPOT 1 + +/* Define to 1 if you have the `hypotf' function. */ +/* #undef _GLIBCXX_HAVE_HYPOTF */ + +/* Define to 1 if you have the `hypotl' function. */ +/* #undef _GLIBCXX_HAVE_HYPOTL */ + +/* Define if you have the iconv() function. */ +//#define _GLIBCXX_HAVE_ICONV 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_IEEEFP_H 1 + +/* Define if int64_t is available in . */ +#define _GLIBCXX_HAVE_INT64_T 1 + +/* Define if int64_t is a long. */ +/* #undef _GLIBCXX_HAVE_INT64_T_LONG */ + +/* Define if int64_t is a long long. */ +#define _GLIBCXX_HAVE_INT64_T_LONG_LONG 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_INTTYPES_H 1 + +/* Define to 1 if you have the `isinf' function. */ +/* #undef _GLIBCXX_HAVE_ISINF */ + +/* Define to 1 if you have the `isinff' function. */ +/* #undef _GLIBCXX_HAVE_ISINFF */ + +/* Define to 1 if you have the `isinfl' function. */ +/* #undef _GLIBCXX_HAVE_ISINFL */ + +/* Define to 1 if you have the `isnan' function. */ +/* #undef _GLIBCXX_HAVE_ISNAN */ + +/* Define to 1 if you have the `isnanf' function. */ +/* #undef _GLIBCXX_HAVE_ISNANF */ + +/* Define to 1 if you have the `isnanl' function. */ +/* #undef _GLIBCXX_HAVE_ISNANL */ + +/* Defined if iswblank exists. */ +//#define _GLIBCXX_HAVE_ISWBLANK 1 + +/* Define if LC_MESSAGES is available in . */ +#define _GLIBCXX_HAVE_LC_MESSAGES 1 + +/* Define to 1 if you have the `ldexpf' function. */ +#define _GLIBCXX_HAVE_LDEXPF 1 + +/* Define to 1 if you have the `ldexpl' function. */ +/* #undef _GLIBCXX_HAVE_LDEXPL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LIBINTL_H */ + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_AS 0 + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_DATA 0 + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_FSIZE 0 + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_RSS 0 + +/* Only used in build directory testsuite_hooks.h. */ +#define _GLIBCXX_HAVE_LIMIT_VMEM 0 + +/* Define if futex syscall is available. */ +/* #undef _GLIBCXX_HAVE_LINUX_FUTEX */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LINUX_RANDOM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_LINUX_TYPES_H */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_LOCALE_H 1 + +/* Define to 1 if you have the `log10f' function. */ +#define _GLIBCXX_HAVE_LOG10F 1 + +/* Define to 1 if you have the `log10l' function. */ +/* #undef _GLIBCXX_HAVE_LOG10L */ + +/* Define to 1 if you have the `logf' function. */ +#define _GLIBCXX_HAVE_LOGF 1 + +/* Define to 1 if you have the `logl' function. */ +/* #undef _GLIBCXX_HAVE_LOGL */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_MACHINE_ENDIAN_H 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_MACHINE_PARAM_H 1 + +/* Define if mbstate_t exists in wchar.h. */ +//#define _GLIBCXX_HAVE_MBSTATE_T 1 + +/* Define to 1 if you have the `memalign' function. */ +//#define _GLIBCXX_HAVE_MEMALIGN 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_MEMORY_H 1 + +/* Define to 1 if you have the `modf' function. */ +/* #undef _GLIBCXX_HAVE_MODF */ + +/* Define to 1 if you have the `modff' function. */ +#define _GLIBCXX_HAVE_MODFF 1 + +/* Define to 1 if you have the `modfl' function. */ +/* #undef _GLIBCXX_HAVE_MODFL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NAN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETDB_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETINET_IN_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_NETINET_TCP_H */ + +/* Define if defines obsolete isinf function. */ +/* #undef _GLIBCXX_HAVE_OBSOLETE_ISINF */ + +/* Define if defines obsolete isnan function. */ +/* #undef _GLIBCXX_HAVE_OBSOLETE_ISNAN */ + +/* Define if poll is available in . */ +/* #undef _GLIBCXX_HAVE_POLL */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_POLL_H */ + +/* Define to 1 if you have the `posix_memalign' function. */ +/* #undef _GLIBCXX_HAVE_POSIX_MEMALIGN */ + +/* Define to 1 if you have the `powf' function. */ +#define _GLIBCXX_HAVE_POWF 1 + +/* Define to 1 if you have the `powl' function. */ +/* #undef _GLIBCXX_HAVE_POWL */ + +/* Define to 1 if you have the `qfpclass' function. */ +/* #undef _GLIBCXX_HAVE_QFPCLASS */ + +/* Define to 1 if you have the `quick_exit' function. */ +/* #undef _GLIBCXX_HAVE_QUICK_EXIT */ + +/* Define to 1 if you have the `setenv' function. */ +/* #undef _GLIBCXX_HAVE_SETENV */ + +/* Define to 1 if you have the `sincos' function. */ +/* #undef _GLIBCXX_HAVE_SINCOS */ + +/* Define to 1 if you have the `sincosf' function. */ +/* #undef _GLIBCXX_HAVE_SINCOSF */ + +/* Define to 1 if you have the `sincosl' function. */ +/* #undef _GLIBCXX_HAVE_SINCOSL */ + +/* Define to 1 if you have the `sinf' function. */ +#define _GLIBCXX_HAVE_SINF 1 + +/* Define to 1 if you have the `sinhf' function. */ +#define _GLIBCXX_HAVE_SINHF 1 + +/* Define to 1 if you have the `sinhl' function. */ +/* #undef _GLIBCXX_HAVE_SINHL */ + +/* Define to 1 if you have the `sinl' function. */ +/* #undef _GLIBCXX_HAVE_SINL */ + +/* Defined if sleep exists. */ +//#define _GLIBCXX_HAVE_SLEEP 1 + +/* Define to 1 if you have the `sqrtf' function. */ +#define _GLIBCXX_HAVE_SQRTF 1 + +/* Define to 1 if you have the `sqrtl' function. */ +/* #undef _GLIBCXX_HAVE_SQRTL */ + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDALIGN_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDBOOL_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDINT_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STDLIB_H 1 + +/* Define if strerror_l is available in . */ +/* #undef _GLIBCXX_HAVE_STRERROR_L */ + +/* Define if strerror_r is available in . */ +#define _GLIBCXX_HAVE_STRERROR_R 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STRINGS_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_STRING_H 1 + +/* Define to 1 if you have the `strtof' function. */ +#define _GLIBCXX_HAVE_STRTOF 1 + +/* Define to 1 if you have the `strtold' function. */ +/* #undef _GLIBCXX_HAVE_STRTOLD */ + +/* Define to 1 if `d_type' is a member of `struct dirent'. */ +/* #undef _GLIBCXX_HAVE_STRUCT_DIRENT_D_TYPE */ + +/* Define if strxfrm_l is available in . */ +/* #undef _GLIBCXX_HAVE_STRXFRM_L */ + +/* Define to 1 if the target runtime linker supports binding the same symbol + to different versions. */ +/* #undef _GLIBCXX_HAVE_SYMVER_SYMBOL_RENAMING_RUNTIME_SUPPORT */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_FILIO_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_IOCTL_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_IPC_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_ISA_DEFS_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_MACHINE_H */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_SYS_PARAM_H 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_SYS_RESOURCE_H 1 + +/* Define to 1 if you have a suitable header file */ +/* #undef _GLIBCXX_HAVE_SYS_SDT_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SEM_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SOCKET_H */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_STATVFS_H */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_SYS_STAT_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_SYSINFO_H */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_SYS_TIME_H 1 + +/* Define to 1 if you have the header file. */ +#define _GLIBCXX_HAVE_SYS_TYPES_H 1 + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_SYS_UIO_H */ + +/* Define if S_IFREG is available in . */ +/* #undef _GLIBCXX_HAVE_S_IFREG */ + +/* Define if S_ISREG is available in . */ +//#define _GLIBCXX_HAVE_S_ISREG 1 + +/* Define to 1 if you have the `tanf' function. */ +#define _GLIBCXX_HAVE_TANF 1 + +/* Define to 1 if you have the `tanhf' function. */ +#define _GLIBCXX_HAVE_TANHF 1 + +/* Define to 1 if you have the `tanhl' function. */ +/* #undef _GLIBCXX_HAVE_TANHL */ + +/* Define to 1 if you have the `tanl' function. */ +/* #undef _GLIBCXX_HAVE_TANL */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_TGMATH_H 1 + +/* Define to 1 if you have the `timespec_get' function. */ +/* #undef _GLIBCXX_HAVE_TIMESPEC_GET */ + +/* Define to 1 if the target supports thread-local storage. */ +/* #undef _GLIBCXX_HAVE_TLS */ + +/* Define to 1 if you have the header file. */ +/* #undef _GLIBCXX_HAVE_UCHAR_H */ + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_UNISTD_H 1 + +/* Defined if usleep exists. */ +//#define _GLIBCXX_HAVE_USLEEP 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_UTIME_H 1 + +/* Defined if vfwscanf exists. */ +//#define _GLIBCXX_HAVE_VFWSCANF 1 + +/* Defined if vswscanf exists. */ +//#define _GLIBCXX_HAVE_VSWSCANF 1 + +/* Defined if vwscanf exists. */ +//#define _GLIBCXX_HAVE_VWSCANF 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_WCHAR_H 1 + +/* Defined if wcstof exists. */ +//#define _GLIBCXX_HAVE_WCSTOF 1 + +/* Define to 1 if you have the header file. */ +//#define _GLIBCXX_HAVE_WCTYPE_H 1 + +/* Defined if Sleep exists. */ +/* #undef _GLIBCXX_HAVE_WIN32_SLEEP */ + +/* Define if writev is available in . */ +/* #undef _GLIBCXX_HAVE_WRITEV */ + +/* Define to 1 if you have the `_acosf' function. */ +/* #undef _GLIBCXX_HAVE__ACOSF */ + +/* Define to 1 if you have the `_acosl' function. */ +/* #undef _GLIBCXX_HAVE__ACOSL */ + +/* Define to 1 if you have the `_aligned_malloc' function. */ +/* #undef _GLIBCXX_HAVE__ALIGNED_MALLOC */ + +/* Define to 1 if you have the `_asinf' function. */ +/* #undef _GLIBCXX_HAVE__ASINF */ + +/* Define to 1 if you have the `_asinl' function. */ +/* #undef _GLIBCXX_HAVE__ASINL */ + +/* Define to 1 if you have the `_atan2f' function. */ +/* #undef _GLIBCXX_HAVE__ATAN2F */ + +/* Define to 1 if you have the `_atan2l' function. */ +/* #undef _GLIBCXX_HAVE__ATAN2L */ + +/* Define to 1 if you have the `_atanf' function. */ +/* #undef _GLIBCXX_HAVE__ATANF */ + +/* Define to 1 if you have the `_atanl' function. */ +/* #undef _GLIBCXX_HAVE__ATANL */ + +/* Define to 1 if you have the `_ceilf' function. */ +/* #undef _GLIBCXX_HAVE__CEILF */ + +/* Define to 1 if you have the `_ceill' function. */ +/* #undef _GLIBCXX_HAVE__CEILL */ + +/* Define to 1 if you have the `_cosf' function. */ +/* #undef _GLIBCXX_HAVE__COSF */ + +/* Define to 1 if you have the `_coshf' function. */ +/* #undef _GLIBCXX_HAVE__COSHF */ + +/* Define to 1 if you have the `_coshl' function. */ +/* #undef _GLIBCXX_HAVE__COSHL */ + +/* Define to 1 if you have the `_cosl' function. */ +/* #undef _GLIBCXX_HAVE__COSL */ + +/* Define to 1 if you have the `_expf' function. */ +/* #undef _GLIBCXX_HAVE__EXPF */ + +/* Define to 1 if you have the `_expl' function. */ +/* #undef _GLIBCXX_HAVE__EXPL */ + +/* Define to 1 if you have the `_fabsf' function. */ +/* #undef _GLIBCXX_HAVE__FABSF */ + +/* Define to 1 if you have the `_fabsl' function. */ +/* #undef _GLIBCXX_HAVE__FABSL */ + +/* Define to 1 if you have the `_finite' function. */ +/* #undef _GLIBCXX_HAVE__FINITE */ + +/* Define to 1 if you have the `_finitef' function. */ +/* #undef _GLIBCXX_HAVE__FINITEF */ + +/* Define to 1 if you have the `_finitel' function. */ +/* #undef _GLIBCXX_HAVE__FINITEL */ + +/* Define to 1 if you have the `_floorf' function. */ +/* #undef _GLIBCXX_HAVE__FLOORF */ + +/* Define to 1 if you have the `_floorl' function. */ +/* #undef _GLIBCXX_HAVE__FLOORL */ + +/* Define to 1 if you have the `_fmodf' function. */ +/* #undef _GLIBCXX_HAVE__FMODF */ + +/* Define to 1 if you have the `_fmodl' function. */ +/* #undef _GLIBCXX_HAVE__FMODL */ + +/* Define to 1 if you have the `_fpclass' function. */ +/* #undef _GLIBCXX_HAVE__FPCLASS */ + +/* Define to 1 if you have the `_frexpf' function. */ +/* #undef _GLIBCXX_HAVE__FREXPF */ + +/* Define to 1 if you have the `_frexpl' function. */ +/* #undef _GLIBCXX_HAVE__FREXPL */ + +/* Define to 1 if you have the `_hypot' function. */ +/* #undef _GLIBCXX_HAVE__HYPOT */ + +/* Define to 1 if you have the `_hypotf' function. */ +/* #undef _GLIBCXX_HAVE__HYPOTF */ + +/* Define to 1 if you have the `_hypotl' function. */ +/* #undef _GLIBCXX_HAVE__HYPOTL */ + +/* Define to 1 if you have the `_isinf' function. */ +/* #undef _GLIBCXX_HAVE__ISINF */ + +/* Define to 1 if you have the `_isinff' function. */ +/* #undef _GLIBCXX_HAVE__ISINFF */ + +/* Define to 1 if you have the `_isinfl' function. */ +/* #undef _GLIBCXX_HAVE__ISINFL */ + +/* Define to 1 if you have the `_isnan' function. */ +/* #undef _GLIBCXX_HAVE__ISNAN */ + +/* Define to 1 if you have the `_isnanf' function. */ +/* #undef _GLIBCXX_HAVE__ISNANF */ + +/* Define to 1 if you have the `_isnanl' function. */ +/* #undef _GLIBCXX_HAVE__ISNANL */ + +/* Define to 1 if you have the `_ldexpf' function. */ +/* #undef _GLIBCXX_HAVE__LDEXPF */ + +/* Define to 1 if you have the `_ldexpl' function. */ +/* #undef _GLIBCXX_HAVE__LDEXPL */ + +/* Define to 1 if you have the `_log10f' function. */ +/* #undef _GLIBCXX_HAVE__LOG10F */ + +/* Define to 1 if you have the `_log10l' function. */ +/* #undef _GLIBCXX_HAVE__LOG10L */ + +/* Define to 1 if you have the `_logf' function. */ +/* #undef _GLIBCXX_HAVE__LOGF */ + +/* Define to 1 if you have the `_logl' function. */ +/* #undef _GLIBCXX_HAVE__LOGL */ + +/* Define to 1 if you have the `_modf' function. */ +/* #undef _GLIBCXX_HAVE__MODF */ + +/* Define to 1 if you have the `_modff' function. */ +/* #undef _GLIBCXX_HAVE__MODFF */ + +/* Define to 1 if you have the `_modfl' function. */ +/* #undef _GLIBCXX_HAVE__MODFL */ + +/* Define to 1 if you have the `_powf' function. */ +/* #undef _GLIBCXX_HAVE__POWF */ + +/* Define to 1 if you have the `_powl' function. */ +/* #undef _GLIBCXX_HAVE__POWL */ + +/* Define to 1 if you have the `_qfpclass' function. */ +/* #undef _GLIBCXX_HAVE__QFPCLASS */ + +/* Define to 1 if you have the `_sincos' function. */ +/* #undef _GLIBCXX_HAVE__SINCOS */ + +/* Define to 1 if you have the `_sincosf' function. */ +/* #undef _GLIBCXX_HAVE__SINCOSF */ + +/* Define to 1 if you have the `_sincosl' function. */ +/* #undef _GLIBCXX_HAVE__SINCOSL */ + +/* Define to 1 if you have the `_sinf' function. */ +/* #undef _GLIBCXX_HAVE__SINF */ + +/* Define to 1 if you have the `_sinhf' function. */ +/* #undef _GLIBCXX_HAVE__SINHF */ + +/* Define to 1 if you have the `_sinhl' function. */ +/* #undef _GLIBCXX_HAVE__SINHL */ + +/* Define to 1 if you have the `_sinl' function. */ +/* #undef _GLIBCXX_HAVE__SINL */ + +/* Define to 1 if you have the `_sqrtf' function. */ +/* #undef _GLIBCXX_HAVE__SQRTF */ + +/* Define to 1 if you have the `_sqrtl' function. */ +/* #undef _GLIBCXX_HAVE__SQRTL */ + +/* Define to 1 if you have the `_tanf' function. */ +/* #undef _GLIBCXX_HAVE__TANF */ + +/* Define to 1 if you have the `_tanhf' function. */ +/* #undef _GLIBCXX_HAVE__TANHF */ + +/* Define to 1 if you have the `_tanhl' function. */ +/* #undef _GLIBCXX_HAVE__TANHL */ + +/* Define to 1 if you have the `_tanl' function. */ +/* #undef _GLIBCXX_HAVE__TANL */ + +/* Define to 1 if you have the `_wfopen' function. */ +/* #undef _GLIBCXX_HAVE__WFOPEN */ + +/* Define to 1 if you have the `__cxa_thread_atexit' function. */ +/* #undef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT */ + +/* Define to 1 if you have the `__cxa_thread_atexit_impl' function. */ +/* #undef _GLIBCXX_HAVE___CXA_THREAD_ATEXIT_IMPL */ + +/* Define as const if the declaration of iconv() needs const. */ +/* #undef _GLIBCXX_ICONV_CONST */ + +/* Define to the sub-directory in which libtool stores uninstalled libraries. + */ +#define LT_OBJDIR ".libs/" + +/* Name of package */ +/* #undef _GLIBCXX_PACKAGE */ + +/* Define to the address where bug reports for this package should be sent. */ +#define _GLIBCXX_PACKAGE_BUGREPORT "" + +/* Define to the full name of this package. */ +#define _GLIBCXX_PACKAGE_NAME "package-unused" + +/* Define to the full name and version of this package. */ +#define _GLIBCXX_PACKAGE_STRING "package-unused version-unused" + +/* Define to the one symbol short name of this package. */ +#define _GLIBCXX_PACKAGE_TARNAME "libstdc++" + +/* Define to the home page for this package. */ +#define _GLIBCXX_PACKAGE_URL "" + +/* Define to the version of this package. */ +#define _GLIBCXX_PACKAGE__GLIBCXX_VERSION "version-unused" + +/* The size of `char', as computed by sizeof. */ +/* #undef SIZEOF_CHAR */ + +/* The size of `int', as computed by sizeof. */ +/* #undef SIZEOF_INT */ + +/* The size of `long', as computed by sizeof. */ +/* #undef SIZEOF_LONG */ + +/* The size of `short', as computed by sizeof. */ +/* #undef SIZEOF_SHORT */ + +/* The size of `void *', as computed by sizeof. */ +/* #undef SIZEOF_VOID_P */ + +/* Define to 1 if you have the ANSI C header files. */ +#define STDC_HEADERS 1 + +/* Version number of package */ +/* #undef _GLIBCXX_VERSION */ + +/* Number of bits in a file offset, on hosts where this is settable. */ +/* #undef _GLIBCXX_FILE_OFFSET_BITS */ + +/* Define if C99 functions in should be used in for + C++11. Using compiler builtins for these functions requires corresponding + C99 library functions to be present. */ +/* #undef _GLIBCXX11_USE_C99_COMPLEX */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +#define _GLIBCXX11_USE_C99_MATH 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +#define _GLIBCXX11_USE_C99_STDIO 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +#define _GLIBCXX11_USE_C99_STDLIB 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++11. */ +//#define _GLIBCXX11_USE_C99_WCHAR 1 + +/* Define if C99 functions in should be used in for + C++98. Using compiler builtins for these functions requires corresponding + C99 library functions to be present. */ +/* #undef _GLIBCXX98_USE_C99_COMPLEX */ + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +#define _GLIBCXX98_USE_C99_MATH 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +#define _GLIBCXX98_USE_C99_STDIO 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +#define _GLIBCXX98_USE_C99_STDLIB 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std for C++98. */ +//#define _GLIBCXX98_USE_C99_WCHAR 1 + +/* Define if the compiler supports C++11 atomics. */ +/* #undef _GLIBCXX_ATOMIC_BUILTINS */ + +/* Define to use concept checking code from the boost libraries. */ +/* #undef _GLIBCXX_CONCEPT_CHECKS */ + +/* Define to 1 if a fully dynamic basic_string is wanted, 0 to disable, + undefined for platform defaults */ +#define _GLIBCXX_FULLY_DYNAMIC_STRING 0 + +/* Define if gthreads library is available. */ +/* #undef _GLIBCXX_HAS_GTHREADS */ + +/* Define to 1 if a full hosted library is built, or 0 if freestanding. */ +#define _GLIBCXX_HOSTED 1 + +/* Define if compatibility should be provided for -mlong-double-64. */ + +/* Define to the letter to which size_t is mangled. */ +#define _GLIBCXX_MANGLE_SIZE_T j + +/* Define if C99 llrint and llround functions are missing from . */ +#define _GLIBCXX_NO_C99_ROUNDING_FUNCS + +/* Define if ptrdiff_t is int. */ +#define _GLIBCXX_PTRDIFF_T_IS_INT 1 + +/* Define if using setrlimit to set resource limits during "make check" */ +/* #undef _GLIBCXX_RES_LIMITS */ + +/* Define if size_t is unsigned int. */ +#define _GLIBCXX_SIZE_T_IS_UINT 1 + +/* Define to the value of the EOF integer constant. */ +#define _GLIBCXX_STDIO_EOF -1 + +/* Define to the value of the SEEK_CUR integer constant. */ +#define _GLIBCXX_STDIO_SEEK_CUR 1 + +/* Define to the value of the SEEK_END integer constant. */ +#define _GLIBCXX_STDIO_SEEK_END 2 + +/* Define to use symbol versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER */ + +/* Define to use darwin versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_DARWIN */ + +/* Define to use GNU versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_GNU */ + +/* Define to use GNU namespace versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_GNU_NAMESPACE */ + +/* Define to use Sun versioning in the shared library. */ +/* #undef _GLIBCXX_SYMVER_SUN */ + +/* Define if C11 functions in should be imported into namespace std + in . */ +/* #undef _GLIBCXX_USE_C11_UCHAR_CXX11 */ + +/* Define if C99 functions or macros from , , , + , and can be used or exposed. */ +/* #undef _GLIBCXX_USE_C99 */ + +/* Define if C99 functions in should be used in . + Using compiler builtins for these functions requires corresponding C99 + library functions to be present. */ +/* #undef _GLIBCXX_USE_C99_COMPLEX_TR1 */ + +/* Define if C99 functions in should be imported in in + namespace std::tr1. */ +#define _GLIBCXX_USE_C99_CTYPE_TR1 1 + +/* Define if C99 functions in should be imported in in + namespace std::tr1. */ +/* #undef _GLIBCXX_USE_C99_FENV_TR1 */ + +/* Define if C99 functions in should be imported in + in namespace std::tr1. */ +#define _GLIBCXX_USE_C99_INTTYPES_TR1 1 + +/* Define if wchar_t C99 functions in should be imported in + in namespace std::tr1. */ +#define _GLIBCXX_USE_C99_INTTYPES_WCHAR_T_TR1 1 + +/* Define if C99 functions or macros in should be imported in + in namespace std::tr1. */ +#define _GLIBCXX_USE_C99_MATH_TR1 1 + +/* Define if C99 types in should be imported in in + namespace std::tr1. */ +#define _GLIBCXX_USE_C99_STDINT_TR1 1 + +/* Defined if clock_gettime syscall has monotonic and realtime clock support. + */ +/* #undef _GLIBCXX_USE_CLOCK_GETTIME_SYSCALL */ + +/* Defined if clock_gettime has monotonic clock support. */ +/* #undef _GLIBCXX_USE_CLOCK_MONOTONIC */ + +/* Defined if clock_gettime has realtime clock support. */ +/* #undef _GLIBCXX_USE_CLOCK_REALTIME */ + +/* Define if ISO/IEC TR 24733 decimal floating point types are supported on + this host. */ +/* #undef _GLIBCXX_USE_DECIMAL_FLOAT */ + +/* Define if /dev/random and /dev/urandom are available for + std::random_device. */ +/* #undef _GLIBCXX_USE_DEV_RANDOM */ + +/* Define if fchmod is available in . */ +//#define _GLIBCXX_USE_FCHMOD 1 + +/* Define if fchmodat is available in . */ +//#define _GLIBCXX_USE_FCHMODAT 1 + + +/* Defined if gettimeofday is available. */ +//#define _GLIBCXX_USE_GETTIMEOFDAY 1 + +/* Define if get_nprocs is available in . */ +/* #undef _GLIBCXX_USE_GET_NPROCS */ + +/* Define if __int128 is supported on this host. */ +/* #undef _GLIBCXX_USE_INT128 */ + +/* Define if LFS support is available. */ +/* #undef _GLIBCXX_USE_LFS */ + +/* Define if code specialized for long long should be used. */ +#define _GLIBCXX_USE_LONG_LONG 1 + +/* Define if lstat is available in . */ +/* #undef _GLIBCXX_USE_LSTAT */ + +/* Defined if nanosleep is available. */ +/* #undef _GLIBCXX_USE_NANOSLEEP */ + +/* Define if NLS translations are to be used. */ +/* #undef _GLIBCXX_USE_NLS */ + +/* Define if pthreads_num_processors_np is available in . */ +/* #undef _GLIBCXX_USE_PTHREADS_NUM_PROCESSORS_NP */ + +/* Define if pthread_cond_clockwait is available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_COND_CLOCKWAIT */ + +/* Define if pthread_mutex_clocklock is available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK */ + +/* Define if pthread_rwlock_clockrdlock and pthread_rwlock_clockwrlock are + available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK */ + +/* Define if POSIX read/write locks are available in . */ +/* #undef _GLIBCXX_USE_PTHREAD_RWLOCK_T */ + +/* Define if /dev/random and /dev/urandom are available for the random_device + of TR1 (Chapter 5.1). */ +/* #undef _GLIBCXX_USE_RANDOM_TR1 */ + +/* Define if usable realpath is available in . */ +/* #undef _GLIBCXX_USE_REALPATH */ + +/* Defined if sched_yield is available. */ +/* #undef _GLIBCXX_USE_SCHED_YIELD */ + +/* Define if _SC_NPROCESSORS_ONLN is available in . */ +//#define _GLIBCXX_USE_SC_NPROCESSORS_ONLN 1 + +/* Define if _SC_NPROC_ONLN is available in . */ +/* #undef _GLIBCXX_USE_SC_NPROC_ONLN */ + +/* Define if sendfile is available in . */ +/* #undef _GLIBCXX_USE_SENDFILE */ + +/* Define if struct stat has timespec members. */ +/* #undef _GLIBCXX_USE_ST_MTIM */ + +/* Define if sysctl(), CTL_HW and HW_NCPU are available in . */ +/* #undef _GLIBCXX_USE_SYSCTL_HW_NCPU */ + +/* Define if obsolescent tmpnam is available in . */ +#define _GLIBCXX_USE_TMPNAM 1 + +/* Define if utimensat and UTIME_OMIT are available in and + AT_FDCWD in . */ +/* #undef _GLIBCXX_USE_UTIMENSAT */ + +/* Define if code specialized for wchar_t should be used. */ +//#define _GLIBCXX_USE_WCHAR_T 1 + +/* Define to 1 if a verbose library is built, or 0 otherwise. */ +#define _GLIBCXX_VERBOSE 1 + +/* Defined if as can handle rdrand. */ +/* #undef _GLIBCXX_X86_RDRAND */ + +/* Defined if as can handle rdseed. */ +/* #undef _GLIBCXX_X86_RDSEED */ + +/* Define to 1 if mutex_timedlock is available. */ +//#define _GTHREAD_USE_MUTEX_TIMEDLOCK 1 + +/* Define for large files, on AIX-style hosts. */ +/* #undef _GLIBCXX_LARGE_FILES */ + +/* Define if all C++11 floating point overloads are available in . */ +#if __cplusplus >= 201103L +/* #undef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP */ +#endif + +/* Define if all C++11 integral type overloads are available in . */ +#if __cplusplus >= 201103L +/* #undef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT */ +#endif + +#if defined (_GLIBCXX_HAVE__ACOSF) && ! defined (_GLIBCXX_HAVE_ACOSF) +# define _GLIBCXX_HAVE_ACOSF 1 +# define acosf _acosf +#endif + +#if defined (_GLIBCXX_HAVE__ACOSL) && ! defined (_GLIBCXX_HAVE_ACOSL) +# define _GLIBCXX_HAVE_ACOSL 1 +# define acosl _acosl +#endif + +#if defined (_GLIBCXX_HAVE__ASINF) && ! defined (_GLIBCXX_HAVE_ASINF) +# define _GLIBCXX_HAVE_ASINF 1 +# define asinf _asinf +#endif + +#if defined (_GLIBCXX_HAVE__ASINL) && ! defined (_GLIBCXX_HAVE_ASINL) +# define _GLIBCXX_HAVE_ASINL 1 +# define asinl _asinl +#endif + +#if defined (_GLIBCXX_HAVE__ATAN2F) && ! defined (_GLIBCXX_HAVE_ATAN2F) +# define _GLIBCXX_HAVE_ATAN2F 1 +# define atan2f _atan2f +#endif + +#if defined (_GLIBCXX_HAVE__ATAN2L) && ! defined (_GLIBCXX_HAVE_ATAN2L) +# define _GLIBCXX_HAVE_ATAN2L 1 +# define atan2l _atan2l +#endif + +#if defined (_GLIBCXX_HAVE__ATANF) && ! defined (_GLIBCXX_HAVE_ATANF) +# define _GLIBCXX_HAVE_ATANF 1 +# define atanf _atanf +#endif + +#if defined (_GLIBCXX_HAVE__ATANL) && ! defined (_GLIBCXX_HAVE_ATANL) +# define _GLIBCXX_HAVE_ATANL 1 +# define atanl _atanl +#endif + +#if defined (_GLIBCXX_HAVE__CEILF) && ! defined (_GLIBCXX_HAVE_CEILF) +# define _GLIBCXX_HAVE_CEILF 1 +# define ceilf _ceilf +#endif + +#if defined (_GLIBCXX_HAVE__CEILL) && ! defined (_GLIBCXX_HAVE_CEILL) +# define _GLIBCXX_HAVE_CEILL 1 +# define ceill _ceill +#endif + +#if defined (_GLIBCXX_HAVE__COSF) && ! defined (_GLIBCXX_HAVE_COSF) +# define _GLIBCXX_HAVE_COSF 1 +# define cosf _cosf +#endif + +#if defined (_GLIBCXX_HAVE__COSHF) && ! defined (_GLIBCXX_HAVE_COSHF) +# define _GLIBCXX_HAVE_COSHF 1 +# define coshf _coshf +#endif + +#if defined (_GLIBCXX_HAVE__COSHL) && ! defined (_GLIBCXX_HAVE_COSHL) +# define _GLIBCXX_HAVE_COSHL 1 +# define coshl _coshl +#endif + +#if defined (_GLIBCXX_HAVE__COSL) && ! defined (_GLIBCXX_HAVE_COSL) +# define _GLIBCXX_HAVE_COSL 1 +# define cosl _cosl +#endif + +#if defined (_GLIBCXX_HAVE__EXPF) && ! defined (_GLIBCXX_HAVE_EXPF) +# define _GLIBCXX_HAVE_EXPF 1 +# define expf _expf +#endif + +#if defined (_GLIBCXX_HAVE__EXPL) && ! defined (_GLIBCXX_HAVE_EXPL) +# define _GLIBCXX_HAVE_EXPL 1 +# define expl _expl +#endif + +#if defined (_GLIBCXX_HAVE__FABSF) && ! defined (_GLIBCXX_HAVE_FABSF) +# define _GLIBCXX_HAVE_FABSF 1 +# define fabsf _fabsf +#endif + +#if defined (_GLIBCXX_HAVE__FABSL) && ! defined (_GLIBCXX_HAVE_FABSL) +# define _GLIBCXX_HAVE_FABSL 1 +# define fabsl _fabsl +#endif + +#if defined (_GLIBCXX_HAVE__FINITE) && ! defined (_GLIBCXX_HAVE_FINITE) +# define _GLIBCXX_HAVE_FINITE 1 +# define finite _finite +#endif + +#if defined (_GLIBCXX_HAVE__FINITEF) && ! defined (_GLIBCXX_HAVE_FINITEF) +# define _GLIBCXX_HAVE_FINITEF 1 +# define finitef _finitef +#endif + +#if defined (_GLIBCXX_HAVE__FINITEL) && ! defined (_GLIBCXX_HAVE_FINITEL) +# define _GLIBCXX_HAVE_FINITEL 1 +# define finitel _finitel +#endif + +#if defined (_GLIBCXX_HAVE__FLOORF) && ! defined (_GLIBCXX_HAVE_FLOORF) +# define _GLIBCXX_HAVE_FLOORF 1 +# define floorf _floorf +#endif + +#if defined (_GLIBCXX_HAVE__FLOORL) && ! defined (_GLIBCXX_HAVE_FLOORL) +# define _GLIBCXX_HAVE_FLOORL 1 +# define floorl _floorl +#endif + +#if defined (_GLIBCXX_HAVE__FMODF) && ! defined (_GLIBCXX_HAVE_FMODF) +# define _GLIBCXX_HAVE_FMODF 1 +# define fmodf _fmodf +#endif + +#if defined (_GLIBCXX_HAVE__FMODL) && ! defined (_GLIBCXX_HAVE_FMODL) +# define _GLIBCXX_HAVE_FMODL 1 +# define fmodl _fmodl +#endif + +#if defined (_GLIBCXX_HAVE__FPCLASS) && ! defined (_GLIBCXX_HAVE_FPCLASS) +# define _GLIBCXX_HAVE_FPCLASS 1 +# define fpclass _fpclass +#endif + +#if defined (_GLIBCXX_HAVE__FREXPF) && ! defined (_GLIBCXX_HAVE_FREXPF) +# define _GLIBCXX_HAVE_FREXPF 1 +# define frexpf _frexpf +#endif + +#if defined (_GLIBCXX_HAVE__FREXPL) && ! defined (_GLIBCXX_HAVE_FREXPL) +# define _GLIBCXX_HAVE_FREXPL 1 +# define frexpl _frexpl +#endif + +#if defined (_GLIBCXX_HAVE__HYPOT) && ! defined (_GLIBCXX_HAVE_HYPOT) +# define _GLIBCXX_HAVE_HYPOT 1 +# define hypot _hypot +#endif + +#if defined (_GLIBCXX_HAVE__HYPOTF) && ! defined (_GLIBCXX_HAVE_HYPOTF) +# define _GLIBCXX_HAVE_HYPOTF 1 +# define hypotf _hypotf +#endif + +#if defined (_GLIBCXX_HAVE__HYPOTL) && ! defined (_GLIBCXX_HAVE_HYPOTL) +# define _GLIBCXX_HAVE_HYPOTL 1 +# define hypotl _hypotl +#endif + +#if defined (_GLIBCXX_HAVE__ISINF) && ! defined (_GLIBCXX_HAVE_ISINF) +# define _GLIBCXX_HAVE_ISINF 1 +# define isinf _isinf +#endif + +#if defined (_GLIBCXX_HAVE__ISINFF) && ! defined (_GLIBCXX_HAVE_ISINFF) +# define _GLIBCXX_HAVE_ISINFF 1 +# define isinff _isinff +#endif + +#if defined (_GLIBCXX_HAVE__ISINFL) && ! defined (_GLIBCXX_HAVE_ISINFL) +# define _GLIBCXX_HAVE_ISINFL 1 +# define isinfl _isinfl +#endif + +#if defined (_GLIBCXX_HAVE__ISNAN) && ! defined (_GLIBCXX_HAVE_ISNAN) +# define _GLIBCXX_HAVE_ISNAN 1 +# define isnan _isnan +#endif + +#if defined (_GLIBCXX_HAVE__ISNANF) && ! defined (_GLIBCXX_HAVE_ISNANF) +# define _GLIBCXX_HAVE_ISNANF 1 +# define isnanf _isnanf +#endif + +#if defined (_GLIBCXX_HAVE__ISNANL) && ! defined (_GLIBCXX_HAVE_ISNANL) +# define _GLIBCXX_HAVE_ISNANL 1 +# define isnanl _isnanl +#endif + +#if defined (_GLIBCXX_HAVE__LDEXPF) && ! defined (_GLIBCXX_HAVE_LDEXPF) +# define _GLIBCXX_HAVE_LDEXPF 1 +# define ldexpf _ldexpf +#endif + +#if defined (_GLIBCXX_HAVE__LDEXPL) && ! defined (_GLIBCXX_HAVE_LDEXPL) +# define _GLIBCXX_HAVE_LDEXPL 1 +# define ldexpl _ldexpl +#endif + +#if defined (_GLIBCXX_HAVE__LOG10F) && ! defined (_GLIBCXX_HAVE_LOG10F) +# define _GLIBCXX_HAVE_LOG10F 1 +# define log10f _log10f +#endif + +#if defined (_GLIBCXX_HAVE__LOG10L) && ! defined (_GLIBCXX_HAVE_LOG10L) +# define _GLIBCXX_HAVE_LOG10L 1 +# define log10l _log10l +#endif + +#if defined (_GLIBCXX_HAVE__LOGF) && ! defined (_GLIBCXX_HAVE_LOGF) +# define _GLIBCXX_HAVE_LOGF 1 +# define logf _logf +#endif + +#if defined (_GLIBCXX_HAVE__LOGL) && ! defined (_GLIBCXX_HAVE_LOGL) +# define _GLIBCXX_HAVE_LOGL 1 +# define logl _logl +#endif + +#if defined (_GLIBCXX_HAVE__MODF) && ! defined (_GLIBCXX_HAVE_MODF) +# define _GLIBCXX_HAVE_MODF 1 +# define modf _modf +#endif + +#if defined (_GLIBCXX_HAVE__MODFF) && ! defined (_GLIBCXX_HAVE_MODFF) +# define _GLIBCXX_HAVE_MODFF 1 +# define modff _modff +#endif + +#if defined (_GLIBCXX_HAVE__MODFL) && ! defined (_GLIBCXX_HAVE_MODFL) +# define _GLIBCXX_HAVE_MODFL 1 +# define modfl _modfl +#endif + +#if defined (_GLIBCXX_HAVE__POWF) && ! defined (_GLIBCXX_HAVE_POWF) +# define _GLIBCXX_HAVE_POWF 1 +# define powf _powf +#endif + +#if defined (_GLIBCXX_HAVE__POWL) && ! defined (_GLIBCXX_HAVE_POWL) +# define _GLIBCXX_HAVE_POWL 1 +# define powl _powl +#endif + +#if defined (_GLIBCXX_HAVE__QFPCLASS) && ! defined (_GLIBCXX_HAVE_QFPCLASS) +# define _GLIBCXX_HAVE_QFPCLASS 1 +# define qfpclass _qfpclass +#endif + +#if defined (_GLIBCXX_HAVE__SINCOS) && ! defined (_GLIBCXX_HAVE_SINCOS) +# define _GLIBCXX_HAVE_SINCOS 1 +# define sincos _sincos +#endif + +#if defined (_GLIBCXX_HAVE__SINCOSF) && ! defined (_GLIBCXX_HAVE_SINCOSF) +# define _GLIBCXX_HAVE_SINCOSF 1 +# define sincosf _sincosf +#endif + +#if defined (_GLIBCXX_HAVE__SINCOSL) && ! defined (_GLIBCXX_HAVE_SINCOSL) +# define _GLIBCXX_HAVE_SINCOSL 1 +# define sincosl _sincosl +#endif + +#if defined (_GLIBCXX_HAVE__SINF) && ! defined (_GLIBCXX_HAVE_SINF) +# define _GLIBCXX_HAVE_SINF 1 +# define sinf _sinf +#endif + +#if defined (_GLIBCXX_HAVE__SINHF) && ! defined (_GLIBCXX_HAVE_SINHF) +# define _GLIBCXX_HAVE_SINHF 1 +# define sinhf _sinhf +#endif + +#if defined (_GLIBCXX_HAVE__SINHL) && ! defined (_GLIBCXX_HAVE_SINHL) +# define _GLIBCXX_HAVE_SINHL 1 +# define sinhl _sinhl +#endif + +#if defined (_GLIBCXX_HAVE__SINL) && ! defined (_GLIBCXX_HAVE_SINL) +# define _GLIBCXX_HAVE_SINL 1 +# define sinl _sinl +#endif + +#if defined (_GLIBCXX_HAVE__SQRTF) && ! defined (_GLIBCXX_HAVE_SQRTF) +# define _GLIBCXX_HAVE_SQRTF 1 +# define sqrtf _sqrtf +#endif + +#if defined (_GLIBCXX_HAVE__SQRTL) && ! defined (_GLIBCXX_HAVE_SQRTL) +# define _GLIBCXX_HAVE_SQRTL 1 +# define sqrtl _sqrtl +#endif + +#if defined (_GLIBCXX_HAVE__STRTOF) && ! defined (_GLIBCXX_HAVE_STRTOF) +# define _GLIBCXX_HAVE_STRTOF 1 +# define strtof _strtof +#endif + +#if defined (_GLIBCXX_HAVE__STRTOLD) && ! defined (_GLIBCXX_HAVE_STRTOLD) +# define _GLIBCXX_HAVE_STRTOLD 1 +# define strtold _strtold +#endif + +#if defined (_GLIBCXX_HAVE__TANF) && ! defined (_GLIBCXX_HAVE_TANF) +# define _GLIBCXX_HAVE_TANF 1 +# define tanf _tanf +#endif + +#if defined (_GLIBCXX_HAVE__TANHF) && ! defined (_GLIBCXX_HAVE_TANHF) +# define _GLIBCXX_HAVE_TANHF 1 +# define tanhf _tanhf +#endif + +#if defined (_GLIBCXX_HAVE__TANHL) && ! defined (_GLIBCXX_HAVE_TANHL) +# define _GLIBCXX_HAVE_TANHL 1 +# define tanhl _tanhl +#endif + +#if defined (_GLIBCXX_HAVE__TANL) && ! defined (_GLIBCXX_HAVE_TANL) +# define _GLIBCXX_HAVE_TANL 1 +# define tanl _tanl +#endif + +#endif // _GLIBCXX_CXX_CONFIG_H diff --git a/resources/sources/avr-libstdcpp/include/bits/char_traits.h b/resources/sources/avr-libstdcpp/include/bits/char_traits.h new file mode 100644 index 000000000..c6da184e4 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/char_traits.h @@ -0,0 +1,943 @@ +// Character Traits for use by standard string and iostream -*- C++ -*- + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/char_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{string} + */ + +// +// ISO C++ 14882: 21 Strings library +// + +#ifndef _CHAR_TRAITS_H +#define _CHAR_TRAITS_H 1 + +#pragma GCC system_header + +#include // std::copy, std::fill_n +#include // For streampos +#include // For WEOF, wmemmove, wmemset, etc. +#if __cplusplus > 201703L +# include +#endif + +#ifndef _GLIBCXX_ALWAYS_INLINE +# define _GLIBCXX_ALWAYS_INLINE inline __attribute__((__always_inline__)) +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Mapping from character type to associated types. + * + * @note This is an implementation class for the generic version + * of char_traits. It defines int_type, off_type, pos_type, and + * state_type. By default these are unsigned long, streamoff, + * streampos, and mbstate_t. Users who need a different set of + * types, but who don't need to change the definitions of any function + * defined in char_traits, can specialize __gnu_cxx::_Char_types + * while leaving __gnu_cxx::char_traits alone. */ + template + struct _Char_types + { + typedef unsigned long int_type; + typedef std::streampos pos_type; + typedef std::streamoff off_type; + typedef std::mbstate_t state_type; + }; + + + /** + * @brief Base class used to implement std::char_traits. + * + * @note For any given actual character type, this definition is + * probably wrong. (Most of the member functions are likely to be + * right, but the int_type and state_type typedefs, and the eof() + * member function, are likely to be wrong.) The reason this class + * exists is so users can specialize it. Classes in namespace std + * may not be specialized for fundamental types, but classes in + * namespace __gnu_cxx may be. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types + * for advice on how to make use of this class for @a unusual character + * types. Also, check out include/ext/pod_char_traits.h. + */ + template + struct char_traits + { + typedef _CharT char_type; + typedef typename _Char_types<_CharT>::int_type int_type; + typedef typename _Char_types<_CharT>::pos_type pos_type; + typedef typename _Char_types<_CharT>::off_type off_type; + typedef typename _Char_types<_CharT>::state_type state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = std::strong_ordering; +#endif + + static _GLIBCXX14_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } + + static _GLIBCXX14_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX14_CONSTEXPR std::size_t + length(const char_type* __s); + + static _GLIBCXX14_CONSTEXPR const char_type* + find(const char_type* __s, std::size_t __n, const char_type& __a); + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, std::size_t __n); + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, std::size_t __n, char_type __a); + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) + { return static_cast(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) + { return static_cast(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() + { return static_cast(_GLIBCXX_STDIO_EOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) + { return !eq_int_type(__c, eof()) ? __c : to_int_type(char_type()); } + }; + + template + _GLIBCXX14_CONSTEXPR int + char_traits<_CharT>:: + compare(const char_type* __s1, const char_type* __s2, std::size_t __n) + { + for (std::size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + template + _GLIBCXX14_CONSTEXPR std::size_t + char_traits<_CharT>:: + length(const char_type* __p) + { + std::size_t __i = 0; + while (!eq(__p[__i], char_type())) + ++__i; + return __i; + } + + template + _GLIBCXX14_CONSTEXPR const typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + find(const char_type* __s, std::size_t __n, const char_type& __a) + { + for (std::size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + move(char_type* __s1, const char_type* __s2, std::size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + if (__s1 > __s2 && __s1 < __s2 + __n) + std::copy_backward(__s2, __s2 + __n, __s1); + else + std::copy(__s2, __s2 + __n, __s1); + return __s1; + } +#endif + return static_cast<_CharT*>(__builtin_memmove(__s1, __s2, + __n * sizeof(char_type))); + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + copy(char_type* __s1, const char_type* __s2, std::size_t __n) + { + // NB: Inline std::copy so no recursive dependencies. + std::copy(__s2, __s2 + __n, __s1); + return __s1; + } + + template + _GLIBCXX20_CONSTEXPR + typename char_traits<_CharT>::char_type* + char_traits<_CharT>:: + assign(char_type* __s, std::size_t __n, char_type __a) + { + // NB: Inline std::fill_n so no recursive dependencies. + std::fill_n(__s, __n, __a); + return __s; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201703L +#define __cpp_lib_constexpr_char_traits 201611 + + /** + * @brief Determine whether the characters of a NULL-terminated + * string are known at compile time. + * @param __s The string. + * + * Assumes that _CharT is a built-in character type. + */ + template + static _GLIBCXX_ALWAYS_INLINE constexpr bool + __constant_string_p(const _CharT* __s) + { +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + (void) __s; + // In constexpr contexts all strings should be constant. + return __builtin_is_constant_evaluated(); +#else + while (__builtin_constant_p(*__s) && *__s) + __s++; + return __builtin_constant_p(*__s); +#endif + } + + /** + * @brief Determine whether the characters of a character array are + * known at compile time. + * @param __a The character array. + * @param __n Number of characters. + * + * Assumes that _CharT is a built-in character type. + */ + template + static _GLIBCXX_ALWAYS_INLINE constexpr bool + __constant_char_array_p(const _CharT* __a, size_t __n) + { +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + (void) __a; + (void) __n; + // In constexpr contexts all character arrays should be constant. + return __builtin_is_constant_evaluated(); +#else + size_t __i = 0; + while (__i < __n && __builtin_constant_p(__a[__i])) + __i++; + return __i == __n; +#endif + } +#endif + + // 21.1 + /** + * @brief Basis for explicit traits specializations. + * + * @note For any given actual character type, this definition is + * probably wrong. Since this is just a thin wrapper around + * __gnu_cxx::char_traits, it is possible to achieve a more + * appropriate definition by specializing __gnu_cxx::char_traits. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/strings.html#strings.string.character_types + * for advice on how to make use of this class for @a unusual character + * types. Also, check out include/ext/pod_char_traits.h. + */ + template + struct char_traits : public __gnu_cxx::char_traits<_CharT> + { }; + + + /// 21.1.3.1 char_traits specializations + template<> + struct char_traits + { + typedef char char_type; + typedef int int_type; + typedef streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { + // LWG 467. + return (static_cast(__c1) + < static_cast(__c2)); + } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits::compare(__s1, __s2, __n); +#endif + return __builtin_memcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus >= 201703L + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits::length(__s); +#endif + return __builtin_strlen(__s); + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return static_cast(__builtin_memchr(__s, __a, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return static_cast(__builtin_memmove(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return static_cast(__builtin_memcpy(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return static_cast(__builtin_memset(__s, __a, __n)); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return static_cast(__c); } + + // To keep both the byte 0xff and the eof symbol 0xffffffff + // from ending up as 0xffffffff. + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return static_cast(static_cast(__c)); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(_GLIBCXX_STDIO_EOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return (__c == eof()) ? 0 : __c; } + }; + + +#ifdef _GLIBCXX_USE_WCHAR_T + /// 21.1.3.2 char_traits specializations + template<> + struct char_traits + { + typedef wchar_t char_type; + typedef wint_t int_type; + typedef streamoff off_type; + typedef wstreampos pos_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits::compare(__s1, __s2, __n); +#endif + return wmemcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus >= 201703L + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits::length(__s); +#endif + return wcslen(__s); + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus >= 201703L + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return wmemchr(__s, __a, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return wmemmove(__s1, __s2, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return wmemcpy(__s1, __s2, __n); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return wmemset(__s, __a, __n); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return char_type(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return int_type(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(WEOF); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; +#endif //_GLIBCXX_USE_WCHAR_T + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct char_traits + { + typedef char8_t char_type; + typedef unsigned int int_type; + typedef u8streampos pos_type; + typedef streamoff off_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { __c1 = __c2; } + + static _GLIBCXX_CONSTEXPR bool + eq(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR bool + lt(const char_type& __c1, const char_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return 0; +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __constant_char_array_p(__s1, __n) + && __constant_char_array_p(__s2, __n)) + return __gnu_cxx::char_traits::compare(__s1, __s2, __n); +#endif + return __builtin_memcmp(__s1, __s2, __n); + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { +#if __cplusplus > 201402 + if (__constant_string_p(__s)) + return __gnu_cxx::char_traits::length(__s); +#endif + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + if (__n == 0) + return 0; +#if __cplusplus > 201402 + if (__builtin_constant_p(__n) + && __builtin_constant_p(__a) + && __constant_char_array_p(__s, __n)) + return __gnu_cxx::char_traits::find(__s, __n, __a); +#endif + return static_cast(__builtin_memchr(__s, __a, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return static_cast(__builtin_memmove(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return static_cast(__builtin_memcpy(__s1, __s2, __n)); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + if (__n == 0) + return __s; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::assign(__s, __n, __a); +#endif + return static_cast(__builtin_memset(__s, __a, __n)); + } + + static _GLIBCXX_CONSTEXPR char_type + to_char_type(const int_type& __c) _GLIBCXX_NOEXCEPT + { return char_type(__c); } + + static _GLIBCXX_CONSTEXPR int_type + to_int_type(const char_type& __c) _GLIBCXX_NOEXCEPT + { return int_type(__c); } + + static _GLIBCXX_CONSTEXPR bool + eq_int_type(const int_type& __c1, const int_type& __c2) _GLIBCXX_NOEXCEPT + { return __c1 == __c2; } + + static _GLIBCXX_CONSTEXPR int_type + eof() _GLIBCXX_NOEXCEPT + { return static_cast(-1); } + + static _GLIBCXX_CONSTEXPR int_type + not_eof(const int_type& __c) _GLIBCXX_NOEXCEPT + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; +#endif //_GLIBCXX_USE_CHAR8_T + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if __cplusplus >= 201103L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template<> + struct char_traits + { + typedef char16_t char_type; +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + typedef uint_least16_t int_type; +#elif defined __UINT_LEAST16_TYPE__ + typedef __UINT_LEAST16_TYPE__ int_type; +#else + typedef make_unsigned::type int_type; +#endif + typedef streamoff off_type; + typedef u16streampos pos_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) noexcept + { __c1 = __c2; } + + static constexpr bool + eq(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr bool + lt(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + for (size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + for (size_t __i = 0; __i < __n; ++__i) + assign(__s[__i], __a); + return __s; + } + + static constexpr char_type + to_char_type(const int_type& __c) noexcept + { return char_type(__c); } + + static constexpr int_type + to_int_type(const char_type& __c) noexcept + { return __c == eof() ? int_type(0xfffd) : int_type(__c); } + + static constexpr bool + eq_int_type(const int_type& __c1, const int_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr int_type + eof() noexcept + { return static_cast(-1); } + + static constexpr int_type + not_eof(const int_type& __c) noexcept + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; + + template<> + struct char_traits + { + typedef char32_t char_type; +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + typedef uint_least32_t int_type; +#elif defined __UINT_LEAST32_TYPE__ + typedef __UINT_LEAST32_TYPE__ int_type; +#else + typedef make_unsigned::type int_type; +#endif + typedef streamoff off_type; + typedef u32streampos pos_type; + typedef mbstate_t state_type; +#if __cpp_lib_three_way_comparison + using comparison_category = strong_ordering; +#endif + + static _GLIBCXX17_CONSTEXPR void + assign(char_type& __c1, const char_type& __c2) noexcept + { __c1 = __c2; } + + static constexpr bool + eq(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr bool + lt(const char_type& __c1, const char_type& __c2) noexcept + { return __c1 < __c2; } + + static _GLIBCXX17_CONSTEXPR int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (lt(__s1[__i], __s2[__i])) + return -1; + else if (lt(__s2[__i], __s1[__i])) + return 1; + return 0; + } + + static _GLIBCXX17_CONSTEXPR size_t + length(const char_type* __s) + { + size_t __i = 0; + while (!eq(__s[__i], char_type())) + ++__i; + return __i; + } + + static _GLIBCXX17_CONSTEXPR const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + for (size_t __i = 0; __i < __n; ++__i) + if (eq(__s[__i], __a)) + return __s + __i; + return 0; + } + + static _GLIBCXX20_CONSTEXPR char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::move(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memmove(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __gnu_cxx::char_traits::copy(__s1, __s2, __n); +#endif + return (static_cast + (__builtin_memcpy(__s1, __s2, __n * sizeof(char_type)))); + } + + static _GLIBCXX20_CONSTEXPR char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + for (size_t __i = 0; __i < __n; ++__i) + assign(__s[__i], __a); + return __s; + } + + static constexpr char_type + to_char_type(const int_type& __c) noexcept + { return char_type(__c); } + + static constexpr int_type + to_int_type(const char_type& __c) noexcept + { return int_type(__c); } + + static constexpr bool + eq_int_type(const int_type& __c1, const int_type& __c2) noexcept + { return __c1 == __c2; } + + static constexpr int_type + eof() noexcept + { return static_cast(-1); } + + static constexpr int_type + not_eof(const int_type& __c) noexcept + { return eq_int_type(__c, eof()) ? 0 : __c; } + }; + +#if __cpp_lib_three_way_comparison + namespace __detail + { + template + constexpr auto + __char_traits_cmp_cat(int __cmp) noexcept + { + if constexpr (requires { typename _ChTraits::comparison_category; }) + { + using _Cat = typename _ChTraits::comparison_category; + static_assert( !is_void_v> ); + return static_cast<_Cat>(__cmp <=> 0); + } + else + return static_cast(__cmp <=> 0); + } + } // namespace __detail +#endif // C++20 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _CHAR_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/charconv.h b/resources/sources/avr-libstdcpp/include/bits/charconv.h new file mode 100644 index 000000000..a3149bddb --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/charconv.h @@ -0,0 +1,106 @@ +// Numeric conversions (to_string, to_chars) -*- C++ -*- + +// Copyright (C) 2017-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/charconv.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{charconv} + */ + +#ifndef _GLIBCXX_CHARCONV_H +#define _GLIBCXX_CHARCONV_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace __detail +{ + // Generic implementation for arbitrary bases. + template + _GLIBCXX14_CONSTEXPR unsigned + __to_chars_len(_Tp __value, int __base = 10) noexcept + { + static_assert(is_integral<_Tp>::value, "implementation bug"); + static_assert(is_unsigned<_Tp>::value, "implementation bug"); + + unsigned __n = 1; + const unsigned __b2 = __base * __base; + const unsigned __b3 = __b2 * __base; + const unsigned long __b4 = __b3 * __base; + for (;;) + { + if (__value < (unsigned)__base) return __n; + if (__value < __b2) return __n + 1; + if (__value < __b3) return __n + 2; + if (__value < __b4) return __n + 3; + __value /= __b4; + __n += 4; + } + } + + // Write an unsigned integer value to the range [first,first+len). + // The caller is required to provide a buffer of exactly the right size + // (which can be determined by the __to_chars_len function). + template + void + __to_chars_10_impl(char* __first, unsigned __len, _Tp __val) noexcept + { + static_assert(is_integral<_Tp>::value, "implementation bug"); + static_assert(is_unsigned<_Tp>::value, "implementation bug"); + + static constexpr char __digits[201] = + "0001020304050607080910111213141516171819" + "2021222324252627282930313233343536373839" + "4041424344454647484950515253545556575859" + "6061626364656667686970717273747576777879" + "8081828384858687888990919293949596979899"; + unsigned __pos = __len - 1; + while (__val >= 100) + { + auto const __num = (__val % 100) * 2; + __val /= 100; + __first[__pos] = __digits[__num + 1]; + __first[__pos - 1] = __digits[__num]; + __pos -= 2; + } + if (__val >= 10) + { + auto const __num = __val * 2; + __first[1] = __digits[__num + 1]; + __first[0] = __digits[__num]; + } + else + __first[0] = '0' + __val; + } + +} // namespace __detail +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++11 +#endif // _GLIBCXX_CHARCONV_H diff --git a/resources/sources/avr-libstdcpp/include/bits/concept_check.h b/resources/sources/avr-libstdcpp/include/bits/concept_check.h new file mode 100644 index 000000000..8923a71fc --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/concept_check.h @@ -0,0 +1,81 @@ +// Concept-checking control -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/concept_check.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _CONCEPT_CHECK_H +#define _CONCEPT_CHECK_H 1 + +#pragma GCC system_header + +#include + +// All places in libstdc++-v3 where these are used, or /might/ be used, or +// don't need to be used, or perhaps /should/ be used, are commented with +// "concept requirements" (and maybe some more text). So grep like crazy +// if you're looking for additional places to use these. + +// Concept-checking code is off by default unless users turn it on via +// configure options or editing c++config.h. +// It is not supported for freestanding implementations. + +#if !defined(_GLIBCXX_CONCEPT_CHECKS) || !_GLIBCXX_HOSTED + +#define __glibcxx_function_requires(...) +#define __glibcxx_class_requires(_a,_b) +#define __glibcxx_class_requires2(_a,_b,_c) +#define __glibcxx_class_requires3(_a,_b,_c,_d) +#define __glibcxx_class_requires4(_a,_b,_c,_d,_e) + +#else // the checks are on + +#include + +// Note that the obvious and elegant approach of +// +//#define glibcxx_function_requires(C) debug::function_requires< debug::C >() +// +// won't work due to concept templates with more than one parameter, e.g., +// BinaryPredicateConcept. The preprocessor tries to split things up on +// the commas in the template argument list. We can't use an inner pair of +// parenthesis to hide the commas, because "debug::(Temp)" isn't +// a valid instantiation pattern. Thus, we steal a feature from C99. + +#define __glibcxx_function_requires(...) \ + __gnu_cxx::__function_requires< __gnu_cxx::__VA_ARGS__ >(); +#define __glibcxx_class_requires(_a,_C) \ + _GLIBCXX_CLASS_REQUIRES(_a, __gnu_cxx, _C); +#define __glibcxx_class_requires2(_a,_b,_C) \ + _GLIBCXX_CLASS_REQUIRES2(_a, _b, __gnu_cxx, _C); +#define __glibcxx_class_requires3(_a,_b,_c,_C) \ + _GLIBCXX_CLASS_REQUIRES3(_a, _b, _c, __gnu_cxx, _C); +#define __glibcxx_class_requires4(_a,_b,_c,_d,_C) \ + _GLIBCXX_CLASS_REQUIRES4(_a, _b, _c, _d, __gnu_cxx, _C); + +#endif // enable/disable + +#endif // _GLIBCXX_CONCEPT_CHECK diff --git a/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h b/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h new file mode 100644 index 000000000..ca83f590e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/cpp_type_traits.h @@ -0,0 +1,551 @@ +// The -*- C++ -*- type traits classes for internal use in libstdc++ + +// Copyright (C) 2000-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cpp_type_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{ext/type_traits} + */ + +// Written by Gabriel Dos Reis + +#ifndef _CPP_TYPE_TRAITS_H +#define _CPP_TYPE_TRAITS_H 1 + +#pragma GCC system_header + +#include + +// +// This file provides some compile-time information about various types. +// These representations were designed, on purpose, to be constant-expressions +// and not types as found in . In particular, they +// can be used in control structures and the optimizer hopefully will do +// the obvious thing. +// +// Why integral expressions, and not functions nor types? +// Firstly, these compile-time entities are used as template-arguments +// so function return values won't work: We need compile-time entities. +// We're left with types and constant integral expressions. +// Secondly, from the point of view of ease of use, type-based compile-time +// information is -not- *that* convenient. One has to write lots of +// overloaded functions and to hope that the compiler will select the right +// one. As a net effect, the overall structure isn't very clear at first +// glance. +// Thirdly, partial ordering and overload resolution (of function templates) +// is highly costly in terms of compiler-resource. It is a Good Thing to +// keep these resource consumption as least as possible. +// +// See valarray_array.h for a case use. +// +// -- Gaby (dosreis@cmla.ens-cachan.fr) 2000-03-06. +// +// Update 2005: types are also provided and has been +// removed. +// + +extern "C++" { + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct __true_type { }; + struct __false_type { }; + + template + struct __truth_type + { typedef __false_type __type; }; + + template<> + struct __truth_type + { typedef __true_type __type; }; + + // N.B. The conversions to bool are needed due to the issue + // explained in c++/19404. + template + struct __traitor + { + enum { __value = bool(_Sp::__value) || bool(_Tp::__value) }; + typedef typename __truth_type<__value>::__type __type; + }; + + // Compare for equality of types. + template + struct __are_same + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template + struct __are_same<_Tp, _Tp> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // Holds if the template-argument is a void type. + template + struct __is_void + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_void + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // + // Integer types + // + template + struct __is_integer + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // Thirteen specializations (yes there are eleven standard integer + // types; long long and unsigned long long are + // supported as extensions). Up to four target-specific __int + // types are supported as well. + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +# ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +# endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + +#if __cplusplus >= 201103L + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_integer + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#define __INT_N(TYPE) \ + template<> \ + struct __is_integer \ + { \ + enum { __value = 1 }; \ + typedef __true_type __type; \ + }; \ + template<> \ + struct __is_integer \ + { \ + enum { __value = 1 }; \ + typedef __true_type __type; \ + }; + +#ifdef __GLIBCXX_TYPE_INT_N_0 +__INT_N(__GLIBCXX_TYPE_INT_N_0) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 +__INT_N(__GLIBCXX_TYPE_INT_N_1) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 +__INT_N(__GLIBCXX_TYPE_INT_N_2) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 +__INT_N(__GLIBCXX_TYPE_INT_N_3) +#endif + +#undef __INT_N + + // + // Floating point types + // + template + struct __is_floating + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // three specializations (float, double and 'long double') + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_floating + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // + // Pointer types + // + template + struct __is_pointer + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template + struct __is_pointer<_Tp*> + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + // + // An arithmetic type is an integer type or a floating point type + // + template + struct __is_arithmetic + : public __traitor<__is_integer<_Tp>, __is_floating<_Tp> > + { }; + + // + // A scalar type is an arithmetic type or a pointer type + // + template + struct __is_scalar + : public __traitor<__is_arithmetic<_Tp>, __is_pointer<_Tp> > + { }; + + // + // For use in std::copy and std::find overloads for streambuf iterators. + // + template + struct __is_char + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_char + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct __is_char + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template + struct __is_byte + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; + +#if __cplusplus >= 201703L + enum class byte : unsigned char; + + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif // C++17 + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_byte + { + enum { __value = 1 }; + typedef __true_type __type; + }; +#endif + + template struct iterator_traits; + + // A type that is safe for use with memcpy, memmove, memcmp etc. + template + struct __is_nonvolatile_trivially_copyable + { + enum { __value = __is_trivially_copyable(_Tp) }; + }; + + // Cannot use memcpy/memmove/memcmp on volatile types even if they are + // trivially copyable, so ensure __memcpyable + // and similar will be false. + template + struct __is_nonvolatile_trivially_copyable + { + enum { __value = 0 }; + }; + + // Whether two iterator types can be used with memcpy/memmove. + template + struct __memcpyable + { + enum { __value = 0 }; + }; + + template + struct __memcpyable<_Tp*, _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcpyable<_Tp*, const _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + // Whether two iterator types can be used with memcmp. + // This trait only says it's well-formed to use memcmp, not that it + // gives the right answer for a given algorithm. So for example, std::equal + // needs to add additional checks that the types are integers or pointers, + // because other trivially copyable types can overload operator==. + template + struct __memcmpable + { + enum { __value = 0 }; + }; + + // OK to use memcmp with pointers to trivially copyable types. + template + struct __memcmpable<_Tp*, _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcmpable + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + template + struct __memcmpable<_Tp*, const _Tp*> + : __is_nonvolatile_trivially_copyable<_Tp> + { }; + + // Whether memcmp can be used to determine ordering for a type + // e.g. in std::lexicographical_compare or three-way comparisons. + // True for unsigned narrow character types (and std::byte). + template::__value> + struct __is_memcmp_ordered + { + static const bool __value = _Tp(-1) > _Tp(1); // is unsigned + }; + + template + struct __is_memcmp_ordered<_Tp, false> + { + static const bool __value = false; + }; + + // Whether two types can be compared using memcmp. + template + struct __is_memcmp_ordered_with + { + static const bool __value = __is_memcmp_ordered<_Tp>::__value + && __is_memcmp_ordered<_Up>::__value; + }; + + template + struct __is_memcmp_ordered_with<_Tp, _Up, false> + { + static const bool __value = false; + }; + +#if __cplusplus >= 201703L + // std::byte can only be compared to itself, not to other types. + template<> + struct __is_memcmp_ordered_with + { static constexpr bool __value = true; }; + + template + struct __is_memcmp_ordered_with<_Tp, std::byte, _SameSize> + { static constexpr bool __value = false; }; + + template + struct __is_memcmp_ordered_with + { static constexpr bool __value = false; }; +#endif + + // + // Move iterator type + // + template + struct __is_move_iterator + { + enum { __value = 0 }; + typedef __false_type __type; + }; + + // Fallback implementation of the function in bits/stl_iterator.h used to + // remove the move_iterator wrapper. + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __miter_base(_Iterator __it) + { return __it; } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#endif //_CPP_TYPE_TRAITS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h b/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h new file mode 100644 index 000000000..9e61a382b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/cxxabi_forced.h @@ -0,0 +1,60 @@ +// cxxabi.h subset for cancellation -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cxxabi_forced.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{cxxabi.h} + */ + +#ifndef _CXXABI_FORCED_H +#define _CXXABI_FORCED_H 1 + +#pragma GCC system_header + +#pragma GCC visibility push(default) + +#ifdef __cplusplus +namespace __cxxabiv1 +{ + /** + * @brief Thrown as part of forced unwinding. + * @ingroup exceptions + * + * A magic placeholder class that can be caught by reference to + * recognize forced unwinding. + */ + class __forced_unwind + { + virtual ~__forced_unwind() throw(); + + // Prevent catch by value. + virtual void __pure_dummy() = 0; + }; +} +#endif // __cplusplus + +#pragma GCC visibility pop + +#endif // __CXXABI_FORCED_H diff --git a/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h b/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h new file mode 100644 index 000000000..9ea0599ed --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/cxxabi_init_exception.h @@ -0,0 +1,80 @@ +// ABI Support -*- C++ -*- + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/cxxabi_init_exception.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef _CXXABI_INIT_EXCEPTION_H +#define _CXXABI_INIT_EXCEPTION_H 1 + +#pragma GCC system_header + +#pragma GCC visibility push(default) + +#include +#include + +#ifndef _GLIBCXX_CDTOR_CALLABI +#define _GLIBCXX_CDTOR_CALLABI +#define _GLIBCXX_HAVE_CDTOR_CALLABI 0 +#else +#define _GLIBCXX_HAVE_CDTOR_CALLABI 1 +#endif + +#ifdef __cplusplus + +namespace std +{ + class type_info; +} + +namespace __cxxabiv1 +{ + struct __cxa_refcounted_exception; + + extern "C" + { + // Allocate memory for the primary exception plus the thrown object. + void* + __cxa_allocate_exception(size_t) _GLIBCXX_NOTHROW; + + void + __cxa_free_exception(void*) _GLIBCXX_NOTHROW; + + // Initialize exception (this is a GNU extension) + __cxa_refcounted_exception* + __cxa_init_primary_exception(void *object, std::type_info *tinfo, + void (_GLIBCXX_CDTOR_CALLABI *dest) (void *)) _GLIBCXX_NOTHROW; + + } +} // namespace __cxxabiv1 + +#endif + +#pragma GCC visibility pop + +#endif // _CXXABI_INIT_EXCEPTION_H diff --git a/resources/sources/avr-libstdcpp/include/bits/deque.tcc b/resources/sources/avr-libstdcpp/include/bits/deque.tcc new file mode 100644 index 000000000..b4943e8ea --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/deque.tcc @@ -0,0 +1,1216 @@ +// Deque implementation (out of line) -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/deque.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{deque} + */ + +#ifndef _DEQUE_TCC +#define _DEQUE_TCC 1 + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + +#if __cplusplus >= 201103L + template + void + deque<_Tp, _Alloc>:: + _M_default_initialize() + { + _Map_pointer __cur; + __try + { + for (__cur = this->_M_impl._M_start._M_node; + __cur < this->_M_impl._M_finish._M_node; + ++__cur) + std::__uninitialized_default_a(*__cur, *__cur + _S_buffer_size(), + _M_get_Tp_allocator()); + std::__uninitialized_default_a(this->_M_impl._M_finish._M_first, + this->_M_impl._M_finish._M_cur, + _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), + _M_get_Tp_allocator()); + __throw_exception_again; + } + } +#endif + + template + deque<_Tp, _Alloc>& + deque<_Tp, _Alloc>:: + operator=(const deque& __x) + { + if (&__x != this) + { +#if __cplusplus >= 201103L + if (_Alloc_traits::_S_propagate_on_copy_assign()) + { + if (!_Alloc_traits::_S_always_equal() + && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) + { + // Replacement allocator cannot free existing storage, + // so deallocate everything and take copy of __x's data. + _M_replace_map(__x, __x.get_allocator()); + std::__alloc_on_copy(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + return *this; + } + std::__alloc_on_copy(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + } +#endif + const size_type __len = size(); + if (__len >= __x.size()) + _M_erase_at_end(std::copy(__x.begin(), __x.end(), + this->_M_impl._M_start)); + else + { + const_iterator __mid = __x.begin() + difference_type(__len); + std::copy(__x.begin(), __mid, this->_M_impl._M_start); + _M_range_insert_aux(this->_M_impl._M_finish, __mid, __x.end(), + std::random_access_iterator_tag()); + } + } + return *this; + } + +#if __cplusplus >= 201103L + template + template +#if __cplusplus > 201402L + typename deque<_Tp, _Alloc>::reference +#else + void +#endif + deque<_Tp, _Alloc>:: + emplace_front(_Args&&... __args) + { + if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) + { + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_start._M_cur - 1, + std::forward<_Args>(__args)...); + --this->_M_impl._M_start._M_cur; + } + else + _M_push_front_aux(std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif + } + + template + template +#if __cplusplus > 201402L + typename deque<_Tp, _Alloc>::reference +#else + void +#endif + deque<_Tp, _Alloc>:: + emplace_back(_Args&&... __args) + { + if (this->_M_impl._M_finish._M_cur + != this->_M_impl._M_finish._M_last - 1) + { + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_finish._M_cur, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish._M_cur; + } + else + _M_push_back_aux(std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif + } +#endif + +#if __cplusplus >= 201103L + template + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + emplace(const_iterator __position, _Args&&... __args) + { + if (__position._M_cur == this->_M_impl._M_start._M_cur) + { + emplace_front(std::forward<_Args>(__args)...); + return this->_M_impl._M_start; + } + else if (__position._M_cur == this->_M_impl._M_finish._M_cur) + { + emplace_back(std::forward<_Args>(__args)...); + iterator __tmp = this->_M_impl._M_finish; + --__tmp; + return __tmp; + } + else + return _M_insert_aux(__position._M_const_cast(), + std::forward<_Args>(__args)...); + } +#endif + + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { + if (__position._M_cur == this->_M_impl._M_start._M_cur) + { + push_front(__x); + return this->_M_impl._M_start; + } + else if (__position._M_cur == this->_M_impl._M_finish._M_cur) + { + push_back(__x); + iterator __tmp = this->_M_impl._M_finish; + --__tmp; + return __tmp; + } + else + return _M_insert_aux(__position._M_const_cast(), __x); + } + + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + _M_erase(iterator __position) + { + iterator __next = __position; + ++__next; + const difference_type __index = __position - begin(); + if (static_cast(__index) < (size() >> 1)) + { + if (__position != begin()) + _GLIBCXX_MOVE_BACKWARD3(begin(), __position, __next); + pop_front(); + } + else + { + if (__next != end()) + _GLIBCXX_MOVE3(__next, end(), __position); + pop_back(); + } + return begin() + __index; + } + + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + _M_erase(iterator __first, iterator __last) + { + if (__first == __last) + return __first; + else if (__first == begin() && __last == end()) + { + clear(); + return end(); + } + else + { + const difference_type __n = __last - __first; + const difference_type __elems_before = __first - begin(); + if (static_cast(__elems_before) <= (size() - __n) / 2) + { + if (__first != begin()) + _GLIBCXX_MOVE_BACKWARD3(begin(), __first, __last); + _M_erase_at_begin(begin() + __n); + } + else + { + if (__last != end()) + _GLIBCXX_MOVE3(__last, end(), __first); + _M_erase_at_end(end() - __n); + } + return begin() + __elems_before; + } + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + iterator __cur = begin(); + for (; __first != __last && __cur != end(); ++__cur, (void)++__first) + *__cur = *__first; + if (__first == __last) + _M_erase_at_end(__cur); + else + _M_range_insert_aux(end(), __first, __last, + std::__iterator_category(__first)); + } + + template + void + deque<_Tp, _Alloc>:: + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x) + { + if (__pos._M_cur == this->_M_impl._M_start._M_cur) + { + iterator __new_start = _M_reserve_elements_at_front(__n); + __try + { + std::__uninitialized_fill_a(__new_start, this->_M_impl._M_start, + __x, _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + } + __catch(...) + { + _M_destroy_nodes(__new_start._M_node, + this->_M_impl._M_start._M_node); + __throw_exception_again; + } + } + else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + __try + { + std::__uninitialized_fill_a(this->_M_impl._M_finish, + __new_finish, __x, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + else + _M_insert_aux(__pos, __n, __x); + } + +#if __cplusplus >= 201103L + template + void + deque<_Tp, _Alloc>:: + _M_default_append(size_type __n) + { + if (__n) + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + __try + { + std::__uninitialized_default_a(this->_M_impl._M_finish, + __new_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + } + + template + bool + deque<_Tp, _Alloc>:: + _M_shrink_to_fit() + { + const difference_type __front_capacity + = (this->_M_impl._M_start._M_cur - this->_M_impl._M_start._M_first); + if (__front_capacity == 0) + return false; + + const difference_type __back_capacity + = (this->_M_impl._M_finish._M_last - this->_M_impl._M_finish._M_cur); + if (__front_capacity + __back_capacity < _S_buffer_size()) + return false; + + return std::__shrink_to_fit_aux::_S_do_it(*this); + } +#endif + + template + void + deque<_Tp, _Alloc>:: + _M_fill_initialize(const value_type& __value) + { + _Map_pointer __cur; + __try + { + for (__cur = this->_M_impl._M_start._M_node; + __cur < this->_M_impl._M_finish._M_node; + ++__cur) + std::__uninitialized_fill_a(*__cur, *__cur + _S_buffer_size(), + __value, _M_get_Tp_allocator()); + std::__uninitialized_fill_a(this->_M_impl._M_finish._M_first, + this->_M_impl._M_finish._M_cur, + __value, _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(this->_M_impl._M_start, iterator(*__cur, __cur), + _M_get_Tp_allocator()); + __throw_exception_again; + } + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_range_initialize(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + this->_M_initialize_map(0); + __try + { + for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else + push_back(*__first); +#endif + } + __catch(...) + { + clear(); + __throw_exception_again; + } + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __n = std::distance(__first, __last); + this->_M_initialize_map(_S_check_init_len(__n, _M_get_Tp_allocator())); + + _Map_pointer __cur_node; + __try + { + for (__cur_node = this->_M_impl._M_start._M_node; + __cur_node < this->_M_impl._M_finish._M_node; + ++__cur_node) + { + _ForwardIterator __mid = __first; + std::advance(__mid, _S_buffer_size()); + std::__uninitialized_copy_a(__first, __mid, *__cur_node, + _M_get_Tp_allocator()); + __first = __mid; + } + std::__uninitialized_copy_a(__first, __last, + this->_M_impl._M_finish._M_first, + _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(this->_M_impl._M_start, + iterator(*__cur_node, __cur_node), + _M_get_Tp_allocator()); + __throw_exception_again; + } + } + + // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_last - 1. + template +#if __cplusplus >= 201103L + template + void + deque<_Tp, _Alloc>:: + _M_push_back_aux(_Args&&... __args) +#else + void + deque<_Tp, _Alloc>:: + _M_push_back_aux(const value_type& __t) +#endif + { + if (size() == max_size()) + __throw_length_error( + __N("cannot create std::deque larger than max_size()")); + + _M_reserve_map_at_back(); + *(this->_M_impl._M_finish._M_node + 1) = this->_M_allocate_node(); + __try + { +#if __cplusplus >= 201103L + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_finish._M_cur, + std::forward<_Args>(__args)...); +#else + this->_M_impl.construct(this->_M_impl._M_finish._M_cur, __t); +#endif + this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node + + 1); + this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_first; + } + __catch(...) + { + _M_deallocate_node(*(this->_M_impl._M_finish._M_node + 1)); + __throw_exception_again; + } + } + + // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_first. + template +#if __cplusplus >= 201103L + template + void + deque<_Tp, _Alloc>:: + _M_push_front_aux(_Args&&... __args) +#else + void + deque<_Tp, _Alloc>:: + _M_push_front_aux(const value_type& __t) +#endif + { + if (size() == max_size()) + __throw_length_error( + __N("cannot create std::deque larger than max_size()")); + + _M_reserve_map_at_front(); + *(this->_M_impl._M_start._M_node - 1) = this->_M_allocate_node(); + __try + { + this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + - 1); + this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_last - 1; +#if __cplusplus >= 201103L + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_start._M_cur, + std::forward<_Args>(__args)...); +#else + this->_M_impl.construct(this->_M_impl._M_start._M_cur, __t); +#endif + } + __catch(...) + { + ++this->_M_impl._M_start; + _M_deallocate_node(*(this->_M_impl._M_start._M_node - 1)); + __throw_exception_again; + } + } + + // Called only if _M_impl._M_finish._M_cur == _M_impl._M_finish._M_first. + template + void deque<_Tp, _Alloc>:: + _M_pop_back_aux() + { + _M_deallocate_node(this->_M_impl._M_finish._M_first); + this->_M_impl._M_finish._M_set_node(this->_M_impl._M_finish._M_node - 1); + this->_M_impl._M_finish._M_cur = this->_M_impl._M_finish._M_last - 1; + _Alloc_traits::destroy(_M_get_Tp_allocator(), + this->_M_impl._M_finish._M_cur); + } + + // Called only if _M_impl._M_start._M_cur == _M_impl._M_start._M_last - 1. + // Note that if the deque has at least one element (a precondition for this + // member function), and if + // _M_impl._M_start._M_cur == _M_impl._M_start._M_last, + // then the deque must have at least two nodes. + template + void deque<_Tp, _Alloc>:: + _M_pop_front_aux() + { + _Alloc_traits::destroy(_M_get_Tp_allocator(), + this->_M_impl._M_start._M_cur); + _M_deallocate_node(this->_M_impl._M_start._M_first); + this->_M_impl._M_start._M_set_node(this->_M_impl._M_start._M_node + 1); + this->_M_impl._M_start._M_cur = this->_M_impl._M_start._M_first; + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_range_insert_aux(iterator __pos, + _InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { std::copy(__first, __last, std::inserter(*this, __pos)); } + + template + template + void + deque<_Tp, _Alloc>:: + _M_range_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __n = std::distance(__first, __last); + if (__pos._M_cur == this->_M_impl._M_start._M_cur) + { + iterator __new_start = _M_reserve_elements_at_front(__n); + __try + { + std::__uninitialized_copy_a(__first, __last, __new_start, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + } + __catch(...) + { + _M_destroy_nodes(__new_start._M_node, + this->_M_impl._M_start._M_node); + __throw_exception_again; + } + } + else if (__pos._M_cur == this->_M_impl._M_finish._M_cur) + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + __try + { + std::__uninitialized_copy_a(__first, __last, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + else + _M_insert_aux(__pos, __first, __last, __n); + } + + template +#if __cplusplus >= 201103L + template + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + _M_insert_aux(iterator __pos, _Args&&... __args) + { + value_type __x_copy(std::forward<_Args>(__args)...); // XXX copy +#else + typename deque<_Tp, _Alloc>::iterator + deque<_Tp, _Alloc>:: + _M_insert_aux(iterator __pos, const value_type& __x) + { + value_type __x_copy = __x; // XXX copy +#endif + difference_type __index = __pos - this->_M_impl._M_start; + if (static_cast(__index) < size() / 2) + { + push_front(_GLIBCXX_MOVE(front())); + iterator __front1 = this->_M_impl._M_start; + ++__front1; + iterator __front2 = __front1; + ++__front2; + __pos = this->_M_impl._M_start + __index; + iterator __pos1 = __pos; + ++__pos1; + _GLIBCXX_MOVE3(__front2, __pos1, __front1); + } + else + { + push_back(_GLIBCXX_MOVE(back())); + iterator __back1 = this->_M_impl._M_finish; + --__back1; + iterator __back2 = __back1; + --__back2; + __pos = this->_M_impl._M_start + __index; + _GLIBCXX_MOVE_BACKWARD3(__pos, __back2, __back1); + } + *__pos = _GLIBCXX_MOVE(__x_copy); + return __pos; + } + + template + void + deque<_Tp, _Alloc>:: + _M_insert_aux(iterator __pos, size_type __n, const value_type& __x) + { + const difference_type __elems_before = __pos - this->_M_impl._M_start; + const size_type __length = this->size(); + value_type __x_copy = __x; + if (__elems_before < difference_type(__length / 2)) + { + iterator __new_start = _M_reserve_elements_at_front(__n); + iterator __old_start = this->_M_impl._M_start; + __pos = this->_M_impl._M_start + __elems_before; + __try + { + if (__elems_before >= difference_type(__n)) + { + iterator __start_n = (this->_M_impl._M_start + + difference_type(__n)); + std::__uninitialized_move_a(this->_M_impl._M_start, + __start_n, __new_start, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + _GLIBCXX_MOVE3(__start_n, __pos, __old_start); + std::fill(__pos - difference_type(__n), __pos, __x_copy); + } + else + { + std::__uninitialized_move_fill(this->_M_impl._M_start, + __pos, __new_start, + this->_M_impl._M_start, + __x_copy, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + std::fill(__old_start, __pos, __x_copy); + } + } + __catch(...) + { + _M_destroy_nodes(__new_start._M_node, + this->_M_impl._M_start._M_node); + __throw_exception_again; + } + } + else + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + iterator __old_finish = this->_M_impl._M_finish; + const difference_type __elems_after = + difference_type(__length) - __elems_before; + __pos = this->_M_impl._M_finish - __elems_after; + __try + { + if (__elems_after > difference_type(__n)) + { + iterator __finish_n = (this->_M_impl._M_finish + - difference_type(__n)); + std::__uninitialized_move_a(__finish_n, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); + std::fill(__pos, __pos + difference_type(__n), __x_copy); + } + else + { + std::__uninitialized_fill_move(this->_M_impl._M_finish, + __pos + difference_type(__n), + __x_copy, __pos, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + std::fill(__pos, __old_finish, __x_copy); + } + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + } + + template + template + void + deque<_Tp, _Alloc>:: + _M_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + size_type __n) + { + const difference_type __elemsbefore = __pos - this->_M_impl._M_start; + const size_type __length = size(); + if (static_cast(__elemsbefore) < __length / 2) + { + iterator __new_start = _M_reserve_elements_at_front(__n); + iterator __old_start = this->_M_impl._M_start; + __pos = this->_M_impl._M_start + __elemsbefore; + __try + { + if (__elemsbefore >= difference_type(__n)) + { + iterator __start_n = (this->_M_impl._M_start + + difference_type(__n)); + std::__uninitialized_move_a(this->_M_impl._M_start, + __start_n, __new_start, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + _GLIBCXX_MOVE3(__start_n, __pos, __old_start); + std::copy(__first, __last, __pos - difference_type(__n)); + } + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, difference_type(__n) - __elemsbefore); + std::__uninitialized_move_copy(this->_M_impl._M_start, + __pos, __first, __mid, + __new_start, + _M_get_Tp_allocator()); + this->_M_impl._M_start = __new_start; + std::copy(__mid, __last, __old_start); + } + } + __catch(...) + { + _M_destroy_nodes(__new_start._M_node, + this->_M_impl._M_start._M_node); + __throw_exception_again; + } + } + else + { + iterator __new_finish = _M_reserve_elements_at_back(__n); + iterator __old_finish = this->_M_impl._M_finish; + const difference_type __elemsafter = + difference_type(__length) - __elemsbefore; + __pos = this->_M_impl._M_finish - __elemsafter; + __try + { + if (__elemsafter > difference_type(__n)) + { + iterator __finish_n = (this->_M_impl._M_finish + - difference_type(__n)); + std::__uninitialized_move_a(__finish_n, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + _GLIBCXX_MOVE_BACKWARD3(__pos, __finish_n, __old_finish); + std::copy(__first, __last, __pos); + } + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, __elemsafter); + std::__uninitialized_copy_move(__mid, __last, __pos, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __new_finish; + std::copy(__first, __mid, __pos); + } + } + __catch(...) + { + _M_destroy_nodes(this->_M_impl._M_finish._M_node + 1, + __new_finish._M_node + 1); + __throw_exception_again; + } + } + } + + template + void + deque<_Tp, _Alloc>:: + _M_destroy_data_aux(iterator __first, iterator __last) + { + for (_Map_pointer __node = __first._M_node + 1; + __node < __last._M_node; ++__node) + std::_Destroy(*__node, *__node + _S_buffer_size(), + _M_get_Tp_allocator()); + + if (__first._M_node != __last._M_node) + { + std::_Destroy(__first._M_cur, __first._M_last, + _M_get_Tp_allocator()); + std::_Destroy(__last._M_first, __last._M_cur, + _M_get_Tp_allocator()); + } + else + std::_Destroy(__first._M_cur, __last._M_cur, + _M_get_Tp_allocator()); + } + + template + void + deque<_Tp, _Alloc>:: + _M_new_elements_at_front(size_type __new_elems) + { + if (this->max_size() - this->size() < __new_elems) + __throw_length_error(__N("deque::_M_new_elements_at_front")); + + const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1) + / _S_buffer_size()); + _M_reserve_map_at_front(__new_nodes); + size_type __i; + __try + { + for (__i = 1; __i <= __new_nodes; ++__i) + *(this->_M_impl._M_start._M_node - __i) = this->_M_allocate_node(); + } + __catch(...) + { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(this->_M_impl._M_start._M_node - __j)); + __throw_exception_again; + } + } + + template + void + deque<_Tp, _Alloc>:: + _M_new_elements_at_back(size_type __new_elems) + { + if (this->max_size() - this->size() < __new_elems) + __throw_length_error(__N("deque::_M_new_elements_at_back")); + + const size_type __new_nodes = ((__new_elems + _S_buffer_size() - 1) + / _S_buffer_size()); + _M_reserve_map_at_back(__new_nodes); + size_type __i; + __try + { + for (__i = 1; __i <= __new_nodes; ++__i) + *(this->_M_impl._M_finish._M_node + __i) = this->_M_allocate_node(); + } + __catch(...) + { + for (size_type __j = 1; __j < __i; ++__j) + _M_deallocate_node(*(this->_M_impl._M_finish._M_node + __j)); + __throw_exception_again; + } + } + + template + void + deque<_Tp, _Alloc>:: + _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front) + { + const size_type __old_num_nodes + = this->_M_impl._M_finish._M_node - this->_M_impl._M_start._M_node + 1; + const size_type __new_num_nodes = __old_num_nodes + __nodes_to_add; + + _Map_pointer __new_nstart; + if (this->_M_impl._M_map_size > 2 * __new_num_nodes) + { + __new_nstart = this->_M_impl._M_map + (this->_M_impl._M_map_size + - __new_num_nodes) / 2 + + (__add_at_front ? __nodes_to_add : 0); + if (__new_nstart < this->_M_impl._M_start._M_node) + std::copy(this->_M_impl._M_start._M_node, + this->_M_impl._M_finish._M_node + 1, + __new_nstart); + else + std::copy_backward(this->_M_impl._M_start._M_node, + this->_M_impl._M_finish._M_node + 1, + __new_nstart + __old_num_nodes); + } + else + { + size_type __new_map_size = this->_M_impl._M_map_size + + std::max(this->_M_impl._M_map_size, + __nodes_to_add) + 2; + + _Map_pointer __new_map = this->_M_allocate_map(__new_map_size); + __new_nstart = __new_map + (__new_map_size - __new_num_nodes) / 2 + + (__add_at_front ? __nodes_to_add : 0); + std::copy(this->_M_impl._M_start._M_node, + this->_M_impl._M_finish._M_node + 1, + __new_nstart); + _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); + + this->_M_impl._M_map = __new_map; + this->_M_impl._M_map_size = __new_map_size; + } + + this->_M_impl._M_start._M_set_node(__new_nstart); + this->_M_impl._M_finish._M_set_node(__new_nstart + __old_num_nodes - 1); + } + +_GLIBCXX_END_NAMESPACE_CONTAINER + + // Overload for deque::iterators, exploiting the "segmented-iterator + // optimization". + template + void + __fill_a1(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __first, + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>& __last, + const _VTp& __value) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; + if (__first._M_node != __last._M_node) + { + std::__fill_a1(__first._M_cur, __first._M_last, __value); + + for (typename _Iter::_Map_pointer __node = __first._M_node + 1; + __node < __last._M_node; ++__node) + std::__fill_a1(*__node, *__node + _Iter::_S_buffer_size(), __value); + + std::__fill_a1(__last._M_first, __last._M_cur, __value); + } + else + std::__fill_a1(__first._M_cur, __last._M_cur, __value); + } + + template + _OI + __copy_move_dit(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, + _OI __result) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; + if (__first._M_node != __last._M_node) + { + __result + = std::__copy_move_a1<_IsMove>(__first._M_cur, __first._M_last, + __result); + + for (typename _Iter::_Map_pointer __node = __first._M_node + 1; + __node != __last._M_node; ++__node) + __result + = std::__copy_move_a1<_IsMove>(*__node, + *__node + _Iter::_S_buffer_size(), + __result); + + return std::__copy_move_a1<_IsMove>(__last._M_first, __last._M_cur, + __result); + } + + return std::__copy_move_a1<_IsMove>(__first._M_cur, __last._M_cur, + __result); + } + + template + _OI + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, + _OI __result) + { return __copy_move_dit<_IsMove>(__first, __last, __result); } + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result) + { return __copy_move_dit<_IsMove>(__first, __last, __result); } + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_a1(_II __first, _II __last, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; + typedef typename _Iter::difference_type difference_type; + + difference_type __len = __last - __first; + while (__len > 0) + { + const difference_type __clen + = std::min(__len, __result._M_last - __result._M_cur); + std::__copy_move_a1<_IsMove>(__first, __first + __clen, + __result._M_cur); + + __first += __clen; + __result += __clen; + __len -= __clen; + } + + return __result; + } + + template + _OI + __copy_move_backward_dit( + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, + _OI __result) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; + if (__first._M_node != __last._M_node) + { + __result = std::__copy_move_backward_a1<_IsMove>( + __last._M_first, __last._M_cur, __result); + + for (typename _Iter::_Map_pointer __node = __last._M_node - 1; + __node != __first._M_node; --__node) + __result = std::__copy_move_backward_a1<_IsMove>( + *__node, *__node + _Iter::_S_buffer_size(), __result); + + return std::__copy_move_backward_a1<_IsMove>( + __first._M_cur, __first._M_last, __result); + } + + return std::__copy_move_backward_a1<_IsMove>( + __first._M_cur, __last._M_cur, __result); + } + + template + _OI + __copy_move_backward_a1( + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last, + _OI __result) + { return __copy_move_backward_dit<_IsMove>(__first, __last, __result); } + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_backward_a1( + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __first, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr> __last, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> __result) + { return __copy_move_backward_dit<_IsMove>(__first, __last, __result); } + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_backward_a1(_II __first, _II __last, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> __result) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> _Iter; + typedef typename _Iter::difference_type difference_type; + + difference_type __len = __last - __first; + while (__len > 0) + { + difference_type __rlen = __result._M_cur - __result._M_first; + _Tp* __rend = __result._M_cur; + if (!__rlen) + { + __rlen = _Iter::_S_buffer_size(); + __rend = *(__result._M_node - 1) + __rlen; + } + + const difference_type __clen = std::min(__len, __rlen); + std::__copy_move_backward_a1<_IsMove>(__last - __clen, __last, __rend); + + __last -= __clen; + __result -= __clen; + __len -= __clen; + } + + return __result; + } + + template + bool + __equal_dit( + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __first1, + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>& __last1, + _II __first2) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; + if (__first1._M_node != __last1._M_node) + { + if (!std::__equal_aux1(__first1._M_cur, __first1._M_last, __first2)) + return false; + + __first2 += __first1._M_last - __first1._M_cur; + for (typename _Iter::_Map_pointer __node = __first1._M_node + 1; + __node != __last1._M_node; + __first2 += _Iter::_S_buffer_size(), ++__node) + if (!std::__equal_aux1(*__node, *__node + _Iter::_S_buffer_size(), + __first2)) + return false; + + return std::__equal_aux1(__last1._M_first, __last1._M_cur, __first2); + } + + return std::__equal_aux1(__first1._M_cur, __last1._M_cur, __first2); + } + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first1, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __last1, + _II __first2) + { return std::__equal_dit(__first1, __last1, __first2); } + + template + bool + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __first1, + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1> __last1, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2> __first2) + { return std::__equal_dit(__first1, __last1, __first2); } + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_II __first1, _II __last1, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> __first2) + { + typedef _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr> _Iter; + typedef typename _Iter::difference_type difference_type; + + difference_type __len = __last1 - __first1; + while (__len > 0) + { + const difference_type __clen + = std::min(__len, __first2._M_last - __first2._M_cur); + if (!std::__equal_aux1(__first1, __first1 + __clen, __first2._M_cur)) + return false; + + __first1 += __clen; + __len -= __clen; + __first2 += __clen; + } + + return true; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h b/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h new file mode 100644 index 000000000..3c12cfcf8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/enable_special_members.h @@ -0,0 +1,312 @@ +// -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/enable_special_members.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef _ENABLE_SPECIAL_MEMBERS_H +#define _ENABLE_SPECIAL_MEMBERS_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct _Enable_default_constructor_tag + { + explicit constexpr _Enable_default_constructor_tag() = default; + }; + +/** + * @brief A mixin helper to conditionally enable or disable the default + * constructor. + * @sa _Enable_special_members + */ +template + struct _Enable_default_constructor + { + constexpr _Enable_default_constructor() noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor const&) + noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor&&) + noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor const&) noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor&&) noexcept = default; + + // Can be used in other ctors. + constexpr explicit + _Enable_default_constructor(_Enable_default_constructor_tag) { } + }; + + +/** + * @brief A mixin helper to conditionally enable or disable the default + * destructor. + * @sa _Enable_special_members + */ +template + struct _Enable_destructor { }; + +/** + * @brief A mixin helper to conditionally enable or disable the copy/move + * special members. + * @sa _Enable_special_members + */ +template + struct _Enable_copy_move { }; + +/** + * @brief A mixin helper to conditionally enable or disable the special + * members. + * + * The @c _Tag type parameter is to make mixin bases unique and thus avoid + * ambiguities. + */ +template + struct _Enable_special_members + : private _Enable_default_constructor<_Default, _Tag>, + private _Enable_destructor<_Destructor, _Tag>, + private _Enable_copy_move<_Copy, _CopyAssignment, + _Move, _MoveAssignment, + _Tag> + { }; + +// Boilerplate follows. + +template + struct _Enable_default_constructor + { + constexpr _Enable_default_constructor() noexcept = delete; + constexpr _Enable_default_constructor(_Enable_default_constructor const&) + noexcept = default; + constexpr _Enable_default_constructor(_Enable_default_constructor&&) + noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor const&) noexcept = default; + _Enable_default_constructor& + operator=(_Enable_default_constructor&&) noexcept = default; + + // Can be used in other ctors. + constexpr explicit + _Enable_default_constructor(_Enable_default_constructor_tag) { } + }; + +template + struct _Enable_destructor + { ~_Enable_destructor() noexcept = delete; }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = default; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = default; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +template + struct _Enable_copy_move + { + constexpr _Enable_copy_move() noexcept = default; + constexpr _Enable_copy_move(_Enable_copy_move const&) noexcept = delete; + constexpr _Enable_copy_move(_Enable_copy_move&&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move const&) noexcept = delete; + _Enable_copy_move& + operator=(_Enable_copy_move&&) noexcept = delete; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _ENABLE_SPECIAL_MEMBERS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/erase_if.h b/resources/sources/avr-libstdcpp/include/bits/erase_if.h new file mode 100644 index 000000000..dc5e6ae58 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/erase_if.h @@ -0,0 +1,72 @@ +// -*- C++ -*- + +// Copyright (C) 2015-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/erase_if.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + */ + +#ifndef _GLIBCXX_ERASE_IF_H +#define _GLIBCXX_ERASE_IF_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201402L + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus > 201703L +# define __cpp_lib_erase_if 202002L +#endif + + namespace __detail + { + template + typename _Container::size_type + __erase_nodes_if(_Container& __cont, _Predicate __pred) + { + typename _Container::size_type __num = 0; + for (auto __iter = __cont.begin(), __last = __cont.end(); + __iter != __last;) + { + if (__pred(*__iter)) + { + __iter = __cont.erase(__iter); + ++__num; + } + else + ++__iter; + } + return __num; + } + } // namespace __detail + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + +#endif // _GLIBCXX_ERASE_IF_H diff --git a/resources/sources/avr-libstdcpp/include/bits/error_constants.h b/resources/sources/avr-libstdcpp/include/bits/error_constants.h new file mode 100644 index 000000000..203891454 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/error_constants.h @@ -0,0 +1,180 @@ +// Specific definitions for generic platforms -*- C++ -*- + +// Copyright (C) 2007-2024 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/error_constants.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{system_error} + */ + +#ifndef _GLIBCXX_ERROR_CONSTANTS +#define _GLIBCXX_ERROR_CONSTANTS 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + enum class errc + { + address_family_not_supported = EAFNOSUPPORT, + address_in_use = EADDRINUSE, + address_not_available = EADDRNOTAVAIL, + already_connected = EISCONN, + argument_list_too_long = E2BIG, + argument_out_of_domain = EDOM, + bad_address = EFAULT, + bad_file_descriptor = EBADF, + +#ifdef EBADMSG + bad_message = EBADMSG, +#endif + + broken_pipe = EPIPE, + connection_aborted = ECONNABORTED, + connection_already_in_progress = EALREADY, + connection_refused = ECONNREFUSED, + connection_reset = ECONNRESET, + cross_device_link = EXDEV, + destination_address_required = EDESTADDRREQ, + device_or_resource_busy = EBUSY, + directory_not_empty = ENOTEMPTY, + executable_format_error = ENOEXEC, + file_exists = EEXIST, + file_too_large = EFBIG, + filename_too_long = ENAMETOOLONG, + function_not_supported = ENOSYS, + host_unreachable = EHOSTUNREACH, + +#ifdef EIDRM + identifier_removed = EIDRM, +#endif + + illegal_byte_sequence = EILSEQ, + inappropriate_io_control_operation = ENOTTY, + interrupted = EINTR, + invalid_argument = EINVAL, + invalid_seek = ESPIPE, + io_error = EIO, + is_a_directory = EISDIR, + message_size = EMSGSIZE, + network_down = ENETDOWN, + network_reset = ENETRESET, + network_unreachable = ENETUNREACH, + no_buffer_space = ENOBUFS, + no_child_process = ECHILD, + +#ifdef ENOLINK + no_link = ENOLINK, +#endif + + no_lock_available = ENOLCK, + +#ifdef ENODATA + no_message_available = ENODATA, +#endif + + no_message = ENOMSG, + no_protocol_option = ENOPROTOOPT, + no_space_on_device = ENOSPC, + +#ifdef ENOSR + no_stream_resources = ENOSR, +#endif + + no_such_device_or_address = ENXIO, + no_such_device = ENODEV, + no_such_file_or_directory = ENOENT, + no_such_process = ESRCH, + not_a_directory = ENOTDIR, + not_a_socket = ENOTSOCK, + +#ifdef ENOSTR + not_a_stream = ENOSTR, +#endif + + not_connected = ENOTCONN, + not_enough_memory = ENOMEM, + +#ifdef ENOTSUP + not_supported = ENOTSUP, +#endif + +#ifdef ECANCELED + operation_canceled = ECANCELED, +#endif + + operation_in_progress = EINPROGRESS, + operation_not_permitted = EPERM, + operation_not_supported = EOPNOTSUPP, + operation_would_block = EWOULDBLOCK, + +#ifdef EOWNERDEAD + owner_dead = EOWNERDEAD, +#endif + + permission_denied = EACCES, + +#ifdef EPROTO + protocol_error = EPROTO, +#endif + + protocol_not_supported = EPROTONOSUPPORT, + read_only_file_system = EROFS, + resource_deadlock_would_occur = EDEADLK, + resource_unavailable_try_again = EAGAIN, + result_out_of_range = ERANGE, + +#ifdef ENOTRECOVERABLE + state_not_recoverable = ENOTRECOVERABLE, +#endif + +#ifdef ETIME + stream_timeout = ETIME, +#endif + +#ifdef ETXTBSY + text_file_busy = ETXTBSY, +#endif + + timed_out = ETIMEDOUT, + too_many_files_open_in_system = ENFILE, + too_many_files_open = EMFILE, + too_many_links = EMLINK, + too_many_symbolic_link_levels = ELOOP, + +#ifdef EOVERFLOW + value_too_large = EOVERFLOW, +#elif defined __AVR__ + value_too_large = 999, +#endif + + wrong_protocol_type = EPROTOTYPE + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/exception_defines.h b/resources/sources/avr-libstdcpp/include/bits/exception_defines.h new file mode 100644 index 000000000..bc73d4194 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/exception_defines.h @@ -0,0 +1,47 @@ +// -fno-exceptions Support -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/exception_defines.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + */ + +#ifndef _EXCEPTION_DEFINES_H +#define _EXCEPTION_DEFINES_H 1 + +#pragma GCC system_header + +#if ! __cpp_exceptions +// Iff -fno-exceptions, transform error handling code to work without it. +# define __try if (true) +# define __catch(X) if (false) +# define __throw_exception_again +#else +// Else proceed normally. +# define __try try +# define __catch(X) catch(X) +# define __throw_exception_again throw +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/forward_list.h b/resources/sources/avr-libstdcpp/include/bits/forward_list.h new file mode 100644 index 000000000..49b2a9737 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/forward_list.h @@ -0,0 +1,1514 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/forward_list.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{forward_list} + */ + +#ifndef _FORWARD_LIST_H +#define _FORWARD_LIST_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * @brief A helper basic node class for %forward_list. + * This is just a linked list with nothing inside it. + * There are purely list shuffling utility methods here. + */ + struct _Fwd_list_node_base + { + _Fwd_list_node_base() = default; + _Fwd_list_node_base(_Fwd_list_node_base&& __x) noexcept + : _M_next(__x._M_next) + { __x._M_next = nullptr; } + + _Fwd_list_node_base(const _Fwd_list_node_base&) = delete; + _Fwd_list_node_base& operator=(const _Fwd_list_node_base&) = delete; + + _Fwd_list_node_base& + operator=(_Fwd_list_node_base&& __x) noexcept + { + _M_next = __x._M_next; + __x._M_next = nullptr; + return *this; + } + + _Fwd_list_node_base* _M_next = nullptr; + + _Fwd_list_node_base* + _M_transfer_after(_Fwd_list_node_base* __begin, + _Fwd_list_node_base* __end) noexcept + { + _Fwd_list_node_base* __keep = __begin->_M_next; + if (__end) + { + __begin->_M_next = __end->_M_next; + __end->_M_next = _M_next; + } + else + __begin->_M_next = nullptr; + _M_next = __keep; + return __end; + } + + void + _M_reverse_after() noexcept + { + _Fwd_list_node_base* __tail = _M_next; + if (!__tail) + return; + while (_Fwd_list_node_base* __temp = __tail->_M_next) + { + _Fwd_list_node_base* __keep = _M_next; + _M_next = __temp; + __tail->_M_next = __temp->_M_next; + _M_next->_M_next = __keep; + } + } + }; + + /** + * @brief A helper node class for %forward_list. + * This is just a linked list with uninitialized storage for a + * data value in each node. + * There is a sorting utility method. + */ + template + struct _Fwd_list_node + : public _Fwd_list_node_base + { + _Fwd_list_node() = default; + + __gnu_cxx::__aligned_buffer<_Tp> _M_storage; + + _Tp* + _M_valptr() noexcept + { return _M_storage._M_ptr(); } + + const _Tp* + _M_valptr() const noexcept + { return _M_storage._M_ptr(); } + }; + + /** + * @brief A forward_list::iterator. + * + * All the functions are op overloads. + */ + template + struct _Fwd_list_iterator + { + typedef _Fwd_list_iterator<_Tp> _Self; + typedef _Fwd_list_node<_Tp> _Node; + + typedef _Tp value_type; + typedef _Tp* pointer; + typedef _Tp& reference; + typedef ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Fwd_list_iterator() noexcept + : _M_node() { } + + explicit + _Fwd_list_iterator(_Fwd_list_node_base* __n) noexcept + : _M_node(__n) { } + + reference + operator*() const noexcept + { return *static_cast<_Node*>(this->_M_node)->_M_valptr(); } + + pointer + operator->() const noexcept + { return static_cast<_Node*>(this->_M_node)->_M_valptr(); } + + _Self& + operator++() noexcept + { + _M_node = _M_node->_M_next; + return *this; + } + + _Self + operator++(int) noexcept + { + _Self __tmp(*this); + _M_node = _M_node->_M_next; + return __tmp; + } + + /** + * @brief Forward list iterator equality comparison. + */ + friend bool + operator==(const _Self& __x, const _Self& __y) noexcept + { return __x._M_node == __y._M_node; } + +#if __cpp_impl_three_way_comparison < 201907L + /** + * @brief Forward list iterator inequality comparison. + */ + friend bool + operator!=(const _Self& __x, const _Self& __y) noexcept + { return __x._M_node != __y._M_node; } +#endif + + _Self + _M_next() const noexcept + { + if (_M_node) + return _Fwd_list_iterator(_M_node->_M_next); + else + return _Fwd_list_iterator(nullptr); + } + + _Fwd_list_node_base* _M_node; + }; + + /** + * @brief A forward_list::const_iterator. + * + * All the functions are op overloads. + */ + template + struct _Fwd_list_const_iterator + { + typedef _Fwd_list_const_iterator<_Tp> _Self; + typedef const _Fwd_list_node<_Tp> _Node; + typedef _Fwd_list_iterator<_Tp> iterator; + + typedef _Tp value_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + typedef ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Fwd_list_const_iterator() noexcept + : _M_node() { } + + explicit + _Fwd_list_const_iterator(const _Fwd_list_node_base* __n) noexcept + : _M_node(__n) { } + + _Fwd_list_const_iterator(const iterator& __iter) noexcept + : _M_node(__iter._M_node) { } + + reference + operator*() const noexcept + { return *static_cast<_Node*>(this->_M_node)->_M_valptr(); } + + pointer + operator->() const noexcept + { return static_cast<_Node*>(this->_M_node)->_M_valptr(); } + + _Self& + operator++() noexcept + { + _M_node = _M_node->_M_next; + return *this; + } + + _Self + operator++(int) noexcept + { + _Self __tmp(*this); + _M_node = _M_node->_M_next; + return __tmp; + } + + /** + * @brief Forward list const_iterator equality comparison. + */ + friend bool + operator==(const _Self& __x, const _Self& __y) noexcept + { return __x._M_node == __y._M_node; } + +#if __cpp_impl_three_way_comparison < 201907L + /** + * @brief Forward list const_iterator inequality comparison. + */ + friend bool + operator!=(const _Self& __x, const _Self& __y) noexcept + { return __x._M_node != __y._M_node; } +#endif + + _Self + _M_next() const noexcept + { + if (this->_M_node) + return _Fwd_list_const_iterator(_M_node->_M_next); + else + return _Fwd_list_const_iterator(nullptr); + } + + const _Fwd_list_node_base* _M_node; + }; + + /** + * @brief Base class for %forward_list. + */ + template + struct _Fwd_list_base + { + protected: + typedef __alloc_rebind<_Alloc, _Fwd_list_node<_Tp>> _Node_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; + + struct _Fwd_list_impl + : public _Node_alloc_type + { + _Fwd_list_node_base _M_head; + + _Fwd_list_impl() + noexcept(is_nothrow_default_constructible<_Node_alloc_type>::value) + : _Node_alloc_type(), _M_head() + { } + + _Fwd_list_impl(_Fwd_list_impl&&) = default; + + _Fwd_list_impl(_Fwd_list_impl&& __fl, _Node_alloc_type&& __a) + : _Node_alloc_type(std::move(__a)), _M_head(std::move(__fl._M_head)) + { } + + _Fwd_list_impl(_Node_alloc_type&& __a) + : _Node_alloc_type(std::move(__a)), _M_head() + { } + }; + + _Fwd_list_impl _M_impl; + + public: + typedef _Fwd_list_iterator<_Tp> iterator; + typedef _Fwd_list_const_iterator<_Tp> const_iterator; + typedef _Fwd_list_node<_Tp> _Node; + + _Node_alloc_type& + _M_get_Node_allocator() noexcept + { return this->_M_impl; } + + const _Node_alloc_type& + _M_get_Node_allocator() const noexcept + { return this->_M_impl; } + + _Fwd_list_base() = default; + + _Fwd_list_base(_Node_alloc_type&& __a) + : _M_impl(std::move(__a)) { } + + // When allocators are always equal. + _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a, + std::true_type) + : _M_impl(std::move(__lst._M_impl), std::move(__a)) + { } + + // When allocators are not always equal. + _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a); + + _Fwd_list_base(_Fwd_list_base&&) = default; + + ~_Fwd_list_base() + { _M_erase_after(&_M_impl._M_head, nullptr); } + + protected: + _Node* + _M_get_node() + { + auto __ptr = _Node_alloc_traits::allocate(_M_get_Node_allocator(), 1); + return std::__to_address(__ptr); + } + + template + _Node* + _M_create_node(_Args&&... __args) + { + _Node* __node = this->_M_get_node(); + __try + { + ::new ((void*)__node) _Node; + _Node_alloc_traits::construct(_M_get_Node_allocator(), + __node->_M_valptr(), + std::forward<_Args>(__args)...); + } + __catch(...) + { + this->_M_put_node(__node); + __throw_exception_again; + } + return __node; + } + + template + _Fwd_list_node_base* + _M_insert_after(const_iterator __pos, _Args&&... __args); + + void + _M_put_node(_Node* __p) + { + typedef typename _Node_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__p); + _Node_alloc_traits::deallocate(_M_get_Node_allocator(), __ptr, 1); + } + + _Fwd_list_node_base* + _M_erase_after(_Fwd_list_node_base* __pos); + + _Fwd_list_node_base* + _M_erase_after(_Fwd_list_node_base* __pos, + _Fwd_list_node_base* __last); + }; + + /** + * @brief A standard container with linear time access to elements, + * and fixed time insertion/deletion at any point in the sequence. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. + * + * Meets the requirements of a container, a + * sequence, including the + * optional sequence requirements with the + * %exception of @c at and @c operator[]. + * + * This is a @e singly @e linked %list. Traversal up the + * %list requires linear time, but adding and removing elements (or + * @e nodes) is done in constant time, regardless of where the + * change takes place. Unlike std::vector and std::deque, + * random-access iterators are not provided, so subscripting ( @c + * [] ) access is not allowed. For algorithms which only need + * sequential access, this lack makes no difference. + * + * Also unlike the other standard containers, std::forward_list provides + * specialized algorithms %unique to linked lists, such as + * splicing, sorting, and in-place reversal. + */ + template> + class forward_list : private _Fwd_list_base<_Tp, _Alloc> + { + static_assert(is_same::type, _Tp>::value, + "std::forward_list must have a non-const, non-volatile value_type"); +#if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::forward_list must have the same value_type as its allocator"); +#endif + + private: + typedef _Fwd_list_base<_Tp, _Alloc> _Base; + typedef _Fwd_list_node_base _Node_base; + typedef typename _Base::_Node _Node; + typedef typename _Base::_Node_alloc_type _Node_alloc_type; + typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; + typedef allocator_traits<__alloc_rebind<_Alloc, _Tp>> _Alloc_traits; + + public: + // types: + typedef _Tp value_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + typedef typename _Base::iterator iterator; + typedef typename _Base::const_iterator const_iterator; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + // 23.3.4.2 construct/copy/destroy: + + /** + * @brief Creates a %forward_list with no elements. + */ + forward_list() = default; + + /** + * @brief Creates a %forward_list with no elements. + * @param __al An allocator object. + */ + explicit + forward_list(const _Alloc& __al) noexcept + : _Base(_Node_alloc_type(__al)) + { } + + /** + * @brief Copy constructor with allocator argument. + * @param __list Input list to copy. + * @param __al An allocator object. + */ + forward_list(const forward_list& __list, const _Alloc& __al) + : _Base(_Node_alloc_type(__al)) + { _M_range_initialize(__list.begin(), __list.end()); } + + private: + forward_list(forward_list&& __list, _Node_alloc_type&& __al, + false_type) + : _Base(std::move(__list), std::move(__al)) + { + // If __list is not empty it means its allocator is not equal to __a, + // so we need to move from each element individually. + insert_after(cbefore_begin(), + std::__make_move_if_noexcept_iterator(__list.begin()), + std::__make_move_if_noexcept_iterator(__list.end())); + } + + forward_list(forward_list&& __list, _Node_alloc_type&& __al, + true_type) + noexcept + : _Base(std::move(__list), _Node_alloc_type(__al), true_type{}) + { } + + public: + /** + * @brief Move constructor with allocator argument. + * @param __list Input list to move. + * @param __al An allocator object. + */ + forward_list(forward_list&& __list, const _Alloc& __al) + noexcept(_Node_alloc_traits::_S_always_equal()) + : forward_list(std::move(__list), _Node_alloc_type(__al), + typename _Node_alloc_traits::is_always_equal{}) + { } + + /** + * @brief Creates a %forward_list with default constructed elements. + * @param __n The number of elements to initially create. + * @param __al An allocator object. + * + * This constructor creates the %forward_list with @a __n default + * constructed elements. + */ + explicit + forward_list(size_type __n, const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) + { _M_default_initialize(__n); } + + /** + * @brief Creates a %forward_list with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __al An allocator object. + * + * This constructor fills the %forward_list with @a __n copies of + * @a __value. + */ + forward_list(size_type __n, const _Tp& __value, + const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) + { _M_fill_initialize(__n, __value); } + + /** + * @brief Builds a %forward_list from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __al An allocator object. + * + * Create a %forward_list consisting of copies of the elements from + * [@a __first,@a __last). This is linear in N (where N is + * distance(@a __first,@a __last)). + */ + template> + forward_list(_InputIterator __first, _InputIterator __last, + const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) + { _M_range_initialize(__first, __last); } + + /** + * @brief The %forward_list copy constructor. + * @param __list A %forward_list of identical element and allocator + * types. + */ + forward_list(const forward_list& __list) + : _Base(_Node_alloc_traits::_S_select_on_copy( + __list._M_get_Node_allocator())) + { _M_range_initialize(__list.begin(), __list.end()); } + + /** + * @brief The %forward_list move constructor. + * @param __list A %forward_list of identical element and allocator + * types. + * + * The newly-created %forward_list contains the exact contents of the + * moved instance. The contents of the moved instance are a valid, but + * unspecified %forward_list. + */ + forward_list(forward_list&&) = default; + + /** + * @brief Builds a %forward_list from an initializer_list + * @param __il An initializer_list of value_type. + * @param __al An allocator object. + * + * Create a %forward_list consisting of copies of the elements + * in the initializer_list @a __il. This is linear in __il.size(). + */ + forward_list(std::initializer_list<_Tp> __il, + const _Alloc& __al = _Alloc()) + : _Base(_Node_alloc_type(__al)) + { _M_range_initialize(__il.begin(), __il.end()); } + + /** + * @brief The forward_list dtor. + */ + ~forward_list() noexcept + { } + + /** + * @brief The %forward_list assignment operator. + * @param __list A %forward_list of identical element and allocator + * types. + * + * All the elements of @a __list are copied. + * + * Whether the allocator is copied depends on the allocator traits. + */ + forward_list& + operator=(const forward_list& __list); + + /** + * @brief The %forward_list move assignment operator. + * @param __list A %forward_list of identical element and allocator + * types. + * + * The contents of @a __list are moved into this %forward_list + * (without copying, if the allocators permit it). + * + * Afterwards @a __list is a valid, but unspecified %forward_list + * + * Whether the allocator is moved depends on the allocator traits. + */ + forward_list& + operator=(forward_list&& __list) + noexcept(_Node_alloc_traits::_S_nothrow_move()) + { + constexpr bool __move_storage = + _Node_alloc_traits::_S_propagate_on_move_assign() + || _Node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__list), __bool_constant<__move_storage>()); + return *this; + } + + /** + * @brief The %forward_list initializer list assignment operator. + * @param __il An initializer_list of value_type. + * + * Replace the contents of the %forward_list with copies of the + * elements in the initializer_list @a __il. This is linear in + * __il.size(). + */ + forward_list& + operator=(std::initializer_list<_Tp> __il) + { + assign(__il); + return *this; + } + + /** + * @brief Assigns a range to a %forward_list. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function fills a %forward_list with copies of the elements + * in the range [@a __first,@a __last). + * + * Note that the assignment completely changes the %forward_list and + * that the number of elements of the resulting %forward_list is the + * same as the number of elements assigned. + */ + template> + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef is_assignable<_Tp, decltype(*__first)> __assignable; + _M_assign(__first, __last, __assignable()); + } + + /** + * @brief Assigns a given value to a %forward_list. + * @param __n Number of elements to be assigned. + * @param __val Value to be assigned. + * + * This function fills a %forward_list with @a __n copies of the + * given value. Note that the assignment completely changes the + * %forward_list, and that the resulting %forward_list has __n + * elements. + */ + void + assign(size_type __n, const _Tp& __val) + { _M_assign_n(__n, __val, is_copy_assignable<_Tp>()); } + + /** + * @brief Assigns an initializer_list to a %forward_list. + * @param __il An initializer_list of value_type. + * + * Replace the contents of the %forward_list with copies of the + * elements in the initializer_list @a __il. This is linear in + * il.size(). + */ + void + assign(std::initializer_list<_Tp> __il) + { assign(__il.begin(), __il.end()); } + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const noexcept + { return allocator_type(this->_M_get_Node_allocator()); } + + // 23.3.4.3 iterators: + + /** + * Returns a read/write iterator that points before the first element + * in the %forward_list. Iteration is done in ordinary element order. + */ + iterator + before_begin() noexcept + { return iterator(&this->_M_impl._M_head); } + + /** + * Returns a read-only (constant) iterator that points before the + * first element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + before_begin() const noexcept + { return const_iterator(&this->_M_impl._M_head); } + + /** + * Returns a read/write iterator that points to the first element + * in the %forward_list. Iteration is done in ordinary element order. + */ + iterator + begin() noexcept + { return iterator(this->_M_impl._M_head._M_next); } + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + begin() const noexcept + { return const_iterator(this->_M_impl._M_head._M_next); } + + /** + * Returns a read/write iterator that points one past the last + * element in the %forward_list. Iteration is done in ordinary + * element order. + */ + iterator + end() noexcept + { return iterator(nullptr); } + + /** + * Returns a read-only iterator that points one past the last + * element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + end() const noexcept + { return const_iterator(nullptr); } + + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + cbegin() const noexcept + { return const_iterator(this->_M_impl._M_head._M_next); } + + /** + * Returns a read-only (constant) iterator that points before the + * first element in the %forward_list. Iteration is done in ordinary + * element order. + */ + const_iterator + cbefore_begin() const noexcept + { return const_iterator(&this->_M_impl._M_head); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %forward_list. Iteration is done in + * ordinary element order. + */ + const_iterator + cend() const noexcept + { return const_iterator(nullptr); } + + /** + * Returns true if the %forward_list is empty. (Thus begin() would + * equal end().) + */ + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return this->_M_impl._M_head._M_next == nullptr; } + + /** + * Returns the largest possible number of elements of %forward_list. + */ + size_type + max_size() const noexcept + { return _Node_alloc_traits::max_size(this->_M_get_Node_allocator()); } + + // 23.3.4.4 element access: + + /** + * Returns a read/write reference to the data at the first + * element of the %forward_list. + */ + reference + front() + { + _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); + return *__front->_M_valptr(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %forward_list. + */ + const_reference + front() const + { + _Node* __front = static_cast<_Node*>(this->_M_impl._M_head._M_next); + return *__front->_M_valptr(); + } + + // 23.3.4.5 modifiers: + + /** + * @brief Constructs object in %forward_list at the front of the + * list. + * @param __args Arguments. + * + * This function will insert an object of type Tp constructed + * with Tp(std::forward(args)...) at the front of the list + * Due to the nature of a %forward_list this operation can + * be done in constant time, and does not invalidate iterators + * and references. + */ + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_front(_Args&&... __args) + { + this->_M_insert_after(cbefore_begin(), + std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif + } + + /** + * @brief Add data to the front of the %forward_list. + * @param __val Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the front of the %forward_list and assigns the given + * data to it. Due to the nature of a %forward_list this operation + * can be done in constant time, and does not invalidate iterators + * and references. + */ + void + push_front(const _Tp& __val) + { this->_M_insert_after(cbefore_begin(), __val); } + + /** + * + */ + void + push_front(_Tp&& __val) + { this->_M_insert_after(cbefore_begin(), std::move(__val)); } + + /** + * @brief Removes first element. + * + * This is a typical stack operation. It shrinks the %forward_list + * by one. Due to the nature of a %forward_list this operation can + * be done in constant time, and only invalidates iterators/references + * to the element being removed. + * + * Note that no data is returned, and if the first element's data + * is needed, it should be retrieved before pop_front() is + * called. + */ + void + pop_front() + { this->_M_erase_after(&this->_M_impl._M_head); } + + /** + * @brief Constructs object in %forward_list after the specified + * iterator. + * @param __pos A const_iterator into the %forward_list. + * @param __args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) after the specified + * location. Due to the nature of a %forward_list this operation can + * be done in constant time, and does not invalidate iterators + * and references. + */ + template + iterator + emplace_after(const_iterator __pos, _Args&&... __args) + { return iterator(this->_M_insert_after(__pos, + std::forward<_Args>(__args)...)); } + + /** + * @brief Inserts given value into %forward_list after specified + * iterator. + * @param __pos An iterator into the %forward_list. + * @param __val Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value after + * the specified location. Due to the nature of a %forward_list this + * operation can be done in constant time, and does not + * invalidate iterators and references. + */ + iterator + insert_after(const_iterator __pos, const _Tp& __val) + { return iterator(this->_M_insert_after(__pos, __val)); } + + /** + * + */ + iterator + insert_after(const_iterator __pos, _Tp&& __val) + { return iterator(this->_M_insert_after(__pos, std::move(__val))); } + + /** + * @brief Inserts a number of copies of given data into the + * %forward_list. + * @param __pos An iterator into the %forward_list. + * @param __n Number of elements to be inserted. + * @param __val Data to be inserted. + * @return An iterator pointing to the last inserted copy of + * @a val or @a pos if @a n == 0. + * + * This function will insert a specified number of copies of the + * given data after the location specified by @a pos. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + iterator + insert_after(const_iterator __pos, size_type __n, const _Tp& __val); + + /** + * @brief Inserts a range into the %forward_list. + * @param __pos An iterator into the %forward_list. + * @param __first An input iterator. + * @param __last An input iterator. + * @return An iterator pointing to the last inserted element or + * @a __pos if @a __first == @a __last. + * + * This function will insert copies of the data in the range + * [@a __first,@a __last) into the %forward_list after the + * location specified by @a __pos. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + template> + iterator + insert_after(const_iterator __pos, + _InputIterator __first, _InputIterator __last); + + /** + * @brief Inserts the contents of an initializer_list into + * %forward_list after the specified iterator. + * @param __pos An iterator into the %forward_list. + * @param __il An initializer_list of value_type. + * @return An iterator pointing to the last inserted element + * or @a __pos if @a __il is empty. + * + * This function will insert copies of the data in the + * initializer_list @a __il into the %forward_list before the location + * specified by @a __pos. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + iterator + insert_after(const_iterator __pos, std::initializer_list<_Tp> __il) + { return insert_after(__pos, __il.begin(), __il.end()); } + + /** + * @brief Removes the element pointed to by the iterator following + * @c pos. + * @param __pos Iterator pointing before element to be erased. + * @return An iterator pointing to the element following the one + * that was erased, or end() if no such element exists. + * + * This function will erase the element at the given position and + * thus shorten the %forward_list by one. + * + * Due to the nature of a %forward_list this operation can be done + * in constant time, and only invalidates iterators/references to + * the element being removed. The user is also cautioned that + * this function only erases the element, and that if the element + * is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator + erase_after(const_iterator __pos) + { return iterator(this->_M_erase_after(const_cast<_Node_base*> + (__pos._M_node))); } + + /** + * @brief Remove a range of elements. + * @param __pos Iterator pointing before the first element to be + * erased. + * @param __last Iterator pointing to one past the last element to be + * erased. + * @return @ __last. + * + * This function will erase the elements in the range + * @a (__pos,__last) and shorten the %forward_list accordingly. + * + * This operation is linear time in the size of the range and only + * invalidates iterators/references to the element being removed. + * The user is also cautioned that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + iterator + erase_after(const_iterator __pos, const_iterator __last) + { return iterator(this->_M_erase_after(const_cast<_Node_base*> + (__pos._M_node), + const_cast<_Node_base*> + (__last._M_node))); } + + /** + * @brief Swaps data with another %forward_list. + * @param __list A %forward_list of the same element and allocator + * types. + * + * This exchanges the elements between two lists in constant + * time. Note that the global std::swap() function is + * specialized such that std::swap(l1,l2) will feed to this + * function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(forward_list& __list) noexcept + { + std::swap(this->_M_impl._M_head._M_next, + __list._M_impl._M_head._M_next); + _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(), + __list._M_get_Node_allocator()); + } + + /** + * @brief Resizes the %forward_list to the specified number of + * elements. + * @param __sz Number of elements the %forward_list should contain. + * + * This function will %resize the %forward_list to the specified + * number of elements. If the number is smaller than the + * %forward_list's current number of elements the %forward_list + * is truncated, otherwise the %forward_list is extended and the + * new elements are default constructed. + */ + void + resize(size_type __sz); + + /** + * @brief Resizes the %forward_list to the specified number of + * elements. + * @param __sz Number of elements the %forward_list should contain. + * @param __val Data with which new elements should be populated. + * + * This function will %resize the %forward_list to the specified + * number of elements. If the number is smaller than the + * %forward_list's current number of elements the %forward_list + * is truncated, otherwise the %forward_list is extended and new + * elements are populated with given data. + */ + void + resize(size_type __sz, const value_type& __val); + + /** + * @brief Erases all the elements. + * + * Note that this function only erases + * the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + void + clear() noexcept + { this->_M_erase_after(&this->_M_impl._M_head, nullptr); } + + // 23.3.4.6 forward_list operations: + + /** + * @brief Insert contents of another %forward_list. + * @param __pos Iterator referencing the element to insert after. + * @param __list Source list. + * + * The elements of @a list are inserted in constant time after + * the element referenced by @a pos. @a list becomes an empty + * list. + * + * Requires this != @a x. + */ + void + splice_after(const_iterator __pos, forward_list&& __list) noexcept + { + if (!__list.empty()) + _M_splice_after(__pos, __list.before_begin(), __list.end()); + } + + void + splice_after(const_iterator __pos, forward_list& __list) noexcept + { splice_after(__pos, std::move(__list)); } + + /** + * @brief Insert element from another %forward_list. + * @param __pos Iterator referencing the element to insert after. + * @param __list Source list. + * @param __i Iterator referencing the element before the element + * to move. + * + * Removes the element in list @a list referenced by @a i and + * inserts it into the current list after @a pos. + */ + void + splice_after(const_iterator __pos, forward_list&& __list, + const_iterator __i) noexcept; + + void + splice_after(const_iterator __pos, forward_list& __list, + const_iterator __i) noexcept + { splice_after(__pos, std::move(__list), __i); } + + /** + * @brief Insert range from another %forward_list. + * @param __pos Iterator referencing the element to insert after. + * @param __list Source list. + * @param __before Iterator referencing before the start of range + * in list. + * @param __last Iterator referencing the end of range in list. + * + * Removes elements in the range (__before,__last) and inserts them + * after @a __pos in constant time. + * + * Undefined if @a __pos is in (__before,__last). + * @{ + */ + void + splice_after(const_iterator __pos, forward_list&&, + const_iterator __before, const_iterator __last) noexcept + { _M_splice_after(__pos, __before, __last); } + + void + splice_after(const_iterator __pos, forward_list&, + const_iterator __before, const_iterator __last) noexcept + { _M_splice_after(__pos, __before, __last); } + // @} + + private: +#if __cplusplus > 201703L +# define __cpp_lib_list_remove_return_type 201806L + using __remove_return_type = size_type; +# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG \ + __attribute__((__abi_tag__("__cxx20"))) +#else + using __remove_return_type = void; +# define _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG +#endif + public: + + /** + * @brief Remove all elements equal to value. + * @param __val The value to remove. + * + * Removes every element in the list equal to @a __val. + * Remaining elements stay in list order. Note that this + * function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type + remove(const _Tp& __val); + + /** + * @brief Remove all elements satisfying a predicate. + * @param __pred Unary predicate function or object. + * + * Removes every element in the list for which the predicate + * returns true. Remaining elements stay in list order. Note + * that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + template + __remove_return_type + remove_if(_Pred __pred); + + /** + * @brief Remove consecutive duplicate elements. + * + * For each consecutive set of elements with the same value, + * remove all but the first one. Remaining elements stay in + * list order. Note that this function only erases the + * elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + */ + _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type + unique() + { return unique(std::equal_to<_Tp>()); } + +#undef _GLIBCXX_FWDLIST_REMOVE_RETURN_TYPE_TAG + + /** + * @brief Remove consecutive elements satisfying a predicate. + * @param __binary_pred Binary predicate function or object. + * + * For each consecutive set of elements [first,last) that + * satisfy predicate(first,i) where i is an iterator in + * [first,last), remove all but the first one. Remaining + * elements stay in list order. Note that this function only + * erases the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + template + __remove_return_type + unique(_BinPred __binary_pred); + + /** + * @brief Merge sorted lists. + * @param __list Sorted list to merge. + * + * Assumes that both @a list and this list are sorted according to + * operator<(). Merges elements of @a __list into this list in + * sorted order, leaving @a __list empty when complete. Elements in + * this list precede elements in @a __list that are equal. + */ + void + merge(forward_list&& __list) + { merge(std::move(__list), std::less<_Tp>()); } + + void + merge(forward_list& __list) + { merge(std::move(__list)); } + + /** + * @brief Merge sorted lists according to comparison function. + * @param __list Sorted list to merge. + * @param __comp Comparison function defining sort order. + * + * Assumes that both @a __list and this list are sorted according to + * comp. Merges elements of @a __list into this list + * in sorted order, leaving @a __list empty when complete. Elements + * in this list precede elements in @a __list that are equivalent + * according to comp(). + */ + template + void + merge(forward_list&& __list, _Comp __comp); + + template + void + merge(forward_list& __list, _Comp __comp) + { merge(std::move(__list), __comp); } + + /** + * @brief Sort the elements of the list. + * + * Sorts the elements of this list in NlogN time. Equivalent + * elements remain in list order. + */ + void + sort() + { sort(std::less<_Tp>()); } + + /** + * @brief Sort the forward_list using a comparison function. + * + * Sorts the elements of this list in NlogN time. Equivalent + * elements remain in list order. + */ + template + void + sort(_Comp __comp); + + /** + * @brief Reverse the elements in list. + * + * Reverse the order of elements in the list in linear time. + */ + void + reverse() noexcept + { this->_M_impl._M_head._M_reverse_after(); } + + private: + // Called by the range constructor to implement [23.3.4.2]/9 + template + void + _M_range_initialize(_InputIterator __first, _InputIterator __last); + + // Called by forward_list(n,v,a), and the range constructor when it + // turns out to be the same thing. + void + _M_fill_initialize(size_type __n, const value_type& __value); + + // Called by splice_after and insert_after. + iterator + _M_splice_after(const_iterator __pos, const_iterator __before, + const_iterator __last); + + // Called by forward_list(n). + void + _M_default_initialize(size_type __n); + + // Called by resize(sz). + void + _M_default_insert_after(const_iterator __pos, size_type __n); + + // Called by operator=(forward_list&&) + void + _M_move_assign(forward_list&& __list, true_type) noexcept + { + clear(); + this->_M_impl._M_head._M_next = __list._M_impl._M_head._M_next; + __list._M_impl._M_head._M_next = nullptr; + std::__alloc_on_move(this->_M_get_Node_allocator(), + __list._M_get_Node_allocator()); + } + + // Called by operator=(forward_list&&) + void + _M_move_assign(forward_list&& __list, false_type) + { + if (__list._M_get_Node_allocator() == this->_M_get_Node_allocator()) + _M_move_assign(std::move(__list), true_type()); + else + // The rvalue's allocator cannot be moved, or is not equal, + // so we need to individually move each element. + this->assign(std::make_move_iterator(__list.begin()), + std::make_move_iterator(__list.end())); + } + + // Called by assign(_InputIterator, _InputIterator) if _Tp is + // CopyAssignable. + template + void + _M_assign(_InputIterator __first, _InputIterator __last, true_type) + { + auto __prev = before_begin(); + auto __curr = begin(); + auto __end = end(); + while (__curr != __end && __first != __last) + { + *__curr = *__first; + ++__prev; + ++__curr; + ++__first; + } + if (__first != __last) + insert_after(__prev, __first, __last); + else if (__curr != __end) + erase_after(__prev, __end); + } + + // Called by assign(_InputIterator, _InputIterator) if _Tp is not + // CopyAssignable. + template + void + _M_assign(_InputIterator __first, _InputIterator __last, false_type) + { + clear(); + insert_after(cbefore_begin(), __first, __last); + } + + // Called by assign(size_type, const _Tp&) if Tp is CopyAssignable + void + _M_assign_n(size_type __n, const _Tp& __val, true_type) + { + auto __prev = before_begin(); + auto __curr = begin(); + auto __end = end(); + while (__curr != __end && __n > 0) + { + *__curr = __val; + ++__prev; + ++__curr; + --__n; + } + if (__n > 0) + insert_after(__prev, __n, __val); + else if (__curr != __end) + erase_after(__prev, __end); + } + + // Called by assign(size_type, const _Tp&) if Tp is non-CopyAssignable + void + _M_assign_n(size_type __n, const _Tp& __val, false_type) + { + clear(); + insert_after(cbefore_begin(), __n, __val); + } + }; + +#if __cpp_deduction_guides >= 201606 + template::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + forward_list(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> forward_list<_ValT, _Allocator>; +#endif + + /** + * @brief Forward list equality comparison. + * @param __lx A %forward_list + * @param __ly A %forward_list of the same type as @a __lx. + * @return True iff the elements of the forward lists are equal. + * + * This is an equivalence relation. It is linear in the number of + * elements of the forward lists. Deques are considered equivalent + * if corresponding elements compare equal. + */ + template + bool + operator==(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly); + +#if __cpp_lib_three_way_comparison + /** + * @brief Forward list ordering relation. + * @param __x A `forward_list`. + * @param __y A `forward_list` of the same type as `__x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Tp> + operator<=>(const forward_list<_Tp, _Alloc>& __x, + const forward_list<_Tp, _Alloc>& __y) + { + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + /** + * @brief Forward list ordering relation. + * @param __lx A %forward_list. + * @param __ly A %forward_list of the same type as @a __lx. + * @return True iff @a __lx is lexicographically less than @a __ly. + * + * This is a total ordering relation. It is linear in the number of + * elements of the forward lists. The elements must be comparable + * with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return std::lexicographical_compare(__lx.cbegin(), __lx.cend(), + __ly.cbegin(), __ly.cend()); } + + /// Based on operator== + template + inline bool + operator!=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__lx == __ly); } + + /// Based on operator< + template + inline bool + operator>(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return (__ly < __lx); } + + /// Based on operator< + template + inline bool + operator>=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__lx < __ly); } + + /// Based on operator< + template + inline bool + operator<=(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { return !(__ly < __lx); } +#endif // three-way comparison + + /// See std::forward_list::swap(). + template + inline void + swap(forward_list<_Tp, _Alloc>& __lx, + forward_list<_Tp, _Alloc>& __ly) + noexcept(noexcept(__lx.swap(__ly))) + { __lx.swap(__ly); } + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _FORWARD_LIST_H diff --git a/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc b/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc new file mode 100644 index 000000000..c42bdc0fd --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/forward_list.tcc @@ -0,0 +1,517 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/forward_list.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{forward_list} + */ + +#ifndef _FORWARD_LIST_TCC +#define _FORWARD_LIST_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + _Fwd_list_base<_Tp, _Alloc>:: + _Fwd_list_base(_Fwd_list_base&& __lst, _Node_alloc_type&& __a) + : _M_impl(std::move(__a)) + { + if (__lst._M_get_Node_allocator() == _M_get_Node_allocator()) + this->_M_impl._M_head = std::move(__lst._M_impl._M_head); + } + + template + template + _Fwd_list_node_base* + _Fwd_list_base<_Tp, _Alloc>:: + _M_insert_after(const_iterator __pos, _Args&&... __args) + { + _Fwd_list_node_base* __to + = const_cast<_Fwd_list_node_base*>(__pos._M_node); + _Node* __thing = _M_create_node(std::forward<_Args>(__args)...); + __thing->_M_next = __to->_M_next; + __to->_M_next = __thing; + return __to->_M_next; + } + + template + _Fwd_list_node_base* + _Fwd_list_base<_Tp, _Alloc>:: + _M_erase_after(_Fwd_list_node_base* __pos) + { + _Node* __curr = static_cast<_Node*>(__pos->_M_next); + __pos->_M_next = __curr->_M_next; + _Node_alloc_traits::destroy(_M_get_Node_allocator(), + __curr->_M_valptr()); + __curr->~_Node(); + _M_put_node(__curr); + return __pos->_M_next; + } + + template + _Fwd_list_node_base* + _Fwd_list_base<_Tp, _Alloc>:: + _M_erase_after(_Fwd_list_node_base* __pos, + _Fwd_list_node_base* __last) + { + _Node* __curr = static_cast<_Node*>(__pos->_M_next); + while (__curr != __last) + { + _Node* __temp = __curr; + __curr = static_cast<_Node*>(__curr->_M_next); + _Node_alloc_traits::destroy(_M_get_Node_allocator(), + __temp->_M_valptr()); + __temp->~_Node(); + _M_put_node(__temp); + } + __pos->_M_next = __last; + return __last; + } + + // Called by the range constructor to implement [23.3.4.2]/9 + template + template + void + forward_list<_Tp, _Alloc>:: + _M_range_initialize(_InputIterator __first, _InputIterator __last) + { + _Node_base* __to = &this->_M_impl._M_head; + for (; __first != __last; ++__first) + { + __to->_M_next = this->_M_create_node(*__first); + __to = __to->_M_next; + } + } + + // Called by forward_list(n,v,a). + template + void + forward_list<_Tp, _Alloc>:: + _M_fill_initialize(size_type __n, const value_type& __value) + { + _Node_base* __to = &this->_M_impl._M_head; + for (; __n; --__n) + { + __to->_M_next = this->_M_create_node(__value); + __to = __to->_M_next; + } + } + + template + void + forward_list<_Tp, _Alloc>:: + _M_default_initialize(size_type __n) + { + _Node_base* __to = &this->_M_impl._M_head; + for (; __n; --__n) + { + __to->_M_next = this->_M_create_node(); + __to = __to->_M_next; + } + } + + template + forward_list<_Tp, _Alloc>& + forward_list<_Tp, _Alloc>:: + operator=(const forward_list& __list) + { + if (std::__addressof(__list) != this) + { + if (_Node_alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_get_Node_allocator(); + auto& __that_alloc = __list._M_get_Node_allocator(); + if (!_Node_alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // replacement allocator cannot free existing storage + clear(); + } + std::__alloc_on_copy(__this_alloc, __that_alloc); + } + assign(__list.cbegin(), __list.cend()); + } + return *this; + } + + template + void + forward_list<_Tp, _Alloc>:: + _M_default_insert_after(const_iterator __pos, size_type __n) + { + const_iterator __saved_pos = __pos; + __try + { + for (; __n; --__n) + __pos = emplace_after(__pos); + } + __catch(...) + { + erase_after(__saved_pos, ++__pos); + __throw_exception_again; + } + } + + template + void + forward_list<_Tp, _Alloc>:: + resize(size_type __sz) + { + iterator __k = before_begin(); + + size_type __len = 0; + while (__k._M_next() != end() && __len < __sz) + { + ++__k; + ++__len; + } + if (__len == __sz) + erase_after(__k, end()); + else + _M_default_insert_after(__k, __sz - __len); + } + + template + void + forward_list<_Tp, _Alloc>:: + resize(size_type __sz, const value_type& __val) + { + iterator __k = before_begin(); + + size_type __len = 0; + while (__k._M_next() != end() && __len < __sz) + { + ++__k; + ++__len; + } + if (__len == __sz) + erase_after(__k, end()); + else + insert_after(__k, __sz - __len, __val); + } + + template + typename forward_list<_Tp, _Alloc>::iterator + forward_list<_Tp, _Alloc>:: + _M_splice_after(const_iterator __pos, + const_iterator __before, const_iterator __last) + { + _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node); + _Node_base* __b = const_cast<_Node_base*>(__before._M_node); + _Node_base* __end = __b; + + while (__end && __end->_M_next != __last._M_node) + __end = __end->_M_next; + + if (__b != __end) + return iterator(__tmp->_M_transfer_after(__b, __end)); + else + return iterator(__tmp); + } + + template + void + forward_list<_Tp, _Alloc>:: + splice_after(const_iterator __pos, forward_list&&, + const_iterator __i) noexcept + { + const_iterator __j = __i; + ++__j; + + if (__pos == __i || __pos == __j) + return; + + _Node_base* __tmp = const_cast<_Node_base*>(__pos._M_node); + __tmp->_M_transfer_after(const_cast<_Node_base*>(__i._M_node), + const_cast<_Node_base*>(__j._M_node)); + } + + template + typename forward_list<_Tp, _Alloc>::iterator + forward_list<_Tp, _Alloc>:: + insert_after(const_iterator __pos, size_type __n, const _Tp& __val) + { + if (__n) + { + forward_list __tmp(__n, __val, get_allocator()); + return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end()); + } + else + return iterator(const_cast<_Node_base*>(__pos._M_node)); + } + + template + template + typename forward_list<_Tp, _Alloc>::iterator + forward_list<_Tp, _Alloc>:: + insert_after(const_iterator __pos, + _InputIterator __first, _InputIterator __last) + { + forward_list __tmp(__first, __last, get_allocator()); + if (!__tmp.empty()) + return _M_splice_after(__pos, __tmp.before_begin(), __tmp.end()); + else + return iterator(const_cast<_Node_base*>(__pos._M_node)); + } + +#if __cplusplus > 201703L +# define _GLIBCXX20_ONLY(__expr) __expr +#else +# define _GLIBCXX20_ONLY(__expr) +#endif + + template + auto + forward_list<_Tp, _Alloc>:: + remove(const _Tp& __val) -> __remove_return_type + { + size_type __removed __attribute__((__unused__)) = 0; + _Node_base* __curr = &this->_M_impl._M_head; + _Node_base* __extra = nullptr; + + while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) + { + if (*__tmp->_M_valptr() == __val) + { + if (__tmp->_M_valptr() != std::__addressof(__val)) + { + this->_M_erase_after(__curr); + _GLIBCXX20_ONLY( __removed++ ); + continue; + } + else + __extra = __curr; + } + __curr = __curr->_M_next; + } + + if (__extra) + { + this->_M_erase_after(__extra); + _GLIBCXX20_ONLY( __removed++ ); + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + template + auto + forward_list<_Tp, _Alloc>:: + remove_if(_Pred __pred) -> __remove_return_type + { + size_type __removed __attribute__((__unused__)) = 0; + _Node_base* __curr = &this->_M_impl._M_head; + while (_Node* __tmp = static_cast<_Node*>(__curr->_M_next)) + { + if (__pred(*__tmp->_M_valptr())) + { + this->_M_erase_after(__curr); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __curr = __curr->_M_next; + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + template + auto + forward_list<_Tp, _Alloc>:: + unique(_BinPred __binary_pred) -> __remove_return_type + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return _GLIBCXX20_ONLY(0); + size_type __removed __attribute__((__unused__)) = 0; + iterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(*__first, *__next)) + { + erase_after(__first); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __first = __next; + __next = __first; + } + return _GLIBCXX20_ONLY( __removed ); + } + +#undef _GLIBCXX20_ONLY + + template + template + void + forward_list<_Tp, _Alloc>:: + merge(forward_list&& __list, _Comp __comp) + { + _Node_base* __node = &this->_M_impl._M_head; + while (__node->_M_next && __list._M_impl._M_head._M_next) + { + if (__comp(*static_cast<_Node*> + (__list._M_impl._M_head._M_next)->_M_valptr(), + *static_cast<_Node*> + (__node->_M_next)->_M_valptr())) + __node->_M_transfer_after(&__list._M_impl._M_head, + __list._M_impl._M_head._M_next); + __node = __node->_M_next; + } + + if (__list._M_impl._M_head._M_next) + *__node = std::move(__list._M_impl._M_head); + } + + template + bool + operator==(const forward_list<_Tp, _Alloc>& __lx, + const forward_list<_Tp, _Alloc>& __ly) + { + // We don't have size() so we need to walk through both lists + // making sure both iterators are valid. + auto __ix = __lx.cbegin(); + auto __iy = __ly.cbegin(); + while (__ix != __lx.cend() && __iy != __ly.cend()) + { + if (!(*__ix == *__iy)) + return false; + ++__ix; + ++__iy; + } + if (__ix == __lx.cend() && __iy == __ly.cend()) + return true; + else + return false; + } + + template + template + void + forward_list<_Tp, _Alloc>:: + sort(_Comp __comp) + { + // If `next' is nullptr, return immediately. + _Node* __list = static_cast<_Node*>(this->_M_impl._M_head._M_next); + if (!__list) + return; + + unsigned long __insize = 1; + + while (1) + { + _Node* __p = __list; + __list = nullptr; + _Node* __tail = nullptr; + + // Count number of merges we do in this pass. + unsigned long __nmerges = 0; + + while (__p) + { + ++__nmerges; + // There exists a merge to be done. + // Step `insize' places along from p. + _Node* __q = __p; + unsigned long __psize = 0; + for (unsigned long __i = 0; __i < __insize; ++__i) + { + ++__psize; + __q = static_cast<_Node*>(__q->_M_next); + if (!__q) + break; + } + + // If q hasn't fallen off end, we have two lists to merge. + unsigned long __qsize = __insize; + + // Now we have two lists; merge them. + while (__psize > 0 || (__qsize > 0 && __q)) + { + // Decide whether next node of merge comes from p or q. + _Node* __e; + if (__psize == 0) + { + // p is empty; e must come from q. + __e = __q; + __q = static_cast<_Node*>(__q->_M_next); + --__qsize; + } + else if (__qsize == 0 || !__q) + { + // q is empty; e must come from p. + __e = __p; + __p = static_cast<_Node*>(__p->_M_next); + --__psize; + } + else if (!__comp(*__q->_M_valptr(), *__p->_M_valptr())) + { + // First node of q is not lower; e must come from p. + __e = __p; + __p = static_cast<_Node*>(__p->_M_next); + --__psize; + } + else + { + // First node of q is lower; e must come from q. + __e = __q; + __q = static_cast<_Node*>(__q->_M_next); + --__qsize; + } + + // Add the next node to the merged list. + if (__tail) + __tail->_M_next = __e; + else + __list = __e; + __tail = __e; + } + + // Now p has stepped `insize' places along, and q has too. + __p = __q; + } + __tail->_M_next = nullptr; + + // If we have done only one merge, we're finished. + // Allow for nmerges == 0, the empty list case. + if (__nmerges <= 1) + { + this->_M_impl._M_head._M_next = __list; + return; + } + + // Otherwise repeat, merging lists twice the size. + __insize *= 2; + } + } + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _FORWARD_LIST_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bits/functexcept.h b/resources/sources/avr-libstdcpp/include/bits/functexcept.h new file mode 100644 index 000000000..b7494f367 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/functexcept.h @@ -0,0 +1,114 @@ +// Function-Based Exception Support -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/functexcept.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{exception} + * + * This header provides support for -fno-exceptions. + */ + +// +// ISO C++ 14882: 19.1 Exception classes +// + +#ifndef _FUNCTEXCEPT_H +#define _FUNCTEXCEPT_H 1 + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Helper for exception objects in + void + __throw_bad_exception(void) __attribute__((__noreturn__)); + + // Helper for exception objects in + void + __throw_bad_alloc(void) __attribute__((__noreturn__)); + + // Helper for exception objects in + void + __throw_bad_cast(void) __attribute__((__noreturn__)); + + void + __throw_bad_typeid(void) __attribute__((__noreturn__)); + + // Helpers for exception objects in + void + __throw_logic_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_domain_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_invalid_argument(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_length_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_out_of_range(const char* __s = "") __attribute__((__noreturn__)); + + inline void __attribute__((__noreturn__)) __attribute__((always_inline)) + __throw_out_of_range_fmt(const char*, ...) + { __throw_out_of_range(); } + + void + __throw_runtime_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_range_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_overflow_error(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_underflow_error(const char* __s = "") __attribute__((__noreturn__)); + + // Helpers for exception objects in + void + __throw_system_error(int) __attribute__((__noreturn__)); + + // Helpers for exception objects in + void + __throw_bad_function_call() __attribute__((__noreturn__)); + + void + __throw_bad_optional_access() __attribute__((__noreturn__)); + + void + __throw_bad_variant_access(const char* __s = "") __attribute__((__noreturn__)); + + void + __throw_bad_any_cast() __attribute__((__noreturn__)); + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/functional_hash.h b/resources/sources/avr-libstdcpp/include/bits/functional_hash.h new file mode 100644 index 000000000..e50b047ff --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/functional_hash.h @@ -0,0 +1,280 @@ +// functional_hash.h header -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/functional_hash.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _FUNCTIONAL_HASH_H +#define _FUNCTIONAL_HASH_H 1 + +#pragma GCC system_header + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @defgroup hashes Hashes + * @ingroup functors + * + * Hashing functors taking a variable type and returning a @c std::size_t. + * + * @{ + */ + + template + struct __hash_base + { + typedef _Result result_type _GLIBCXX17_DEPRECATED; + typedef _Arg argument_type _GLIBCXX17_DEPRECATED; + }; + + /// Primary class template hash. + template + struct hash; + + template + struct __poison_hash + { + static constexpr bool __enable_hash_call = false; + private: + // Private rather than deleted to be non-trivially-copyable. + __poison_hash(__poison_hash&&); + ~__poison_hash(); + }; + + template + struct __poison_hash<_Tp, __void_t()(declval<_Tp>()))>> + { + static constexpr bool __enable_hash_call = true; + }; + + // Helper struct for SFINAE-poisoning non-enum types. + template::value> + struct __hash_enum + { + private: + // Private rather than deleted to be non-trivially-copyable. + __hash_enum(__hash_enum&&); + ~__hash_enum(); + }; + + // Helper struct for hash with enum types. + template + struct __hash_enum<_Tp, true> : public __hash_base + { + size_t + operator()(_Tp __val) const noexcept + { + using __type = typename underlying_type<_Tp>::type; + return hash<__type>{}(static_cast<__type>(__val)); + } + }; + + /// Primary class template hash, usable for enum types only. + // Use with non-enum types still SFINAES. + template + struct hash : __hash_enum<_Tp> + { }; + + /// Partial specializations for pointer types. + template + struct hash<_Tp*> : public __hash_base + { + size_t + operator()(_Tp* __p) const noexcept + { return reinterpret_cast(__p); } + }; + + // Explicit specializations for integer types. +#define _Cxx_hashtable_define_trivial_hash(_Tp) \ + template<> \ + struct hash<_Tp> : public __hash_base \ + { \ + size_t \ + operator()(_Tp __val) const noexcept \ + { return static_cast(__val); } \ + }; + + /// Explicit specialization for bool. + _Cxx_hashtable_define_trivial_hash(bool) + + /// Explicit specialization for char. + _Cxx_hashtable_define_trivial_hash(char) + + /// Explicit specialization for signed char. + _Cxx_hashtable_define_trivial_hash(signed char) + + /// Explicit specialization for unsigned char. + _Cxx_hashtable_define_trivial_hash(unsigned char) + + /// Explicit specialization for wchar_t. + _Cxx_hashtable_define_trivial_hash(wchar_t) + +#ifdef _GLIBCXX_USE_CHAR8_T + /// Explicit specialization for char8_t. + _Cxx_hashtable_define_trivial_hash(char8_t) +#endif + + /// Explicit specialization for char16_t. + _Cxx_hashtable_define_trivial_hash(char16_t) + + /// Explicit specialization for char32_t. + _Cxx_hashtable_define_trivial_hash(char32_t) + + /// Explicit specialization for short. + _Cxx_hashtable_define_trivial_hash(short) + + /// Explicit specialization for int. + _Cxx_hashtable_define_trivial_hash(int) + + /// Explicit specialization for long. + _Cxx_hashtable_define_trivial_hash(long) + + /// Explicit specialization for long long. + _Cxx_hashtable_define_trivial_hash(long long) + + /// Explicit specialization for unsigned short. + _Cxx_hashtable_define_trivial_hash(unsigned short) + + /// Explicit specialization for unsigned int. + _Cxx_hashtable_define_trivial_hash(unsigned int) + + /// Explicit specialization for unsigned long. + _Cxx_hashtable_define_trivial_hash(unsigned long) + + /// Explicit specialization for unsigned long long. + _Cxx_hashtable_define_trivial_hash(unsigned long long) + +#ifdef __GLIBCXX_TYPE_INT_N_0 + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0) + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_0 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1) + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_1 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2) + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_2 unsigned) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3) + _Cxx_hashtable_define_trivial_hash(__GLIBCXX_TYPE_INT_N_3 unsigned) +#endif + +#undef _Cxx_hashtable_define_trivial_hash + + struct _Hash_impl + { + static size_t + hash(const void* __ptr, size_t __clength, + size_t __seed = static_cast(0xc70f6907UL)) + { return _Hash_bytes(__ptr, __clength, __seed); } + + template + static size_t + hash(const _Tp& __val) + { return hash(&__val, sizeof(__val)); } + + template + static size_t + __hash_combine(const _Tp& __val, size_t __hash) + { return hash(&__val, sizeof(__val), __hash); } + }; + + // A hash function similar to FNV-1a (see PR59406 for how it differs). + struct _Fnv_hash_impl + { + static size_t + hash(const void* __ptr, size_t __clength, + size_t __seed = static_cast(2166136261UL)) + { return _Fnv_hash_bytes(__ptr, __clength, __seed); } + + template + static size_t + hash(const _Tp& __val) + { return hash(&__val, sizeof(__val)); } + + template + static size_t + __hash_combine(const _Tp& __val, size_t __hash) + { return hash(&__val, sizeof(__val), __hash); } + }; + + /// Specialization for float. + template<> + struct hash : public __hash_base + { + size_t + operator()(float __val) const noexcept + { + // 0 and -0 both hash to zero. + return __val != 0.0f ? std::_Hash_impl::hash(__val) : 0; + } + }; + + /// Specialization for double. + template<> + struct hash : public __hash_base + { + size_t + operator()(double __val) const noexcept + { + // 0 and -0 both hash to zero. + return __val != 0.0 ? std::_Hash_impl::hash(__val) : 0; + } + }; + +#if __cplusplus >= 201703L + template<> + struct hash : public __hash_base + { + size_t + operator()(nullptr_t) const noexcept + { return 0; } + }; +#endif + + // @} group hashes + + // Hint about performance of hash functor. If not fast the hash-based + // containers will cache the hash code. + // Default behavior is to consider that hashers are fast unless specified + // otherwise. + template + struct __is_fast_hash : public std::true_type + { }; + + template<> + struct __is_fast_hash> : public std::false_type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // _FUNCTIONAL_HASH_H diff --git a/resources/sources/avr-libstdcpp/include/bits/gslice.h b/resources/sources/avr-libstdcpp/include/bits/gslice.h new file mode 100644 index 000000000..b252c3c1f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/gslice.h @@ -0,0 +1,185 @@ +// The template and inlines for the -*- C++ -*- gslice class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/gslice.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _GSLICE_H +#define _GSLICE_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Class defining multi-dimensional subset of an array. + * + * The slice class represents a multi-dimensional subset of an array, + * specified by three parameter sets: start offset, size array, and stride + * array. The start offset is the index of the first element of the array + * that is part of the subset. The size and stride array describe each + * dimension of the slice. Size is the number of elements in that + * dimension, and stride is the distance in the array between successive + * elements in that dimension. Each dimension's size and stride is taken + * to begin at an array element described by the previous dimension. The + * size array and stride array must be the same size. + * + * For example, if you have offset==3, stride[0]==11, size[1]==3, + * stride[1]==3, then slice[0,0]==array[3], slice[0,1]==array[6], + * slice[0,2]==array[9], slice[1,0]==array[14], slice[1,1]==array[17], + * slice[1,2]==array[20]. + */ + class gslice + { + public: + /// Construct an empty slice. + gslice(); + + /** + * @brief Construct a slice. + * + * Constructs a slice with as many dimensions as the length of the @a l + * and @a s arrays. + * + * @param __o Offset in array of first element. + * @param __l Array of dimension lengths. + * @param __s Array of dimension strides between array elements. + */ + gslice(size_t __o, const valarray& __l, + const valarray& __s); + + // XXX: the IS says the copy-ctor and copy-assignment operators are + // synthesized by the compiler but they are just unsuitable + // for a ref-counted semantic + /// Copy constructor. + gslice(const gslice&); + + /// Destructor. + ~gslice(); + + // XXX: See the note above. + /// Assignment operator. + gslice& operator=(const gslice&); + + /// Return array offset of first slice element. + size_t start() const; + + /// Return array of sizes of slice dimensions. + valarray size() const; + + /// Return array of array strides for each dimension. + valarray stride() const; + + private: + struct _Indexer + { + size_t _M_count; + size_t _M_start; + valarray _M_size; + valarray _M_stride; + valarray _M_index; // Linear array of referenced indices + + _Indexer() + : _M_count(1), _M_start(0), _M_size(), _M_stride(), _M_index() {} + + _Indexer(size_t, const valarray&, + const valarray&); + + void + _M_increment_use() + { ++_M_count; } + + size_t + _M_decrement_use() + { return --_M_count; } + }; + + _Indexer* _M_index; + + template friend class valarray; + }; + + inline size_t + gslice::start() const + { return _M_index ? _M_index->_M_start : 0; } + + inline valarray + gslice::size() const + { return _M_index ? _M_index->_M_size : valarray(); } + + inline valarray + gslice::stride() const + { return _M_index ? _M_index->_M_stride : valarray(); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 543. valarray slice default constructor + inline + gslice::gslice() + : _M_index(new gslice::_Indexer()) {} + + inline + gslice::gslice(size_t __o, const valarray& __l, + const valarray& __s) + : _M_index(new gslice::_Indexer(__o, __l, __s)) {} + + inline + gslice::gslice(const gslice& __g) + : _M_index(__g._M_index) + { if (_M_index) _M_index->_M_increment_use(); } + + inline + gslice::~gslice() + { + if (_M_index && _M_index->_M_decrement_use() == 0) + delete _M_index; + } + + inline gslice& + gslice::operator=(const gslice& __g) + { + if (__g._M_index) + __g._M_index->_M_increment_use(); + if (_M_index && _M_index->_M_decrement_use() == 0) + delete _M_index; + _M_index = __g._M_index; + return *this; + } + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _GSLICE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/gslice_array.h b/resources/sources/avr-libstdcpp/include/bits/gslice_array.h new file mode 100644 index 000000000..89fdda537 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/gslice_array.h @@ -0,0 +1,223 @@ +// The template and inlines for the -*- C++ -*- gslice_array class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/gslice_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _GSLICE_ARRAY_H +#define _GSLICE_ARRAY_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Reference to multi-dimensional subset of an array. + * + * A gslice_array is a reference to the actual elements of an array + * specified by a gslice. The way to get a gslice_array is to call + * operator[](gslice) on a valarray. The returned gslice_array then + * permits carrying operations out on the referenced subset of elements in + * the original valarray. For example, operator+=(valarray) will add + * values to the subset of elements in the underlying valarray this + * gslice_array refers to. + * + * @param Tp Element type. + */ + template + class gslice_array + { + public: + typedef _Tp value_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 253. valarray helper functions are almost entirely useless + + /// Copy constructor. Both slices refer to the same underlying array. + gslice_array(const gslice_array&); + + /// Assignment operator. Assigns slice elements to corresponding + /// elements of @a a. + gslice_array& operator=(const gslice_array&); + + /// Assign slice elements to corresponding elements of @a v. + void operator=(const valarray<_Tp>&) const; + /// Multiply slice elements by corresponding elements of @a v. + void operator*=(const valarray<_Tp>&) const; + /// Divide slice elements by corresponding elements of @a v. + void operator/=(const valarray<_Tp>&) const; + /// Modulo slice elements by corresponding elements of @a v. + void operator%=(const valarray<_Tp>&) const; + /// Add corresponding elements of @a v to slice elements. + void operator+=(const valarray<_Tp>&) const; + /// Subtract corresponding elements of @a v from slice elements. + void operator-=(const valarray<_Tp>&) const; + /// Logical xor slice elements with corresponding elements of @a v. + void operator^=(const valarray<_Tp>&) const; + /// Logical and slice elements with corresponding elements of @a v. + void operator&=(const valarray<_Tp>&) const; + /// Logical or slice elements with corresponding elements of @a v. + void operator|=(const valarray<_Tp>&) const; + /// Left shift slice elements by corresponding elements of @a v. + void operator<<=(const valarray<_Tp>&) const; + /// Right shift slice elements by corresponding elements of @a v. + void operator>>=(const valarray<_Tp>&) const; + /// Assign all slice elements to @a t. + void operator=(const _Tp&) const; + + template + void operator=(const _Expr<_Dom, _Tp>&) const; + template + void operator*=(const _Expr<_Dom, _Tp>&) const; + template + void operator/=(const _Expr<_Dom, _Tp>&) const; + template + void operator%=(const _Expr<_Dom, _Tp>&) const; + template + void operator+=(const _Expr<_Dom, _Tp>&) const; + template + void operator-=(const _Expr<_Dom, _Tp>&) const; + template + void operator^=(const _Expr<_Dom, _Tp>&) const; + template + void operator&=(const _Expr<_Dom, _Tp>&) const; + template + void operator|=(const _Expr<_Dom, _Tp>&) const; + template + void operator<<=(const _Expr<_Dom, _Tp>&) const; + template + void operator>>=(const _Expr<_Dom, _Tp>&) const; + + private: + _Array<_Tp> _M_array; + const valarray& _M_index; + + friend class valarray<_Tp>; + + gslice_array(_Array<_Tp>, const valarray&); + +#if __cplusplus < 201103L + // not implemented + gslice_array(); +#else + public: + gslice_array() = delete; +#endif + }; + + template + inline + gslice_array<_Tp>::gslice_array(_Array<_Tp> __a, + const valarray& __i) + : _M_array(__a), _M_index(__i) {} + + template + inline + gslice_array<_Tp>::gslice_array(const gslice_array<_Tp>& __a) + : _M_array(__a._M_array), _M_index(__a._M_index) {} + + template + inline gslice_array<_Tp>& + gslice_array<_Tp>::operator=(const gslice_array<_Tp>& __a) + { + std::__valarray_copy(_Array<_Tp>(__a._M_array), + _Array(__a._M_index), _M_index.size(), + _M_array, _Array(_M_index)); + return *this; + } + + template + inline void + gslice_array<_Tp>::operator=(const _Tp& __t) const + { + std::__valarray_fill(_M_array, _Array(_M_index), + _M_index.size(), __t); + } + + template + inline void + gslice_array<_Tp>::operator=(const valarray<_Tp>& __v) const + { + std::__valarray_copy(_Array<_Tp>(__v), __v.size(), + _M_array, _Array(_M_index)); + } + + template + template + inline void + gslice_array<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) const + { + std::__valarray_copy (__e, _M_index.size(), _M_array, + _Array(_M_index)); + } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ + template \ + inline void \ + gslice_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ + { \ + _Array_augmented_##_Name(_M_array, _Array(_M_index), \ + _Array<_Tp>(__v), __v.size()); \ + } \ + \ + template \ + template \ + inline void \ + gslice_array<_Tp>::operator _Op##= (const _Expr<_Dom, _Tp>& __e) const\ + { \ + _Array_augmented_##_Name(_M_array, _Array(_M_index), __e,\ + _M_index.size()); \ + } + +_DEFINE_VALARRAY_OPERATOR(*, __multiplies) +_DEFINE_VALARRAY_OPERATOR(/, __divides) +_DEFINE_VALARRAY_OPERATOR(%, __modulus) +_DEFINE_VALARRAY_OPERATOR(+, __plus) +_DEFINE_VALARRAY_OPERATOR(-, __minus) +_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) +_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) +_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) +_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _GSLICE_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h b/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h new file mode 100644 index 000000000..8d9c9eb24 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/hash_bytes.h @@ -0,0 +1,59 @@ +// Declarations for hash functions. -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/hash_bytes.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _HASH_BYTES_H +#define _HASH_BYTES_H 1 + +#pragma GCC system_header + +#include + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Hash function implementation for the nontrivial specialization. + // All of them are based on a primitive that hashes a pointer to a + // byte array. The actual hash algorithm is not guaranteed to stay + // the same from release to release -- it may be updated or tuned to + // improve hash quality or speed. + size_t + _Hash_bytes(const void* __ptr, size_t __len, size_t __seed); + + // A similar hash primitive, using the FNV hash algorithm. This + // algorithm is guaranteed to stay the same from release to release. + // (although it might not produce the same values on different + // machines.) + size_t + _Fnv_hash_bytes(const void* __ptr, size_t __len, size_t __seed); + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/hashtable.h b/resources/sources/avr-libstdcpp/include/bits/hashtable.h new file mode 100644 index 000000000..b00319a66 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/hashtable.h @@ -0,0 +1,2228 @@ +// hashtable.h header -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/hashtable.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{unordered_map, unordered_set} + */ + +#ifndef _HASHTABLE_H +#define _HASHTABLE_H 1 + +#pragma GCC system_header + +#include +#if __cplusplus > 201402L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + using __cache_default + = __not_<__and_, + // Mandatory to have erase not throwing. + __is_nothrow_invocable>>; + + /** + * Primary class template _Hashtable. + * + * @ingroup hashtable-detail + * + * @tparam _Value CopyConstructible type. + * + * @tparam _Key CopyConstructible type. + * + * @tparam _Alloc An allocator type + * ([lib.allocator.requirements]) whose _Alloc::value_type is + * _Value. As a conforming extension, we allow for + * _Alloc::value_type != _Value. + * + * @tparam _ExtractKey Function object that takes an object of type + * _Value and returns a value of type _Key. + * + * @tparam _Equal Function object that takes two objects of type k + * and returns a bool-like value that is true if the two objects + * are considered equal. + * + * @tparam _H1 The hash function. A unary function object with + * argument type _Key and result type size_t. Return values should + * be distributed over the entire range [0, numeric_limits:::max()]. + * + * @tparam _H2 The range-hashing function (in the terminology of + * Tavori and Dreizin). A binary function object whose argument + * types and result type are all size_t. Given arguments r and N, + * the return value is in the range [0, N). + * + * @tparam _Hash The ranged hash function (Tavori and Dreizin). A + * binary function whose argument types are _Key and size_t and + * whose result type is size_t. Given arguments k and N, the + * return value is in the range [0, N). Default: hash(k, N) = + * h2(h1(k), N). If _Hash is anything other than the default, _H1 + * and _H2 are ignored. + * + * @tparam _RehashPolicy Policy class with three members, all of + * which govern the bucket count. _M_next_bkt(n) returns a bucket + * count no smaller than n. _M_bkt_for_elements(n) returns a + * bucket count appropriate for an element count of n. + * _M_need_rehash(n_bkt, n_elt, n_ins) determines whether, if the + * current bucket count is n_bkt and the current element count is + * n_elt, we need to increase the bucket count. If so, returns + * make_pair(true, n), where n is the new bucket count. If not, + * returns make_pair(false, ) + * + * @tparam _Traits Compile-time class with three boolean + * std::integral_constant members: __cache_hash_code, __constant_iterators, + * __unique_keys. + * + * Each _Hashtable data structure has: + * + * - _Bucket[] _M_buckets + * - _Hash_node_base _M_before_begin + * - size_type _M_bucket_count + * - size_type _M_element_count + * + * with _Bucket being _Hash_node* and _Hash_node containing: + * + * - _Hash_node* _M_next + * - Tp _M_value + * - size_t _M_hash_code if cache_hash_code is true + * + * In terms of Standard containers the hashtable is like the aggregation of: + * + * - std::forward_list<_Node> containing the elements + * - std::vector::iterator> representing the buckets + * + * The non-empty buckets contain the node before the first node in the + * bucket. This design makes it possible to implement something like a + * std::forward_list::insert_after on container insertion and + * std::forward_list::erase_after on container erase + * calls. _M_before_begin is equivalent to + * std::forward_list::before_begin. Empty buckets contain + * nullptr. Note that one of the non-empty buckets contains + * &_M_before_begin which is not a dereferenceable node so the + * node pointer in a bucket shall never be dereferenced, only its + * next node can be. + * + * Walking through a bucket's nodes requires a check on the hash code to + * see if each node is still in the bucket. Such a design assumes a + * quite efficient hash functor and is one of the reasons it is + * highly advisable to set __cache_hash_code to true. + * + * The container iterators are simply built from nodes. This way + * incrementing the iterator is perfectly efficient independent of + * how many empty buckets there are in the container. + * + * On insert we compute the element's hash code and use it to find the + * bucket index. If the element must be inserted in an empty bucket + * we add it at the beginning of the singly linked list and make the + * bucket point to _M_before_begin. The bucket that used to point to + * _M_before_begin, if any, is updated to point to its new before + * begin node. + * + * On erase, the simple iterator design requires using the hash + * functor to get the index of the bucket to update. For this + * reason, when __cache_hash_code is set to false the hash functor must + * not throw and this is enforced by a static assertion. + * + * Functionality is implemented by decomposition into base classes, + * where the derived _Hashtable class is used in _Map_base, + * _Insert, _Rehash_base, and _Equality base classes to access the + * "this" pointer. _Hashtable_base is used in the base classes as a + * non-recursive, fully-completed-type so that detailed nested type + * information, such as iterator type and node type, can be + * used. This is similar to the "Curiously Recurring Template + * Pattern" (CRTP) technique, but uses a reconstructed, not + * explicitly passed, template pattern. + * + * Base class templates are: + * - __detail::_Hashtable_base + * - __detail::_Map_base + * - __detail::_Insert + * - __detail::_Rehash_base + * - __detail::_Equality + */ + template + class _Hashtable + : public __detail::_Hashtable_base<_Key, _Value, _ExtractKey, _Equal, + _H1, _H2, _Hash, _Traits>, + public __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>, + public __detail::_Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>, + public __detail::_Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>, + public __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>, + private __detail::_Hashtable_alloc< + __alloc_rebind<_Alloc, + __detail::_Hash_node<_Value, + _Traits::__hash_cached::value>>> + { + static_assert(is_same::type, _Value>::value, + "unordered container must have a non-const, non-volatile value_type"); +#if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same{}, + "unordered container must have the same value_type as its allocator"); +#endif + + using __traits_type = _Traits; + using __hash_cached = typename __traits_type::__hash_cached; + using __node_type = __detail::_Hash_node<_Value, __hash_cached::value>; + using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>; + + using __hashtable_alloc = __detail::_Hashtable_alloc<__node_alloc_type>; + + using __value_alloc_traits = + typename __hashtable_alloc::__value_alloc_traits; + using __node_alloc_traits = + typename __hashtable_alloc::__node_alloc_traits; + using __node_base = typename __hashtable_alloc::__node_base; + using __bucket_type = typename __hashtable_alloc::__bucket_type; + + public: + typedef _Key key_type; + typedef _Value value_type; + typedef _Alloc allocator_type; + typedef _Equal key_equal; + + // mapped_type, if present, comes from _Map_base. + // hasher, if present, comes from _Hash_code_base/_Hashtable_base. + typedef typename __value_alloc_traits::pointer pointer; + typedef typename __value_alloc_traits::const_pointer const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + + private: + using __rehash_type = _RehashPolicy; + using __rehash_state = typename __rehash_type::_State; + + using __constant_iterators = typename __traits_type::__constant_iterators; + using __unique_keys = typename __traits_type::__unique_keys; + + using __key_extract = typename std::conditional< + __constant_iterators::value, + __detail::_Identity, + __detail::_Select1st>::type; + + using __hashtable_base = __detail:: + _Hashtable_base<_Key, _Value, _ExtractKey, + _Equal, _H1, _H2, _Hash, _Traits>; + + using __hash_code_base = typename __hashtable_base::__hash_code_base; + using __hash_code = typename __hashtable_base::__hash_code; + using __ireturn_type = typename __hashtable_base::__ireturn_type; + + using __map_base = __detail::_Map_base<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __rehash_base = __detail::_Rehash_base<_Key, _Value, _Alloc, + _ExtractKey, _Equal, + _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __eq_base = __detail::_Equality<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __reuse_or_alloc_node_gen_t = + __detail::_ReuseOrAllocNode<__node_alloc_type>; + using __alloc_node_gen_t = + __detail::_AllocNode<__node_alloc_type>; + + // Simple RAII type for managing a node containing an element + struct _Scoped_node + { + // Take ownership of a node with a constructed element. + _Scoped_node(__node_type* __n, __hashtable_alloc* __h) + : _M_h(__h), _M_node(__n) { } + + // Allocate a node and construct an element within it. + template + _Scoped_node(__hashtable_alloc* __h, _Args&&... __args) + : _M_h(__h), + _M_node(__h->_M_allocate_node(std::forward<_Args>(__args)...)) + { } + + // Destroy element and deallocate node. + ~_Scoped_node() { if (_M_node) _M_h->_M_deallocate_node(_M_node); }; + + _Scoped_node(const _Scoped_node&) = delete; + _Scoped_node& operator=(const _Scoped_node&) = delete; + + __hashtable_alloc* _M_h; + __node_type* _M_node; + }; + + template + static constexpr + typename conditional::value, + const value_type&, value_type&&>::type + __fwd_value_for(value_type& __val) noexcept + { return std::move(__val); } + + // Metaprogramming for picking apart hash caching. + template + using __if_hash_cached = __or_<__not_<__hash_cached>, _Cond>; + + template + using __if_hash_not_cached = __or_<__hash_cached, _Cond>; + + // Compile-time diagnostics. + + // _Hash_code_base has everything protected, so use this derived type to + // access it. + struct __hash_code_base_access : __hash_code_base + { using __hash_code_base::_M_bucket_index; }; + + // Getting a bucket index from a node shall not throw because it is used + // in methods (erase, swap...) that shall not throw. + static_assert(noexcept(declval() + ._M_bucket_index((const __node_type*)nullptr, + (std::size_t)0)), + "Cache the hash code or qualify your functors involved" + " in hash code and bucket index computation with noexcept"); + + // When hash codes are cached local iterator inherits from H2 functor + // which must then be default constructible. + static_assert(__if_hash_cached>::value, + "Functor used to map hash code to bucket index" + " must be default constructible"); + + template + friend struct __detail::_Map_base; + + template + friend struct __detail::_Insert_base; + + template + friend struct __detail::_Insert; + + template + friend struct __detail::_Equality; + + public: + using size_type = typename __hashtable_base::size_type; + using difference_type = typename __hashtable_base::difference_type; + + using iterator = typename __hashtable_base::iterator; + using const_iterator = typename __hashtable_base::const_iterator; + + using local_iterator = typename __hashtable_base::local_iterator; + using const_local_iterator = typename __hashtable_base:: + const_local_iterator; + +#if __cplusplus > 201402L + using node_type = _Node_handle<_Key, _Value, __node_alloc_type>; + using insert_return_type = _Node_insert_return; +#endif + + private: + __bucket_type* _M_buckets = &_M_single_bucket; + size_type _M_bucket_count = 1; + __node_base _M_before_begin; + size_type _M_element_count = 0; + _RehashPolicy _M_rehash_policy; + + // A single bucket used when only need for 1 bucket. Especially + // interesting in move semantic to leave hashtable with only 1 bucket + // which is not allocated so that we can have those operations noexcept + // qualified. + // Note that we can't leave hashtable with 0 bucket without adding + // numerous checks in the code to avoid 0 modulus. + __bucket_type _M_single_bucket = nullptr; + + bool + _M_uses_single_bucket(__bucket_type* __bkts) const + { return __builtin_expect(__bkts == &_M_single_bucket, false); } + + bool + _M_uses_single_bucket() const + { return _M_uses_single_bucket(_M_buckets); } + + __hashtable_alloc& + _M_base_alloc() { return *this; } + + __bucket_type* + _M_allocate_buckets(size_type __bkt_count) + { + if (__builtin_expect(__bkt_count == 1, false)) + { + _M_single_bucket = nullptr; + return &_M_single_bucket; + } + + return __hashtable_alloc::_M_allocate_buckets(__bkt_count); + } + + void + _M_deallocate_buckets(__bucket_type* __bkts, size_type __bkt_count) + { + if (_M_uses_single_bucket(__bkts)) + return; + + __hashtable_alloc::_M_deallocate_buckets(__bkts, __bkt_count); + } + + void + _M_deallocate_buckets() + { _M_deallocate_buckets(_M_buckets, _M_bucket_count); } + + // Gets bucket begin, deals with the fact that non-empty buckets contain + // their before begin node. + __node_type* + _M_bucket_begin(size_type __bkt) const; + + __node_type* + _M_begin() const + { return static_cast<__node_type*>(_M_before_begin._M_nxt); } + + // Assign *this using another _Hashtable instance. Whether elements + // are copied or moved depends on the _Ht reference. + template + void + _M_assign_elements(_Ht&&); + + template + void + _M_assign(_Ht&&, const _NodeGenerator&); + + void + _M_move_assign(_Hashtable&&, true_type); + + void + _M_move_assign(_Hashtable&&, false_type); + + void + _M_reset() noexcept; + + _Hashtable(const _H1& __h1, const _H2& __h2, const _Hash& __h, + const _Equal& __eq, const _ExtractKey& __exk, + const allocator_type& __a) + : __hashtable_base(__exk, __h1, __h2, __h, __eq), + __hashtable_alloc(__node_alloc_type(__a)) + { } + + public: + // Constructor, destructor, assignment, swap + _Hashtable() = default; + _Hashtable(size_type __bkt_count_hint, + const _H1&, const _H2&, const _Hash&, + const _Equal&, const _ExtractKey&, + const allocator_type&); + + template + _Hashtable(_InputIterator __first, _InputIterator __last, + size_type __bkt_count_hint, + const _H1&, const _H2&, const _Hash&, + const _Equal&, const _ExtractKey&, + const allocator_type&); + + _Hashtable(const _Hashtable&); + + _Hashtable(_Hashtable&&) noexcept; + + _Hashtable(const _Hashtable&, const allocator_type&); + + _Hashtable(_Hashtable&&, const allocator_type&); + + // Use delegating constructors. + explicit + _Hashtable(const allocator_type& __a) + : __hashtable_alloc(__node_alloc_type(__a)) + { } + + explicit + _Hashtable(size_type __bkt_count_hint, + const _H1& __hf = _H1(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Hashtable(__bkt_count_hint, __hf, _H2(), _Hash(), __eql, + __key_extract(), __a) + { } + + template + _Hashtable(_InputIterator __f, _InputIterator __l, + size_type __bkt_count_hint = 0, + const _H1& __hf = _H1(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Hashtable(__f, __l, __bkt_count_hint, __hf, _H2(), _Hash(), __eql, + __key_extract(), __a) + { } + + _Hashtable(initializer_list __l, + size_type __bkt_count_hint = 0, + const _H1& __hf = _H1(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _Hashtable(__l.begin(), __l.end(), __bkt_count_hint, + __hf, _H2(), _Hash(), __eql, + __key_extract(), __a) + { } + + _Hashtable& + operator=(const _Hashtable& __ht); + + _Hashtable& + operator=(_Hashtable&& __ht) + noexcept(__node_alloc_traits::_S_nothrow_move() + && is_nothrow_move_assignable<_H1>::value + && is_nothrow_move_assignable<_Equal>::value) + { + constexpr bool __move_storage = + __node_alloc_traits::_S_propagate_on_move_assign() + || __node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__ht), __bool_constant<__move_storage>()); + return *this; + } + + _Hashtable& + operator=(initializer_list __l) + { + __reuse_or_alloc_node_gen_t __roan(_M_begin(), *this); + _M_before_begin._M_nxt = nullptr; + clear(); + this->_M_insert_range(__l.begin(), __l.end(), __roan, __unique_keys()); + return *this; + } + + ~_Hashtable() noexcept; + + void + swap(_Hashtable&) + noexcept(__and_<__is_nothrow_swappable<_H1>, + __is_nothrow_swappable<_Equal>>::value); + + // Basic container operations + iterator + begin() noexcept + { return iterator(_M_begin()); } + + const_iterator + begin() const noexcept + { return const_iterator(_M_begin()); } + + iterator + end() noexcept + { return iterator(nullptr); } + + const_iterator + end() const noexcept + { return const_iterator(nullptr); } + + const_iterator + cbegin() const noexcept + { return const_iterator(_M_begin()); } + + const_iterator + cend() const noexcept + { return const_iterator(nullptr); } + + size_type + size() const noexcept + { return _M_element_count; } + + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return size() == 0; } + + allocator_type + get_allocator() const noexcept + { return allocator_type(this->_M_node_allocator()); } + + size_type + max_size() const noexcept + { return __node_alloc_traits::max_size(this->_M_node_allocator()); } + + // Observers + key_equal + key_eq() const + { return this->_M_eq(); } + + // hash_function, if present, comes from _Hash_code_base. + + // Bucket operations + size_type + bucket_count() const noexcept + { return _M_bucket_count; } + + size_type + max_bucket_count() const noexcept + { return max_size(); } + + size_type + bucket_size(size_type __bkt) const + { return std::distance(begin(__bkt), end(__bkt)); } + + size_type + bucket(const key_type& __k) const + { return _M_bucket_index(__k, this->_M_hash_code(__k)); } + + local_iterator + begin(size_type __bkt) + { + return local_iterator(*this, _M_bucket_begin(__bkt), + __bkt, _M_bucket_count); + } + + local_iterator + end(size_type __bkt) + { return local_iterator(*this, nullptr, __bkt, _M_bucket_count); } + + const_local_iterator + begin(size_type __bkt) const + { + return const_local_iterator(*this, _M_bucket_begin(__bkt), + __bkt, _M_bucket_count); + } + + const_local_iterator + end(size_type __bkt) const + { return const_local_iterator(*this, nullptr, __bkt, _M_bucket_count); } + + // DR 691. + const_local_iterator + cbegin(size_type __bkt) const + { + return const_local_iterator(*this, _M_bucket_begin(__bkt), + __bkt, _M_bucket_count); + } + + const_local_iterator + cend(size_type __bkt) const + { return const_local_iterator(*this, nullptr, __bkt, _M_bucket_count); } + + float + load_factor() const noexcept + { + return static_cast(size()) / static_cast(bucket_count()); + } + + // max_load_factor, if present, comes from _Rehash_base. + + // Generalization of max_load_factor. Extension, not found in + // TR1. Only useful if _RehashPolicy is something other than + // the default. + const _RehashPolicy& + __rehash_policy() const + { return _M_rehash_policy; } + + void + __rehash_policy(const _RehashPolicy& __pol) + { _M_rehash_policy = __pol; } + + // Lookup. + iterator + find(const key_type& __k); + + const_iterator + find(const key_type& __k) const; + + size_type + count(const key_type& __k) const; + + std::pair + equal_range(const key_type& __k); + + std::pair + equal_range(const key_type& __k) const; + + protected: + // Bucket index computation helpers. + size_type + _M_bucket_index(__node_type* __n) const noexcept + { return __hash_code_base::_M_bucket_index(__n, _M_bucket_count); } + + size_type + _M_bucket_index(const key_type& __k, __hash_code __c) const + { return __hash_code_base::_M_bucket_index(__k, __c, _M_bucket_count); } + + // Find and insert helper functions and types + // Find the node before the one matching the criteria. + __node_base* + _M_find_before_node(size_type, const key_type&, __hash_code) const; + + __node_type* + _M_find_node(size_type __bkt, const key_type& __key, + __hash_code __c) const + { + __node_base* __before_n = _M_find_before_node(__bkt, __key, __c); + if (__before_n) + return static_cast<__node_type*>(__before_n->_M_nxt); + return nullptr; + } + + // Insert a node at the beginning of a bucket. + void + _M_insert_bucket_begin(size_type, __node_type*); + + // Remove the bucket first node + void + _M_remove_bucket_begin(size_type __bkt, __node_type* __next_n, + size_type __next_bkt); + + // Get the node before __n in the bucket __bkt + __node_base* + _M_get_previous_node(size_type __bkt, __node_base* __n); + + // Insert node __n with key __k and hash code __code, in bucket __bkt + // if no rehash (assumes no element with same key already present). + // Takes ownership of __n if insertion succeeds, throws otherwise. + iterator + _M_insert_unique_node(const key_type& __k, size_type __bkt, + __hash_code __code, __node_type* __n, + size_type __n_elt = 1); + + // Insert node __n with key __k and hash code __code. + // Takes ownership of __n if insertion succeeds, throws otherwise. + iterator + _M_insert_multi_node(__node_type* __hint, const key_type& __k, + __hash_code __code, __node_type* __n); + + template + std::pair + _M_emplace(true_type, _Args&&... __args); + + template + iterator + _M_emplace(false_type __uk, _Args&&... __args) + { return _M_emplace(cend(), __uk, std::forward<_Args>(__args)...); } + + // Emplace with hint, useless when keys are unique. + template + iterator + _M_emplace(const_iterator, true_type __uk, _Args&&... __args) + { return _M_emplace(__uk, std::forward<_Args>(__args)...).first; } + + template + iterator + _M_emplace(const_iterator, false_type, _Args&&... __args); + + template + std::pair + _M_insert(_Arg&&, const _NodeGenerator&, true_type, size_type = 1); + + template + iterator + _M_insert(_Arg&& __arg, const _NodeGenerator& __node_gen, + false_type __uk) + { + return _M_insert(cend(), std::forward<_Arg>(__arg), __node_gen, + __uk); + } + + // Insert with hint, not used when keys are unique. + template + iterator + _M_insert(const_iterator, _Arg&& __arg, + const _NodeGenerator& __node_gen, true_type __uk) + { + return + _M_insert(std::forward<_Arg>(__arg), __node_gen, __uk).first; + } + + // Insert with hint when keys are not unique. + template + iterator + _M_insert(const_iterator, _Arg&&, + const _NodeGenerator&, false_type); + + size_type + _M_erase(true_type, const key_type&); + + size_type + _M_erase(false_type, const key_type&); + + iterator + _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n); + + public: + // Emplace + template + __ireturn_type + emplace(_Args&&... __args) + { return _M_emplace(__unique_keys(), std::forward<_Args>(__args)...); } + + template + iterator + emplace_hint(const_iterator __hint, _Args&&... __args) + { + return _M_emplace(__hint, __unique_keys(), + std::forward<_Args>(__args)...); + } + + // Insert member functions via inheritance. + + // Erase + iterator + erase(const_iterator); + + // LWG 2059. + iterator + erase(iterator __it) + { return erase(const_iterator(__it)); } + + size_type + erase(const key_type& __k) + { return _M_erase(__unique_keys(), __k); } + + iterator + erase(const_iterator, const_iterator); + + void + clear() noexcept; + + // Set number of buckets keeping it appropriate for container's number + // of elements. + void rehash(size_type __bkt_count); + + // DR 1189. + // reserve, if present, comes from _Rehash_base. + +#if __cplusplus > 201402L + /// Re-insert an extracted node into a container with unique keys. + insert_return_type + _M_reinsert_node(node_type&& __nh) + { + insert_return_type __ret; + if (__nh.empty()) + __ret.position = end(); + else + { + __glibcxx_assert(get_allocator() == __nh.get_allocator()); + + const key_type& __k = __nh._M_key(); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + if (__node_type* __n = _M_find_node(__bkt, __k, __code)) + { + __ret.node = std::move(__nh); + __ret.position = iterator(__n); + __ret.inserted = false; + } + else + { + __ret.position + = _M_insert_unique_node(__k, __bkt, __code, __nh._M_ptr); + __nh._M_ptr = nullptr; + __ret.inserted = true; + } + } + return __ret; + } + + /// Re-insert an extracted node into a container with equivalent keys. + iterator + _M_reinsert_node_multi(const_iterator __hint, node_type&& __nh) + { + if (__nh.empty()) + return end(); + + __glibcxx_assert(get_allocator() == __nh.get_allocator()); + + const key_type& __k = __nh._M_key(); + auto __code = this->_M_hash_code(__k); + auto __ret + = _M_insert_multi_node(__hint._M_cur, __k, __code, __nh._M_ptr); + __nh._M_ptr = nullptr; + return __ret; + } + + private: + node_type + _M_extract_node(size_t __bkt, __node_base* __prev_n) + { + __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); + if (__prev_n == _M_buckets[__bkt]) + _M_remove_bucket_begin(__bkt, __n->_M_next(), + __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0); + else if (__n->_M_nxt) + { + size_type __next_bkt = _M_bucket_index(__n->_M_next()); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __prev_n; + } + + __prev_n->_M_nxt = __n->_M_nxt; + __n->_M_nxt = nullptr; + --_M_element_count; + return { __n, this->_M_node_allocator() }; + } + + public: + // Extract a node. + node_type + extract(const_iterator __pos) + { + size_t __bkt = _M_bucket_index(__pos._M_cur); + return _M_extract_node(__bkt, + _M_get_previous_node(__bkt, __pos._M_cur)); + } + + /// Extract a node. + node_type + extract(const _Key& __k) + { + node_type __nh; + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + if (__node_base* __prev_node = _M_find_before_node(__bkt, __k, __code)) + __nh = _M_extract_node(__bkt, __prev_node); + return __nh; + } + + /// Merge from a compatible container into one with unique keys. + template + void + _M_merge_unique(_Compatible_Hashtable& __src) noexcept + { + static_assert(is_same_v, "Node types are compatible"); + __glibcxx_assert(get_allocator() == __src.get_allocator()); + + auto __n_elt = __src.size(); + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + const key_type& __k = this->_M_extract()(*__pos); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + if (_M_find_node(__bkt, __k, __code) == nullptr) + { + auto __nh = __src.extract(__pos); + _M_insert_unique_node(__k, __bkt, __code, __nh._M_ptr, + __n_elt); + __nh._M_ptr = nullptr; + __n_elt = 1; + } + else if (__n_elt != 1) + --__n_elt; + } + } + + /// Merge from a compatible container into one with equivalent keys. + template + void + _M_merge_multi(_Compatible_Hashtable& __src) noexcept + { + static_assert(is_same_v, "Node types are compatible"); + __glibcxx_assert(get_allocator() == __src.get_allocator()); + + this->reserve(size() + __src.size()); + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + _M_reinsert_node_multi(cend(), __src.extract(__i++)); + } +#endif // C++17 + + private: + // Helper rehash method used when keys are unique. + void _M_rehash_aux(size_type __bkt_count, true_type); + + // Helper rehash method used when keys can be non-unique. + void _M_rehash_aux(size_type __bkt_count, false_type); + + // Unconditionally change size of bucket array to n, restore + // hash policy state to __state on exception. + void _M_rehash(size_type __bkt_count, const __rehash_state& __state); + }; + + + // Definitions of class template _Hashtable's out-of-line member functions. + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_bucket_begin(size_type __bkt) const + -> __node_type* + { + __node_base* __n = _M_buckets[__bkt]; + return __n ? static_cast<__node_type*>(__n->_M_nxt) : nullptr; + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(size_type __bkt_count_hint, + const _H1& __h1, const _H2& __h2, const _Hash& __h, + const _Equal& __eq, const _ExtractKey& __exk, + const allocator_type& __a) + : _Hashtable(__h1, __h2, __h, __eq, __exk, __a) + { + auto __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count_hint); + if (__bkt_count > _M_bucket_count) + { + _M_buckets = _M_allocate_buckets(__bkt_count); + _M_bucket_count = __bkt_count; + } + } + + template + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(_InputIterator __f, _InputIterator __l, + size_type __bkt_count_hint, + const _H1& __h1, const _H2& __h2, const _Hash& __h, + const _Equal& __eq, const _ExtractKey& __exk, + const allocator_type& __a) + : _Hashtable(__h1, __h2, __h, __eq, __exk, __a) + { + auto __nb_elems = __detail::__distance_fw(__f, __l); + auto __bkt_count = + _M_rehash_policy._M_next_bkt( + std::max(_M_rehash_policy._M_bkt_for_elements(__nb_elems), + __bkt_count_hint)); + + if (__bkt_count > _M_bucket_count) + { + _M_buckets = _M_allocate_buckets(__bkt_count); + _M_bucket_count = __bkt_count; + } + + for (; __f != __l; ++__f) + this->insert(*__f); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + operator=(const _Hashtable& __ht) + -> _Hashtable& + { + if (&__ht == this) + return *this; + + if (__node_alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_node_allocator(); + auto& __that_alloc = __ht._M_node_allocator(); + if (!__node_alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // Replacement allocator cannot free existing storage. + this->_M_deallocate_nodes(_M_begin()); + _M_before_begin._M_nxt = nullptr; + _M_deallocate_buckets(); + _M_buckets = nullptr; + std::__alloc_on_copy(__this_alloc, __that_alloc); + __hashtable_base::operator=(__ht); + _M_bucket_count = __ht._M_bucket_count; + _M_element_count = __ht._M_element_count; + _M_rehash_policy = __ht._M_rehash_policy; + __alloc_node_gen_t __alloc_node_gen(*this); + __try + { + _M_assign(__ht, __alloc_node_gen); + } + __catch(...) + { + // _M_assign took care of deallocating all memory. Now we + // must make sure this instance remains in a usable state. + _M_reset(); + __throw_exception_again; + } + return *this; + } + std::__alloc_on_copy(__this_alloc, __that_alloc); + } + + // Reuse allocated buckets and nodes. + _M_assign_elements(__ht); + return *this; + } + + template + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_assign_elements(_Ht&& __ht) + { + __bucket_type* __former_buckets = nullptr; + std::size_t __former_bucket_count = _M_bucket_count; + const __rehash_state& __former_state = _M_rehash_policy._M_state(); + + if (_M_bucket_count != __ht._M_bucket_count) + { + __former_buckets = _M_buckets; + _M_buckets = _M_allocate_buckets(__ht._M_bucket_count); + _M_bucket_count = __ht._M_bucket_count; + } + else + __builtin_memset(_M_buckets, 0, + _M_bucket_count * sizeof(__bucket_type)); + + __try + { + __hashtable_base::operator=(std::forward<_Ht>(__ht)); + _M_element_count = __ht._M_element_count; + _M_rehash_policy = __ht._M_rehash_policy; + __reuse_or_alloc_node_gen_t __roan(_M_begin(), *this); + _M_before_begin._M_nxt = nullptr; + _M_assign(std::forward<_Ht>(__ht), __roan); + if (__former_buckets) + _M_deallocate_buckets(__former_buckets, __former_bucket_count); + } + __catch(...) + { + if (__former_buckets) + { + // Restore previous buckets. + _M_deallocate_buckets(); + _M_rehash_policy._M_reset(__former_state); + _M_buckets = __former_buckets; + _M_bucket_count = __former_bucket_count; + } + __builtin_memset(_M_buckets, 0, + _M_bucket_count * sizeof(__bucket_type)); + __throw_exception_again; + } + } + + template + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_assign(_Ht&& __ht, const _NodeGenerator& __node_gen) + { + __bucket_type* __buckets = nullptr; + if (!_M_buckets) + _M_buckets = __buckets = _M_allocate_buckets(_M_bucket_count); + + __try + { + if (!__ht._M_before_begin._M_nxt) + return; + + // First deal with the special first node pointed to by + // _M_before_begin. + __node_type* __ht_n = __ht._M_begin(); + __node_type* __this_n + = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v())); + this->_M_copy_code(__this_n, __ht_n); + _M_before_begin._M_nxt = __this_n; + _M_buckets[_M_bucket_index(__this_n)] = &_M_before_begin; + + // Then deal with other nodes. + __node_base* __prev_n = __this_n; + for (__ht_n = __ht_n->_M_next(); __ht_n; __ht_n = __ht_n->_M_next()) + { + __this_n = __node_gen(__fwd_value_for<_Ht>(__ht_n->_M_v())); + __prev_n->_M_nxt = __this_n; + this->_M_copy_code(__this_n, __ht_n); + size_type __bkt = _M_bucket_index(__this_n); + if (!_M_buckets[__bkt]) + _M_buckets[__bkt] = __prev_n; + __prev_n = __this_n; + } + } + __catch(...) + { + clear(); + if (__buckets) + _M_deallocate_buckets(); + __throw_exception_again; + } + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_reset() noexcept + { + _M_rehash_policy._M_reset(); + _M_bucket_count = 1; + _M_single_bucket = nullptr; + _M_buckets = &_M_single_bucket; + _M_before_begin._M_nxt = nullptr; + _M_element_count = 0; + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_move_assign(_Hashtable&& __ht, true_type) + { + this->_M_deallocate_nodes(_M_begin()); + _M_deallocate_buckets(); + __hashtable_base::operator=(std::move(__ht)); + _M_rehash_policy = __ht._M_rehash_policy; + if (!__ht._M_uses_single_bucket()) + _M_buckets = __ht._M_buckets; + else + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } + _M_bucket_count = __ht._M_bucket_count; + _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt; + _M_element_count = __ht._M_element_count; + std::__alloc_on_move(this->_M_node_allocator(), __ht._M_node_allocator()); + + // Fix buckets containing the _M_before_begin pointers that can't be + // moved. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + __ht._M_reset(); + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_move_assign(_Hashtable&& __ht, false_type) + { + if (__ht._M_node_allocator() == this->_M_node_allocator()) + _M_move_assign(std::move(__ht), true_type()); + else + { + // Can't move memory, move elements then. + _M_assign_elements(std::move(__ht)); + __ht.clear(); + } + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(const _Hashtable& __ht) + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + __hashtable_alloc( + __node_alloc_traits::_S_select_on_copy(__ht._M_node_allocator())), + _M_buckets(nullptr), + _M_bucket_count(__ht._M_bucket_count), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + __alloc_node_gen_t __alloc_node_gen(*this); + _M_assign(__ht, __alloc_node_gen); + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(_Hashtable&& __ht) noexcept + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + __hashtable_alloc(std::move(__ht._M_base_alloc())), + _M_buckets(__ht._M_buckets), + _M_bucket_count(__ht._M_bucket_count), + _M_before_begin(__ht._M_before_begin._M_nxt), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + // Update, if necessary, buckets if __ht is using its single bucket. + if (__ht._M_uses_single_bucket()) + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } + + // Update, if necessary, bucket pointing to before begin that hasn't + // moved. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + + __ht._M_reset(); + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(const _Hashtable& __ht, const allocator_type& __a) + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + __hashtable_alloc(__node_alloc_type(__a)), + _M_buckets(), + _M_bucket_count(__ht._M_bucket_count), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + __alloc_node_gen_t __alloc_node_gen(*this); + _M_assign(__ht, __alloc_node_gen); + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _Hashtable(_Hashtable&& __ht, const allocator_type& __a) + : __hashtable_base(__ht), + __map_base(__ht), + __rehash_base(__ht), + __hashtable_alloc(__node_alloc_type(__a)), + _M_buckets(nullptr), + _M_bucket_count(__ht._M_bucket_count), + _M_element_count(__ht._M_element_count), + _M_rehash_policy(__ht._M_rehash_policy) + { + if (__ht._M_node_allocator() == this->_M_node_allocator()) + { + if (__ht._M_uses_single_bucket()) + { + _M_buckets = &_M_single_bucket; + _M_single_bucket = __ht._M_single_bucket; + } + else + _M_buckets = __ht._M_buckets; + + _M_before_begin._M_nxt = __ht._M_before_begin._M_nxt; + // Update, if necessary, bucket pointing to before begin that hasn't + // moved. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + __ht._M_reset(); + } + else + { + __alloc_node_gen_t __alloc_gen(*this); + + using _Fwd_Ht = typename + conditional<__move_if_noexcept_cond::value, + const _Hashtable&, _Hashtable&&>::type; + _M_assign(std::forward<_Fwd_Ht>(__ht), __alloc_gen); + __ht.clear(); + } + } + + template + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + ~_Hashtable() noexcept + { + clear(); + _M_deallocate_buckets(); + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + swap(_Hashtable& __x) + noexcept(__and_<__is_nothrow_swappable<_H1>, + __is_nothrow_swappable<_Equal>>::value) + { + // The only base class with member variables is hash_code_base. + // We define _Hash_code_base::_M_swap because different + // specializations have different members. + this->_M_swap(__x); + + std::__alloc_on_swap(this->_M_node_allocator(), __x._M_node_allocator()); + std::swap(_M_rehash_policy, __x._M_rehash_policy); + + // Deal properly with potentially moved instances. + if (this->_M_uses_single_bucket()) + { + if (!__x._M_uses_single_bucket()) + { + _M_buckets = __x._M_buckets; + __x._M_buckets = &__x._M_single_bucket; + } + } + else if (__x._M_uses_single_bucket()) + { + __x._M_buckets = _M_buckets; + _M_buckets = &_M_single_bucket; + } + else + std::swap(_M_buckets, __x._M_buckets); + + std::swap(_M_bucket_count, __x._M_bucket_count); + std::swap(_M_before_begin._M_nxt, __x._M_before_begin._M_nxt); + std::swap(_M_element_count, __x._M_element_count); + std::swap(_M_single_bucket, __x._M_single_bucket); + + // Fix buckets containing the _M_before_begin pointers that can't be + // swapped. + if (_M_begin()) + _M_buckets[_M_bucket_index(_M_begin())] = &_M_before_begin; + + if (__x._M_begin()) + __x._M_buckets[__x._M_bucket_index(__x._M_begin())] + = &__x._M_before_begin; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + find(const key_type& __k) + -> iterator + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_find_node(__bkt, __k, __code); + return __p ? iterator(__p) : end(); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + find(const key_type& __k) const + -> const_iterator + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_find_node(__bkt, __k, __code); + return __p ? const_iterator(__p) : end(); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + count(const key_type& __k) const + -> size_type + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_bucket_begin(__bkt); + if (!__p) + return 0; + + std::size_t __result = 0; + for (;; __p = __p->_M_next()) + { + if (this->_M_equals(__k, __code, __p)) + ++__result; + else if (__result) + // All equivalent values are next to each other, if we + // found a non-equivalent value after an equivalent one it + // means that we won't find any new equivalent value. + break; + if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __bkt) + break; + } + return __result; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + equal_range(const key_type& __k) + -> pair + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_find_node(__bkt, __k, __code); + + if (__p) + { + __node_type* __p1 = __p->_M_next(); + while (__p1 && _M_bucket_index(__p1) == __bkt + && this->_M_equals(__k, __code, __p1)) + __p1 = __p1->_M_next(); + + return std::make_pair(iterator(__p), iterator(__p1)); + } + else + return std::make_pair(end(), end()); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + equal_range(const key_type& __k) const + -> pair + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + __node_type* __p = _M_find_node(__bkt, __k, __code); + + if (__p) + { + __node_type* __p1 = __p->_M_next(); + while (__p1 && _M_bucket_index(__p1) == __bkt + && this->_M_equals(__k, __code, __p1)) + __p1 = __p1->_M_next(); + + return std::make_pair(const_iterator(__p), const_iterator(__p1)); + } + else + return std::make_pair(end(), end()); + } + + // Find the node whose key compares equal to k in the bucket bkt. + // Return nullptr if no node is found. + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_find_before_node(size_type __bkt, const key_type& __k, + __hash_code __code) const + -> __node_base* + { + __node_base* __prev_p = _M_buckets[__bkt]; + if (!__prev_p) + return nullptr; + + for (__node_type* __p = static_cast<__node_type*>(__prev_p->_M_nxt);; + __p = __p->_M_next()) + { + if (this->_M_equals(__k, __code, __p)) + return __prev_p; + + if (!__p->_M_nxt || _M_bucket_index(__p->_M_next()) != __bkt) + break; + __prev_p = __p; + } + return nullptr; + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert_bucket_begin(size_type __bkt, __node_type* __node) + { + if (_M_buckets[__bkt]) + { + // Bucket is not empty, we just need to insert the new node + // after the bucket before begin. + __node->_M_nxt = _M_buckets[__bkt]->_M_nxt; + _M_buckets[__bkt]->_M_nxt = __node; + } + else + { + // The bucket is empty, the new node is inserted at the + // beginning of the singly-linked list and the bucket will + // contain _M_before_begin pointer. + __node->_M_nxt = _M_before_begin._M_nxt; + _M_before_begin._M_nxt = __node; + if (__node->_M_nxt) + // We must update former begin bucket that is pointing to + // _M_before_begin. + _M_buckets[_M_bucket_index(__node->_M_next())] = __node; + _M_buckets[__bkt] = &_M_before_begin; + } + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_remove_bucket_begin(size_type __bkt, __node_type* __next, + size_type __next_bkt) + { + if (!__next || __next_bkt != __bkt) + { + // Bucket is now empty + // First update next bucket if any + if (__next) + _M_buckets[__next_bkt] = _M_buckets[__bkt]; + + // Second update before begin node if necessary + if (&_M_before_begin == _M_buckets[__bkt]) + _M_before_begin._M_nxt = __next; + _M_buckets[__bkt] = nullptr; + } + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_get_previous_node(size_type __bkt, __node_base* __n) + -> __node_base* + { + __node_base* __prev_n = _M_buckets[__bkt]; + while (__prev_n->_M_nxt != __n) + __prev_n = __prev_n->_M_nxt; + return __prev_n; + } + + template + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_emplace(true_type, _Args&&... __args) + -> pair + { + // First build the node to get access to the hash code + _Scoped_node __node { this, std::forward<_Args>(__args)... }; + const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + if (__node_type* __p = _M_find_node(__bkt, __k, __code)) + // There is already an equivalent node, no insertion + return std::make_pair(iterator(__p), false); + + // Insert the node + auto __pos = _M_insert_unique_node(__k, __bkt, __code, __node._M_node); + __node._M_node = nullptr; + return { __pos, true }; + } + + template + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_emplace(const_iterator __hint, false_type, _Args&&... __args) + -> iterator + { + // First build the node to get its hash code. + _Scoped_node __node { this, std::forward<_Args>(__args)... }; + const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); + + __hash_code __code = this->_M_hash_code(__k); + auto __pos + = _M_insert_multi_node(__hint._M_cur, __k, __code, __node._M_node); + __node._M_node = nullptr; + return __pos; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert_unique_node(const key_type& __k, size_type __bkt, + __hash_code __code, __node_type* __node, + size_type __n_elt) + -> iterator + { + const __rehash_state& __saved_state = _M_rehash_policy._M_state(); + std::pair __do_rehash + = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, + __n_elt); + + if (__do_rehash.first) + { + _M_rehash(__do_rehash.second, __saved_state); + __bkt = _M_bucket_index(__k, __code); + } + + this->_M_store_code(__node, __code); + + // Always insert at the beginning of the bucket. + _M_insert_bucket_begin(__bkt, __node); + ++_M_element_count; + return iterator(__node); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert_multi_node(__node_type* __hint, const key_type& __k, + __hash_code __code, __node_type* __node) + -> iterator + { + const __rehash_state& __saved_state = _M_rehash_policy._M_state(); + std::pair __do_rehash + = _M_rehash_policy._M_need_rehash(_M_bucket_count, _M_element_count, 1); + + if (__do_rehash.first) + _M_rehash(__do_rehash.second, __saved_state); + + this->_M_store_code(__node, __code); + size_type __bkt = _M_bucket_index(__k, __code); + + // Find the node before an equivalent one or use hint if it exists and + // if it is equivalent. + __node_base* __prev + = __builtin_expect(__hint != nullptr, false) + && this->_M_equals(__k, __code, __hint) + ? __hint + : _M_find_before_node(__bkt, __k, __code); + if (__prev) + { + // Insert after the node before the equivalent one. + __node->_M_nxt = __prev->_M_nxt; + __prev->_M_nxt = __node; + if (__builtin_expect(__prev == __hint, false)) + // hint might be the last bucket node, in this case we need to + // update next bucket. + if (__node->_M_nxt + && !this->_M_equals(__k, __code, __node->_M_next())) + { + size_type __next_bkt = _M_bucket_index(__node->_M_next()); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __node; + } + } + else + // The inserted node has no equivalent in the hashtable. We must + // insert the new node at the beginning of the bucket to preserve + // equivalent elements' relative positions. + _M_insert_bucket_begin(__bkt, __node); + ++_M_element_count; + return iterator(__node); + } + + // Insert v if no element with its key is already present. + template + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert(_Arg&& __v, const _NodeGenerator& __node_gen, true_type, + size_type __n_elt) + -> pair + { + const key_type& __k = this->_M_extract()(__v); + __hash_code __code = this->_M_hash_code(__k); + size_type __bkt = _M_bucket_index(__k, __code); + + if (__node_type* __node = _M_find_node(__bkt, __k, __code)) + return { iterator(__node), false }; + + _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)), this }; + auto __pos + = _M_insert_unique_node(__k, __bkt, __code, __node._M_node, __n_elt); + __node._M_node = nullptr; + return { __pos, true }; + } + + // Insert v unconditionally. + template + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_insert(const_iterator __hint, _Arg&& __v, + const _NodeGenerator& __node_gen, false_type) + -> iterator + { + // First compute the hash code so that we don't do anything if it + // throws. + __hash_code __code = this->_M_hash_code(this->_M_extract()(__v)); + + // Second allocate new node so that we don't rehash if it throws. + _Scoped_node __node{ __node_gen(std::forward<_Arg>(__v)), this }; + const key_type& __k = this->_M_extract()(__node._M_node->_M_v()); + auto __pos + = _M_insert_multi_node(__hint._M_cur, __k, __code, __node._M_node); + __node._M_node = nullptr; + return __pos; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + erase(const_iterator __it) + -> iterator + { + __node_type* __n = __it._M_cur; + std::size_t __bkt = _M_bucket_index(__n); + + // Look for previous node to unlink it from the erased one, this + // is why we need buckets to contain the before begin to make + // this search fast. + __node_base* __prev_n = _M_get_previous_node(__bkt, __n); + return _M_erase(__bkt, __prev_n, __n); + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_erase(size_type __bkt, __node_base* __prev_n, __node_type* __n) + -> iterator + { + if (__prev_n == _M_buckets[__bkt]) + _M_remove_bucket_begin(__bkt, __n->_M_next(), + __n->_M_nxt ? _M_bucket_index(__n->_M_next()) : 0); + else if (__n->_M_nxt) + { + size_type __next_bkt = _M_bucket_index(__n->_M_next()); + if (__next_bkt != __bkt) + _M_buckets[__next_bkt] = __prev_n; + } + + __prev_n->_M_nxt = __n->_M_nxt; + iterator __result(__n->_M_next()); + this->_M_deallocate_node(__n); + --_M_element_count; + + return __result; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_erase(true_type, const key_type& __k) + -> size_type + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + + // Look for the node before the first matching node. + __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code); + if (!__prev_n) + return 0; + + // We found a matching node, erase it. + __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); + _M_erase(__bkt, __prev_n, __n); + return 1; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_erase(false_type, const key_type& __k) + -> size_type + { + __hash_code __code = this->_M_hash_code(__k); + std::size_t __bkt = _M_bucket_index(__k, __code); + + // Look for the node before the first matching node. + __node_base* __prev_n = _M_find_before_node(__bkt, __k, __code); + if (!__prev_n) + return 0; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 526. Is it undefined if a function in the standard changes + // in parameters? + // We use one loop to find all matching nodes and another to deallocate + // them so that the key stays valid during the first loop. It might be + // invalidated indirectly when destroying nodes. + __node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt); + __node_type* __n_last = __n; + std::size_t __n_last_bkt = __bkt; + do + { + __n_last = __n_last->_M_next(); + if (!__n_last) + break; + __n_last_bkt = _M_bucket_index(__n_last); + } + while (__n_last_bkt == __bkt && this->_M_equals(__k, __code, __n_last)); + + // Deallocate nodes. + size_type __result = 0; + do + { + __node_type* __p = __n->_M_next(); + this->_M_deallocate_node(__n); + __n = __p; + ++__result; + --_M_element_count; + } + while (__n != __n_last); + + if (__prev_n == _M_buckets[__bkt]) + _M_remove_bucket_begin(__bkt, __n_last, __n_last_bkt); + else if (__n_last && __n_last_bkt != __bkt) + _M_buckets[__n_last_bkt] = __prev_n; + __prev_n->_M_nxt = __n_last; + return __result; + } + + template + auto + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + erase(const_iterator __first, const_iterator __last) + -> iterator + { + __node_type* __n = __first._M_cur; + __node_type* __last_n = __last._M_cur; + if (__n == __last_n) + return iterator(__n); + + std::size_t __bkt = _M_bucket_index(__n); + + __node_base* __prev_n = _M_get_previous_node(__bkt, __n); + bool __is_bucket_begin = __n == _M_bucket_begin(__bkt); + std::size_t __n_bkt = __bkt; + for (;;) + { + do + { + __node_type* __tmp = __n; + __n = __n->_M_next(); + this->_M_deallocate_node(__tmp); + --_M_element_count; + if (!__n) + break; + __n_bkt = _M_bucket_index(__n); + } + while (__n != __last_n && __n_bkt == __bkt); + if (__is_bucket_begin) + _M_remove_bucket_begin(__bkt, __n, __n_bkt); + if (__n == __last_n) + break; + __is_bucket_begin = true; + __bkt = __n_bkt; + } + + if (__n && (__n_bkt != __bkt || __is_bucket_begin)) + _M_buckets[__n_bkt] = __prev_n; + __prev_n->_M_nxt = __n; + return iterator(__n); + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + clear() noexcept + { + this->_M_deallocate_nodes(_M_begin()); + __builtin_memset(_M_buckets, 0, _M_bucket_count * sizeof(__bucket_type)); + _M_element_count = 0; + _M_before_begin._M_nxt = nullptr; + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + rehash(size_type __bkt_count) + { + const __rehash_state& __saved_state = _M_rehash_policy._M_state(); + __bkt_count + = std::max(_M_rehash_policy._M_bkt_for_elements(_M_element_count + 1), + __bkt_count); + __bkt_count = _M_rehash_policy._M_next_bkt(__bkt_count); + + if (__bkt_count != _M_bucket_count) + _M_rehash(__bkt_count, __saved_state); + else + // No rehash, restore previous state to keep it consistent with + // container state. + _M_rehash_policy._M_reset(__saved_state); + } + + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_rehash(size_type __bkt_count, const __rehash_state& __state) + { + __try + { + _M_rehash_aux(__bkt_count, __unique_keys()); + } + __catch(...) + { + // A failure here means that buckets allocation failed. We only + // have to restore hash policy previous state. + _M_rehash_policy._M_reset(__state); + __throw_exception_again; + } + } + + // Rehash when there is no equivalent elements. + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_rehash_aux(size_type __bkt_count, true_type) + { + __bucket_type* __new_buckets = _M_allocate_buckets(__bkt_count); + __node_type* __p = _M_begin(); + _M_before_begin._M_nxt = nullptr; + std::size_t __bbegin_bkt = 0; + while (__p) + { + __node_type* __next = __p->_M_next(); + std::size_t __bkt + = __hash_code_base::_M_bucket_index(__p, __bkt_count); + if (!__new_buckets[__bkt]) + { + __p->_M_nxt = _M_before_begin._M_nxt; + _M_before_begin._M_nxt = __p; + __new_buckets[__bkt] = &_M_before_begin; + if (__p->_M_nxt) + __new_buckets[__bbegin_bkt] = __p; + __bbegin_bkt = __bkt; + } + else + { + __p->_M_nxt = __new_buckets[__bkt]->_M_nxt; + __new_buckets[__bkt]->_M_nxt = __p; + } + __p = __next; + } + + _M_deallocate_buckets(); + _M_bucket_count = __bkt_count; + _M_buckets = __new_buckets; + } + + // Rehash when there can be equivalent elements, preserve their relative + // order. + template + void + _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>:: + _M_rehash_aux(size_type __bkt_count, false_type) + { + __bucket_type* __new_buckets = _M_allocate_buckets(__bkt_count); + + __node_type* __p = _M_begin(); + _M_before_begin._M_nxt = nullptr; + std::size_t __bbegin_bkt = 0; + std::size_t __prev_bkt = 0; + __node_type* __prev_p = nullptr; + bool __check_bucket = false; + + while (__p) + { + __node_type* __next = __p->_M_next(); + std::size_t __bkt + = __hash_code_base::_M_bucket_index(__p, __bkt_count); + + if (__prev_p && __prev_bkt == __bkt) + { + // Previous insert was already in this bucket, we insert after + // the previously inserted one to preserve equivalent elements + // relative order. + __p->_M_nxt = __prev_p->_M_nxt; + __prev_p->_M_nxt = __p; + + // Inserting after a node in a bucket require to check that we + // haven't change the bucket last node, in this case next + // bucket containing its before begin node must be updated. We + // schedule a check as soon as we move out of the sequence of + // equivalent nodes to limit the number of checks. + __check_bucket = true; + } + else + { + if (__check_bucket) + { + // Check if we shall update the next bucket because of + // insertions into __prev_bkt bucket. + if (__prev_p->_M_nxt) + { + std::size_t __next_bkt + = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), + __bkt_count); + if (__next_bkt != __prev_bkt) + __new_buckets[__next_bkt] = __prev_p; + } + __check_bucket = false; + } + + if (!__new_buckets[__bkt]) + { + __p->_M_nxt = _M_before_begin._M_nxt; + _M_before_begin._M_nxt = __p; + __new_buckets[__bkt] = &_M_before_begin; + if (__p->_M_nxt) + __new_buckets[__bbegin_bkt] = __p; + __bbegin_bkt = __bkt; + } + else + { + __p->_M_nxt = __new_buckets[__bkt]->_M_nxt; + __new_buckets[__bkt]->_M_nxt = __p; + } + } + __prev_p = __p; + __prev_bkt = __bkt; + __p = __next; + } + + if (__check_bucket && __prev_p->_M_nxt) + { + std::size_t __next_bkt + = __hash_code_base::_M_bucket_index(__prev_p->_M_next(), + __bkt_count); + if (__next_bkt != __prev_bkt) + __new_buckets[__next_bkt] = __prev_p; + } + + _M_deallocate_buckets(); + _M_bucket_count = __bkt_count; + _M_buckets = __new_buckets; + } + +#if __cplusplus > 201402L + template class _Hash_merge_helper { }; +#endif // C++17 + +#if __cpp_deduction_guides >= 201606 + // Used to constrain deduction guides + template + using _RequireNotAllocatorOrIntegral + = __enable_if_t, __is_allocator<_Hash>>::value>; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _HASHTABLE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h b/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h new file mode 100644 index 000000000..ef1201349 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/hashtable_policy.h @@ -0,0 +1,2107 @@ +// Internal policy header for unordered_set and unordered_map -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/hashtable_policy.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + * @headername{unordered_map,unordered_set} + */ + +#ifndef _HASHTABLE_POLICY_H +#define _HASHTABLE_POLICY_H 1 + +#include // for std::tuple, std::forward_as_tuple +#include // for std::numeric_limits +#include // for std::min, std::is_permutation. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + class _Hashtable; + +namespace __detail +{ + /** + * @defgroup hashtable-detail Base and Implementation Classes + * @ingroup unordered_associative_containers + * @{ + */ + template + struct _Hashtable_base; + + // Helper function: return distance(first, last) for forward + // iterators, or 0/1 for input iterators. + template + inline typename std::iterator_traits<_Iterator>::difference_type + __distance_fw(_Iterator __first, _Iterator __last, + std::input_iterator_tag) + { return __first != __last ? 1 : 0; } + + template + inline typename std::iterator_traits<_Iterator>::difference_type + __distance_fw(_Iterator __first, _Iterator __last, + std::forward_iterator_tag) + { return std::distance(__first, __last); } + + template + inline typename std::iterator_traits<_Iterator>::difference_type + __distance_fw(_Iterator __first, _Iterator __last) + { return __distance_fw(__first, __last, + std::__iterator_category(__first)); } + + struct _Identity + { + template + _Tp&& + operator()(_Tp&& __x) const + { return std::forward<_Tp>(__x); } + }; + + struct _Select1st + { + template + auto + operator()(_Tp&& __x) const + -> decltype(std::get<0>(std::forward<_Tp>(__x))) + { return std::get<0>(std::forward<_Tp>(__x)); } + }; + + template + struct _Hashtable_alloc; + + // Functor recycling a pool of nodes and using allocation once the pool is + // empty. + template + struct _ReuseOrAllocNode + { + private: + using __node_alloc_type = _NodeAlloc; + using __hashtable_alloc = _Hashtable_alloc<__node_alloc_type>; + using __node_alloc_traits = + typename __hashtable_alloc::__node_alloc_traits; + using __node_type = typename __hashtable_alloc::__node_type; + + public: + _ReuseOrAllocNode(__node_type* __nodes, __hashtable_alloc& __h) + : _M_nodes(__nodes), _M_h(__h) { } + _ReuseOrAllocNode(const _ReuseOrAllocNode&) = delete; + + ~_ReuseOrAllocNode() + { _M_h._M_deallocate_nodes(_M_nodes); } + + template + __node_type* + operator()(_Arg&& __arg) const + { + if (_M_nodes) + { + __node_type* __node = _M_nodes; + _M_nodes = _M_nodes->_M_next(); + __node->_M_nxt = nullptr; + auto& __a = _M_h._M_node_allocator(); + __node_alloc_traits::destroy(__a, __node->_M_valptr()); + __try + { + __node_alloc_traits::construct(__a, __node->_M_valptr(), + std::forward<_Arg>(__arg)); + } + __catch(...) + { + _M_h._M_deallocate_node_ptr(__node); + __throw_exception_again; + } + return __node; + } + return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); + } + + private: + mutable __node_type* _M_nodes; + __hashtable_alloc& _M_h; + }; + + // Functor similar to the previous one but without any pool of nodes to + // recycle. + template + struct _AllocNode + { + private: + using __hashtable_alloc = _Hashtable_alloc<_NodeAlloc>; + using __node_type = typename __hashtable_alloc::__node_type; + + public: + _AllocNode(__hashtable_alloc& __h) + : _M_h(__h) { } + + template + __node_type* + operator()(_Arg&& __arg) const + { return _M_h._M_allocate_node(std::forward<_Arg>(__arg)); } + + private: + __hashtable_alloc& _M_h; + }; + + // Auxiliary types used for all instantiations of _Hashtable nodes + // and iterators. + + /** + * struct _Hashtable_traits + * + * Important traits for hash tables. + * + * @tparam _Cache_hash_code Boolean value. True if the value of + * the hash function is stored along with the value. This is a + * time-space tradeoff. Storing it may improve lookup speed by + * reducing the number of times we need to call the _Hash or _Equal + * functors. + * + * @tparam _Constant_iterators Boolean value. True if iterator and + * const_iterator are both constant iterator types. This is true + * for unordered_set and unordered_multiset, false for + * unordered_map and unordered_multimap. + * + * @tparam _Unique_keys Boolean value. True if the return value + * of _Hashtable::count(k) is always at most one, false if it may + * be an arbitrary number. This is true for unordered_set and + * unordered_map, false for unordered_multiset and + * unordered_multimap. + */ + template + struct _Hashtable_traits + { + using __hash_cached = __bool_constant<_Cache_hash_code>; + using __constant_iterators = __bool_constant<_Constant_iterators>; + using __unique_keys = __bool_constant<_Unique_keys>; + }; + + /** + * struct _Hash_node_base + * + * Nodes, used to wrap elements stored in the hash table. A policy + * template parameter of class template _Hashtable controls whether + * nodes also store a hash code. In some cases (e.g. strings) this + * may be a performance win. + */ + struct _Hash_node_base + { + _Hash_node_base* _M_nxt; + + _Hash_node_base() noexcept : _M_nxt() { } + + _Hash_node_base(_Hash_node_base* __next) noexcept : _M_nxt(__next) { } + }; + + /** + * struct _Hash_node_value_base + * + * Node type with the value to store. + */ + template + struct _Hash_node_value_base : _Hash_node_base + { + typedef _Value value_type; + + __gnu_cxx::__aligned_buffer<_Value> _M_storage; + + _Value* + _M_valptr() noexcept + { return _M_storage._M_ptr(); } + + const _Value* + _M_valptr() const noexcept + { return _M_storage._M_ptr(); } + + _Value& + _M_v() noexcept + { return *_M_valptr(); } + + const _Value& + _M_v() const noexcept + { return *_M_valptr(); } + }; + + /** + * Primary template struct _Hash_node. + */ + template + struct _Hash_node; + + /** + * Specialization for nodes with caches, struct _Hash_node. + * + * Base class is __detail::_Hash_node_value_base. + */ + template + struct _Hash_node<_Value, true> : _Hash_node_value_base<_Value> + { + std::size_t _M_hash_code; + + _Hash_node* + _M_next() const noexcept + { return static_cast<_Hash_node*>(this->_M_nxt); } + }; + + /** + * Specialization for nodes without caches, struct _Hash_node. + * + * Base class is __detail::_Hash_node_value_base. + */ + template + struct _Hash_node<_Value, false> : _Hash_node_value_base<_Value> + { + _Hash_node* + _M_next() const noexcept + { return static_cast<_Hash_node*>(this->_M_nxt); } + }; + + /// Base class for node iterators. + template + struct _Node_iterator_base + { + using __node_type = _Hash_node<_Value, _Cache_hash_code>; + + __node_type* _M_cur; + + _Node_iterator_base(__node_type* __p) noexcept + : _M_cur(__p) { } + + void + _M_incr() noexcept + { _M_cur = _M_cur->_M_next(); } + }; + + template + inline bool + operator==(const _Node_iterator_base<_Value, _Cache_hash_code>& __x, + const _Node_iterator_base<_Value, _Cache_hash_code >& __y) + noexcept + { return __x._M_cur == __y._M_cur; } + + template + inline bool + operator!=(const _Node_iterator_base<_Value, _Cache_hash_code>& __x, + const _Node_iterator_base<_Value, _Cache_hash_code>& __y) + noexcept + { return __x._M_cur != __y._M_cur; } + + /// Node iterators, used to iterate through all the hashtable. + template + struct _Node_iterator + : public _Node_iterator_base<_Value, __cache> + { + private: + using __base_type = _Node_iterator_base<_Value, __cache>; + using __node_type = typename __base_type::__node_type; + + public: + typedef _Value value_type; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + using pointer = typename std::conditional<__constant_iterators, + const _Value*, _Value*>::type; + + using reference = typename std::conditional<__constant_iterators, + const _Value&, _Value&>::type; + + _Node_iterator() noexcept + : __base_type(0) { } + + explicit + _Node_iterator(__node_type* __p) noexcept + : __base_type(__p) { } + + reference + operator*() const noexcept + { return this->_M_cur->_M_v(); } + + pointer + operator->() const noexcept + { return this->_M_cur->_M_valptr(); } + + _Node_iterator& + operator++() noexcept + { + this->_M_incr(); + return *this; + } + + _Node_iterator + operator++(int) noexcept + { + _Node_iterator __tmp(*this); + this->_M_incr(); + return __tmp; + } + }; + + /// Node const_iterators, used to iterate through all the hashtable. + template + struct _Node_const_iterator + : public _Node_iterator_base<_Value, __cache> + { + private: + using __base_type = _Node_iterator_base<_Value, __cache>; + using __node_type = typename __base_type::__node_type; + + public: + typedef _Value value_type; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + typedef const _Value* pointer; + typedef const _Value& reference; + + _Node_const_iterator() noexcept + : __base_type(0) { } + + explicit + _Node_const_iterator(__node_type* __p) noexcept + : __base_type(__p) { } + + _Node_const_iterator(const _Node_iterator<_Value, __constant_iterators, + __cache>& __x) noexcept + : __base_type(__x._M_cur) { } + + reference + operator*() const noexcept + { return this->_M_cur->_M_v(); } + + pointer + operator->() const noexcept + { return this->_M_cur->_M_valptr(); } + + _Node_const_iterator& + operator++() noexcept + { + this->_M_incr(); + return *this; + } + + _Node_const_iterator + operator++(int) noexcept + { + _Node_const_iterator __tmp(*this); + this->_M_incr(); + return __tmp; + } + }; + + // Many of class template _Hashtable's template parameters are policy + // classes. These are defaults for the policies. + + /// Default range hashing function: use division to fold a large number + /// into the range [0, N). + struct _Mod_range_hashing + { + typedef std::size_t first_argument_type; + typedef std::size_t second_argument_type; + typedef std::size_t result_type; + + result_type + operator()(first_argument_type __num, + second_argument_type __den) const noexcept + { return __num % __den; } + }; + + /// Default ranged hash function H. In principle it should be a + /// function object composed from objects of type H1 and H2 such that + /// h(k, N) = h2(h1(k), N), but that would mean making extra copies of + /// h1 and h2. So instead we'll just use a tag to tell class template + /// hashtable to do that composition. + struct _Default_ranged_hash { }; + + /// Default value for rehash policy. Bucket size is (usually) the + /// smallest prime that keeps the load factor small enough. + struct _Prime_rehash_policy + { + using __has_load_factor = true_type; + + _Prime_rehash_policy(float __z = 1.0) noexcept + : _M_max_load_factor(__z), _M_next_resize(0) { } + + float + max_load_factor() const noexcept + { return _M_max_load_factor; } + + // Return a bucket size no smaller than n. + std::size_t + _M_next_bkt(std::size_t __n) const; + + // Return a bucket count appropriate for n elements + std::size_t + _M_bkt_for_elements(std::size_t __n) const + { return __builtin_ceill(__n / (long double)_M_max_load_factor); } + + // __n_bkt is current bucket count, __n_elt is current element count, + // and __n_ins is number of elements to be inserted. Do we need to + // increase bucket count? If so, return make_pair(true, n), where n + // is the new bucket count. If not, return make_pair(false, 0). + std::pair + _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, + std::size_t __n_ins) const; + + typedef std::size_t _State; + + _State + _M_state() const + { return _M_next_resize; } + + void + _M_reset() noexcept + { _M_next_resize = 0; } + + void + _M_reset(_State __state) + { _M_next_resize = __state; } + + static const std::size_t _S_growth_factor = 2; + + float _M_max_load_factor; + mutable std::size_t _M_next_resize; + }; + + /// Range hashing function assuming that second arg is a power of 2. + struct _Mask_range_hashing + { + typedef std::size_t first_argument_type; + typedef std::size_t second_argument_type; + typedef std::size_t result_type; + + result_type + operator()(first_argument_type __num, + second_argument_type __den) const noexcept + { return __num & (__den - 1); } + }; + + /// Compute closest power of 2 not less than __n + inline std::size_t + __clp2(std::size_t __n) noexcept + { + // Equivalent to return __n ? std::bit_ceil(__n) : 0; + if (__n < 2) + return __n; + const unsigned __lz = sizeof(size_t) > sizeof(long) + ? __builtin_clzll(__n - 1ull) + : __builtin_clzl(__n - 1ul); + // Doing two shifts avoids undefined behaviour when __lz == 0. + return (size_t(1) << (numeric_limits::digits - __lz - 1)) << 1; + } + + /// Rehash policy providing power of 2 bucket numbers. Avoids modulo + /// operations. + struct _Power2_rehash_policy + { + using __has_load_factor = true_type; + + _Power2_rehash_policy(float __z = 1.0) noexcept + : _M_max_load_factor(__z), _M_next_resize(0) { } + + float + max_load_factor() const noexcept + { return _M_max_load_factor; } + + // Return a bucket size no smaller than n (as long as n is not above the + // highest power of 2). + std::size_t + _M_next_bkt(std::size_t __n) noexcept + { + if (__n == 0) + // Special case on container 1st initialization with 0 bucket count + // hint. We keep _M_next_resize to 0 to make sure that next time we + // want to add an element allocation will take place. + return 1; + + const auto __max_width = std::min(sizeof(size_t), 8); + const auto __max_bkt = size_t(1) << (__max_width * __CHAR_BIT__ - 1); + std::size_t __res = __clp2(__n); + + if (__res == 0) + __res = __max_bkt; + else if (__res == 1) + // If __res is 1 we force it to 2 to make sure there will be an + // allocation so that nothing need to be stored in the initial + // single bucket + __res = 2; + + if (__res == __max_bkt) + // Set next resize to the max value so that we never try to rehash again + // as we already reach the biggest possible bucket number. + // Note that it might result in max_load_factor not being respected. + _M_next_resize = numeric_limits::max(); + else + _M_next_resize + = __builtin_floorl(__res * (long double)_M_max_load_factor); + + return __res; + } + + // Return a bucket count appropriate for n elements + std::size_t + _M_bkt_for_elements(std::size_t __n) const noexcept + { return __builtin_ceill(__n / (long double)_M_max_load_factor); } + + // __n_bkt is current bucket count, __n_elt is current element count, + // and __n_ins is number of elements to be inserted. Do we need to + // increase bucket count? If so, return make_pair(true, n), where n + // is the new bucket count. If not, return make_pair(false, 0). + std::pair + _M_need_rehash(std::size_t __n_bkt, std::size_t __n_elt, + std::size_t __n_ins) noexcept + { + if (__n_elt + __n_ins > _M_next_resize) + { + // If _M_next_resize is 0 it means that we have nothing allocated so + // far and that we start inserting elements. In this case we start + // with an initial bucket size of 11. + long double __min_bkts + = std::max(__n_elt + __n_ins, _M_next_resize ? 0 : 11) + / (long double)_M_max_load_factor; + if (__min_bkts >= __n_bkt) + return { true, + _M_next_bkt(std::max(__builtin_floorl(__min_bkts) + 1, + __n_bkt * _S_growth_factor)) }; + + _M_next_resize + = __builtin_floorl(__n_bkt * (long double)_M_max_load_factor); + return { false, 0 }; + } + else + return { false, 0 }; + } + + typedef std::size_t _State; + + _State + _M_state() const noexcept + { return _M_next_resize; } + + void + _M_reset() noexcept + { _M_next_resize = 0; } + + void + _M_reset(_State __state) noexcept + { _M_next_resize = __state; } + + static const std::size_t _S_growth_factor = 2; + + float _M_max_load_factor; + std::size_t _M_next_resize; + }; + + // Base classes for std::_Hashtable. We define these base classes + // because in some cases we want to do different things depending on + // the value of a policy class. In some cases the policy class + // affects which member functions and nested typedefs are defined; + // we handle that by specializing base class templates. Several of + // the base class templates need to access other members of class + // template _Hashtable, so we use a variant of the "Curiously + // Recurring Template Pattern" (CRTP) technique. + + /** + * Primary class template _Map_base. + * + * If the hashtable has a value type of the form pair and a + * key extraction policy (_ExtractKey) that returns the first part + * of the pair, the hashtable gets a mapped_type typedef. If it + * satisfies those criteria and also has unique keys, then it also + * gets an operator[]. + */ + template + struct _Map_base { }; + + /// Partial specialization, __unique_keys set to false. + template + struct _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, false> + { + using mapped_type = typename std::tuple_element<1, _Pair>::type; + }; + + /// Partial specialization, __unique_keys set to true. + template + struct _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true> + { + private: + using __hashtable_base = __detail::_Hashtable_base<_Key, _Pair, + _Select1st, + _Equal, _H1, _H2, _Hash, + _Traits>; + + using __hashtable = _Hashtable<_Key, _Pair, _Alloc, + _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>; + + using __hash_code = typename __hashtable_base::__hash_code; + using __node_type = typename __hashtable_base::__node_type; + + public: + using key_type = typename __hashtable_base::key_type; + using iterator = typename __hashtable_base::iterator; + using mapped_type = typename std::tuple_element<1, _Pair>::type; + + mapped_type& + operator[](const key_type& __k); + + mapped_type& + operator[](key_type&& __k); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 761. unordered_map needs an at() member function. + mapped_type& + at(const key_type& __k); + + const mapped_type& + at(const key_type& __k) const; + }; + + template + auto + _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + operator[](const key_type& __k) + -> mapped_type& + { + __hashtable* __h = static_cast<__hashtable*>(this); + __hash_code __code = __h->_M_hash_code(__k); + std::size_t __bkt = __h->_M_bucket_index(__k, __code); + if (__node_type* __node = __h->_M_find_node(__bkt, __k, __code)) + return __node->_M_v().second; + + typename __hashtable::_Scoped_node __node { + __h, + std::piecewise_construct, + std::tuple(__k), + std::tuple<>() + }; + auto __pos + = __h->_M_insert_unique_node(__k, __bkt, __code, __node._M_node); + __node._M_node = nullptr; + return __pos->second; + } + + template + auto + _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + operator[](key_type&& __k) + -> mapped_type& + { + __hashtable* __h = static_cast<__hashtable*>(this); + __hash_code __code = __h->_M_hash_code(__k); + std::size_t __bkt = __h->_M_bucket_index(__k, __code); + if (__node_type* __node = __h->_M_find_node(__bkt, __k, __code)) + return __node->_M_v().second; + + typename __hashtable::_Scoped_node __node { + __h, + std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::tuple<>() + }; + auto __pos + = __h->_M_insert_unique_node(__k, __bkt, __code, __node._M_node); + __node._M_node = nullptr; + return __pos->second; + } + + template + auto + _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + at(const key_type& __k) + -> mapped_type& + { + __hashtable* __h = static_cast<__hashtable*>(this); + __hash_code __code = __h->_M_hash_code(__k); + std::size_t __bkt = __h->_M_bucket_index(__k, __code); + __node_type* __p = __h->_M_find_node(__bkt, __k, __code); + + if (!__p) + __throw_out_of_range(__N("_Map_base::at")); + return __p->_M_v().second; + } + + template + auto + _Map_base<_Key, _Pair, _Alloc, _Select1st, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + at(const key_type& __k) const + -> const mapped_type& + { + const __hashtable* __h = static_cast(this); + __hash_code __code = __h->_M_hash_code(__k); + std::size_t __bkt = __h->_M_bucket_index(__k, __code); + __node_type* __p = __h->_M_find_node(__bkt, __k, __code); + + if (!__p) + __throw_out_of_range(__N("_Map_base::at")); + return __p->_M_v().second; + } + + /** + * Primary class template _Insert_base. + * + * Defines @c insert member functions appropriate to all _Hashtables. + */ + template + struct _Insert_base + { + protected: + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _Traits>; + + using value_type = typename __hashtable_base::value_type; + using iterator = typename __hashtable_base::iterator; + using const_iterator = typename __hashtable_base::const_iterator; + using size_type = typename __hashtable_base::size_type; + + using __unique_keys = typename __hashtable_base::__unique_keys; + using __ireturn_type = typename __hashtable_base::__ireturn_type; + using __node_type = _Hash_node<_Value, _Traits::__hash_cached::value>; + using __node_alloc_type = __alloc_rebind<_Alloc, __node_type>; + using __node_gen_type = _AllocNode<__node_alloc_type>; + + __hashtable& + _M_conjure_hashtable() + { return *(static_cast<__hashtable*>(this)); } + + template + void + _M_insert_range(_InputIterator __first, _InputIterator __last, + const _NodeGetter&, true_type); + + template + void + _M_insert_range(_InputIterator __first, _InputIterator __last, + const _NodeGetter&, false_type); + + public: + __ireturn_type + insert(const value_type& __v) + { + __hashtable& __h = _M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return __h._M_insert(__v, __node_gen, __unique_keys()); + } + + iterator + insert(const_iterator __hint, const value_type& __v) + { + __hashtable& __h = _M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return __h._M_insert(__hint, __v, __node_gen, __unique_keys()); + } + + void + insert(initializer_list __l) + { this->insert(__l.begin(), __l.end()); } + + template + void + insert(_InputIterator __first, _InputIterator __last) + { + __hashtable& __h = _M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return _M_insert_range(__first, __last, __node_gen, __unique_keys()); + } + }; + + template + template + void + _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>:: + _M_insert_range(_InputIterator __first, _InputIterator __last, + const _NodeGetter& __node_gen, true_type) + { + size_type __n_elt = __detail::__distance_fw(__first, __last); + if (__n_elt == 0) + return; + + __hashtable& __h = _M_conjure_hashtable(); + for (; __first != __last; ++__first) + { + if (__h._M_insert(*__first, __node_gen, __unique_keys(), + __n_elt).second) + __n_elt = 1; + else if (__n_elt != 1) + --__n_elt; + } + } + + template + template + void + _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>:: + _M_insert_range(_InputIterator __first, _InputIterator __last, + const _NodeGetter& __node_gen, false_type) + { + using __rehash_type = typename __hashtable::__rehash_type; + using __rehash_state = typename __hashtable::__rehash_state; + using pair_type = std::pair; + + size_type __n_elt = __detail::__distance_fw(__first, __last); + if (__n_elt == 0) + return; + + __hashtable& __h = _M_conjure_hashtable(); + __rehash_type& __rehash = __h._M_rehash_policy; + const __rehash_state& __saved_state = __rehash._M_state(); + pair_type __do_rehash = __rehash._M_need_rehash(__h._M_bucket_count, + __h._M_element_count, + __n_elt); + + if (__do_rehash.first) + __h._M_rehash(__do_rehash.second, __saved_state); + + for (; __first != __last; ++__first) + __h._M_insert(*__first, __node_gen, __unique_keys()); + } + + /** + * Primary class template _Insert. + * + * Defines @c insert member functions that depend on _Hashtable policies, + * via partial specializations. + */ + template + struct _Insert; + + /// Specialization. + template + struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits, true> + : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits> + { + using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + using __hashtable_base = _Hashtable_base<_Key, _Value, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _Traits>; + + using value_type = typename __base_type::value_type; + using iterator = typename __base_type::iterator; + using const_iterator = typename __base_type::const_iterator; + + using __unique_keys = typename __base_type::__unique_keys; + using __ireturn_type = typename __hashtable_base::__ireturn_type; + using __hashtable = typename __base_type::__hashtable; + using __node_gen_type = typename __base_type::__node_gen_type; + + using __base_type::insert; + + __ireturn_type + insert(value_type&& __v) + { + __hashtable& __h = this->_M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return __h._M_insert(std::move(__v), __node_gen, __unique_keys()); + } + + iterator + insert(const_iterator __hint, value_type&& __v) + { + __hashtable& __h = this->_M_conjure_hashtable(); + __node_gen_type __node_gen(__h); + return __h._M_insert(__hint, std::move(__v), __node_gen, + __unique_keys()); + } + }; + + /// Specialization. + template + struct _Insert<_Key, _Value, _Alloc, _ExtractKey, _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits, false> + : public _Insert_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits> + { + using __base_type = _Insert_base<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + using value_type = typename __base_type::value_type; + using iterator = typename __base_type::iterator; + using const_iterator = typename __base_type::const_iterator; + + using __unique_keys = typename __base_type::__unique_keys; + using __hashtable = typename __base_type::__hashtable; + using __ireturn_type = typename __base_type::__ireturn_type; + + using __base_type::insert; + + template + using __is_cons = std::is_constructible; + + template + using _IFcons = std::enable_if<__is_cons<_Pair>::value>; + + template + using _IFconsp = typename _IFcons<_Pair>::type; + + template> + __ireturn_type + insert(_Pair&& __v) + { + __hashtable& __h = this->_M_conjure_hashtable(); + return __h._M_emplace(__unique_keys(), std::forward<_Pair>(__v)); + } + + template> + iterator + insert(const_iterator __hint, _Pair&& __v) + { + __hashtable& __h = this->_M_conjure_hashtable(); + return __h._M_emplace(__hint, __unique_keys(), + std::forward<_Pair>(__v)); + } + }; + + template + using __has_load_factor = typename _Policy::__has_load_factor; + + /** + * Primary class template _Rehash_base. + * + * Give hashtable the max_load_factor functions and reserve iff the + * rehash policy supports it. + */ + template> + struct _Rehash_base; + + /// Specialization when rehash policy doesn't provide load factor management. + template + struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, + false_type> + { + }; + + /// Specialization when rehash policy provide load factor management. + template + struct _Rehash_base<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, + true_type> + { + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, + _Equal, _H1, _H2, _Hash, + _RehashPolicy, _Traits>; + + float + max_load_factor() const noexcept + { + const __hashtable* __this = static_cast(this); + return __this->__rehash_policy().max_load_factor(); + } + + void + max_load_factor(float __z) + { + __hashtable* __this = static_cast<__hashtable*>(this); + __this->__rehash_policy(_RehashPolicy(__z)); + } + + void + reserve(std::size_t __n) + { + __hashtable* __this = static_cast<__hashtable*>(this); + __this->rehash(__this->__rehash_policy()._M_bkt_for_elements(__n)); + } + }; + + /** + * Primary class template _Hashtable_ebo_helper. + * + * Helper class using EBO when it is not forbidden (the type is not + * final) and when it is worth it (the type is empty.) + */ + template + struct _Hashtable_ebo_helper; + + /// Specialization using EBO. + template + struct _Hashtable_ebo_helper<_Nm, _Tp, true> + : private _Tp + { + _Hashtable_ebo_helper() = default; + + template + _Hashtable_ebo_helper(_OtherTp&& __tp) + : _Tp(std::forward<_OtherTp>(__tp)) + { } + + const _Tp& _M_cget() const { return static_cast(*this); } + _Tp& _M_get() { return static_cast<_Tp&>(*this); } + }; + + /// Specialization not using EBO. + template + struct _Hashtable_ebo_helper<_Nm, _Tp, false> + { + _Hashtable_ebo_helper() = default; + + template + _Hashtable_ebo_helper(_OtherTp&& __tp) + : _M_tp(std::forward<_OtherTp>(__tp)) + { } + + const _Tp& _M_cget() const { return _M_tp; } + _Tp& _M_get() { return _M_tp; } + + private: + _Tp _M_tp; + }; + + /** + * Primary class template _Local_iterator_base. + * + * Base class for local iterators, used to iterate within a bucket + * but not between buckets. + */ + template + struct _Local_iterator_base; + + /** + * Primary class template _Hash_code_base. + * + * Encapsulates two policy issues that aren't quite orthogonal. + * (1) the difference between using a ranged hash function and using + * the combination of a hash function and a range-hashing function. + * In the former case we don't have such things as hash codes, so + * we have a dummy type as placeholder. + * (2) Whether or not we cache hash codes. Caching hash codes is + * meaningless if we have a ranged hash function. + * + * We also put the key extraction objects here, for convenience. + * Each specialization derives from one or more of the template + * parameters to benefit from Ebo. This is important as this type + * is inherited in some cases by the _Local_iterator_base type used + * to implement local_iterator and const_local_iterator. As with + * any iterator type we prefer to make it as small as possible. + * + * Primary template is unused except as a hook for specializations. + */ + template + struct _Hash_code_base; + + /// Specialization: ranged hash function, no caching hash codes. H1 + /// and H2 are provided but ignored. We define a dummy hash code type. + template + struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, false> + : private _Hashtable_ebo_helper<0, _ExtractKey>, + private _Hashtable_ebo_helper<1, _Hash> + { + private: + using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; + using __ebo_hash = _Hashtable_ebo_helper<1, _Hash>; + + protected: + typedef void* __hash_code; + typedef _Hash_node<_Value, false> __node_type; + + // We need the default constructor for the local iterators and _Hashtable + // default constructor. + _Hash_code_base() = default; + + _Hash_code_base(const _ExtractKey& __ex, const _H1&, const _H2&, + const _Hash& __h) + : __ebo_extract_key(__ex), __ebo_hash(__h) { } + + __hash_code + _M_hash_code(const _Key& __key) const + { return 0; } + + std::size_t + _M_bucket_index(const _Key& __k, __hash_code, + std::size_t __bkt_count) const + { return _M_ranged_hash()(__k, __bkt_count); } + + std::size_t + _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const + noexcept( noexcept(declval()(declval(), + (std::size_t)0)) ) + { return _M_ranged_hash()(_M_extract()(__p->_M_v()), __bkt_count); } + + void + _M_store_code(__node_type*, __hash_code) const + { } + + void + _M_copy_code(__node_type*, const __node_type*) const + { } + + void + _M_swap(_Hash_code_base& __x) + { + std::swap(__ebo_extract_key::_M_get(), + __x.__ebo_extract_key::_M_get()); + std::swap(__ebo_hash::_M_get(), __x.__ebo_hash::_M_get()); + } + + const _ExtractKey& + _M_extract() const { return __ebo_extract_key::_M_cget(); } + + const _Hash& + _M_ranged_hash() const { return __ebo_hash::_M_cget(); } + }; + + // No specialization for ranged hash function while caching hash codes. + // That combination is meaningless, and trying to do it is an error. + + /// Specialization: ranged hash function, cache hash codes. This + /// combination is meaningless, so we provide only a declaration + /// and no definition. + template + struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, true>; + + /// Specialization: hash function and range-hashing function, no + /// caching of hash codes. + /// Provides typedef and accessor required by C++ 11. + template + struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, + _Default_ranged_hash, false> + : private _Hashtable_ebo_helper<0, _ExtractKey>, + private _Hashtable_ebo_helper<1, _H1>, + private _Hashtable_ebo_helper<2, _H2> + { + private: + using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; + using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>; + using __ebo_h2 = _Hashtable_ebo_helper<2, _H2>; + + // Gives the local iterator implementation access to _M_bucket_index(). + friend struct _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, + _Default_ranged_hash, false>; + + public: + typedef _H1 hasher; + + hasher + hash_function() const + { return _M_h1(); } + + protected: + typedef std::size_t __hash_code; + typedef _Hash_node<_Value, false> __node_type; + + // We need the default constructor for the local iterators and _Hashtable + // default constructor. + _Hash_code_base() = default; + + _Hash_code_base(const _ExtractKey& __ex, + const _H1& __h1, const _H2& __h2, + const _Default_ranged_hash&) + : __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { } + + __hash_code + _M_hash_code(const _Key& __k) const + { + static_assert(__is_invocable{}, + "hash function must be invocable with an argument of key type"); + return _M_h1()(__k); + } + + std::size_t + _M_bucket_index(const _Key&, __hash_code __c, + std::size_t __bkt_count) const + { return _M_h2()(__c, __bkt_count); } + + std::size_t + _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const + noexcept( noexcept(declval()(declval())) + && noexcept(declval()((__hash_code)0, + (std::size_t)0)) ) + { return _M_h2()(_M_h1()(_M_extract()(__p->_M_v())), __bkt_count); } + + void + _M_store_code(__node_type*, __hash_code) const + { } + + void + _M_copy_code(__node_type*, const __node_type*) const + { } + + void + _M_swap(_Hash_code_base& __x) + { + std::swap(__ebo_extract_key::_M_get(), + __x.__ebo_extract_key::_M_get()); + std::swap(__ebo_h1::_M_get(), __x.__ebo_h1::_M_get()); + std::swap(__ebo_h2::_M_get(), __x.__ebo_h2::_M_get()); + } + + const _ExtractKey& + _M_extract() const { return __ebo_extract_key::_M_cget(); } + + const _H1& + _M_h1() const { return __ebo_h1::_M_cget(); } + + const _H2& + _M_h2() const { return __ebo_h2::_M_cget(); } + }; + + /// Specialization: hash function and range-hashing function, + /// caching hash codes. H is provided but ignored. Provides + /// typedef and accessor required by C++ 11. + template + struct _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, + _Default_ranged_hash, true> + : private _Hashtable_ebo_helper<0, _ExtractKey>, + private _Hashtable_ebo_helper<1, _H1>, + private _Hashtable_ebo_helper<2, _H2> + { + private: + // Gives the local iterator implementation access to _M_h2(). + friend struct _Local_iterator_base<_Key, _Value, _ExtractKey, _H1, _H2, + _Default_ranged_hash, true>; + + using __ebo_extract_key = _Hashtable_ebo_helper<0, _ExtractKey>; + using __ebo_h1 = _Hashtable_ebo_helper<1, _H1>; + using __ebo_h2 = _Hashtable_ebo_helper<2, _H2>; + + public: + typedef _H1 hasher; + + hasher + hash_function() const + { return _M_h1(); } + + protected: + typedef std::size_t __hash_code; + typedef _Hash_node<_Value, true> __node_type; + + // We need the default constructor for _Hashtable default constructor. + _Hash_code_base() = default; + _Hash_code_base(const _ExtractKey& __ex, + const _H1& __h1, const _H2& __h2, + const _Default_ranged_hash&) + : __ebo_extract_key(__ex), __ebo_h1(__h1), __ebo_h2(__h2) { } + + __hash_code + _M_hash_code(const _Key& __k) const + { + static_assert(__is_invocable{}, + "hash function must be invocable with an argument of key type"); + return _M_h1()(__k); + } + + std::size_t + _M_bucket_index(const _Key&, __hash_code __c, + std::size_t __bkt_count) const + { return _M_h2()(__c, __bkt_count); } + + std::size_t + _M_bucket_index(const __node_type* __p, std::size_t __bkt_count) const + noexcept( noexcept(declval()((__hash_code)0, + (std::size_t)0)) ) + { return _M_h2()(__p->_M_hash_code, __bkt_count); } + + void + _M_store_code(__node_type* __n, __hash_code __c) const + { __n->_M_hash_code = __c; } + + void + _M_copy_code(__node_type* __to, const __node_type* __from) const + { __to->_M_hash_code = __from->_M_hash_code; } + + void + _M_swap(_Hash_code_base& __x) + { + std::swap(__ebo_extract_key::_M_get(), + __x.__ebo_extract_key::_M_get()); + std::swap(__ebo_h1::_M_get(), __x.__ebo_h1::_M_get()); + std::swap(__ebo_h2::_M_get(), __x.__ebo_h2::_M_get()); + } + + const _ExtractKey& + _M_extract() const { return __ebo_extract_key::_M_cget(); } + + const _H1& + _M_h1() const { return __ebo_h1::_M_cget(); } + + const _H2& + _M_h2() const { return __ebo_h2::_M_cget(); } + }; + + /// Partial specialization used when nodes contain a cached hash code. + template + struct _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, true> + : private _Hashtable_ebo_helper<0, _H2> + { + protected: + using __base_type = _Hashtable_ebo_helper<0, _H2>; + using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, true>; + + _Local_iterator_base() = default; + _Local_iterator_base(const __hash_code_base& __base, + _Hash_node<_Value, true>* __p, + std::size_t __bkt, std::size_t __bkt_count) + : __base_type(__base._M_h2()), + _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) { } + + void + _M_incr() + { + _M_cur = _M_cur->_M_next(); + if (_M_cur) + { + std::size_t __bkt + = __base_type::_M_get()(_M_cur->_M_hash_code, + _M_bucket_count); + if (__bkt != _M_bucket) + _M_cur = nullptr; + } + } + + _Hash_node<_Value, true>* _M_cur; + std::size_t _M_bucket; + std::size_t _M_bucket_count; + + public: + const void* + _M_curr() const { return _M_cur; } // for equality ops + + std::size_t + _M_get_bucket() const { return _M_bucket; } // for debug mode + }; + + // Uninitialized storage for a _Hash_code_base. + // This type is DefaultConstructible and Assignable even if the + // _Hash_code_base type isn't, so that _Local_iterator_base<..., false> + // can be DefaultConstructible and Assignable. + template::value> + struct _Hash_code_storage + { + __gnu_cxx::__aligned_buffer<_Tp> _M_storage; + + _Tp* + _M_h() { return _M_storage._M_ptr(); } + + const _Tp* + _M_h() const { return _M_storage._M_ptr(); } + }; + + // Empty partial specialization for empty _Hash_code_base types. + template + struct _Hash_code_storage<_Tp, true> + { + static_assert( std::is_empty<_Tp>::value, "Type must be empty" ); + + // As _Tp is an empty type there will be no bytes written/read through + // the cast pointer, so no strict-aliasing violation. + _Tp* + _M_h() { return reinterpret_cast<_Tp*>(this); } + + const _Tp* + _M_h() const { return reinterpret_cast(this); } + }; + + template + using __hash_code_for_local_iter + = _Hash_code_storage<_Hash_code_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, false>>; + + // Partial specialization used when hash codes are not cached + template + struct _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, false> + : __hash_code_for_local_iter<_Key, _Value, _ExtractKey, _H1, _H2, _Hash> + { + protected: + using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, false>; + + _Local_iterator_base() : _M_bucket_count(-1) { } + + _Local_iterator_base(const __hash_code_base& __base, + _Hash_node<_Value, false>* __p, + std::size_t __bkt, std::size_t __bkt_count) + : _M_cur(__p), _M_bucket(__bkt), _M_bucket_count(__bkt_count) + { _M_init(__base); } + + ~_Local_iterator_base() + { + if (_M_bucket_count != -1) + _M_destroy(); + } + + _Local_iterator_base(const _Local_iterator_base& __iter) + : _M_cur(__iter._M_cur), _M_bucket(__iter._M_bucket), + _M_bucket_count(__iter._M_bucket_count) + { + if (_M_bucket_count != -1) + _M_init(*__iter._M_h()); + } + + _Local_iterator_base& + operator=(const _Local_iterator_base& __iter) + { + if (_M_bucket_count != -1) + _M_destroy(); + _M_cur = __iter._M_cur; + _M_bucket = __iter._M_bucket; + _M_bucket_count = __iter._M_bucket_count; + if (_M_bucket_count != -1) + _M_init(*__iter._M_h()); + return *this; + } + + void + _M_incr() + { + _M_cur = _M_cur->_M_next(); + if (_M_cur) + { + std::size_t __bkt = this->_M_h()->_M_bucket_index(_M_cur, + _M_bucket_count); + if (__bkt != _M_bucket) + _M_cur = nullptr; + } + } + + _Hash_node<_Value, false>* _M_cur; + std::size_t _M_bucket; + std::size_t _M_bucket_count; + + void + _M_init(const __hash_code_base& __base) + { ::new(this->_M_h()) __hash_code_base(__base); } + + void + _M_destroy() { this->_M_h()->~__hash_code_base(); } + + public: + const void* + _M_curr() const { return _M_cur; } // for equality ops and debug mode + + std::size_t + _M_get_bucket() const { return _M_bucket; } // for debug mode + }; + + template + inline bool + operator==(const _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>& __x, + const _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>& __y) + { return __x._M_curr() == __y._M_curr(); } + + template + inline bool + operator!=(const _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>& __x, + const _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>& __y) + { return __x._M_curr() != __y._M_curr(); } + + /// local iterators + template + struct _Local_iterator + : public _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache> + { + private: + using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>; + using __hash_code_base = typename __base_type::__hash_code_base; + public: + typedef _Value value_type; + typedef typename std::conditional<__constant_iterators, + const _Value*, _Value*>::type + pointer; + typedef typename std::conditional<__constant_iterators, + const _Value&, _Value&>::type + reference; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Local_iterator() = default; + + _Local_iterator(const __hash_code_base& __base, + _Hash_node<_Value, __cache>* __n, + std::size_t __bkt, std::size_t __bkt_count) + : __base_type(__base, __n, __bkt, __bkt_count) + { } + + reference + operator*() const + { return this->_M_cur->_M_v(); } + + pointer + operator->() const + { return this->_M_cur->_M_valptr(); } + + _Local_iterator& + operator++() + { + this->_M_incr(); + return *this; + } + + _Local_iterator + operator++(int) + { + _Local_iterator __tmp(*this); + this->_M_incr(); + return __tmp; + } + }; + + /// local const_iterators + template + struct _Local_const_iterator + : public _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache> + { + private: + using __base_type = _Local_iterator_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, __cache>; + using __hash_code_base = typename __base_type::__hash_code_base; + + public: + typedef _Value value_type; + typedef const _Value* pointer; + typedef const _Value& reference; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Local_const_iterator() = default; + + _Local_const_iterator(const __hash_code_base& __base, + _Hash_node<_Value, __cache>* __n, + std::size_t __bkt, std::size_t __bkt_count) + : __base_type(__base, __n, __bkt, __bkt_count) + { } + + _Local_const_iterator(const _Local_iterator<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, + __constant_iterators, + __cache>& __x) + : __base_type(__x) + { } + + reference + operator*() const + { return this->_M_cur->_M_v(); } + + pointer + operator->() const + { return this->_M_cur->_M_valptr(); } + + _Local_const_iterator& + operator++() + { + this->_M_incr(); + return *this; + } + + _Local_const_iterator + operator++(int) + { + _Local_const_iterator __tmp(*this); + this->_M_incr(); + return __tmp; + } + }; + + /** + * Primary class template _Hashtable_base. + * + * Helper class adding management of _Equal functor to + * _Hash_code_base type. + * + * Base class templates are: + * - __detail::_Hash_code_base + * - __detail::_Hashtable_ebo_helper + */ + template + struct _Hashtable_base + : public _Hash_code_base<_Key, _Value, _ExtractKey, _H1, _H2, _Hash, + _Traits::__hash_cached::value>, + private _Hashtable_ebo_helper<0, _Equal> + { + public: + typedef _Key key_type; + typedef _Value value_type; + typedef _Equal key_equal; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + using __traits_type = _Traits; + using __hash_cached = typename __traits_type::__hash_cached; + using __constant_iterators = typename __traits_type::__constant_iterators; + using __unique_keys = typename __traits_type::__unique_keys; + + using __hash_code_base = _Hash_code_base<_Key, _Value, _ExtractKey, + _H1, _H2, _Hash, + __hash_cached::value>; + + using __hash_code = typename __hash_code_base::__hash_code; + using __node_type = typename __hash_code_base::__node_type; + + using iterator = __detail::_Node_iterator; + + using const_iterator = __detail::_Node_const_iterator; + + using local_iterator = __detail::_Local_iterator; + + using const_local_iterator = __detail::_Local_const_iterator; + + using __ireturn_type = typename std::conditional<__unique_keys::value, + std::pair, + iterator>::type; + private: + using _EqualEBO = _Hashtable_ebo_helper<0, _Equal>; + + template + struct _Equal_hash_code + { + static bool + _S_equals(__hash_code, const _NodeT&) + { return true; } + }; + + template + struct _Equal_hash_code<_Hash_node<_Ptr2, true>> + { + static bool + _S_equals(__hash_code __c, const _Hash_node<_Ptr2, true>& __n) + { return __c == __n._M_hash_code; } + }; + + protected: + _Hashtable_base() = default; + _Hashtable_base(const _ExtractKey& __ex, const _H1& __h1, const _H2& __h2, + const _Hash& __hash, const _Equal& __eq) + : __hash_code_base(__ex, __h1, __h2, __hash), _EqualEBO(__eq) + { } + + bool + _M_equals(const _Key& __k, __hash_code __c, __node_type* __n) const + { + static_assert(__is_invocable{}, + "key equality predicate must be invocable with two arguments of " + "key type"); + return _Equal_hash_code<__node_type>::_S_equals(__c, *__n) + && _M_eq()(__k, this->_M_extract()(__n->_M_v())); + } + + void + _M_swap(_Hashtable_base& __x) + { + __hash_code_base::_M_swap(__x); + std::swap(_EqualEBO::_M_get(), __x._EqualEBO::_M_get()); + } + + const _Equal& + _M_eq() const { return _EqualEBO::_M_cget(); } + }; + + /** + * Primary class template _Equality. + * + * This is for implementing equality comparison for unordered + * containers, per N3068, by John Lakos and Pablo Halpern. + * Algorithmically, we follow closely the reference implementations + * therein. + */ + template + struct _Equality; + + /// unordered_map and unordered_set specializations. + template + struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true> + { + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>; + + bool + _M_equal(const __hashtable&) const; + }; + + template + bool + _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, true>:: + _M_equal(const __hashtable& __other) const + { + using __node_base = typename __hashtable::__node_base; + using __node_type = typename __hashtable::__node_type; + const __hashtable* __this = static_cast(this); + if (__this->size() != __other.size()) + return false; + + for (auto __itx = __this->begin(); __itx != __this->end(); ++__itx) + { + std::size_t __ybkt = __other._M_bucket_index(__itx._M_cur); + __node_base* __prev_n = __other._M_buckets[__ybkt]; + if (!__prev_n) + return false; + + for (__node_type* __n = static_cast<__node_type*>(__prev_n->_M_nxt);; + __n = __n->_M_next()) + { + if (__n->_M_v() == *__itx) + break; + + if (!__n->_M_nxt + || __other._M_bucket_index(__n->_M_next()) != __ybkt) + return false; + } + } + + return true; + } + + /// unordered_multiset and unordered_multimap specializations. + template + struct _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, false> + { + using __hashtable = _Hashtable<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits>; + + bool + _M_equal(const __hashtable&) const; + }; + + template + bool + _Equality<_Key, _Value, _Alloc, _ExtractKey, _Equal, + _H1, _H2, _Hash, _RehashPolicy, _Traits, false>:: + _M_equal(const __hashtable& __other) const + { + using __node_base = typename __hashtable::__node_base; + using __node_type = typename __hashtable::__node_type; + const __hashtable* __this = static_cast(this); + if (__this->size() != __other.size()) + return false; + + for (auto __itx = __this->begin(); __itx != __this->end();) + { + std::size_t __x_count = 1; + auto __itx_end = __itx; + for (++__itx_end; __itx_end != __this->end() + && __this->key_eq()(_ExtractKey()(*__itx), + _ExtractKey()(*__itx_end)); + ++__itx_end) + ++__x_count; + + std::size_t __ybkt = __other._M_bucket_index(__itx._M_cur); + __node_base* __y_prev_n = __other._M_buckets[__ybkt]; + if (!__y_prev_n) + return false; + + __node_type* __y_n = static_cast<__node_type*>(__y_prev_n->_M_nxt); + for (;; __y_n = __y_n->_M_next()) + { + if (__this->key_eq()(_ExtractKey()(__y_n->_M_v()), + _ExtractKey()(*__itx))) + break; + + if (!__y_n->_M_nxt + || __other._M_bucket_index(__y_n->_M_next()) != __ybkt) + return false; + } + + typename __hashtable::const_iterator __ity(__y_n); + for (auto __ity_end = __ity; __ity_end != __other.end(); ++__ity_end) + if (--__x_count == 0) + break; + + if (__x_count != 0) + return false; + + if (!std::is_permutation(__itx, __itx_end, __ity)) + return false; + + __itx = __itx_end; + } + return true; + } + + /** + * This type deals with all allocation and keeps an allocator instance + * through inheritance to benefit from EBO when possible. + */ + template + struct _Hashtable_alloc : private _Hashtable_ebo_helper<0, _NodeAlloc> + { + private: + using __ebo_node_alloc = _Hashtable_ebo_helper<0, _NodeAlloc>; + public: + using __node_type = typename _NodeAlloc::value_type; + using __node_alloc_type = _NodeAlloc; + // Use __gnu_cxx to benefit from _S_always_equal and al. + using __node_alloc_traits = __gnu_cxx::__alloc_traits<__node_alloc_type>; + + using __value_alloc_traits = typename __node_alloc_traits::template + rebind_traits; + + using __node_base = __detail::_Hash_node_base; + using __bucket_type = __node_base*; + using __bucket_alloc_type = + __alloc_rebind<__node_alloc_type, __bucket_type>; + using __bucket_alloc_traits = std::allocator_traits<__bucket_alloc_type>; + + _Hashtable_alloc() = default; + _Hashtable_alloc(const _Hashtable_alloc&) = default; + _Hashtable_alloc(_Hashtable_alloc&&) = default; + + template + _Hashtable_alloc(_Alloc&& __a) + : __ebo_node_alloc(std::forward<_Alloc>(__a)) + { } + + __node_alloc_type& + _M_node_allocator() + { return __ebo_node_alloc::_M_get(); } + + const __node_alloc_type& + _M_node_allocator() const + { return __ebo_node_alloc::_M_cget(); } + + // Allocate a node and construct an element within it. + template + __node_type* + _M_allocate_node(_Args&&... __args); + + // Destroy the element within a node and deallocate the node. + void + _M_deallocate_node(__node_type* __n); + + // Deallocate a node. + void + _M_deallocate_node_ptr(__node_type* __n); + + // Deallocate the linked list of nodes pointed to by __n. + // The elements within the nodes are destroyed. + void + _M_deallocate_nodes(__node_type* __n); + + __bucket_type* + _M_allocate_buckets(std::size_t __bkt_count); + + void + _M_deallocate_buckets(__bucket_type*, std::size_t __bkt_count); + }; + + // Definitions of class template _Hashtable_alloc's out-of-line member + // functions. + template + template + auto + _Hashtable_alloc<_NodeAlloc>::_M_allocate_node(_Args&&... __args) + -> __node_type* + { + auto __nptr = __node_alloc_traits::allocate(_M_node_allocator(), 1); + __node_type* __n = std::__to_address(__nptr); + __try + { + ::new ((void*)__n) __node_type; + __node_alloc_traits::construct(_M_node_allocator(), + __n->_M_valptr(), + std::forward<_Args>(__args)...); + return __n; + } + __catch(...) + { + __node_alloc_traits::deallocate(_M_node_allocator(), __nptr, 1); + __throw_exception_again; + } + } + + template + void + _Hashtable_alloc<_NodeAlloc>::_M_deallocate_node(__node_type* __n) + { + __node_alloc_traits::destroy(_M_node_allocator(), __n->_M_valptr()); + _M_deallocate_node_ptr(__n); + } + + template + void + _Hashtable_alloc<_NodeAlloc>::_M_deallocate_node_ptr(__node_type* __n) + { + typedef typename __node_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__n); + __n->~__node_type(); + __node_alloc_traits::deallocate(_M_node_allocator(), __ptr, 1); + } + + template + void + _Hashtable_alloc<_NodeAlloc>::_M_deallocate_nodes(__node_type* __n) + { + while (__n) + { + __node_type* __tmp = __n; + __n = __n->_M_next(); + _M_deallocate_node(__tmp); + } + } + + template + typename _Hashtable_alloc<_NodeAlloc>::__bucket_type* + _Hashtable_alloc<_NodeAlloc>::_M_allocate_buckets(std::size_t __bkt_count) + { + __bucket_alloc_type __alloc(_M_node_allocator()); + + auto __ptr = __bucket_alloc_traits::allocate(__alloc, __bkt_count); + __bucket_type* __p = std::__to_address(__ptr); + __builtin_memset(__p, 0, __bkt_count * sizeof(__bucket_type)); + return __p; + } + + template + void + _Hashtable_alloc<_NodeAlloc>::_M_deallocate_buckets(__bucket_type* __bkts, + std::size_t __bkt_count) + { + typedef typename __bucket_alloc_traits::pointer _Ptr; + auto __ptr = std::pointer_traits<_Ptr>::pointer_to(*__bkts); + __bucket_alloc_type __alloc(_M_node_allocator()); + __bucket_alloc_traits::deallocate(__alloc, __ptr, __bkt_count); + } + + //@} hashtable-detail +} // namespace __detail +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _HASHTABLE_POLICY_H diff --git a/resources/sources/avr-libstdcpp/include/bits/indirect_array.h b/resources/sources/avr-libstdcpp/include/bits/indirect_array.h new file mode 100644 index 000000000..11fac3290 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/indirect_array.h @@ -0,0 +1,212 @@ +// The template and inlines for the -*- C++ -*- indirect_array class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/indirect_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _INDIRECT_ARRAY_H +#define _INDIRECT_ARRAY_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Reference to arbitrary subset of an array. + * + * An indirect_array is a reference to the actual elements of an array + * specified by an ordered array of indices. The way to get an + * indirect_array is to call operator[](valarray) on a valarray. + * The returned indirect_array then permits carrying operations out on the + * referenced subset of elements in the original valarray. + * + * For example, if an indirect_array is obtained using the array (4,2,0) as + * an argument, and then assigned to an array containing (1,2,3), then the + * underlying array will have array[0]==3, array[2]==2, and array[4]==1. + * + * @param Tp Element type. + */ + template + class indirect_array + { + public: + typedef _Tp value_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 253. valarray helper functions are almost entirely useless + + /// Copy constructor. Both slices refer to the same underlying array. + indirect_array(const indirect_array&); + + /// Assignment operator. Assigns elements to corresponding elements + /// of @a a. + indirect_array& operator=(const indirect_array&); + + /// Assign slice elements to corresponding elements of @a v. + void operator=(const valarray<_Tp>&) const; + /// Multiply slice elements by corresponding elements of @a v. + void operator*=(const valarray<_Tp>&) const; + /// Divide slice elements by corresponding elements of @a v. + void operator/=(const valarray<_Tp>&) const; + /// Modulo slice elements by corresponding elements of @a v. + void operator%=(const valarray<_Tp>&) const; + /// Add corresponding elements of @a v to slice elements. + void operator+=(const valarray<_Tp>&) const; + /// Subtract corresponding elements of @a v from slice elements. + void operator-=(const valarray<_Tp>&) const; + /// Logical xor slice elements with corresponding elements of @a v. + void operator^=(const valarray<_Tp>&) const; + /// Logical and slice elements with corresponding elements of @a v. + void operator&=(const valarray<_Tp>&) const; + /// Logical or slice elements with corresponding elements of @a v. + void operator|=(const valarray<_Tp>&) const; + /// Left shift slice elements by corresponding elements of @a v. + void operator<<=(const valarray<_Tp>&) const; + /// Right shift slice elements by corresponding elements of @a v. + void operator>>=(const valarray<_Tp>&) const; + /// Assign all slice elements to @a t. + void operator= (const _Tp&) const; + // ~indirect_array(); + + template + void operator=(const _Expr<_Dom, _Tp>&) const; + template + void operator*=(const _Expr<_Dom, _Tp>&) const; + template + void operator/=(const _Expr<_Dom, _Tp>&) const; + template + void operator%=(const _Expr<_Dom, _Tp>&) const; + template + void operator+=(const _Expr<_Dom, _Tp>&) const; + template + void operator-=(const _Expr<_Dom, _Tp>&) const; + template + void operator^=(const _Expr<_Dom, _Tp>&) const; + template + void operator&=(const _Expr<_Dom, _Tp>&) const; + template + void operator|=(const _Expr<_Dom, _Tp>&) const; + template + void operator<<=(const _Expr<_Dom, _Tp>&) const; + template + void operator>>=(const _Expr<_Dom, _Tp>&) const; + + private: + /// Copy constructor. Both slices refer to the same underlying array. + indirect_array(_Array<_Tp>, size_t, _Array); + + friend class valarray<_Tp>; + friend class gslice_array<_Tp>; + + const size_t _M_sz; + const _Array _M_index; + const _Array<_Tp> _M_array; + + // not implemented + indirect_array(); + }; + + template + inline + indirect_array<_Tp>::indirect_array(const indirect_array<_Tp>& __a) + : _M_sz(__a._M_sz), _M_index(__a._M_index), _M_array(__a._M_array) {} + + template + inline + indirect_array<_Tp>::indirect_array(_Array<_Tp> __a, size_t __s, + _Array __i) + : _M_sz(__s), _M_index(__i), _M_array(__a) {} + + template + inline indirect_array<_Tp>& + indirect_array<_Tp>::operator=(const indirect_array<_Tp>& __a) + { + std::__valarray_copy(__a._M_array, _M_sz, __a._M_index, _M_array, + _M_index); + return *this; + } + + template + inline void + indirect_array<_Tp>::operator=(const _Tp& __t) const + { std::__valarray_fill(_M_array, _M_index, _M_sz, __t); } + + template + inline void + indirect_array<_Tp>::operator=(const valarray<_Tp>& __v) const + { std::__valarray_copy(_Array<_Tp>(__v), _M_sz, _M_array, _M_index); } + + template + template + inline void + indirect_array<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) const + { std::__valarray_copy(__e, _M_sz, _M_array, _M_index); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ + template \ + inline void \ + indirect_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const\ + { \ + _Array_augmented_##_Name(_M_array, _M_index, _Array<_Tp>(__v), _M_sz); \ + } \ + \ + template \ + template \ + inline void \ + indirect_array<_Tp>::operator _Op##=(const _Expr<_Dom,_Tp>& __e) const\ + { \ + _Array_augmented_##_Name(_M_array, _M_index, __e, _M_sz); \ + } + +_DEFINE_VALARRAY_OPERATOR(*, __multiplies) +_DEFINE_VALARRAY_OPERATOR(/, __divides) +_DEFINE_VALARRAY_OPERATOR(%, __modulus) +_DEFINE_VALARRAY_OPERATOR(+, __plus) +_DEFINE_VALARRAY_OPERATOR(-, __minus) +_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) +_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) +_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) +_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _INDIRECT_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/invoke.h b/resources/sources/avr-libstdcpp/include/bits/invoke.h new file mode 100644 index 000000000..18f5b9442 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/invoke.h @@ -0,0 +1,163 @@ +// Implementation of INVOKE -*- C++ -*- + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/invoke.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_INVOKE_H +#define _GLIBCXX_INVOKE_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + // Used by __invoke_impl instead of std::forward<_Tp> so that a + // reference_wrapper is converted to an lvalue-reference. + template::type> + constexpr _Up&& + __invfwd(typename remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Up&&>(__t); } + + template + constexpr _Res + __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args) + { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); } + + template + constexpr _Res + __invoke_impl(__invoke_memfun_ref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...); } + + template + constexpr _Res + __invoke_impl(__invoke_memfun_deref, _MemFun&& __f, _Tp&& __t, + _Args&&... __args) + { + return ((*std::forward<_Tp>(__t)).*__f)(std::forward<_Args>(__args)...); + } + + template + constexpr _Res + __invoke_impl(__invoke_memobj_ref, _MemPtr&& __f, _Tp&& __t) + { return __invfwd<_Tp>(__t).*__f; } + + template + constexpr _Res + __invoke_impl(__invoke_memobj_deref, _MemPtr&& __f, _Tp&& __t) + { return (*std::forward<_Tp>(__t)).*__f; } + + /// Invoke a callable object. + template + constexpr typename __invoke_result<_Callable, _Args...>::type + __invoke(_Callable&& __fn, _Args&&... __args) + noexcept(__is_nothrow_invocable<_Callable, _Args...>::value) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } + +#if __cplusplus >= 201703L + // INVOKE: Invoke a callable object and convert the result to R. + template + constexpr enable_if_t, _Res> + __invoke_r(_Callable&& __fn, _Args&&... __args) + noexcept(is_nothrow_invocable_r_v<_Res, _Callable, _Args...>) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + if constexpr (is_void_v<_Res>) + std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + else + return std::__invoke_impl<__type>(__tag{}, + std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#else // C++11 + template + using __can_invoke_as_void = __enable_if_t< + __and_, __is_invocable<_Callable, _Args...>>::value, + _Res + >; + + template + using __can_invoke_as_nonvoid = __enable_if_t< + __and_<__not_>, + is_convertible::type, + _Res> + >::value, + _Res + >; + + // INVOKE: Invoke a callable object and convert the result to R. + template + constexpr __can_invoke_as_nonvoid<_Res, _Callable, _Args...> + __invoke_r(_Callable&& __fn, _Args&&... __args) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + return std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } + + // INVOKE when R is cv void + template + _GLIBCXX14_CONSTEXPR __can_invoke_as_void<_Res, _Callable, _Args...> + __invoke_r(_Callable&& __fn, _Args&&... __args) + { + using __result = __invoke_result<_Callable, _Args...>; + using __type = typename __result::type; + using __tag = typename __result::__invoke_type; + std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_INVOKE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h b/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h new file mode 100644 index 000000000..2721240e3 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/iterator_concepts.h @@ -0,0 +1,911 @@ +// Concepts and traits for use with iterators -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/iterator_concepts.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _ITERATOR_CONCEPTS_H +#define _ITERATOR_CONCEPTS_H 1 + +#pragma GCC system_header + +#include +#include // to_address +#include // identity, ranges::less + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct input_iterator_tag; + struct output_iterator_tag; + struct forward_iterator_tag; + struct bidirectional_iterator_tag; + struct random_access_iterator_tag; + struct contiguous_iterator_tag; + + template + struct iterator_traits; + + template requires is_object_v<_Tp> + struct iterator_traits<_Tp*>; + + template + struct __iterator_traits; + + namespace __detail + { + template + using __with_ref = _Tp&; + + template + concept __can_reference = requires { typename __with_ref<_Tp>; }; + + template + concept __dereferenceable = requires(_Tp& __t) + { + { *__t } -> __can_reference; + }; + } // namespace __detail + + template<__detail::__dereferenceable _Tp> + using iter_reference_t = decltype(*std::declval<_Tp&>()); + + namespace ranges + { + namespace __cust_imove + { + void iter_move(); + + template + concept __adl_imove + = (std::__detail::__class_or_enum>) + && requires(_Tp&& __t) { iter_move(static_cast<_Tp&&>(__t)); }; + + struct _IMove + { + private: + template + struct __result + { using type = iter_reference_t<_Tp>; }; + + template + requires __adl_imove<_Tp> + struct __result<_Tp> + { using type = decltype(iter_move(std::declval<_Tp>())); }; + + template + requires (!__adl_imove<_Tp>) + && is_lvalue_reference_v> + struct __result<_Tp> + { using type = remove_reference_t>&&; }; + + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_imove<_Tp>) + return noexcept(iter_move(std::declval<_Tp>())); + else + return noexcept(*std::declval<_Tp>()); + } + + public: + // The result type of iter_move(std::declval<_Tp>()) + template + using __type = typename __result<_Tp>::type; + + template + constexpr __type<_Tp> + operator()(_Tp&& __e) const + noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__adl_imove<_Tp>) + return iter_move(static_cast<_Tp&&>(__e)); + else if constexpr (is_lvalue_reference_v>) + return static_cast<__type<_Tp>>(*__e); + else + return *__e; + } + }; + } // namespace __cust_imove + + inline namespace __cust + { + inline constexpr __cust_imove::_IMove iter_move{}; + } // inline namespace __cust + } // namespace ranges + + template<__detail::__dereferenceable _Tp> + requires requires(_Tp& __t) + { { ranges::iter_move(__t) } -> __detail::__can_reference; } + using iter_rvalue_reference_t + = decltype(ranges::iter_move(std::declval<_Tp&>())); + + template struct incrementable_traits { }; + + template requires is_object_v<_Tp> + struct incrementable_traits<_Tp*> + { using difference_type = ptrdiff_t; }; + + template + struct incrementable_traits + : incrementable_traits<_Iter> { }; + + template requires requires { typename _Tp::difference_type; } + struct incrementable_traits<_Tp> + { using difference_type = typename _Tp::difference_type; }; + + template + requires (!requires { typename _Tp::difference_type; } + && requires(const _Tp& __a, const _Tp& __b) + { + requires (!is_void_v>); // PR c++/78173 + { __a - __b } -> integral; + }) + struct incrementable_traits<_Tp> + { + using difference_type + = make_signed_t() - std::declval<_Tp>())>; + }; + + namespace __detail + { + // An iterator such that iterator_traits<_Iter> names a specialization + // generated from the primary template. + template + concept __primary_traits_iter + = __is_base_of(__iterator_traits<_Iter, void>, iterator_traits<_Iter>); + + template + struct __iter_traits_impl + { using type = iterator_traits<_Iter>; }; + + template + requires __primary_traits_iter<_Iter> + struct __iter_traits_impl<_Iter, _Tp> + { using type = _Tp; }; + + // ITER_TRAITS + template + using __iter_traits = typename __iter_traits_impl<_Iter, _Tp>::type; + + template + using __iter_diff_t = typename + __iter_traits<_Tp, incrementable_traits<_Tp>>::difference_type; + } // namespace __detail + + template + using iter_difference_t = __detail::__iter_diff_t>; + + namespace __detail + { + template struct __cond_value_type { }; + + template requires is_object_v<_Tp> + struct __cond_value_type<_Tp> + { using value_type = remove_cv_t<_Tp>; }; + } // namespace __detail + + template struct indirectly_readable_traits { }; + + template + struct indirectly_readable_traits<_Tp*> + : __detail::__cond_value_type<_Tp> + { }; + + template requires is_array_v<_Iter> + struct indirectly_readable_traits<_Iter> + { using value_type = remove_cv_t>; }; + + template + struct indirectly_readable_traits + : indirectly_readable_traits<_Iter> + { }; + + template requires requires { typename _Tp::value_type; } + struct indirectly_readable_traits<_Tp> + : __detail::__cond_value_type + { }; + + template requires requires { typename _Tp::element_type; } + struct indirectly_readable_traits<_Tp> + : __detail::__cond_value_type + { }; + + namespace __detail + { + template + using __iter_value_t = typename + __iter_traits<_Tp, indirectly_readable_traits<_Tp>>::value_type; + } // namespace __detail + + template + using iter_value_t = __detail::__iter_value_t>; + + namespace __detail + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3420. cpp17-iterator should check [type] looks like an iterator first + template + concept __cpp17_iterator = requires(_Iter __it) + { + { *__it } -> __can_reference; + { ++__it } -> same_as<_Iter&>; + { *__it++ } -> __can_reference; + } && copyable<_Iter>; + + template + concept __cpp17_input_iterator = __cpp17_iterator<_Iter> + && equality_comparable<_Iter> + && requires(_Iter __it) + { + typename incrementable_traits<_Iter>::difference_type; + typename indirectly_readable_traits<_Iter>::value_type; + typename common_reference_t&&, + typename indirectly_readable_traits<_Iter>::value_type&>; + typename common_reference_t::value_type&>; + requires signed_integral< + typename incrementable_traits<_Iter>::difference_type>; + }; + + template + concept __cpp17_fwd_iterator = __cpp17_input_iterator<_Iter> + && constructible_from<_Iter> + && is_lvalue_reference_v> + && same_as>, + typename indirectly_readable_traits<_Iter>::value_type> + && requires(_Iter __it) + { + { __it++ } -> convertible_to; + { *__it++ } -> same_as>; + }; + + template + concept __cpp17_bidi_iterator = __cpp17_fwd_iterator<_Iter> + && requires(_Iter __it) + { + { --__it } -> same_as<_Iter&>; + { __it-- } -> convertible_to; + { *__it-- } -> same_as>; + }; + + template + concept __cpp17_randacc_iterator = __cpp17_bidi_iterator<_Iter> + && totally_ordered<_Iter> + && requires(_Iter __it, + typename incrementable_traits<_Iter>::difference_type __n) + { + { __it += __n } -> same_as<_Iter&>; + { __it -= __n } -> same_as<_Iter&>; + { __it + __n } -> same_as<_Iter>; + { __n + __it } -> same_as<_Iter>; + { __it - __n } -> same_as<_Iter>; + { __it - __it } -> same_as; + { __it[__n] } -> convertible_to>; + }; + + template + concept __iter_with_nested_types = requires { + typename _Iter::iterator_category; + typename _Iter::value_type; + typename _Iter::difference_type; + typename _Iter::reference; + }; + + template + concept __iter_without_nested_types = !__iter_with_nested_types<_Iter>; + + // FIXME: These have to be at namespace-scope because of PR 92103. + template + struct __ptr + { using type = void; }; + + template requires requires { typename _Iter::pointer; } + struct __ptr<_Iter, true> + { using type = typename _Iter::pointer; }; + + template requires requires { typename _Iter::pointer; } + struct __ptr<_Iter, false> + { using type = typename _Iter::pointer; }; + + template + requires (!requires { typename _Iter::pointer; } + && requires(_Iter& __it) { __it.operator->(); }) + struct __ptr<_Iter, true> + { using type = decltype(std::declval<_Iter&>().operator->()); }; + + template + struct __ref + { using type = iter_reference_t<_Iter>; }; + + template requires requires { typename _Iter::reference; } + struct __ref<_Iter> + { using type = typename _Iter::reference; }; + + template + struct __cat + { using type = input_iterator_tag; }; + + template + requires requires { typename _Iter::iterator_category; } + struct __cat<_Iter> + { using type = typename _Iter::iterator_category; }; + + template + requires (!requires { typename _Iter::iterator_category; } + && __detail::__cpp17_randacc_iterator<_Iter>) + struct __cat<_Iter> + { using type = random_access_iterator_tag; }; + + template + requires (!requires { typename _Iter::iterator_category; } + && __detail::__cpp17_bidi_iterator<_Iter>) + struct __cat<_Iter> + { using type = bidirectional_iterator_tag; }; + + template + requires (!requires { typename _Iter::iterator_category; } + && __detail::__cpp17_fwd_iterator<_Iter>) + struct __cat<_Iter> + { using type = forward_iterator_tag; }; + + template + struct __diff + { using type = void; }; + + template + requires requires { + typename incrementable_traits<_Iter>::difference_type; + } + struct __diff<_Iter> + { + using type = typename incrementable_traits<_Iter>::difference_type; + }; + + } // namespace __detail + + template + requires __detail::__iter_with_nested_types<_Iterator> + struct __iterator_traits<_Iterator, void> + { + using iterator_category = typename _Iterator::iterator_category; + using value_type = typename _Iterator::value_type; + using difference_type = typename _Iterator::difference_type; + using pointer = typename __detail::__ptr<_Iterator>::type; + using reference = typename _Iterator::reference; + }; + + template + requires __detail::__iter_without_nested_types<_Iterator> + && __detail::__cpp17_input_iterator<_Iterator> + struct __iterator_traits<_Iterator, void> + { + using iterator_category = typename __detail::__cat<_Iterator>::type; + using value_type + = typename indirectly_readable_traits<_Iterator>::value_type; + using difference_type + = typename incrementable_traits<_Iterator>::difference_type; + using pointer = typename __detail::__ptr<_Iterator, true>::type; + using reference = typename __detail::__ref<_Iterator>::type; + }; + + template + requires __detail::__iter_without_nested_types<_Iterator> + && __detail::__cpp17_iterator<_Iterator> + struct __iterator_traits<_Iterator, void> + { + using iterator_category = output_iterator_tag; + using value_type = void; + using difference_type = typename __detail::__diff<_Iterator>::type; + using pointer = void; + using reference = void; + }; + + namespace __detail + { + template + struct __iter_concept_impl; + + // ITER_CONCEPT(I) is ITER_TRAITS(I)::iterator_concept if that is valid. + template + requires requires { typename __iter_traits<_Iter>::iterator_concept; } + struct __iter_concept_impl<_Iter> + { using type = typename __iter_traits<_Iter>::iterator_concept; }; + + // Otherwise, ITER_TRAITS(I)::iterator_category if that is valid. + template + requires (!requires { typename __iter_traits<_Iter>::iterator_concept; } + && requires { typename __iter_traits<_Iter>::iterator_category; }) + struct __iter_concept_impl<_Iter> + { using type = typename __iter_traits<_Iter>::iterator_category; }; + + // Otherwise, random_access_tag if iterator_traits is not specialized. + template + requires (!requires { typename __iter_traits<_Iter>::iterator_concept; } + && !requires { typename __iter_traits<_Iter>::iterator_category; } + && __primary_traits_iter<_Iter>) + struct __iter_concept_impl<_Iter> + { using type = random_access_iterator_tag; }; + + // Otherwise, there is no ITER_CONCEPT(I) type. + template + struct __iter_concept_impl + { }; + + // ITER_CONCEPT + template + using __iter_concept = typename __iter_concept_impl<_Iter>::type; + + template + concept __indirectly_readable_impl = requires(const _In __in) + { + typename iter_value_t<_In>; + typename iter_reference_t<_In>; + typename iter_rvalue_reference_t<_In>; + { *__in } -> same_as>; + { ranges::iter_move(__in) } -> same_as>; + } + && common_reference_with&&, iter_value_t<_In>&> + && common_reference_with&&, + iter_rvalue_reference_t<_In>&&> + && common_reference_with&&, + const iter_value_t<_In>&>; + + } // namespace __detail + + /// Requirements for types that are readable by applying operator*. + template + concept indirectly_readable + = __detail::__indirectly_readable_impl>; + + template + using iter_common_reference_t + = common_reference_t, iter_value_t<_Tp>&>; + + /// Requirements for writing a value into an iterator's referenced object. + template + concept indirectly_writable = requires(_Out&& __o, _Tp&& __t) + { + *__o = std::forward<_Tp>(__t); + *std::forward<_Out>(__o) = std::forward<_Tp>(__t); + const_cast&&>(*__o) + = std::forward<_Tp>(__t); + const_cast&&>(*std::forward<_Out>(__o)) + = std::forward<_Tp>(__t); + }; + + namespace ranges::__detail + { +#if __SIZEOF_INT128__ + using __max_diff_type = __int128; + using __max_size_type = unsigned __int128; +#else + using __max_diff_type = long long; + using __max_size_type = unsigned long long; +#endif + + template + concept __is_integer_like = integral<_Tp> + || same_as<_Tp, __max_diff_type> || same_as<_Tp, __max_size_type>; + + template + concept __is_signed_integer_like = signed_integral<_Tp> + || same_as<_Tp, __max_diff_type>; + + } // namespace ranges::__detail + + namespace __detail { using ranges::__detail::__is_signed_integer_like; } + + /// Requirements on types that can be incremented with ++. + template + concept weakly_incrementable = default_initializable<_Iter> + && movable<_Iter> + && requires(_Iter __i) + { + typename iter_difference_t<_Iter>; + requires __detail::__is_signed_integer_like>; + { ++__i } -> same_as<_Iter&>; + __i++; + }; + + template + concept incrementable = regular<_Iter> && weakly_incrementable<_Iter> + && requires(_Iter __i) { { __i++ } -> same_as<_Iter>; }; + + template + concept input_or_output_iterator + = requires(_Iter __i) { { *__i } -> __detail::__can_reference; } + && weakly_incrementable<_Iter>; + + template + concept sentinel_for = semiregular<_Sent> + && input_or_output_iterator<_Iter> + && __detail::__weakly_eq_cmp_with<_Sent, _Iter>; + + template + inline constexpr bool disable_sized_sentinel_for = false; + + template + concept sized_sentinel_for = sentinel_for<_Sent, _Iter> + && !disable_sized_sentinel_for, remove_cv_t<_Iter>> + && requires(const _Iter& __i, const _Sent& __s) + { + { __s - __i } -> same_as>; + { __i - __s } -> same_as>; + }; + + template + concept input_iterator = input_or_output_iterator<_Iter> + && indirectly_readable<_Iter> + && requires { typename __detail::__iter_concept<_Iter>; } + && derived_from<__detail::__iter_concept<_Iter>, input_iterator_tag>; + + template + concept output_iterator = input_or_output_iterator<_Iter> + && indirectly_writable<_Iter, _Tp> + && requires(_Iter __i, _Tp&& __t) { *__i++ = std::forward<_Tp>(__t); }; + + template + concept forward_iterator = input_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, forward_iterator_tag> + && incrementable<_Iter> && sentinel_for<_Iter, _Iter>; + + template + concept bidirectional_iterator = forward_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, + bidirectional_iterator_tag> + && requires(_Iter __i) + { + { --__i } -> same_as<_Iter&>; + { __i-- } -> same_as<_Iter>; + }; + + template + concept random_access_iterator = bidirectional_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, + random_access_iterator_tag> + && totally_ordered<_Iter> && sized_sentinel_for<_Iter, _Iter> + && requires(_Iter __i, const _Iter __j, + const iter_difference_t<_Iter> __n) + { + { __i += __n } -> same_as<_Iter&>; + { __j + __n } -> same_as<_Iter>; + { __n + __j } -> same_as<_Iter>; + { __i -= __n } -> same_as<_Iter&>; + { __j - __n } -> same_as<_Iter>; + { __j[__n] } -> same_as>; + }; + + template + concept contiguous_iterator = random_access_iterator<_Iter> + && derived_from<__detail::__iter_concept<_Iter>, contiguous_iterator_tag> + && is_lvalue_reference_v> + && same_as, remove_cvref_t>> + && requires(const _Iter& __i) + { + { std::to_address(__i) } + -> same_as>>; + }; + + // [indirectcallable], indirect callable requirements + + // [indirectcallable.indirectinvocable], indirect callables + + template + concept indirectly_unary_invocable = indirectly_readable<_Iter> + && copy_constructible<_Fn> && invocable<_Fn&, iter_value_t<_Iter>&> + && invocable<_Fn&, iter_reference_t<_Iter>> + && invocable<_Fn&, iter_common_reference_t<_Iter>> + && common_reference_with&>, + invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; + + template + concept indirectly_regular_unary_invocable = indirectly_readable<_Iter> + && copy_constructible<_Fn> + && regular_invocable<_Fn&, iter_value_t<_Iter>&> + && regular_invocable<_Fn&, iter_reference_t<_Iter>> + && regular_invocable<_Fn&, iter_common_reference_t<_Iter>> + && common_reference_with&>, + invoke_result_t<_Fn&, iter_reference_t<_Iter>>>; + + template + concept indirect_unary_predicate = indirectly_readable<_Iter> + && copy_constructible<_Fn> && predicate<_Fn&, iter_value_t<_Iter>&> + && predicate<_Fn&, iter_reference_t<_Iter>> + && predicate<_Fn&, iter_common_reference_t<_Iter>>; + + template + concept indirect_binary_predicate + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && predicate<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && predicate<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && predicate<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && predicate<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>> + && predicate<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + concept indirect_equivalence_relation + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && equivalence_relation<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && equivalence_relation<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && equivalence_relation<_Fn&, iter_reference_t<_I1>, + iter_reference_t<_I2>> + && equivalence_relation<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + concept indirect_strict_weak_order + = indirectly_readable<_I1> && indirectly_readable<_I2> + && copy_constructible<_Fn> + && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_value_t<_I2>&> + && strict_weak_order<_Fn&, iter_value_t<_I1>&, iter_reference_t<_I2>> + && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_value_t<_I2>&> + && strict_weak_order<_Fn&, iter_reference_t<_I1>, iter_reference_t<_I2>> + && strict_weak_order<_Fn&, iter_common_reference_t<_I1>, + iter_common_reference_t<_I2>>; + + template + requires (indirectly_readable<_Is> && ...) + && invocable<_Fn, iter_reference_t<_Is>...> + using indirect_result_t = invoke_result_t<_Fn, iter_reference_t<_Is>...>; + + /// [projected], projected + template _Proj> + struct projected + { + using value_type = remove_cvref_t>; + + indirect_result_t<_Proj&, _Iter> operator*() const; // not defined + }; + + template + struct incrementable_traits> + { using difference_type = iter_difference_t<_Iter>; }; + + // [alg.req], common algorithm requirements + + /// [alg.req.ind.move], concept `indirectly_movable` + + template + concept indirectly_movable = indirectly_readable<_In> + && indirectly_writable<_Out, iter_rvalue_reference_t<_In>>; + + template + concept indirectly_movable_storable = indirectly_movable<_In, _Out> + && indirectly_writable<_Out, iter_value_t<_In>> + && movable> + && constructible_from, iter_rvalue_reference_t<_In>> + && assignable_from&, iter_rvalue_reference_t<_In>>; + + /// [alg.req.ind.copy], concept `indirectly_copyable` + template + concept indirectly_copyable = indirectly_readable<_In> + && indirectly_writable<_Out, iter_reference_t<_In>>; + + template + concept indirectly_copyable_storable = indirectly_copyable<_In, _Out> + && indirectly_writable<_Out, iter_value_t<_In>&> + && indirectly_writable<_Out, const iter_value_t<_In>&> + && indirectly_writable<_Out, iter_value_t<_In>&&> + && indirectly_writable<_Out, const iter_value_t<_In>&&> + && copyable> + && constructible_from, iter_reference_t<_In>> + && assignable_from&, iter_reference_t<_In>>; + +namespace ranges +{ + namespace __cust_iswap + { + template + void iter_swap(_It1, _It2) = delete; + + template + concept __adl_iswap + = (std::__detail::__class_or_enum> + || std::__detail::__class_or_enum>) + && requires(_Tp&& __t, _Up&& __u) { + iter_swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + }; + + template + constexpr iter_value_t<_Xp> + __iter_exchange_move(_Xp&& __x, _Yp&& __y) + noexcept(noexcept(iter_value_t<_Xp>(iter_move(__x))) + && noexcept(*__x = iter_move(__y))) + { + iter_value_t<_Xp> __old_value(iter_move(__x)); + *__x = iter_move(__y); + return __old_value; + } + + struct _IterSwap + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_iswap<_Tp, _Up>) + return noexcept(iter_swap(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (indirectly_readable<_Tp> + && indirectly_readable<_Up> + && swappable_with, iter_reference_t<_Up>>) + return noexcept(ranges::swap(*std::declval<_Tp>(), + *std::declval<_Up>())); + else + return noexcept(*std::declval<_Tp>() + = __iter_exchange_move(std::declval<_Up>(), + std::declval<_Tp>())); + } + + public: + template + requires __adl_iswap<_Tp, _Up> + || (indirectly_readable> + && indirectly_readable> + && swappable_with, iter_reference_t<_Up>>) + || (indirectly_movable_storable<_Tp, _Up> + && indirectly_movable_storable<_Up, _Tp>) + constexpr void + operator()(_Tp&& __e1, _Up&& __e2) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__adl_iswap<_Tp, _Up>) + iter_swap(static_cast<_Tp&&>(__e1), static_cast<_Up&&>(__e2)); + else if constexpr (indirectly_readable<_Tp> + && indirectly_readable<_Up> + && swappable_with, iter_reference_t<_Up>>) + ranges::swap(*__e1, *__e2); + else + *__e1 = __iter_exchange_move(__e2, __e1); + } + }; + } // namespace __cust_iswap + + inline namespace __cust + { + inline constexpr __cust_iswap::_IterSwap iter_swap{}; + } // inline namespace __cust + +} // namespace ranges + + /// [alg.req.ind.swap], concept `indirectly_swappable` + template + concept indirectly_swappable + = indirectly_readable<_I1> && indirectly_readable<_I2> + && requires(const _I1 __i1, const _I2 __i2) + { + ranges::iter_swap(__i1, __i1); + ranges::iter_swap(__i2, __i2); + ranges::iter_swap(__i1, __i2); + ranges::iter_swap(__i2, __i1); + }; + + /// [alg.req.ind.cmp], concept `indirectly_comparable` + template + concept indirectly_comparable + = indirect_binary_predicate<_Rel, projected<_I1, _P1>, + projected<_I2, _P2>>; + + /// [alg.req.permutable], concept `permutable` + template + concept permutable = forward_iterator<_Iter> + && indirectly_movable_storable<_Iter, _Iter> + && indirectly_swappable<_Iter, _Iter>; + + /// [alg.req.mergeable], concept `mergeable` + template + concept mergeable = input_iterator<_I1> && input_iterator<_I2> + && weakly_incrementable<_Out> && indirectly_copyable<_I1, _Out> + && indirectly_copyable<_I2, _Out> + && indirect_strict_weak_order<_Rel, projected<_I1, _P1>, + projected<_I2, _P2>>; + + /// [alg.req.sortable], concept `sortable` + template + concept sortable = permutable<_Iter> + && indirect_strict_weak_order<_Rel, projected<_Iter, _Proj>>; + + struct unreachable_sentinel_t + { + template + friend constexpr bool + operator==(unreachable_sentinel_t, const _It&) noexcept + { return false; } + }; + + inline constexpr unreachable_sentinel_t unreachable_sentinel{}; + + struct default_sentinel_t { }; + inline constexpr default_sentinel_t default_sentinel{}; + + namespace __detail + { + template + constexpr decay_t<_Tp> + __decay_copy(_Tp&& __t) + noexcept(is_nothrow_convertible_v<_Tp, decay_t<_Tp>>) + { return std::forward<_Tp>(__t); } + + template + concept __member_begin = requires(_Tp& __t) + { + { __detail::__decay_copy(__t.begin()) } -> input_or_output_iterator; + }; + + void begin(auto&) = delete; + void begin(const auto&) = delete; + + template + concept __adl_begin = __class_or_enum> + && requires(_Tp& __t) + { + { __detail::__decay_copy(begin(__t)) } -> input_or_output_iterator; + }; + + // Simplified version of std::ranges::begin that only supports lvalues, + // for use by __range_iter_t below. + template + requires is_array_v<_Tp> || __member_begin<_Tp&> || __adl_begin<_Tp&> + auto + __ranges_begin(_Tp& __t) + { + if constexpr (is_array_v<_Tp>) + { + static_assert(sizeof(remove_all_extents_t<_Tp>) != 0, + "not array of incomplete type"); + return __t + 0; + } + else if constexpr (__member_begin<_Tp&>) + return __t.begin(); + else + return begin(__t); + } + + // Implementation of std::ranges::iterator_t, without using ranges::begin. + template + using __range_iter_t + = decltype(__detail::__ranges_begin(std::declval<_Tp&>())); + + } // namespace __detail + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 library concepts +#endif // _ITERATOR_CONCEPTS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/list.tcc b/resources/sources/avr-libstdcpp/include/bits/list.tcc new file mode 100644 index 000000000..ce9e983c5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/list.tcc @@ -0,0 +1,633 @@ +// List implementation (out of line) -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/list.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{list} + */ + +#ifndef _LIST_TCC +#define _LIST_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + void + _List_base<_Tp, _Alloc>:: + _M_clear() _GLIBCXX_NOEXCEPT + { + typedef _List_node<_Tp> _Node; + __detail::_List_node_base* __cur = _M_impl._M_node._M_next; + while (__cur != &_M_impl._M_node) + { + _Node* __tmp = static_cast<_Node*>(__cur); + __cur = __tmp->_M_next; + _Tp* __val = __tmp->_M_valptr(); +#if __cplusplus >= 201103L + _Node_alloc_traits::destroy(_M_get_Node_allocator(), __val); +#else + _Tp_alloc_type(_M_get_Node_allocator()).destroy(__val); +#endif + _M_put_node(__tmp); + } + } + +#if __cplusplus >= 201103L + template + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: + emplace(const_iterator __position, _Args&&... __args) + { + _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...); + __tmp->_M_hook(__position._M_const_cast()._M_node); + this->_M_inc_size(1); + return iterator(__tmp); + } +#endif + + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { + _Node* __tmp = _M_create_node(__x); + __tmp->_M_hook(__position._M_const_cast()._M_node); + this->_M_inc_size(1); + return iterator(__tmp); + } + +#if __cplusplus >= 201103L + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: + insert(const_iterator __position, size_type __n, const value_type& __x) + { + if (__n) + { + list __tmp(__n, __x, get_allocator()); + iterator __it = __tmp.begin(); + splice(__position, __tmp); + return __it; + } + return __position._M_const_cast(); + } + + template + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: + insert(const_iterator __position, _InputIterator __first, + _InputIterator __last) + { + list __tmp(__first, __last, get_allocator()); + if (!__tmp.empty()) + { + iterator __it = __tmp.begin(); + splice(__position, __tmp); + return __it; + } + return __position._M_const_cast(); + } +#endif + + template + typename list<_Tp, _Alloc>::iterator + list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + erase(const_iterator __position) noexcept +#else + erase(iterator __position) +#endif + { + iterator __ret = iterator(__position._M_node->_M_next); + _M_erase(__position._M_const_cast()); + return __ret; + } + + // Return a const_iterator indicating the position to start inserting or + // erasing elements (depending whether the list is growing or shrinking), + // and set __new_size to the number of new elements that must be appended. + // Equivalent to the following, but performed optimally: + // if (__new_size < size()) { + // __new_size = 0; + // return std::next(begin(), __new_size); + // } else { + // __newsize -= size(); + // return end(); + // } + template + typename list<_Tp, _Alloc>::const_iterator + list<_Tp, _Alloc>:: + _M_resize_pos(size_type& __new_size) const + { + const_iterator __i; +#if _GLIBCXX_USE_CXX11_ABI + const size_type __len = size(); + if (__new_size < __len) + { + if (__new_size <= __len / 2) + { + __i = begin(); + std::advance(__i, __new_size); + } + else + { + __i = end(); + ptrdiff_t __num_erase = __len - __new_size; + std::advance(__i, -__num_erase); + } + __new_size = 0; + return __i; + } + else + __i = end(); +#else + size_type __len = 0; + for (__i = begin(); __i != end() && __len < __new_size; ++__i, ++__len) + ; +#endif + __new_size -= __len; + return __i; + } + +#if __cplusplus >= 201103L + template + void + list<_Tp, _Alloc>:: + _M_default_append(size_type __n) + { + size_type __i = 0; + __try + { + for (; __i < __n; ++__i) + emplace_back(); + } + __catch(...) + { + for (; __i; --__i) + pop_back(); + __throw_exception_again; + } + } + + template + void + list<_Tp, _Alloc>:: + resize(size_type __new_size) + { + const_iterator __i = _M_resize_pos(__new_size); + if (__new_size) + _M_default_append(__new_size); + else + erase(__i, end()); + } + + template + void + list<_Tp, _Alloc>:: + resize(size_type __new_size, const value_type& __x) + { + const_iterator __i = _M_resize_pos(__new_size); + if (__new_size) + insert(end(), __new_size, __x); + else + erase(__i, end()); + } +#else + template + void + list<_Tp, _Alloc>:: + resize(size_type __new_size, value_type __x) + { + const_iterator __i = _M_resize_pos(__new_size); + if (__new_size) + insert(end(), __new_size, __x); + else + erase(__i._M_const_cast(), end()); + } +#endif + + template + list<_Tp, _Alloc>& + list<_Tp, _Alloc>:: + operator=(const list& __x) + { + if (this != std::__addressof(__x)) + { +#if __cplusplus >= 201103L + if (_Node_alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_get_Node_allocator(); + auto& __that_alloc = __x._M_get_Node_allocator(); + if (!_Node_alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // replacement allocator cannot free existing storage + clear(); + } + std::__alloc_on_copy(__this_alloc, __that_alloc); + } +#endif + _M_assign_dispatch(__x.begin(), __x.end(), __false_type()); + } + return *this; + } + + template + void + list<_Tp, _Alloc>:: + _M_fill_assign(size_type __n, const value_type& __val) + { + iterator __i = begin(); + for (; __i != end() && __n > 0; ++__i, --__n) + *__i = __val; + if (__n > 0) + insert(end(), __n, __val); + else + erase(__i, end()); + } + + template + template + void + list<_Tp, _Alloc>:: + _M_assign_dispatch(_InputIterator __first2, _InputIterator __last2, + __false_type) + { + iterator __first1 = begin(); + iterator __last1 = end(); + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + *__first1 = *__first2; + if (__first2 == __last2) + erase(__first1, __last1); + else + insert(__last1, __first2, __last2); + } + +#if __cplusplus > 201703L +# define _GLIBCXX20_ONLY(__expr) __expr +#else +# define _GLIBCXX20_ONLY(__expr) +#endif + + template + typename list<_Tp, _Alloc>::__remove_return_type + list<_Tp, _Alloc>:: + remove(const value_type& __value) + { + size_type __removed __attribute__((__unused__)) = 0; + iterator __first = begin(); + iterator __last = end(); + iterator __extra = __last; + while (__first != __last) + { + iterator __next = __first; + ++__next; + if (*__first == __value) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 526. Is it undefined if a function in the standard changes + // in parameters? + if (std::__addressof(*__first) != std::__addressof(__value)) + { + _M_erase(__first); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __extra = __first; + } + __first = __next; + } + if (__extra != __last) + { + _M_erase(__extra); + _GLIBCXX20_ONLY( __removed++ ); + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + typename list<_Tp, _Alloc>::__remove_return_type + list<_Tp, _Alloc>:: + unique() + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return _GLIBCXX20_ONLY( 0 ); + size_type __removed __attribute__((__unused__)) = 0; + iterator __next = __first; + while (++__next != __last) + { + if (*__first == *__next) + { + _M_erase(__next); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __first = __next; + __next = __first; + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + void + list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + merge(list&& __x) +#else + merge(list& __x) +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 300. list::merge() specification incomplete + if (this != std::__addressof(__x)) + { + _M_check_equal_allocators(__x); + + iterator __first1 = begin(); + iterator __last1 = end(); + iterator __first2 = __x.begin(); + iterator __last2 = __x.end(); + const size_t __orig_size = __x.size(); + __try { + while (__first1 != __last1 && __first2 != __last2) + if (*__first2 < *__first1) + { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); + + this->_M_inc_size(__x._M_get_size()); + __x._M_set_size(0); + } + __catch(...) + { + const size_t __dist = std::distance(__first2, __last2); + this->_M_inc_size(__orig_size - __dist); + __x._M_set_size(__dist); + __throw_exception_again; + } + } + } + + template + template + void + list<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + merge(list&& __x, _StrictWeakOrdering __comp) +#else + merge(list& __x, _StrictWeakOrdering __comp) +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 300. list::merge() specification incomplete + if (this != std::__addressof(__x)) + { + _M_check_equal_allocators(__x); + + iterator __first1 = begin(); + iterator __last1 = end(); + iterator __first2 = __x.begin(); + iterator __last2 = __x.end(); + const size_t __orig_size = __x.size(); + __try + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(*__first2, *__first1)) + { + iterator __next = __first2; + _M_transfer(__first1, __first2, ++__next); + __first2 = __next; + } + else + ++__first1; + if (__first2 != __last2) + _M_transfer(__last1, __first2, __last2); + + this->_M_inc_size(__x._M_get_size()); + __x._M_set_size(0); + } + __catch(...) + { + const size_t __dist = std::distance(__first2, __last2); + this->_M_inc_size(__orig_size - __dist); + __x._M_set_size(__dist); + __throw_exception_again; + } + } + } + + template + void + list<_Tp, _Alloc>:: + sort() + { + // Do nothing if the list has length 0 or 1. + if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node + && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) + { + list __carry; + list __tmp[64]; + list * __fill = __tmp; + list * __counter; + __try + { + do + { + __carry.splice(__carry.begin(), *this, begin()); + + for(__counter = __tmp; + __counter != __fill && !__counter->empty(); + ++__counter) + { + __counter->merge(__carry); + __carry.swap(*__counter); + } + __carry.swap(*__counter); + if (__counter == __fill) + ++__fill; + } + while ( !empty() ); + + for (__counter = __tmp + 1; __counter != __fill; ++__counter) + __counter->merge(*(__counter - 1)); + swap( *(__fill - 1) ); + } + __catch(...) + { + this->splice(this->end(), __carry); + for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i) + this->splice(this->end(), __tmp[__i]); + __throw_exception_again; + } + } + } + + template + template + typename list<_Tp, _Alloc>::__remove_return_type + list<_Tp, _Alloc>:: + remove_if(_Predicate __pred) + { + size_type __removed __attribute__((__unused__)) = 0; + iterator __first = begin(); + iterator __last = end(); + while (__first != __last) + { + iterator __next = __first; + ++__next; + if (__pred(*__first)) + { + _M_erase(__first); + _GLIBCXX20_ONLY( __removed++ ); + } + __first = __next; + } + return _GLIBCXX20_ONLY( __removed ); + } + + template + template + typename list<_Tp, _Alloc>::__remove_return_type + list<_Tp, _Alloc>:: + unique(_BinaryPredicate __binary_pred) + { + iterator __first = begin(); + iterator __last = end(); + if (__first == __last) + return _GLIBCXX20_ONLY(0); + size_type __removed __attribute__((__unused__)) = 0; + iterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(*__first, *__next)) + { + _M_erase(__next); + _GLIBCXX20_ONLY( __removed++ ); + } + else + __first = __next; + __next = __first; + } + return _GLIBCXX20_ONLY( __removed ); + } + +#undef _GLIBCXX20_ONLY + + template + template + void + list<_Tp, _Alloc>:: + sort(_StrictWeakOrdering __comp) + { + // Do nothing if the list has length 0 or 1. + if (this->_M_impl._M_node._M_next != &this->_M_impl._M_node + && this->_M_impl._M_node._M_next->_M_next != &this->_M_impl._M_node) + { + list __carry; + list __tmp[64]; + list * __fill = __tmp; + list * __counter; + __try + { + do + { + __carry.splice(__carry.begin(), *this, begin()); + + for(__counter = __tmp; + __counter != __fill && !__counter->empty(); + ++__counter) + { + __counter->merge(__carry, __comp); + __carry.swap(*__counter); + } + __carry.swap(*__counter); + if (__counter == __fill) + ++__fill; + } + while ( !empty() ); + + for (__counter = __tmp + 1; __counter != __fill; ++__counter) + __counter->merge(*(__counter - 1), __comp); + swap(*(__fill - 1)); + } + __catch(...) + { + this->splice(this->end(), __carry); + for (int __i = 0; __i < sizeof(__tmp)/sizeof(__tmp[0]); ++__i) + this->splice(this->end(), __tmp[__i]); + __throw_exception_again; + } + } + } + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _LIST_TCC */ + diff --git a/resources/sources/avr-libstdcpp/include/bits/mask_array.h b/resources/sources/avr-libstdcpp/include/bits/mask_array.h new file mode 100644 index 000000000..579cd59e5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/mask_array.h @@ -0,0 +1,213 @@ +// The template and inlines for the -*- C++ -*- mask_array class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/mask_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _MASK_ARRAY_H +#define _MASK_ARRAY_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Reference to selected subset of an array. + * + * A mask_array is a reference to the actual elements of an array specified + * by a bitmask in the form of an array of bool. The way to get a + * mask_array is to call operator[](valarray) on a valarray. The + * returned mask_array then permits carrying operations out on the + * referenced subset of elements in the original valarray. + * + * For example, if a mask_array is obtained using the array (false, true, + * false, true) as an argument, the mask array has two elements referring + * to array[1] and array[3] in the underlying array. + * + * @param Tp Element type. + */ + template + class mask_array + { + public: + typedef _Tp value_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 253. valarray helper functions are almost entirely useless + + /// Copy constructor. Both slices refer to the same underlying array. + mask_array (const mask_array&); + + /// Assignment operator. Assigns elements to corresponding elements + /// of @a a. + mask_array& operator=(const mask_array&); + + void operator=(const valarray<_Tp>&) const; + /// Multiply slice elements by corresponding elements of @a v. + void operator*=(const valarray<_Tp>&) const; + /// Divide slice elements by corresponding elements of @a v. + void operator/=(const valarray<_Tp>&) const; + /// Modulo slice elements by corresponding elements of @a v. + void operator%=(const valarray<_Tp>&) const; + /// Add corresponding elements of @a v to slice elements. + void operator+=(const valarray<_Tp>&) const; + /// Subtract corresponding elements of @a v from slice elements. + void operator-=(const valarray<_Tp>&) const; + /// Logical xor slice elements with corresponding elements of @a v. + void operator^=(const valarray<_Tp>&) const; + /// Logical and slice elements with corresponding elements of @a v. + void operator&=(const valarray<_Tp>&) const; + /// Logical or slice elements with corresponding elements of @a v. + void operator|=(const valarray<_Tp>&) const; + /// Left shift slice elements by corresponding elements of @a v. + void operator<<=(const valarray<_Tp>&) const; + /// Right shift slice elements by corresponding elements of @a v. + void operator>>=(const valarray<_Tp>&) const; + /// Assign all slice elements to @a t. + void operator=(const _Tp&) const; + + // ~mask_array (); + + template + void operator=(const _Expr<_Dom,_Tp>&) const; + template + void operator*=(const _Expr<_Dom,_Tp>&) const; + template + void operator/=(const _Expr<_Dom,_Tp>&) const; + template + void operator%=(const _Expr<_Dom,_Tp>&) const; + template + void operator+=(const _Expr<_Dom,_Tp>&) const; + template + void operator-=(const _Expr<_Dom,_Tp>&) const; + template + void operator^=(const _Expr<_Dom,_Tp>&) const; + template + void operator&=(const _Expr<_Dom,_Tp>&) const; + template + void operator|=(const _Expr<_Dom,_Tp>&) const; + template + void operator<<=(const _Expr<_Dom,_Tp>&) const; + template + void operator>>=(const _Expr<_Dom,_Tp>&) const; + + private: + mask_array(_Array<_Tp>, size_t, _Array); + friend class valarray<_Tp>; + + const size_t _M_sz; + const _Array _M_mask; + const _Array<_Tp> _M_array; + +#if __cplusplus < 201103L + // not implemented + mask_array(); +#else + public: + mask_array() = delete; +#endif + }; + + template + inline mask_array<_Tp>::mask_array(const mask_array<_Tp>& __a) + : _M_sz(__a._M_sz), _M_mask(__a._M_mask), _M_array(__a._M_array) {} + + template + inline + mask_array<_Tp>::mask_array(_Array<_Tp> __a, size_t __s, _Array __m) + : _M_sz(__s), _M_mask(__m), _M_array(__a) {} + + template + inline mask_array<_Tp>& + mask_array<_Tp>::operator=(const mask_array<_Tp>& __a) + { + std::__valarray_copy(__a._M_array, __a._M_mask, + _M_sz, _M_array, _M_mask); + return *this; + } + + template + inline void + mask_array<_Tp>::operator=(const _Tp& __t) const + { std::__valarray_fill(_M_array, _M_sz, _M_mask, __t); } + + template + inline void + mask_array<_Tp>::operator=(const valarray<_Tp>& __v) const + { std::__valarray_copy(_Array<_Tp>(__v), __v.size(), _M_array, _M_mask); } + + template + template + inline void + mask_array<_Tp>::operator=(const _Expr<_Ex, _Tp>& __e) const + { std::__valarray_copy(__e, __e.size(), _M_array, _M_mask); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(_Op, _Name) \ + template \ + inline void \ + mask_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ + { \ + _Array_augmented_##_Name(_M_array, _M_mask, \ + _Array<_Tp>(__v), __v.size()); \ + } \ + \ + template \ + template \ + inline void \ + mask_array<_Tp>::operator _Op##=(const _Expr<_Dom, _Tp>& __e) const\ + { \ + _Array_augmented_##_Name(_M_array, _M_mask, __e, __e.size()); \ + } + +_DEFINE_VALARRAY_OPERATOR(*, __multiplies) +_DEFINE_VALARRAY_OPERATOR(/, __divides) +_DEFINE_VALARRAY_OPERATOR(%, __modulus) +_DEFINE_VALARRAY_OPERATOR(+, __plus) +_DEFINE_VALARRAY_OPERATOR(-, __minus) +_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) +_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) +_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) +_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _MASK_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h b/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h new file mode 100644 index 000000000..af1a1c69c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/memoryfwd.h @@ -0,0 +1,82 @@ +// Forward declarations -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996-1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/memoryfwd.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _MEMORYFWD_H +#define _MEMORYFWD_H 1 + +#pragma GCC system_header + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup allocators Allocators + * @ingroup memory + * + * Classes encapsulating memory operations. + * + * @{ + */ + + template + class allocator; + +#if __cplusplus <= 201703L + template<> + class allocator; +#endif + +#if __cplusplus >= 201103L + /// Declare uses_allocator so it can be specialized in \ etc. + template + struct uses_allocator; +#endif + + /// @} group memory + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/move.h b/resources/sources/avr-libstdcpp/include/bits/move.h new file mode 100644 index 000000000..5a4dbdc82 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/move.h @@ -0,0 +1,224 @@ +// Move, forward and identity for C++11 + swap -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/move.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + */ + +#ifndef _MOVE_H +#define _MOVE_H 1 + +#include +#if __cplusplus < 201103L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Used, in C++03 mode too, by allocators, etc. + /** + * @brief Same as C++11 std::addressof + * @ingroup utilities + */ + template + inline _GLIBCXX_CONSTEXPR _Tp* + __addressof(_Tp& __r) _GLIBCXX_NOEXCEPT + { return __builtin_addressof(__r); } + +#if __cplusplus >= 201103L + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#include // Brings in std::declval too. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Forward an lvalue. + * @return The parameter cast to the specified type. + * + * This function is used to implement "perfect forwarding". + */ + template + constexpr _Tp&& + forward(typename std::remove_reference<_Tp>::type& __t) noexcept + { return static_cast<_Tp&&>(__t); } + + /** + * @brief Forward an rvalue. + * @return The parameter cast to the specified type. + * + * This function is used to implement "perfect forwarding". + */ + template + constexpr _Tp&& + forward(typename std::remove_reference<_Tp>::type&& __t) noexcept + { + static_assert(!std::is_lvalue_reference<_Tp>::value, "template argument" + " substituting _Tp is an lvalue reference type"); + return static_cast<_Tp&&>(__t); + } + + /** + * @brief Convert a value to an rvalue. + * @param __t A thing of arbitrary type. + * @return The parameter cast to an rvalue-reference to allow moving it. + */ + template + constexpr typename std::remove_reference<_Tp>::type&& + move(_Tp&& __t) noexcept + { return static_cast::type&&>(__t); } + + + template + struct __move_if_noexcept_cond + : public __and_<__not_>, + is_copy_constructible<_Tp>>::type { }; + + /** + * @brief Conditionally convert a value to an rvalue. + * @param __x A thing of arbitrary type. + * @return The parameter, possibly cast to an rvalue-reference. + * + * Same as std::move unless the type's move constructor could throw and the + * type is copyable, in which case an lvalue-reference is returned instead. + */ + template + constexpr typename + conditional<__move_if_noexcept_cond<_Tp>::value, const _Tp&, _Tp&&>::type + move_if_noexcept(_Tp& __x) noexcept + { return std::move(__x); } + + // declval, from type_traits. + +#if __cplusplus > 201402L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2296. std::addressof should be constexpr +# define __cpp_lib_addressof_constexpr 201603 +#endif + /** + * @brief Returns the actual address of the object or function + * referenced by r, even in the presence of an overloaded + * operator&. + * @param __r Reference to an object or function. + * @return The actual address. + */ + template + inline _GLIBCXX17_CONSTEXPR _Tp* + addressof(_Tp& __r) noexcept + { return std::__addressof(__r); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2598. addressof works on temporaries + template + const _Tp* addressof(const _Tp&&) = delete; + + // C++11 version of std::exchange for internal use. + template + _GLIBCXX20_CONSTEXPR + inline _Tp + __exchange(_Tp& __obj, _Up&& __new_val) + { + _Tp __old_val = std::move(__obj); + __obj = std::forward<_Up>(__new_val); + return __old_val; + } + + /// @} group utilities + +#define _GLIBCXX_MOVE(__val) std::move(__val) +#define _GLIBCXX_FORWARD(_Tp, __val) std::forward<_Tp>(__val) +#else +#define _GLIBCXX_MOVE(__val) (__val) +#define _GLIBCXX_FORWARD(_Tp, __val) (__val) +#endif + + /** + * @addtogroup utilities + * @{ + */ + + /** + * @brief Swaps two values. + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return Nothing. + */ + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus >= 201103L + typename enable_if<__and_<__not_<__is_tuple_like<_Tp>>, + is_move_constructible<_Tp>, + is_move_assignable<_Tp>>::value>::type +#else + void +#endif + swap(_Tp& __a, _Tp& __b) + _GLIBCXX_NOEXCEPT_IF(__and_, + is_nothrow_move_assignable<_Tp>>::value) + { +#if __cplusplus < 201103L + // concept requirements + __glibcxx_function_requires(_SGIAssignableConcept<_Tp>) +#endif + _Tp __tmp = _GLIBCXX_MOVE(__a); + __a = _GLIBCXX_MOVE(__b); + __b = _GLIBCXX_MOVE(__tmp); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 809. std::swap should be overloaded for array types. + /// Swap the contents of two arrays. + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus >= 201103L + typename enable_if<__is_swappable<_Tp>::value>::type +#else + void +#endif + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Tp>::value) + { + for (size_t __n = 0; __n < _Nm; ++__n) + swap(__a[__n], __b[__n]); + } + + /// @} group utilities +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _MOVE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/node_handle.h b/resources/sources/avr-libstdcpp/include/bits/node_handle.h new file mode 100644 index 000000000..cbf95f045 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/node_handle.h @@ -0,0 +1,299 @@ +// Node handles for containers -*- C++ -*- + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/node_handle.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. + * @headername{map,set,unordered_map,unordered_set} + */ + +#ifndef _NODE_HANDLE +#define _NODE_HANDLE 1 + +#pragma GCC system_header + +#if __cplusplus > 201402L +# define __cpp_lib_node_extract 201606 + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Base class for node handle types of maps and sets. + template + class _Node_handle_common + { + using _AllocTraits = allocator_traits<_NodeAlloc>; + + public: + using allocator_type = __alloc_rebind<_NodeAlloc, _Val>; + + allocator_type + get_allocator() const noexcept + { + __glibcxx_assert(!this->empty()); + return allocator_type(*_M_alloc); + } + + explicit operator bool() const noexcept { return _M_ptr != nullptr; } + + [[nodiscard]] bool empty() const noexcept { return _M_ptr == nullptr; } + + protected: + constexpr _Node_handle_common() noexcept : _M_ptr(), _M_alloc() {} + + ~_Node_handle_common() { _M_destroy(); } + + _Node_handle_common(_Node_handle_common&& __nh) noexcept + : _M_ptr(__nh._M_ptr), _M_alloc(std::move(__nh._M_alloc)) + { + __nh._M_ptr = nullptr; + __nh._M_alloc = nullopt; + } + + _Node_handle_common& + operator=(_Node_handle_common&& __nh) noexcept + { + _M_destroy(); + _M_ptr = __nh._M_ptr; + if constexpr (is_move_assignable_v<_NodeAlloc>) + { + if (_AllocTraits::propagate_on_container_move_assignment::value + || !this->_M_alloc) + this->_M_alloc = std::move(__nh._M_alloc); + else + { + __glibcxx_assert(this->_M_alloc == __nh._M_alloc); + } + } + else + { + __glibcxx_assert(_M_alloc); + } + __nh._M_ptr = nullptr; + __nh._M_alloc = nullopt; + return *this; + } + + _Node_handle_common(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _M_ptr(__ptr), _M_alloc(__alloc) { } + + void + _M_swap(_Node_handle_common& __nh) noexcept + { + using std::swap; + swap(_M_ptr, __nh._M_ptr); + if (_AllocTraits::propagate_on_container_swap::value + || !_M_alloc || !__nh._M_alloc) + _M_alloc.swap(__nh._M_alloc); + else + { + __glibcxx_assert(_M_alloc == __nh._M_alloc); + } + } + + private: + void + _M_destroy() noexcept + { + if (_M_ptr != nullptr) + { + allocator_type __alloc(*_M_alloc); + allocator_traits::destroy(__alloc, + _M_ptr->_M_valptr()); + _AllocTraits::deallocate(*_M_alloc, _M_ptr, 1); + } + } + + protected: + typename _AllocTraits::pointer _M_ptr; + private: + optional<_NodeAlloc> _M_alloc; + + template + friend class _Rb_tree; + }; + + /// Node handle type for maps. + template + class _Node_handle : public _Node_handle_common<_Value, _NodeAlloc> + { + public: + constexpr _Node_handle() noexcept = default; + ~_Node_handle() = default; + _Node_handle(_Node_handle&&) noexcept = default; + + _Node_handle& + operator=(_Node_handle&&) noexcept = default; + + using key_type = _Key; + using mapped_type = typename _Value::second_type; + + key_type& + key() const noexcept + { + __glibcxx_assert(!this->empty()); + return *_M_pkey; + } + + mapped_type& + mapped() const noexcept + { + __glibcxx_assert(!this->empty()); + return *_M_pmapped; + } + + void + swap(_Node_handle& __nh) noexcept + { + this->_M_swap(__nh); + using std::swap; + swap(_M_pkey, __nh._M_pkey); + swap(_M_pmapped, __nh._M_pmapped); + } + + friend void + swap(_Node_handle& __x, _Node_handle& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + private: + using _AllocTraits = allocator_traits<_NodeAlloc>; + + _Node_handle(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) + { + if (__ptr) + { + auto& __key = const_cast<_Key&>(__ptr->_M_valptr()->first); + _M_pkey = _S_pointer_to(__key); + _M_pmapped = _S_pointer_to(__ptr->_M_valptr()->second); + } + else + { + _M_pkey = nullptr; + _M_pmapped = nullptr; + } + } + + template + using __pointer + = __ptr_rebind>; + + __pointer<_Key> _M_pkey = nullptr; + __pointer _M_pmapped = nullptr; + + template + __pointer<_Tp> + _S_pointer_to(_Tp& __obj) + { return pointer_traits<__pointer<_Tp>>::pointer_to(__obj); } + + const key_type& + _M_key() const noexcept { return key(); } + + template + friend class _Rb_tree; + + template + friend class _Hashtable; + }; + + /// Node handle type for sets. + template + class _Node_handle<_Value, _Value, _NodeAlloc> + : public _Node_handle_common<_Value, _NodeAlloc> + { + public: + constexpr _Node_handle() noexcept = default; + ~_Node_handle() = default; + _Node_handle(_Node_handle&&) noexcept = default; + + _Node_handle& + operator=(_Node_handle&&) noexcept = default; + + using value_type = _Value; + + value_type& + value() const noexcept + { + __glibcxx_assert(!this->empty()); + return *this->_M_ptr->_M_valptr(); + } + + void + swap(_Node_handle& __nh) noexcept + { this->_M_swap(__nh); } + + friend void + swap(_Node_handle& __x, _Node_handle& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + private: + using _AllocTraits = allocator_traits<_NodeAlloc>; + + _Node_handle(typename _AllocTraits::pointer __ptr, + const _NodeAlloc& __alloc) + : _Node_handle_common<_Value, _NodeAlloc>(__ptr, __alloc) { } + + const value_type& + _M_key() const noexcept { return value(); } + + template + friend class _Rb_tree; + + template + friend class _Hashtable; + }; + + /// Return type of insert(node_handle&&) on unique maps/sets. + template + struct _Node_insert_return + { + _Iterator position = _Iterator(); + bool inserted = false; + _NodeHandle node; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h b/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h new file mode 100644 index 000000000..5e80907af --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/parse_numbers.h @@ -0,0 +1,294 @@ +// Components for compile-time parsing of numbers -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/parse_numbers.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{chrono} + */ + +#ifndef _GLIBCXX_PARSE_NUMBERS_H +#define _GLIBCXX_PARSE_NUMBERS_H 1 + +#pragma GCC system_header + +// From n3642.pdf except I added binary literals and digit separator '\''. + +#if __cplusplus >= 201402L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __parse_int +{ + template + struct _Digit; + + template + struct _Digit<_Base, '0'> : integral_constant + { + using __valid = true_type; + }; + + template + struct _Digit<_Base, '1'> : integral_constant + { + using __valid = true_type; + }; + + template + struct _Digit_impl : integral_constant + { + static_assert(_Base > _Val, "invalid digit"); + using __valid = true_type; + }; + + template + struct _Digit<_Base, '2'> : _Digit_impl<_Base, 2> + { }; + + template + struct _Digit<_Base, '3'> : _Digit_impl<_Base, 3> + { }; + + template + struct _Digit<_Base, '4'> : _Digit_impl<_Base, 4> + { }; + + template + struct _Digit<_Base, '5'> : _Digit_impl<_Base, 5> + { }; + + template + struct _Digit<_Base, '6'> : _Digit_impl<_Base, 6> + { }; + + template + struct _Digit<_Base, '7'> : _Digit_impl<_Base, 7> + { }; + + template + struct _Digit<_Base, '8'> : _Digit_impl<_Base, 8> + { }; + + template + struct _Digit<_Base, '9'> : _Digit_impl<_Base, 9> + { }; + + template + struct _Digit<_Base, 'a'> : _Digit_impl<_Base, 0xa> + { }; + + template + struct _Digit<_Base, 'A'> : _Digit_impl<_Base, 0xa> + { }; + + template + struct _Digit<_Base, 'b'> : _Digit_impl<_Base, 0xb> + { }; + + template + struct _Digit<_Base, 'B'> : _Digit_impl<_Base, 0xb> + { }; + + template + struct _Digit<_Base, 'c'> : _Digit_impl<_Base, 0xc> + { }; + + template + struct _Digit<_Base, 'C'> : _Digit_impl<_Base, 0xc> + { }; + + template + struct _Digit<_Base, 'd'> : _Digit_impl<_Base, 0xd> + { }; + + template + struct _Digit<_Base, 'D'> : _Digit_impl<_Base, 0xd> + { }; + + template + struct _Digit<_Base, 'e'> : _Digit_impl<_Base, 0xe> + { }; + + template + struct _Digit<_Base, 'E'> : _Digit_impl<_Base, 0xe> + { }; + + template + struct _Digit<_Base, 'f'> : _Digit_impl<_Base, 0xf> + { }; + + template + struct _Digit<_Base, 'F'> : _Digit_impl<_Base, 0xf> + { }; + + // Digit separator + template + struct _Digit<_Base, '\''> : integral_constant + { + using __valid = false_type; + }; + +//------------------------------------------------------------------------------ + + template + using __ull_constant = integral_constant; + + template + struct _Power_help + { + using __next = typename _Power_help<_Base, _Digs...>::type; + using __valid_digit = typename _Digit<_Base, _Dig>::__valid; + using type + = __ull_constant<__next::value * (__valid_digit{} ? _Base : 1ULL)>; + }; + + template + struct _Power_help<_Base, _Dig> + { + using __valid_digit = typename _Digit<_Base, _Dig>::__valid; + using type = __ull_constant<__valid_digit::value>; + }; + + template + struct _Power : _Power_help<_Base, _Digs...>::type + { }; + + template + struct _Power<_Base> : __ull_constant<0> + { }; + +//------------------------------------------------------------------------------ + + template + struct _Number_help + { + using __digit = _Digit<_Base, _Dig>; + using __valid_digit = typename __digit::__valid; + using __next = _Number_help<_Base, + __valid_digit::value ? _Pow / _Base : _Pow, + _Digs...>; + using type = __ull_constant<_Pow * __digit::value + __next::type::value>; + static_assert((type::value / _Pow) == __digit::value, + "integer literal does not fit in unsigned long long"); + }; + + // Skip past digit separators: + template + struct _Number_help<_Base, _Pow, '\'', _Dig, _Digs...> + : _Number_help<_Base, _Pow, _Dig, _Digs...> + { }; + + // Terminating case for recursion: + template + struct _Number_help<_Base, 1ULL, _Dig> + { + using type = __ull_constant<_Digit<_Base, _Dig>::value>; + }; + + template + struct _Number + : _Number_help<_Base, _Power<_Base, _Digs...>::value, _Digs...>::type + { }; + + template + struct _Number<_Base> + : __ull_constant<0> + { }; + +//------------------------------------------------------------------------------ + + template + struct _Parse_int; + + template + struct _Parse_int<'0', 'b', _Digs...> + : _Number<2U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'B', _Digs...> + : _Number<2U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'x', _Digs...> + : _Number<16U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', 'X', _Digs...> + : _Number<16U, _Digs...>::type + { }; + + template + struct _Parse_int<'0', _Digs...> + : _Number<8U, _Digs...>::type + { }; + + template + struct _Parse_int + : _Number<10U, _Digs...>::type + { }; + +} // namespace __parse_int + + +namespace __select_int +{ + template + struct _Select_int_base; + + template + struct _Select_int_base<_Val, _IntType, _Ints...> + : conditional_t<(_Val <= __gnu_cxx::__int_traits<_IntType>::__max), + integral_constant<_IntType, _Val>, + _Select_int_base<_Val, _Ints...>> + { }; + + template + struct _Select_int_base<_Val> + { }; + + template + using _Select_int = typename _Select_int_base< + __parse_int::_Parse_int<_Digs...>::value, + unsigned char, + unsigned short, + unsigned int, + unsigned long, + unsigned long long + >::type; + +} // namespace __select_int + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + +#endif // _GLIBCXX_PARSE_NUMBERS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/postypes.h b/resources/sources/avr-libstdcpp/include/bits/postypes.h new file mode 100644 index 000000000..718ff4462 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/postypes.h @@ -0,0 +1,253 @@ +// Position types -*- C++ -*- + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/postypes.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iosfwd} + */ + +// +// ISO C++ 14882: 27.4.1 - Types +// ISO C++ 14882: 27.4.3 - Template class fpos +// + +#ifndef _GLIBCXX_POSTYPES_H +#define _GLIBCXX_POSTYPES_H 1 + +#pragma GCC system_header + +#include // For mbstate_t + +// XXX If is really needed, make sure to define the macros +// before including it, in order not to break (and +// in C++11). Reconsider all this as soon as possible... +#if (defined(_GLIBCXX_HAVE_INT64_T) && !defined(_GLIBCXX_HAVE_INT64_T_LONG) \ + && !defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG)) + +#ifndef __STDC_LIMIT_MACROS +# define _UNDEF__STDC_LIMIT_MACROS +# define __STDC_LIMIT_MACROS +#endif +#ifndef __STDC_CONSTANT_MACROS +# define _UNDEF__STDC_CONSTANT_MACROS +# define __STDC_CONSTANT_MACROS +#endif +#include // For int64_t +#ifdef _UNDEF__STDC_LIMIT_MACROS +# undef __STDC_LIMIT_MACROS +# undef _UNDEF__STDC_LIMIT_MACROS +#endif +#ifdef _UNDEF__STDC_CONSTANT_MACROS +# undef __STDC_CONSTANT_MACROS +# undef _UNDEF__STDC_CONSTANT_MACROS +#endif + +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // The types streamoff, streampos and wstreampos and the class + // template fpos<> are described in clauses 21.1.2, 21.1.3, 27.1.2, + // 27.2, 27.4.1, 27.4.3 and D.6. Despite all this verbiage, the + // behaviour of these types is mostly implementation defined or + // unspecified. The behaviour in this implementation is as noted + // below. + + /** + * @brief Type used by fpos, char_traits, and char_traits. + * + * In clauses 21.1.3.1 and 27.4.1 streamoff is described as an + * implementation defined type. + * Note: In versions of GCC up to and including GCC 3.3, streamoff + * was typedef long. + */ +#ifdef _GLIBCXX_HAVE_INT64_T_LONG + typedef long streamoff; +#elif defined(_GLIBCXX_HAVE_INT64_T_LONG_LONG) + typedef long long streamoff; +#elif defined(_GLIBCXX_HAVE_INT64_T) + typedef int64_t streamoff; +#else + typedef long long streamoff; +#endif + + /// Integral type for I/O operation counts and buffer sizes. + typedef ptrdiff_t streamsize; // Signed integral type + + /** + * @brief Class representing stream positions. + * + * The standard places no requirements upon the template parameter StateT. + * In this implementation StateT must be DefaultConstructible, + * CopyConstructible and Assignable. The standard only requires that fpos + * should contain a member of type StateT. In this implementation it also + * contains an offset stored as a signed integer. + * + * @param StateT Type passed to and returned from state(). + */ + template + class fpos + { + private: + streamoff _M_off; + _StateT _M_state; + + public: + // The standard doesn't require that fpos objects can be default + // constructed. This implementation provides a default + // constructor that initializes the offset to 0 and default + // constructs the state. + fpos() + : _M_off(0), _M_state() { } + + // The standard requires that fpos objects can be constructed + // from streamoff objects using the constructor syntax, and + // fails to give any meaningful semantics. In this + // implementation implicit conversion is also allowed, and this + // constructor stores the streamoff as the offset and default + // constructs the state. + /// Construct position from offset. + fpos(streamoff __off) + : _M_off(__off), _M_state() { } + +#if __cplusplus >= 201103L + fpos(const fpos&) = default; + fpos& operator=(const fpos&) = default; + ~fpos() = default; +#endif + + /// Convert to streamoff. + operator streamoff() const { return _M_off; } + + /// Remember the value of @a st. + void + state(_StateT __st) + { _M_state = __st; } + + /// Return the last set value of @a st. + _StateT + state() const + { return _M_state; } + + // The standard requires that this operator must be defined, but + // gives no semantics. In this implementation it just adds its + // argument to the stored offset and returns *this. + /// Add offset to this position. + fpos& + operator+=(streamoff __off) + { + _M_off += __off; + return *this; + } + + // The standard requires that this operator must be defined, but + // gives no semantics. In this implementation it just subtracts + // its argument from the stored offset and returns *this. + /// Subtract offset from this position. + fpos& + operator-=(streamoff __off) + { + _M_off -= __off; + return *this; + } + + // The standard requires that this operator must be defined, but + // defines its semantics only in terms of operator-. In this + // implementation it constructs a copy of *this, adds the + // argument to that copy using operator+= and then returns the + // copy. + /// Add position and offset. + fpos + operator+(streamoff __off) const + { + fpos __pos(*this); + __pos += __off; + return __pos; + } + + // The standard requires that this operator must be defined, but + // defines its semantics only in terms of operator+. In this + // implementation it constructs a copy of *this, subtracts the + // argument from that copy using operator-= and then returns the + // copy. + /// Subtract offset from position. + fpos + operator-(streamoff __off) const + { + fpos __pos(*this); + __pos -= __off; + return __pos; + } + + // The standard requires that this operator must be defined, but + // defines its semantics only in terms of operator+. In this + // implementation it returns the difference between the offset + // stored in *this and in the argument. + /// Subtract position to return offset. + streamoff + operator-(const fpos& __other) const + { return _M_off - __other._M_off; } + }; + + // The standard only requires that operator== must be an + // equivalence relation. In this implementation two fpos + // objects belong to the same equivalence class if the contained + // offsets compare equal. + /// Test if equivalent to another position. + template + inline bool + operator==(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs) + { return streamoff(__lhs) == streamoff(__rhs); } + + template + inline bool + operator!=(const fpos<_StateT>& __lhs, const fpos<_StateT>& __rhs) + { return streamoff(__lhs) != streamoff(__rhs); } + + // Clauses 21.1.3.1 and 21.1.3.2 describe streampos and wstreampos + // as implementation defined types, but clause 27.2 requires that + // they must both be typedefs for fpos + /// File position for char streams. + typedef fpos streampos; + /// File position for wchar_t streams. + typedef fpos wstreampos; + +#ifdef _GLIBCXX_USE_CHAR8_T + /// File position for char8_t streams. + typedef fpos u8streampos; +#endif + +#if __cplusplus >= 201103L + /// File position for char16_t streams. + typedef fpos u16streampos; + /// File position for char32_t streams. + typedef fpos u32streampos; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h b/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h new file mode 100644 index 000000000..7ac9a467d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/predefined_ops.h @@ -0,0 +1,405 @@ +// Default predicates for internal use -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file predefined_ops.h + * This is an internal header file, included by other library headers. + * You should not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _GLIBCXX_PREDEFINED_OPS_H +#define _GLIBCXX_PREDEFINED_OPS_H 1 + +namespace __gnu_cxx +{ +namespace __ops +{ + struct _Iter_less_iter + { + template + _GLIBCXX14_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) const + { return *__it1 < *__it2; } + }; + + _GLIBCXX14_CONSTEXPR + inline _Iter_less_iter + __iter_less_iter() + { return _Iter_less_iter(); } + + struct _Iter_less_val + { +#if __cplusplus >= 201103L + constexpr _Iter_less_val() = default; +#else + _Iter_less_val() { } +#endif + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_less_val(_Iter_less_iter) { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) const + { return *__it < __val; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_less_val + __iter_less_val() + { return _Iter_less_val(); } + + _GLIBCXX20_CONSTEXPR + inline _Iter_less_val + __iter_comp_val(_Iter_less_iter) + { return _Iter_less_val(); } + + struct _Val_less_iter + { +#if __cplusplus >= 201103L + constexpr _Val_less_iter() = default; +#else + _Val_less_iter() { } +#endif + + _GLIBCXX20_CONSTEXPR + explicit + _Val_less_iter(_Iter_less_iter) { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Value& __val, _Iterator __it) const + { return __val < *__it; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Val_less_iter + __val_less_iter() + { return _Val_less_iter(); } + + _GLIBCXX20_CONSTEXPR + inline _Val_less_iter + __val_comp_iter(_Iter_less_iter) + { return _Val_less_iter(); } + + struct _Iter_equal_to_iter + { + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) const + { return *__it1 == *__it2; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_iter + __iter_equal_to_iter() + { return _Iter_equal_to_iter(); } + + struct _Iter_equal_to_val + { + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) const + { return *__it == __val; } + }; + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_val + __iter_equal_to_val() + { return _Iter_equal_to_val(); } + + _GLIBCXX20_CONSTEXPR + inline _Iter_equal_to_val + __iter_comp_val(_Iter_equal_to_iter) + { return _Iter_equal_to_val(); } + + template + struct _Iter_comp_iter + { + _Compare _M_comp; + + explicit _GLIBCXX14_CONSTEXPR + _Iter_comp_iter(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + template + _GLIBCXX14_CONSTEXPR + bool + operator()(_Iterator1 __it1, _Iterator2 __it2) + { return bool(_M_comp(*__it1, *__it2)); } + }; + + template + _GLIBCXX14_CONSTEXPR + inline _Iter_comp_iter<_Compare> + __iter_comp_iter(_Compare __comp) + { return _Iter_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Iter_comp_val + { + _Compare _M_comp; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(const _Iter_comp_iter<_Compare>& __comp) + : _M_comp(__comp._M_comp) + { } + +#if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR + explicit + _Iter_comp_val(_Iter_comp_iter<_Compare>&& __comp) + : _M_comp(std::move(__comp._M_comp)) + { } +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it, _Value& __val) + { return bool(_M_comp(*__it, __val)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_val<_Compare> + __iter_comp_val(_Compare __comp) + { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_val<_Compare> + __iter_comp_val(_Iter_comp_iter<_Compare> __comp) + { return _Iter_comp_val<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Val_comp_iter + { + _Compare _M_comp; + + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(_Compare __comp) + : _M_comp(_GLIBCXX_MOVE(__comp)) + { } + + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(const _Iter_comp_iter<_Compare>& __comp) + : _M_comp(__comp._M_comp) + { } + +#if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR + explicit + _Val_comp_iter(_Iter_comp_iter<_Compare>&& __comp) + : _M_comp(std::move(__comp._M_comp)) + { } +#endif + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Value& __val, _Iterator __it) + { return bool(_M_comp(__val, *__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Val_comp_iter<_Compare> + __val_comp_iter(_Compare __comp) + { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + _GLIBCXX20_CONSTEXPR + inline _Val_comp_iter<_Compare> + __val_comp_iter(_Iter_comp_iter<_Compare> __comp) + { return _Val_comp_iter<_Compare>(_GLIBCXX_MOVE(__comp)); } + + template + struct _Iter_equals_val + { + _Value& _M_value; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_equals_val(_Value& __value) + : _M_value(__value) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return *__it == _M_value; } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_equals_val<_Value> + __iter_equals_val(_Value& __val) + { return _Iter_equals_val<_Value>(__val); } + + template + struct _Iter_equals_iter + { + _Iterator1 _M_it1; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_equals_iter(_Iterator1 __it1) + : _M_it1(__it1) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator2 __it2) + { return *__it2 == *_M_it1; } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_equals_iter<_Iterator> + __iter_comp_iter(_Iter_equal_to_iter, _Iterator __it) + { return _Iter_equals_iter<_Iterator>(__it); } + + template + struct _Iter_pred + { + _Predicate _M_pred; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_pred(_Predicate __pred) + : _M_pred(_GLIBCXX_MOVE(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return bool(_M_pred(*__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_pred<_Predicate> + __pred_iter(_Predicate __pred) + { return _Iter_pred<_Predicate>(_GLIBCXX_MOVE(__pred)); } + + template + struct _Iter_comp_to_val + { + _Compare _M_comp; + _Value& _M_value; + + _GLIBCXX20_CONSTEXPR + _Iter_comp_to_val(_Compare __comp, _Value& __value) + : _M_comp(_GLIBCXX_MOVE(__comp)), _M_value(__value) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return bool(_M_comp(*__it, _M_value)); } + }; + + template + _Iter_comp_to_val<_Compare, _Value> + _GLIBCXX20_CONSTEXPR + __iter_comp_val(_Compare __comp, _Value &__val) + { + return _Iter_comp_to_val<_Compare, _Value>(_GLIBCXX_MOVE(__comp), __val); + } + + template + struct _Iter_comp_to_iter + { + _Compare _M_comp; + _Iterator1 _M_it1; + + _GLIBCXX20_CONSTEXPR + _Iter_comp_to_iter(_Compare __comp, _Iterator1 __it1) + : _M_comp(_GLIBCXX_MOVE(__comp)), _M_it1(__it1) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator2 __it2) + { return bool(_M_comp(*__it2, *_M_it1)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_comp_to_iter<_Compare, _Iterator> + __iter_comp_iter(_Iter_comp_iter<_Compare> __comp, _Iterator __it) + { + return _Iter_comp_to_iter<_Compare, _Iterator>( + _GLIBCXX_MOVE(__comp._M_comp), __it); + } + + template + struct _Iter_negate + { + _Predicate _M_pred; + + _GLIBCXX20_CONSTEXPR + explicit + _Iter_negate(_Predicate __pred) + : _M_pred(_GLIBCXX_MOVE(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + bool + operator()(_Iterator __it) + { return !bool(_M_pred(*__it)); } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _Iter_negate<_Predicate> + __negate(_Iter_pred<_Predicate> __pred) + { return _Iter_negate<_Predicate>(_GLIBCXX_MOVE(__pred._M_pred)); } + +} // namespace __ops +} // namespace __gnu_cxx + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h b/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h new file mode 100644 index 000000000..38f694df5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/ptr_traits.h @@ -0,0 +1,211 @@ +// Pointer Traits -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ptr_traits.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _PTR_TRAITS_H +#define _PTR_TRAITS_H 1 + +#if __cplusplus >= 201103L + +#include + +#if __cplusplus > 201703L +#define __cpp_lib_constexpr_memory 201811L +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + class __undefined; + + // Given Template return T, otherwise invalid. + template + struct __get_first_arg + { using type = __undefined; }; + + template class _Template, typename _Tp, + typename... _Types> + struct __get_first_arg<_Template<_Tp, _Types...>> + { using type = _Tp; }; + + template + using __get_first_arg_t = typename __get_first_arg<_Tp>::type; + + // Given Template and U return Template, otherwise invalid. + template + struct __replace_first_arg + { }; + + template class _Template, typename _Up, + typename _Tp, typename... _Types> + struct __replace_first_arg<_Template<_Tp, _Types...>, _Up> + { using type = _Template<_Up, _Types...>; }; + + template + using __replace_first_arg_t = typename __replace_first_arg<_Tp, _Up>::type; + + template + using __make_not_void + = typename conditional::value, __undefined, _Tp>::type; + + /** + * @brief Uniform interface to all pointer-like types + * @ingroup pointer_abstractions + */ + template + struct pointer_traits + { + private: + template + using __element_type = typename _Tp::element_type; + + template + using __difference_type = typename _Tp::difference_type; + + template + struct __rebind : __replace_first_arg<_Tp, _Up> { }; + + template + struct __rebind<_Tp, _Up, __void_t>> + { using type = typename _Tp::template rebind<_Up>; }; + + public: + /// The pointer type. + using pointer = _Ptr; + + /// The type pointed to. + using element_type + = __detected_or_t<__get_first_arg_t<_Ptr>, __element_type, _Ptr>; + + /// The type used to represent the difference between two pointers. + using difference_type + = __detected_or_t; + + /// A pointer to a different type. + template + using rebind = typename __rebind<_Ptr, _Up>::type; + + static _Ptr + pointer_to(__make_not_void& __e) + { return _Ptr::pointer_to(__e); } + + static_assert(!is_same::value, + "pointer type defines element_type or is like SomePointer"); + }; + + /** + * @brief Partial specialization for built-in pointers. + * @ingroup pointer_abstractions + */ + template + struct pointer_traits<_Tp*> + { + /// The pointer type + typedef _Tp* pointer; + /// The type pointed to + typedef _Tp element_type; + /// Type used to represent the difference between two pointers + typedef ptrdiff_t difference_type; + + template + using rebind = _Up*; + + /** + * @brief Obtain a pointer to an object + * @param __r A reference to an object of type @c element_type + * @return @c addressof(__r) + */ + static _GLIBCXX20_CONSTEXPR pointer + pointer_to(__make_not_void& __r) noexcept + { return std::addressof(__r); } + }; + + /// Convenience alias for rebinding pointers. + template + using __ptr_rebind = typename pointer_traits<_Ptr>::template rebind<_Tp>; + + template + constexpr _Tp* + __to_address(_Tp* __ptr) noexcept + { + static_assert(!std::is_function<_Tp>::value, "not a function pointer"); + return __ptr; + } + +#if __cplusplus <= 201703L + template + constexpr typename std::pointer_traits<_Ptr>::element_type* + __to_address(const _Ptr& __ptr) + { return std::__to_address(__ptr.operator->()); } +#else + template + constexpr auto + __to_address(const _Ptr& __ptr) noexcept + -> decltype(std::pointer_traits<_Ptr>::to_address(__ptr)) + { return std::pointer_traits<_Ptr>::to_address(__ptr); } + + template + constexpr auto + __to_address(const _Ptr& __ptr, _None...) noexcept + { + return std::__to_address(__ptr.operator->()); + } + +#define __cpp_lib_to_address 201711L + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __ptr A pointer to an object + * @return @c __ptr + * @ingroup pointer_abstractions + */ + template + constexpr _Tp* + to_address(_Tp* __ptr) noexcept + { return std::__to_address(__ptr); } + + /** + * @brief Obtain address referenced by a pointer to an object + * @param __ptr A pointer to an object + * @return @c pointer_traits<_Ptr>::to_address(__ptr) if that expression is + well-formed, otherwise @c to_address(__ptr.operator->()) + * @ingroup pointer_abstractions + */ + template + constexpr auto + to_address(const _Ptr& __ptr) noexcept + { return std::__to_address(__ptr); } +#endif // C++2a + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/random.h b/resources/sources/avr-libstdcpp/include/bits/random.h new file mode 100644 index 000000000..0b0877394 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/random.h @@ -0,0 +1,5183 @@ +// random number generation -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** + * @file bits/random.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{random} + */ + +#ifndef _RANDOM_H +#define _RANDOM_H 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // [26.4] Random number generation + + /** + * @defgroup random Random Number Generation + * @ingroup numerics + * + * A facility for generating random numbers on selected distributions. + * @{ + */ + + // std::uniform_random_bit_generator is defined in + + /** + * @brief A function template for converting the output of a (integral) + * uniform random number generator to a floatng point result in the range + * [0-1). + */ + template + _RealType + generate_canonical(_UniformRandomNumberGenerator& __g); + + /* + * Implementation-space details. + */ + namespace __detail + { + template + (std::numeric_limits<_UIntType>::digits)> + struct _Shift + { static const _UIntType __value = 0; }; + + template + struct _Shift<_UIntType, __w, true> + { static const _UIntType __value = _UIntType(1) << __w; }; + + template + struct _Select_uint_least_t + { + static_assert(__which < 0, /* needs to be dependent */ + "sorry, would be too much trouble for a slow result"); + }; + + template + struct _Select_uint_least_t<__s, 4> + { typedef unsigned int type; }; + + template + struct _Select_uint_least_t<__s, 3> + { typedef unsigned long type; }; + + template + struct _Select_uint_least_t<__s, 2> + { typedef unsigned long long type; }; + +#ifdef _GLIBCXX_USE_INT128 + template + struct _Select_uint_least_t<__s, 1> + { typedef unsigned __int128 type; }; +#endif + + // Assume a != 0, a < m, c < m, x < m. + template= __m - 1), + bool __schrage_ok = __m % __a < __m / __a> + struct _Mod + { + typedef typename _Select_uint_least_t::type _Tp2; + static _Tp + __calc(_Tp __x) + { return static_cast<_Tp>((_Tp2(__a) * __x + __c) % __m); } + }; + + // Schrage. + template + struct _Mod<_Tp, __m, __a, __c, false, true> + { + static _Tp + __calc(_Tp __x); + }; + + // Special cases: + // - for m == 2^n or m == 0, unsigned integer overflow is safe. + // - a * (m - 1) + c fits in _Tp, there is no overflow. + template + struct _Mod<_Tp, __m, __a, __c, true, __s> + { + static _Tp + __calc(_Tp __x) + { + _Tp __res = __a * __x + __c; + if (__m) + __res %= __m; + return __res; + } + }; + + template + inline _Tp + __mod(_Tp __x) + { return _Mod<_Tp, __m, __a, __c>::__calc(__x); } + + /* + * An adaptor class for converting the output of any Generator into + * the input for a specific Distribution. + */ + template + struct _Adaptor + { + static_assert(std::is_floating_point<_DInputType>::value, + "template argument must be a floating point type"); + + public: + _Adaptor(_Engine& __g) + : _M_g(__g) { } + + _DInputType + min() const + { return _DInputType(0); } + + _DInputType + max() const + { return _DInputType(1); } + + /* + * Converts a value generated by the adapted random number generator + * into a value in the input domain for the dependent random number + * distribution. + */ + _DInputType + operator()() + { + return std::generate_canonical<_DInputType, + std::numeric_limits<_DInputType>::digits, + _Engine>(_M_g); + } + + private: + _Engine& _M_g; + }; + + template + using __seed_seq_generate_t = decltype( + std::declval<_Sseq&>().generate(std::declval(), + std::declval())); + + // Detect whether _Sseq is a valid seed sequence for + // a random number engine _Engine with result type _Res. + template> + using __is_seed_seq = __and_< + __not_, _Engine>>, + is_unsigned, + __not_> + >; + + } // namespace __detail + + /** + * @addtogroup random_generators Random Number Generators + * @ingroup random + * + * These classes define objects which provide random or pseudorandom + * numbers, either from a discrete or a continuous interval. The + * random number generator supplied as a part of this library are + * all uniform random number generators which provide a sequence of + * random number uniformly distributed over their range. + * + * A number generator is a function object with an operator() that + * takes zero arguments and returns a number. + * + * A compliant random number generator must satisfy the following + * requirements. + * + *
Random Number Generator Requirements
To be documented.
+ * + * @{ + */ + + /** + * @brief A model of a linear congruential random number generator. + * + * A random number generator that produces pseudorandom numbers via + * linear function: + * @f[ + * x_{i+1}\leftarrow(ax_{i} + c) \bmod m + * @f] + * + * The template parameter @p _UIntType must be an unsigned integral type + * large enough to store values up to (__m-1). If the template parameter + * @p __m is 0, the modulus @p __m used is + * std::numeric_limits<_UIntType>::max() plus 1. Otherwise, the template + * parameters @p __a and @p __c must be less than @p __m. + * + * The size of the state is @f$1@f$. + */ + template + class linear_congruential_engine + { + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); + static_assert(__m == 0u || (__a < __m && __c < __m), + "template argument substituting __m out of bounds"); + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, linear_congruential_engine, _UIntType>::value>::type; + + public: + /** The type of the generated random value. */ + typedef _UIntType result_type; + + /** The multiplier. */ + static constexpr result_type multiplier = __a; + /** An increment. */ + static constexpr result_type increment = __c; + /** The modulus. */ + static constexpr result_type modulus = __m; + static constexpr result_type default_seed = 1u; + + /** + * @brief Constructs a %linear_congruential_engine random number + * generator engine with seed 1. + */ + linear_congruential_engine() : linear_congruential_engine(default_seed) + { } + + /** + * @brief Constructs a %linear_congruential_engine random number + * generator engine with seed @p __s. The default seed value + * is 1. + * + * @param __s The initial seed value. + */ + explicit + linear_congruential_engine(result_type __s) + { seed(__s); } + + /** + * @brief Constructs a %linear_congruential_engine random number + * generator engine seeded from the seed sequence @p __q. + * + * @param __q the seed sequence. + */ + template> + explicit + linear_congruential_engine(_Sseq& __q) + { seed(__q); } + + /** + * @brief Reseeds the %linear_congruential_engine random number generator + * engine sequence to the seed @p __s. + * + * @param __s The new seed. + */ + void + seed(result_type __s = default_seed); + + /** + * @brief Reseeds the %linear_congruential_engine random number generator + * engine + * sequence using values from the seed sequence @p __q. + * + * @param __q the seed sequence. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q); + + /** + * @brief Gets the smallest possible value in the output range. + * + * The minimum depends on the @p __c parameter: if it is zero, the + * minimum generated must be > 0, otherwise 0 is allowed. + */ + static constexpr result_type + min() + { return __c == 0u ? 1u : 0u; } + + /** + * @brief Gets the largest possible value in the output range. + */ + static constexpr result_type + max() + { return __m - 1u; } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * @brief Gets the next random number in the sequence. + */ + result_type + operator()() + { + _M_x = __detail::__mod<_UIntType, __m, __a, __c>(_M_x); + return _M_x; + } + + /** + * @brief Compares two linear congruential random number generator + * objects of the same type for equality. + * + * @param __lhs A linear congruential random number generator object. + * @param __rhs Another linear congruential random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const linear_congruential_engine& __lhs, + const linear_congruential_engine& __rhs) + { return __lhs._M_x == __rhs._M_x; } + + private: + _UIntType _M_x; + }; + + /** + * @brief Compares two linear congruential random number generator + * objects of the same type for inequality. + * + * @param __lhs A linear congruential random number generator object. + * @param __rhs Another linear congruential random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::linear_congruential_engine<_UIntType, __a, + __c, __m>& __lhs, + const std::linear_congruential_engine<_UIntType, __a, + __c, __m>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * A generalized feedback shift register discrete random number generator. + * + * This algorithm avoids multiplication and division and is designed to be + * friendly to a pipelined architecture. If the parameters are chosen + * correctly, this generator will produce numbers with a very long period and + * fairly good apparent entropy, although still not cryptographically strong. + * + * The best way to use this generator is with the predefined mt19937 class. + * + * This algorithm was originally invented by Makoto Matsumoto and + * Takuji Nishimura. + * + * @tparam __w Word size, the number of bits in each element of + * the state vector. + * @tparam __n The degree of recursion. + * @tparam __m The period parameter. + * @tparam __r The separation point bit index. + * @tparam __a The last row of the twist matrix. + * @tparam __u The first right-shift tempering matrix parameter. + * @tparam __d The first right-shift tempering matrix mask. + * @tparam __s The first left-shift tempering matrix parameter. + * @tparam __b The first left-shift tempering matrix mask. + * @tparam __t The second left-shift tempering matrix parameter. + * @tparam __c The second left-shift tempering matrix mask. + * @tparam __l The second right-shift tempering matrix parameter. + * @tparam __f Initialization multiplier. + */ + template + class mersenne_twister_engine + { + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); + static_assert(1u <= __m && __m <= __n, + "template argument substituting __m out of bounds"); + static_assert(__r <= __w, "template argument substituting " + "__r out of bound"); + static_assert(__u <= __w, "template argument substituting " + "__u out of bound"); + static_assert(__s <= __w, "template argument substituting " + "__s out of bound"); + static_assert(__t <= __w, "template argument substituting " + "__t out of bound"); + static_assert(__l <= __w, "template argument substituting " + "__l out of bound"); + static_assert(__w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bound"); + static_assert(__a <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __a out of bound"); + static_assert(__b <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __b out of bound"); + static_assert(__c <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __c out of bound"); + static_assert(__d <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __d out of bound"); + static_assert(__f <= (__detail::_Shift<_UIntType, __w>::__value - 1), + "template argument substituting __f out of bound"); + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, mersenne_twister_engine, _UIntType>::value>::type; + + public: + /** The type of the generated random value. */ + typedef _UIntType result_type; + + // parameter values + static constexpr size_t word_size = __w; + static constexpr size_t state_size = __n; + static constexpr size_t shift_size = __m; + static constexpr size_t mask_bits = __r; + static constexpr result_type xor_mask = __a; + static constexpr size_t tempering_u = __u; + static constexpr result_type tempering_d = __d; + static constexpr size_t tempering_s = __s; + static constexpr result_type tempering_b = __b; + static constexpr size_t tempering_t = __t; + static constexpr result_type tempering_c = __c; + static constexpr size_t tempering_l = __l; + static constexpr result_type initialization_multiplier = __f; + static constexpr result_type default_seed = 5489u; + + // constructors and member functions + + mersenne_twister_engine() : mersenne_twister_engine(default_seed) { } + + explicit + mersenne_twister_engine(result_type __sd) + { seed(__sd); } + + /** + * @brief Constructs a %mersenne_twister_engine random number generator + * engine seeded from the seed sequence @p __q. + * + * @param __q the seed sequence. + */ + template> + explicit + mersenne_twister_engine(_Sseq& __q) + { seed(__q); } + + void + seed(result_type __sd = default_seed); + + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q); + + /** + * @brief Gets the smallest possible value in the output range. + */ + static constexpr result_type + min() + { return 0; } + + /** + * @brief Gets the largest possible value in the output range. + */ + static constexpr result_type + max() + { return __detail::_Shift<_UIntType, __w>::__value - 1; } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z); + + result_type + operator()(); + + /** + * @brief Compares two % mersenne_twister_engine random number generator + * objects of the same type for equality. + * + * @param __lhs A % mersenne_twister_engine random number generator + * object. + * @param __rhs Another % mersenne_twister_engine random number + * generator object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const mersenne_twister_engine& __lhs, + const mersenne_twister_engine& __rhs) + { return (std::equal(__lhs._M_x, __lhs._M_x + state_size, __rhs._M_x) + && __lhs._M_p == __rhs._M_p); } + + private: + void _M_gen_rand(); + + _UIntType _M_x[state_size]; + size_t _M_p; + }; + + /** + * @brief Compares two % mersenne_twister_engine random number generator + * objects of the same type for inequality. + * + * @param __lhs A % mersenne_twister_engine random number generator + * object. + * @param __rhs Another % mersenne_twister_engine random number + * generator object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::mersenne_twister_engine<_UIntType, __w, __n, __m, + __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __lhs, + const std::mersenne_twister_engine<_UIntType, __w, __n, __m, + __r, __a, __u, __d, __s, __b, __t, __c, __l, __f>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * @brief The Marsaglia-Zaman generator. + * + * This is a model of a Generalized Fibonacci discrete random number + * generator, sometimes referred to as the SWC generator. + * + * A discrete random number generator that produces pseudorandom + * numbers using: + * @f[ + * x_{i}\leftarrow(x_{i - s} - x_{i - r} - carry_{i-1}) \bmod m + * @f] + * + * The size of the state is @f$r@f$ + * and the maximum period of the generator is @f$(m^r - m^s - 1)@f$. + */ + template + class subtract_with_carry_engine + { + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); + static_assert(0u < __s && __s < __r, + "0 < s < r"); + static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bounds"); + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, subtract_with_carry_engine, _UIntType>::value>::type; + + public: + /** The type of the generated random value. */ + typedef _UIntType result_type; + + // parameter values + static constexpr size_t word_size = __w; + static constexpr size_t short_lag = __s; + static constexpr size_t long_lag = __r; + static constexpr result_type default_seed = 19780503u; + + subtract_with_carry_engine() : subtract_with_carry_engine(default_seed) + { } + + /** + * @brief Constructs an explicitly seeded %subtract_with_carry_engine + * random number generator. + */ + explicit + subtract_with_carry_engine(result_type __sd) + { seed(__sd); } + + /** + * @brief Constructs a %subtract_with_carry_engine random number engine + * seeded from the seed sequence @p __q. + * + * @param __q the seed sequence. + */ + template> + explicit + subtract_with_carry_engine(_Sseq& __q) + { seed(__q); } + + /** + * @brief Seeds the initial state @f$x_0@f$ of the random number + * generator. + * + * N1688[4.19] modifies this as follows. If @p __value == 0, + * sets value to 19780503. In any case, with a linear + * congruential generator lcg(i) having parameters @f$ m_{lcg} = + * 2147483563, a_{lcg} = 40014, c_{lcg} = 0, and lcg(0) = value + * @f$, sets @f$ x_{-r} \dots x_{-1} @f$ to @f$ lcg(1) \bmod m + * \dots lcg(r) \bmod m @f$ respectively. If @f$ x_{-1} = 0 @f$ + * set carry to 1, otherwise sets carry to 0. + */ + void + seed(result_type __sd = default_seed); + + /** + * @brief Seeds the initial state @f$x_0@f$ of the + * % subtract_with_carry_engine random number generator. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q); + + /** + * @brief Gets the inclusive minimum value of the range of random + * integers returned by this generator. + */ + static constexpr result_type + min() + { return 0; } + + /** + * @brief Gets the inclusive maximum value of the range of random + * integers returned by this generator. + */ + static constexpr result_type + max() + { return __detail::_Shift<_UIntType, __w>::__value - 1; } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * @brief Gets the next random number in the sequence. + */ + result_type + operator()(); + + /** + * @brief Compares two % subtract_with_carry_engine random number + * generator objects of the same type for equality. + * + * @param __lhs A % subtract_with_carry_engine random number generator + * object. + * @param __rhs Another % subtract_with_carry_engine random number + * generator object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const subtract_with_carry_engine& __lhs, + const subtract_with_carry_engine& __rhs) + { return (std::equal(__lhs._M_x, __lhs._M_x + long_lag, __rhs._M_x) + && __lhs._M_carry == __rhs._M_carry + && __lhs._M_p == __rhs._M_p); } + + private: + /// The state of the generator. This is a ring buffer. + _UIntType _M_x[long_lag]; + _UIntType _M_carry; ///< The carry + size_t _M_p; ///< Current index of x(i - r). + }; + + /** + * @brief Compares two % subtract_with_carry_engine random number + * generator objects of the same type for inequality. + * + * @param __lhs A % subtract_with_carry_engine random number generator + * object. + * @param __rhs Another % subtract_with_carry_engine random number + * generator object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::subtract_with_carry_engine<_UIntType, __w, + __s, __r>& __lhs, + const std::subtract_with_carry_engine<_UIntType, __w, + __s, __r>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * Produces random numbers from some base engine by discarding blocks of + * data. + * + * 0 <= @p __r <= @p __p + */ + template + class discard_block_engine + { + static_assert(1 <= __r && __r <= __p, + "template argument substituting __r out of bounds"); + + public: + /** The type of the generated random value. */ + typedef typename _RandomNumberEngine::result_type result_type; + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, discard_block_engine, result_type>::value>::type; + + // parameter values + static constexpr size_t block_size = __p; + static constexpr size_t used_block = __r; + + /** + * @brief Constructs a default %discard_block_engine engine. + * + * The underlying engine is default constructed as well. + */ + discard_block_engine() + : _M_b(), _M_n(0) { } + + /** + * @brief Copy constructs a %discard_block_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + discard_block_engine(const _RandomNumberEngine& __rng) + : _M_b(__rng), _M_n(0) { } + + /** + * @brief Move constructs a %discard_block_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + discard_block_engine(_RandomNumberEngine&& __rng) + : _M_b(std::move(__rng)), _M_n(0) { } + + /** + * @brief Seed constructs a %discard_block_engine engine. + * + * Constructs the underlying generator engine seeded with @p __s. + * @param __s A seed value for the base class engine. + */ + explicit + discard_block_engine(result_type __s) + : _M_b(__s), _M_n(0) { } + + /** + * @brief Generator construct a %discard_block_engine engine. + * + * @param __q A seed sequence. + */ + template> + explicit + discard_block_engine(_Sseq& __q) + : _M_b(__q), _M_n(0) + { } + + /** + * @brief Reseeds the %discard_block_engine object with the default + * seed for the underlying base class generator engine. + */ + void + seed() + { + _M_b.seed(); + _M_n = 0; + } + + /** + * @brief Reseeds the %discard_block_engine object with the default + * seed for the underlying base class generator engine. + */ + void + seed(result_type __s) + { + _M_b.seed(__s); + _M_n = 0; + } + + /** + * @brief Reseeds the %discard_block_engine object with the given seed + * sequence. + * @param __q A seed generator function. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q) + { + _M_b.seed(__q); + _M_n = 0; + } + + /** + * @brief Gets a const reference to the underlying generator engine + * object. + */ + const _RandomNumberEngine& + base() const noexcept + { return _M_b; } + + /** + * @brief Gets the minimum value in the generated random number range. + */ + static constexpr result_type + min() + { return _RandomNumberEngine::min(); } + + /** + * @brief Gets the maximum value in the generated random number range. + */ + static constexpr result_type + max() + { return _RandomNumberEngine::max(); } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * @brief Gets the next value in the generated random number sequence. + */ + result_type + operator()(); + + /** + * @brief Compares two %discard_block_engine random number generator + * objects of the same type for equality. + * + * @param __lhs A %discard_block_engine random number generator object. + * @param __rhs Another %discard_block_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const discard_block_engine& __lhs, + const discard_block_engine& __rhs) + { return __lhs._M_b == __rhs._M_b && __lhs._M_n == __rhs._M_n; } + + private: + _RandomNumberEngine _M_b; + size_t _M_n; + }; + + /** + * @brief Compares two %discard_block_engine random number generator + * objects of the same type for inequality. + * + * @param __lhs A %discard_block_engine random number generator object. + * @param __rhs Another %discard_block_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::discard_block_engine<_RandomNumberEngine, __p, + __r>& __lhs, + const std::discard_block_engine<_RandomNumberEngine, __p, + __r>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * Produces random numbers by combining random numbers from some base + * engine to produce random numbers with a specifies number of bits @p __w. + */ + template + class independent_bits_engine + { + static_assert(std::is_unsigned<_UIntType>::value, + "result_type must be an unsigned integral type"); + static_assert(0u < __w && __w <= std::numeric_limits<_UIntType>::digits, + "template argument substituting __w out of bounds"); + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, independent_bits_engine, _UIntType>::value>::type; + + public: + /** The type of the generated random value. */ + typedef _UIntType result_type; + + /** + * @brief Constructs a default %independent_bits_engine engine. + * + * The underlying engine is default constructed as well. + */ + independent_bits_engine() + : _M_b() { } + + /** + * @brief Copy constructs a %independent_bits_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + independent_bits_engine(const _RandomNumberEngine& __rng) + : _M_b(__rng) { } + + /** + * @brief Move constructs a %independent_bits_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + independent_bits_engine(_RandomNumberEngine&& __rng) + : _M_b(std::move(__rng)) { } + + /** + * @brief Seed constructs a %independent_bits_engine engine. + * + * Constructs the underlying generator engine seeded with @p __s. + * @param __s A seed value for the base class engine. + */ + explicit + independent_bits_engine(result_type __s) + : _M_b(__s) { } + + /** + * @brief Generator construct a %independent_bits_engine engine. + * + * @param __q A seed sequence. + */ + template> + explicit + independent_bits_engine(_Sseq& __q) + : _M_b(__q) + { } + + /** + * @brief Reseeds the %independent_bits_engine object with the default + * seed for the underlying base class generator engine. + */ + void + seed() + { _M_b.seed(); } + + /** + * @brief Reseeds the %independent_bits_engine object with the default + * seed for the underlying base class generator engine. + */ + void + seed(result_type __s) + { _M_b.seed(__s); } + + /** + * @brief Reseeds the %independent_bits_engine object with the given + * seed sequence. + * @param __q A seed generator function. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q) + { _M_b.seed(__q); } + + /** + * @brief Gets a const reference to the underlying generator engine + * object. + */ + const _RandomNumberEngine& + base() const noexcept + { return _M_b; } + + /** + * @brief Gets the minimum value in the generated random number range. + */ + static constexpr result_type + min() + { return 0U; } + + /** + * @brief Gets the maximum value in the generated random number range. + */ + static constexpr result_type + max() + { return __detail::_Shift<_UIntType, __w>::__value - 1; } + + /** + * @brief Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * @brief Gets the next value in the generated random number sequence. + */ + result_type + operator()(); + + /** + * @brief Compares two %independent_bits_engine random number generator + * objects of the same type for equality. + * + * @param __lhs A %independent_bits_engine random number generator + * object. + * @param __rhs Another %independent_bits_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const independent_bits_engine& __lhs, + const independent_bits_engine& __rhs) + { return __lhs._M_b == __rhs._M_b; } + + private: + _RandomNumberEngine _M_b; + }; + + /** + * @brief Compares two %independent_bits_engine random number generator + * objects of the same type for inequality. + * + * @param __lhs A %independent_bits_engine random number generator + * object. + * @param __rhs Another %independent_bits_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::independent_bits_engine<_RandomNumberEngine, __w, + _UIntType>& __lhs, + const std::independent_bits_engine<_RandomNumberEngine, __w, + _UIntType>& __rhs) + { return !(__lhs == __rhs); } + + + + /** + * @brief Produces random numbers by combining random numbers from some + * base engine to produce random numbers with a specifies number of bits + * @p __k. + */ + template + class shuffle_order_engine + { + static_assert(1u <= __k, "template argument substituting " + "__k out of bound"); + + public: + /** The type of the generated random value. */ + typedef typename _RandomNumberEngine::result_type result_type; + + template + using _If_seed_seq = typename enable_if<__detail::__is_seed_seq< + _Sseq, shuffle_order_engine, result_type>::value>::type; + + static constexpr size_t table_size = __k; + + /** + * @brief Constructs a default %shuffle_order_engine engine. + * + * The underlying engine is default constructed as well. + */ + shuffle_order_engine() + : _M_b() + { _M_initialize(); } + + /** + * @brief Copy constructs a %shuffle_order_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + shuffle_order_engine(const _RandomNumberEngine& __rng) + : _M_b(__rng) + { _M_initialize(); } + + /** + * @brief Move constructs a %shuffle_order_engine engine. + * + * Copies an existing base class random number generator. + * @param __rng An existing (base class) engine object. + */ + explicit + shuffle_order_engine(_RandomNumberEngine&& __rng) + : _M_b(std::move(__rng)) + { _M_initialize(); } + + /** + * @brief Seed constructs a %shuffle_order_engine engine. + * + * Constructs the underlying generator engine seeded with @p __s. + * @param __s A seed value for the base class engine. + */ + explicit + shuffle_order_engine(result_type __s) + : _M_b(__s) + { _M_initialize(); } + + /** + * @brief Generator construct a %shuffle_order_engine engine. + * + * @param __q A seed sequence. + */ + template> + explicit + shuffle_order_engine(_Sseq& __q) + : _M_b(__q) + { _M_initialize(); } + + /** + * @brief Reseeds the %shuffle_order_engine object with the default seed + for the underlying base class generator engine. + */ + void + seed() + { + _M_b.seed(); + _M_initialize(); + } + + /** + * @brief Reseeds the %shuffle_order_engine object with the default seed + * for the underlying base class generator engine. + */ + void + seed(result_type __s) + { + _M_b.seed(__s); + _M_initialize(); + } + + /** + * @brief Reseeds the %shuffle_order_engine object with the given seed + * sequence. + * @param __q A seed generator function. + */ + template + _If_seed_seq<_Sseq> + seed(_Sseq& __q) + { + _M_b.seed(__q); + _M_initialize(); + } + + /** + * Gets a const reference to the underlying generator engine object. + */ + const _RandomNumberEngine& + base() const noexcept + { return _M_b; } + + /** + * Gets the minimum value in the generated random number range. + */ + static constexpr result_type + min() + { return _RandomNumberEngine::min(); } + + /** + * Gets the maximum value in the generated random number range. + */ + static constexpr result_type + max() + { return _RandomNumberEngine::max(); } + + /** + * Discard a sequence of random numbers. + */ + void + discard(unsigned long long __z) + { + for (; __z != 0ULL; --__z) + (*this)(); + } + + /** + * Gets the next value in the generated random number sequence. + */ + result_type + operator()(); + + /** + * Compares two %shuffle_order_engine random number generator objects + * of the same type for equality. + * + * @param __lhs A %shuffle_order_engine random number generator object. + * @param __rhs Another %shuffle_order_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be equal, false otherwise. + */ + friend bool + operator==(const shuffle_order_engine& __lhs, + const shuffle_order_engine& __rhs) + { return (__lhs._M_b == __rhs._M_b + && std::equal(__lhs._M_v, __lhs._M_v + __k, __rhs._M_v) + && __lhs._M_y == __rhs._M_y); } + + + private: + void _M_initialize() + { + for (size_t __i = 0; __i < __k; ++__i) + _M_v[__i] = _M_b(); + _M_y = _M_b(); + } + + _RandomNumberEngine _M_b; + result_type _M_v[__k]; + result_type _M_y; + }; + + /** + * Compares two %shuffle_order_engine random number generator objects + * of the same type for inequality. + * + * @param __lhs A %shuffle_order_engine random number generator object. + * @param __rhs Another %shuffle_order_engine random number generator + * object. + * + * @returns true if the infinite sequences of generated values + * would be different, false otherwise. + */ + template + inline bool + operator!=(const std::shuffle_order_engine<_RandomNumberEngine, + __k>& __lhs, + const std::shuffle_order_engine<_RandomNumberEngine, + __k>& __rhs) + { return !(__lhs == __rhs); } + + + /** + * The classic Minimum Standard rand0 of Lewis, Goodman, and Miller. + */ + typedef linear_congruential_engine + minstd_rand0; + + /** + * An alternative LCR (Lehmer Generator function). + */ + typedef linear_congruential_engine + minstd_rand; + + /** + * The classic Mersenne Twister. + * + * Reference: + * M. Matsumoto and T. Nishimura, Mersenne Twister: A 623-Dimensionally + * Equidistributed Uniform Pseudo-Random Number Generator, ACM Transactions + * on Modeling and Computer Simulation, Vol. 8, No. 1, January 1998, pp 3-30. + */ + typedef mersenne_twister_engine< + uint_fast32_t, + 32, 624, 397, 31, + 0x9908b0dfUL, 11, + 0xffffffffUL, 7, + 0x9d2c5680UL, 15, + 0xefc60000UL, 18, 1812433253UL> mt19937; + + /** + * An alternative Mersenne Twister. + */ + typedef mersenne_twister_engine< + uint_fast64_t, + 64, 312, 156, 31, + 0xb5026f5aa96619e9ULL, 29, + 0x5555555555555555ULL, 17, + 0x71d67fffeda60000ULL, 37, + 0xfff7eee000000000ULL, 43, + 6364136223846793005ULL> mt19937_64; + + typedef subtract_with_carry_engine + ranlux24_base; + + typedef subtract_with_carry_engine + ranlux48_base; + + typedef discard_block_engine ranlux24; + + typedef discard_block_engine ranlux48; + + typedef shuffle_order_engine knuth_b; + + typedef minstd_rand0 default_random_engine; + + /* @} */ // group random_generators + + /** + * @addtogroup random_distributions Random Number Distributions + * @ingroup random + * @{ + */ + + /** + * @addtogroup random_distributions_uniform Uniform Distributions + * @ingroup random_distributions + * @{ + */ + + // std::uniform_int_distribution is defined in + + /** + * @brief Return true if two uniform integer distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::uniform_int_distribution<_IntType>& __d1, + const std::uniform_int_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief Uniform continuous distribution for random numbers. + * + * A continuous random distribution on the range [min, max) with equal + * probability throughout the range. The URNG should be real-valued and + * deliver number in the range [0, 1). + */ + template + class uniform_real_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef uniform_real_distribution<_RealType> distribution_type; + + param_type() : param_type(0) { } + + explicit + param_type(_RealType __a, _RealType __b = _RealType(1)) + : _M_a(__a), _M_b(__b) + { + __glibcxx_assert(_M_a <= _M_b); + } + + result_type + a() const + { return _M_a; } + + result_type + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_a; + _RealType _M_b; + }; + + public: + /** + * @brief Constructs a uniform_real_distribution object. + * + * The lower bound is set to 0.0 and the upper bound to 1.0 + */ + uniform_real_distribution() : uniform_real_distribution(0.0) { } + + /** + * @brief Constructs a uniform_real_distribution object. + * + * @param __a [IN] The lower bound of the distribution. + * @param __b [IN] The upper bound of the distribution. + */ + explicit + uniform_real_distribution(_RealType __a, _RealType __b = _RealType(1)) + : _M_param(__a, __b) + { } + + explicit + uniform_real_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for the uniform real distribution. + */ + void + reset() { } + + result_type + a() const + { return _M_param.a(); } + + result_type + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the inclusive lower bound of the distribution range. + */ + result_type + min() const + { return this->a(); } + + /** + * @brief Returns the inclusive upper bound of the distribution range. + */ + result_type + max() const + { return this->b(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + return (__aurng() * (__p.b() - __p.a())) + __p.a(); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two uniform real distributions have + * the same parameters. + */ + friend bool + operator==(const uniform_real_distribution& __d1, + const uniform_real_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two uniform real distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::uniform_real_distribution<_IntType>& __d1, + const std::uniform_real_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + /* @} */ // group random_distributions_uniform + + /** + * @addtogroup random_distributions_normal Normal Distributions + * @ingroup random_distributions + * @{ + */ + + /** + * @brief A normal continuous distribution for random numbers. + * + * The formula for the normal probability density function is + * @f[ + * p(x|\mu,\sigma) = \frac{1}{\sigma \sqrt{2 \pi}} + * e^{- \frac{{x - \mu}^ {2}}{2 \sigma ^ {2}} } + * @f] + */ + template + class normal_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef normal_distribution<_RealType> distribution_type; + + param_type() : param_type(0.0) { } + + explicit + param_type(_RealType __mean, _RealType __stddev = _RealType(1)) + : _M_mean(__mean), _M_stddev(__stddev) + { + __glibcxx_assert(_M_stddev > _RealType(0)); + } + + _RealType + mean() const + { return _M_mean; } + + _RealType + stddev() const + { return _M_stddev; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return (__p1._M_mean == __p2._M_mean + && __p1._M_stddev == __p2._M_stddev); } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_mean; + _RealType _M_stddev; + }; + + public: + normal_distribution() : normal_distribution(0.0) { } + + /** + * Constructs a normal distribution with parameters @f$mean@f$ and + * standard deviation. + */ + explicit + normal_distribution(result_type __mean, + result_type __stddev = result_type(1)) + : _M_param(__mean, __stddev), _M_saved_available(false) + { } + + explicit + normal_distribution(const param_type& __p) + : _M_param(__p), _M_saved_available(false) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_saved_available = false; } + + /** + * @brief Returns the mean of the distribution. + */ + _RealType + mean() const + { return _M_param.mean(); } + + /** + * @brief Returns the standard deviation of the distribution. + */ + _RealType + stddev() const + { return _M_param.stddev(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::lowest(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two normal distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + template + friend bool + operator==(const std::normal_distribution<_RealType1>& __d1, + const std::normal_distribution<_RealType1>& __d2); + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + result_type _M_saved; + bool _M_saved_available; + }; + + /** + * @brief Return true if two normal distributions are different. + */ + template + inline bool + operator!=(const std::normal_distribution<_RealType>& __d1, + const std::normal_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A lognormal_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f[ + * p(x|m,s) = \frac{1}{sx\sqrt{2\pi}} + * \exp{-\frac{(\ln{x} - m)^2}{2s^2}} + * @f] + */ + template + class lognormal_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef lognormal_distribution<_RealType> distribution_type; + + param_type() : param_type(0.0) { } + + explicit + param_type(_RealType __m, _RealType __s = _RealType(1)) + : _M_m(__m), _M_s(__s) + { } + + _RealType + m() const + { return _M_m; } + + _RealType + s() const + { return _M_s; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_m == __p2._M_m && __p1._M_s == __p2._M_s; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_m; + _RealType _M_s; + }; + + lognormal_distribution() : lognormal_distribution(0.0) { } + + explicit + lognormal_distribution(_RealType __m, _RealType __s = _RealType(1)) + : _M_param(__m, __s), _M_nd() + { } + + explicit + lognormal_distribution(const param_type& __p) + : _M_param(__p), _M_nd() + { } + + /** + * Resets the distribution state. + */ + void + reset() + { _M_nd.reset(); } + + /** + * + */ + _RealType + m() const + { return _M_param.m(); } + + _RealType + s() const + { return _M_param.s(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { return std::exp(__p.s() * _M_nd(__urng) + __p.m()); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two lognormal distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + friend bool + operator==(const lognormal_distribution& __d1, + const lognormal_distribution& __d2) + { return (__d1._M_param == __d2._M_param + && __d1._M_nd == __d2._M_nd); } + + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::normal_distribution _M_nd; + }; + + /** + * @brief Return true if two lognormal distributions are different. + */ + template + inline bool + operator!=(const std::lognormal_distribution<_RealType>& __d1, + const std::lognormal_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A gamma continuous distribution for random numbers. + * + * The formula for the gamma probability density function is: + * @f[ + * p(x|\alpha,\beta) = \frac{1}{\beta\Gamma(\alpha)} + * (x/\beta)^{\alpha - 1} e^{-x/\beta} + * @f] + */ + template + class gamma_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef gamma_distribution<_RealType> distribution_type; + friend class gamma_distribution<_RealType>; + + param_type() : param_type(1.0) { } + + explicit + param_type(_RealType __alpha_val, _RealType __beta_val = _RealType(1)) + : _M_alpha(__alpha_val), _M_beta(__beta_val) + { + __glibcxx_assert(_M_alpha > _RealType(0)); + _M_initialize(); + } + + _RealType + alpha() const + { return _M_alpha; } + + _RealType + beta() const + { return _M_beta; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return (__p1._M_alpha == __p2._M_alpha + && __p1._M_beta == __p2._M_beta); } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + _RealType _M_alpha; + _RealType _M_beta; + + _RealType _M_malpha, _M_a2; + }; + + public: + /** + * @brief Constructs a gamma distribution with parameters 1 and 1. + */ + gamma_distribution() : gamma_distribution(1.0) { } + + /** + * @brief Constructs a gamma distribution with parameters + * @f$\alpha@f$ and @f$\beta@f$. + */ + explicit + gamma_distribution(_RealType __alpha_val, + _RealType __beta_val = _RealType(1)) + : _M_param(__alpha_val, __beta_val), _M_nd() + { } + + explicit + gamma_distribution(const param_type& __p) + : _M_param(__p), _M_nd() + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_nd.reset(); } + + /** + * @brief Returns the @f$\alpha@f$ of the distribution. + */ + _RealType + alpha() const + { return _M_param.alpha(); } + + /** + * @brief Returns the @f$\beta@f$ of the distribution. + */ + _RealType + beta() const + { return _M_param.beta(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two gamma distributions have the same + * parameters and the sequences that would be generated + * are equal. + */ + friend bool + operator==(const gamma_distribution& __d1, + const gamma_distribution& __d2) + { return (__d1._M_param == __d2._M_param + && __d1._M_nd == __d2._M_nd); } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::normal_distribution _M_nd; + }; + + /** + * @brief Return true if two gamma distributions are different. + */ + template + inline bool + operator!=(const std::gamma_distribution<_RealType>& __d1, + const std::gamma_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A chi_squared_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f$p(x|n) = \frac{x^{(n/2) - 1}e^{-x/2}}{\Gamma(n/2) 2^{n/2}}@f$ + */ + template + class chi_squared_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef chi_squared_distribution<_RealType> distribution_type; + + param_type() : param_type(1) { } + + explicit + param_type(_RealType __n) + : _M_n(__n) + { } + + _RealType + n() const + { return _M_n; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_n == __p2._M_n; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_n; + }; + + chi_squared_distribution() : chi_squared_distribution(1) { } + + explicit + chi_squared_distribution(_RealType __n) + : _M_param(__n), _M_gd(__n / 2) + { } + + explicit + chi_squared_distribution(const param_type& __p) + : _M_param(__p), _M_gd(__p.n() / 2) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_gd.reset(); } + + /** + * + */ + _RealType + n() const + { return _M_param.n(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { + _M_param = __param; + typedef typename std::gamma_distribution::param_type + param_type; + _M_gd.param(param_type{__param.n() / 2}); + } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return 2 * _M_gd(__urng); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + return 2 * _M_gd(__urng, param_type(__p.n() / 2)); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { typename std::gamma_distribution::param_type + __p2(__p.n() / 2); + this->__generate_impl(__f, __t, __urng, __p2); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { typename std::gamma_distribution::param_type + __p2(__p.n() / 2); + this->__generate_impl(__f, __t, __urng, __p2); } + + /** + * @brief Return true if two Chi-squared distributions have + * the same parameters and the sequences that would be + * generated are equal. + */ + friend bool + operator==(const chi_squared_distribution& __d1, + const chi_squared_distribution& __d2) + { return __d1._M_param == __d2._M_param && __d1._M_gd == __d2._M_gd; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng); + + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const typename + std::gamma_distribution::param_type& __p); + + param_type _M_param; + + std::gamma_distribution _M_gd; + }; + + /** + * @brief Return true if two Chi-squared distributions are different. + */ + template + inline bool + operator!=(const std::chi_squared_distribution<_RealType>& __d1, + const std::chi_squared_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A cauchy_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f$p(x|a,b) = (\pi b (1 + (\frac{x-a}{b})^2))^{-1}@f$ + */ + template + class cauchy_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef cauchy_distribution<_RealType> distribution_type; + + param_type() : param_type(0) { } + + explicit + param_type(_RealType __a, _RealType __b = _RealType(1)) + : _M_a(__a), _M_b(__b) + { } + + _RealType + a() const + { return _M_a; } + + _RealType + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_a; + _RealType _M_b; + }; + + cauchy_distribution() : cauchy_distribution(0.0) { } + + explicit + cauchy_distribution(_RealType __a, _RealType __b = 1.0) + : _M_param(__a, __b) + { } + + explicit + cauchy_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * + */ + _RealType + a() const + { return _M_param.a(); } + + _RealType + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::lowest(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Cauchy distributions have + * the same parameters. + */ + friend bool + operator==(const cauchy_distribution& __d1, + const cauchy_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two Cauchy distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::cauchy_distribution<_RealType>& __d1, + const std::cauchy_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + + /** + * @brief A fisher_f_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f[ + * p(x|m,n) = \frac{\Gamma((m+n)/2)}{\Gamma(m/2)\Gamma(n/2)} + * (\frac{m}{n})^{m/2} x^{(m/2)-1} + * (1 + \frac{mx}{n})^{-(m+n)/2} + * @f] + */ + template + class fisher_f_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef fisher_f_distribution<_RealType> distribution_type; + + param_type() : param_type(1) { } + + explicit + param_type(_RealType __m, _RealType __n = _RealType(1)) + : _M_m(__m), _M_n(__n) + { } + + _RealType + m() const + { return _M_m; } + + _RealType + n() const + { return _M_n; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_m == __p2._M_m && __p1._M_n == __p2._M_n; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_m; + _RealType _M_n; + }; + + fisher_f_distribution() : fisher_f_distribution(1.0) { } + + explicit + fisher_f_distribution(_RealType __m, + _RealType __n = _RealType(1)) + : _M_param(__m, __n), _M_gd_x(__m / 2), _M_gd_y(__n / 2) + { } + + explicit + fisher_f_distribution(const param_type& __p) + : _M_param(__p), _M_gd_x(__p.m() / 2), _M_gd_y(__p.n() / 2) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { + _M_gd_x.reset(); + _M_gd_y.reset(); + } + + /** + * + */ + _RealType + m() const + { return _M_param.m(); } + + _RealType + n() const + { return _M_param.n(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return (_M_gd_x(__urng) * n()) / (_M_gd_y(__urng) * m()); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + return ((_M_gd_x(__urng, param_type(__p.m() / 2)) * n()) + / (_M_gd_y(__urng, param_type(__p.n() / 2)) * m())); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Fisher f distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + friend bool + operator==(const fisher_f_distribution& __d1, + const fisher_f_distribution& __d2) + { return (__d1._M_param == __d2._M_param + && __d1._M_gd_x == __d2._M_gd_x + && __d1._M_gd_y == __d2._M_gd_y); } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng); + + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::gamma_distribution _M_gd_x, _M_gd_y; + }; + + /** + * @brief Return true if two Fisher f distributions are different. + */ + template + inline bool + operator!=(const std::fisher_f_distribution<_RealType>& __d1, + const std::fisher_f_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + /** + * @brief A student_t_distribution random number distribution. + * + * The formula for the normal probability mass function is: + * @f[ + * p(x|n) = \frac{1}{\sqrt(n\pi)} \frac{\Gamma((n+1)/2)}{\Gamma(n/2)} + * (1 + \frac{x^2}{n}) ^{-(n+1)/2} + * @f] + */ + template + class student_t_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef student_t_distribution<_RealType> distribution_type; + + param_type() : param_type(1) { } + + explicit + param_type(_RealType __n) + : _M_n(__n) + { } + + _RealType + n() const + { return _M_n; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_n == __p2._M_n; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_n; + }; + + student_t_distribution() : student_t_distribution(1.0) { } + + explicit + student_t_distribution(_RealType __n) + : _M_param(__n), _M_nd(), _M_gd(__n / 2, 2) + { } + + explicit + student_t_distribution(const param_type& __p) + : _M_param(__p), _M_nd(), _M_gd(__p.n() / 2, 2) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { + _M_nd.reset(); + _M_gd.reset(); + } + + /** + * + */ + _RealType + n() const + { return _M_param.n(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::lowest(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return _M_nd(__urng) * std::sqrt(n() / _M_gd(__urng)); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + + const result_type __g = _M_gd(__urng, param_type(__p.n() / 2, 2)); + return _M_nd(__urng) * std::sqrt(__p.n() / __g); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Student t distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + friend bool + operator==(const student_t_distribution& __d1, + const student_t_distribution& __d2) + { return (__d1._M_param == __d2._M_param + && __d1._M_nd == __d2._M_nd && __d1._M_gd == __d2._M_gd); } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng); + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::normal_distribution _M_nd; + std::gamma_distribution _M_gd; + }; + + /** + * @brief Return true if two Student t distributions are different. + */ + template + inline bool + operator!=(const std::student_t_distribution<_RealType>& __d1, + const std::student_t_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /* @} */ // group random_distributions_normal + + /** + * @addtogroup random_distributions_bernoulli Bernoulli Distributions + * @ingroup random_distributions + * @{ + */ + + /** + * @brief A Bernoulli random number distribution. + * + * Generates a sequence of true and false values with likelihood @f$p@f$ + * that true will come up and @f$(1 - p)@f$ that false will appear. + */ + class bernoulli_distribution + { + public: + /** The type of the range of the distribution. */ + typedef bool result_type; + + /** Parameter type. */ + struct param_type + { + typedef bernoulli_distribution distribution_type; + + param_type() : param_type(0.5) { } + + explicit + param_type(double __p) + : _M_p(__p) + { + __glibcxx_assert((_M_p >= 0.0) && (_M_p <= 1.0)); + } + + double + p() const + { return _M_p; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_p == __p2._M_p; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + double _M_p; + }; + + public: + /** + * @brief Constructs a Bernoulli distribution with likelihood 0.5. + */ + bernoulli_distribution() : bernoulli_distribution(0.5) { } + + /** + * @brief Constructs a Bernoulli distribution with likelihood @p p. + * + * @param __p [IN] The likelihood of a true result being returned. + * Must be in the interval @f$[0, 1]@f$. + */ + explicit + bernoulli_distribution(double __p) + : _M_param(__p) + { } + + explicit + bernoulli_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for a Bernoulli distribution. + */ + void + reset() { } + + /** + * @brief Returns the @p p parameter of the distribution. + */ + double + p() const + { return _M_param.p(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::min(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + if ((__aurng() - __aurng.min()) + < __p.p() * (__aurng.max() - __aurng.min())) + return true; + return false; + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Bernoulli distributions have + * the same parameters. + */ + friend bool + operator==(const bernoulli_distribution& __d1, + const bernoulli_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two Bernoulli distributions have + * different parameters. + */ + inline bool + operator!=(const std::bernoulli_distribution& __d1, + const std::bernoulli_distribution& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A discrete binomial random number distribution. + * + * The formula for the binomial probability density function is + * @f$p(i|t,p) = \binom{t}{i} p^i (1 - p)^{t - i}@f$ where @f$t@f$ + * and @f$p@f$ are the parameters of the distribution. + */ + template + class binomial_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef binomial_distribution<_IntType> distribution_type; + friend class binomial_distribution<_IntType>; + + param_type() : param_type(1) { } + + explicit + param_type(_IntType __t, double __p = 0.5) + : _M_t(__t), _M_p(__p) + { + __glibcxx_assert((_M_t >= _IntType(0)) + && (_M_p >= 0.0) + && (_M_p <= 1.0)); + _M_initialize(); + } + + _IntType + t() const + { return _M_t; } + + double + p() const + { return _M_p; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_t == __p2._M_t && __p1._M_p == __p2._M_p; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + _IntType _M_t; + double _M_p; + + double _M_q; +#if _GLIBCXX_USE_C99_MATH_TR1 + double _M_d1, _M_d2, _M_s1, _M_s2, _M_c, + _M_a1, _M_a123, _M_s, _M_lf, _M_lp1p; +#endif + bool _M_easy; + }; + + // constructors and member functions + + binomial_distribution() : binomial_distribution(1) { } + + explicit + binomial_distribution(_IntType __t, double __p = 0.5) + : _M_param(__t, __p), _M_nd() + { } + + explicit + binomial_distribution(const param_type& __p) + : _M_param(__p), _M_nd() + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_nd.reset(); } + + /** + * @brief Returns the distribution @p t parameter. + */ + _IntType + t() const + { return _M_param.t(); } + + /** + * @brief Returns the distribution @p p parameter. + */ + double + p() const + { return _M_param.p(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return 0; } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return _M_param.t(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two binomial distributions have + * the same parameters and the sequences that would + * be generated are equal. + */ + friend bool + operator==(const binomial_distribution& __d1, + const binomial_distribution& __d2) +#ifdef _GLIBCXX_USE_C99_MATH_TR1 + { return __d1._M_param == __d2._M_param && __d1._M_nd == __d2._M_nd; } +#else + { return __d1._M_param == __d2._M_param; } +#endif + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + result_type + _M_waiting(_UniformRandomNumberGenerator& __urng, + _IntType __t, double __q); + + param_type _M_param; + + // NB: Unused when _GLIBCXX_USE_C99_MATH_TR1 is undefined. + std::normal_distribution _M_nd; + }; + + /** + * @brief Return true if two binomial distributions are different. + */ + template + inline bool + operator!=(const std::binomial_distribution<_IntType>& __d1, + const std::binomial_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A discrete geometric random number distribution. + * + * The formula for the geometric probability density function is + * @f$p(i|p) = p(1 - p)^{i}@f$ where @f$p@f$ is the parameter of the + * distribution. + */ + template + class geometric_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef geometric_distribution<_IntType> distribution_type; + friend class geometric_distribution<_IntType>; + + param_type() : param_type(0.5) { } + + explicit + param_type(double __p) + : _M_p(__p) + { + __glibcxx_assert((_M_p > 0.0) && (_M_p < 1.0)); + _M_initialize(); + } + + double + p() const + { return _M_p; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_p == __p2._M_p; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize() + { _M_log_1_p = std::log(1.0 - _M_p); } + + double _M_p; + + double _M_log_1_p; + }; + + // constructors and member functions + + geometric_distribution() : geometric_distribution(0.5) { } + + explicit + geometric_distribution(double __p) + : _M_param(__p) + { } + + explicit + geometric_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for the geometric distribution. + */ + void + reset() { } + + /** + * @brief Returns the distribution parameter @p p. + */ + double + p() const + { return _M_param.p(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return 0; } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two geometric distributions have + * the same parameters. + */ + friend bool + operator==(const geometric_distribution& __d1, + const geometric_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two geometric distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::geometric_distribution<_IntType>& __d1, + const std::geometric_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A negative_binomial_distribution random number distribution. + * + * The formula for the negative binomial probability mass function is + * @f$p(i) = \binom{n}{i} p^i (1 - p)^{t - i}@f$ where @f$t@f$ + * and @f$p@f$ are the parameters of the distribution. + */ + template + class negative_binomial_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef negative_binomial_distribution<_IntType> distribution_type; + + param_type() : param_type(1) { } + + explicit + param_type(_IntType __k, double __p = 0.5) + : _M_k(__k), _M_p(__p) + { + __glibcxx_assert((_M_k > 0) && (_M_p > 0.0) && (_M_p <= 1.0)); + } + + _IntType + k() const + { return _M_k; } + + double + p() const + { return _M_p; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_k == __p2._M_k && __p1._M_p == __p2._M_p; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _IntType _M_k; + double _M_p; + }; + + negative_binomial_distribution() : negative_binomial_distribution(1) { } + + explicit + negative_binomial_distribution(_IntType __k, double __p = 0.5) + : _M_param(__k, __p), _M_gd(__k, (1.0 - __p) / __p) + { } + + explicit + negative_binomial_distribution(const param_type& __p) + : _M_param(__p), _M_gd(__p.k(), (1.0 - __p.p()) / __p.p()) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_gd.reset(); } + + /** + * @brief Return the @f$k@f$ parameter of the distribution. + */ + _IntType + k() const + { return _M_param.k(); } + + /** + * @brief Return the @f$p@f$ parameter of the distribution. + */ + double + p() const + { return _M_param.p(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng); + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate_impl(__f, __t, __urng); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two negative binomial distributions have + * the same parameters and the sequences that would be + * generated are equal. + */ + friend bool + operator==(const negative_binomial_distribution& __d1, + const negative_binomial_distribution& __d2) + { return __d1._M_param == __d2._M_param && __d1._M_gd == __d2._M_gd; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng); + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + std::gamma_distribution _M_gd; + }; + + /** + * @brief Return true if two negative binomial distributions are different. + */ + template + inline bool + operator!=(const std::negative_binomial_distribution<_IntType>& __d1, + const std::negative_binomial_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /* @} */ // group random_distributions_bernoulli + + /** + * @addtogroup random_distributions_poisson Poisson Distributions + * @ingroup random_distributions + * @{ + */ + + /** + * @brief A discrete Poisson random number distribution. + * + * The formula for the Poisson probability density function is + * @f$p(i|\mu) = \frac{\mu^i}{i!} e^{-\mu}@f$ where @f$\mu@f$ is the + * parameter of the distribution. + */ + template + class poisson_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef poisson_distribution<_IntType> distribution_type; + friend class poisson_distribution<_IntType>; + + param_type() : param_type(1.0) { } + + explicit + param_type(double __mean) + : _M_mean(__mean) + { + __glibcxx_assert(_M_mean > 0.0); + _M_initialize(); + } + + double + mean() const + { return _M_mean; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_mean == __p2._M_mean; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + // Hosts either log(mean) or the threshold of the simple method. + void + _M_initialize(); + + double _M_mean; + + double _M_lm_thr; +#if _GLIBCXX_USE_C99_MATH_TR1 + double _M_lfm, _M_sm, _M_d, _M_scx, _M_1cx, _M_c2b, _M_cb; +#endif + }; + + // constructors and member functions + + poisson_distribution() : poisson_distribution(1.0) { } + + explicit + poisson_distribution(double __mean) + : _M_param(__mean), _M_nd() + { } + + explicit + poisson_distribution(const param_type& __p) + : _M_param(__p), _M_nd() + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { _M_nd.reset(); } + + /** + * @brief Returns the distribution parameter @p mean. + */ + double + mean() const + { return _M_param.mean(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return 0; } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Poisson distributions have the same + * parameters and the sequences that would be generated + * are equal. + */ + friend bool + operator==(const poisson_distribution& __d1, + const poisson_distribution& __d2) +#ifdef _GLIBCXX_USE_C99_MATH_TR1 + { return __d1._M_param == __d2._M_param && __d1._M_nd == __d2._M_nd; } +#else + { return __d1._M_param == __d2._M_param; } +#endif + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + + // NB: Unused when _GLIBCXX_USE_C99_MATH_TR1 is undefined. + std::normal_distribution _M_nd; + }; + + /** + * @brief Return true if two Poisson distributions are different. + */ + template + inline bool + operator!=(const std::poisson_distribution<_IntType>& __d1, + const std::poisson_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief An exponential continuous distribution for random numbers. + * + * The formula for the exponential probability density function is + * @f$p(x|\lambda) = \lambda e^{-\lambda x}@f$. + * + * + * + * + * + * + * + * + *
Distribution Statistics
Mean@f$\frac{1}{\lambda}@f$
Median@f$\frac{\ln 2}{\lambda}@f$
Mode@f$zero@f$
Range@f$[0, \infty]@f$
Standard Deviation@f$\frac{1}{\lambda}@f$
+ */ + template + class exponential_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef exponential_distribution<_RealType> distribution_type; + + param_type() : param_type(1.0) { } + + explicit + param_type(_RealType __lambda) + : _M_lambda(__lambda) + { + __glibcxx_assert(_M_lambda > _RealType(0)); + } + + _RealType + lambda() const + { return _M_lambda; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_lambda == __p2._M_lambda; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_lambda; + }; + + public: + /** + * @brief Constructs an exponential distribution with inverse scale + * parameter 1.0 + */ + exponential_distribution() : exponential_distribution(1.0) { } + + /** + * @brief Constructs an exponential distribution with inverse scale + * parameter @f$\lambda@f$. + */ + explicit + exponential_distribution(_RealType __lambda) + : _M_param(__lambda) + { } + + explicit + exponential_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Has no effect on exponential distributions. + */ + void + reset() { } + + /** + * @brief Returns the inverse scale parameter of the distribution. + */ + _RealType + lambda() const + { return _M_param.lambda(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + return -std::log(result_type(1) - __aurng()) / __p.lambda(); + } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two exponential distributions have the same + * parameters. + */ + friend bool + operator==(const exponential_distribution& __d1, + const exponential_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two exponential distributions have different + * parameters. + */ + template + inline bool + operator!=(const std::exponential_distribution<_RealType>& __d1, + const std::exponential_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A weibull_distribution random number distribution. + * + * The formula for the normal probability density function is: + * @f[ + * p(x|\alpha,\beta) = \frac{\alpha}{\beta} (\frac{x}{\beta})^{\alpha-1} + * \exp{(-(\frac{x}{\beta})^\alpha)} + * @f] + */ + template + class weibull_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef weibull_distribution<_RealType> distribution_type; + + param_type() : param_type(1.0) { } + + explicit + param_type(_RealType __a, _RealType __b = _RealType(1.0)) + : _M_a(__a), _M_b(__b) + { } + + _RealType + a() const + { return _M_a; } + + _RealType + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_a; + _RealType _M_b; + }; + + weibull_distribution() : weibull_distribution(1.0) { } + + explicit + weibull_distribution(_RealType __a, _RealType __b = _RealType(1)) + : _M_param(__a, __b) + { } + + explicit + weibull_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Return the @f$a@f$ parameter of the distribution. + */ + _RealType + a() const + { return _M_param.a(); } + + /** + * @brief Return the @f$b@f$ parameter of the distribution. + */ + _RealType + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two Weibull distributions have the same + * parameters. + */ + friend bool + operator==(const weibull_distribution& __d1, + const weibull_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two Weibull distributions have different + * parameters. + */ + template + inline bool + operator!=(const std::weibull_distribution<_RealType>& __d1, + const std::weibull_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A extreme_value_distribution random number distribution. + * + * The formula for the normal probability mass function is + * @f[ + * p(x|a,b) = \frac{1}{b} + * \exp( \frac{a-x}{b} - \exp(\frac{a-x}{b})) + * @f] + */ + template + class extreme_value_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef extreme_value_distribution<_RealType> distribution_type; + + param_type() : param_type(0.0) { } + + explicit + param_type(_RealType __a, _RealType __b = _RealType(1.0)) + : _M_a(__a), _M_b(__b) + { } + + _RealType + a() const + { return _M_a; } + + _RealType + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _RealType _M_a; + _RealType _M_b; + }; + + extreme_value_distribution() : extreme_value_distribution(0.0) { } + + explicit + extreme_value_distribution(_RealType __a, _RealType __b = _RealType(1)) + : _M_param(__a, __b) + { } + + explicit + extreme_value_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Return the @f$a@f$ parameter of the distribution. + */ + _RealType + a() const + { return _M_param.a(); } + + /** + * @brief Return the @f$b@f$ parameter of the distribution. + */ + _RealType + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return std::numeric_limits::lowest(); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { return std::numeric_limits::max(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two extreme value distributions have the same + * parameters. + */ + friend bool + operator==(const extreme_value_distribution& __d1, + const extreme_value_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two extreme value distributions have different + * parameters. + */ + template + inline bool + operator!=(const std::extreme_value_distribution<_RealType>& __d1, + const std::extreme_value_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A discrete_distribution random number distribution. + * + * The formula for the discrete probability mass function is + * + */ + template + class discrete_distribution + { + static_assert(std::is_integral<_IntType>::value, + "result_type must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + + /** Parameter type. */ + struct param_type + { + typedef discrete_distribution<_IntType> distribution_type; + friend class discrete_distribution<_IntType>; + + param_type() + : _M_prob(), _M_cp() + { } + + template + param_type(_InputIterator __wbegin, + _InputIterator __wend) + : _M_prob(__wbegin, __wend), _M_cp() + { _M_initialize(); } + + param_type(initializer_list __wil) + : _M_prob(__wil.begin(), __wil.end()), _M_cp() + { _M_initialize(); } + + template + param_type(size_t __nw, double __xmin, double __xmax, + _Func __fw); + + // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ + param_type(const param_type&) = default; + param_type& operator=(const param_type&) = default; + + std::vector + probabilities() const + { return _M_prob.empty() ? std::vector(1, 1.0) : _M_prob; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_prob == __p2._M_prob; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + std::vector _M_prob; + std::vector _M_cp; + }; + + discrete_distribution() + : _M_param() + { } + + template + discrete_distribution(_InputIterator __wbegin, + _InputIterator __wend) + : _M_param(__wbegin, __wend) + { } + + discrete_distribution(initializer_list __wl) + : _M_param(__wl) + { } + + template + discrete_distribution(size_t __nw, double __xmin, double __xmax, + _Func __fw) + : _M_param(__nw, __xmin, __xmax, __fw) + { } + + explicit + discrete_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Returns the probabilities of the distribution. + */ + std::vector + probabilities() const + { + return _M_param._M_prob.empty() + ? std::vector(1, 1.0) : _M_param._M_prob; + } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { return result_type(0); } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { + return _M_param._M_prob.empty() + ? result_type(0) : result_type(_M_param._M_prob.size() - 1); + } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two discrete distributions have the same + * parameters. + */ + friend bool + operator==(const discrete_distribution& __d1, + const discrete_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two discrete distributions have different + * parameters. + */ + template + inline bool + operator!=(const std::discrete_distribution<_IntType>& __d1, + const std::discrete_distribution<_IntType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A piecewise_constant_distribution random number distribution. + * + * The formula for the piecewise constant probability mass function is + * + */ + template + class piecewise_constant_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef piecewise_constant_distribution<_RealType> distribution_type; + friend class piecewise_constant_distribution<_RealType>; + + param_type() + : _M_int(), _M_den(), _M_cp() + { } + + template + param_type(_InputIteratorB __bfirst, + _InputIteratorB __bend, + _InputIteratorW __wbegin); + + template + param_type(initializer_list<_RealType> __bi, _Func __fw); + + template + param_type(size_t __nw, _RealType __xmin, _RealType __xmax, + _Func __fw); + + // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ + param_type(const param_type&) = default; + param_type& operator=(const param_type&) = default; + + std::vector<_RealType> + intervals() const + { + if (_M_int.empty()) + { + std::vector<_RealType> __tmp(2); + __tmp[1] = _RealType(1); + return __tmp; + } + else + return _M_int; + } + + std::vector + densities() const + { return _M_den.empty() ? std::vector(1, 1.0) : _M_den; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_int == __p2._M_int && __p1._M_den == __p2._M_den; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + std::vector<_RealType> _M_int; + std::vector _M_den; + std::vector _M_cp; + }; + + piecewise_constant_distribution() + : _M_param() + { } + + template + piecewise_constant_distribution(_InputIteratorB __bfirst, + _InputIteratorB __bend, + _InputIteratorW __wbegin) + : _M_param(__bfirst, __bend, __wbegin) + { } + + template + piecewise_constant_distribution(initializer_list<_RealType> __bl, + _Func __fw) + : _M_param(__bl, __fw) + { } + + template + piecewise_constant_distribution(size_t __nw, + _RealType __xmin, _RealType __xmax, + _Func __fw) + : _M_param(__nw, __xmin, __xmax, __fw) + { } + + explicit + piecewise_constant_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Returns a vector of the intervals. + */ + std::vector<_RealType> + intervals() const + { + if (_M_param._M_int.empty()) + { + std::vector<_RealType> __tmp(2); + __tmp[1] = _RealType(1); + return __tmp; + } + else + return _M_param._M_int; + } + + /** + * @brief Returns a vector of the probability densities. + */ + std::vector + densities() const + { + return _M_param._M_den.empty() + ? std::vector(1, 1.0) : _M_param._M_den; + } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { + return _M_param._M_int.empty() + ? result_type(0) : _M_param._M_int.front(); + } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { + return _M_param._M_int.empty() + ? result_type(1) : _M_param._M_int.back(); + } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two piecewise constant distributions have the + * same parameters. + */ + friend bool + operator==(const piecewise_constant_distribution& __d1, + const piecewise_constant_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two piecewise constant distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::piecewise_constant_distribution<_RealType>& __d1, + const std::piecewise_constant_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /** + * @brief A piecewise_linear_distribution random number distribution. + * + * The formula for the piecewise linear probability mass function is + * + */ + template + class piecewise_linear_distribution + { + static_assert(std::is_floating_point<_RealType>::value, + "result_type must be a floating point type"); + + public: + /** The type of the range of the distribution. */ + typedef _RealType result_type; + + /** Parameter type. */ + struct param_type + { + typedef piecewise_linear_distribution<_RealType> distribution_type; + friend class piecewise_linear_distribution<_RealType>; + + param_type() + : _M_int(), _M_den(), _M_cp(), _M_m() + { } + + template + param_type(_InputIteratorB __bfirst, + _InputIteratorB __bend, + _InputIteratorW __wbegin); + + template + param_type(initializer_list<_RealType> __bl, _Func __fw); + + template + param_type(size_t __nw, _RealType __xmin, _RealType __xmax, + _Func __fw); + + // See: http://cpp-next.com/archive/2010/10/implicit-move-must-go/ + param_type(const param_type&) = default; + param_type& operator=(const param_type&) = default; + + std::vector<_RealType> + intervals() const + { + if (_M_int.empty()) + { + std::vector<_RealType> __tmp(2); + __tmp[1] = _RealType(1); + return __tmp; + } + else + return _M_int; + } + + std::vector + densities() const + { return _M_den.empty() ? std::vector(2, 1.0) : _M_den; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_int == __p2._M_int && __p1._M_den == __p2._M_den; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + void + _M_initialize(); + + std::vector<_RealType> _M_int; + std::vector _M_den; + std::vector _M_cp; + std::vector _M_m; + }; + + piecewise_linear_distribution() + : _M_param() + { } + + template + piecewise_linear_distribution(_InputIteratorB __bfirst, + _InputIteratorB __bend, + _InputIteratorW __wbegin) + : _M_param(__bfirst, __bend, __wbegin) + { } + + template + piecewise_linear_distribution(initializer_list<_RealType> __bl, + _Func __fw) + : _M_param(__bl, __fw) + { } + + template + piecewise_linear_distribution(size_t __nw, + _RealType __xmin, _RealType __xmax, + _Func __fw) + : _M_param(__nw, __xmin, __xmax, __fw) + { } + + explicit + piecewise_linear_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * Resets the distribution state. + */ + void + reset() + { } + + /** + * @brief Return the intervals of the distribution. + */ + std::vector<_RealType> + intervals() const + { + if (_M_param._M_int.empty()) + { + std::vector<_RealType> __tmp(2); + __tmp[1] = _RealType(1); + return __tmp; + } + else + return _M_param._M_int; + } + + /** + * @brief Return a vector of the probability densities of the + * distribution. + */ + std::vector + densities() const + { + return _M_param._M_den.empty() + ? std::vector(2, 1.0) : _M_param._M_den; + } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the greatest lower bound value of the distribution. + */ + result_type + min() const + { + return _M_param._M_int.empty() + ? result_type(0) : _M_param._M_int.front(); + } + + /** + * @brief Returns the least upper bound value of the distribution. + */ + result_type + max() const + { + return _M_param._M_int.empty() + ? result_type(1) : _M_param._M_int.back(); + } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two piecewise linear distributions have the + * same parameters. + */ + friend bool + operator==(const piecewise_linear_distribution& __d1, + const piecewise_linear_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + /** + * @brief Return true if two piecewise linear distributions have + * different parameters. + */ + template + inline bool + operator!=(const std::piecewise_linear_distribution<_RealType>& __d1, + const std::piecewise_linear_distribution<_RealType>& __d2) + { return !(__d1 == __d2); } + + + /* @} */ // group random_distributions_poisson + + /* @} */ // group random_distributions + + /** + * @addtogroup random_utilities Random Number Utilities + * @ingroup random + * @{ + */ + + /** + * @brief The seed_seq class generates sequences of seeds for random + * number generators. + */ + class seed_seq + { + public: + /** The type of the seed vales. */ + typedef uint_least32_t result_type; + + /** Default constructor. */ + seed_seq() noexcept + : _M_v() + { } + + template + seed_seq(std::initializer_list<_IntType> __il); + + template + seed_seq(_InputIterator __begin, _InputIterator __end); + + // generating functions + template + void + generate(_RandomAccessIterator __begin, _RandomAccessIterator __end); + + // property functions + size_t size() const noexcept + { return _M_v.size(); } + + template + void + param(_OutputIterator __dest) const + { std::copy(_M_v.begin(), _M_v.end(), __dest); } + + // no copy functions + seed_seq(const seed_seq&) = delete; + seed_seq& operator=(const seed_seq&) = delete; + + private: + std::vector _M_v; + }; + + /* @} */ // group random_utilities + + /* @} */ // group random + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/random.tcc b/resources/sources/avr-libstdcpp/include/bits/random.tcc new file mode 100644 index 000000000..a9b90d6ca --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/random.tcc @@ -0,0 +1,2193 @@ +// random number generation (out of line) -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/random.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{random} + */ + +#ifndef _RANDOM_TCC +#define _RANDOM_TCC 1 + +#include // std::accumulate and std::partial_sum + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /* + * (Further) implementation-space details. + */ + namespace __detail + { + // General case for x = (ax + c) mod m -- use Schrage's algorithm + // to avoid integer overflow. + // + // Preconditions: a > 0, m > 0. + // + // Note: only works correctly for __m % __a < __m / __a. + template + _Tp + _Mod<_Tp, __m, __a, __c, false, true>:: + __calc(_Tp __x) + { + if (__a == 1) + __x %= __m; + else + { + static const _Tp __q = __m / __a; + static const _Tp __r = __m % __a; + + _Tp __t1 = __a * (__x % __q); + _Tp __t2 = __r * (__x / __q); + if (__t1 >= __t2) + __x = __t1 - __t2; + else + __x = __m - __t2 + __t1; + } + + if (__c != 0) + { + const _Tp __d = __m - __x; + if (__d > __c) + __x += __c; + else + __x = __c - __d; + } + return __x; + } + + template + _OutputIterator + __normalize(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, const _Tp& __factor) + { + for (; __first != __last; ++__first, ++__result) + *__result = *__first / __factor; + return __result; + } + + } // namespace __detail + + template + constexpr _UIntType + linear_congruential_engine<_UIntType, __a, __c, __m>::multiplier; + + template + constexpr _UIntType + linear_congruential_engine<_UIntType, __a, __c, __m>::increment; + + template + constexpr _UIntType + linear_congruential_engine<_UIntType, __a, __c, __m>::modulus; + + template + constexpr _UIntType + linear_congruential_engine<_UIntType, __a, __c, __m>::default_seed; + + /** + * Seeds the LCR with integral value @p __s, adjusted so that the + * ring identity is never a member of the convergence set. + */ + template + void + linear_congruential_engine<_UIntType, __a, __c, __m>:: + seed(result_type __s) + { + if ((__detail::__mod<_UIntType, __m>(__c) == 0) + && (__detail::__mod<_UIntType, __m>(__s) == 0)) + _M_x = 1; + else + _M_x = __detail::__mod<_UIntType, __m>(__s); + } + + /** + * Seeds the LCR engine with a value generated by @p __q. + */ + template + template + auto + linear_congruential_engine<_UIntType, __a, __c, __m>:: + seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> + { + const _UIntType __k0 = __m == 0 ? std::numeric_limits<_UIntType>::digits + : std::__lg(__m); + const _UIntType __k = (__k0 + 31) / 32; + uint_least32_t __arr[__k + 3]; + __q.generate(__arr + 0, __arr + __k + 3); + _UIntType __factor = 1u; + _UIntType __sum = 0u; + for (size_t __j = 0; __j < __k; ++__j) + { + __sum += __arr[__j + 3] * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + seed(__sum); + } + + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::word_size; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::state_size; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::shift_size; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::mask_bits; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::xor_mask; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_u; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_d; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_s; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_b; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_t; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_c; + + template + constexpr size_t + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::tempering_l; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + initialization_multiplier; + + template + constexpr _UIntType + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::default_seed; + + template + void + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + seed(result_type __sd) + { + _M_x[0] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__sd); + + for (size_t __i = 1; __i < state_size; ++__i) + { + _UIntType __x = _M_x[__i - 1]; + __x ^= __x >> (__w - 2); + __x *= __f; + __x += __detail::__mod<_UIntType, __n>(__i); + _M_x[__i] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__x); + } + _M_p = state_size; + } + + template + template + auto + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> + { + const _UIntType __upper_mask = (~_UIntType()) << __r; + const size_t __k = (__w + 31) / 32; + uint_least32_t __arr[__n * __k]; + __q.generate(__arr + 0, __arr + __n * __k); + + bool __zero = true; + for (size_t __i = 0; __i < state_size; ++__i) + { + _UIntType __factor = 1u; + _UIntType __sum = 0u; + for (size_t __j = 0; __j < __k; ++__j) + { + __sum += __arr[__k * __i + __j] * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + _M_x[__i] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__sum); + + if (__zero) + { + if (__i == 0) + { + if ((_M_x[0] & __upper_mask) != 0u) + __zero = false; + } + else if (_M_x[__i] != 0u) + __zero = false; + } + } + if (__zero) + _M_x[0] = __detail::_Shift<_UIntType, __w - 1>::__value; + _M_p = state_size; + } + + template + void + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + _M_gen_rand(void) + { + const _UIntType __upper_mask = (~_UIntType()) << __r; + const _UIntType __lower_mask = ~__upper_mask; + + for (size_t __k = 0; __k < (__n - __m); ++__k) + { + _UIntType __y = ((_M_x[__k] & __upper_mask) + | (_M_x[__k + 1] & __lower_mask)); + _M_x[__k] = (_M_x[__k + __m] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + } + + for (size_t __k = (__n - __m); __k < (__n - 1); ++__k) + { + _UIntType __y = ((_M_x[__k] & __upper_mask) + | (_M_x[__k + 1] & __lower_mask)); + _M_x[__k] = (_M_x[__k + (__m - __n)] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + } + + _UIntType __y = ((_M_x[__n - 1] & __upper_mask) + | (_M_x[0] & __lower_mask)); + _M_x[__n - 1] = (_M_x[__m - 1] ^ (__y >> 1) + ^ ((__y & 0x01) ? __a : 0)); + _M_p = 0; + } + + template + void + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + discard(unsigned long long __z) + { + while (__z > state_size - _M_p) + { + __z -= state_size - _M_p; + _M_gen_rand(); + } + _M_p += __z; + } + + template + typename + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>::result_type + mersenne_twister_engine<_UIntType, __w, __n, __m, __r, __a, __u, __d, + __s, __b, __t, __c, __l, __f>:: + operator()() + { + // Reload the vector - cost is O(n) amortized over n calls. + if (_M_p >= state_size) + _M_gen_rand(); + + // Calculate o(x(i)). + result_type __z = _M_x[_M_p++]; + __z ^= (__z >> __u) & __d; + __z ^= (__z << __s) & __b; + __z ^= (__z << __t) & __c; + __z ^= (__z >> __l); + + return __z; + } + + + template + constexpr size_t + subtract_with_carry_engine<_UIntType, __w, __s, __r>::word_size; + + template + constexpr size_t + subtract_with_carry_engine<_UIntType, __w, __s, __r>::short_lag; + + template + constexpr size_t + subtract_with_carry_engine<_UIntType, __w, __s, __r>::long_lag; + + template + constexpr _UIntType + subtract_with_carry_engine<_UIntType, __w, __s, __r>::default_seed; + + template + void + subtract_with_carry_engine<_UIntType, __w, __s, __r>:: + seed(result_type __value) + { + std::linear_congruential_engine + __lcg(__value == 0u ? default_seed : __value); + + const size_t __n = (__w + 31) / 32; + + for (size_t __i = 0; __i < long_lag; ++__i) + { + _UIntType __sum = 0u; + _UIntType __factor = 1u; + for (size_t __j = 0; __j < __n; ++__j) + { + __sum += __detail::__mod::__value> + (__lcg()) * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + _M_x[__i] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__sum); + } + _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0; + _M_p = 0; + } + + template + template + auto + subtract_with_carry_engine<_UIntType, __w, __s, __r>:: + seed(_Sseq& __q) + -> _If_seed_seq<_Sseq> + { + const size_t __k = (__w + 31) / 32; + uint_least32_t __arr[__r * __k]; + __q.generate(__arr + 0, __arr + __r * __k); + + for (size_t __i = 0; __i < long_lag; ++__i) + { + _UIntType __sum = 0u; + _UIntType __factor = 1u; + for (size_t __j = 0; __j < __k; ++__j) + { + __sum += __arr[__k * __i + __j] * __factor; + __factor *= __detail::_Shift<_UIntType, 32>::__value; + } + _M_x[__i] = __detail::__mod<_UIntType, + __detail::_Shift<_UIntType, __w>::__value>(__sum); + } + _M_carry = (_M_x[long_lag - 1] == 0) ? 1 : 0; + _M_p = 0; + } + + template + typename subtract_with_carry_engine<_UIntType, __w, __s, __r>:: + result_type + subtract_with_carry_engine<_UIntType, __w, __s, __r>:: + operator()() + { + // Derive short lag index from current index. + long __ps = _M_p - short_lag; + if (__ps < 0) + __ps += long_lag; + + // Calculate new x(i) without overflow or division. + // NB: Thanks to the requirements for _UIntType, _M_x[_M_p] + _M_carry + // cannot overflow. + _UIntType __xi; + if (_M_x[__ps] >= _M_x[_M_p] + _M_carry) + { + __xi = _M_x[__ps] - _M_x[_M_p] - _M_carry; + _M_carry = 0; + } + else + { + __xi = (__detail::_Shift<_UIntType, __w>::__value + - _M_x[_M_p] - _M_carry + _M_x[__ps]); + _M_carry = 1; + } + _M_x[_M_p] = __xi; + + // Adjust current index to loop around in ring buffer. + if (++_M_p >= long_lag) + _M_p = 0; + + return __xi; + } + + + template + constexpr size_t + discard_block_engine<_RandomNumberEngine, __p, __r>::block_size; + + template + constexpr size_t + discard_block_engine<_RandomNumberEngine, __p, __r>::used_block; + + template + typename discard_block_engine<_RandomNumberEngine, + __p, __r>::result_type + discard_block_engine<_RandomNumberEngine, __p, __r>:: + operator()() + { + if (_M_n >= used_block) + { + _M_b.discard(block_size - _M_n); + _M_n = 0; + } + ++_M_n; + return _M_b(); + } + + + template + typename independent_bits_engine<_RandomNumberEngine, __w, _UIntType>:: + result_type + independent_bits_engine<_RandomNumberEngine, __w, _UIntType>:: + operator()() + { + typedef typename _RandomNumberEngine::result_type _Eresult_type; + const _Eresult_type __r + = (_M_b.max() - _M_b.min() < std::numeric_limits<_Eresult_type>::max() + ? _M_b.max() - _M_b.min() + 1 : 0); + const unsigned __edig = std::numeric_limits<_Eresult_type>::digits; + const unsigned __m = __r ? std::__lg(__r) : __edig; + + typedef typename std::common_type<_Eresult_type, result_type>::type + __ctype; + const unsigned __cdig = std::numeric_limits<__ctype>::digits; + + unsigned __n, __n0; + __ctype __s0, __s1, __y0, __y1; + + for (size_t __i = 0; __i < 2; ++__i) + { + __n = (__w + __m - 1) / __m + __i; + __n0 = __n - __w % __n; + const unsigned __w0 = __w / __n; // __w0 <= __m + + __s0 = 0; + __s1 = 0; + if (__w0 < __cdig) + { + __s0 = __ctype(1) << __w0; + __s1 = __s0 << 1; + } + + __y0 = 0; + __y1 = 0; + if (__r) + { + __y0 = __s0 * (__r / __s0); + if (__s1) + __y1 = __s1 * (__r / __s1); + + if (__r - __y0 <= __y0 / __n) + break; + } + else + break; + } + + result_type __sum = 0; + for (size_t __k = 0; __k < __n0; ++__k) + { + __ctype __u; + do + __u = _M_b() - _M_b.min(); + while (__y0 && __u >= __y0); + __sum = __s0 * __sum + (__s0 ? __u % __s0 : __u); + } + for (size_t __k = __n0; __k < __n; ++__k) + { + __ctype __u; + do + __u = _M_b() - _M_b.min(); + while (__y1 && __u >= __y1); + __sum = __s1 * __sum + (__s1 ? __u % __s1 : __u); + } + return __sum; + } + + + template + constexpr size_t + shuffle_order_engine<_RandomNumberEngine, __k>::table_size; + + template + typename shuffle_order_engine<_RandomNumberEngine, __k>::result_type + shuffle_order_engine<_RandomNumberEngine, __k>:: + operator()() + { + size_t __j = __k * ((_M_y - _M_b.min()) + / (_M_b.max() - _M_b.min() + 1.0L)); + _M_y = _M_v[__j]; + _M_v[__j] = _M_b(); + + return _M_y; + } + + + template + template + void + uniform_real_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + auto __range = __p.b() - __p.a(); + while (__f != __t) + *__f++ = __aurng() * __range + __p.a(); + } + + + template + void + std::bernoulli_distribution:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + auto __limit = __p.p() * (__aurng.max() - __aurng.min()); + + while (__f != __t) + *__f++ = (__aurng() - __aurng.min()) < __limit; + } + + + template + template + typename geometric_distribution<_IntType>::result_type + geometric_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + // About the epsilon thing see this thread: + // http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00971.html + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + // The largest _RealType convertible to _IntType. + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + double __cand; + do + __cand = std::floor(std::log(1.0 - __aurng()) / __param._M_log_1_p); + while (__cand >= __thr); + + return result_type(__cand + __naf); + } + + template + template + void + geometric_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // About the epsilon thing see this thread: + // http://gcc.gnu.org/ml/gcc-patches/2006-10/msg00971.html + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + // The largest _RealType convertible to _IntType. + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + while (__f != __t) + { + double __cand; + do + __cand = std::floor(std::log(1.0 - __aurng()) + / __param._M_log_1_p); + while (__cand >= __thr); + + *__f++ = __cand + __naf; + } + } + + + // This is Leger's algorithm, also in Devroye, Ch. X, Example 1.5. + template + template + typename negative_binomial_distribution<_IntType>::result_type + negative_binomial_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng) + { + const double __y = _M_gd(__urng); + + // XXX Is the constructor too slow? + std::poisson_distribution __poisson(__y); + return __poisson(__urng); + } + + template + template + typename negative_binomial_distribution<_IntType>::result_type + negative_binomial_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + typedef typename std::gamma_distribution::param_type + param_type; + + const double __y = + _M_gd(__urng, param_type(__p.k(), (1.0 - __p.p()) / __p.p())); + + std::poisson_distribution __poisson(__y); + return __poisson(__urng); + } + + template + template + void + negative_binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + { + const double __y = _M_gd(__urng); + + // XXX Is the constructor too slow? + std::poisson_distribution __poisson(__y); + *__f++ = __poisson(__urng); + } + } + + template + template + void + negative_binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typename std::gamma_distribution::param_type + __p2(__p.k(), (1.0 - __p.p()) / __p.p()); + + while (__f != __t) + { + const double __y = _M_gd(__urng, __p2); + + std::poisson_distribution __poisson(__y); + *__f++ = __poisson(__urng); + } + } + + + template + void + poisson_distribution<_IntType>::param_type:: + _M_initialize() + { +#if _GLIBCXX_USE_C99_MATH_TR1 + if (_M_mean >= 12) + { + const double __m = std::floor(_M_mean); + _M_lm_thr = std::log(_M_mean); + _M_lfm = std::lgamma(__m + 1); + _M_sm = std::sqrt(__m); + + const double __pi_4 = 0.7853981633974483096156608458198757L; + const double __dx = std::sqrt(2 * __m * std::log(32 * __m + / __pi_4)); + _M_d = std::round(std::max(6.0, std::min(__m, __dx))); + const double __cx = 2 * __m + _M_d; + _M_scx = std::sqrt(__cx / 2); + _M_1cx = 1 / __cx; + + _M_c2b = std::sqrt(__pi_4 * __cx) * std::exp(_M_1cx); + _M_cb = 2 * __cx * std::exp(-_M_d * _M_1cx * (1 + _M_d / 2)) + / _M_d; + } + else +#endif + _M_lm_thr = std::exp(-_M_mean); + } + + /** + * A rejection algorithm when mean >= 12 and a simple method based + * upon the multiplication of uniform random variates otherwise. + * NB: The former is available only if _GLIBCXX_USE_C99_MATH_TR1 + * is defined. + * + * Reference: + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. X, Sects. 3.3 & 3.4 (+ Errata!). + */ + template + template + typename poisson_distribution<_IntType>::result_type + poisson_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); +#if _GLIBCXX_USE_C99_MATH_TR1 + if (__param.mean() >= 12) + { + double __x; + + // See comments above... + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + + const double __m = std::floor(__param.mean()); + // sqrt(pi / 2) + const double __spi_2 = 1.2533141373155002512078826424055226L; + const double __c1 = __param._M_sm * __spi_2; + const double __c2 = __param._M_c2b + __c1; + const double __c3 = __c2 + 1; + const double __c4 = __c3 + 1; + // 1 / 78 + const double __178 = 0.0128205128205128205128205128205128L; + // e^(1 / 78) + const double __e178 = 1.0129030479320018583185514777512983L; + const double __c5 = __c4 + __e178; + const double __c = __param._M_cb + __c5; + const double __2cx = 2 * (2 * __m + __param._M_d); + + bool __reject = true; + do + { + const double __u = __c * __aurng(); + const double __e = -std::log(1.0 - __aurng()); + + double __w = 0.0; + + if (__u <= __c1) + { + const double __n = _M_nd(__urng); + const double __y = -std::abs(__n) * __param._M_sm - 1; + __x = std::floor(__y); + __w = -__n * __n / 2; + if (__x < -__m) + continue; + } + else if (__u <= __c2) + { + const double __n = _M_nd(__urng); + const double __y = 1 + std::abs(__n) * __param._M_scx; + __x = std::ceil(__y); + __w = __y * (2 - __y) * __param._M_1cx; + if (__x > __param._M_d) + continue; + } + else if (__u <= __c3) + // NB: This case not in the book, nor in the Errata, + // but should be ok... + __x = -1; + else if (__u <= __c4) + __x = 0; + else if (__u <= __c5) + { + __x = 1; + // Only in the Errata, see libstdc++/83237. + __w = __178; + } + else + { + const double __v = -std::log(1.0 - __aurng()); + const double __y = __param._M_d + + __v * __2cx / __param._M_d; + __x = std::ceil(__y); + __w = -__param._M_d * __param._M_1cx * (1 + __y / 2); + } + + __reject = (__w - __e - __x * __param._M_lm_thr + > __param._M_lfm - std::lgamma(__x + __m + 1)); + + __reject |= __x + __m >= __thr; + + } while (__reject); + + return result_type(__x + __m + __naf); + } + else +#endif + { + _IntType __x = 0; + double __prod = 1.0; + + do + { + __prod *= __aurng(); + __x += 1; + } + while (__prod > __param._M_lm_thr); + + return __x - 1; + } + } + + template + template + void + poisson_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + + + template + void + binomial_distribution<_IntType>::param_type:: + _M_initialize() + { + const double __p12 = _M_p <= 0.5 ? _M_p : 1.0 - _M_p; + + _M_easy = true; + +#if _GLIBCXX_USE_C99_MATH_TR1 + if (_M_t * __p12 >= 8) + { + _M_easy = false; + const double __np = std::floor(_M_t * __p12); + const double __pa = __np / _M_t; + const double __1p = 1 - __pa; + + const double __pi_4 = 0.7853981633974483096156608458198757L; + const double __d1x = + std::sqrt(__np * __1p * std::log(32 * __np + / (81 * __pi_4 * __1p))); + _M_d1 = std::round(std::max(1.0, __d1x)); + const double __d2x = + std::sqrt(__np * __1p * std::log(32 * _M_t * __1p + / (__pi_4 * __pa))); + _M_d2 = std::round(std::max(1.0, __d2x)); + + // sqrt(pi / 2) + const double __spi_2 = 1.2533141373155002512078826424055226L; + _M_s1 = std::sqrt(__np * __1p) * (1 + _M_d1 / (4 * __np)); + _M_s2 = std::sqrt(__np * __1p) * (1 + _M_d2 / (4 * _M_t * __1p)); + _M_c = 2 * _M_d1 / __np; + _M_a1 = std::exp(_M_c) * _M_s1 * __spi_2; + const double __a12 = _M_a1 + _M_s2 * __spi_2; + const double __s1s = _M_s1 * _M_s1; + _M_a123 = __a12 + (std::exp(_M_d1 / (_M_t * __1p)) + * 2 * __s1s / _M_d1 + * std::exp(-_M_d1 * _M_d1 / (2 * __s1s))); + const double __s2s = _M_s2 * _M_s2; + _M_s = (_M_a123 + 2 * __s2s / _M_d2 + * std::exp(-_M_d2 * _M_d2 / (2 * __s2s))); + _M_lf = (std::lgamma(__np + 1) + + std::lgamma(_M_t - __np + 1)); + _M_lp1p = std::log(__pa / __1p); + + _M_q = -std::log(1 - (__p12 - __pa) / __1p); + } + else +#endif + _M_q = -std::log(1 - __p12); + } + + template + template + typename binomial_distribution<_IntType>::result_type + binomial_distribution<_IntType>:: + _M_waiting(_UniformRandomNumberGenerator& __urng, + _IntType __t, double __q) + { + _IntType __x = 0; + double __sum = 0.0; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + do + { + if (__t == __x) + return __x; + const double __e = -std::log(1.0 - __aurng()); + __sum += __e / (__t - __x); + __x += 1; + } + while (__sum <= __q); + + return __x - 1; + } + + /** + * A rejection algorithm when t * p >= 8 and a simple waiting time + * method - the second in the referenced book - otherwise. + * NB: The former is available only if _GLIBCXX_USE_C99_MATH_TR1 + * is defined. + * + * Reference: + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. X, Sect. 4 (+ Errata!). + */ + template + template + typename binomial_distribution<_IntType>::result_type + binomial_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + result_type __ret; + const _IntType __t = __param.t(); + const double __p = __param.p(); + const double __p12 = __p <= 0.5 ? __p : 1.0 - __p; + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + +#if _GLIBCXX_USE_C99_MATH_TR1 + if (!__param._M_easy) + { + double __x; + + // See comments above... + const double __naf = + (1 - std::numeric_limits::epsilon()) / 2; + const double __thr = + std::numeric_limits<_IntType>::max() + __naf; + + const double __np = std::floor(__t * __p12); + + // sqrt(pi / 2) + const double __spi_2 = 1.2533141373155002512078826424055226L; + const double __a1 = __param._M_a1; + const double __a12 = __a1 + __param._M_s2 * __spi_2; + const double __a123 = __param._M_a123; + const double __s1s = __param._M_s1 * __param._M_s1; + const double __s2s = __param._M_s2 * __param._M_s2; + + bool __reject; + do + { + const double __u = __param._M_s * __aurng(); + + double __v; + + if (__u <= __a1) + { + const double __n = _M_nd(__urng); + const double __y = __param._M_s1 * std::abs(__n); + __reject = __y >= __param._M_d1; + if (!__reject) + { + const double __e = -std::log(1.0 - __aurng()); + __x = std::floor(__y); + __v = -__e - __n * __n / 2 + __param._M_c; + } + } + else if (__u <= __a12) + { + const double __n = _M_nd(__urng); + const double __y = __param._M_s2 * std::abs(__n); + __reject = __y >= __param._M_d2; + if (!__reject) + { + const double __e = -std::log(1.0 - __aurng()); + __x = std::floor(-__y); + __v = -__e - __n * __n / 2; + } + } + else if (__u <= __a123) + { + const double __e1 = -std::log(1.0 - __aurng()); + const double __e2 = -std::log(1.0 - __aurng()); + + const double __y = __param._M_d1 + + 2 * __s1s * __e1 / __param._M_d1; + __x = std::floor(__y); + __v = (-__e2 + __param._M_d1 * (1 / (__t - __np) + -__y / (2 * __s1s))); + __reject = false; + } + else + { + const double __e1 = -std::log(1.0 - __aurng()); + const double __e2 = -std::log(1.0 - __aurng()); + + const double __y = __param._M_d2 + + 2 * __s2s * __e1 / __param._M_d2; + __x = std::floor(-__y); + __v = -__e2 - __param._M_d2 * __y / (2 * __s2s); + __reject = false; + } + + __reject = __reject || __x < -__np || __x > __t - __np; + if (!__reject) + { + const double __lfx = + std::lgamma(__np + __x + 1) + + std::lgamma(__t - (__np + __x) + 1); + __reject = __v > __param._M_lf - __lfx + + __x * __param._M_lp1p; + } + + __reject |= __x + __np >= __thr; + } + while (__reject); + + __x += __np + __naf; + + const _IntType __z = _M_waiting(__urng, __t - _IntType(__x), + __param._M_q); + __ret = _IntType(__x) + __z; + } + else +#endif + __ret = _M_waiting(__urng, __t, __param._M_q); + + if (__p12 != __p) + __ret = __t - __ret; + return __ret; + } + + template + template + void + binomial_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + + + template + template + void + std::exponential_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + while (__f != __t) + *__f++ = -std::log(result_type(1) - __aurng()) / __p.lambda(); + } + + + /** + * Polar method due to Marsaglia. + * + * Devroye, L. Non-Uniform Random Variates Generation. Springer-Verlag, + * New York, 1986, Ch. V, Sect. 4.4. + */ + template + template + typename normal_distribution<_RealType>::result_type + normal_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + result_type __ret; + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + if (_M_saved_available) + { + _M_saved_available = false; + __ret = _M_saved; + } + else + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + _M_saved = __x * __mult; + _M_saved_available = true; + __ret = __y * __mult; + } + + __ret = __ret * __param.stddev() + __param.mean(); + return __ret; + } + + template + template + void + normal_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + + if (__f == __t) + return; + + if (_M_saved_available) + { + _M_saved_available = false; + *__f++ = _M_saved * __param.stddev() + __param.mean(); + + if (__f == __t) + return; + } + + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + while (__f + 1 < __t) + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + *__f++ = __y * __mult * __param.stddev() + __param.mean(); + *__f++ = __x * __mult * __param.stddev() + __param.mean(); + } + + if (__f != __t) + { + result_type __x, __y, __r2; + do + { + __x = result_type(2.0) * __aurng() - 1.0; + __y = result_type(2.0) * __aurng() - 1.0; + __r2 = __x * __x + __y * __y; + } + while (__r2 > 1.0 || __r2 == 0.0); + + const result_type __mult = std::sqrt(-2 * std::log(__r2) / __r2); + _M_saved = __x * __mult; + _M_saved_available = true; + *__f = __y * __mult * __param.stddev() + __param.mean(); + } + } + + template + bool + operator==(const std::normal_distribution<_RealType>& __d1, + const std::normal_distribution<_RealType>& __d2) + { + if (__d1._M_param == __d2._M_param + && __d1._M_saved_available == __d2._M_saved_available) + { + if (__d1._M_saved_available + && __d1._M_saved == __d2._M_saved) + return true; + else if(!__d1._M_saved_available) + return true; + else + return false; + } + else + return false; + } + + + template + template + void + lognormal_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = std::exp(__p.s() * _M_nd(__urng) + __p.m()); + } + + template + template + void + std::chi_squared_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = 2 * _M_gd(__urng); + } + + template + template + void + std::chi_squared_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const typename + std::gamma_distribution::param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = 2 * _M_gd(__urng, __p); + } + + + template + template + typename cauchy_distribution<_RealType>::result_type + cauchy_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + _RealType __u; + do + __u = __aurng(); + while (__u == 0.5); + + const _RealType __pi = 3.1415926535897932384626433832795029L; + return __p.a() + __p.b() * std::tan(__pi * __u); + } + + template + template + void + cauchy_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + const _RealType __pi = 3.1415926535897932384626433832795029L; + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + while (__f != __t) + { + _RealType __u; + do + __u = __aurng(); + while (__u == 0.5); + + *__f++ = __p.a() + __p.b() * std::tan(__pi * __u); + } + } + + + template + template + void + std::fisher_f_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = ((_M_gd_x(__urng) * n()) / (_M_gd_y(__urng) * m())); + } + + template + template + void + std::fisher_f_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typedef typename std::gamma_distribution::param_type + param_type; + param_type __p1(__p.m() / 2); + param_type __p2(__p.n() / 2); + while (__f != __t) + *__f++ = ((_M_gd_x(__urng, __p1) * n()) + / (_M_gd_y(__urng, __p2) * m())); + } + + + template + template + void + std::student_t_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + while (__f != __t) + *__f++ = _M_nd(__urng) * std::sqrt(n() / _M_gd(__urng)); + } + + template + template + void + std::student_t_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typename std::gamma_distribution::param_type + __p2(__p.n() / 2, 2); + while (__f != __t) + *__f++ = _M_nd(__urng) * std::sqrt(__p.n() / _M_gd(__urng, __p2)); + } + + + template + void + gamma_distribution<_RealType>::param_type:: + _M_initialize() + { + _M_malpha = _M_alpha < 1.0 ? _M_alpha + _RealType(1.0) : _M_alpha; + + const _RealType __a1 = _M_malpha - _RealType(1.0) / _RealType(3.0); + _M_a2 = _RealType(1.0) / std::sqrt(_RealType(9.0) * __a1); + } + + /** + * Marsaglia, G. and Tsang, W. W. + * "A Simple Method for Generating Gamma Variables" + * ACM Transactions on Mathematical Software, 26, 3, 363-372, 2000. + */ + template + template + typename gamma_distribution<_RealType>::result_type + gamma_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + result_type __u, __v, __n; + const result_type __a1 = (__param._M_malpha + - _RealType(1.0) / _RealType(3.0)); + + do + { + do + { + __n = _M_nd(__urng); + __v = result_type(1.0) + __param._M_a2 * __n; + } + while (__v <= 0.0); + + __v = __v * __v * __v; + __u = __aurng(); + } + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n + && (std::log(__u) > (0.5 * __n * __n + __a1 + * (1.0 - __v + std::log(__v))))); + + if (__param.alpha() == __param._M_malpha) + return __a1 * __v * __param.beta(); + else + { + do + __u = __aurng(); + while (__u == 0.0); + + return (std::pow(__u, result_type(1.0) / __param.alpha()) + * __a1 * __v * __param.beta()); + } + } + + template + template + void + gamma_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + result_type __u, __v, __n; + const result_type __a1 = (__param._M_malpha + - _RealType(1.0) / _RealType(3.0)); + + if (__param.alpha() == __param._M_malpha) + while (__f != __t) + { + do + { + do + { + __n = _M_nd(__urng); + __v = result_type(1.0) + __param._M_a2 * __n; + } + while (__v <= 0.0); + + __v = __v * __v * __v; + __u = __aurng(); + } + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n + && (std::log(__u) > (0.5 * __n * __n + __a1 + * (1.0 - __v + std::log(__v))))); + + *__f++ = __a1 * __v * __param.beta(); + } + else + while (__f != __t) + { + do + { + do + { + __n = _M_nd(__urng); + __v = result_type(1.0) + __param._M_a2 * __n; + } + while (__v <= 0.0); + + __v = __v * __v * __v; + __u = __aurng(); + } + while (__u > result_type(1.0) - 0.0331 * __n * __n * __n * __n + && (std::log(__u) > (0.5 * __n * __n + __a1 + * (1.0 - __v + std::log(__v))))); + + do + __u = __aurng(); + while (__u == 0.0); + + *__f++ = (std::pow(__u, result_type(1.0) / __param.alpha()) + * __a1 * __v * __param.beta()); + } + } + + + template + template + typename weibull_distribution<_RealType>::result_type + weibull_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + return __p.b() * std::pow(-std::log(result_type(1) - __aurng()), + result_type(1) / __p.a()); + } + + template + template + void + weibull_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + auto __inv_a = result_type(1) / __p.a(); + + while (__f != __t) + *__f++ = __p.b() * std::pow(-std::log(result_type(1) - __aurng()), + __inv_a); + } + + + template + template + typename extreme_value_distribution<_RealType>::result_type + extreme_value_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + return __p.a() - __p.b() * std::log(-std::log(result_type(1) + - __aurng())); + } + + template + template + void + extreme_value_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, result_type> + __aurng(__urng); + + while (__f != __t) + *__f++ = __p.a() - __p.b() * std::log(-std::log(result_type(1) + - __aurng())); + } + + + template + void + discrete_distribution<_IntType>::param_type:: + _M_initialize() + { + if (_M_prob.size() < 2) + { + _M_prob.clear(); + return; + } + + const double __sum = std::accumulate(_M_prob.begin(), + _M_prob.end(), 0.0); + // Now normalize the probabilites. + __detail::__normalize(_M_prob.begin(), _M_prob.end(), _M_prob.begin(), + __sum); + // Accumulate partial sums. + _M_cp.reserve(_M_prob.size()); + std::partial_sum(_M_prob.begin(), _M_prob.end(), + std::back_inserter(_M_cp)); + // Make sure the last cumulative probability is one. + _M_cp[_M_cp.size() - 1] = 1.0; + } + + template + template + discrete_distribution<_IntType>::param_type:: + param_type(size_t __nw, double __xmin, double __xmax, _Func __fw) + : _M_prob(), _M_cp() + { + const size_t __n = __nw == 0 ? 1 : __nw; + const double __delta = (__xmax - __xmin) / __n; + + _M_prob.reserve(__n); + for (size_t __k = 0; __k < __nw; ++__k) + _M_prob.push_back(__fw(__xmin + __k * __delta + 0.5 * __delta)); + + _M_initialize(); + } + + template + template + typename discrete_distribution<_IntType>::result_type + discrete_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + if (__param._M_cp.empty()) + return result_type(0); + + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + const double __p = __aurng(); + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + + return __pos - __param._M_cp.begin(); + } + + template + template + void + discrete_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + + if (__param._M_cp.empty()) + { + while (__f != __t) + *__f++ = result_type(0); + return; + } + + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + while (__f != __t) + { + const double __p = __aurng(); + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + + *__f++ = __pos - __param._M_cp.begin(); + } + } + + + template + void + piecewise_constant_distribution<_RealType>::param_type:: + _M_initialize() + { + if (_M_int.size() < 2 + || (_M_int.size() == 2 + && _M_int[0] == _RealType(0) + && _M_int[1] == _RealType(1))) + { + _M_int.clear(); + _M_den.clear(); + return; + } + + const double __sum = std::accumulate(_M_den.begin(), + _M_den.end(), 0.0); + + __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(), + __sum); + + _M_cp.reserve(_M_den.size()); + std::partial_sum(_M_den.begin(), _M_den.end(), + std::back_inserter(_M_cp)); + + // Make sure the last cumulative probability is one. + _M_cp[_M_cp.size() - 1] = 1.0; + + for (size_t __k = 0; __k < _M_den.size(); ++__k) + _M_den[__k] /= _M_int[__k + 1] - _M_int[__k]; + } + + template + template + piecewise_constant_distribution<_RealType>::param_type:: + param_type(_InputIteratorB __bbegin, + _InputIteratorB __bend, + _InputIteratorW __wbegin) + : _M_int(), _M_den(), _M_cp() + { + if (__bbegin != __bend) + { + for (;;) + { + _M_int.push_back(*__bbegin); + ++__bbegin; + if (__bbegin == __bend) + break; + + _M_den.push_back(*__wbegin); + ++__wbegin; + } + } + + _M_initialize(); + } + + template + template + piecewise_constant_distribution<_RealType>::param_type:: + param_type(initializer_list<_RealType> __bl, _Func __fw) + : _M_int(), _M_den(), _M_cp() + { + _M_int.reserve(__bl.size()); + for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter) + _M_int.push_back(*__biter); + + _M_den.reserve(_M_int.size() - 1); + for (size_t __k = 0; __k < _M_int.size() - 1; ++__k) + _M_den.push_back(__fw(0.5 * (_M_int[__k + 1] + _M_int[__k]))); + + _M_initialize(); + } + + template + template + piecewise_constant_distribution<_RealType>::param_type:: + param_type(size_t __nw, _RealType __xmin, _RealType __xmax, _Func __fw) + : _M_int(), _M_den(), _M_cp() + { + const size_t __n = __nw == 0 ? 1 : __nw; + const _RealType __delta = (__xmax - __xmin) / __n; + + _M_int.reserve(__n + 1); + for (size_t __k = 0; __k <= __nw; ++__k) + _M_int.push_back(__xmin + __k * __delta); + + _M_den.reserve(__n); + for (size_t __k = 0; __k < __nw; ++__k) + _M_den.push_back(__fw(_M_int[__k] + 0.5 * __delta)); + + _M_initialize(); + } + + template + template + typename piecewise_constant_distribution<_RealType>::result_type + piecewise_constant_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + const double __p = __aurng(); + if (__param._M_cp.empty()) + return __p; + + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + const size_t __i = __pos - __param._M_cp.begin(); + + const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; + + return __param._M_int[__i] + (__p - __pref) / __param._M_den[__i]; + } + + template + template + void + piecewise_constant_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + if (__param._M_cp.empty()) + { + while (__f != __t) + *__f++ = __aurng(); + return; + } + + while (__f != __t) + { + const double __p = __aurng(); + + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + const size_t __i = __pos - __param._M_cp.begin(); + + const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; + + *__f++ = (__param._M_int[__i] + + (__p - __pref) / __param._M_den[__i]); + } + } + + + template + void + piecewise_linear_distribution<_RealType>::param_type:: + _M_initialize() + { + if (_M_int.size() < 2 + || (_M_int.size() == 2 + && _M_int[0] == _RealType(0) + && _M_int[1] == _RealType(1) + && _M_den[0] == _M_den[1])) + { + _M_int.clear(); + _M_den.clear(); + return; + } + + double __sum = 0.0; + _M_cp.reserve(_M_int.size() - 1); + _M_m.reserve(_M_int.size() - 1); + for (size_t __k = 0; __k < _M_int.size() - 1; ++__k) + { + const _RealType __delta = _M_int[__k + 1] - _M_int[__k]; + __sum += 0.5 * (_M_den[__k + 1] + _M_den[__k]) * __delta; + _M_cp.push_back(__sum); + _M_m.push_back((_M_den[__k + 1] - _M_den[__k]) / __delta); + } + + // Now normalize the densities... + __detail::__normalize(_M_den.begin(), _M_den.end(), _M_den.begin(), + __sum); + // ... and partial sums... + __detail::__normalize(_M_cp.begin(), _M_cp.end(), _M_cp.begin(), __sum); + // ... and slopes. + __detail::__normalize(_M_m.begin(), _M_m.end(), _M_m.begin(), __sum); + + // Make sure the last cumulative probablility is one. + _M_cp[_M_cp.size() - 1] = 1.0; + } + + template + template + piecewise_linear_distribution<_RealType>::param_type:: + param_type(_InputIteratorB __bbegin, + _InputIteratorB __bend, + _InputIteratorW __wbegin) + : _M_int(), _M_den(), _M_cp(), _M_m() + { + for (; __bbegin != __bend; ++__bbegin, ++__wbegin) + { + _M_int.push_back(*__bbegin); + _M_den.push_back(*__wbegin); + } + + _M_initialize(); + } + + template + template + piecewise_linear_distribution<_RealType>::param_type:: + param_type(initializer_list<_RealType> __bl, _Func __fw) + : _M_int(), _M_den(), _M_cp(), _M_m() + { + _M_int.reserve(__bl.size()); + _M_den.reserve(__bl.size()); + for (auto __biter = __bl.begin(); __biter != __bl.end(); ++__biter) + { + _M_int.push_back(*__biter); + _M_den.push_back(__fw(*__biter)); + } + + _M_initialize(); + } + + template + template + piecewise_linear_distribution<_RealType>::param_type:: + param_type(size_t __nw, _RealType __xmin, _RealType __xmax, _Func __fw) + : _M_int(), _M_den(), _M_cp(), _M_m() + { + const size_t __n = __nw == 0 ? 1 : __nw; + const _RealType __delta = (__xmax - __xmin) / __n; + + _M_int.reserve(__n + 1); + _M_den.reserve(__n + 1); + for (size_t __k = 0; __k <= __nw; ++__k) + { + _M_int.push_back(__xmin + __k * __delta); + _M_den.push_back(__fw(_M_int[__k] + __delta)); + } + + _M_initialize(); + } + + template + template + typename piecewise_linear_distribution<_RealType>::result_type + piecewise_linear_distribution<_RealType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __detail::_Adaptor<_UniformRandomNumberGenerator, double> + __aurng(__urng); + + const double __p = __aurng(); + if (__param._M_cp.empty()) + return __p; + + auto __pos = std::lower_bound(__param._M_cp.begin(), + __param._M_cp.end(), __p); + const size_t __i = __pos - __param._M_cp.begin(); + + const double __pref = __i > 0 ? __param._M_cp[__i - 1] : 0.0; + + const double __a = 0.5 * __param._M_m[__i]; + const double __b = __param._M_den[__i]; + const double __cm = __p - __pref; + + _RealType __x = __param._M_int[__i]; + if (__a == 0) + __x += __cm / __b; + else + { + const double __d = __b * __b + 4.0 * __a * __cm; + __x += 0.5 * (std::sqrt(__d) - __b) / __a; + } + + return __x; + } + + template + template + void + piecewise_linear_distribution<_RealType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + // We could duplicate everything from operator()... + while (__f != __t) + *__f++ = this->operator()(__urng, __param); + } + + + template + seed_seq::seed_seq(std::initializer_list<_IntType> __il) + { + for (auto __iter = __il.begin(); __iter != __il.end(); ++__iter) + _M_v.push_back(__detail::__mod::__value>(*__iter)); + } + + template + seed_seq::seed_seq(_InputIterator __begin, _InputIterator __end) + { + for (_InputIterator __iter = __begin; __iter != __end; ++__iter) + _M_v.push_back(__detail::__mod::__value>(*__iter)); + } + + template + void + seed_seq::generate(_RandomAccessIterator __begin, + _RandomAccessIterator __end) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _Type; + + if (__begin == __end) + return; + + std::fill(__begin, __end, _Type(0x8b8b8b8bu)); + + const size_t __n = __end - __begin; + const size_t __s = _M_v.size(); + const size_t __t = (__n >= 623) ? 11 + : (__n >= 68) ? 7 + : (__n >= 39) ? 5 + : (__n >= 7) ? 3 + : (__n - 1) / 2; + const size_t __p = (__n - __t) / 2; + const size_t __q = __p + __t; + const size_t __m = std::max(size_t(__s + 1), __n); + + for (size_t __k = 0; __k < __m; ++__k) + { + _Type __arg = (__begin[__k % __n] + ^ __begin[(__k + __p) % __n] + ^ __begin[(__k - 1) % __n]); + _Type __r1 = __arg ^ (__arg >> 27); + __r1 = __detail::__mod<_Type, + __detail::_Shift<_Type, 32>::__value>(1664525u * __r1); + _Type __r2 = __r1; + if (__k == 0) + __r2 += __s; + else if (__k <= __s) + __r2 += __k % __n + _M_v[__k - 1]; + else + __r2 += __k % __n; + __r2 = __detail::__mod<_Type, + __detail::_Shift<_Type, 32>::__value>(__r2); + __begin[(__k + __p) % __n] += __r1; + __begin[(__k + __q) % __n] += __r2; + __begin[__k % __n] = __r2; + } + + for (size_t __k = __m; __k < __m + __n; ++__k) + { + _Type __arg = (__begin[__k % __n] + + __begin[(__k + __p) % __n] + + __begin[(__k - 1) % __n]); + _Type __r3 = __arg ^ (__arg >> 27); + __r3 = __detail::__mod<_Type, + __detail::_Shift<_Type, 32>::__value>(1566083941u * __r3); + _Type __r4 = __r3 - __k % __n; + __r4 = __detail::__mod<_Type, + __detail::_Shift<_Type, 32>::__value>(__r4); + __begin[(__k + __p) % __n] ^= __r3; + __begin[(__k + __q) % __n] ^= __r4; + __begin[__k % __n] = __r4; + } + } + + template + _RealType + generate_canonical(_UniformRandomNumberGenerator& __urng) + { + static_assert(std::is_floating_point<_RealType>::value, + "template argument must be a floating point type"); + + const size_t __b + = std::min(static_cast(std::numeric_limits<_RealType>::digits), + __bits); + const long double __r = static_cast(__urng.max()) + - static_cast(__urng.min()) + 1.0L; + const size_t __log2r = std::log(__r) / std::log(2.0L); + const size_t __m = std::max(1UL, + (__b + __log2r - 1UL) / __log2r); + _RealType __ret; + _RealType __sum = _RealType(0); + _RealType __tmp = _RealType(1); + for (size_t __k = __m; __k != 0; --__k) + { + __sum += _RealType(__urng() - __urng.min()) * __tmp; + __tmp *= __r; + } + __ret = __sum / __tmp; + if (__builtin_expect(__ret >= _RealType(1), 0)) + { +#if _GLIBCXX_USE_C99_MATH_TR1 + __ret = std::nextafter(_RealType(1), _RealType(0)); +#else + __ret = _RealType(1) + - std::numeric_limits<_RealType>::epsilon() / _RealType(2); +#endif + } + return __ret; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/range_access.h b/resources/sources/avr-libstdcpp/include/bits/range_access.h new file mode 100644 index 000000000..3919183c5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/range_access.h @@ -0,0 +1,1148 @@ +// -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/range_access.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + */ + +#ifndef _GLIBCXX_RANGE_ACCESS_H +#define _GLIBCXX_RANGE_ACCESS_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Return an iterator pointing to the first element of + * the container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + begin(_Container& __cont) -> decltype(__cont.begin()) + { return __cont.begin(); } + + /** + * @brief Return an iterator pointing to the first element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + begin(const _Container& __cont) -> decltype(__cont.begin()) + { return __cont.begin(); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + end(_Container& __cont) -> decltype(__cont.end()) + { return __cont.end(); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + end(const _Container& __cont) -> decltype(__cont.end()) + { return __cont.end(); } + + /** + * @brief Return an iterator pointing to the first element of the array. + * @param __arr Array. + */ + template + inline _GLIBCXX14_CONSTEXPR _Tp* + begin(_Tp (&__arr)[_Nm]) + { return __arr; } + + /** + * @brief Return an iterator pointing to one past the last element + * of the array. + * @param __arr Array. + */ + template + inline _GLIBCXX14_CONSTEXPR _Tp* + end(_Tp (&__arr)[_Nm]) + { return __arr + _Nm; } + +#if __cplusplus >= 201402L + + template class valarray; + // These overloads must be declared for cbegin and cend to use them. + template _Tp* begin(valarray<_Tp>&); + template const _Tp* begin(const valarray<_Tp>&); + template _Tp* end(valarray<_Tp>&); + template const _Tp* end(const valarray<_Tp>&); + + /** + * @brief Return an iterator pointing to the first element of + * the const container. + * @param __cont Container. + */ + template + inline constexpr auto + cbegin(const _Container& __cont) noexcept(noexcept(std::begin(__cont))) + -> decltype(std::begin(__cont)) + { return std::begin(__cont); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the const container. + * @param __cont Container. + */ + template + inline constexpr auto + cend(const _Container& __cont) noexcept(noexcept(std::end(__cont))) + -> decltype(std::end(__cont)) + { return std::end(__cont); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + rbegin(_Container& __cont) -> decltype(__cont.rbegin()) + { return __cont.rbegin(); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + rbegin(const _Container& __cont) -> decltype(__cont.rbegin()) + { return __cont.rbegin(); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + rend(_Container& __cont) -> decltype(__cont.rend()) + { return __cont.rend(); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + rend(const _Container& __cont) -> decltype(__cont.rend()) + { return __cont.rend(); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the array. + * @param __arr Array. + */ + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> + rbegin(_Tp (&__arr)[_Nm]) + { return reverse_iterator<_Tp*>(__arr + _Nm); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the array. + * @param __arr Array. + */ + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Tp*> + rend(_Tp (&__arr)[_Nm]) + { return reverse_iterator<_Tp*>(__arr); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the initializer_list. + * @param __il initializer_list. + */ + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator + rbegin(initializer_list<_Tp> __il) + { return reverse_iterator(__il.end()); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the initializer_list. + * @param __il initializer_list. + */ + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator + rend(initializer_list<_Tp> __il) + { return reverse_iterator(__il.begin()); } + + /** + * @brief Return a reverse iterator pointing to the last element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + crbegin(const _Container& __cont) -> decltype(std::rbegin(__cont)) + { return std::rbegin(__cont); } + + /** + * @brief Return a reverse iterator pointing one past the first element of + * the const container. + * @param __cont Container. + */ + template + inline _GLIBCXX17_CONSTEXPR auto + crend(const _Container& __cont) -> decltype(std::rend(__cont)) + { return std::rend(__cont); } + +#endif // C++14 + +#if __cplusplus >= 201703L +#define __cpp_lib_nonmember_container_access 201411 + + /** + * @brief Return the size of a container. + * @param __cont Container. + */ + template + constexpr auto + size(const _Container& __cont) noexcept(noexcept(__cont.size())) + -> decltype(__cont.size()) + { return __cont.size(); } + + /** + * @brief Return the size of an array. + */ + template + constexpr size_t + size(const _Tp (&)[_Nm]) noexcept + { return _Nm; } + + /** + * @brief Return whether a container is empty. + * @param __cont Container. + */ + template + [[nodiscard]] constexpr auto + empty(const _Container& __cont) noexcept(noexcept(__cont.empty())) + -> decltype(__cont.empty()) + { return __cont.empty(); } + + /** + * @brief Return whether an array is empty (always false). + */ + template + [[nodiscard]] constexpr bool + empty(const _Tp (&)[_Nm]) noexcept + { return false; } + + /** + * @brief Return whether an initializer_list is empty. + * @param __il Initializer list. + */ + template + [[nodiscard]] constexpr bool + empty(initializer_list<_Tp> __il) noexcept + { return __il.size() == 0;} + + /** + * @brief Return the data pointer of a container. + * @param __cont Container. + */ + template + constexpr auto + data(_Container& __cont) noexcept(noexcept(__cont.data())) + -> decltype(__cont.data()) + { return __cont.data(); } + + /** + * @brief Return the data pointer of a const container. + * @param __cont Container. + */ + template + constexpr auto + data(const _Container& __cont) noexcept(noexcept(__cont.data())) + -> decltype(__cont.data()) + { return __cont.data(); } + + /** + * @brief Return the data pointer of an array. + * @param __array Array. + */ + template + constexpr _Tp* + data(_Tp (&__array)[_Nm]) noexcept + { return __array; } + + /** + * @brief Return the data pointer of an initializer list. + * @param __il Initializer list. + */ + template + constexpr const _Tp* + data(initializer_list<_Tp> __il) noexcept + { return __il.begin(); } + +#endif // C++17 + +#if __cplusplus > 201703L +#define __cpp_lib_ssize 201902L + template + constexpr auto + ssize(const _Container& __cont) + noexcept(noexcept(__cont.size())) + -> common_type_t> + { + using type = make_signed_t; + return static_cast>(__cont.size()); + } + + template + constexpr ptrdiff_t + ssize(const _Tp (&)[_Num]) noexcept + { return _Num; } + +#ifdef __cpp_lib_concepts +namespace ranges +{ + template + inline constexpr bool disable_sized_range = false; + + template + inline constexpr bool enable_borrowed_range = false; + + template + extern const bool enable_view; + + namespace __detail + { + template + constexpr make_unsigned_t<_Tp> + __to_unsigned_like(_Tp __t) noexcept + { return __t; } + + template> + using __make_unsigned_like_t + = conditional_t<_MaxDiff, __max_size_type, make_unsigned_t<_Tp>>; + + // Part of the constraints of ranges::borrowed_range + template + concept __maybe_borrowed_range + = is_lvalue_reference_v<_Tp> + || enable_borrowed_range>; + + } // namespace __detail + + namespace __cust_access + { + using std::ranges::__detail::__maybe_borrowed_range; + using std::__detail::__class_or_enum; + using std::__detail::__decay_copy; + using std::__detail::__member_begin; + using std::__detail::__adl_begin; + + struct _Begin + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_array_v>) + return true; + else if constexpr (__member_begin<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().begin())); + else + return noexcept(__decay_copy(begin(std::declval<_Tp&>()))); + } + + public: + template<__maybe_borrowed_range _Tp> + requires is_array_v> || __member_begin<_Tp> + || __adl_begin<_Tp> + constexpr auto + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (is_array_v>) + { + static_assert(is_lvalue_reference_v<_Tp>); + using _Up = remove_all_extents_t>; + static_assert(sizeof(_Up) != 0, "not array of incomplete type"); + return __t + 0; + } + else if constexpr (__member_begin<_Tp>) + return __t.begin(); + else + return begin(__t); + } + }; + + template + concept __member_end = requires(_Tp& __t) + { + { __decay_copy(__t.end()) } + -> sentinel_for(__t)))>; + }; + + void end(auto&) = delete; + void end(const auto&) = delete; + + template + concept __adl_end = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(end(__t)) } + -> sentinel_for(__t)))>; + }; + + struct _End + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_bounded_array_v>) + return true; + else if constexpr (__member_end<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().end())); + else + return noexcept(__decay_copy(end(std::declval<_Tp&>()))); + } + + public: + template<__maybe_borrowed_range _Tp> + requires is_bounded_array_v> || __member_end<_Tp> + || __adl_end<_Tp> + constexpr auto + operator()(_Tp&& __t) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (is_bounded_array_v>) + { + static_assert(is_lvalue_reference_v<_Tp>); + return __t + extent_v>; + } + else if constexpr (__member_end<_Tp>) + return __t.end(); + else + return end(__t); + } + }; + + template + constexpr decltype(auto) + __as_const(_Tp&& __t) noexcept + { + if constexpr (is_lvalue_reference_v<_Tp>) + return static_cast&>(__t); + else + return static_cast(__t); + } + + struct _CBegin + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Begin{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _Begin{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _Begin{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + struct _CEnd + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_End{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _End{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _End{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + template + concept __member_rbegin = requires(_Tp& __t) + { + { __decay_copy(__t.rbegin()) } -> input_or_output_iterator; + }; + + void rbegin(auto&) = delete; + void rbegin(const auto&) = delete; + + template + concept __adl_rbegin = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(rbegin(__t)) } -> input_or_output_iterator; + }; + + template + concept __reversable = requires(_Tp& __t) + { + { _Begin{}(__t) } -> bidirectional_iterator; + { _End{}(__t) } -> same_as; + }; + + struct _RBegin + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_rbegin<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().rbegin())); + else if constexpr (__adl_rbegin<_Tp>) + return noexcept(__decay_copy(rbegin(std::declval<_Tp&>()))); + else + { + if constexpr (noexcept(_End{}(std::declval<_Tp&>()))) + { + using _It = decltype(_End{}(std::declval<_Tp&>())); + // std::reverse_iterator copy-initializes its member. + return is_nothrow_copy_constructible_v<_It>; + } + else + return false; + } + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_rbegin<_Tp> || __adl_rbegin<_Tp> || __reversable<_Tp> + constexpr auto + operator()(_Tp&& __t) const + noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_rbegin<_Tp>) + return __t.rbegin(); + else if constexpr (__adl_rbegin<_Tp>) + return rbegin(__t); + else + return std::make_reverse_iterator(_End{}(__t)); + } + }; + + template + concept __member_rend = requires(_Tp& __t) + { + { __decay_copy(__t.rend()) } + -> sentinel_for; + }; + + void rend(auto&) = delete; + void rend(const auto&) = delete; + + template + concept __adl_rend = __class_or_enum> + && requires(_Tp& __t) + { + { __decay_copy(rend(__t)) } + -> sentinel_for(__t)))>; + }; + + struct _REnd + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_rend<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp&>().rend())); + else if constexpr (__adl_rend<_Tp>) + return noexcept(__decay_copy(rend(std::declval<_Tp&>()))); + else + { + if constexpr (noexcept(_Begin{}(std::declval<_Tp&>()))) + { + using _It = decltype(_Begin{}(std::declval<_Tp&>())); + // std::reverse_iterator copy-initializes its member. + return is_nothrow_copy_constructible_v<_It>; + } + else + return false; + } + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_rend<_Tp> || __adl_rend<_Tp> || __reversable<_Tp> + constexpr auto + operator()(_Tp&& __t) const + noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_rend<_Tp>) + return __t.rend(); + else if constexpr (__adl_rend<_Tp>) + return rend(__t); + else + return std::make_reverse_iterator(_Begin{}(__t)); + } + }; + + struct _CRBegin + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_RBegin{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _RBegin{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _RBegin{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + struct _CREnd + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_REnd{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _REnd{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _REnd{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + template + concept __member_size = !disable_sized_range> + && requires(_Tp&& __t) + { + { __decay_copy(std::forward<_Tp>(__t).size()) } + -> __detail::__is_integer_like; + }; + + void size(auto&) = delete; + void size(const auto&) = delete; + + template + concept __adl_size = __class_or_enum> + && !disable_sized_range> + && requires(_Tp&& __t) + { + { __decay_copy(size(std::forward<_Tp>(__t))) } + -> __detail::__is_integer_like; + }; + + template + concept __sentinel_size = requires(_Tp&& __t) + { + { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator; + + { _End{}(std::forward<_Tp>(__t)) } + -> sized_sentinel_for(__t)))>; + }; + + struct _Size + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (is_bounded_array_v>) + return true; + else if constexpr (__member_size<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp>().size())); + else if constexpr (__adl_size<_Tp>) + return noexcept(__decay_copy(size(std::declval<_Tp>()))); + else if constexpr (__sentinel_size<_Tp>) + return noexcept(_End{}(std::declval<_Tp>()) + - _Begin{}(std::declval<_Tp>())); + } + + public: + template + requires is_bounded_array_v> + || __member_size<_Tp> || __adl_size<_Tp> || __sentinel_size<_Tp> + constexpr auto + operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (is_bounded_array_v>) + { + return extent_v>; + } + else if constexpr (__member_size<_Tp>) + return std::forward<_Tp>(__e).size(); + else if constexpr (__adl_size<_Tp>) + return size(std::forward<_Tp>(__e)); + else if constexpr (__sentinel_size<_Tp>) + return __detail::__to_unsigned_like( + _End{}(std::forward<_Tp>(__e)) + - _Begin{}(std::forward<_Tp>(__e))); + } + }; + + struct _SSize + { + template + requires requires (_Tp&& __e) + { + _Begin{}(std::forward<_Tp>(__e)); + _Size{}(std::forward<_Tp>(__e)); + } + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Size{}(std::forward<_Tp>(__e)))) + { + using __iter_type = decltype(_Begin{}(std::forward<_Tp>(__e))); + using __diff_type = iter_difference_t<__iter_type>; + using __gnu_cxx::__int_traits; + auto __size = _Size{}(std::forward<_Tp>(__e)); + if constexpr (integral<__diff_type>) + { + if constexpr (__int_traits<__diff_type>::__digits + < __int_traits::__digits) + return static_cast(__size); + } + return static_cast<__diff_type>(__size); + } + }; + + template + concept __member_empty = requires(_Tp&& __t) + { bool(std::forward<_Tp>(__t).empty()); }; + + template + concept __size0_empty = requires(_Tp&& __t) + { _Size{}(std::forward<_Tp>(__t)) == 0; }; + + template + concept __eq_iter_empty = requires(_Tp&& __t) + { + { _Begin{}(std::forward<_Tp>(__t)) } -> forward_iterator; + bool(_Begin{}(std::forward<_Tp>(__t)) + == _End{}(std::forward<_Tp>(__t))); + }; + + struct _Empty + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_empty<_Tp>) + return noexcept(std::declval<_Tp>().empty()); + else if constexpr (__size0_empty<_Tp>) + return noexcept(_Size{}(std::declval<_Tp>()) == 0); + else + return noexcept(bool(_Begin{}(std::declval<_Tp>()) + == _End{}(std::declval<_Tp>()))); + } + + public: + template + requires __member_empty<_Tp> || __size0_empty<_Tp> + || __eq_iter_empty<_Tp> + constexpr bool + operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_empty<_Tp>) + return bool(std::forward<_Tp>(__e).empty()); + else if constexpr (__size0_empty<_Tp>) + return _Size{}(std::forward<_Tp>(__e)) == 0; + else + return bool(_Begin{}(std::forward<_Tp>(__e)) + == _End{}(std::forward<_Tp>(__e))); + } + }; + + template + concept __pointer_to_object = is_pointer_v<_Tp> + && is_object_v>; + + template + concept __member_data = is_lvalue_reference_v<_Tp> + && requires(_Tp __t) { { __t.data() } -> __pointer_to_object; }; + + template + concept __begin_data = requires(_Tp&& __t) + { { _Begin{}(std::forward<_Tp>(__t)) } -> contiguous_iterator; }; + + struct _Data + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__member_data<_Tp>) + return noexcept(__decay_copy(std::declval<_Tp>().data())); + else + return noexcept(_Begin{}(std::declval<_Tp>())); + } + + public: + template<__maybe_borrowed_range _Tp> + requires __member_data<_Tp> || __begin_data<_Tp> + constexpr auto + operator()(_Tp&& __e) const noexcept(_S_noexcept<_Tp>()) + { + if constexpr (__member_data<_Tp>) + return __e.data(); + else + return std::to_address(_Begin{}(std::forward<_Tp>(__e))); + } + }; + + struct _CData + { + template + constexpr auto + operator()(_Tp&& __e) const + noexcept(noexcept(_Data{}(__cust_access::__as_const((_Tp&&)__e)))) + requires requires { _Data{}(__cust_access::__as_const((_Tp&&)__e)); } + { + return _Data{}(__cust_access::__as_const(std::forward<_Tp>(__e))); + } + }; + + } // namespace __cust_access + + inline namespace __cust + { + inline constexpr __cust_access::_Begin begin{}; + inline constexpr __cust_access::_End end{}; + inline constexpr __cust_access::_CBegin cbegin{}; + inline constexpr __cust_access::_CEnd cend{}; + inline constexpr __cust_access::_RBegin rbegin{}; + inline constexpr __cust_access::_REnd rend{}; + inline constexpr __cust_access::_CRBegin crbegin{}; + inline constexpr __cust_access::_CREnd crend{}; + inline constexpr __cust_access::_Size size{}; + inline constexpr __cust_access::_SSize ssize{}; + inline constexpr __cust_access::_Empty empty{}; + inline constexpr __cust_access::_Data data{}; + inline constexpr __cust_access::_CData cdata{}; + } + + /// [range.range] The range concept. + template + concept range = requires(_Tp& __t) + { + ranges::begin(__t); + ranges::end(__t); + }; + + /// [range.range] The borrowed_range concept. + template + concept borrowed_range + = range<_Tp> && __detail::__maybe_borrowed_range<_Tp>; + + template + using iterator_t = std::__detail::__range_iter_t<_Tp>; + + template + using sentinel_t = decltype(ranges::end(std::declval<_Range&>())); + + template + using range_difference_t = iter_difference_t>; + + template + using range_value_t = iter_value_t>; + + template + using range_reference_t = iter_reference_t>; + + template + using range_rvalue_reference_t + = iter_rvalue_reference_t>; + + /// [range.sized] The sized_range concept. + template + concept sized_range = range<_Tp> + && requires(_Tp& __t) { ranges::size(__t); }; + + template + using range_size_t = decltype(ranges::size(std::declval<_Range&>())); + + // [range.refinements] + + /// A range for which ranges::begin returns an output iterator. + template + concept output_range + = range<_Range> && output_iterator, _Tp>; + + /// A range for which ranges::begin returns an input iterator. + template + concept input_range = range<_Tp> && input_iterator>; + + /// A range for which ranges::begin returns a forward iterator. + template + concept forward_range + = input_range<_Tp> && forward_iterator>; + + /// A range for which ranges::begin returns a bidirectional iterator. + template + concept bidirectional_range + = forward_range<_Tp> && bidirectional_iterator>; + + /// A range for which ranges::begin returns a random access iterator. + template + concept random_access_range + = bidirectional_range<_Tp> && random_access_iterator>; + + /// A range for which ranges::begin returns a contiguous iterator. + template + concept contiguous_range + = random_access_range<_Tp> && contiguous_iterator> + && requires(_Tp& __t) + { + { ranges::data(__t) } -> same_as>>; + }; + + /// A range for which ranges::begin and ranges::end return the same type. + template + concept common_range + = range<_Tp> && same_as, sentinel_t<_Tp>>; + + // [range.iter.ops] range iterator operations + + template + constexpr void + advance(_It& __it, iter_difference_t<_It> __n) + { + if constexpr (random_access_iterator<_It>) + __it += __n; + else if constexpr (bidirectional_iterator<_It>) + { + if (__n > 0) + { + do + { + ++__it; + } + while (--__n); + } + else if (__n < 0) + { + do + { + --__it; + } + while (++__n); + } + } + else + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated() && __n < 0) + throw "attempt to decrement a non-bidirectional iterator"; +#endif + __glibcxx_assert(__n >= 0); + while (__n-- > 0) + ++__it; + } + } + + template _Sent> + constexpr void + advance(_It& __it, _Sent __bound) + { + if constexpr (assignable_from<_It&, _Sent>) + __it = std::move(__bound); + else if constexpr (sized_sentinel_for<_Sent, _It>) + ranges::advance(__it, __bound - __it); + else + { + while (__it != __bound) + ++__it; + } + } + + template _Sent> + constexpr iter_difference_t<_It> + advance(_It& __it, iter_difference_t<_It> __n, _Sent __bound) + { + if constexpr (sized_sentinel_for<_Sent, _It>) + { + const auto __diff = __bound - __it; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated() + && !(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0))) + throw "inconsistent directions for distance and bound"; +#endif + // n and bound must not lead in opposite directions: + __glibcxx_assert(__n == 0 || __diff == 0 || (__n < 0 == __diff < 0)); + const auto __absdiff = __diff < 0 ? -__diff : __diff; + const auto __absn = __n < 0 ? -__n : __n;; + if (__absn >= __absdiff) + { + ranges::advance(__it, __bound); + return __n - __diff; + } + else + { + ranges::advance(__it, __n); + return 0; + } + } + else if (__it == __bound || __n == 0) + return iter_difference_t<_It>(0); + else if (__n > 0) + { + iter_difference_t<_It> __m = 0; + do + { + ++__it; + ++__m; + } + while (__m != __n && __it != __bound); + return __n - __m; + } + else if constexpr (bidirectional_iterator<_It> && same_as<_It, _Sent>) + { + iter_difference_t<_It> __m = 0; + do + { + --__it; + --__m; + } + while (__m != __n && __it != __bound); + return __n - __m; + } + else + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated() && __n < 0) + throw "attempt to decrement a non-bidirectional iterator"; +#endif + __glibcxx_assert(__n >= 0); + return __n; + } + } + + template _Sent> + constexpr iter_difference_t<_It> + distance(_It __first, _Sent __last) + { + if constexpr (sized_sentinel_for<_Sent, _It>) + return __last - __first; + else + { + iter_difference_t<_It> __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } + } + + template + constexpr range_difference_t<_Range> + distance(_Range&& __r) + { + if constexpr (sized_range<_Range>) + return static_cast>(ranges::size(__r)); + else + return ranges::distance(ranges::begin(__r), ranges::end(__r)); + } + + template + constexpr _It + next(_It __x) + { + ++__x; + return __x; + } + + template + constexpr _It + next(_It __x, iter_difference_t<_It> __n) + { + ranges::advance(__x, __n); + return __x; + } + + template _Sent> + constexpr _It + next(_It __x, _Sent __bound) + { + ranges::advance(__x, __bound); + return __x; + } + + template _Sent> + constexpr _It + next(_It __x, iter_difference_t<_It> __n, _Sent __bound) + { + ranges::advance(__x, __n, __bound); + return __x; + } + + template + constexpr _It + prev(_It __x) + { + --__x; + return __x; + } + + template + constexpr _It + prev(_It __x, iter_difference_t<_It> __n) + { + ranges::advance(__x, -__n); + return __x; + } + + template + constexpr _It + prev(_It __x, iter_difference_t<_It> __n, _It __bound) + { + ranges::advance(__x, -__n, __bound); + return __x; + } + +} // namespace ranges +#endif // library concepts +#endif // C++20 +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _GLIBCXX_RANGE_ACCESS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/range_cmp.h b/resources/sources/avr-libstdcpp/include/bits/range_cmp.h new file mode 100644 index 000000000..0587c599c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/range_cmp.h @@ -0,0 +1,195 @@ +// Concept-constrained comparison implementations -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/range_cmp.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _RANGE_CMP_H +#define _RANGE_CMP_H 1 + +#if __cplusplus > 201703L +# include +# include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct __is_transparent; // not defined + + // Define std::identity here so that and + // don't need to include to get it. + + /// [func.identity] The identity function. + struct identity + { + template + constexpr _Tp&& + operator()(_Tp&& __t) const noexcept + { return std::forward<_Tp>(__t); } + + using is_transparent = __is_transparent; + }; + +#ifdef __cpp_lib_concepts +// Define this here, included by all the headers that need to define it. +#define __cpp_lib_ranges 201911L + +namespace ranges +{ + namespace __detail + { + // BUILTIN-PTR-CMP(T, ==, U) + template + concept __eq_builtin_ptr_cmp + = requires (_Tp&& __t, _Up&& __u) { { __t == __u } -> same_as; } + && convertible_to<_Tp, const volatile void*> + && convertible_to<_Up, const volatile void*> + && (! requires(_Tp&& __t, _Up&& __u) + { operator==(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + && + ! requires(_Tp&& __t, _Up&& __u) + { std::forward<_Tp>(__t).operator==(std::forward<_Up>(__u)); }); + + // BUILTIN-PTR-CMP(T, <, U) + template + concept __less_builtin_ptr_cmp + = requires (_Tp&& __t, _Up&& __u) { { __t < __u } -> same_as; } + && convertible_to<_Tp, const volatile void*> + && convertible_to<_Up, const volatile void*> + && (! requires(_Tp&& __t, _Up&& __u) + { operator<(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + && ! requires(_Tp&& __t, _Up&& __u) + { std::forward<_Tp>(__t).operator<(std::forward<_Up>(__u)); }); + } // namespace __detail + + // [range.cmp] Concept-constrained comparisons + + /// ranges::equal_to function object type. + struct equal_to + { + template + requires equality_comparable_with<_Tp, _Up> + || __detail::__eq_builtin_ptr_cmp<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() == std::declval<_Up>())) + { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } + + using is_transparent = __is_transparent; + }; + + /// ranges::not_equal_to function object type. + struct not_equal_to + { + template + requires equality_comparable_with<_Tp, _Up> + || __detail::__eq_builtin_ptr_cmp<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() == std::declval<_Tp>())) + { return !equal_to{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::less function object type. + struct less + { + template + requires totally_ordered_with<_Tp, _Up> + || __detail::__less_builtin_ptr_cmp<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) + { + if constexpr (__detail::__less_builtin_ptr_cmp<_Tp, _Up>) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return __t < __u; +#endif + auto __x = reinterpret_cast<__UINTPTR_TYPE__>( + static_cast(std::forward<_Tp>(__t))); + auto __y = reinterpret_cast<__UINTPTR_TYPE__>( + static_cast(std::forward<_Up>(__u))); + return __x < __y; + } + else + return std::forward<_Tp>(__t) < std::forward<_Up>(__u); + } + + using is_transparent = __is_transparent; + }; + + /// ranges::greater function object type. + struct greater + { + template + requires totally_ordered_with<_Tp, _Up> + || __detail::__less_builtin_ptr_cmp<_Up, _Tp> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) + { return less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::greater_equal function object type. + struct greater_equal + { + template + requires totally_ordered_with<_Tp, _Up> + || __detail::__less_builtin_ptr_cmp<_Tp, _Up> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() < std::declval<_Up>())) + { return !less{}(std::forward<_Tp>(__t), std::forward<_Up>(__u)); } + + using is_transparent = __is_transparent; + }; + + /// ranges::less_equal function object type. + struct less_equal + { + template + requires totally_ordered_with<_Tp, _Up> + || __detail::__less_builtin_ptr_cmp<_Up, _Tp> + constexpr bool + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Up>() < std::declval<_Tp>())) + { return !less{}(std::forward<_Up>(__u), std::forward<_Tp>(__t)); } + + using is_transparent = __is_transparent; + }; + +} // namespace ranges +#endif // library concepts +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 +#endif // _RANGE_CMP_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h b/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h new file mode 100644 index 000000000..4d4f74016 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/ranges_algo.h @@ -0,0 +1,3792 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_algo.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _RANGES_ALGO_H +#define _RANGES_ALGO_H 1 + +#if __cplusplus > 201703L + +#include +#include // concept uniform_random_bit_generator + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr auto + __make_comp_proj(_Comp& __comp, _Proj& __proj) + { + return [&] (auto&& __lhs, auto&& __rhs) -> bool { + using _TL = decltype(__lhs); + using _TR = decltype(__rhs); + return std::__invoke(__comp, + std::__invoke(__proj, std::forward<_TL>(__lhs)), + std::__invoke(__proj, std::forward<_TR>(__rhs))); + }; + } + + template + constexpr auto + __make_pred_proj(_Pred& __pred, _Proj& __proj) + { + return [&] (_Tp&& __arg) -> bool { + return std::__invoke(__pred, + std::__invoke(__proj, std::forward<_Tp>(__arg))); + }; + } + } // namespace __detail + + struct __all_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __all_of_fn all_of{}; + + struct __any_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return true; + return false; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __any_of_fn any_of{}; + + struct __none_of_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __none_of_fn none_of{}; + + template + struct in_fun_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Fp fun; + + template + requires convertible_to + && convertible_to + constexpr + operator in_fun_result<_Iter2, _F2p>() const & + { return {in, fun}; } + + template + requires convertible_to<_Iter, _Iter2> && convertible_to<_Fp, _F2p> + constexpr + operator in_fun_result<_Iter2, _F2p>() && + { return {std::move(in), std::move(fun)}; } + }; + + template + using for_each_result = in_fun_result<_Iter, _Fp>; + + struct __for_each_fn + { + template _Sent, + typename _Proj = identity, + indirectly_unary_invocable> _Fun> + constexpr for_each_result<_Iter, _Fun> + operator()(_Iter __first, _Sent __last, _Fun __f, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + std::__invoke(__f, std::__invoke(__proj, *__first)); + return { std::move(__first), std::move(__f) }; + } + + template, _Proj>> + _Fun> + constexpr for_each_result, _Fun> + operator()(_Range&& __r, _Fun __f, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__f), std::move(__proj)); + } + }; + + inline constexpr __for_each_fn for_each{}; + + template + using for_each_n_result = in_fun_result<_Iter, _Fp>; + + struct __for_each_n_fn + { + template> _Fun> + constexpr for_each_n_result<_Iter, _Fun> + operator()(_Iter __first, iter_difference_t<_Iter> __n, + _Fun __f, _Proj __proj = {}) const + { + if constexpr (random_access_iterator<_Iter>) + { + if (__n <= 0) + return {std::move(__first), std::move(__f)}; + auto __last = __first + __n; + return ranges::for_each(std::move(__first), std::move(__last), + std::move(__f), std::move(__proj)); + } + else + { + while (__n-- > 0) + { + std::__invoke(__f, std::__invoke(__proj, *__first)); + ++__first; + } + return {std::move(__first), std::move(__f)}; + } + } + }; + + inline constexpr __for_each_n_fn for_each_n{}; + + struct __find_fn + { + template _Sent, typename _Tp, + typename _Proj = identity> + requires indirect_binary_predicate, const _Tp*> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + while (__first != __last + && !(std::__invoke(__proj, *__first) == __value)) + ++__first; + return __first; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __find_fn find{}; + + struct __find_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + while (__first != __last + && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __find_if_fn find_if{}; + + struct __find_if_not_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + while (__first != __last + && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __find_if_not_fn find_if_not{}; + + struct __find_first_of_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr _Iter1 + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + for (; __first1 != __last1; ++__first1) + for (auto __iter = __first2; __iter != __last2; ++__iter) + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__iter))) + return __first1; + return __first1; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_iterator_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __find_first_of_fn find_first_of{}; + + struct __count_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __value) + ++__n; + return __n; + } + + template + requires indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr range_difference_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __count_fn count{}; + + struct __count_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr iter_difference_t<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = 0; + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__n; + return __n; + } + + template, _Proj>> + _Pred> + constexpr range_difference_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __count_if_fn count_if{}; + + template + struct in_in_result + { + [[no_unique_address]] _Iter1 in1; + [[no_unique_address]] _Iter2 in2; + + template + requires convertible_to + && convertible_to + constexpr + operator in_in_result<_IIter1, _IIter2>() const & + { return {in1, in2}; } + + template + requires convertible_to<_Iter1, _IIter1> + && convertible_to<_Iter2, _IIter2> + constexpr + operator in_in_result<_IIter1, _IIter2>() && + { return {std::move(in1), std::move(in2)}; } + }; + + template + using mismatch_result = in_in_result<_Iter1, _Iter2>; + + struct __mismatch_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr mismatch_result<_Iter1, _Iter2> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2 + && (bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + ++__first1; + ++__first2; + } + return { std::move(__first1), std::move(__first2) }; + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr mismatch_result, iterator_t<_Range2>> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __mismatch_fn mismatch{}; + + struct __search_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if (__first1 == __last1 || __first2 == __last2) + return {__first1, __first1}; + + for (;;) + { + for (;;) + { + if (__first1 == __last1) + return {__first1, __first1}; + if (std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + ++__first1; + } + auto __cur1 = __first1; + auto __cur2 = __first2; + for (;;) + { + if (++__cur2 == __last2) + return {__first1, ++__cur1}; + if (++__cur1 == __last1) + return {__cur1, __cur1}; + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__cur1), + std::__invoke(__proj2, *__cur2))) + { + ++__first1; + break; + } + } + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_subrange_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __search_fn search{}; + + struct __search_n_fn + { + template _Sent, typename _Tp, + typename _Pred = ranges::equal_to, typename _Proj = identity> + requires indirectly_comparable<_Iter, const _Tp*, _Pred, _Proj> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, iter_difference_t<_Iter> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const + { + if (__count <= 0) + return {__first, __first}; + + auto __value_comp = [&] (_Rp&& __arg) { + return std::__invoke(__pred, std::forward<_Rp>(__arg), __value); + }; + if (__count == 1) + { + __first = ranges::find_if(std::move(__first), __last, + std::move(__value_comp), + std::move(__proj)); + if (__first == __last) + return {__first, __first}; + else + { + auto __end = __first; + return {__first, ++__end}; + } + } + + if constexpr (sized_sentinel_for<_Sent, _Iter>) + { + auto __tail_size = __last - __first; + auto __remainder = __count; + + while (__remainder <= __tail_size) + { + __first += __remainder; + __tail_size -= __remainder; + auto __backtrack = __first; + while (__value_comp(std::__invoke(__proj, *--__backtrack))) + { + if (--__remainder == 0) + return {__first - __count, __first}; + } + } + auto __i = __first + __tail_size; + return {__i, __i}; + } + else + { + __first = ranges::find_if(__first, __last, __value_comp, __proj); + while (__first != __last) + { + auto __n = __count; + auto __i = __first; + ++__i; + while (__i != __last && __n != 1 + && __value_comp(std::__invoke(__proj, *__i))) + { + ++__i; + --__n; + } + if (__n == 1) + return {__first, __i}; + if (__i == __last) + return {__i, __i}; + __first = ranges::find_if(++__i, __last, __value_comp, __proj); + } + return {__first, __first}; + } + } + + template + requires indirectly_comparable, const _Tp*, + _Pred, _Proj> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, range_difference_t<_Range> __count, + const _Tp& __value, _Pred __pred = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__count), __value, + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __search_n_fn search_n{}; + + struct __find_end_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr subrange<_Iter1> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if constexpr (bidirectional_iterator<_Iter1> + && bidirectional_iterator<_Iter2>) + { + auto __i1 = ranges::next(__first1, __last1); + auto __i2 = ranges::next(__first2, __last2); + auto __rresult + = ranges::search(reverse_iterator<_Iter1>{__i1}, + reverse_iterator<_Iter1>{__first1}, + reverse_iterator<_Iter2>{__i2}, + reverse_iterator<_Iter2>{__first2}, + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + auto __result_first = ranges::end(__rresult).base(); + auto __result_last = ranges::begin(__rresult).base(); + if (__result_last == __first1) + return {__i1, __i1}; + else + return {__result_first, __result_last}; + } + else + { + auto __i = ranges::next(__first1, __last1); + if (__first2 == __last2) + return {__i, __i}; + + auto __result_begin = __i; + auto __result_end = __i; + for (;;) + { + auto __new_range = ranges::search(__first1, __last1, + __first2, __last2, + __pred, __proj1, __proj2); + auto __new_result_begin = ranges::begin(__new_range); + auto __new_result_end = ranges::end(__new_range); + if (__new_result_begin == __last1) + return {__result_begin, __result_end}; + else + { + __result_begin = __new_result_begin; + __result_end = __new_result_end; + __first1 = __result_begin; + ++__first1; + } + } + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr borrowed_subrange_t<_Range1> + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __find_end_fn find_end{}; + + struct __adjacent_find_fn + { + template _Sent, + typename _Proj = identity, + indirect_binary_predicate, + projected<_Iter, _Proj>> _Pred + = ranges::equal_to> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + auto __next = __first; + for (; ++__next != __last; __first = __next) + { + if (std::__invoke(__pred, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + return __first; + } + return __next; + } + + template, _Proj>, + projected, _Proj>> _Pred = ranges::equal_to> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __adjacent_find_fn adjacent_find{}; + + struct __is_permutation_fn + { + template _Sent1, + forward_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_equivalence_relation, + projected<_Iter2, _Proj2>> _Pred + = ranges::equal_to> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + break; + + if constexpr (__sized_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (auto __scan = __first1; __scan != __last1; ++__scan) + { + auto __proj_scan = std::__invoke(__proj1, *__scan); + auto __comp_scan = [&] (_Tp&& __arg) { + return std::__invoke(__pred, __proj_scan, + std::forward<_Tp>(__arg)); + }; + if (__scan != ranges::find_if(__first1, __scan, + __comp_scan, __proj1)) + continue; // We've seen this one before. + + auto __matches = ranges::count_if(__first2, __last2, + __comp_scan, __proj2); + if (__matches == 0 + || ranges::count_if(__scan, __last1, + __comp_scan, __proj1) != __matches) + return false; + } + return true; + } + + template, _Proj1>, + projected, _Proj2>> _Pred = ranges::equal_to> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __is_permutation_fn is_permutation{}; + + template + using copy_if_result = in_out_result<_Iter, _Out>; + + struct __copy_if_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __copy_if_fn copy_if{}; + + template + using swap_ranges_result = in_in_result<_Iter1, _Iter2>; + + struct __swap_ranges_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2> + requires indirectly_swappable<_Iter1, _Iter2> + constexpr swap_ranges_result<_Iter1, _Iter2> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2) const + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + ranges::iter_swap(__first1, __first2); + return {std::move(__first1), std::move(__first2)}; + } + + template + requires indirectly_swappable, iterator_t<_Range2>> + constexpr swap_ranges_result, + borrowed_iterator_t<_Range2>> + operator()(_Range1&& __r1, _Range2&& __r2) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2)); + } + }; + + inline constexpr __swap_ranges_fn swap_ranges{}; + + template + using unary_transform_result = in_out_result<_Iter, _Out>; + + template + struct in_in_out_result + { + [[no_unique_address]] _Iter1 in1; + [[no_unique_address]] _Iter2 in2; + [[no_unique_address]] _Out out; + + template + requires convertible_to + && convertible_to + && convertible_to + constexpr + operator in_in_out_result<_IIter1, _IIter2, _OOut>() const & + { return {in1, in2, out}; } + + template + requires convertible_to<_Iter1, _IIter1> + && convertible_to<_Iter2, _IIter2> + && convertible_to<_Out, _OOut> + constexpr + operator in_in_out_result<_IIter1, _IIter2, _OOut>() && + { return {std::move(in1), std::move(in2), std::move(out)}; } + }; + + template + using binary_transform_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __transform_fn + { + template _Sent, + weakly_incrementable _Out, + copy_constructible _Fp, typename _Proj = identity> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected<_Iter, _Proj>>> + constexpr unary_transform_result<_Iter, _Out> + operator()(_Iter __first1, _Sent __last1, _Out __result, + _Fp __op, _Proj __proj = {}) const + { + for (; __first1 != __last1; ++__first1, (void)++__result) + *__result = std::__invoke(__op, std::__invoke(__proj, *__first1)); + return {std::move(__first1), std::move(__result)}; + } + + template + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj>>> + constexpr unary_transform_result, _Out> + operator()(_Range&& __r, _Out __result, _Fp __op, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__op), std::move(__proj)); + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, copy_constructible _Fp, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>>> + constexpr binary_transform_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Fp __binary_op, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2, ++__result) + *__result = std::__invoke(__binary_op, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2)); + return {std::move(__first1), std::move(__first2), std::move(__result)}; + } + + template + requires indirectly_writable<_Out, + indirect_result_t<_Fp&, + projected, _Proj1>, + projected, _Proj2>>> + constexpr binary_transform_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, _Fp __binary_op, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__binary_op), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __transform_fn transform{}; + + struct __replace_fn + { + template _Sent, + typename _Tp1, typename _Tp2, typename _Proj = identity> + requires indirectly_writable<_Iter, const _Tp2&> + && indirect_binary_predicate, + const _Tp1*> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__proj, *__first) == __old_value) + *__first = __new_value; + return __first; + } + + template + requires indirectly_writable, const _Tp2&> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __old_value, __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_fn replace{}; + + struct __replace_if_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_writable<_Iter, const _Tp&> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__first = __new_value; + return std::move(__first); + } + + template, _Proj>> + _Pred> + requires indirectly_writable, const _Tp&> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_if_fn replace_if{}; + + template + using replace_copy_result = in_out_result<_Iter, _Out>; + + struct __replace_copy_fn + { + template _Sent, + typename _Tp1, typename _Tp2, output_iterator _Out, + typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, const _Tp1*> + constexpr replace_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__proj, *__first) == __old_value) + *__result = __new_value; + else + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + + template _Out, typename _Proj = identity> + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp1*> + constexpr replace_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + const _Tp1& __old_value, const _Tp2& __new_value, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), __old_value, + __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_copy_fn replace_copy{}; + + template + using replace_copy_if_result = in_out_result<_Iter, _Out>; + + struct __replace_copy_if_fn + { + template _Sent, + typename _Tp, output_iterator _Out, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr replace_copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first, (void)++__result) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + *__result = __new_value; + else + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + + template _Out, + typename _Proj = identity, + indirect_unary_predicate, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr replace_copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, const _Tp& __new_value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), std::move(__pred), + __new_value, std::move(__proj)); + } + }; + + inline constexpr __replace_copy_if_fn replace_copy_if{}; + + struct __generate_n_fn + { + template + requires invocable<_Fp&> + && indirectly_writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + operator()(_Out __first, iter_difference_t<_Out> __n, _Fp __gen) const + { + for (; __n > 0; --__n, (void)++__first) + *__first = std::__invoke(__gen); + return __first; + } + }; + + inline constexpr __generate_n_fn generate_n{}; + + struct __generate_fn + { + template _Sent, + copy_constructible _Fp> + requires invocable<_Fp&> + && indirectly_writable<_Out, invoke_result_t<_Fp&>> + constexpr _Out + operator()(_Out __first, _Sent __last, _Fp __gen) const + { + for (; __first != __last; ++__first) + *__first = std::__invoke(__gen); + return __first; + } + + template + requires invocable<_Fp&> && output_range<_Range, invoke_result_t<_Fp&>> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Fp __gen) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), std::move(__gen)); + } + }; + + inline constexpr __generate_fn generate{}; + + struct __remove_if_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + __first = ranges::find_if(__first, __last, __pred, __proj); + if (__first == __last) + return {__first, __first}; + + auto __result = __first; + ++__first; + for (; __first != __last; ++__first) + if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = std::move(*__first); + ++__result; + } + + return {__result, __first}; + } + + template, _Proj>> + _Pred> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __remove_if_fn remove_if{}; + + struct __remove_fn + { + template _Sent, + typename _Tp, typename _Proj = identity> + requires indirect_binary_predicate, + const _Tp*> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Proj __proj = {}) const + { + auto __pred = [&] (auto&& __arg) { + return std::forward(__arg) == __value; + }; + return ranges::remove_if(__first, __last, + std::move(__pred), std::move(__proj)); + } + + template + requires permutable> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__proj)); + } + }; + + inline constexpr __remove_fn remove{}; + + template + using remove_copy_if_result = in_out_result<_Iter, _Out>; + + struct __remove_copy_if_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out> + constexpr remove_copy_if_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out> + constexpr remove_copy_if_result, _Out> + operator()(_Range&& __r, _Out __result, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __remove_copy_if_fn remove_copy_if{}; + + template + using remove_copy_result = in_out_result<_Iter, _Out>; + + struct __remove_copy_fn + { + template _Sent, + weakly_incrementable _Out, typename _Tp, typename _Proj = identity> + requires indirectly_copyable<_Iter, _Out> + && indirect_binary_predicate, + const _Tp*> + constexpr remove_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + const _Tp& __value, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (!(std::__invoke(__proj, *__first) == __value)) + { + *__result = *__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + + template + requires indirectly_copyable, _Out> + && indirect_binary_predicate, _Proj>, + const _Tp*> + constexpr remove_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + const _Tp& __value, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), __value, std::move(__proj)); + } + }; + + inline constexpr __remove_copy_fn remove_copy{}; + + struct __unique_fn + { + template _Sent, + typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + __first = ranges::adjacent_find(__first, __last, __comp, __proj); + if (__first == __last) + return {__first, __first}; + + auto __dest = __first; + ++__first; + while (++__first != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__dest), + std::__invoke(__proj, *__first))) + *++__dest = std::move(*__first); + return {++__dest, __first}; + } + + template, _Proj>> _Comp = ranges::equal_to> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __unique_fn unique{}; + + template + using unique_copy_result = in_out_result<_Iter, _Out>; + + struct __unique_copy_fn + { + template _Sent, + weakly_incrementable _Out, typename _Proj = identity, + indirect_equivalence_relation< + projected<_Iter, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable<_Iter, _Out> + && (forward_iterator<_Iter> + || (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + || indirectly_copyable_storable<_Iter, _Out>) + constexpr unique_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), std::move(__result)}; + + // TODO: perform a closer comparison with reference implementations + if constexpr (forward_iterator<_Iter>) + { + auto __next = __first; + *__result = *__next; + while (++__next != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__next))) + { + __first = __next; + *++__result = *__first; + } + return {__next, std::move(++__result)}; + } + else if constexpr (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + { + *__result = *__first; + while (++__first != __last) + if (!std::__invoke(__comp, + std::__invoke(__proj, *__result), + std::__invoke(__proj, *__first))) + *++__result = *__first; + return {std::move(__first), std::move(++__result)}; + } + else // indirectly_copyable_storable<_Iter, _Out> + { + auto __value = *__first; + *__result = __value; + while (++__first != __last) + { + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, __value))) + { + __value = *__first; + *++__result = __value; + } + } + return {std::move(__first), std::move(++__result)}; + } + } + + template, _Proj>> _Comp = ranges::equal_to> + requires indirectly_copyable, _Out> + && (forward_iterator> + || (input_iterator<_Out> + && same_as, iter_value_t<_Out>>) + || indirectly_copyable_storable, _Out>) + constexpr unique_copy_result, _Out> + operator()(_Range&& __r, _Out __result, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __unique_copy_fn unique_copy{}; + + struct __reverse_fn + { + template _Sent> + requires permutable<_Iter> + constexpr _Iter + operator()(_Iter __first, _Sent __last) const + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + + if constexpr (random_access_iterator<_Iter>) + { + if (__first != __last) + { + --__tail; + while (__first < __tail) + { + ranges::iter_swap(__first, __tail); + ++__first; + --__tail; + } + } + return __i; + } + else + { + for (;;) + if (__first == __tail || __first == --__tail) + break; + else + { + ranges::iter_swap(__first, __tail); + ++__first; + } + return __i; + } + } + + template + requires permutable> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __reverse_fn reverse{}; + + template + using reverse_copy_result = in_out_result<_Iter, _Out>; + + struct __reverse_copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr reverse_copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + auto __i = ranges::next(__first, __last); + auto __tail = __i; + while (__first != __tail) + { + --__tail; + *__result = *__tail; + ++__result; + } + return {__i, __result}; + } + + template + requires indirectly_copyable, _Out> + constexpr reverse_copy_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __reverse_copy_fn reverse_copy{}; + + struct __rotate_fn + { + template _Sent> + constexpr subrange<_Iter> + operator()(_Iter __first, _Iter __middle, _Sent __last) const + { + auto __lasti = ranges::next(__first, __last); + if (__first == __middle) + return {__lasti, __lasti}; + if (__last == __middle) + return {std::move(__first), std::move(__lasti)}; + + if constexpr (random_access_iterator<_Iter>) + { + auto __n = __lasti - __first; + auto __k = __middle - __first; + + if (__k == __n - __k) + { + ranges::swap_ranges(__first, __middle, __middle, __middle + __k); + return {std::move(__middle), std::move(__lasti)}; + } + + auto __p = __first; + auto __ret = __first + (__lasti - __middle); + + for (;;) + { + if (__k < __n - __k) + { + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*__p); + ranges::move(__p + 1, __p + __n, __p); + *(__p + __n - 1) = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + ranges::iter_swap(__p, __q); + ++__p; + ++__q; + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + ranges::swap(__n, __k); + __k = __n - __k; + } + else + { + __k = __n - __k; + // TODO: is_pod is deprecated, but this condition is + // consistent with the STL implementation. + if constexpr (__is_pod(iter_value_t<_Iter>)) + if (__k == 1) + { + auto __t = std::move(*(__p + __n - 1)); + ranges::move_backward(__p, __p + __n - 1, __p + __n); + *__p = std::move(__t); + return {std::move(__ret), std::move(__lasti)}; + } + auto __q = __p + __n; + __p = __q - __k; + for (decltype(__n) __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + ranges::iter_swap(__p, __q); + } + __n %= __k; + if (__n == 0) + return {std::move(__ret), std::move(__lasti)}; + std::swap(__n, __k); + } + } + } + else if constexpr (bidirectional_iterator<_Iter>) + { + auto __tail = __lasti; + + ranges::reverse(__first, __middle); + ranges::reverse(__middle, __tail); + + while (__first != __middle && __middle != __tail) + { + ranges::iter_swap(__first, --__tail); + ++__first; + } + + if (__first == __middle) + { + ranges::reverse(__middle, __tail); + return {std::move(__tail), std::move(__lasti)}; + } + else + { + ranges::reverse(__first, __middle); + return {std::move(__first), std::move(__lasti)}; + } + } + else + { + auto __first2 = __middle; + do + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + } while (__first2 != __last); + + auto __ret = __first; + + __first2 = __middle; + + while (__first2 != __last) + { + ranges::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + return {std::move(__ret), std::move(__lasti)}; + } + } + + template + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r)); + } + }; + + inline constexpr __rotate_fn rotate{}; + + template + using rotate_copy_result = in_out_result<_Iter, _Out>; + + struct __rotate_copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr rotate_copy_result<_Iter, _Out> + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Out __result) const + { + auto __copy1 = ranges::copy(__middle, + std::move(__last), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first), + std::move(__middle), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.out) }; + } + + template + requires indirectly_copyable, _Out> + constexpr rotate_copy_result, _Out> + operator()(_Range&& __r, iterator_t<_Range> __middle, _Out __result) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), std::move(__result)); + } + }; + + inline constexpr __rotate_copy_fn rotate_copy{}; + + struct __sample_fn + { + template _Sent, + weakly_incrementable _Out, typename _Gen> + requires (forward_iterator<_Iter> || random_access_iterator<_Out>) + && indirectly_copyable<_Iter, _Out> + && uniform_random_bit_generator> + _Out + operator()(_Iter __first, _Sent __last, _Out __out, + iter_difference_t<_Iter> __n, _Gen&& __g) const + { + if constexpr (forward_iterator<_Iter>) + { + // FIXME: Forwarding to std::sample here requires computing __lasti + // which may take linear time. + auto __lasti = ranges::next(__first, __last); + return std::sample(std::move(__first), std::move(__lasti), + std::move(__out), __n, std::forward<_Gen>(__g)); + } + else + { + using __distrib_type + = uniform_int_distribution>; + using __param_type = typename __distrib_type::param_type; + __distrib_type __d{}; + iter_difference_t<_Iter> __sample_sz = 0; + while (__first != __last && __sample_sz != __n) + { + __out[__sample_sz++] = *__first; + ++__first; + } + for (auto __pop_sz = __sample_sz; __first != __last; + ++__first, (void) ++__pop_sz) + { + const auto __k = __d(__g, __param_type{0, __pop_sz}); + if (__k < __n) + __out[__k] = *__first; + } + return __out + __sample_sz; + } + } + + template + requires (forward_range<_Range> || random_access_iterator<_Out>) + && indirectly_copyable, _Out> + && uniform_random_bit_generator> + _Out + operator()(_Range&& __r, _Out __out, + range_difference_t<_Range> __n, _Gen&& __g) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__out), __n, + std::forward<_Gen>(__g)); + } + }; + + inline constexpr __sample_fn sample{}; + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + struct __shuffle_fn + { + template _Sent, + typename _Gen> + requires permutable<_Iter> + && uniform_random_bit_generator> + _Iter + operator()(_Iter __first, _Sent __last, _Gen&& __g) const + { + auto __lasti = ranges::next(__first, __last); + std::shuffle(std::move(__first), __lasti, std::forward<_Gen>(__g)); + return __lasti; + } + + template + requires permutable> + && uniform_random_bit_generator> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Gen&& __g) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::forward<_Gen>(__g)); + } + }; + + inline constexpr __shuffle_fn shuffle{}; +#endif + + struct __push_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::push_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __push_heap_fn push_heap{}; + + struct __pop_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::pop_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __pop_heap_fn pop_heap{}; + + struct __make_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::make_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __make_heap_fn make_heap{}; + + struct __sort_heap_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::sort_heap(__first, __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __sort_heap_fn sort_heap{}; + + struct __is_heap_until_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + iter_difference_t<_Iter> __n = ranges::distance(__first, __last); + iter_difference_t<_Iter> __parent = 0, __child = 1; + for (; __child < __n; ++__child) + if (std::__invoke(__comp, + std::__invoke(__proj, *(__first + __parent)), + std::__invoke(__proj, *(__first + __child)))) + return __first + __child; + else if ((__child & 1) == 0) + ++__parent; + + return __first + __n; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_heap_until_fn is_heap_until{}; + + struct __is_heap_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (__last + == ranges::is_heap_until(__first, __last, + std::move(__comp), + std::move(__proj))); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_heap_fn is_heap{}; + + struct __sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __sort_fn sort{}; + + struct __stable_sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::stable_sort(std::move(__first), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __stable_sort_fn stable_sort{}; + + struct __partial_sort_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __middle) + return ranges::next(__first, __last); + + ranges::make_heap(__first, __middle, __comp, __proj); + auto __i = __middle; + for (; __i != __last; ++__i) + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + { + ranges::pop_heap(__first, __middle, __comp, __proj); + ranges::iter_swap(__middle-1, __i); + ranges::push_heap(__first, __middle, __comp, __proj); + } + ranges::sort_heap(__first, __middle, __comp, __proj); + + return __i; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __partial_sort_fn partial_sort{}; + + template + using partial_sort_copy_result = in_out_result<_Iter, _Out>; + + struct __partial_sort_copy_fn + { + template _Sent1, + random_access_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_copyable<_Iter1, _Iter2> + && sortable<_Iter2, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected<_Iter1, _Proj1>, + projected<_Iter2, _Proj2>> + constexpr partial_sort_copy_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, + _Iter2 __result_first, _Sent2 __result_last, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if (__result_first == __result_last) + { + // TODO: Eliminating the variable __lasti triggers an ICE. + auto __lasti = ranges::next(std::move(__first), + std::move(__last)); + return {std::move(__lasti), std::move(__result_first)}; + } + + auto __result_real_last = __result_first; + while (__first != __last && __result_real_last != __result_last) + { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + + ranges::make_heap(__result_first, __result_real_last, __comp, __proj2); + for (; __first != __last; ++__first) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first), + std::__invoke(__proj2, *__result_first))) + { + ranges::pop_heap(__result_first, __result_real_last, + __comp, __proj2); + *(__result_real_last-1) = *__first; + ranges::push_heap(__result_first, __result_real_last, + __comp, __proj2); + } + ranges::sort_heap(__result_first, __result_real_last, __comp, __proj2); + + return {std::move(__first), std::move(__result_real_last)}; + } + + template + requires indirectly_copyable, iterator_t<_Range2>> + && sortable, _Comp, _Proj2> + && indirect_strict_weak_order<_Comp, + projected, _Proj1>, + projected, _Proj2>> + constexpr partial_sort_copy_result, + borrowed_iterator_t<_Range2>> + operator()(_Range1&& __r, _Range2&& __out, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + ranges::begin(__out), ranges::end(__out), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __partial_sort_copy_fn partial_sort_copy{}; + + struct __is_sorted_until_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return __next; + return __next; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_sorted_until_fn is_sorted_until{}; + + struct __is_sorted_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return true; + + auto __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (std::__invoke(__comp, + std::__invoke(__proj, *__next), + std::__invoke(__proj, *__first))) + return false; + return true; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __is_sorted_fn is_sorted{}; + + struct __nth_element_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr _Iter + operator()(_Iter __first, _Iter __nth, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::nth_element(std::move(__first), std::move(__nth), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __nth, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__nth), + ranges::end(__r), std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __nth_element_fn nth_element{}; + + struct __lower_bound_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, std::__invoke(__proj, *__middle), __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __lower_bound_fn lower_bound{}; + + struct __upper_bound_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, __value, std::__invoke(__proj, *__middle))) + __len = __half; + else + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __upper_bound_fn upper_bound{}; + + struct __equal_range_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__comp, + std::__invoke(__proj, *__middle), + __value)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (std::__invoke(__comp, + __value, + std::__invoke(__proj, *__middle))) + __len = __half; + else + { + auto __left + = ranges::lower_bound(__first, __middle, + __value, __comp, __proj); + ranges::advance(__first, __len); + auto __right + = ranges::upper_bound(++__middle, __first, + __value, __comp, __proj); + return {__left, __right}; + } + } + return {__first, __first}; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, const _Tp& __value, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __equal_range_fn equal_range{}; + + struct __binary_search_fn + { + template _Sent, + typename _Tp, typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr bool + operator()(_Iter __first, _Sent __last, + const _Tp& __value, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __i = ranges::lower_bound(__first, __last, __value, __comp, __proj); + if (__i == __last) + return false; + return !(bool)std::__invoke(__comp, __value, + std::__invoke(__proj, *__i)); + } + + template, _Proj>> + _Comp = ranges::less> + constexpr bool + operator()(_Range&& __r, const _Tp& __value, _Comp __comp = {}, + _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + __value, std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __binary_search_fn binary_search{}; + + struct __is_partitioned_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr bool + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + __first = ranges::find_if_not(std::move(__first), __last, + __pred, __proj); + if (__first == __last) + return true; + ++__first; + return ranges::none_of(std::move(__first), std::move(__last), + std::move(__pred), std::move(__proj)); + } + + template, _Proj>> + _Pred> + constexpr bool + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __is_partitioned_fn is_partitioned{}; + + struct __partition_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + if constexpr (bidirectional_iterator<_Iter>) + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + for (;;) + { + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (std::__invoke(__pred, + std::__invoke(__proj, *__first))) + ++__first; + else + break; + --__tail; + for (;;) + if (__first == __tail) + return {std::move(__first), std::move(__lasti)}; + else if (!(bool)std::__invoke(__pred, + std::__invoke(__proj, *__tail))) + --__tail; + else + break; + ranges::iter_swap(__first, __tail); + ++__first; + } + } + else + { + if (__first == __last) + return {std::move(__first), std::move(__first)}; + + while (std::__invoke(__pred, std::__invoke(__proj, *__first))) + if (++__first == __last) + return {std::move(__first), std::move(__first)}; + + auto __next = __first; + while (++__next != __last) + if (std::__invoke(__pred, std::__invoke(__proj, *__next))) + { + ranges::iter_swap(__first, __next); + ++__first; + } + + return {std::move(__first), std::move(__next)}; + } + } + + template, _Proj>> + _Pred> + requires permutable> + constexpr borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_fn partition{}; + + struct __stable_partition_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires permutable<_Iter> + subrange<_Iter> + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + auto __middle + = std::stable_partition(std::move(__first), __lasti, + __detail::__make_pred_proj(__pred, __proj)); + return {std::move(__middle), std::move(__lasti)}; + } + + template, _Proj>> + _Pred> + requires permutable> + borrowed_subrange_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __stable_partition_fn stable_partition{}; + + template + struct in_out_out_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Out1 out1; + [[no_unique_address]] _Out2 out2; + + template + requires convertible_to + && convertible_to + && convertible_to + constexpr + operator in_out_out_result<_IIter, _OOut1, _OOut2>() const & + { return {in, out1, out2}; } + + template + requires convertible_to<_Iter, _IIter> + && convertible_to<_Out1, _OOut1> + && convertible_to<_Out2, _OOut2> + constexpr + operator in_out_out_result<_IIter, _OOut1, _OOut2>() && + { return {std::move(in), std::move(out1), std::move(out2)}; } + }; + + template + using partition_copy_result = in_out_out_result<_Iter, _Out1, _Out2>; + + struct __partition_copy_fn + { + template _Sent, + weakly_incrementable _Out1, weakly_incrementable _O2, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + requires indirectly_copyable<_Iter, _Out1> + && indirectly_copyable<_Iter, _O2> + constexpr partition_copy_result<_Iter, _Out1, _O2> + operator()(_Iter __first, _Sent __last, + _Out1 __out_true, _O2 __out_false, + _Pred __pred, _Proj __proj = {}) const + { + for (; __first != __last; ++__first) + if (std::__invoke(__pred, std::__invoke(__proj, *__first))) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + + return {std::move(__first), + std::move(__out_true), std::move(__out_false)}; + } + + template, _Proj>> + _Pred> + requires indirectly_copyable, _Out1> + && indirectly_copyable, _O2> + constexpr partition_copy_result, _Out1, _O2> + operator()(_Range&& __r, _Out1 out_true, _O2 out_false, + _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(out_true), std::move(out_false), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_copy_fn partition_copy{}; + + struct __partition_point_fn + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Pred __pred, _Proj __proj = {}) const + { + auto __len = ranges::distance(__first, __last); + + while (__len > 0) + { + auto __half = __len / 2; + auto __middle = __first; + ranges::advance(__middle, __half); + if (std::__invoke(__pred, std::__invoke(__proj, *__middle))) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + template, _Proj>> + _Pred> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Pred __pred, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__pred), std::move(__proj)); + } + }; + + inline constexpr __partition_point_fn partition_point{}; + + template + using merge_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __merge_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr merge_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return { std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out) }; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr merge_result, + borrowed_iterator_t<_Range2>, + _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __merge_fn merge{}; + + struct __inplace_merge_fn + { + template _Sent, + typename _Comp = ranges::less, + typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + _Iter + operator()(_Iter __first, _Iter __middle, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + auto __lasti = ranges::next(__first, __last); + std::inplace_merge(std::move(__first), std::move(__middle), __lasti, + __detail::__make_comp_proj(__comp, __proj)); + return __lasti; + } + + template + requires sortable, _Comp, _Proj> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, iterator_t<_Range> __middle, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), std::move(__middle), + ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __inplace_merge_fn inplace_merge{}; + + struct __includes_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + else if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else + { + ++__first1; + ++__first2; + } + + return __first2 == __last2; + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __includes_fn includes{}; + + template + using set_union_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_union_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_union_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_union_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_union_fn set_union{}; + + template + using set_intersection_result = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_intersection_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_intersection_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + ++__first1; + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; + else + { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + // TODO: Eliminating these variables triggers an ICE. + auto __last1i = ranges::next(std::move(__first1), std::move(__last1)); + auto __last2i = ranges::next(std::move(__first2), std::move(__last2)); + return {std::move(__last1i), std::move(__last2i), std::move(__result)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_intersection_result, + borrowed_iterator_t<_Range2>, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_intersection_fn set_intersection{}; + + template + using set_difference_result = in_out_result<_Iter, _Out>; + + struct __set_difference_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_difference_result<_Iter1, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + ++__first2; + else + { + ++__first1; + ++__first2; + } + return ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_difference_result, _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_difference_fn set_difference{}; + + template + using set_symmetric_difference_result + = in_in_out_result<_Iter1, _Iter2, _Out>; + + struct __set_symmetric_difference_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + weakly_incrementable _Out, typename _Comp = ranges::less, + typename _Proj1 = identity, typename _Proj2 = identity> + requires mergeable<_Iter1, _Iter2, _Out, _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result<_Iter1, _Iter2, _Out> + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Out __result, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + while (__first1 != __last1 && __first2 != __last2) + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + { + *__result = *__first2; + ++__first2; + ++__result; + } + else + { + ++__first1; + ++__first2; + } + auto __copy1 = ranges::copy(std::move(__first1), std::move(__last1), + std::move(__result)); + auto __copy2 = ranges::copy(std::move(__first2), std::move(__last2), + std::move(__copy1.out)); + return {std::move(__copy1.in), std::move(__copy2.in), + std::move(__copy2.out)}; + } + + template + requires mergeable, iterator_t<_Range2>, _Out, + _Comp, _Proj1, _Proj2> + constexpr set_symmetric_difference_result, + borrowed_iterator_t<_Range2>, + _Out> + operator()(_Range1&& __r1, _Range2&& __r2, _Out __result, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__result), std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __set_symmetric_difference_fn set_symmetric_difference{}; + + struct __min_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_fn min{}; + + struct __max_fn + { + template> + _Comp = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __a), + std::__invoke(__proj, __b))) + return __b; + else + return __a; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr range_value_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + auto __result = *__first; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __result), + std::__invoke(__proj, __tmp))) + __result = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr _Tp + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __max_fn max{}; + + struct __clamp_fn + { + template> _Comp + = ranges::less> + constexpr const _Tp& + operator()(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, + _Comp __comp = {}, _Proj __proj = {}) const + { + __glibcxx_assert(!(std::__invoke(__comp, + std::__invoke(__proj, __hi), + std::__invoke(__proj, __lo)))); + auto&& __proj_val = std::__invoke(__proj, __val); + if (std::__invoke(__comp, __proj_val, std::__invoke(__proj, __lo))) + return __lo; + else if (std::__invoke(__comp, std::__invoke(__proj, __hi), __proj_val)) + return __hi; + else + return __val; + } + }; + + inline constexpr __clamp_fn clamp{}; + + template + struct min_max_result + { + [[no_unique_address]] _Tp min; + [[no_unique_address]] _Tp max; + + template + requires convertible_to + constexpr + operator min_max_result<_Tp2>() const & + { return {min, max}; } + + template + requires convertible_to<_Tp, _Tp2> + constexpr + operator min_max_result<_Tp2>() && + { return {std::move(min), std::move(max)}; } + }; + + template + using minmax_result = min_max_result<_Tp>; + + struct __minmax_fn + { + template> + _Comp = ranges::less> + constexpr minmax_result + operator()(const _Tp& __a, const _Tp& __b, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return {__b, __a}; + else + return {__a, __b}; + } + + template, _Proj>> + _Comp = ranges::less> + requires indirectly_copyable_storable, + range_value_t<_Range>*> + constexpr minmax_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + auto __first = ranges::begin(__r); + auto __last = ranges::end(__r); + __glibcxx_assert(__first != __last); + minmax_result> __result = {*__first, *__first}; + while (++__first != __last) + { + auto __tmp = *__first; + if (std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result.min))) + __result.min = std::move(__tmp); + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, __tmp), + std::__invoke(__proj, __result.max))) + __result.max = std::move(__tmp); + } + return __result; + } + + template> + _Comp = ranges::less> + constexpr minmax_result<_Tp> + operator()(initializer_list<_Tp> __r, + _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::subrange(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __minmax_fn minmax{}; + + struct __min_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__first))) + __first = __i; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __min_element_fn min_element{}; + + struct __max_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr _Iter + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return __first; + + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__first), + std::__invoke(__proj, *__i))) + __first = __i; + } + return __first; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __max_element_fn max_element{}; + + template + using minmax_element_result = min_max_result<_Iter>; + + struct __minmax_element_fn + { + template _Sent, + typename _Proj = identity, + indirect_strict_weak_order> + _Comp = ranges::less> + constexpr minmax_element_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {__first, __first}; + + minmax_element_result<_Iter> __result = {__first, __first}; + auto __i = __first; + while (++__i != __last) + { + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__result.min))) + __result.min = __i; + if (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__result.max))) + __result.max = __i; + } + return __result; + } + + template, _Proj>> + _Comp = ranges::less> + constexpr minmax_element_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __minmax_element_fn minmax_element{}; + + struct __lexicographical_compare_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Proj1 = identity, typename _Proj2 = identity, + indirect_strict_weak_order, + projected<_Iter2, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, + _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + if constexpr (__detail::__is_normal_iterator<_Iter1> + && same_as<_Iter1, _Sent1>) + return (*this)(__first1.base(), __last1.base(), + std::move(__first2), std::move(__last2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + else if constexpr (__detail::__is_normal_iterator<_Iter2> + && same_as<_Iter2, _Sent2>) + return (*this)(std::move(__first1), std::move(__last1), + __first2.base(), __last2.base(), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + else + { + constexpr bool __sized_iters + = (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>); + if constexpr (__sized_iters) + { + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + // This condition is consistent with the one in + // __lexicographical_compare_aux in . + constexpr bool __use_memcmp + = (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value + && __ptr_to_nonvolatile<_Iter1> + && __ptr_to_nonvolatile<_Iter2> + && (is_same_v<_Comp, ranges::less> + || is_same_v<_Comp, ranges::greater>) + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + const auto __d1 = __last1 - __first1; + const auto __d2 = __last2 - __first2; + + if (const auto __len = std::min(__d1, __d2)) + { + const auto __c + = std::__memcmp(__first1, __first2, __len); + if constexpr (is_same_v<_Comp, ranges::less>) + { + if (__c < 0) + return true; + if (__c > 0) + return false; + } + else if constexpr (is_same_v<_Comp, ranges::greater>) + { + if (__c > 0) + return true; + if (__c < 0) + return false; + } + } + return __d1 < __d2; + } + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void) ++__first2) + { + if (std::__invoke(__comp, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return true; + if (std::__invoke(__comp, + std::__invoke(__proj2, *__first2), + std::__invoke(__proj1, *__first1))) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + } + + template, _Proj1>, + projected, _Proj2>> + _Comp = ranges::less> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Comp __comp = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__comp), + std::move(__proj1), std::move(__proj2)); + } + + private: + template> + static constexpr bool __ptr_to_nonvolatile + = is_pointer_v<_Iter> && !is_volatile_v>; + }; + + inline constexpr __lexicographical_compare_fn lexicographical_compare; + + template + struct in_found_result + { + [[no_unique_address]] _Iter in; + bool found; + + template + requires convertible_to + constexpr + operator in_found_result<_Iter2>() const & + { return {in, found}; } + + template + requires convertible_to<_Iter, _Iter2> + constexpr + operator in_found_result<_Iter2>() && + { return {std::move(in), found}; } + }; + + template + using next_permutation_result = in_found_result<_Iter>; + + struct __next_permutation_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr next_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), false}; + + auto __i = __first; + ++__i; + if (__i == __last) + return {std::move(__i), false}; + + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; + + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *__ii))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *__i), + std::__invoke(__proj, *--__j))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {std::move(__lasti), true}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {std::move(__lasti), false}; + } + } + } + + template + requires sortable, _Comp, _Proj> + constexpr next_permutation_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __next_permutation_fn next_permutation{}; + + template + using prev_permutation_result = in_found_result<_Iter>; + + struct __prev_permutation_fn + { + template _Sent, + typename _Comp = ranges::less, typename _Proj = identity> + requires sortable<_Iter, _Comp, _Proj> + constexpr prev_permutation_result<_Iter> + operator()(_Iter __first, _Sent __last, + _Comp __comp = {}, _Proj __proj = {}) const + { + if (__first == __last) + return {std::move(__first), false}; + + auto __i = __first; + ++__i; + if (__i == __last) + return {std::move(__i), false}; + + auto __lasti = ranges::next(__first, __last); + __i = __lasti; + --__i; + + for (;;) + { + auto __ii = __i; + --__i; + if (std::__invoke(__comp, + std::__invoke(__proj, *__ii), + std::__invoke(__proj, *__i))) + { + auto __j = __lasti; + while (!(bool)std::__invoke(__comp, + std::__invoke(__proj, *--__j), + std::__invoke(__proj, *__i))) + ; + ranges::iter_swap(__i, __j); + ranges::reverse(__ii, __last); + return {std::move(__lasti), true}; + } + if (__i == __first) + { + ranges::reverse(__first, __last); + return {std::move(__lasti), false}; + } + } + } + + template + requires sortable, _Comp, _Proj> + constexpr prev_permutation_result> + operator()(_Range&& __r, _Comp __comp = {}, _Proj __proj = {}) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__comp), std::move(__proj)); + } + }; + + inline constexpr __prev_permutation_fn prev_permutation{}; + +} // namespace ranges + +#define __cpp_lib_shift 201806L + template + constexpr _ForwardIterator + shift_left(_ForwardIterator __first, _ForwardIterator __last, + typename iterator_traits<_ForwardIterator>::difference_type __n) + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return __last; + + auto __mid = ranges::next(__first, __n, __last); + if (__mid == __last) + return __first; + return std::move(std::move(__mid), std::move(__last), std::move(__first)); + } + + template + constexpr _ForwardIterator + shift_right(_ForwardIterator __first, _ForwardIterator __last, + typename iterator_traits<_ForwardIterator>::difference_type __n) + { + __glibcxx_assert(__n >= 0); + if (__n == 0) + return __first; + + using _Cat + = typename iterator_traits<_ForwardIterator>::iterator_category; + if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + { + auto __mid = ranges::next(__last, -__n, __first); + if (__mid == __first) + return __last; + + return std::move_backward(std::move(__first), std::move(__mid), + std::move(__last)); + } + else + { + auto __result = ranges::next(__first, __n, __last); + if (__result == __last) + return __last; + + auto __dest_head = __first, __dest_tail = __result; + while (__dest_head != __result) + { + if (__dest_tail == __last) + { + // If we get here, then we must have + // 2*n >= distance(__first, __last) + // i.e. we are shifting out at least half of the range. In + // this case we can safely perform the shift with a single + // move. + std::move(std::move(__first), std::move(__dest_head), + std::move(__result)); + return __result; + } + ++__dest_head; + ++__dest_tail; + } + + for (;;) + { + // At the start of each iteration of this outer loop, the range + // [__first, __result) contains those elements that after shifting + // the whole range right by __n, should end up in + // [__dest_head, __dest_tail) in order. + + // The below inner loop swaps the elements of [__first, __result) + // and [__dest_head, __dest_tail), while simultaneously shifting + // the latter range by __n. + auto __cursor = __first; + while (__cursor != __result) + { + if (__dest_tail == __last) + { + // At this point the ranges [__first, result) and + // [__dest_head, dest_tail) are disjoint, so we can safely + // move the remaining elements. + __dest_head = std::move(__cursor, __result, + std::move(__dest_head)); + std::move(std::move(__first), std::move(__cursor), + std::move(__dest_head)); + return __result; + } + std::iter_swap(__cursor, __dest_head); + ++__dest_head; + ++__dest_tail; + ++__cursor; + } + } + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_ALGO_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h b/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h new file mode 100644 index 000000000..618bc7d10 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/ranges_algobase.h @@ -0,0 +1,597 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_algobase.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _RANGES_ALGOBASE_H +#define _RANGES_ALGOBASE_H 1 + +#if __cplusplus > 201703L + +#include +#include +// #include +#include +#include +#include // __is_byte + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr inline bool __is_normal_iterator = false; + + template + constexpr inline bool + __is_normal_iterator<__gnu_cxx::__normal_iterator<_Iterator, + _Container>> = true; + + template + constexpr inline bool __is_reverse_iterator = false; + + template + constexpr inline bool + __is_reverse_iterator> = true; + + template + constexpr inline bool __is_move_iterator = false; + + template + constexpr inline bool + __is_move_iterator> = true; + } // namespace __detail + + struct __equal_fn + { + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Iter1 __first1, _Sent1 __last1, + _Iter2 __first2, _Sent2 __last2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + // TODO: implement more specializations to at least have parity with + // std::equal. + if constexpr (__detail::__is_normal_iterator<_Iter1> + && same_as<_Iter1, _Sent1>) + return (*this)(__first1.base(), __last1.base(), + std::move(__first2), std::move(__last2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + else if constexpr (__detail::__is_normal_iterator<_Iter2> + && same_as<_Iter2, _Sent2>) + return (*this)(std::move(__first1), std::move(__last1), + __first2.base(), __last2.base(), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + else if constexpr (sized_sentinel_for<_Sent1, _Iter1> + && sized_sentinel_for<_Sent2, _Iter2>) + { + auto __d1 = ranges::distance(__first1, __last1); + auto __d2 = ranges::distance(__first2, __last2); + if (__d1 != __d2) + return false; + + using _ValueType1 = iter_value_t<_Iter1>; + using _ValueType2 = iter_value_t<_Iter2>; + constexpr bool __use_memcmp + = ((is_integral_v<_ValueType1> || is_pointer_v<_ValueType1>) + && __memcmpable<_Iter1, _Iter2>::__value + && is_same_v<_Pred, ranges::equal_to> + && is_same_v<_Proj1, identity> + && is_same_v<_Proj2, identity>); + if constexpr (__use_memcmp) + { + if (const size_t __len = (__last1 - __first1)) + return !std::__memcmp(__first1, __first2, __len); + return true; + } + else + { + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return true; + } + } + else + { + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } + } + + template + requires indirectly_comparable, iterator_t<_Range2>, + _Pred, _Proj1, _Proj2> + constexpr bool + operator()(_Range1&& __r1, _Range2&& __r2, _Pred __pred = {}, + _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) const + { + return (*this)(ranges::begin(__r1), ranges::end(__r1), + ranges::begin(__r2), ranges::end(__r2), + std::move(__pred), + std::move(__proj1), std::move(__proj2)); + } + }; + + inline constexpr __equal_fn equal{}; + + template + struct in_out_result + { + [[no_unique_address]] _Iter in; + [[no_unique_address]] _Out out; + + template + requires convertible_to + && convertible_to + constexpr + operator in_out_result<_Iter2, _Out2>() const & + { return {in, out}; } + + template + requires convertible_to<_Iter, _Iter2> + && convertible_to<_Out, _Out2> + constexpr + operator in_out_result<_Iter2, _Out2>() && + { return {std::move(in), std::move(out)}; } + }; + + template + using copy_result = in_out_result<_Iter, _Out>; + + template + using move_result = in_out_result<_Iter, _Out>; + + template + using move_backward_result = in_out_result<_Iter1, _Iter2>; + + template + using copy_backward_result = in_out_result<_Iter1, _Iter2>; + + template _Sent, + bidirectional_iterator _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_backward_result<_Iter, _Out>, + copy_backward_result<_Iter, _Out>> + __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result); + + template _Sent, + weakly_incrementable _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_result<_Iter, _Out>, + copy_result<_Iter, _Out>> + __copy_or_move(_Iter __first, _Sent __last, _Out __result) + { + // TODO: implement more specializations to be at least on par with + // std::copy/std::move. + using __detail::__is_move_iterator; + using __detail::__is_reverse_iterator; + using __detail::__is_normal_iterator; + if constexpr (__is_move_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in, __out] + = ranges::__copy_or_move(std::move(__first).base(), + std::move(__last).base(), + std::move(__result)); + return {move_iterator{std::move(__in)}, std::move(__out)}; + } + else if constexpr (__is_reverse_iterator<_Iter> && same_as<_Iter, _Sent> + && __is_reverse_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(std::move(__last).base(), + std::move(__first).base(), + std::move(__result).base()); + return {reverse_iterator{std::move(__in)}, + reverse_iterator{std::move(__out)}}; + } + else if constexpr (__is_normal_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(__first.base(), __last.base(), + __result); + return {decltype(__first){__in}, std::move(__out)}; + } + else if constexpr (__is_normal_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(__first, __last, __result.base()); + return {std::move(__in), decltype(__result){__out}}; + } + else if constexpr (sized_sentinel_for<_Sent, _Iter>) + { +#ifdef __cpp_lib_is_constant_evaluated + if (!std::is_constant_evaluated()) +#endif + { + if constexpr (__memcpyable<_Iter, _Out>::__value) + { + using _ValueTypeI = iter_value_t<_Iter>; + static_assert(_IsMove + ? is_move_assignable_v<_ValueTypeI> + : is_copy_assignable_v<_ValueTypeI>); + auto __num = __last - __first; + if (__num) + __builtin_memmove(__result, __first, + sizeof(_ValueTypeI) * __num); + return {__first + __num, __result + __num}; + } + } + + for (auto __n = __last - __first; __n > 0; --__n) + { + if constexpr (_IsMove) + *__result = std::move(*__first); + else + *__result = *__first; + ++__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + else + { + while (__first != __last) + { + if constexpr (_IsMove) + *__result = std::move(*__first); + else + *__result = *__first; + ++__first; + ++__result; + } + return {std::move(__first), std::move(__result)}; + } + } + + struct __copy_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_copyable<_Iter, _Out> + constexpr copy_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Out> + constexpr copy_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __copy_fn copy{}; + + struct __move_fn + { + template _Sent, + weakly_incrementable _Out> + requires indirectly_movable<_Iter, _Out> + constexpr move_result<_Iter, _Out> + operator()(_Iter __first, _Sent __last, _Out __result) const + { + return ranges::__copy_or_move(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Out> + constexpr move_result, _Out> + operator()(_Range&& __r, _Out __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __move_fn move{}; + + template _Sent, + bidirectional_iterator _Out> + requires (_IsMove + ? indirectly_movable<_Iter, _Out> + : indirectly_copyable<_Iter, _Out>) + constexpr conditional_t<_IsMove, + move_backward_result<_Iter, _Out>, + copy_backward_result<_Iter, _Out>> + __copy_or_move_backward(_Iter __first, _Sent __last, _Out __result) + { + // TODO: implement more specializations to be at least on par with + // std::copy_backward/std::move_backward. + using __detail::__is_reverse_iterator; + using __detail::__is_normal_iterator; + if constexpr (__is_reverse_iterator<_Iter> && same_as<_Iter, _Sent> + && __is_reverse_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move<_IsMove>(std::move(__last).base(), + std::move(__first).base(), + std::move(__result).base()); + return {reverse_iterator{std::move(__in)}, + reverse_iterator{std::move(__out)}}; + } + else if constexpr (__is_normal_iterator<_Iter> && same_as<_Iter, _Sent>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(__first.base(), + __last.base(), + std::move(__result)); + return {decltype(__first){__in}, std::move(__out)}; + } + else if constexpr (__is_normal_iterator<_Out>) + { + auto [__in,__out] + = ranges::__copy_or_move_backward<_IsMove>(std::move(__first), + std::move(__last), + __result.base()); + return {std::move(__in), decltype(__result){__out}}; + } + else if constexpr (sized_sentinel_for<_Sent, _Iter>) + { +#ifdef __cpp_lib_is_constant_evaluated + if (!std::is_constant_evaluated()) +#endif + { + if constexpr (__memcpyable<_Out, _Iter>::__value) + { + using _ValueTypeI = iter_value_t<_Iter>; + static_assert(_IsMove + ? is_move_assignable_v<_ValueTypeI> + : is_copy_assignable_v<_ValueTypeI>); + auto __num = __last - __first; + if (__num) + __builtin_memmove(__result - __num, __first, + sizeof(_ValueTypeI) * __num); + return {__first + __num, __result - __num}; + } + } + + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + + for (auto __n = __last - __first; __n > 0; --__n) + { + --__tail; + --__result; + if constexpr (_IsMove) + *__result = std::move(*__tail); + else + *__result = *__tail; + } + return {std::move(__lasti), std::move(__result)}; + } + else + { + auto __lasti = ranges::next(__first, __last); + auto __tail = __lasti; + + while (__first != __tail) + { + --__tail; + --__result; + if constexpr (_IsMove) + *__result = std::move(*__tail); + else + *__result = *__tail; + } + return {std::move(__lasti), std::move(__result)}; + } + } + + struct __copy_backward_fn + { + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_copyable<_Iter1, _Iter2> + constexpr copy_backward_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_copyable, _Iter> + constexpr copy_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __copy_backward_fn copy_backward{}; + + struct __move_backward_fn + { + template _Sent1, + bidirectional_iterator _Iter2> + requires indirectly_movable<_Iter1, _Iter2> + constexpr move_backward_result<_Iter1, _Iter2> + operator()(_Iter1 __first, _Sent1 __last, _Iter2 __result) const + { + return ranges::__copy_or_move_backward(std::move(__first), + std::move(__last), + std::move(__result)); + } + + template + requires indirectly_movable, _Iter> + constexpr move_backward_result, _Iter> + operator()(_Range&& __r, _Iter __result) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), + std::move(__result)); + } + }; + + inline constexpr __move_backward_fn move_backward{}; + + template + using copy_n_result = in_out_result<_Iter, _Out>; + + struct __copy_n_fn + { + template + requires indirectly_copyable<_Iter, _Out> + constexpr copy_n_result<_Iter, _Out> + operator()(_Iter __first, iter_difference_t<_Iter> __n, + _Out __result) const + { + if constexpr (random_access_iterator<_Iter>) + return ranges::copy(__first, __first + __n, std::move(__result)); + else + { + for (; __n > 0; --__n, (void)++__result, (void)++__first) + *__result = *__first; + return {std::move(__first), std::move(__result)}; + } + } + }; + + inline constexpr __copy_n_fn copy_n{}; + + struct __fill_n_fn + { + template _Out> + constexpr _Out + operator()(_Out __first, iter_difference_t<_Out> __n, + const _Tp& __value) const + { + // TODO: implement more specializations to be at least on par with + // std::fill_n + if (__n <= 0) + return __first; + + // TODO: Generalize this optimization to contiguous iterators. + if constexpr (is_pointer_v<_Out> + // Note that __is_byte already implies !is_volatile. + && __is_byte>::__value + && integral<_Tp>) + { + __builtin_memset(__first, static_cast(__value), __n); + return __first + __n; + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __n > 0; --__n, (void)++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __n > 0; --__n, (void)++__first) + *__first = __value; + return __first; + } + } + }; + + inline constexpr __fill_n_fn fill_n{}; + + struct __fill_fn + { + template _Out, sentinel_for<_Out> _Sent> + constexpr _Out + operator()(_Out __first, _Sent __last, const _Tp& __value) const + { + // TODO: implement more specializations to be at least on par with + // std::fill + if constexpr (sized_sentinel_for<_Sent, _Out>) + { + const auto __len = __last - __first; + return ranges::fill_n(__first, __len, __value); + } + else if constexpr (is_scalar_v<_Tp>) + { + const auto __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + return __first; + } + else + { + for (; __first != __last; ++__first) + *__first = __value; + return __first; + } + } + + template _Range> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __value) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __value); + } + }; + + inline constexpr __fill_fn fill{}; +} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_ALGOBASE_H diff --git a/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h b/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h new file mode 100644 index 000000000..25e664de7 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/ranges_uninitialized.h @@ -0,0 +1,574 @@ +// Raw memory manipulators -*- C++ -*- + +// Copyright (C) 2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/ranges_uninitialized.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _RANGES_UNINITIALIZED_H +#define _RANGES_UNINITIALIZED_H 1 + +#if __cplusplus > 201703L +#if __cpp_lib_concepts + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + namespace __detail + { + template + constexpr void* + __voidify(_Tp& __obj) noexcept + { + return const_cast + (static_cast(std::__addressof(__obj))); + } + + template + concept __nothrow_input_iterator + = (input_iterator<_Iter> + && is_lvalue_reference_v> + && same_as>, + iter_value_t<_Iter>>); + + template + concept __nothrow_sentinel = sentinel_for<_Sent, _Iter>; + + template + concept __nothrow_input_range + = (range<_Range> + && __nothrow_input_iterator> + && __nothrow_sentinel, iterator_t<_Range>>); + + template + concept __nothrow_forward_iterator + = (__nothrow_input_iterator<_Iter> + && forward_iterator<_Iter> + && __nothrow_sentinel<_Iter, _Iter>); + + template + concept __nothrow_forward_range + = (__nothrow_input_range<_Range> + && __nothrow_forward_iterator>); + } // namespace __detail + + struct __destroy_fn + { + template<__detail::__nothrow_input_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires destructible> + constexpr _Iter + operator()(_Iter __first, _Sent __last) const noexcept; + + template<__detail::__nothrow_input_range _Range> + requires destructible> + constexpr borrowed_iterator_t<_Range> + operator()(_Range&& __r) const noexcept; + }; + + inline constexpr __destroy_fn destroy{}; + + namespace __detail + { + template + requires destructible> + struct _DestroyGuard + { + private: + _Iter _M_first; + const _Iter* _M_cur; + + public: + explicit + _DestroyGuard(const _Iter* __iter) + : _M_first(*__iter), _M_cur(__iter) + { } + + void + release() noexcept + { _M_cur = nullptr; } + + ~_DestroyGuard() + { + if (_M_cur != nullptr) + ranges::destroy(std::move(_M_first), *_M_cur); + } + }; + + template + requires destructible> + && is_trivially_destructible_v> + struct _DestroyGuard<_Iter> + { + explicit + _DestroyGuard(const _Iter*) + { } + + void + release() noexcept + { } + }; + } // namespace __detail + + struct __uninitialized_default_construct_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires default_initializable> + _Iter + operator()(_Iter __first, _Sent __last) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivially_default_constructible_v<_ValueType>) + return ranges::next(__first, __last); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType; + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range> + requires default_initializable> + borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __uninitialized_default_construct_fn + uninitialized_default_construct{}; + + struct __uninitialized_default_construct_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter> + requires default_initializable> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivially_default_constructible_v<_ValueType>) + return ranges::next(__first, __n); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void) --__n) + ::new (__detail::__voidify(*__first)) _ValueType; + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_default_construct_n_fn + uninitialized_default_construct_n; + + struct __uninitialized_value_construct_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires default_initializable> + _Iter + operator()(_Iter __first, _Sent __last) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_copy_assignable_v<_ValueType>) + return ranges::fill(__first, __last, _ValueType()); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType(); + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range> + requires default_initializable> + borrowed_iterator_t<_Range> + operator()(_Range&& __r) const + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + }; + + inline constexpr __uninitialized_value_construct_fn + uninitialized_value_construct{}; + + struct __uninitialized_value_construct_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter> + requires default_initializable> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_copy_assignable_v<_ValueType>) + return ranges::fill_n(__first, __n, _ValueType()); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void) --__n) + ::new (__detail::__voidify(*__first)) _ValueType(); + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_value_construct_n_fn + uninitialized_value_construct_n; + + template + using uninitialized_copy_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_copy_fn + { + template _ISent, + __detail::__nothrow_forward_iterator _Out, + __detail::__nothrow_sentinel<_Out> _OSent> + requires constructible_from, iter_reference_t<_Iter>> + uninitialized_copy_result<_Iter, _Out> + operator()(_Iter __ifirst, _ISent __ilast, + _Out __ofirst, _OSent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_ISent, _Iter> + && sized_sentinel_for<_OSent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_reference_t<_Iter>>) + { + auto __d1 = __ilast - __ifirst; + auto __d2 = __olast - __ofirst; + return ranges::copy_n(std::move(__ifirst), std::min(__d1, __d2), + __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __ifirst != __ilast && __ofirst != __olast; + ++__ofirst, (void)++__ifirst) + ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + + template + requires constructible_from, + range_reference_t<_IRange>> + uninitialized_copy_result, + borrowed_iterator_t<_ORange>> + operator()(_IRange&& __inr, _ORange&& __outr) const + { + return (*this)(ranges::begin(__inr), ranges::end(__inr), + ranges::begin(__outr), ranges::end(__outr)); + } + }; + + inline constexpr __uninitialized_copy_fn uninitialized_copy{}; + + template + using uninitialized_copy_n_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_copy_n_fn + { + template _Sent> + requires constructible_from, iter_reference_t<_Iter>> + uninitialized_copy_n_result<_Iter, _Out> + operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, + _Out __ofirst, _Sent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_Sent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_reference_t<_Iter>>) + { + auto __d = __olast - __ofirst; + return ranges::copy_n(std::move(__ifirst), std::min(__n, __d), + __ofirst); + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __n > 0 && __ofirst != __olast; + ++__ofirst, (void)++__ifirst, (void)--__n) + ::new (__detail::__voidify(*__ofirst)) _OutType(*__ifirst); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + }; + + inline constexpr __uninitialized_copy_n_fn uninitialized_copy_n{}; + + template + using uninitialized_move_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_move_fn + { + template _ISent, + __detail::__nothrow_forward_iterator _Out, + __detail::__nothrow_sentinel<_Out> _OSent> + requires constructible_from, + iter_rvalue_reference_t<_Iter>> + uninitialized_move_result<_Iter, _Out> + operator()(_Iter __ifirst, _ISent __ilast, + _Out __ofirst, _OSent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_ISent, _Iter> + && sized_sentinel_for<_OSent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_rvalue_reference_t<_Iter>>) + { + auto __d1 = __ilast - __ifirst; + auto __d2 = __olast - __ofirst; + auto [__in, __out] + = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), + std::min(__d1, __d2), __ofirst); + return {std::move(__in).base(), __out}; + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __ifirst != __ilast && __ofirst != __olast; + ++__ofirst, (void)++__ifirst) + ::new (__detail::__voidify(*__ofirst)) + _OutType(ranges::iter_move(__ifirst)); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + + template + requires constructible_from, + range_rvalue_reference_t<_IRange>> + uninitialized_move_result, + borrowed_iterator_t<_ORange>> + operator()(_IRange&& __inr, _ORange&& __outr) const + { + return (*this)(ranges::begin(__inr), ranges::end(__inr), + ranges::begin(__outr), ranges::end(__outr)); + } + }; + + inline constexpr __uninitialized_move_fn uninitialized_move{}; + + template + using uninitialized_move_n_result = in_out_result<_Iter, _Out>; + + struct __uninitialized_move_n_fn + { + template _Sent> + requires constructible_from, + iter_rvalue_reference_t<_Iter>> + uninitialized_move_n_result<_Iter, _Out> + operator()(_Iter __ifirst, iter_difference_t<_Iter> __n, + _Out __ofirst, _Sent __olast) const + { + using _OutType = remove_reference_t>; + if constexpr (sized_sentinel_for<_Sent, _Out> + && is_trivial_v<_OutType> + && is_nothrow_assignable_v<_OutType&, + iter_rvalue_reference_t<_Iter>>) + { + auto __d = __olast - __ofirst; + auto [__in, __out] + = ranges::copy_n(std::make_move_iterator(std::move(__ifirst)), + std::min(__n, __d), __ofirst); + return {std::move(__in).base(), __out}; + } + else + { + auto __guard = __detail::_DestroyGuard(&__ofirst); + for (; __n > 0 && __ofirst != __olast; + ++__ofirst, (void)++__ifirst, (void)--__n) + ::new (__detail::__voidify(*__ofirst)) + _OutType(ranges::iter_move(__ifirst)); + __guard.release(); + return {std::move(__ifirst), __ofirst}; + } + } + }; + + inline constexpr __uninitialized_move_n_fn uninitialized_move_n{}; + + struct __uninitialized_fill_fn + { + template<__detail::__nothrow_forward_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent, typename _Tp> + requires constructible_from, const _Tp&> + _Iter + operator()(_Iter __first, _Sent __last, const _Tp& __x) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_nothrow_assignable_v<_ValueType&, const _Tp&>) + return ranges::fill(__first, __last, __x); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __first != __last; ++__first) + ::new (__detail::__voidify(*__first)) _ValueType(__x); + __guard.release(); + return __first; + } + } + + template<__detail::__nothrow_forward_range _Range, typename _Tp> + requires constructible_from, const _Tp&> + borrowed_iterator_t<_Range> + operator()(_Range&& __r, const _Tp& __x) const + { + return (*this)(ranges::begin(__r), ranges::end(__r), __x); + } + }; + + inline constexpr __uninitialized_fill_fn uninitialized_fill{}; + + struct __uninitialized_fill_n_fn + { + template<__detail::__nothrow_forward_iterator _Iter, typename _Tp> + requires constructible_from, const _Tp&> + _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n, + const _Tp& __x) const + { + using _ValueType = remove_reference_t>; + if constexpr (is_trivial_v<_ValueType> + && is_nothrow_assignable_v<_ValueType&, const _Tp&>) + return ranges::fill_n(__first, __n, __x); + else + { + auto __guard = __detail::_DestroyGuard(&__first); + for (; __n > 0; ++__first, (void)--__n) + ::new (__detail::__voidify(*__first)) _ValueType(__x); + __guard.release(); + return __first; + } + } + }; + + inline constexpr __uninitialized_fill_n_fn uninitialized_fill_n{}; + + struct __construct_at_fn + { + template + requires requires { + ::new (std::declval()) _Tp(std::declval<_Args>()...); + } + constexpr _Tp* + operator()(_Tp* __location, _Args&&... __args) const + noexcept(noexcept(std::construct_at(__location, + std::forward<_Args>(__args)...))) + { + return std::construct_at(__location, + std::forward<_Args>(__args)...); + } + }; + + inline constexpr __construct_at_fn construct_at{}; + + struct __destroy_at_fn + { + template + constexpr void + operator()(_Tp* __location) const noexcept + { + if constexpr (is_array_v<_Tp>) + ranges::destroy(ranges::begin(*__location), ranges::end(*__location)); + else + __location->~_Tp(); + } + }; + + inline constexpr __destroy_at_fn destroy_at{}; + + template<__detail::__nothrow_input_iterator _Iter, + __detail::__nothrow_sentinel<_Iter> _Sent> + requires destructible> + constexpr _Iter + __destroy_fn::operator()(_Iter __first, _Sent __last) const noexcept + { + if constexpr (is_trivially_destructible_v>) + return ranges::next(std::move(__first), __last); + else + { + for (; __first != __last; ++__first) + ranges::destroy_at(std::__addressof(*__first)); + return __first; + } + } + + template<__detail::__nothrow_input_range _Range> + requires destructible> + constexpr borrowed_iterator_t<_Range> + __destroy_fn::operator()(_Range&& __r) const noexcept + { + return (*this)(ranges::begin(__r), ranges::end(__r)); + } + + struct __destroy_n_fn + { + template<__detail::__nothrow_input_iterator _Iter> + requires destructible> + constexpr _Iter + operator()(_Iter __first, iter_difference_t<_Iter> __n) const noexcept + { + if constexpr (is_trivially_destructible_v>) + return ranges::next(std::move(__first), __n); + else + { + for (; __n > 0; ++__first, (void)--__n) + ranges::destroy_at(std::__addressof(*__first)); + return __first; + } + } + }; + + inline constexpr __destroy_n_fn destroy_n{}; +} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _RANGES_UNINITIALIZED_H diff --git a/resources/sources/avr-libstdcpp/include/bits/refwrap.h b/resources/sources/avr-libstdcpp/include/bits/refwrap.h new file mode 100644 index 000000000..717aa0162 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/refwrap.h @@ -0,0 +1,401 @@ +// Implementation of std::reference_wrapper -*- C++ -*- + +// Copyright (C) 2004-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/refwrap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_REFWRAP_H +#define _GLIBCXX_REFWRAP_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include // for unary_function and binary_function + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// @cond undocumented + + /** + * Derives from @c unary_function or @c binary_function, or perhaps + * nothing, depending on the number of arguments provided. The + * primary template is the basis case, which derives nothing. + */ + template + struct _Maybe_unary_or_binary_function { }; + + /// Derives from @c unary_function, as appropriate. + template + struct _Maybe_unary_or_binary_function<_Res, _T1> + : std::unary_function<_T1, _Res> { }; + + /// Derives from @c binary_function, as appropriate. + template + struct _Maybe_unary_or_binary_function<_Res, _T1, _T2> + : std::binary_function<_T1, _T2, _Res> { }; + + template + struct _Mem_fn_traits; + + template + struct _Mem_fn_traits_base + { + using __result_type = _Res; + using __maybe_type + = _Maybe_unary_or_binary_function<_Res, _Class*, _ArgTypes...>; + using __arity = integral_constant; + }; + +#define _GLIBCXX_MEM_FN_TRAITS2(_CV, _REF, _LVAL, _RVAL) \ + template \ + struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes...) _CV _REF> \ + : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ + { \ + using __vararg = false_type; \ + }; \ + template \ + struct _Mem_fn_traits<_Res (_Class::*)(_ArgTypes... ...) _CV _REF> \ + : _Mem_fn_traits_base<_Res, _CV _Class, _ArgTypes...> \ + { \ + using __vararg = true_type; \ + }; + +#define _GLIBCXX_MEM_FN_TRAITS(_REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2( , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(const , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(volatile , _REF, _LVAL, _RVAL) \ + _GLIBCXX_MEM_FN_TRAITS2(const volatile, _REF, _LVAL, _RVAL) + +_GLIBCXX_MEM_FN_TRAITS( , true_type, true_type) +_GLIBCXX_MEM_FN_TRAITS(&, true_type, false_type) +_GLIBCXX_MEM_FN_TRAITS(&&, false_type, true_type) + +#if __cplusplus > 201402L +_GLIBCXX_MEM_FN_TRAITS(noexcept, true_type, true_type) +_GLIBCXX_MEM_FN_TRAITS(& noexcept, true_type, false_type) +_GLIBCXX_MEM_FN_TRAITS(&& noexcept, false_type, true_type) +#endif + +#undef _GLIBCXX_MEM_FN_TRAITS +#undef _GLIBCXX_MEM_FN_TRAITS2 + + /// If we have found a result_type, extract it. + template> + struct _Maybe_get_result_type + { }; + + template + struct _Maybe_get_result_type<_Functor, + __void_t> + { typedef typename _Functor::result_type result_type; }; + + /** + * Base class for any function object that has a weak result type, as + * defined in 20.8.2 [func.require] of C++11. + */ + template + struct _Weak_result_type_impl + : _Maybe_get_result_type<_Functor> + { }; + + /// Retrieve the result type for a function type. + template + struct _Weak_result_type_impl<_Res(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a varargs function type. + template + struct _Weak_result_type_impl<_Res(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a function pointer. + template + struct _Weak_result_type_impl<_Res(*)(_ArgTypes...) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + /// Retrieve the result type for a varargs function pointer. + template + struct + _Weak_result_type_impl<_Res(*)(_ArgTypes......) _GLIBCXX_NOEXCEPT_QUAL> + { typedef _Res result_type; }; + + // Let _Weak_result_type_impl perform the real work. + template::value> + struct _Weak_result_type_memfun + : _Weak_result_type_impl<_Functor> + { }; + + // A pointer to member function has a weak result type. + template + struct _Weak_result_type_memfun<_MemFunPtr, true> + { + using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; + }; + + // A pointer to data member doesn't have a weak result type. + template + struct _Weak_result_type_memfun<_Func _Class::*, false> + { }; + + /** + * Strip top-level cv-qualifiers from the function object and let + * _Weak_result_type_memfun perform the real work. + */ + template + struct _Weak_result_type + : _Weak_result_type_memfun::type> + { }; + +#if __cplusplus <= 201703L + // Detect nested argument_type. + template> + struct _Refwrap_base_arg1 + { }; + + // Nested argument_type. + template + struct _Refwrap_base_arg1<_Tp, + __void_t> + { + typedef typename _Tp::argument_type argument_type; + }; + + // Detect nested first_argument_type and second_argument_type. + template> + struct _Refwrap_base_arg2 + { }; + + // Nested first_argument_type and second_argument_type. + template + struct _Refwrap_base_arg2<_Tp, + __void_t> + { + typedef typename _Tp::first_argument_type first_argument_type; + typedef typename _Tp::second_argument_type second_argument_type; + }; + + /** + * Derives from unary_function or binary_function when it + * can. Specializations handle all of the easy cases. The primary + * template determines what to do with a class type, which may + * derive from both unary_function and binary_function. + */ + template + struct _Reference_wrapper_base + : _Weak_result_type<_Tp>, _Refwrap_base_arg1<_Tp>, _Refwrap_base_arg2<_Tp> + { }; + + // - a function type (unary) + template + struct _Reference_wrapper_base<_Res(_T1) _GLIBCXX_NOEXCEPT_QUAL> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) const> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) volatile> + : unary_function<_T1, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1) const volatile> + : unary_function<_T1, _Res> + { }; + + // - a function type (binary) + template + struct _Reference_wrapper_base<_Res(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) const> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) volatile> + : binary_function<_T1, _T2, _Res> + { }; + + template + struct _Reference_wrapper_base<_Res(_T1, _T2) const volatile> + : binary_function<_T1, _T2, _Res> + { }; + + // - a function pointer type (unary) + template + struct _Reference_wrapper_base<_Res(*)(_T1) _GLIBCXX_NOEXCEPT_QUAL> + : unary_function<_T1, _Res> + { }; + + // - a function pointer type (binary) + template + struct _Reference_wrapper_base<_Res(*)(_T1, _T2) _GLIBCXX_NOEXCEPT_QUAL> + : binary_function<_T1, _T2, _Res> + { }; + + template::value> + struct _Reference_wrapper_base_memfun + : _Reference_wrapper_base<_Tp> + { }; + + template + struct _Reference_wrapper_base_memfun<_MemFunPtr, true> + : _Mem_fn_traits<_MemFunPtr>::__maybe_type + { + using result_type = typename _Mem_fn_traits<_MemFunPtr>::__result_type; + }; +#endif // ! C++20 + + /// @endcond + + /** + * @brief Primary class template for reference_wrapper. + * @ingroup functors + */ + template + class reference_wrapper +#if __cplusplus <= 201703L + // In C++20 std::reference_wrapper allows T to be incomplete, + // so checking for nested types could result in ODR violations. + : public _Reference_wrapper_base_memfun::type> +#endif + { + _Tp* _M_data; + + _GLIBCXX20_CONSTEXPR + static _Tp* _S_fun(_Tp& __r) noexcept { return std::__addressof(__r); } + + static void _S_fun(_Tp&&) = delete; + + template> + using __not_same + = typename enable_if::value>::type; + + public: + typedef _Tp type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2993. reference_wrapper conversion from T&& + // 3041. Unnecessary decay in reference_wrapper + template, typename + = decltype(reference_wrapper::_S_fun(std::declval<_Up>()))> + _GLIBCXX20_CONSTEXPR + reference_wrapper(_Up&& __uref) + noexcept(noexcept(reference_wrapper::_S_fun(std::declval<_Up>()))) + : _M_data(reference_wrapper::_S_fun(std::forward<_Up>(__uref))) + { } + + reference_wrapper(const reference_wrapper&) = default; + + reference_wrapper& + operator=(const reference_wrapper&) = default; + + _GLIBCXX20_CONSTEXPR + operator _Tp&() const noexcept + { return this->get(); } + + _GLIBCXX20_CONSTEXPR + _Tp& + get() const noexcept + { return *_M_data; } + + template + _GLIBCXX20_CONSTEXPR + typename result_of<_Tp&(_Args&&...)>::type + operator()(_Args&&... __args) const + { +#if __cplusplus > 201703L + if constexpr (is_object_v) + static_assert(sizeof(type), "type must be complete"); +#endif + return std::__invoke(get(), std::forward<_Args>(__args)...); + } + }; + +#if __cpp_deduction_guides + template + reference_wrapper(_Tp&) -> reference_wrapper<_Tp>; +#endif + + /// @relates reference_wrapper @{ + + /// Denotes a reference should be taken to a variable. + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper<_Tp> + ref(_Tp& __t) noexcept + { return reference_wrapper<_Tp>(__t); } + + /// Denotes a const reference should be taken to a variable. + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper + cref(const _Tp& __t) noexcept + { return reference_wrapper(__t); } + + template + void ref(const _Tp&&) = delete; + + template + void cref(const _Tp&&) = delete; + + /// std::ref overload to prevent wrapping a reference_wrapper + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper<_Tp> + ref(reference_wrapper<_Tp> __t) noexcept + { return __t; } + + /// std::cref overload to prevent wrapping a reference_wrapper + template + _GLIBCXX20_CONSTEXPR + inline reference_wrapper + cref(reference_wrapper<_Tp> __t) noexcept + { return { __t.get() }; } + + // @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_REFWRAP_H diff --git a/resources/sources/avr-libstdcpp/include/bits/slice_array.h b/resources/sources/avr-libstdcpp/include/bits/slice_array.h new file mode 100644 index 000000000..de33342e2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/slice_array.h @@ -0,0 +1,284 @@ +// The template and inlines for the -*- C++ -*- slice_array class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/slice_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _SLICE_ARRAY_H +#define _SLICE_ARRAY_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + /** + * @brief Class defining one-dimensional subset of an array. + * + * The slice class represents a one-dimensional subset of an array, + * specified by three parameters: start offset, size, and stride. The + * start offset is the index of the first element of the array that is part + * of the subset. The size is the total number of elements in the subset. + * Stride is the distance between each successive array element to include + * in the subset. + * + * For example, with an array of size 10, and a slice with offset 1, size 3 + * and stride 2, the subset consists of array elements 1, 3, and 5. + */ + class slice + { + public: + /// Construct an empty slice. + slice(); + + /** + * @brief Construct a slice. + * + * @param __o Offset in array of first element. + * @param __d Number of elements in slice. + * @param __s Stride between array elements. + */ + slice(size_t __o, size_t __d, size_t __s); + + /// Return array offset of first slice element. + size_t start() const; + /// Return size of slice. + size_t size() const; + /// Return array stride of slice. + size_t stride() const; + +#if __cpp_impl_three_way_comparison >= 201907L + /// Equality comparison + friend bool operator==(const slice&, const slice&) = default; +#endif + + private: + size_t _M_off; // offset + size_t _M_sz; // size + size_t _M_st; // stride unit + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 543. valarray slice default constructor + inline + slice::slice() + : _M_off(0), _M_sz(0), _M_st(0) {} + + inline + slice::slice(size_t __o, size_t __d, size_t __s) + : _M_off(__o), _M_sz(__d), _M_st(__s) {} + + inline size_t + slice::start() const + { return _M_off; } + + inline size_t + slice::size() const + { return _M_sz; } + + inline size_t + slice::stride() const + { return _M_st; } + + /** + * @brief Reference to one-dimensional subset of an array. + * + * A slice_array is a reference to the actual elements of an array + * specified by a slice. The way to get a slice_array is to call + * operator[](slice) on a valarray. The returned slice_array then permits + * carrying operations out on the referenced subset of elements in the + * original valarray. For example, operator+=(valarray) will add values + * to the subset of elements in the underlying valarray this slice_array + * refers to. + * + * @param Tp Element type. + */ + template + class slice_array + { + public: + typedef _Tp value_type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 253. valarray helper functions are almost entirely useless + + /// Copy constructor. Both slices refer to the same underlying array. + slice_array(const slice_array&); + + /// Assignment operator. Assigns slice elements to corresponding + /// elements of @a a. + slice_array& operator=(const slice_array&); + + /// Assign slice elements to corresponding elements of @a v. + void operator=(const valarray<_Tp>&) const; + /// Multiply slice elements by corresponding elements of @a v. + void operator*=(const valarray<_Tp>&) const; + /// Divide slice elements by corresponding elements of @a v. + void operator/=(const valarray<_Tp>&) const; + /// Modulo slice elements by corresponding elements of @a v. + void operator%=(const valarray<_Tp>&) const; + /// Add corresponding elements of @a v to slice elements. + void operator+=(const valarray<_Tp>&) const; + /// Subtract corresponding elements of @a v from slice elements. + void operator-=(const valarray<_Tp>&) const; + /// Logical xor slice elements with corresponding elements of @a v. + void operator^=(const valarray<_Tp>&) const; + /// Logical and slice elements with corresponding elements of @a v. + void operator&=(const valarray<_Tp>&) const; + /// Logical or slice elements with corresponding elements of @a v. + void operator|=(const valarray<_Tp>&) const; + /// Left shift slice elements by corresponding elements of @a v. + void operator<<=(const valarray<_Tp>&) const; + /// Right shift slice elements by corresponding elements of @a v. + void operator>>=(const valarray<_Tp>&) const; + /// Assign all slice elements to @a t. + void operator=(const _Tp &) const; + // ~slice_array (); + + template + void operator=(const _Expr<_Dom, _Tp>&) const; + template + void operator*=(const _Expr<_Dom, _Tp>&) const; + template + void operator/=(const _Expr<_Dom, _Tp>&) const; + template + void operator%=(const _Expr<_Dom, _Tp>&) const; + template + void operator+=(const _Expr<_Dom, _Tp>&) const; + template + void operator-=(const _Expr<_Dom, _Tp>&) const; + template + void operator^=(const _Expr<_Dom, _Tp>&) const; + template + void operator&=(const _Expr<_Dom, _Tp>&) const; + template + void operator|=(const _Expr<_Dom, _Tp>&) const; + template + void operator<<=(const _Expr<_Dom, _Tp>&) const; + template + void operator>>=(const _Expr<_Dom, _Tp>&) const; + + private: + friend class valarray<_Tp>; + slice_array(_Array<_Tp>, const slice&); + + const size_t _M_sz; + const size_t _M_stride; + const _Array<_Tp> _M_array; + +#if __cplusplus < 201103L + // not implemented + slice_array(); +#else + public: + slice_array() = delete; +#endif + }; + + template + inline + slice_array<_Tp>::slice_array(_Array<_Tp> __a, const slice& __s) + : _M_sz(__s.size()), _M_stride(__s.stride()), + _M_array(__a.begin() + __s.start()) {} + + template + inline + slice_array<_Tp>::slice_array(const slice_array<_Tp>& __a) + : _M_sz(__a._M_sz), _M_stride(__a._M_stride), _M_array(__a._M_array) {} + + // template + // inline slice_array<_Tp>::~slice_array () {} + + template + inline slice_array<_Tp>& + slice_array<_Tp>::operator=(const slice_array<_Tp>& __a) + { + std::__valarray_copy(__a._M_array, __a._M_sz, __a._M_stride, + _M_array, _M_stride); + return *this; + } + + template + inline void + slice_array<_Tp>::operator=(const _Tp& __t) const + { std::__valarray_fill(_M_array, _M_sz, _M_stride, __t); } + + template + inline void + slice_array<_Tp>::operator=(const valarray<_Tp>& __v) const + { std::__valarray_copy(_Array<_Tp>(__v), _M_array, _M_sz, _M_stride); } + + template + template + inline void + slice_array<_Tp>::operator=(const _Expr<_Dom,_Tp>& __e) const + { std::__valarray_copy(__e, _M_sz, _M_array, _M_stride); } + +#undef _DEFINE_VALARRAY_OPERATOR +#define _DEFINE_VALARRAY_OPERATOR(_Op,_Name) \ + template \ + inline void \ + slice_array<_Tp>::operator _Op##=(const valarray<_Tp>& __v) const \ + { \ + _Array_augmented_##_Name(_M_array, _M_sz, _M_stride, _Array<_Tp>(__v));\ + } \ + \ + template \ + template \ + inline void \ + slice_array<_Tp>::operator _Op##=(const _Expr<_Dom,_Tp>& __e) const\ + { \ + _Array_augmented_##_Name(_M_array, _M_stride, __e, _M_sz); \ + } + + +_DEFINE_VALARRAY_OPERATOR(*, __multiplies) +_DEFINE_VALARRAY_OPERATOR(/, __divides) +_DEFINE_VALARRAY_OPERATOR(%, __modulus) +_DEFINE_VALARRAY_OPERATOR(+, __plus) +_DEFINE_VALARRAY_OPERATOR(-, __minus) +_DEFINE_VALARRAY_OPERATOR(^, __bitwise_xor) +_DEFINE_VALARRAY_OPERATOR(&, __bitwise_and) +_DEFINE_VALARRAY_OPERATOR(|, __bitwise_or) +_DEFINE_VALARRAY_OPERATOR(<<, __shift_left) +_DEFINE_VALARRAY_OPERATOR(>>, __shift_right) + +#undef _DEFINE_VALARRAY_OPERATOR + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _SLICE_ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/std_abs.h b/resources/sources/avr-libstdcpp/include/bits/std_abs.h new file mode 100644 index 000000000..b0451a3ab --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/std_abs.h @@ -0,0 +1,111 @@ +// -*- C++ -*- C library enhancements header. + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/std_abs.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{cmath, cstdlib} + */ + +#ifndef _GLIBCXX_BITS_STD_ABS_H +#define _GLIBCXX_BITS_STD_ABS_H + +#pragma GCC system_header + +#include + +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include_next +#ifdef __CORRECT_ISO_CPP_MATH_H_PROTO +# include_next +#endif +#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS + +#undef abs + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::abs; + +#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO + inline long + abs(long __i) { return __builtin_labs(__i); } +#endif + +#ifdef _GLIBCXX_USE_LONG_LONG + inline long long + abs(long long __x) { return __builtin_llabs (__x); } +#endif + +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// 2192. Validity and return type of std::abs(0u) is unclear +// 2294. should declare abs(double) +// 2735. std::abs(short), std::abs(signed char) and others should return int + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR double + abs(double __x) + { return __builtin_fabs(__x); } + + inline _GLIBCXX_CONSTEXPR float + abs(float __x) + { return __builtin_fabsf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + abs(long double __x) + { return __builtin_fabsl(__x); } +#endif + +#if defined(__GLIBCXX_TYPE_INT_N_0) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0 + abs(__GLIBCXX_TYPE_INT_N_0 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1 + abs(__GLIBCXX_TYPE_INT_N_1 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2 + abs(__GLIBCXX_TYPE_INT_N_2 __x) { return __x >= 0 ? __x : -__x; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 + abs(__GLIBCXX_TYPE_INT_N_3 __x) { return __x >= 0 ? __x : -__x; } +#endif + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + inline _GLIBCXX_CONSTEXPR + __float128 + abs(__float128 __x) + { return __x < 0 ? -__x : __x; } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C"++" + +#endif // _GLIBCXX_BITS_STD_ABS_H diff --git a/resources/sources/avr-libstdcpp/include/bits/std_function.h b/resources/sources/avr-libstdcpp/include/bits/std_function.h new file mode 100644 index 000000000..4a3848030 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/std_function.h @@ -0,0 +1,728 @@ +// Implementation of std::function -*- C++ -*- + +// Copyright (C) 2004-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/std_function.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _GLIBCXX_STD_FUNCTION_H +#define _GLIBCXX_STD_FUNCTION_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#if __cpp_rtti +# include +#endif +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * Trait identifying "location-invariant" types, meaning that the + * address of the object (or any of its members) will not escape. + * Trivially copyable types are location-invariant and users can + * specialize this trait for other types. + */ + template + struct __is_location_invariant + : is_trivially_copyable<_Tp>::type + { }; + + class _Undefined_class; + + union _Nocopy_types + { + void* _M_object; + const void* _M_const_object; + void (*_M_function_pointer)(); + void (_Undefined_class::*_M_member_pointer)(); + }; + + union [[gnu::may_alias]] _Any_data + { + void* _M_access() { return &_M_pod_data[0]; } + const void* _M_access() const { return &_M_pod_data[0]; } + + template + _Tp& + _M_access() + { return *static_cast<_Tp*>(_M_access()); } + + template + const _Tp& + _M_access() const + { return *static_cast(_M_access()); } + + _Nocopy_types _M_unused; + char _M_pod_data[sizeof(_Nocopy_types)]; + }; + + enum _Manager_operation + { + __get_type_info, + __get_functor_ptr, + __clone_functor, + __destroy_functor + }; + + template + class function; + + /// Base class of all polymorphic function object wrappers. + class _Function_base + { + public: + static const size_t _M_max_size = sizeof(_Nocopy_types); + static const size_t _M_max_align = __alignof__(_Nocopy_types); + + template + class _Base_manager + { + protected: + static const bool __stored_locally = + (__is_location_invariant<_Functor>::value + && sizeof(_Functor) <= _M_max_size + && __alignof__(_Functor) <= _M_max_align + && (_M_max_align % __alignof__(_Functor) == 0)); + + typedef integral_constant _Local_storage; + + // Retrieve a pointer to the function object + static _Functor* + _M_get_pointer(const _Any_data& __source) + { + if _GLIBCXX17_CONSTEXPR (__stored_locally) + { + const _Functor& __f = __source._M_access<_Functor>(); + return const_cast<_Functor*>(std::__addressof(__f)); + } + else // have stored a pointer + return __source._M_access<_Functor*>(); + } + + // Clone a location-invariant function object that fits within + // an _Any_data structure. + static void + _M_clone(_Any_data& __dest, const _Any_data& __source, true_type) + { + ::new (__dest._M_access()) _Functor(__source._M_access<_Functor>()); + } + + // Clone a function object that is not location-invariant or + // that cannot fit into an _Any_data structure. + static void + _M_clone(_Any_data& __dest, const _Any_data& __source, false_type) + { + __dest._M_access<_Functor*>() = + new _Functor(*__source._M_access()); + } + + // Destroying a location-invariant object may still require + // destruction. + static void + _M_destroy(_Any_data& __victim, true_type) + { + __victim._M_access<_Functor>().~_Functor(); + } + + // Destroying an object located on the heap. + static void + _M_destroy(_Any_data& __victim, false_type) + { + delete __victim._M_access<_Functor*>(); + } + + public: + static bool + _M_manager(_Any_data& __dest, const _Any_data& __source, + _Manager_operation __op) + { + switch (__op) + { +#if __cpp_rtti + case __get_type_info: + __dest._M_access() = &typeid(_Functor); + break; +#endif + case __get_functor_ptr: + __dest._M_access<_Functor*>() = _M_get_pointer(__source); + break; + + case __clone_functor: + _M_clone(__dest, __source, _Local_storage()); + break; + + case __destroy_functor: + _M_destroy(__dest, _Local_storage()); + break; + } + return false; + } + + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f) + { _M_init_functor(__functor, std::move(__f), _Local_storage()); } + + template + static bool + _M_not_empty_function(const function<_Signature>& __f) + { return static_cast(__f); } + + template + static bool + _M_not_empty_function(_Tp* __fp) + { return __fp != nullptr; } + + template + static bool + _M_not_empty_function(_Tp _Class::* __mp) + { return __mp != nullptr; } + + template + static bool + _M_not_empty_function(const _Tp&) + { return true; } + + private: + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f, true_type) + { ::new (__functor._M_access()) _Functor(std::move(__f)); } + + static void + _M_init_functor(_Any_data& __functor, _Functor&& __f, false_type) + { __functor._M_access<_Functor*>() = new _Functor(std::move(__f)); } + }; + + _Function_base() : _M_manager(nullptr) { } + + ~_Function_base() + { + if (_M_manager) + _M_manager(_M_functor, _M_functor, __destroy_functor); + } + + bool _M_empty() const { return !_M_manager; } + + typedef bool (*_Manager_type)(_Any_data&, const _Any_data&, + _Manager_operation); + + _Any_data _M_functor; + _Manager_type _M_manager; + }; + + template + class _Function_handler; + + template + class _Function_handler<_Res(_ArgTypes...), _Functor> + : public _Function_base::_Base_manager<_Functor> + { + typedef _Function_base::_Base_manager<_Functor> _Base; + + public: + static bool + _M_manager(_Any_data& __dest, const _Any_data& __source, + _Manager_operation __op) + { + switch (__op) + { +#if __cpp_rtti + case __get_type_info: + __dest._M_access() = &typeid(_Functor); + break; +#endif + case __get_functor_ptr: + __dest._M_access<_Functor*>() = _Base::_M_get_pointer(__source); + break; + + default: + _Base::_M_manager(__dest, __source, __op); + } + return false; + } + + static _Res + _M_invoke(const _Any_data& __functor, _ArgTypes&&... __args) + { + return std::__invoke_r<_Res>(*_Base::_M_get_pointer(__functor), + std::forward<_ArgTypes>(__args)...); + } + }; + + /** + * @brief Primary class template for std::function. + * @ingroup functors + * + * Polymorphic function wrapper. + */ + template + class function<_Res(_ArgTypes...)> + : public _Maybe_unary_or_binary_function<_Res, _ArgTypes...>, + private _Function_base + { + template> + struct _Callable + : __is_invocable_impl<_Res2, _Res>::type + { }; + + // Used so the return type convertibility checks aren't done when + // performing overload resolution for copy construction/assignment. + template + struct _Callable : false_type { }; + + template + using _Requires = typename enable_if<_Cond::value, _Tp>::type; + + public: + typedef _Res result_type; + + // [3.7.2.1] construct/copy/destroy + + /** + * @brief Default construct creates an empty function call wrapper. + * @post @c !(bool)*this + */ + function() noexcept + : _Function_base() { } + + /** + * @brief Creates an empty function call wrapper. + * @post @c !(bool)*this + */ + function(nullptr_t) noexcept + : _Function_base() { } + + /** + * @brief %Function copy constructor. + * @param __x A %function object with identical call signature. + * @post @c bool(*this) == bool(__x) + * + * The newly-created %function contains a copy of the target of @a + * __x (if it has one). + */ + function(const function& __x); + + /** + * @brief %Function move constructor. + * @param __x A %function object rvalue with identical call signature. + * + * The newly-created %function contains the target of @a __x + * (if it has one). + */ + function(function&& __x) noexcept : _Function_base() + { + __x.swap(*this); + } + + /** + * @brief Builds a %function that targets a copy of the incoming + * function object. + * @param __f A %function object that is callable with parameters of + * type @c T1, @c T2, ..., @c TN and returns a value convertible + * to @c Res. + * + * The newly-created %function object will target a copy of + * @a __f. If @a __f is @c reference_wrapper, then this function + * object will contain a reference to the function object @c + * __f.get(). If @a __f is a NULL function pointer or NULL + * pointer-to-member, the newly-created object will be empty. + * + * If @a __f is a non-NULL function pointer or an object of type @c + * reference_wrapper, this function will not throw. + */ + template>, void>, + typename = _Requires<_Callable<_Functor>, void>> + function(_Functor); + + /** + * @brief %Function assignment operator. + * @param __x A %function with identical call signature. + * @post @c (bool)*this == (bool)x + * @returns @c *this + * + * The target of @a __x is copied to @c *this. If @a __x has no + * target, then @c *this will be empty. + * + * If @a __x targets a function pointer or a reference to a function + * object, then this operation will not throw an %exception. + */ + function& + operator=(const function& __x) + { + function(__x).swap(*this); + return *this; + } + + /** + * @brief %Function move-assignment operator. + * @param __x A %function rvalue with identical call signature. + * @returns @c *this + * + * The target of @a __x is moved to @c *this. If @a __x has no + * target, then @c *this will be empty. + * + * If @a __x targets a function pointer or a reference to a function + * object, then this operation will not throw an %exception. + */ + function& + operator=(function&& __x) noexcept + { + function(std::move(__x)).swap(*this); + return *this; + } + + /** + * @brief %Function assignment to zero. + * @post @c !(bool)*this + * @returns @c *this + * + * The target of @c *this is deallocated, leaving it empty. + */ + function& + operator=(nullptr_t) noexcept + { + if (_M_manager) + { + _M_manager(_M_functor, _M_functor, __destroy_functor); + _M_manager = nullptr; + _M_invoker = nullptr; + } + return *this; + } + + /** + * @brief %Function assignment to a new target. + * @param __f A %function object that is callable with parameters of + * type @c T1, @c T2, ..., @c TN and returns a value convertible + * to @c Res. + * @return @c *this + * + * This %function object wrapper will target a copy of @a + * __f. If @a __f is @c reference_wrapper, then this function + * object will contain a reference to the function object @c + * __f.get(). If @a __f is a NULL function pointer or NULL + * pointer-to-member, @c this object will be empty. + * + * If @a __f is a non-NULL function pointer or an object of type @c + * reference_wrapper, this function will not throw. + */ + template + _Requires<_Callable::type>, function&> + operator=(_Functor&& __f) + { + function(std::forward<_Functor>(__f)).swap(*this); + return *this; + } + + /// @overload + template + function& + operator=(reference_wrapper<_Functor> __f) noexcept + { + function(__f).swap(*this); + return *this; + } + + // [3.7.2.2] function modifiers + + /** + * @brief Swap the targets of two %function objects. + * @param __x A %function with identical call signature. + * + * Swap the targets of @c this function object and @a __f. This + * function will not throw an %exception. + */ + void swap(function& __x) noexcept + { + std::swap(_M_functor, __x._M_functor); + std::swap(_M_manager, __x._M_manager); + std::swap(_M_invoker, __x._M_invoker); + } + + // [3.7.2.3] function capacity + + /** + * @brief Determine if the %function wrapper has a target. + * + * @return @c true when this %function object contains a target, + * or @c false when it is empty. + * + * This function will not throw an %exception. + */ + explicit operator bool() const noexcept + { return !_M_empty(); } + + // [3.7.2.4] function invocation + + /** + * @brief Invokes the function targeted by @c *this. + * @returns the result of the target. + * @throws bad_function_call when @c !(bool)*this + * + * The function call operator invokes the target function object + * stored by @c this. + */ + _Res operator()(_ArgTypes... __args) const; + +#if __cpp_rtti + // [3.7.2.5] function target access + /** + * @brief Determine the type of the target of this function object + * wrapper. + * + * @returns the type identifier of the target function object, or + * @c typeid(void) if @c !(bool)*this. + * + * This function will not throw an %exception. + */ + const type_info& target_type() const noexcept; + + /** + * @brief Access the stored target function object. + * + * @return Returns a pointer to the stored target function object, + * if @c typeid(_Functor).equals(target_type()); otherwise, a NULL + * pointer. + * + * This function does not throw exceptions. + * + * @{ + */ + template _Functor* target() noexcept; + + template const _Functor* target() const noexcept; + // @} +#endif + + private: + using _Invoker_type = _Res (*)(const _Any_data&, _ArgTypes&&...); + _Invoker_type _M_invoker; + }; + +#if __cpp_deduction_guides >= 201606 + template + struct __function_guide_helper + { }; + + template + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) & noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) const noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template + struct __function_guide_helper< + _Res (_Tp::*) (_Args...) const & noexcept(_Nx) + > + { using type = _Res(_Args...); }; + + template + function(_Res(*)(_ArgTypes...)) -> function<_Res(_ArgTypes...)>; + + template::type> + function(_Functor) -> function<_Signature>; +#endif + + // Out-of-line member definitions. + template + function<_Res(_ArgTypes...)>:: + function(const function& __x) + : _Function_base() + { + if (static_cast(__x)) + { + __x._M_manager(_M_functor, __x._M_functor, __clone_functor); + _M_invoker = __x._M_invoker; + _M_manager = __x._M_manager; + } + } + + template + template + function<_Res(_ArgTypes...)>:: + function(_Functor __f) + : _Function_base() + { + typedef _Function_handler<_Res(_ArgTypes...), _Functor> _My_handler; + + if (_My_handler::_M_not_empty_function(__f)) + { + _My_handler::_M_init_functor(_M_functor, std::move(__f)); + _M_invoker = &_My_handler::_M_invoke; + _M_manager = &_My_handler::_M_manager; + } + } + + template + _Res + function<_Res(_ArgTypes...)>:: + operator()(_ArgTypes... __args) const + { + if (_M_empty()) + __throw_bad_function_call(); + return _M_invoker(_M_functor, std::forward<_ArgTypes>(__args)...); + } + +#if __cpp_rtti + template + const type_info& + function<_Res(_ArgTypes...)>:: + target_type() const noexcept + { + if (_M_manager) + { + _Any_data __typeinfo_result; + _M_manager(__typeinfo_result, _M_functor, __get_type_info); + return *__typeinfo_result._M_access(); + } + else + return typeid(void); + } + + template + template + _Functor* + function<_Res(_ArgTypes...)>:: + target() noexcept + { + const function* __const_this = this; + const _Functor* __func = __const_this->template target<_Functor>(); + return const_cast<_Functor*>(__func); + } + + template + template + const _Functor* + function<_Res(_ArgTypes...)>:: + target() const noexcept + { + if (typeid(_Functor) == target_type() && _M_manager) + { + _Any_data __ptr; + _M_manager(__ptr, _M_functor, __get_functor_ptr); + return __ptr._M_access(); + } + else + return nullptr; + } +#endif + + // [20.7.15.2.6] null pointer comparisons + + /** + * @brief Compares a polymorphic function object wrapper against 0 + * (the NULL pointer). + * @returns @c true if the wrapper has no target, @c false otherwise + * + * This function will not throw an %exception. + */ + template + inline bool + operator==(const function<_Res(_Args...)>& __f, nullptr_t) noexcept + { return !static_cast(__f); } + +#if __cpp_impl_three_way_comparison < 201907L + /// @overload + template + inline bool + operator==(nullptr_t, const function<_Res(_Args...)>& __f) noexcept + { return !static_cast(__f); } + + /** + * @brief Compares a polymorphic function object wrapper against 0 + * (the NULL pointer). + * @returns @c false if the wrapper has no target, @c true otherwise + * + * This function will not throw an %exception. + */ + template + inline bool + operator!=(const function<_Res(_Args...)>& __f, nullptr_t) noexcept + { return static_cast(__f); } + + /// @overload + template + inline bool + operator!=(nullptr_t, const function<_Res(_Args...)>& __f) noexcept + { return static_cast(__f); } +#endif + + // [20.7.15.2.7] specialized algorithms + + /** + * @brief Swap the targets of two polymorphic function object wrappers. + * + * This function will not throw an %exception. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2062. Effect contradictions w/o no-throw guarantee of std::function swaps + template + inline void + swap(function<_Res(_Args...)>& __x, function<_Res(_Args...)>& __y) noexcept + { __x.swap(__y); } + +#if __cplusplus >= 201703L + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing a + // function into a variant. + template + struct _Never_valueless_alt> + : std::true_type + { }; + } // namespace __detail::__variant +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 +#endif // _GLIBCXX_STD_FUNCTION_H diff --git a/resources/sources/avr-libstdcpp/include/bits/std_mutex.h b/resources/sources/avr-libstdcpp/include/bits/std_mutex.h new file mode 100644 index 000000000..aef12b679 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/std_mutex.h @@ -0,0 +1,176 @@ +// std::mutex implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/std_mutex.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{mutex} + */ + +#ifndef _GLIBCXX_MUTEX_H +#define _GLIBCXX_MUTEX_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup mutexes Mutexes + * @ingroup concurrency + * + * Classes for mutex support. + * @{ + */ + +#ifdef _GLIBCXX_HAS_GTHREADS + // Common base class for std::mutex and std::timed_mutex + class __mutex_base + { + protected: + typedef __gthread_mutex_t __native_type; + +#ifdef __GTHREAD_MUTEX_INIT + __native_type _M_mutex = __GTHREAD_MUTEX_INIT; + + constexpr __mutex_base() noexcept = default; +#else + __native_type _M_mutex; + + __mutex_base() noexcept + { + // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) + __GTHREAD_MUTEX_INIT_FUNCTION(&_M_mutex); + } + + ~__mutex_base() noexcept { __gthread_mutex_destroy(&_M_mutex); } +#endif + + __mutex_base(const __mutex_base&) = delete; + __mutex_base& operator=(const __mutex_base&) = delete; + }; + + /// The standard mutex type. + class mutex : private __mutex_base + { + public: + typedef __native_type* native_handle_type; + +#ifdef __GTHREAD_MUTEX_INIT + constexpr +#endif + mutex() noexcept = default; + ~mutex() = default; + + mutex(const mutex&) = delete; + mutex& operator=(const mutex&) = delete; + + void + lock() + { + int __e = __gthread_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() noexcept + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_mutex_trylock(&_M_mutex); + } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EPERM + __gthread_mutex_unlock(&_M_mutex); + } + + native_handle_type + native_handle() noexcept + { return &_M_mutex; } + }; + +#endif // _GLIBCXX_HAS_GTHREADS + + /// Do not acquire ownership of the mutex. + struct defer_lock_t { explicit defer_lock_t() = default; }; + + /// Try to acquire ownership of the mutex without blocking. + struct try_to_lock_t { explicit try_to_lock_t() = default; }; + + /// Assume the calling thread has already obtained mutex ownership + /// and manage it. + struct adopt_lock_t { explicit adopt_lock_t() = default; }; + + /// Tag used to prevent a scoped lock from acquiring ownership of a mutex. + _GLIBCXX17_INLINE constexpr defer_lock_t defer_lock { }; + + /// Tag used to prevent a scoped lock from blocking if a mutex is locked. + _GLIBCXX17_INLINE constexpr try_to_lock_t try_to_lock { }; + + /// Tag used to make a scoped lock take ownership of a locked mutex. + _GLIBCXX17_INLINE constexpr adopt_lock_t adopt_lock { }; + + /** @brief A simple scoped lock type. + * + * A lock_guard controls mutex ownership within a scope, releasing + * ownership in the destructor. + */ + template + class lock_guard + { + public: + typedef _Mutex mutex_type; + + explicit lock_guard(mutex_type& __m) : _M_device(__m) + { _M_device.lock(); } + + lock_guard(mutex_type& __m, adopt_lock_t) noexcept : _M_device(__m) + { } // calling thread owns mutex + + ~lock_guard() + { _M_device.unlock(); } + + lock_guard(const lock_guard&) = delete; + lock_guard& operator=(const lock_guard&) = delete; + + private: + mutex_type& _M_device; + }; + + // @} group mutexes +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // C++11 +#endif // _GLIBCXX_MUTEX_H diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_algo.h b/resources/sources/avr-libstdcpp/include/bits/stl_algo.h new file mode 100644 index 000000000..2eb637e85 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_algo.h @@ -0,0 +1,5884 @@ +// Algorithm implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_algo.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _STL_ALGO_H +#define _STL_ALGO_H 1 + +#include // for rand +#include +#include +#include // for _Temporary_buffer +#include + +#if __cplusplus >= 201103L +#include +#endif + +// See concept_check.h for the __glibcxx_*_requires macros. + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Swaps the median value of *__a, *__b and *__c under __comp to *__result + template + _GLIBCXX20_CONSTEXPR + void + __move_median_to_first(_Iterator __result,_Iterator __a, _Iterator __b, + _Iterator __c, _Compare __comp) + { + if (__comp(__a, __b)) + { + if (__comp(__b, __c)) + std::iter_swap(__result, __b); + else if (__comp(__a, __c)) + std::iter_swap(__result, __c); + else + std::iter_swap(__result, __a); + } + else if (__comp(__a, __c)) + std::iter_swap(__result, __a); + else if (__comp(__b, __c)) + std::iter_swap(__result, __c); + else + std::iter_swap(__result, __b); + } + + /// Provided for stable_partition to use. + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + __find_if_not(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__negate(__pred), + std::__iterator_category(__first)); + } + + /// Like find_if_not(), but uses and updates a count of the + /// remaining range length instead of comparing against an end + /// iterator. + template + _GLIBCXX20_CONSTEXPR + _InputIterator + __find_if_not_n(_InputIterator __first, _Distance& __len, _Predicate __pred) + { + for (; __len; --__len, (void) ++__first) + if (!__pred(__first)) + break; + return __first; + } + + // set_difference + // set_intersection + // set_symmetric_difference + // set_union + // for_each + // find + // find_if + // find_first_of + // adjacent_find + // count + // count_if + // search + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator1 + __search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __predicate) + { + // Test for empty ranges + if (__first1 == __last1 || __first2 == __last2) + return __first1; + + // Test for a pattern of length 1. + _ForwardIterator2 __p1(__first2); + if (++__p1 == __last2) + return std::__find_if(__first1, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); + + // General case. + _ForwardIterator1 __current = __first1; + + for (;;) + { + __first1 = + std::__find_if(__first1, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__predicate, __first2)); + + if (__first1 == __last1) + return __last1; + + _ForwardIterator2 __p = __p1; + __current = __first1; + if (++__current == __last1) + return __last1; + + while (__predicate(__current, __p)) + { + if (++__p == __last2) + return __first1; + if (++__current == __last1) + return __last1; + } + ++__first1; + } + return __first1; + } + + // search_n + + /** + * This is an helper function for search_n overloaded for forward iterators. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __search_n_aux(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, _UnaryPredicate __unary_pred, + std::forward_iterator_tag) + { + __first = std::__find_if(__first, __last, __unary_pred); + while (__first != __last) + { + typename iterator_traits<_ForwardIterator>::difference_type + __n = __count; + _ForwardIterator __i = __first; + ++__i; + while (__i != __last && __n != 1 && __unary_pred(__i)) + { + ++__i; + --__n; + } + if (__n == 1) + return __first; + if (__i == __last) + return __last; + __first = std::__find_if(++__i, __last, __unary_pred); + } + return __last; + } + + /** + * This is an helper function for search_n overloaded for random access + * iterators. + */ + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIter + __search_n_aux(_RandomAccessIter __first, _RandomAccessIter __last, + _Integer __count, _UnaryPredicate __unary_pred, + std::random_access_iterator_tag) + { + typedef typename std::iterator_traits<_RandomAccessIter>::difference_type + _DistanceType; + + _DistanceType __tailSize = __last - __first; + _DistanceType __remainder = __count; + + while (__remainder <= __tailSize) // the main loop... + { + __first += __remainder; + __tailSize -= __remainder; + // __first here is always pointing to one past the last element of + // next possible match. + _RandomAccessIter __backTrack = __first; + while (__unary_pred(--__backTrack)) + { + if (--__remainder == 0) + return (__first - __count); // Success + } + __remainder = __count + 1 - (__first - __backTrack); + } + return __last; // Failure + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, + _UnaryPredicate __unary_pred) + { + if (__count <= 0) + return __first; + + if (__count == 1) + return std::__find_if(__first, __last, __unary_pred); + + return std::__search_n_aux(__first, __last, __count, __unary_pred, + std::__iterator_category(__first)); + } + + // find_end for forward iterators. + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator1 + __find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + forward_iterator_tag, forward_iterator_tag, + _BinaryPredicate __comp) + { + if (__first2 == __last2) + return __last1; + + _ForwardIterator1 __result = __last1; + while (1) + { + _ForwardIterator1 __new_result + = std::__search(__first1, __last1, __first2, __last2, __comp); + if (__new_result == __last1) + return __result; + else + { + __result = __new_result; + __first1 = __new_result; + ++__first1; + } + } + } + + // find_end for bidirectional iterators (much faster). + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator1 + __find_end(_BidirectionalIterator1 __first1, + _BidirectionalIterator1 __last1, + _BidirectionalIterator2 __first2, + _BidirectionalIterator2 __last2, + bidirectional_iterator_tag, bidirectional_iterator_tag, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator1>) + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator2>) + + typedef reverse_iterator<_BidirectionalIterator1> _RevIterator1; + typedef reverse_iterator<_BidirectionalIterator2> _RevIterator2; + + _RevIterator1 __rlast1(__first1); + _RevIterator2 __rlast2(__first2); + _RevIterator1 __rresult = std::__search(_RevIterator1(__last1), __rlast1, + _RevIterator2(__last2), __rlast2, + __comp); + + if (__rresult == __rlast1) + return __last1; + else + { + _BidirectionalIterator1 __result = __rresult.base(); + std::advance(__result, -std::distance(__first2, __last2)); + return __result; + } + } + + /** + * @brief Find last matching subsequence in a sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of sequence to match. + * @param __last2 End of sequence to match. + * @return The last iterator @c i in the range + * @p [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == + * @p *(__first2+N) for each @c N in the range @p + * [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) and returns an iterator to the __first + * element of the sub-sequence, or @p __last1 if the sub-sequence + * is not found. The sub-sequence will be the last such + * subsequence contained in [__first1,__last1). + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. This means that the returned + * iterator @c i will be in the range @p + * [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__find_end(__first1, __last1, __first2, __last2, + std::__iterator_category(__first1), + std::__iterator_category(__first2), + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Find last matching subsequence in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of sequence to match. + * @param __last2 End of sequence to match. + * @param __comp The predicate to use. + * @return The last iterator @c i in the range @p + * [__first1,__last1-(__last2-__first2)) such that @c + * predicate(*(i+N), @p (__first2+N)) is true for each @c N in the + * range @p [0,__last2-__first2), or @p __last1 if no such iterator + * exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) using comp as a predicate and returns an + * iterator to the first element of the sub-sequence, or @p __last1 + * if the sub-sequence is not found. The sub-sequence will be the + * last such subsequence contained in [__first,__last1). + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. This means that the returned + * iterator @c i will be in the range @p + * [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + find_end(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__find_end(__first1, __last1, __first2, __last2, + std::__iterator_category(__first1), + std::__iterator_category(__first2), + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cplusplus >= 201103L + /** + * @brief Checks that a predicate is true for all the elements + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if @p __pred is true for each element in the range + * @p [__first,__last), and false otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + all_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return __last == std::find_if_not(__first, __last, __pred); } + + /** + * @brief Checks that a predicate is false for all the elements + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if @p __pred is false for each element in the range + * @p [__first,__last), and false otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + none_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return __last == _GLIBCXX_STD_A::find_if(__first, __last, __pred); } + + /** + * @brief Checks that a predicate is true for at least one element + * of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the check is true, false otherwise. + * + * Returns true if an element exists in the range @p + * [__first,__last) such that @p __pred is true, and false + * otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + any_of(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { return !std::none_of(__first, __last, __pred); } + + /** + * @brief Find the first element in a sequence for which a + * predicate is false. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @p __pred(*i) is false, or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + find_if_not(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + return std::__find_if_not(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Checks whether the sequence is partitioned. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return True if the range @p [__first,__last) is partioned by @p __pred, + * i.e. if all elements that satisfy @p __pred appear before those that + * do not. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_partitioned(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + __first = std::find_if_not(__first, __last, __pred); + if (__first == __last) + return true; + ++__first; + return std::none_of(__first, __last, __pred); + } + + /** + * @brief Find the partition point of a partitioned range. + * @ingroup mutating_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __pred A predicate. + * @return An iterator @p mid such that @p all_of(__first, mid, __pred) + * and @p none_of(mid, __last, __pred) are both true. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + partition_point(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + + // A specific debug-mode test will be necessary... + __glibcxx_requires_valid_range(__first, __last); + + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__pred(*__middle)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } +#endif + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __remove_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + for (; __first != __last; ++__first) + if (!__pred(__first)) + { + *__result = *__first; + ++__result; + } + return __result; + } + + /** + * @brief Copy a sequence, removing elements of a given value. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __value The value to be removed. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) not equal + * to @p __value to the range beginning at @p __result. + * remove_copy() is stable, so the relative order of elements that + * are copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + remove_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Copy a sequence, removing elements for which a predicate is true. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns false to the range beginning at @p __result. + * + * remove_copy_if() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + remove_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + +#if __cplusplus >= 201103L + /** + * @brief Copy the elements of a sequence for which a predicate is true. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns true to the range beginning at @p __result. + * + * copy_if() is stable, so the relative order of elements that are + * copied is unchanged. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + { + *__result = *__first; + ++__result; + } + return __result; + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __copy_n_a(_InputIterator __first, _Size __n, _OutputIterator __result) + { + if (__n > 0) + { + while (true) + { + *__result = *__first; + ++__result; + if (--__n > 0) + ++__first; + else + break; + } + } + return __result; + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __copy_n(_InputIterator __first, _Size __n, + _OutputIterator __result, input_iterator_tag) + { + return std::__niter_wrap(__result, + __copy_n_a(__first, __n, + std::__niter_base(__result))); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __copy_n(_RandomAccessIterator __first, _Size __n, + _OutputIterator __result, random_access_iterator_tag) + { return std::copy(__first, __first + __n, __result); } + + /** + * @brief Copies the range [first,first+n) into [result,result+n). + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __n The number of elements to copy. + * @param __result An output iterator. + * @return result+n. + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + copy_n(_InputIterator __first, _Size __n, _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_can_increment(__first, __n); + __glibcxx_requires_can_increment(__result, __n); + + return std::__copy_n(__first, __n, __result, + std::__iterator_category(__first)); + } + + /** + * @brief Copy the elements of a sequence to separate output sequences + * depending on the truth value of a predicate. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __out_true An output iterator. + * @param __out_false An output iterator. + * @param __pred A predicate. + * @return A pair designating the ends of the resulting sequences. + * + * Copies each element in the range @p [__first,__last) for which + * @p __pred returns true to the range beginning at @p out_true + * and each element for which @p __pred returns false to @p __out_false. + */ + template + _GLIBCXX20_CONSTEXPR + pair<_OutputIterator1, _OutputIterator2> + partition_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator1 __out_true, _OutputIterator2 __out_false, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator1, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator2, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + { + *__out_true = *__first; + ++__out_true; + } + else + { + *__out_false = *__first; + ++__out_false; + } + + return pair<_OutputIterator1, _OutputIterator2>(__out_true, __out_false); + } +#endif // C++11 + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __remove_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + __first = std::__find_if(__first, __last, __pred); + if (__first == __last) + return __first; + _ForwardIterator __result = __first; + ++__first; + for (; __first != __last; ++__first) + if (!__pred(__first)) + { + *__result = _GLIBCXX_MOVE(*__first); + ++__result; + } + return __result; + } + + /** + * @brief Remove elements from a sequence. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __value The value to be removed. + * @return An iterator designating the end of the resulting sequence. + * + * All elements equal to @p __value are removed from the range + * @p [__first,__last). + * + * remove() is stable, so the relative order of elements that are + * not removed is unchanged. + * + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + remove(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Remove elements from a sequence using a predicate. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate. + * @return An iterator designating the end of the resulting sequence. + * + * All elements for which @p __pred returns true are removed from the range + * @p [__first,__last). + * + * remove_if() is stable, so the relative order of elements that are + * not removed is unchanged. + * + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + remove_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__remove_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __adjacent_find(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + if (__first == __last) + return __last; + _ForwardIterator __next = __first; + while (++__next != __last) + { + if (__binary_pred(__first, __next)) + return __first; + __first = __next; + } + return __last; + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __unique(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // Skip the beginning, if already unique. + __first = std::__adjacent_find(__first, __last, __binary_pred); + if (__first == __last) + return __last; + + // Do the real copy work. + _ForwardIterator __dest = __first; + ++__first; + while (++__first != __last) + if (!__binary_pred(__dest, __first)) + *++__dest = _GLIBCXX_MOVE(*__first); + return ++__dest; + } + + /** + * @brief Remove consecutive duplicate values from a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Removes all but the first element from each group of consecutive + * values that compare equal. + * unique() is stable, so the relative order of elements that are + * not removed is unchanged. + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + unique(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__unique(__first, __last, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Remove consecutive values from a sequence using a predicate. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __binary_pred A binary predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Removes all but the first element from each group of consecutive + * values for which @p __binary_pred returns true. + * unique() is stable, so the relative order of elements that are + * not removed is unchanged. + * Elements between the end of the resulting sequence and @p __last + * are still present, but their value is unspecified. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + unique(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__unique(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for forward iterators and output iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __unique_copy(_ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __result, _BinaryPredicate __binary_pred, + forward_iterator_tag, output_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + + _ForwardIterator __next = __first; + *__result = *__first; + while (++__next != __last) + if (!__binary_pred(__first, __next)) + { + __first = __next; + *++__result = *__first; + } + return ++__result; + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for input iterators and output iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryPredicate __binary_pred, + input_iterator_tag, output_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_InputIterator>::value_type>) + + typename iterator_traits<_InputIterator>::value_type __value = *__first; + __decltype(__gnu_cxx::__ops::__iter_comp_val(__binary_pred)) + __rebound_pred + = __gnu_cxx::__ops::__iter_comp_val(__binary_pred); + *__result = __value; + while (++__first != __last) + if (!__rebound_pred(__first, __value)) + { + __value = *__first; + *++__result = __value; + } + return ++__result; + } + + /** + * This is an uglified + * unique_copy(_InputIterator, _InputIterator, _OutputIterator, + * _BinaryPredicate) + * overloaded for input iterators and forward iterator as result. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __unique_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _BinaryPredicate __binary_pred, + input_iterator_tag, forward_iterator_tag) + { + // concept requirements -- iterators already checked + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_InputIterator>::value_type>) + *__result = *__first; + while (++__first != __last) + if (!__binary_pred(__result, __first)) + *++__result = *__first; + return ++__result; + } + + /** + * This is an uglified reverse(_BidirectionalIterator, + * _BidirectionalIterator) + * overloaded for bidirectional iterators. + */ + template + _GLIBCXX20_CONSTEXPR + void + __reverse(_BidirectionalIterator __first, _BidirectionalIterator __last, + bidirectional_iterator_tag) + { + while (true) + if (__first == __last || __first == --__last) + return; + else + { + std::iter_swap(__first, __last); + ++__first; + } + } + + /** + * This is an uglified reverse(_BidirectionalIterator, + * _BidirectionalIterator) + * overloaded for random access iterators. + */ + template + _GLIBCXX20_CONSTEXPR + void + __reverse(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + if (__first == __last) + return; + --__last; + while (__first < __last) + { + std::iter_swap(__first, __last); + ++__first; + --__last; + } + } + + /** + * @brief Reverse a sequence. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @return reverse() returns no value. + * + * Reverses the order of the elements in the range @p [__first,__last), + * so that the first element becomes the last etc. + * For every @c i such that @p 0<=i<=(__last-__first)/2), @p reverse() + * swaps @p *(__first+i) and @p *(__last-(i+1)) + */ + template + _GLIBCXX20_CONSTEXPR + inline void + reverse(_BidirectionalIterator __first, _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_requires_valid_range(__first, __last); + std::__reverse(__first, __last, std::__iterator_category(__first)); + } + + /** + * @brief Copy a sequence, reversing its elements. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies the elements in the range @p [__first,__last) to the + * range @p [__result,__result+(__last-__first)) such that the + * order of the elements is reversed. For every @c i such that @p + * 0<=i<=(__last-__first), @p reverse_copy() performs the + * assignment @p *(__result+(__last-__first)-1-i) = *(__first+i). + * The ranges @p [__first,__last) and @p + * [__result,__result+(__last-__first)) must not overlap. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + reverse_copy(_BidirectionalIterator __first, _BidirectionalIterator __last, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + while (__first != __last) + { + --__last; + *__result = *__last; + ++__result; + } + return __result; + } + + /** + * This is a helper function for the rotate algorithm specialized on RAIs. + * It returns the greatest common divisor of two integer values. + */ + template + _GLIBCXX20_CONSTEXPR + _EuclideanRingElement + __gcd(_EuclideanRingElement __m, _EuclideanRingElement __n) + { + while (__n != 0) + { + _EuclideanRingElement __t = __m % __n; + __m = __n; + __n = __t; + } + return __m; + } + + inline namespace _V2 + { + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __rotate(_ForwardIterator __first, + _ForwardIterator __middle, + _ForwardIterator __last, + forward_iterator_tag) + { + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + _ForwardIterator __first2 = __middle; + do + { + std::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + } + while (__first2 != __last); + + _ForwardIterator __ret = __first; + + __first2 = __middle; + + while (__first2 != __last) + { + std::iter_swap(__first, __first2); + ++__first; + ++__first2; + if (__first == __middle) + __middle = __first2; + else if (__first2 == __last) + __first2 = __middle; + } + return __ret; + } + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator + __rotate(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + bidirectional_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + std::__reverse(__first, __middle, bidirectional_iterator_tag()); + std::__reverse(__middle, __last, bidirectional_iterator_tag()); + + while (__first != __middle && __middle != __last) + { + std::iter_swap(__first, --__last); + ++__first; + } + + if (__first == __middle) + { + std::__reverse(__middle, __last, bidirectional_iterator_tag()); + return __last; + } + else + { + std::__reverse(__first, __middle, bidirectional_iterator_tag()); + return __first; + } + } + + /// This is a helper function for the rotate algorithm. + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __rotate(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + + if (__first == __middle) + return __last; + else if (__last == __middle) + return __first; + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _Distance; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + + _Distance __n = __last - __first; + _Distance __k = __middle - __first; + + if (__k == __n - __k) + { + std::swap_ranges(__first, __middle, __middle); + return __middle; + } + + _RandomAccessIterator __p = __first; + _RandomAccessIterator __ret = __first + (__last - __middle); + + for (;;) + { + if (__k < __n - __k) + { + if (__is_pod(_ValueType) && __k == 1) + { + _ValueType __t = _GLIBCXX_MOVE(*__p); + _GLIBCXX_MOVE3(__p + 1, __p + __n, __p); + *(__p + __n - 1) = _GLIBCXX_MOVE(__t); + return __ret; + } + _RandomAccessIterator __q = __p + __k; + for (_Distance __i = 0; __i < __n - __k; ++ __i) + { + std::iter_swap(__p, __q); + ++__p; + ++__q; + } + __n %= __k; + if (__n == 0) + return __ret; + std::swap(__n, __k); + __k = __n - __k; + } + else + { + __k = __n - __k; + if (__is_pod(_ValueType) && __k == 1) + { + _ValueType __t = _GLIBCXX_MOVE(*(__p + __n - 1)); + _GLIBCXX_MOVE_BACKWARD3(__p, __p + __n - 1, __p + __n); + *__p = _GLIBCXX_MOVE(__t); + return __ret; + } + _RandomAccessIterator __q = __p + __n; + __p = __q - __k; + for (_Distance __i = 0; __i < __n - __k; ++ __i) + { + --__p; + --__q; + std::iter_swap(__p, __q); + } + __n %= __k; + if (__n == 0) + return __ret; + std::swap(__n, __k); + } + } + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 488. rotate throws away useful information + /** + * @brief Rotate the elements of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __middle A forward iterator. + * @param __last A forward iterator. + * @return first + (last - middle). + * + * Rotates the elements of the range @p [__first,__last) by + * @p (__middle - __first) positions so that the element at @p __middle + * is moved to @p __first, the element at @p __middle+1 is moved to + * @p __first+1 and so on for each element in the range + * @p [__first,__last). + * + * This effectively swaps the ranges @p [__first,__middle) and + * @p [__middle,__last). + * + * Performs + * @p *(__first+(n+(__last-__middle))%(__last-__first))=*(__first+n) + * for each @p n in the range @p [0,__last-__first). + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + rotate(_ForwardIterator __first, _ForwardIterator __middle, + _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + + return std::__rotate(__first, __middle, __last, + std::__iterator_category(__first)); + } + + } // namespace _V2 + + /** + * @brief Copy a sequence, rotating its elements. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __middle A forward iterator. + * @param __last A forward iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies the elements of the range @p [__first,__last) to the + * range beginning at @result, rotating the copied elements by + * @p (__middle-__first) positions so that the element at @p __middle + * is moved to @p __result, the element at @p __middle+1 is moved + * to @p __result+1 and so on for each element in the range @p + * [__first,__last). + * + * Performs + * @p *(__result+(n+(__last-__middle))%(__last-__first))=*(__first+n) + * for each @p n in the range @p [0,__last-__first). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + rotate_copy(_ForwardIterator __first, _ForwardIterator __middle, + _ForwardIterator __last, _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + + return std::copy(__first, __middle, + std::copy(__middle, __last, __result)); + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, forward_iterator_tag) + { + if (__first == __last) + return __first; + + while (__pred(*__first)) + if (++__first == __last) + return __first; + + _ForwardIterator __next = __first; + + while (++__next != __last) + if (__pred(*__next)) + { + std::iter_swap(__first, __next); + ++__first; + } + + return __first; + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _BidirectionalIterator + __partition(_BidirectionalIterator __first, _BidirectionalIterator __last, + _Predicate __pred, bidirectional_iterator_tag) + { + while (true) + { + while (true) + if (__first == __last) + return __first; + else if (__pred(*__first)) + ++__first; + else + break; + --__last; + while (true) + if (__first == __last) + return __first; + else if (!bool(__pred(*__last))) + --__last; + else + break; + std::iter_swap(__first, __last); + ++__first; + } + } + + // partition + + /// This is a helper function... + /// Requires __first != __last and !__pred(__first) + /// and __len == distance(__first, __last). + /// + /// !__pred(__first) allows us to guarantee that we don't + /// move-assign an element onto itself. + template + _ForwardIterator + __stable_partition_adaptive(_ForwardIterator __first, + _ForwardIterator __last, + _Predicate __pred, _Distance __len, + _Pointer __buffer, + _Distance __buffer_size) + { + if (__len == 1) + return __first; + + if (__len <= __buffer_size) + { + _ForwardIterator __result1 = __first; + _Pointer __result2 = __buffer; + + // The precondition guarantees that !__pred(__first), so + // move that element to the buffer before starting the loop. + // This ensures that we only call __pred once per element. + *__result2 = _GLIBCXX_MOVE(*__first); + ++__result2; + ++__first; + for (; __first != __last; ++__first) + if (__pred(__first)) + { + *__result1 = _GLIBCXX_MOVE(*__first); + ++__result1; + } + else + { + *__result2 = _GLIBCXX_MOVE(*__first); + ++__result2; + } + + _GLIBCXX_MOVE3(__buffer, __result2, __result1); + return __result1; + } + + _ForwardIterator __middle = __first; + std::advance(__middle, __len / 2); + _ForwardIterator __left_split = + std::__stable_partition_adaptive(__first, __middle, __pred, + __len / 2, __buffer, + __buffer_size); + + // Advance past true-predicate values to satisfy this + // function's preconditions. + _Distance __right_len = __len - __len / 2; + _ForwardIterator __right_split = + std::__find_if_not_n(__middle, __right_len, __pred); + + if (__right_len) + __right_split = + std::__stable_partition_adaptive(__right_split, __last, __pred, + __right_len, + __buffer, __buffer_size); + + return std::rotate(__left_split, __middle, __right_split); + } + + template + _ForwardIterator + __stable_partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + __first = std::__find_if_not(__first, __last, __pred); + + if (__first == __last) + return __first; + + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _Temporary_buffer<_ForwardIterator, _ValueType> + __buf(__first, std::distance(__first, __last)); + return + std::__stable_partition_adaptive(__first, __last, __pred, + _DistanceType(__buf.requested_size()), + __buf.begin(), + _DistanceType(__buf.size())); + } + + /** + * @brief Move elements for which a predicate is true to the beginning + * of a sequence, preserving relative ordering. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate functor. + * @return An iterator @p middle such that @p __pred(i) is true for each + * iterator @p i in the range @p [first,middle) and false for each @p i + * in the range @p [middle,last). + * + * Performs the same function as @p partition() with the additional + * guarantee that the relative ordering of elements in each group is + * preserved, so any two elements @p x and @p y in the range + * @p [__first,__last) such that @p __pred(x)==__pred(y) will have the same + * relative ordering after calling @p stable_partition(). + */ + template + inline _ForwardIterator + stable_partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__stable_partition(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /// This is a helper function for the sort routines. + template + _GLIBCXX20_CONSTEXPR + void + __heap_select(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, _Compare __comp) + { + std::__make_heap(__first, __middle, __comp); + for (_RandomAccessIterator __i = __middle; __i < __last; ++__i) + if (__comp(__i, __first)) + std::__pop_heap(__first, __middle, __i, __comp); + } + + // partial_sort + + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last, + _Compare __comp) + { + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef iterator_traits<_RandomAccessIterator> _RItTraits; + typedef typename _RItTraits::difference_type _DistanceType; + + if (__result_first == __result_last) + return __result_last; + _RandomAccessIterator __result_real_last = __result_first; + while (__first != __last && __result_real_last != __result_last) + { + *__result_real_last = *__first; + ++__result_real_last; + ++__first; + } + + std::__make_heap(__result_first, __result_real_last, __comp); + while (__first != __last) + { + if (__comp(__first, __result_first)) + std::__adjust_heap(__result_first, _DistanceType(0), + _DistanceType(__result_real_last + - __result_first), + _InputValueType(*__first), __comp); + ++__first; + } + std::__sort_heap(__result_first, __result_real_last, __comp); + return __result_real_last; + } + + /** + * @brief Copy the smallest elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __result_first A random-access iterator. + * @param __result_last Another random-access iterator. + * @return An iterator indicating the end of the resulting sequence. + * + * Copies and sorts the smallest N values from the range @p [__first,__last) + * to the range beginning at @p __result_first, where the number of + * elements to be copied, @p N, is the smaller of @p (__last-__first) and + * @p (__result_last-__result_first). + * After the sort if @e i and @e j are iterators in the range + * @p [__result_first,__result_first+N) such that i precedes j then + * *j<*i is false. + * The value returned is @p __result_first+N. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _OutputValueType; +#endif + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_LessThanOpConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_LessThanComparableConcept<_OutputValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_valid_range(__result_first, __result_last); + + return std::__partial_sort_copy(__first, __last, + __result_first, __result_last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Copy the smallest elements of a sequence using a predicate for + * comparison. + * @ingroup sorting_algorithms + * @param __first An input iterator. + * @param __last Another input iterator. + * @param __result_first A random-access iterator. + * @param __result_last Another random-access iterator. + * @param __comp A comparison functor. + * @return An iterator indicating the end of the resulting sequence. + * + * Copies and sorts the smallest N values from the range @p [__first,__last) + * to the range beginning at @p result_first, where the number of + * elements to be copied, @p N, is the smaller of @p (__last-__first) and + * @p (__result_last-__result_first). + * After the sort if @e i and @e j are iterators in the range + * @p [__result_first,__result_first+N) such that i precedes j then + * @p __comp(*j,*i) is false. + * The value returned is @p __result_first+N. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + partial_sort_copy(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __result_first, + _RandomAccessIterator __result_last, + _Compare __comp) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + typedef typename iterator_traits<_InputIterator>::value_type + _InputValueType; + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _OutputValueType; +#endif + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_InputValueType, + _OutputValueType>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _InputValueType, _OutputValueType>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _OutputValueType, _OutputValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_valid_range(__result_first, __result_last); + + return std::__partial_sort_copy(__first, __last, + __result_first, __result_last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __unguarded_linear_insert(_RandomAccessIterator __last, + _Compare __comp) + { + typename iterator_traits<_RandomAccessIterator>::value_type + __val = _GLIBCXX_MOVE(*__last); + _RandomAccessIterator __next = __last; + --__next; + while (__comp(__val, __next)) + { + *__last = _GLIBCXX_MOVE(*__next); + __last = __next; + --__next; + } + *__last = _GLIBCXX_MOVE(__val); + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__first == __last) return; + + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + if (__comp(__i, __first)) + { + typename iterator_traits<_RandomAccessIterator>::value_type + __val = _GLIBCXX_MOVE(*__i); + _GLIBCXX_MOVE_BACKWARD3(__first, __i, __i + 1); + *__first = _GLIBCXX_MOVE(__val); + } + else + std::__unguarded_linear_insert(__i, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + inline void + __unguarded_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + for (_RandomAccessIterator __i = __first; __i != __last; ++__i) + std::__unguarded_linear_insert(__i, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + /** + * @doctodo + * This controls some aspect of the sort routines. + */ + enum { _S_threshold = 16 }; + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __final_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__last - __first > int(_S_threshold)) + { + std::__insertion_sort(__first, __first + int(_S_threshold), __comp); + std::__unguarded_insertion_sort(__first + int(_S_threshold), __last, + __comp); + } + else + std::__insertion_sort(__first, __last, __comp); + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __unguarded_partition(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _RandomAccessIterator __pivot, _Compare __comp) + { + while (true) + { + while (__comp(__first, __pivot)) + ++__first; + --__last; + while (__comp(__pivot, __last)) + --__last; + if (!(__first < __last)) + return __first; + std::iter_swap(__first, __last); + ++__first; + } + } + + /// This is a helper function... + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + __unguarded_partition_pivot(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + _RandomAccessIterator __mid = __first + (__last - __first) / 2; + std::__move_median_to_first(__first, __first + 1, __mid, __last - 1, + __comp); + return std::__unguarded_partition(__first + 1, __last, __first, __comp); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) + { + std::__heap_select(__first, __middle, __last, __comp); + std::__sort_heap(__first, __middle, __comp); + } + + /// This is a helper function for the sort routine. + template + _GLIBCXX20_CONSTEXPR + void + __introsort_loop(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Size __depth_limit, _Compare __comp) + { + while (__last - __first > int(_S_threshold)) + { + if (__depth_limit == 0) + { + std::__partial_sort(__first, __last, __last, __comp); + return; + } + --__depth_limit; + _RandomAccessIterator __cut = + std::__unguarded_partition_pivot(__first, __last, __comp); + std::__introsort_loop(__cut, __last, __depth_limit, __comp); + __last = __cut; + } + } + + // sort + + template + _GLIBCXX20_CONSTEXPR + inline void + __sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + if (__first != __last) + { + std::__introsort_loop(__first, __last, + std::__lg(__last - __first) * 2, + __comp); + std::__final_insertion_sort(__first, __last, __comp); + } + } + + template + _GLIBCXX20_CONSTEXPR + void + __introselect(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last, _Size __depth_limit, + _Compare __comp) + { + while (__last - __first > 3) + { + if (__depth_limit == 0) + { + std::__heap_select(__first, __nth + 1, __last, __comp); + // Place the nth largest element in its final position. + std::iter_swap(__first, __nth); + return; + } + --__depth_limit; + _RandomAccessIterator __cut = + std::__unguarded_partition_pivot(__first, __last, __comp); + if (__cut <= __nth) + __first = __cut; + else + __last = __cut; + } + std::__insertion_sort(__first, __last, __comp); + } + + // nth_element + + // lower_bound moved to stl_algobase.h + + /** + * @brief Finds the first position in which @p __val could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An iterator pointing to the first element not less + * than @p __val, or end() if every element is less + * than @p __val. + * @ingroup binary_search_algorithms + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + + return std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp(__val, __middle)) + __len = __half; + else + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + } + return __first; + } + + /** + * @brief Finds the last position in which @p __val could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An iterator pointing to the first element greater than @p __val, + * or end() if no elements are greater than @p __val. + * @ingroup binary_search_algorithms + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + return std::__upper_bound(__first, __last, __val, + __gnu_cxx::__ops::__val_less_iter()); + } + + /** + * @brief Finds the last position in which @p __val could be inserted + * without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An iterator pointing to the first element greater than @p __val, + * or end() if no elements are greater than @p __val. + * @ingroup binary_search_algorithms + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + upper_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + return std::__upper_bound(__first, __last, __val, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + pair<_ForwardIterator, _ForwardIterator> + __equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, + _CompareItTp __comp_it_val, _CompareTpIt __comp_val_it) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp_it_val(__middle, __val)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else if (__comp_val_it(__val, __middle)) + __len = __half; + else + { + _ForwardIterator __left + = std::__lower_bound(__first, __middle, __val, __comp_it_val); + std::advance(__first, __len); + _ForwardIterator __right + = std::__upper_bound(++__middle, __first, __val, __comp_val_it); + return pair<_ForwardIterator, _ForwardIterator>(__left, __right); + } + } + return pair<_ForwardIterator, _ForwardIterator>(__first, __first); + } + + /** + * @brief Finds the largest subrange in which @p __val could be inserted + * at any place in it without changing the ordering. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An pair of iterators defining the subrange. + * @ingroup binary_search_algorithms + * + * This is equivalent to + * @code + * std::make_pair(lower_bound(__first, __last, __val), + * upper_bound(__first, __last, __val)) + * @endcode + * but does not actually call those functions. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + return std::__equal_range(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val(), + __gnu_cxx::__ops::__val_less_iter()); + } + + /** + * @brief Finds the largest subrange in which @p __val could be inserted + * at any place in it without changing the ordering. + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return An pair of iterators defining the subrange. + * @ingroup binary_search_algorithms + * + * This is equivalent to + * @code + * std::make_pair(lower_bound(__first, __last, __val, __comp), + * upper_bound(__first, __last, __val, __comp)) + * @endcode + * but does not actually call those functions. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + equal_range(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + return std::__equal_range(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp), + __gnu_cxx::__ops::__val_comp_iter(__comp)); + } + + /** + * @brief Determines whether an element exists in a range. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return True if @p __val (or its equivalent) is in [@p + * __first,@p __last ]. + * + * Note that this does not actually return an iterator to @p __val. For + * that, use std::find or a container's specialized find member functions. + */ + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + __glibcxx_requires_partitioned_upper(__first, __last, __val); + + _ForwardIterator __i + = std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val()); + return __i != __last && !(__val < *__i); + } + + /** + * @brief Determines whether an element exists in a range. + * @ingroup binary_search_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @param __comp A functor to use for comparisons. + * @return True if @p __val (or its equivalent) is in @p [__first,__last]. + * + * Note that this does not actually return an iterator to @p __val. For + * that, use std::find or a container's specialized find member functions. + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + bool + binary_search(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + _Tp, typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_partitioned_lower_pred(__first, __last, + __val, __comp); + __glibcxx_requires_partitioned_upper_pred(__first, __last, + __val, __comp); + + _ForwardIterator __i + = std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + return __i != __last && !bool(__comp(__val, *__i)); + } + + // merge + + /// This is a helper function for the __merge_adaptive routines. + template + void + __move_merge_adaptive(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + if (__first1 != __last1) + _GLIBCXX_MOVE3(__first1, __last1, __result); + } + + /// This is a helper function for the __merge_adaptive routines. + template + void + __move_merge_adaptive_backward(_BidirectionalIterator1 __first1, + _BidirectionalIterator1 __last1, + _BidirectionalIterator2 __first2, + _BidirectionalIterator2 __last2, + _BidirectionalIterator3 __result, + _Compare __comp) + { + if (__first1 == __last1) + { + _GLIBCXX_MOVE_BACKWARD3(__first2, __last2, __result); + return; + } + else if (__first2 == __last2) + return; + + --__last1; + --__last2; + while (true) + { + if (__comp(__last2, __last1)) + { + *--__result = _GLIBCXX_MOVE(*__last1); + if (__first1 == __last1) + { + _GLIBCXX_MOVE_BACKWARD3(__first2, ++__last2, __result); + return; + } + --__last1; + } + else + { + *--__result = _GLIBCXX_MOVE(*__last2); + if (__first2 == __last2) + return; + --__last2; + } + } + } + + /// This is a helper function for the merge routines. + template + _BidirectionalIterator1 + __rotate_adaptive(_BidirectionalIterator1 __first, + _BidirectionalIterator1 __middle, + _BidirectionalIterator1 __last, + _Distance __len1, _Distance __len2, + _BidirectionalIterator2 __buffer, + _Distance __buffer_size) + { + _BidirectionalIterator2 __buffer_end; + if (__len1 > __len2 && __len2 <= __buffer_size) + { + if (__len2) + { + __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + _GLIBCXX_MOVE_BACKWARD3(__first, __middle, __last); + return _GLIBCXX_MOVE3(__buffer, __buffer_end, __first); + } + else + return __first; + } + else if (__len1 <= __buffer_size) + { + if (__len1) + { + __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + _GLIBCXX_MOVE3(__middle, __last, __first); + return _GLIBCXX_MOVE_BACKWARD3(__buffer, __buffer_end, __last); + } + else + return __last; + } + else + return std::rotate(__first, __middle, __last); + } + + /// This is a helper function for the merge routines. + template + void + __merge_adaptive(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Distance __len1, _Distance __len2, + _Pointer __buffer, _Distance __buffer_size, + _Compare __comp) + { + if (__len1 <= __len2 && __len1 <= __buffer_size) + { + _Pointer __buffer_end = _GLIBCXX_MOVE3(__first, __middle, __buffer); + std::__move_merge_adaptive(__buffer, __buffer_end, __middle, __last, + __first, __comp); + } + else if (__len2 <= __buffer_size) + { + _Pointer __buffer_end = _GLIBCXX_MOVE3(__middle, __last, __buffer); + std::__move_merge_adaptive_backward(__first, __middle, __buffer, + __buffer_end, __last, __comp); + } + else + { + _BidirectionalIterator __first_cut = __first; + _BidirectionalIterator __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) + { + __len11 = __len1 / 2; + std::advance(__first_cut, __len11); + __second_cut + = std::__lower_bound(__middle, __last, *__first_cut, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + __len22 = std::distance(__middle, __second_cut); + } + else + { + __len22 = __len2 / 2; + std::advance(__second_cut, __len22); + __first_cut + = std::__upper_bound(__first, __middle, *__second_cut, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + __len11 = std::distance(__first, __first_cut); + } + + _BidirectionalIterator __new_middle + = std::__rotate_adaptive(__first_cut, __middle, __second_cut, + __len1 - __len11, __len22, __buffer, + __buffer_size); + std::__merge_adaptive(__first, __first_cut, __new_middle, __len11, + __len22, __buffer, __buffer_size, __comp); + std::__merge_adaptive(__new_middle, __second_cut, __last, + __len1 - __len11, + __len2 - __len22, __buffer, + __buffer_size, __comp); + } + } + + /// This is a helper function for the merge routines. + template + void + __merge_without_buffer(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Distance __len1, _Distance __len2, + _Compare __comp) + { + if (__len1 == 0 || __len2 == 0) + return; + + if (__len1 + __len2 == 2) + { + if (__comp(__middle, __first)) + std::iter_swap(__first, __middle); + return; + } + + _BidirectionalIterator __first_cut = __first; + _BidirectionalIterator __second_cut = __middle; + _Distance __len11 = 0; + _Distance __len22 = 0; + if (__len1 > __len2) + { + __len11 = __len1 / 2; + std::advance(__first_cut, __len11); + __second_cut + = std::__lower_bound(__middle, __last, *__first_cut, + __gnu_cxx::__ops::__iter_comp_val(__comp)); + __len22 = std::distance(__middle, __second_cut); + } + else + { + __len22 = __len2 / 2; + std::advance(__second_cut, __len22); + __first_cut + = std::__upper_bound(__first, __middle, *__second_cut, + __gnu_cxx::__ops::__val_comp_iter(__comp)); + __len11 = std::distance(__first, __first_cut); + } + + _BidirectionalIterator __new_middle + = std::rotate(__first_cut, __middle, __second_cut); + std::__merge_without_buffer(__first, __first_cut, __new_middle, + __len11, __len22, __comp); + std::__merge_without_buffer(__new_middle, __second_cut, __last, + __len1 - __len11, __len2 - __len22, __comp); + } + + template + void + __inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_BidirectionalIterator>::value_type + _ValueType; + typedef typename iterator_traits<_BidirectionalIterator>::difference_type + _DistanceType; + + if (__first == __middle || __middle == __last) + return; + + const _DistanceType __len1 = std::distance(__first, __middle); + const _DistanceType __len2 = std::distance(__middle, __last); + + typedef _Temporary_buffer<_BidirectionalIterator, _ValueType> _TmpBuf; + _TmpBuf __buf(__first, __len1 + __len2); + + if (__buf.begin() == 0) + std::__merge_without_buffer + (__first, __middle, __last, __len1, __len2, __comp); + else + std::__merge_adaptive + (__first, __middle, __last, __len1, __len2, __buf.begin(), + _DistanceType(__buf.size()), __comp); + } + + /** + * @brief Merges two sorted ranges in place. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Merges two sorted and consecutive ranges, [__first,__middle) and + * [__middle,__last), and puts the result in [__first,__last). The + * output will be sorted. The sort is @e stable, that is, for + * equivalent elements in the two ranges, elements from the first + * range will always come before elements from the second. + * + * If enough additional memory is available, this takes (__last-__first)-1 + * comparisons. Otherwise an NlogN algorithm is used, where N is + * distance(__first,__last). + */ + template + inline void + inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_sorted(__first, __middle); + __glibcxx_requires_sorted(__middle, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__inplace_merge(__first, __middle, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Merges two sorted ranges in place. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @param __comp A functor to use for comparisons. + * @return Nothing. + * + * Merges two sorted and consecutive ranges, [__first,__middle) and + * [middle,last), and puts the result in [__first,__last). The output will + * be sorted. The sort is @e stable, that is, for equivalent + * elements in the two ranges, elements from the first range will always + * come before elements from the second. + * + * If enough additional memory is available, this takes (__last-__first)-1 + * comparisons. Otherwise an NlogN algorithm is used, where N is + * distance(__first,__last). + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + inline void + inplace_merge(_BidirectionalIterator __first, + _BidirectionalIterator __middle, + _BidirectionalIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_sorted_pred(__first, __middle, __comp); + __glibcxx_requires_sorted_pred(__middle, __last, __comp); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__inplace_merge(__first, __middle, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + + /// This is a helper function for the __merge_sort_loop routines. + template + _OutputIterator + __move_merge(_InputIterator __first1, _InputIterator __last1, + _InputIterator __first2, _InputIterator __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = _GLIBCXX_MOVE(*__first2); + ++__first2; + } + else + { + *__result = _GLIBCXX_MOVE(*__first1); + ++__first1; + } + ++__result; + } + return _GLIBCXX_MOVE3(__first2, __last2, + _GLIBCXX_MOVE3(__first1, __last1, + __result)); + } + + template + void + __merge_sort_loop(_RandomAccessIterator1 __first, + _RandomAccessIterator1 __last, + _RandomAccessIterator2 __result, _Distance __step_size, + _Compare __comp) + { + const _Distance __two_step = 2 * __step_size; + + while (__last - __first >= __two_step) + { + __result = std::__move_merge(__first, __first + __step_size, + __first + __step_size, + __first + __two_step, + __result, __comp); + __first += __two_step; + } + __step_size = std::min(_Distance(__last - __first), __step_size); + + std::__move_merge(__first, __first + __step_size, + __first + __step_size, __last, __result, __comp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __chunk_insertion_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Distance __chunk_size, _Compare __comp) + { + while (__last - __first >= __chunk_size) + { + std::__insertion_sort(__first, __first + __chunk_size, __comp); + __first += __chunk_size; + } + std::__insertion_sort(__first, __last, __comp); + } + + enum { _S_chunk_size = 7 }; + + template + void + __merge_sort_with_buffer(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Pointer __buffer, _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _Distance; + + const _Distance __len = __last - __first; + const _Pointer __buffer_last = __buffer + __len; + + _Distance __step_size = _S_chunk_size; + std::__chunk_insertion_sort(__first, __last, __step_size, __comp); + + while (__step_size < __len) + { + std::__merge_sort_loop(__first, __last, __buffer, + __step_size, __comp); + __step_size *= 2; + std::__merge_sort_loop(__buffer, __buffer_last, __first, + __step_size, __comp); + __step_size *= 2; + } + } + + template + void + __stable_sort_adaptive(_RandomAccessIterator __first, + _RandomAccessIterator __last, + _Pointer __buffer, _Distance __buffer_size, + _Compare __comp) + { + const _Distance __len = (__last - __first + 1) / 2; + const _RandomAccessIterator __middle = __first + __len; + if (__len > __buffer_size) + { + std::__stable_sort_adaptive(__first, __middle, __buffer, + __buffer_size, __comp); + std::__stable_sort_adaptive(__middle, __last, __buffer, + __buffer_size, __comp); + } + else + { + std::__merge_sort_with_buffer(__first, __middle, __buffer, __comp); + std::__merge_sort_with_buffer(__middle, __last, __buffer, __comp); + } + std::__merge_adaptive(__first, __middle, __last, + _Distance(__middle - __first), + _Distance(__last - __middle), + __buffer, __buffer_size, + __comp); + } + + /// This is a helper function for the stable sorting routines. + template + void + __inplace_stable_sort(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + if (__last - __first < 15) + { + std::__insertion_sort(__first, __last, __comp); + return; + } + _RandomAccessIterator __middle = __first + (__last - __first) / 2; + std::__inplace_stable_sort(__first, __middle, __comp); + std::__inplace_stable_sort(__middle, __last, __comp); + std::__merge_without_buffer(__first, __middle, __last, + __middle - __first, + __last - __middle, + __comp); + } + + // stable_sort + + // Set algorithms: includes, set_union, set_intersection, set_difference, + // set_symmetric_difference. All of these algorithms have the precondition + // that their input ranges are sorted and the postcondition that their output + // ranges are sorted. + + template + _GLIBCXX20_CONSTEXPR + bool + __includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first2, __first1)) + return false; + else if (__comp(__first1, __first2)) + ++__first1; + else + { + ++__first1; + ++__first2; + } + + return __first2 == __last2; + } + + /** + * @brief Determines whether all elements of a sequence exists in a range. + * @param __first1 Start of search range. + * @param __last1 End of search range. + * @param __first2 Start of sequence + * @param __last2 End of sequence. + * @return True if each element in [__first2,__last2) is contained in order + * within [__first1,__last1). False otherwise. + * @ingroup set_algorithms + * + * This operation expects both [__first1,__last1) and + * [__first2,__last2) to be sorted. Searches for the presence of + * each element in [__first2,__last2) within [__first1,__last1). + * The iterators over each range only move forward, so this is a + * linear algorithm. If an element in [__first2,__last2) is not + * found before the search iterator reaches @p __last2, false is + * returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return std::__includes(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Determines whether all elements of a sequence exists in a range + * using comparison. + * @ingroup set_algorithms + * @param __first1 Start of search range. + * @param __last1 End of search range. + * @param __first2 Start of sequence + * @param __last2 End of sequence. + * @param __comp Comparison function to use. + * @return True if each element in [__first2,__last2) is contained + * in order within [__first1,__last1) according to comp. False + * otherwise. @ingroup set_algorithms + * + * This operation expects both [__first1,__last1) and + * [__first2,__last2) to be sorted. Searches for the presence of + * each element in [__first2,__last2) within [__first1,__last1), + * using comp to decide. The iterators over each range only move + * forward, so this is a linear algorithm. If an element in + * [__first2,__last2) is not found before the search iterator + * reaches @p __last2, false is returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + includes(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return std::__includes(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + // nth_element + // merge + // set_difference + // set_intersection + // set_union + // stable_sort + // set_symmetric_difference + // min_element + // max_element + + template + _GLIBCXX20_CONSTEXPR + bool + __next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + if (__first == __last) + return false; + _BidirectionalIterator __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) + { + _BidirectionalIterator __ii = __i; + --__i; + if (__comp(__i, __ii)) + { + _BidirectionalIterator __j = __last; + while (!__comp(__i, --__j)) + {} + std::iter_swap(__i, __j); + std::__reverse(__ii, __last, + std::__iterator_category(__first)); + return true; + } + if (__i == __first) + { + std::__reverse(__first, __last, + std::__iterator_category(__first)); + return false; + } + } + } + + /** + * @brief Permute range into the next @e dictionary ordering. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return False if wrapped to first permutation, true otherwise. + * + * Treats all permutations of the range as a set of @e dictionary sorted + * sequences. Permutes the current sequence into the next one of this set. + * Returns true if there are more sequences to generate. If the sequence + * is the largest of the set, the smallest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__next_permutation + (__first, __last, __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Permute range into the next @e dictionary ordering using + * comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp A comparison functor. + * @return False if wrapped to first permutation, true otherwise. + * + * Treats all permutations of the range [__first,__last) as a set of + * @e dictionary sorted sequences ordered by @p __comp. Permutes the current + * sequence into the next one of this set. Returns true if there are more + * sequences to generate. If the sequence is the largest of the set, the + * smallest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + next_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__next_permutation + (__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + bool + __prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + if (__first == __last) + return false; + _BidirectionalIterator __i = __first; + ++__i; + if (__i == __last) + return false; + __i = __last; + --__i; + + for(;;) + { + _BidirectionalIterator __ii = __i; + --__i; + if (__comp(__ii, __i)) + { + _BidirectionalIterator __j = __last; + while (!__comp(--__j, __i)) + {} + std::iter_swap(__i, __j); + std::__reverse(__ii, __last, + std::__iterator_category(__first)); + return true; + } + if (__i == __first) + { + std::__reverse(__first, __last, + std::__iterator_category(__first)); + return false; + } + } + } + + /** + * @brief Permute range into the previous @e dictionary ordering. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return False if wrapped to last permutation, true otherwise. + * + * Treats all permutations of the range as a set of @e dictionary sorted + * sequences. Permutes the current sequence into the previous one of this + * set. Returns true if there are more sequences to generate. If the + * sequence is the smallest of the set, the largest is generated and false + * returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__prev_permutation(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Permute range into the previous @e dictionary ordering using + * comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp A comparison functor. + * @return False if wrapped to last permutation, true otherwise. + * + * Treats all permutations of the range [__first,__last) as a set of + * @e dictionary sorted sequences ordered by @p __comp. Permutes the current + * sequence into the previous one of this set. Returns true if there are + * more sequences to generate. If the sequence is the smallest of the set, + * the largest is generated and false returned. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + prev_permutation(_BidirectionalIterator __first, + _BidirectionalIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_BidirectionalIterator>::value_type, + typename iterator_traits<_BidirectionalIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__prev_permutation(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + // replace + // replace_if + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __replace_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _Predicate __pred, const _Tp& __new_value) + { + for (; __first != __last; ++__first, (void)++__result) + if (__pred(__first)) + *__result = __new_value; + else + *__result = *__first; + return __result; + } + + /** + * @brief Copy a sequence, replacing each element of one value with another + * value. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __old_value The value to be replaced. + * @param __new_value The replacement value. + * @return The end of the output sequence, @p result+(last-first). + * + * Copies each element in the input range @p [__first,__last) to the + * output range @p [__result,__result+(__last-__first)) replacing elements + * equal to @p __old_value with @p __new_value. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + replace_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + const _Tp& __old_value, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__replace_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__iter_equals_val(__old_value), + __new_value); + } + + /** + * @brief Copy a sequence, replacing each value for which a predicate + * returns true with another value. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __pred A predicate. + * @param __new_value The replacement value. + * @return The end of the output sequence, @p __result+(__last-__first). + * + * Copies each element in the range @p [__first,__last) to the range + * @p [__result,__result+(__last-__first)) replacing elements for which + * @p __pred returns true with @p __new_value. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + replace_copy_if(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _Predicate __pred, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__replace_copy_if(__first, __last, __result, + __gnu_cxx::__ops::__pred_iter(__pred), + __new_value); + } + +#if __cplusplus >= 201103L + /** + * @brief Determines whether the elements of a sequence are sorted. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return True if the elements are sorted, false otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last) + { return std::is_sorted_until(__first, __last) == __last; } + + /** + * @brief Determines whether the elements of a sequence are sorted + * according to a comparison functor. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return True if the elements are sorted, false otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { return std::is_sorted_until(__first, __last, __comp) == __last; } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) + return __last; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (__comp(__next, __first)) + return __next; + return __next; + } + + /** + * @brief Determines the end of a sorted sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return An iterator pointing to the last iterator i in [__first, __last) + * for which the range [__first, i) is sorted. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + is_sorted_until(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__is_sorted_until(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Determines the end of a sorted sequence using comparison functor. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return An iterator pointing to the last iterator i in [__first, __last) + * for which the range [__first, i) is sorted. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + is_sorted_until(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__is_sorted_until(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Determines min and max at once as an ordered pair. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return A pair(__b, __a) if __b is smaller than __a, pair(__a, + * __b) otherwise. + */ + template + _GLIBCXX14_CONSTEXPR + inline pair + minmax(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + + return __b < __a ? pair(__b, __a) + : pair(__a, __b); + } + + /** + * @brief Determines min and max at once as an ordered pair. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor @endlink. + * @return A pair(__b, __a) if __b is smaller than __a, pair(__a, + * __b) otherwise. + */ + template + _GLIBCXX14_CONSTEXPR + inline pair + minmax(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + return __comp(__b, __a) ? pair(__b, __a) + : pair(__a, __b); + } + + template + _GLIBCXX14_CONSTEXPR + pair<_ForwardIterator, _ForwardIterator> + __minmax_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + _ForwardIterator __next = __first; + if (__first == __last + || ++__next == __last) + return std::make_pair(__first, __first); + + _ForwardIterator __min{}, __max{}; + if (__comp(__next, __first)) + { + __min = __next; + __max = __first; + } + else + { + __min = __first; + __max = __next; + } + + __first = __next; + ++__first; + + while (__first != __last) + { + __next = __first; + if (++__next == __last) + { + if (__comp(__first, __min)) + __min = __first; + else if (!__comp(__first, __max)) + __max = __first; + break; + } + + if (__comp(__next, __first)) + { + if (__comp(__next, __min)) + __min = __next; + if (!__comp(__first, __max)) + __max = __first; + } + else + { + if (__comp(__first, __min)) + __min = __first; + if (!__comp(__next, __max)) + __max = __next; + } + + __first = __next; + ++__first; + } + + return std::make_pair(__min, __max); + } + + /** + * @brief Return a pair of iterators pointing to the minimum and maximum + * elements in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return make_pair(m, M), where m is the first iterator i in + * [__first, __last) such that no other element in the range is + * smaller, and where M is the last iterator i in [__first, __last) + * such that no other element in the range is larger. + */ + template + _GLIBCXX14_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + minmax_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return std::__minmax_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return a pair of iterators pointing to the minimum and maximum + * elements in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return make_pair(m, M), where m is the first iterator i in + * [__first, __last) such that no other element in the range is + * smaller, and where M is the last iterator i in [__first, __last) + * such that no other element in the range is larger. + */ + template + _GLIBCXX14_CONSTEXPR + inline pair<_ForwardIterator, _ForwardIterator> + minmax_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return std::__minmax_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + // N2722 + DR 915. + template + _GLIBCXX14_CONSTEXPR + inline _Tp + min(initializer_list<_Tp> __l) + { return *std::min_element(__l.begin(), __l.end()); } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + min(initializer_list<_Tp> __l, _Compare __comp) + { return *std::min_element(__l.begin(), __l.end(), __comp); } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + max(initializer_list<_Tp> __l) + { return *std::max_element(__l.begin(), __l.end()); } + + template + _GLIBCXX14_CONSTEXPR + inline _Tp + max(initializer_list<_Tp> __l, _Compare __comp) + { return *std::max_element(__l.begin(), __l.end(), __comp); } + + template + _GLIBCXX14_CONSTEXPR + inline pair<_Tp, _Tp> + minmax(initializer_list<_Tp> __l) + { + pair __p = + std::minmax_element(__l.begin(), __l.end()); + return std::make_pair(*__p.first, *__p.second); + } + + template + _GLIBCXX14_CONSTEXPR + inline pair<_Tp, _Tp> + minmax(initializer_list<_Tp> __l, _Compare __comp) + { + pair __p = + std::minmax_element(__l.begin(), __l.end(), __comp); + return std::make_pair(*__p.first, *__p.second); + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __pred A binary predicate. + * @return true if there exists a permutation of the elements in + * the range [__first2, __first2 + (__last1 - __first1)), + * beginning with ForwardIterator2 begin, such that + * equal(__first1, __last1, __begin, __pred) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _BinaryPredicate __pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return std::__is_permutation(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_comp_iter(__pred)); + } + +#if __cplusplus > 201103L + template + _GLIBCXX20_CONSTEXPR + bool + __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) + { + using _Cat1 + = typename iterator_traits<_ForwardIterator1>::iterator_category; + using _Cat2 + = typename iterator_traits<_ForwardIterator2>::iterator_category; + using _It1_is_RA = is_same<_Cat1, random_access_iterator_tag>; + using _It2_is_RA = is_same<_Cat2, random_access_iterator_tag>; + constexpr bool __ra_iters = _It1_is_RA() && _It2_is_RA(); + if (__ra_iters) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + } + + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!__pred(__first1, __first2)) + break; + + if (__ra_iters) + { + if (__first1 == __last1) + return true; + } + else + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 == 0 && __d2 == 0) + return true; + if (__d1 != __d2) + return false; + } + + for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) + { + if (__scan != std::__find_if(__first1, __scan, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) + continue; // We've seen this one before. + + auto __matches = std::__count_if(__first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); + if (0 == __matches + || std::__count_if(__scan, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) + != __matches) + return false; + } + return true; + } + + /** + * @brief Checks whether a permutaion of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of first range. + * @return true if there exists a permutation of the elements in the range + * [__first2, __last2), beginning with ForwardIterator2 begin, + * such that equal(__first1, __last1, begin) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return + std::__is_permutation(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of first range. + * @param __pred A binary predicate. + * @return true if there exists a permutation of the elements in the range + * [__first2, __last2), beginning with ForwardIterator2 begin, + * such that equal(__first1, __last1, __begin, __pred) returns true; + * otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __pred) + { + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__is_permutation(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred)); + } + +#if __cplusplus > 201402L + +#define __cpp_lib_clamp 201603 + + /** + * @brief Returns the value clamped between lo and hi. + * @ingroup sorting_algorithms + * @param __val A value of arbitrary type. + * @param __lo A lower limit of arbitrary type. + * @param __hi An upper limit of arbitrary type. + * @return max(__val, __lo) if __val < __hi or min(__val, __hi) otherwise. + */ + template + constexpr const _Tp& + clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi) + { + __glibcxx_assert(!(__hi < __lo)); + return (__val < __lo) ? __lo : (__hi < __val) ? __hi : __val; + } + + /** + * @brief Returns the value clamped between lo and hi. + * @ingroup sorting_algorithms + * @param __val A value of arbitrary type. + * @param __lo A lower limit of arbitrary type. + * @param __hi An upper limit of arbitrary type. + * @param __comp A comparison functor. + * @return max(__val, __lo, __comp) if __comp(__val, __hi) + * or min(__val, __hi, __comp) otherwise. + */ + template + constexpr const _Tp& + clamp(const _Tp& __val, const _Tp& __lo, const _Tp& __hi, _Compare __comp) + { + __glibcxx_assert(!__comp(__hi, __lo)); + return __comp(__val, __lo) ? __lo : __comp(__hi, __val) ? __hi : __val; + } +#endif // C++17 +#endif // C++14 + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + /** + * @brief Generate two uniformly distributed integers using a + * single distribution invocation. + * @param __b0 The upper bound for the first integer. + * @param __b1 The upper bound for the second integer. + * @param __g A UniformRandomBitGenerator. + * @return A pair (i, j) with i and j uniformly distributed + * over [0, __b0) and [0, __b1), respectively. + * + * Requires: __b0 * __b1 <= __g.max() - __g.min(). + * + * Using uniform_int_distribution with a range that is very + * small relative to the range of the generator ends up wasting + * potentially expensively generated randomness, since + * uniform_int_distribution does not store leftover randomness + * between invocations. + * + * If we know we want two integers in ranges that are sufficiently + * small, we can compose the ranges, use a single distribution + * invocation, and significantly reduce the waste. + */ + template + pair<_IntType, _IntType> + __gen_two_uniform_ints(_IntType __b0, _IntType __b1, + _UniformRandomBitGenerator&& __g) + { + _IntType __x + = uniform_int_distribution<_IntType>{0, (__b0 * __b1) - 1}(__g); + return std::make_pair(__x / __b1, __x % __b1); + } + + /** + * @brief Shuffle the elements of a sequence using a uniform random + * number generator. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __g A UniformRandomNumberGenerator (26.5.1.3). + * @return Nothing. + * + * Reorders the elements in the range @p [__first,__last) using @p __g to + * provide random numbers. + */ + template + void + shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, + _UniformRandomNumberGenerator&& __g) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return; + + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + typedef typename std::make_unsigned<_DistanceType>::type __ud_type; + typedef typename std::uniform_int_distribution<__ud_type> __distr_type; + typedef typename __distr_type::param_type __p_type; + + typedef typename remove_reference<_UniformRandomNumberGenerator>::type + _Gen; + typedef typename common_type::type + __uc_type; + + const __uc_type __urngrange = __g.max() - __g.min(); + const __uc_type __urange = __uc_type(__last - __first); + + if (__urngrange / __urange >= __urange) + // I.e. (__urngrange >= __urange * __urange) but without wrap issues. + { + _RandomAccessIterator __i = __first + 1; + + // Since we know the range isn't empty, an even number of elements + // means an uneven number of elements /to swap/, in which case we + // do the first one up front: + + if ((__urange % 2) == 0) + { + __distr_type __d{0, 1}; + std::iter_swap(__i++, __first + __d(__g)); + } + + // Now we know that __last - __i is even, so we do the rest in pairs, + // using a single distribution invocation to produce swap positions + // for two successive elements at a time: + + while (__i != __last) + { + const __uc_type __swap_range = __uc_type(__i - __first) + 1; + + const pair<__uc_type, __uc_type> __pospos = + __gen_two_uniform_ints(__swap_range, __swap_range + 1, __g); + + std::iter_swap(__i++, __first + __pospos.first); + std::iter_swap(__i++, __first + __pospos.second); + } + + return; + } + + __distr_type __d; + + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + std::iter_swap(__i, __first + __d(__g, __p_type(0, __i - __first))); + } +#endif + +#endif // C++11 + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + /** + * @brief Apply a function to every element of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __f A unary function object. + * @return @p __f + * + * Applies the function object @p __f to each element in the range + * @p [first,last). @p __f must not modify the order of the sequence. + * If @p __f has a return value it is ignored. + */ + template + _GLIBCXX20_CONSTEXPR + _Function + for_each(_InputIterator __first, _InputIterator __last, _Function __f) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + for (; __first != __last; ++__first) + __f(*__first); + return __f; // N.B. [alg.foreach] says std::move(f) but it's redundant. + } + +#if __cplusplus >= 201703L + /** + * @brief Apply a function to every element of a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __n A value convertible to an integer. + * @param __f A unary function object. + * @return `__first+__n` + * + * Applies the function object `__f` to each element in the range + * `[first, first+n)`. `__f` must not modify the order of the sequence. + * If `__f` has a return value it is ignored. + */ + template + _GLIBCXX20_CONSTEXPR + _InputIterator + for_each_n(_InputIterator __first, _Size __n, _Function __f) + { + auto __n2 = std::__size_to_integer(__n); + using _Cat = typename iterator_traits<_InputIterator>::iterator_category; + if constexpr (is_base_of_v) + { + if (__n2 <= 0) + return __first; + auto __last = __first + __n2; + std::for_each(__first, __last, std::move(__f)); + return __last; + } + else + { + while (__n2-->0) + { + __f(*__first); + ++__first; + } + return __first; + } + } +#endif // C++17 + + /** + * @brief Find the first occurrence of a value in a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __val The value to find. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @c *i == @p __val, or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + find(_InputIterator __first, _InputIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__val)); + } + + /** + * @brief Find the first element in a sequence for which a + * predicate is true. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The first iterator @c i in the range @p [__first,__last) + * such that @p __pred(*i) is true, or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + find_if(_InputIterator __first, _InputIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__find_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Find element from a set in a sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of match candidates. + * @param __last2 End of match candidates. + * @return The first iterator @c i in the range + * @p [__first1,__last1) such that @c *i == @p *(i2) such that i2 is an + * iterator in [__first2,__last2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for an element that is + * equal to some element in the range [__first2,__last2). If + * found, returns an iterator in the range [__first1,__last1), + * otherwise returns @p __last1. + */ + template + _GLIBCXX20_CONSTEXPR + _InputIterator + find_first_of(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, _ForwardIterator __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + for (; __first1 != __last1; ++__first1) + for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) + if (*__first1 == *__iter) + return __first1; + return __last1; + } + + /** + * @brief Find element from a set in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 Start of range to search. + * @param __last1 End of range to search. + * @param __first2 Start of match candidates. + * @param __last2 End of match candidates. + * @param __comp Predicate to use. + * @return The first iterator @c i in the range + * @p [__first1,__last1) such that @c comp(*i, @p *(i2)) is true + * and i2 is an iterator in [__first2,__last2), or @p __last1 if no + * such iterator exists. + * + + * Searches the range @p [__first1,__last1) for an element that is + * equal to some element in the range [__first2,__last2). If + * found, returns an iterator in the range [__first1,__last1), + * otherwise returns @p __last1. + */ + template + _GLIBCXX20_CONSTEXPR + _InputIterator + find_first_of(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, _ForwardIterator __last2, + _BinaryPredicate __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_InputIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + for (; __first1 != __last1; ++__first1) + for (_ForwardIterator __iter = __first2; __iter != __last2; ++__iter) + if (__comp(*__first1, *__iter)) + return __first1; + return __last1; + } + + /** + * @brief Find two adjacent values in a sequence that are equal. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return The first iterator @c i such that @c i and @c i+1 are both + * valid iterators in @p [__first,__last) and such that @c *i == @c *(i+1), + * or @p __last if no such iterator exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + adjacent_find(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__adjacent_find(__first, __last, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Find two adjacent values in a sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __binary_pred A binary predicate. + * @return The first iterator @c i such that @c i and @c i+1 are both + * valid iterators in @p [__first,__last) and such that + * @p __binary_pred(*i,*(i+1)) is true, or @p __last if no such iterator + * exists. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + adjacent_find(_ForwardIterator __first, _ForwardIterator __last, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__adjacent_find(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + + /** + * @brief Count the number of copies of a value in a sequence. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __value The value to be counted. + * @return The number of iterators @c i in the range @p [__first,__last) + * for which @c *i == @p __value + */ + template + _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::difference_type + count(_InputIterator __first, _InputIterator __last, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__count_if(__first, __last, + __gnu_cxx::__ops::__iter_equals_val(__value)); + } + + /** + * @brief Count the elements of a sequence for which a predicate is true. + * @ingroup non_mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __pred A predicate. + * @return The number of iterators @c i in the range @p [__first,__last) + * for which @p __pred(*i) is true. + */ + template + _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::difference_type + count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__count_if(__first, __last, + __gnu_cxx::__ops::__pred_iter(__pred)); + } + + /** + * @brief Search a sequence for a matching sub-sequence. + * @ingroup non_mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @param __last2 A forward iterator. + * @return The first iterator @c i in the range @p + * [__first1,__last1-(__last2-__first2)) such that @c *(i+N) == @p + * *(__first2+N) for each @c N in the range @p + * [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2) and returns an iterator to the first element + * of the sub-sequence, or @p __last1 if the sub-sequence is not + * found. + * + * Because the sub-sequence must lie completely within the range @p + * [__first1,__last1) it must start at a position less than @p + * __last1-(__last2-__first2) where @p __last2-__first2 is the + * length of the sub-sequence. + * + * This means that the returned iterator @c i will be in the range + * @p [__first1,__last1-(__last2-__first2)) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__search(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Search a sequence for a matching sub-sequence using a predicate. + * @ingroup non_mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @param __last2 A forward iterator. + * @param __predicate A binary predicate. + * @return The first iterator @c i in the range + * @p [__first1,__last1-(__last2-__first2)) such that + * @p __predicate(*(i+N),*(__first2+N)) is true for each @c N in the range + * @p [0,__last2-__first2), or @p __last1 if no such iterator exists. + * + * Searches the range @p [__first1,__last1) for a sub-sequence that + * compares equal value-by-value with the sequence given by @p + * [__first2,__last2), using @p __predicate to determine equality, + * and returns an iterator to the first element of the + * sub-sequence, or @p __last1 if no such iterator exists. + * + * @see search(_ForwardIter1, _ForwardIter1, _ForwardIter2, _ForwardIter2) + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator1 + search(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _ForwardIterator2 __last2, + _BinaryPredicate __predicate) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__search(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__predicate)); + } + + /** + * @brief Search a sequence for a number of consecutive values. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __count The number of consecutive values. + * @param __val The value to find. + * @return The first iterator @c i in the range @p + * [__first,__last-__count) such that @c *(i+N) == @p __val for + * each @c N in the range @p [0,__count), or @p __last if no such + * iterator exists. + * + * Searches the range @p [__first,__last) for @p count consecutive elements + * equal to @p __val. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__search_n(__first, __last, __count, + __gnu_cxx::__ops::__iter_equals_val(__val)); + } + + + /** + * @brief Search a sequence for a number of consecutive values using a + * predicate. + * @ingroup non_mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __count The number of consecutive values. + * @param __val The value to find. + * @param __binary_pred A binary predicate. + * @return The first iterator @c i in the range @p + * [__first,__last-__count) such that @p + * __binary_pred(*(i+N),__val) is true for each @c N in the range + * @p [0,__count), or @p __last if no such iterator exists. + * + * Searches the range @p [__first,__last) for @p __count + * consecutive elements for which the predicate returns true. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search_n(_ForwardIterator __first, _ForwardIterator __last, + _Integer __count, const _Tp& __val, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_BinaryPredicate, + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__search_n(__first, __last, __count, + __gnu_cxx::__ops::__iter_comp_val(__binary_pred, __val)); + } + +#if __cplusplus > 201402L + /** @brief Search a sequence using a Searcher object. + * + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __searcher A callable object. + * @return @p __searcher(__first,__last).first + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + search(_ForwardIterator __first, _ForwardIterator __last, + const _Searcher& __searcher) + { return __searcher(__first, __last).first; } +#endif + + /** + * @brief Perform an operation on a sequence. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __unary_op A unary operator. + * @return An output iterator equal to @p __result+(__last-__first). + * + * Applies the operator to each element in the input range and assigns + * the results to successive elements of the output sequence. + * Evaluates @p *(__result+N)=unary_op(*(__first+N)) for each @c N in the + * range @p [0,__last-__first). + * + * @p unary_op must not alter its argument. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _UnaryOperation __unary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _UnaryOperation" + __typeof__(__unary_op(*__first))>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first, (void)++__result) + *__result = __unary_op(*__first); + return __result; + } + + /** + * @brief Perform an operation on corresponding elements of two sequences. + * @ingroup mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __result An output iterator. + * @param __binary_op A binary operator. + * @return An output iterator equal to @p result+(last-first). + * + * Applies the operator to the corresponding elements in the two + * input ranges and assigns the results to successive elements of the + * output sequence. + * Evaluates @p + * *(__result+N)=__binary_op(*(__first1+N),*(__first2+N)) for each + * @c N in the range @p [0,__last1-__first1). + * + * @p binary_op must not alter either of its arguments. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _OutputIterator __result, + _BinaryOperation __binary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _BinaryOperation" + __typeof__(__binary_op(*__first1,*__first2))>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2, ++__result) + *__result = __binary_op(*__first1, *__first2); + return __result; + } + + /** + * @brief Replace each occurrence of one value in a sequence with another + * value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __old_value The value to be replaced. + * @param __new_value The replacement value. + * @return replace() returns no value. + * + * For each iterator @c i in the range @p [__first,__last) if @c *i == + * @p __old_value then the assignment @c *i = @p __new_value is performed. + */ + template + _GLIBCXX20_CONSTEXPR + void + replace(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __old_value, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (*__first == __old_value) + *__first = __new_value; + } + + /** + * @brief Replace each value in a sequence for which a predicate returns + * true with another value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate. + * @param __new_value The replacement value. + * @return replace_if() returns no value. + * + * For each iterator @c i in the range @p [__first,__last) if @p __pred(*i) + * is true then the assignment @c *i = @p __new_value is performed. + */ + template + _GLIBCXX20_CONSTEXPR + void + replace_if(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, const _Tp& __new_value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + if (__pred(*__first)) + *__first = __new_value; + } + + /** + * @brief Assign the result of a function object to each value in a + * sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __gen A function object taking no arguments and returning + * std::iterator_traits<_ForwardIterator>::value_type + * @return generate() returns no value. + * + * Performs the assignment @c *i = @p __gen() for each @c i in the range + * @p [__first,__last). + */ + template + _GLIBCXX20_CONSTEXPR + void + generate(_ForwardIterator __first, _ForwardIterator __last, + _Generator __gen) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_GeneratorConcept<_Generator, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + *__first = __gen(); + } + + /** + * @brief Assign the result of a function object to each value in a + * sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __n The length of the sequence. + * @param __gen A function object taking no arguments and returning + * std::iterator_traits<_ForwardIterator>::value_type + * @return The end of the sequence, @p __first+__n + * + * Performs the assignment @c *i = @p __gen() for each @c i in the range + * @p [__first,__first+__n). + * + * If @p __n is negative, the function does nothing and returns @p __first. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 865. More algorithms that throw away information + // DR 426. search_n(), fill_n(), and generate_n() with negative n + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + generate_n(_OutputIterator __first, _Size __n, _Generator __gen) + { + // concept requirements + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + // "the type returned by a _Generator" + __typeof__(__gen())>) + + typedef __decltype(std::__size_to_integer(__n)) _IntSize; + for (_IntSize __niter = std::__size_to_integer(__n); + __niter > 0; --__niter, (void) ++__first) + *__first = __gen(); + return __first; + } + + /** + * @brief Copy a sequence, removing consecutive duplicate values. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) to the range + * beginning at @p __result, except that only the first element is copied + * from groups of consecutive elements that compare equal. + * unique_copy() is stable, so the relative order of elements that are + * copied is unchanged. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 241. Does unique_copy() require CopyConstructible and Assignable? + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 538. 241 again: Does unique_copy() require CopyConstructible and + * Assignable? + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + return std::__unique_copy(__first, __last, __result, + __gnu_cxx::__ops::__iter_equal_to_iter(), + std::__iterator_category(__first), + std::__iterator_category(__result)); + } + + /** + * @brief Copy a sequence, removing consecutive values using a predicate. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @param __binary_pred A binary predicate. + * @return An iterator designating the end of the resulting sequence. + * + * Copies each element in the range @p [__first,__last) to the range + * beginning at @p __result, except that only the first element is copied + * from groups of consecutive elements for which @p __binary_pred returns + * true. + * unique_copy() is stable, so the relative order of elements that are + * copied is unchanged. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 241. Does unique_copy() require CopyConstructible and Assignable? + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + unique_copy(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryPredicate __binary_pred) + { + // concept requirements -- predicates checked later + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + return std::__unique_copy(__first, __last, __result, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred), + std::__iterator_category(__first), + std::__iterator_category(__result)); + } + +#if _GLIBCXX_HOSTED + /** + * @brief Randomly shuffle the elements of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @return Nothing. + * + * Reorder the elements in the range @p [__first,__last) using a random + * distribution, so that every possible ordering of the sequence is + * equally likely. + */ + template + inline void + random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first != __last) + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + // XXX rand() % N is not uniformly distributed + _RandomAccessIterator __j = __first + + std::rand() % ((__i - __first) + 1); + if (__i != __j) + std::iter_swap(__i, __j); + } + } +#endif + + /** + * @brief Shuffle the elements of a sequence using a random number + * generator. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __rand The RNG functor or function. + * @return Nothing. + * + * Reorders the elements in the range @p [__first,__last) using @p __rand to + * provide a random distribution. Calling @p __rand(N) for a positive + * integer @p N should return a randomly chosen integer from the + * range [0,N). + */ + template + void + random_shuffle(_RandomAccessIterator __first, _RandomAccessIterator __last, +#if __cplusplus >= 201103L + _RandomNumberGenerator&& __rand) +#else + _RandomNumberGenerator& __rand) +#endif + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return; + for (_RandomAccessIterator __i = __first + 1; __i != __last; ++__i) + { + _RandomAccessIterator __j = __first + __rand((__i - __first) + 1); + if (__i != __j) + std::iter_swap(__i, __j); + } + } + + + /** + * @brief Move elements for which a predicate is true to the beginning + * of a sequence. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __pred A predicate functor. + * @return An iterator @p middle such that @p __pred(i) is true for each + * iterator @p i in the range @p [__first,middle) and false for each @p i + * in the range @p [middle,__last). + * + * @p __pred must not modify its operand. @p partition() does not preserve + * the relative ordering of elements in each group, use + * @p stable_partition() if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + partition(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__partition(__first, __last, __pred, + std::__iterator_category(__first)); + } + + + /** + * @brief Sort the smallest elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the smallest @p (__middle-__first) elements in the range + * @p [first,last) and moves them to the range @p [__first,__middle). The + * order of the remaining elements in the range @p [__middle,__last) is + * undefined. + * After the sort if @e i and @e j are iterators in the range + * @p [__first,__middle) such that i precedes j and @e k is an iterator in + * the range @p [__middle,__last) then *j<*i and *k<*i are both false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__partial_sort(__first, __middle, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the smallest elements of a sequence using a predicate + * for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __middle Another iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the smallest @p (__middle-__first) elements in the range + * @p [__first,__last) and moves them to the range @p [__first,__middle). The + * order of the remaining elements in the range @p [__middle,__last) is + * undefined. + * After the sort if @e i and @e j are iterators in the range + * @p [__first,__middle) such that i precedes j and @e k is an iterator in + * the range @p [__middle,__last) then @p *__comp(j,*i) and @p __comp(*k,*i) + * are both false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + partial_sort(_RandomAccessIterator __first, + _RandomAccessIterator __middle, + _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __middle); + __glibcxx_requires_valid_range(__middle, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__partial_sort(__first, __middle, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Sort a sequence just enough to find a particular position. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __nth Another iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Rearranges the elements in the range @p [__first,__last) so that @p *__nth + * is the same element that would have been in that position had the + * whole sequence been sorted. The elements either side of @p *__nth are + * not completely sorted, but for any iterator @e i in the range + * @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it + * holds that *j < *i is false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __nth); + __glibcxx_requires_valid_range(__nth, __last); + __glibcxx_requires_irreflexive(__first, __last); + + if (__first == __last || __nth == __last) + return; + + std::__introselect(__first, __nth, __last, + std::__lg(__last - __first) * 2, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort a sequence just enough to find a particular position + * using a predicate for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __nth Another iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Rearranges the elements in the range @p [__first,__last) so that @p *__nth + * is the same element that would have been in that position had the + * whole sequence been sorted. The elements either side of @p *__nth are + * not completely sorted, but for any iterator @e i in the range + * @p [__first,__nth) and any iterator @e j in the range @p [__nth,__last) it + * holds that @p __comp(*j,*i) is false. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + nth_element(_RandomAccessIterator __first, _RandomAccessIterator __nth, + _RandomAccessIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __nth); + __glibcxx_requires_valid_range(__nth, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + if (__first == __last || __nth == __last) + return; + + std::__introselect(__first, __nth, __last, + std::__lg(__last - __first) * 2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + /** + * @brief Sort the elements of a sequence. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that for each iterator @e i in the range @p [__first,__last-1), + * *(i+1)<*i is false. + * + * The relative ordering of equivalent elements is not preserved, use + * @p stable_sort() if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + std::__sort(__first, __last, __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the elements of a sequence using a predicate for comparison. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that @p __comp(*(i+1),*i) is false for every iterator @e i in the + * range @p [__first,__last-1). + * + * The relative ordering of equivalent elements is not preserved, use + * @p stable_sort() if this is needed. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + std::__sort(__first, __last, __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + } + ++__result; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Merges two sorted ranges. + * @ingroup sorting_algorithms + * @param __first1 An iterator. + * @param __first2 Another iterator. + * @param __last1 Another iterator. + * @param __last2 Another iterator. + * @param __result An iterator pointing to the end of the merged range. + * @return An output iterator equal to @p __result + (__last1 - __first1) + * + (__last2 - __first2). + * + * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into + * the sorted range @p [__result, __result + (__last1-__first1) + + * (__last2-__first2)). Both input ranges must be sorted, and the + * output range must not overlap with either of the input ranges. + * The sort is @e stable, that is, for equivalent elements in the + * two ranges, elements from the first range will always come + * before elements from the second. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__merge(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Merges two sorted ranges. + * @ingroup sorting_algorithms + * @param __first1 An iterator. + * @param __first2 Another iterator. + * @param __last1 Another iterator. + * @param __last2 Another iterator. + * @param __result An iterator pointing to the end of the merged range. + * @param __comp A functor to use for comparisons. + * @return An output iterator equal to @p __result + (__last1 - __first1) + * + (__last2 - __first2). + * + * Merges the ranges @p [__first1,__last1) and @p [__first2,__last2) into + * the sorted range @p [__result, __result + (__last1-__first1) + + * (__last2-__first2)). Both input ranges must be sorted, and the + * output range must not overlap with either of the input ranges. + * The sort is @e stable, that is, for equivalent elements in the + * two ranges, elements from the first range will always come + * before elements from the second. + * + * The comparison function should have the same effects on ordering as + * the function used for the initial sort. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + merge(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__merge(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + inline void + __stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + typedef _Temporary_buffer<_RandomAccessIterator, _ValueType> _TmpBuf; + _TmpBuf __buf(__first, std::distance(__first, __last)); + + if (__buf.begin() == 0) + std::__inplace_stable_sort(__first, __last, __comp); + else + std::__stable_sort_adaptive(__first, __last, __buf.begin(), + _DistanceType(__buf.size()), __comp); + } + + /** + * @brief Sort the elements of a sequence, preserving the relative order + * of equivalent elements. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that for each iterator @p i in the range @p [__first,__last-1), + * @p *(i+1)<*i is false. + * + * The relative ordering of equivalent elements is preserved, so any two + * elements @p x and @p y in the range @p [__first,__last) such that + * @p x + inline void + stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + _GLIBCXX_STD_A::__stable_sort(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Sort the elements of a sequence using a predicate for comparison, + * preserving the relative order of equivalent elements. + * @ingroup sorting_algorithms + * @param __first An iterator. + * @param __last Another iterator. + * @param __comp A comparison functor. + * @return Nothing. + * + * Sorts the elements in the range @p [__first,__last) in ascending order, + * such that for each iterator @p i in the range @p [__first,__last-1), + * @p __comp(*(i+1),*i) is false. + * + * The relative ordering of equivalent elements is preserved, so any two + * elements @p x and @p y in the range @p [__first,__last) such that + * @p __comp(x,y) is false and @p __comp(y,x) is false will have the same + * relative ordering after calling @p stable_sort(). + */ + template + inline void + stable_sort(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_RandomAccessIterator>::value_type, + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + _GLIBCXX_STD_A::__stable_sort(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + } + else if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + } + else + { + *__result = *__first1; + ++__first1; + ++__first2; + } + ++__result; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Return the union of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * each range in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other, + * that element is copied and the iterator advanced. If an element is + * contained in both ranges, the element from the first range is copied and + * both ranges advance. The output range may not overlap either input + * range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_union(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the union of two sorted ranges using a comparison functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * each range in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other + * according to @p __comp, that element is copied and the iterator advanced. + * If an equivalent element according to @p __comp is contained in both + * ranges, the element from the first range is copied and both ranges + * advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_union(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_union(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + ++__first1; + else if (__comp(__first2, __first1)) + ++__first2; + else + { + *__result = *__first1; + ++__first1; + ++__first2; + ++__result; + } + return __result; + } + + /** + * @brief Return the intersection of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * both ranges in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other, + * that iterator advances. If an element is contained in both ranges, the + * element from the first range is copied and both ranges advance. The + * output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the intersection of two sorted ranges using comparison + * functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * both ranges in order to the output range. Iterators increment for each + * range. When the current element of one range is less than the other + * according to @p __comp, that iterator advances. If an element is + * contained in both ranges according to @p __comp, the element from the + * first range is copied and both ranges advance. The output range may not + * overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_intersection(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_intersection(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (__comp(__first2, __first1)) + ++__first2; + else + { + ++__first1; + ++__first2; + } + return std::copy(__first1, __last1, __result); + } + + /** + * @brief Return the difference of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * the first range but not the second in order to the output range. + * Iterators increment for each range. When the current element of the + * first range is less than the second, that element is copied and the + * iterator advances. If the current element of the second range is less, + * the iterator advances, but no element is copied. If an element is + * contained in both ranges, no elements are copied and both ranges + * advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the difference of two sorted ranges using comparison + * functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * the first range but not the second in order to the output range. + * Iterators increment for each range. When the current element of the + * first range is less than the second according to @p __comp, that element + * is copied and the iterator advances. If the current element of the + * second range is less, no element is copied and the iterator advances. + * If an element is contained in both ranges according to @p __comp, no + * elements are copied and both ranges advance. The output range may not + * overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + __set_symmetric_difference(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) + { + while (__first1 != __last1 && __first2 != __last2) + if (__comp(__first1, __first2)) + { + *__result = *__first1; + ++__first1; + ++__result; + } + else if (__comp(__first2, __first1)) + { + *__result = *__first2; + ++__first2; + ++__result; + } + else + { + ++__first1; + ++__first2; + } + return std::copy(__first2, __last2, + std::copy(__first1, __last1, __result)); + } + + /** + * @brief Return the symmetric difference of two sorted ranges. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * one range but not the other in order to the output range. Iterators + * increment for each range. When the current element of one range is less + * than the other, that element is copied and the iterator advances. If an + * element is contained in both ranges, no elements are copied and both + * ranges advance. The output range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set(__first1, __last1, __first2); + __glibcxx_requires_sorted_set(__first2, __last2, __first1); + __glibcxx_requires_irreflexive2(__first1, __last1); + __glibcxx_requires_irreflexive2(__first2, __last2); + + return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the symmetric difference of two sorted ranges using + * comparison functor. + * @ingroup set_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __last2 End of second range. + * @param __result Start of output range. + * @param __comp The comparison functor. + * @return End of the output range. + * @ingroup set_algorithms + * + * This operation iterates over both ranges, copying elements present in + * one range but not the other in order to the output range. Iterators + * increment for each range. When the current element of one range is less + * than the other according to @p comp, that element is copied and the + * iterator advances. If an element is contained in both ranges according + * to @p __comp, no elements are copied and both ranges advance. The output + * range may not overlap either input range. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + set_symmetric_difference(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _OutputIterator __result, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_InputIterator2>::value_type, + typename iterator_traits<_InputIterator1>::value_type>) + __glibcxx_requires_sorted_set_pred(__first1, __last1, __first2, __comp); + __glibcxx_requires_sorted_set_pred(__first2, __last2, __first1, __comp); + __glibcxx_requires_irreflexive_pred2(__first1, __last1, __comp); + __glibcxx_requires_irreflexive_pred2(__first2, __last2, __comp); + + return _GLIBCXX_STD_A::__set_symmetric_difference(__first1, __last1, + __first2, __last2, __result, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX14_CONSTEXPR + _ForwardIterator + __min_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) + return __first; + _ForwardIterator __result = __first; + while (++__first != __last) + if (__comp(__first, __result)) + __result = __first; + return __result; + } + + /** + * @brief Return the minimum element in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return Iterator referencing the first instance of the smallest value. + */ + template + _GLIBCXX14_CONSTEXPR + _ForwardIterator + inline min_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return _GLIBCXX_STD_A::__min_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the minimum element in a range using comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return Iterator referencing the first instance of the smallest value + * according to __comp. + */ + template + _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + min_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return _GLIBCXX_STD_A::__min_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + + template + _GLIBCXX14_CONSTEXPR + _ForwardIterator + __max_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + if (__first == __last) return __first; + _ForwardIterator __result = __first; + while (++__first != __last) + if (__comp(__result, __first)) + __result = __first; + return __result; + } + + /** + * @brief Return the maximum element in a range. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @return Iterator referencing the first instance of the largest value. + */ + template + _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + max_element(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + return _GLIBCXX_STD_A::__max_element(__first, __last, + __gnu_cxx::__ops::__iter_less_iter()); + } + + /** + * @brief Return the maximum element in a range using comparison functor. + * @ingroup sorting_algorithms + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor. + * @return Iterator referencing the first instance of the largest value + * according to __comp. + */ + template + _GLIBCXX14_CONSTEXPR + inline _ForwardIterator + max_element(_ForwardIterator __first, _ForwardIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_Compare, + typename iterator_traits<_ForwardIterator>::value_type, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + return _GLIBCXX_STD_A::__max_element(__first, __last, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cplusplus >= 201402L + /// Reservoir sampling algorithm. + template + _RandomAccessIterator + __sample(_InputIterator __first, _InputIterator __last, input_iterator_tag, + _RandomAccessIterator __out, random_access_iterator_tag, + _Size __n, _UniformRandomBitGenerator&& __g) + { + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + __distrib_type __d{}; + _Size __sample_sz = 0; + while (__first != __last && __sample_sz != __n) + { + __out[__sample_sz++] = *__first; + ++__first; + } + for (auto __pop_sz = __sample_sz; __first != __last; + ++__first, (void) ++__pop_sz) + { + const auto __k = __d(__g, __param_type{0, __pop_sz}); + if (__k < __n) + __out[__k] = *__first; + } + return __out + __sample_sz; + } + + /// Selection sampling algorithm. + template + _OutputIterator + __sample(_ForwardIterator __first, _ForwardIterator __last, + forward_iterator_tag, + _OutputIterator __out, _Cat, + _Size __n, _UniformRandomBitGenerator&& __g) + { + using __distrib_type = uniform_int_distribution<_Size>; + using __param_type = typename __distrib_type::param_type; + using _USize = make_unsigned_t<_Size>; + using _Gen = remove_reference_t<_UniformRandomBitGenerator>; + using __uc_type = common_type_t; + + if (__first == __last) + return __out; + + __distrib_type __d{}; + _Size __unsampled_sz = std::distance(__first, __last); + __n = std::min(__n, __unsampled_sz); + + // If possible, we use __gen_two_uniform_ints to efficiently produce + // two random numbers using a single distribution invocation: + + const __uc_type __urngrange = __g.max() - __g.min(); + if (__urngrange / __uc_type(__unsampled_sz) >= __uc_type(__unsampled_sz)) + // I.e. (__urngrange >= __unsampled_sz * __unsampled_sz) but without + // wrapping issues. + { + while (__n != 0 && __unsampled_sz >= 2) + { + const pair<_Size, _Size> __p = + __gen_two_uniform_ints(__unsampled_sz, __unsampled_sz - 1, __g); + + --__unsampled_sz; + if (__p.first < __n) + { + *__out++ = *__first; + --__n; + } + + ++__first; + + if (__n == 0) break; + + --__unsampled_sz; + if (__p.second < __n) + { + *__out++ = *__first; + --__n; + } + + ++__first; + } + } + + // The loop above is otherwise equivalent to this one-at-a-time version: + + for (; __n != 0; ++__first) + if (__d(__g, __param_type{0, --__unsampled_sz}) < __n) + { + *__out++ = *__first; + --__n; + } + return __out; + } + +#if __cplusplus > 201402L +#define __cpp_lib_sample 201603 + /// Take a random sample from a population. + template + _SampleIterator + sample(_PopulationIterator __first, _PopulationIterator __last, + _SampleIterator __out, _Distance __n, + _UniformRandomBitGenerator&& __g) + { + using __pop_cat = typename + std::iterator_traits<_PopulationIterator>::iterator_category; + using __samp_cat = typename + std::iterator_traits<_SampleIterator>::iterator_category; + + static_assert( + __or_, + is_convertible<__samp_cat, random_access_iterator_tag>>::value, + "output range must use a RandomAccessIterator when input range" + " does not meet the ForwardIterator requirements"); + + static_assert(is_integral<_Distance>::value, + "sample size must be an integer type"); + + typename iterator_traits<_PopulationIterator>::difference_type __d = __n; + return _GLIBCXX_STD_A:: + __sample(__first, __last, __pop_cat{}, __out, __samp_cat{}, __d, + std::forward<_UniformRandomBitGenerator>(__g)); + } +#endif // C++17 +#endif // C++14 + +_GLIBCXX_END_NAMESPACE_ALGO +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_ALGO_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h b/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h new file mode 100644 index 000000000..dd2bd1727 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_algobase.h @@ -0,0 +1,1959 @@ +// Core algorithmic facilities -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_algobase.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{algorithm} + */ + +#ifndef _STL_ALGOBASE_H +#define _STL_ALGOBASE_H 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include // For std::swap +#include +#if __cplusplus >= 201103L +# include +#endif +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /* + * A constexpr wrapper for __builtin_memcmp. + * @param __num The number of elements of type _Tp (not bytes). + */ + template + _GLIBCXX14_CONSTEXPR + inline int + __memcmp(const _Tp* __first1, const _Up* __first2, size_t __num) + { +#if __cplusplus >= 201103L + static_assert(sizeof(_Tp) == sizeof(_Up), "can be compared with memcmp"); +#endif +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + for(; __num > 0; ++__first1, ++__first2, --__num) + if (*__first1 != *__first2) + return *__first1 < *__first2 ? -1 : 1; + return 0; + } + else +#endif + return __builtin_memcmp(__first1, __first2, sizeof(_Tp) * __num); + } + +#if __cplusplus < 201103L + // See http://gcc.gnu.org/ml/libstdc++/2004-08/msg00167.html: in a + // nutshell, we are partially implementing the resolution of DR 187, + // when it's safe, i.e., the value_types are equal. + template + struct __iter_swap + { + template + static void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + typedef typename iterator_traits<_ForwardIterator1>::value_type + _ValueType1; + _ValueType1 __tmp = *__a; + *__a = *__b; + *__b = __tmp; + } + }; + + template<> + struct __iter_swap + { + template + static void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + swap(*__a, *__b); + } + }; +#endif // C++03 + + /** + * @brief Swaps the contents of two iterators. + * @ingroup mutating_algorithms + * @param __a An iterator. + * @param __b Another iterator. + * @return Nothing. + * + * This function swaps the values pointed to by two iterators, not the + * iterators themselves. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + iter_swap(_ForwardIterator1 __a, _ForwardIterator2 __b) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator1>) + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator2>) + +#if __cplusplus < 201103L + typedef typename iterator_traits<_ForwardIterator1>::value_type + _ValueType1; + typedef typename iterator_traits<_ForwardIterator2>::value_type + _ValueType2; + + __glibcxx_function_requires(_ConvertibleConcept<_ValueType1, + _ValueType2>) + __glibcxx_function_requires(_ConvertibleConcept<_ValueType2, + _ValueType1>) + + typedef typename iterator_traits<_ForwardIterator1>::reference + _ReferenceType1; + typedef typename iterator_traits<_ForwardIterator2>::reference + _ReferenceType2; + std::__iter_swap<__are_same<_ValueType1, _ValueType2>::__value + && __are_same<_ValueType1&, _ReferenceType1>::__value + && __are_same<_ValueType2&, _ReferenceType2>::__value>:: + iter_swap(__a, __b); +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 187. iter_swap underspecified + swap(*__a, *__b); +#endif + } + + /** + * @brief Swap the elements of two sequences. + * @ingroup mutating_algorithms + * @param __first1 A forward iterator. + * @param __last1 A forward iterator. + * @param __first2 A forward iterator. + * @return An iterator equal to @p first2+(last1-first1). + * + * Swaps each element in the range @p [first1,last1) with the + * corresponding element in the range @p [first2,(last1-first1)). + * The ranges must not overlap. + */ + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator2 + swap_ranges(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator1>) + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + std::iter_swap(__first1, __first2); + return __first2; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return The lesser of the parameters. + * + * This is the simple classic generic implementation. It will work on + * temporary expressions, since they are only evaluated once, unlike a + * preprocessor macro. + */ + template + _GLIBCXX14_CONSTEXPR + inline const _Tp& + min(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + //return __b < __a ? __b : __a; + if (__b < __a) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @return The greater of the parameters. + * + * This is the simple classic generic implementation. It will work on + * temporary expressions, since they are only evaluated once, unlike a + * preprocessor macro. + */ + template + _GLIBCXX14_CONSTEXPR + inline const _Tp& + max(const _Tp& __a, const _Tp& __b) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + //return __a < __b ? __b : __a; + if (__a < __b) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The lesser of the parameters. + * + * This will work on temporary expressions, since they are only evaluated + * once, unlike a preprocessor macro. + */ + template + _GLIBCXX14_CONSTEXPR + inline const _Tp& + min(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + //return __comp(__b, __a) ? __b : __a; + if (__comp(__b, __a)) + return __b; + return __a; + } + + /** + * @brief This does what you think it does. + * @ingroup sorting_algorithms + * @param __a A thing of arbitrary type. + * @param __b Another thing of arbitrary type. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The greater of the parameters. + * + * This will work on temporary expressions, since they are only evaluated + * once, unlike a preprocessor macro. + */ + template + _GLIBCXX14_CONSTEXPR + inline const _Tp& + max(const _Tp& __a, const _Tp& __b, _Compare __comp) + { + //return __comp(__a, __b) ? __b : __a; + if (__comp(__a, __b)) + return __b; + return __a; + } + + // Fallback implementation of the function in bits/stl_iterator.h used to + // remove the __normal_iterator wrapper. See copy, fill, ... + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __niter_base(_Iterator __it) + _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) + { return __it; } + + // Reverse the __niter_base transformation to get a + // __normal_iterator back again (this assumes that __normal_iterator + // is only used to wrap random access iterators, like pointers). + template + _GLIBCXX20_CONSTEXPR + inline _From + __niter_wrap(_From __from, _To __res) + { return __from + (__res - std::__niter_base(__from)); } + + // No need to wrap, iterator already has the right type. + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __niter_wrap(const _Iterator&, _Iterator __res) + { return __res; } + + // All of these auxiliary structs serve two purposes. (1) Replace + // calls to copy with memmove whenever possible. (Memmove, not memcpy, + // because the input and output ranges are permitted to overlap.) + // (2) If we're using random access iterators, then write the loop as + // a for loop with an explicit count. + + template + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + for (; __first != __last; ++__result, (void)++__first) + *__result = *__first; + return __result; + } + }; + +#if __cplusplus >= 201103L + template + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + for (; __first != __last; ++__result, (void)++__first) + *__result = std::move(*__first); + return __result; + } + }; +#endif + + template<> + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::difference_type _Distance; + for(_Distance __n = __last - __first; __n > 0; --__n) + { + *__result = *__first; + ++__first; + ++__result; + } + return __result; + } + }; + +#if __cplusplus >= 201103L + template<> + struct __copy_move + { + template + _GLIBCXX20_CONSTEXPR + static _OI + __copy_m(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::difference_type _Distance; + for(_Distance __n = __last - __first; __n > 0; --__n) + { + *__result = std::move(*__first); + ++__first; + ++__result; + } + return __result; + } + }; +#endif + + template + struct __copy_move<_IsMove, true, random_access_iterator_tag> + { + template + _GLIBCXX20_CONSTEXPR + static _Tp* + __copy_m(const _Tp* __first, const _Tp* __last, _Tp* __result) + { +#if __cplusplus >= 201103L + using __assignable = conditional<_IsMove, + is_move_assignable<_Tp>, + is_copy_assignable<_Tp>>; + // trivial types can have deleted assignment + static_assert( __assignable::type::value, "type is not assignable" ); +#endif + const ptrdiff_t _Num = __last - __first; + if (_Num) + __builtin_memmove(__result, __first, sizeof(_Tp) * _Num); + return __result + _Num; + } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a2(_II __first, _II __last, _OI __result) + { + typedef typename iterator_traits<_II>::iterator_category _Category; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__copy_move<_IsMove, false, _Category>:: + __copy_m(__first, __last, __result); +#endif + return std::__copy_move<_IsMove, __memcpyable<_OI, _II>::__value, + _Category>::__copy_m(__first, __last, __result); + } + +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + struct _Deque_iterator; + +_GLIBCXX_END_NAMESPACE_CONTAINER + + template + _OI + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _OI); + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_a1(_GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_a1(_II, _II, _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a1(_II __first, _II __last, _OI __result) + { return std::__copy_move_a2<_IsMove>(__first, __last, __result); } + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_a(_II __first, _II __last, _OI __result) + { + return std::__niter_wrap(__result, + std::__copy_move_a1<_IsMove>(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result))); + } + + /** + * @brief Copies the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return result + (last - first) + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). Result may not be contained within + * [first,last); the copy_backward function should be used instead. + * + * Note that the end of the output range is permitted to be contained + * within [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OI + copy(_II __first, _II __last, _OI __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II>) + __glibcxx_function_requires(_OutputIteratorConcept<_OI, + typename iterator_traits<_II>::value_type>) + __glibcxx_requires_can_increment_range(__first, __last, __result); + + return std::__copy_move_a<__is_move_iterator<_II>::__value> + (std::__miter_base(__first), std::__miter_base(__last), __result); + } + +#if __cplusplus >= 201103L + /** + * @brief Moves the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return result + (last - first) + * + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). Result may not be contained within + * [first,last); the move_backward function should be used instead. + * + * Note that the end of the output range is permitted to be contained + * within [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _OI + move(_II __first, _II __last, _OI __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II>) + __glibcxx_function_requires(_OutputIteratorConcept<_OI, + typename iterator_traits<_II>::value_type>) + __glibcxx_requires_can_increment_range(__first, __last, __result); + + return std::__copy_move_a(std::__miter_base(__first), + std::__miter_base(__last), __result); + } + +#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::move(_Tp, _Up, _Vp) +#else +#define _GLIBCXX_MOVE3(_Tp, _Up, _Vp) std::copy(_Tp, _Up, _Vp) +#endif + + template + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + while (__first != __last) + *--__result = *--__last; + return __result; + } + }; + +#if __cplusplus >= 201103L + template + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + while (__first != __last) + *--__result = std::move(*--__last); + return __result; + } + }; +#endif + + template<> + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + typename iterator_traits<_BI1>::difference_type + __n = __last - __first; + for (; __n > 0; --__n) + *--__result = *--__last; + return __result; + } + }; + +#if __cplusplus >= 201103L + template<> + struct __copy_move_backward + { + template + _GLIBCXX20_CONSTEXPR + static _BI2 + __copy_move_b(_BI1 __first, _BI1 __last, _BI2 __result) + { + typename iterator_traits<_BI1>::difference_type + __n = __last - __first; + for (; __n > 0; --__n) + *--__result = std::move(*--__last); + return __result; + } + }; +#endif + + template + struct __copy_move_backward<_IsMove, true, random_access_iterator_tag> + { + template + _GLIBCXX20_CONSTEXPR + static _Tp* + __copy_move_b(const _Tp* __first, const _Tp* __last, _Tp* __result) + { +#if __cplusplus >= 201103L + using __assignable = conditional<_IsMove, + is_move_assignable<_Tp>, + is_copy_assignable<_Tp>>; + // trivial types can have deleted assignment + static_assert( __assignable::type::value, "type is not assignable" ); +#endif + const ptrdiff_t _Num = __last - __first; + if (_Num) + __builtin_memmove(__result - _Num, __first, sizeof(_Tp) * _Num); + return __result - _Num; + } + }; + + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + __copy_move_backward_a2(_BI1 __first, _BI1 __last, _BI2 __result) + { + typedef typename iterator_traits<_BI1>::iterator_category _Category; +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return std::__copy_move_backward<_IsMove, false, _Category>:: + __copy_move_b(__first, __last, __result); +#endif + return std::__copy_move_backward<_IsMove, + __memcpyable<_BI2, _BI1>::__value, + _Category>::__copy_move_b(__first, + __last, + __result); + } + + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + __copy_move_backward_a1(_BI1 __first, _BI1 __last, _BI2 __result) + { return std::__copy_move_backward_a2<_IsMove>(__first, __last, __result); } + + template + _OI + __copy_move_backward_a1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _OI); + + template + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*> + __copy_move_backward_a1( + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_ITp, _IRef, _IPtr>, + _GLIBCXX_STD_C::_Deque_iterator<_OTp, _OTp&, _OTp*>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*> >::__type + __copy_move_backward_a1(_II, _II, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>); + + template + _GLIBCXX20_CONSTEXPR + inline _OI + __copy_move_backward_a(_II __first, _II __last, _OI __result) + { + return std::__niter_wrap(__result, + std::__copy_move_backward_a1<_IsMove> + (std::__niter_base(__first), std::__niter_base(__last), + std::__niter_base(__result))); + } + + /** + * @brief Copies the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result A bidirectional iterator. + * @return result - (last - first) + * + * The function has the same effect as copy, but starts at the end of the + * range and works its way to the start, returning the start of the result. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + * + * Result may not be in the range (first,last]. Use copy instead. Note + * that the start of the output range may overlap [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + copy_backward(_BI1 __first, _BI1 __last, _BI2 __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) + __glibcxx_function_requires(_ConvertibleConcept< + typename iterator_traits<_BI1>::value_type, + typename iterator_traits<_BI2>::value_type>) + __glibcxx_requires_can_decrement_range(__first, __last, __result); + + return std::__copy_move_backward_a<__is_move_iterator<_BI1>::__value> + (std::__miter_base(__first), std::__miter_base(__last), __result); + } + +#if __cplusplus >= 201103L + /** + * @brief Moves the range [first,last) into result. + * @ingroup mutating_algorithms + * @param __first A bidirectional iterator. + * @param __last A bidirectional iterator. + * @param __result A bidirectional iterator. + * @return result - (last - first) + * + * The function has the same effect as move, but starts at the end of the + * range and works its way to the start, returning the start of the result. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + * + * Result may not be in the range (first,last]. Use move instead. Note + * that the start of the output range may overlap [first,last). + */ + template + _GLIBCXX20_CONSTEXPR + inline _BI2 + move_backward(_BI1 __first, _BI1 __last, _BI2 __result) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept<_BI1>) + __glibcxx_function_requires(_Mutable_BidirectionalIteratorConcept<_BI2>) + __glibcxx_function_requires(_ConvertibleConcept< + typename iterator_traits<_BI1>::value_type, + typename iterator_traits<_BI2>::value_type>) + __glibcxx_requires_can_decrement_range(__first, __last, __result); + + return std::__copy_move_backward_a(std::__miter_base(__first), + std::__miter_base(__last), + __result); + } + +#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::move_backward(_Tp, _Up, _Vp) +#else +#define _GLIBCXX_MOVE_BACKWARD3(_Tp, _Up, _Vp) std::copy_backward(_Tp, _Up, _Vp) +#endif + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if::__value, void>::__type + __fill_a1(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + for (; __first != __last; ++__first) + *__first = __value; + } + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, void>::__type + __fill_a1(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __value) + { + const _Tp __tmp = __value; + for (; __first != __last; ++__first) + *__first = __tmp; + } + + // Specialization: for char types we can use memset. + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_byte<_Tp>::__value, void>::__type + __fill_a1(_Tp* __first, _Tp* __last, const _Tp& __c) + { + const _Tp __tmp = __c; +#if __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + { + for (; __first != __last; ++__first) + *__first = __tmp; + return; + } +#endif + if (const size_t __len = __last - __first) + __builtin_memset(__first, static_cast(__tmp), __len); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __fill_a1(::__gnu_cxx::__normal_iterator<_Ite, _Cont> __first, + ::__gnu_cxx::__normal_iterator<_Ite, _Cont> __last, + const _Tp& __value) + { std::__fill_a1(__first.base(), __last.base(), __value); } + + template + void + __fill_a1(const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&, + const _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Tp&, _Tp*>&, + const _VTp&); + + template + _GLIBCXX20_CONSTEXPR + inline void + __fill_a(_FIte __first, _FIte __last, const _Tp& __value) + { std::__fill_a1(__first, __last, __value); } + + /** + * @brief Fills the range [first,last) with copies of value. + * @ingroup mutating_algorithms + * @param __first A forward iterator. + * @param __last A forward iterator. + * @param __value A reference-to-const of arbitrary type. + * @return Nothing. + * + * This function fills a range with copies of the same value. For char + * types filling contiguous areas of memory, this becomes an inline call + * to @c memset or @c wmemset. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + fill(_ForwardIterator __first, _ForwardIterator __last, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_requires_valid_range(__first, __last); + + std::__fill_a(__first, __last, __value); + } + + // Used by fill_n, generate_n, etc. to convert _Size to an integral type: + inline _GLIBCXX_CONSTEXPR int + __size_to_integer(int __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned + __size_to_integer(unsigned __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long + __size_to_integer(long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned long + __size_to_integer(unsigned long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(long long __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned long long + __size_to_integer(unsigned long long __n) { return __n; } + +#if defined(__GLIBCXX_TYPE_INT_N_0) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_0 + __size_to_integer(__GLIBCXX_TYPE_INT_N_0 __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_0 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_0 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_1 + __size_to_integer(__GLIBCXX_TYPE_INT_N_1 __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_1 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_1 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_2 + __size_to_integer(__GLIBCXX_TYPE_INT_N_2 __n) { return __n; } + inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_2 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_2 __n) { return __n; } +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + inline _GLIBCXX_CONSTEXPR unsigned __GLIBCXX_TYPE_INT_N_3 + __size_to_integer(__GLIBCXX_TYPE_INT_N_3 __n) { return __n; } + inline _GLIBCXX_CONSTEXPR __GLIBCXX_TYPE_INT_N_3 + __size_to_integer(unsigned __GLIBCXX_TYPE_INT_N_3 __n) { return __n; } +#endif + + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(float __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(double __n) { return __n; } + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(long double __n) { return __n; } +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + inline _GLIBCXX_CONSTEXPR long long + __size_to_integer(__float128 __n) { return __n; } +#endif + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if::__value, _OutputIterator>::__type + __fill_n_a1(_OutputIterator __first, _Size __n, const _Tp& __value) + { + for (; __n > 0; --__n, (void) ++__first) + *__first = __value; + return __first; + } + + template + _GLIBCXX20_CONSTEXPR + inline typename + __gnu_cxx::__enable_if<__is_scalar<_Tp>::__value, _OutputIterator>::__type + __fill_n_a1(_OutputIterator __first, _Size __n, const _Tp& __value) + { + const _Tp __tmp = __value; + for (; __n > 0; --__n, (void) ++__first) + *__first = __tmp; + return __first; + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::output_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + return __fill_n_a1(__first, __n, __value); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::input_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + return __fill_n_a1(__first, __n, __value); + } + + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + __fill_n_a(_OutputIterator __first, _Size __n, const _Tp& __value, + std::random_access_iterator_tag) + { +#if __cplusplus >= 201103L + static_assert(is_integral<_Size>{}, "fill_n must pass integral size"); +#endif + if (__n <= 0) + return __first; + + __glibcxx_requires_can_increment(__first, __n); + + std::__fill_a(__first, __first + __n, __value); + return __first + __n; + } + + /** + * @brief Fills the range [first,first+n) with copies of value. + * @ingroup mutating_algorithms + * @param __first An output iterator. + * @param __n The count of copies to perform. + * @param __value A reference-to-const of arbitrary type. + * @return The iterator at first+n. + * + * This function fills a range with copies of the same value. For char + * types filling contiguous areas of memory, this becomes an inline call + * to @c memset or @c wmemset. + * + * If @p __n is negative, the function does nothing. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 865. More algorithms that throw away information + // DR 426. search_n(), fill_n(), and generate_n() with negative n + template + _GLIBCXX20_CONSTEXPR + inline _OI + fill_n(_OI __first, _Size __n, const _Tp& __value) + { + // concept requirements + __glibcxx_function_requires(_OutputIteratorConcept<_OI, _Tp>) + + return std::__fill_n_a(__first, std::__size_to_integer(__n), __value, + std::__iterator_category(__first)); + } + + template + struct __equal + { + template + _GLIBCXX20_CONSTEXPR + static bool + equal(_II1 __first1, _II1 __last1, _II2 __first2) + { + for (; __first1 != __last1; ++__first1, (void) ++__first2) + if (!(*__first1 == *__first2)) + return false; + return true; + } + }; + + template<> + struct __equal + { + template + _GLIBCXX20_CONSTEXPR + static bool + equal(const _Tp* __first1, const _Tp* __last1, const _Tp* __first2) + { + if (const size_t __len = (__last1 - __first1)) + return !std::__memcmp(__first1, __first2, __len); + return true; + } + }; + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>, + _II); + + template + bool + __equal_aux1(_GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp1, _Ref1, _Ptr1>, + _GLIBCXX_STD_C::_Deque_iterator<_Tp2, _Ref2, _Ptr2>); + + template + typename __gnu_cxx::__enable_if< + __is_random_access_iter<_II>::__value, bool>::__type + __equal_aux1(_II, _II, + _GLIBCXX_STD_C::_Deque_iterator<_Tp, _Ref, _Ptr>); + + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal_aux1(_II1 __first1, _II1 __last1, _II2 __first2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + const bool __simple = ((__is_integer<_ValueType1>::__value + || __is_pointer<_ValueType1>::__value) + && __memcmpable<_II1, _II2>::__value); + return std::__equal<__simple>::equal(__first1, __last1, __first2); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal_aux(_II1 __first1, _II1 __last1, _II2 __first2) + { + return std::__equal_aux1(std::__niter_base(__first1), + std::__niter_base(__last1), + std::__niter_base(__first2)); + } + + template + struct __lc_rai + { + template + _GLIBCXX20_CONSTEXPR + static _II1 + __newlast1(_II1, _II1 __last1, _II2, _II2) + { return __last1; } + + template + _GLIBCXX20_CONSTEXPR + static bool + __cnd2(_II __first, _II __last) + { return __first != __last; } + }; + + template<> + struct __lc_rai + { + template + _GLIBCXX20_CONSTEXPR + static _RAI1 + __newlast1(_RAI1 __first1, _RAI1 __last1, + _RAI2 __first2, _RAI2 __last2) + { + const typename iterator_traits<_RAI1>::difference_type + __diff1 = __last1 - __first1; + const typename iterator_traits<_RAI2>::difference_type + __diff2 = __last2 - __first2; + return __diff2 < __diff1 ? __first1 + __diff2 : __last1; + } + + template + static _GLIBCXX20_CONSTEXPR bool + __cnd2(_RAI, _RAI) + { return true; } + }; + + template + _GLIBCXX20_CONSTEXPR + bool + __lexicographical_compare_impl(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2, + _Compare __comp) + { + typedef typename iterator_traits<_II1>::iterator_category _Category1; + typedef typename iterator_traits<_II2>::iterator_category _Category2; + typedef std::__lc_rai<_Category1, _Category2> __rai_type; + + __last1 = __rai_type::__newlast1(__first1, __last1, __first2, __last2); + for (; __first1 != __last1 && __rai_type::__cnd2(__first2, __last2); + ++__first1, (void)++__first2) + { + if (__comp(__first1, __first2)) + return true; + if (__comp(__first2, __first1)) + return false; + } + return __first1 == __last1 && __first2 != __last2; + } + + template + struct __lexicographical_compare + { + template + _GLIBCXX20_CONSTEXPR + static bool + __lc(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + using __gnu_cxx::__ops::__iter_less_iter; + return std::__lexicographical_compare_impl(__first1, __last1, + __first2, __last2, + __iter_less_iter()); + } + }; + + template<> + struct __lexicographical_compare + { + template + _GLIBCXX20_CONSTEXPR + static bool + __lc(const _Tp* __first1, const _Tp* __last1, + const _Up* __first2, const _Up* __last2) + { + const size_t __len1 = __last1 - __first1; + const size_t __len2 = __last2 - __first2; + if (const size_t __len = std::min(__len1, __len2)) + if (int __result = std::__memcmp(__first1, __first2, __len)) + return __result < 0; + return __len1 < __len2; + } + }; + + template + _GLIBCXX20_CONSTEXPR + inline bool + __lexicographical_compare_aux(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; + const bool __simple = + (__is_memcmp_ordered_with<_ValueType1, _ValueType2>::__value + && __is_pointer<_II1>::__value + && __is_pointer<_II2>::__value +#if __cplusplus > 201703L && __cpp_lib_concepts + // For C++20 iterator_traits::value_type is non-volatile + // so __is_byte could be true, but we can't use memcmp with + // volatile data. + && !is_volatile_v>> + && !is_volatile_v>> +#endif + ); + + return std::__lexicographical_compare<__simple>::__lc(__first1, __last1, + __first2, __last2); + } + + template + _GLIBCXX20_CONSTEXPR + _ForwardIterator + __lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val, _Compare __comp) + { + typedef typename iterator_traits<_ForwardIterator>::difference_type + _DistanceType; + + _DistanceType __len = std::distance(__first, __last); + + while (__len > 0) + { + _DistanceType __half = __len >> 1; + _ForwardIterator __middle = __first; + std::advance(__middle, __half); + if (__comp(__middle, __val)) + { + __first = __middle; + ++__first; + __len = __len - __half - 1; + } + else + __len = __half; + } + return __first; + } + + /** + * @brief Finds the first position in which @a val could be inserted + * without changing the ordering. + * @param __first An iterator. + * @param __last Another iterator. + * @param __val The search term. + * @return An iterator pointing to the first element not less + * than @a val, or end() if every element is less than + * @a val. + * @ingroup binary_search_algorithms + */ + template + _GLIBCXX20_CONSTEXPR + inline _ForwardIterator + lower_bound(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __val) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanOpConcept< + typename iterator_traits<_ForwardIterator>::value_type, _Tp>) + __glibcxx_requires_partitioned_lower(__first, __last, __val); + + return std::__lower_bound(__first, __last, __val, + __gnu_cxx::__ops::__iter_less_val()); + } + + /// This is a helper function for the sort routines and for random.tcc. + // Precondition: __n > 0. + inline _GLIBCXX_CONSTEXPR int + __lg(int __n) + { return (int)sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } + + inline _GLIBCXX_CONSTEXPR unsigned + __lg(unsigned __n) + { return (int)sizeof(int) * __CHAR_BIT__ - 1 - __builtin_clz(__n); } + + inline _GLIBCXX_CONSTEXPR long + __lg(long __n) + { return (int)sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } + + inline _GLIBCXX_CONSTEXPR unsigned long + __lg(unsigned long __n) + { return (int)sizeof(long) * __CHAR_BIT__ - 1 - __builtin_clzl(__n); } + + inline _GLIBCXX_CONSTEXPR long long + __lg(long long __n) + { return (int)sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } + + inline _GLIBCXX_CONSTEXPR unsigned long long + __lg(unsigned long long __n) + { return (int)sizeof(long long) * __CHAR_BIT__ - 1 - __builtin_clzll(__n); } + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @return A boolean true or false. + * + * This compares the elements of two ranges using @c == and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + equal(_II1 __first1, _II1 __last1, _II2 __first2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_II1>::value_type, + typename iterator_traits<_II2>::value_type>) + __glibcxx_requires_can_increment_range(__first1, __last1, __first2); + + return std::__equal_aux(__first1, __last1, __first2); + } + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A boolean true or false. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + equal(_IIter1 __first1, _IIter1 __last1, + _IIter2 __first2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!bool(__binary_pred(*__first1, *__first2))) + return false; + return true; + } + +#if __cplusplus >= 201103L + // 4-iterator version of std::equal for use in C++11. + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + using _RATag = random_access_iterator_tag; + using _Cat1 = typename iterator_traits<_II1>::iterator_category; + using _Cat2 = typename iterator_traits<_II2>::iterator_category; + using _RAIters = __and_, is_same<_Cat2, _RATag>>; + if (_RAIters()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + return _GLIBCXX_STD_A::equal(__first1, __last1, __first2); + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!(*__first1 == *__first2)) + return false; + return __first1 == __last1 && __first2 == __last2; + } + + // 4-iterator version of std::equal for use in C++11. + template + _GLIBCXX20_CONSTEXPR + inline bool + __equal4(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2, + _BinaryPredicate __binary_pred) + { + using _RATag = random_access_iterator_tag; + using _Cat1 = typename iterator_traits<_II1>::iterator_category; + using _Cat2 = typename iterator_traits<_II2>::iterator_category; + using _RAIters = __and_, is_same<_Cat2, _RATag>>; + if (_RAIters()) + { + auto __d1 = std::distance(__first1, __last1); + auto __d2 = std::distance(__first2, __last2); + if (__d1 != __d2) + return false; + return _GLIBCXX_STD_A::equal(__first1, __last1, __first2, + __binary_pred); + } + + for (; __first1 != __last1 && __first2 != __last2; + ++__first1, (void)++__first2) + if (!bool(__binary_pred(*__first1, *__first2))) + return false; + return __first1 == __last1 && __first2 == __last2; + } +#endif // C++11 + +#if __cplusplus > 201103L + +#define __cpp_lib_robust_nonmodifying_seq_ops 201304 + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A boolean true or false. + * + * This compares the elements of two ranges using @c == and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + equal(_II1 __first1, _II1 __last1, _II2 __first2, _II2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_II1>::value_type, + typename iterator_traits<_II2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2); + } + + /** + * @brief Tests a range for element-wise equality. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A boolean true or false. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns true or + * false depending on whether all of the corresponding elements of the + * ranges are equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + equal(_IIter1 __first1, _IIter1 __last1, + _IIter2 __first2, _IIter2 __last2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_IIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_IIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__equal4(__first1, __last1, __first2, __last2, + __binary_pred); + } +#endif // C++14 + + /** + * @brief Performs @b dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A boolean true or false. + * + * Returns true if the sequence of elements defined by the range + * [first1,last1) is lexicographically less than the sequence of elements + * defined by the range [first2,last2). Returns false otherwise. + * (Quoted from [25.3.8]/1.) If the iterators are all character pointers, + * then this is an inline call to @c memcmp. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + lexicographical_compare(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2) + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename iterator_traits<_II1>::value_type _ValueType1; + typedef typename iterator_traits<_II2>::value_type _ValueType2; +#endif + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_function_requires(_LessThanOpConcept<_ValueType1, _ValueType2>) + __glibcxx_function_requires(_LessThanOpConcept<_ValueType2, _ValueType1>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__lexicographical_compare_aux(std::__niter_base(__first1), + std::__niter_base(__last1), + std::__niter_base(__first2), + std::__niter_base(__last2)); + } + + /** + * @brief Performs @b dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return A boolean true or false. + * + * The same as the four-parameter @c lexicographical_compare, but uses the + * comp parameter instead of @c <. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + lexicographical_compare(_II1 __first1, _II1 __last1, + _II2 __first2, _II2 __last2, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_II1>) + __glibcxx_function_requires(_InputIteratorConcept<_II2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return std::__lexicographical_compare_impl + (__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__comp)); + } + +#if __cpp_lib_three_way_comparison + // Iter points to a contiguous range of unsigned narrow character type + // or std::byte, suitable for comparison by memcmp. + template + concept __is_byte_iter = contiguous_iterator<_Iter> + && __is_memcmp_ordered>::__value; + + // Return a struct with two members, initialized to the smaller of x and y + // (or x if they compare equal) and the result of the comparison x <=> y. + template + constexpr auto + __min_cmp(_Tp __x, _Tp __y) + { + struct _Res { + _Tp _M_min; + decltype(__x <=> __y) _M_cmp; + }; + auto __c = __x <=> __y; + if (__c > 0) + return _Res{__y, __c}; + return _Res{__x, __c}; + } + + /** + * @brief Performs dictionary comparison on ranges. + * @ingroup sorting_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __comp A @link comparison_functors comparison functor@endlink. + * @return The comparison category that `__comp(*__first1, *__first2)` + * returns. + */ + template + constexpr auto + lexicographical_compare_three_way(_InputIter1 __first1, + _InputIter1 __last1, + _InputIter2 __first2, + _InputIter2 __last2, + _Comp __comp) + -> decltype(__comp(*__first1, *__first2)) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIter1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIter2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + +#if __cpp_lib_is_constant_evaluated + using _Cat = decltype(__comp(*__first1, *__first2)); + static_assert(same_as, _Cat>); + + if (!std::is_constant_evaluated()) + if constexpr (same_as<_Comp, __detail::_Synth3way> + || same_as<_Comp, compare_three_way>) + if constexpr (__is_byte_iter<_InputIter1>) + if constexpr (__is_byte_iter<_InputIter2>) + { + const auto [__len, __lencmp] + = std::__min_cmp(__last1 - __first1, __last2 - __first2); + if (__len) + { + const auto __c + = __builtin_memcmp(&*__first1, &*__first2, __len) <=> 0; + if (__c != 0) + return __c; + } + return __lencmp; + } +#endif // is_constant_evaluated + while (__first1 != __last1) + { + if (__first2 == __last2) + return strong_ordering::greater; + if (auto __cmp = __comp(*__first1, *__first2); __cmp != 0) + return __cmp; + ++__first1; + ++__first2; + } + return (__first2 == __last2) <=> true; // See PR 94006 + } + + template + constexpr auto + lexicographical_compare_three_way(_InputIter1 __first1, + _InputIter1 __last1, + _InputIter2 __first2, + _InputIter2 __last2) + { + return std::lexicographical_compare_three_way(__first1, __last1, + __first2, __last2, + compare_three_way{}); + } +#endif // three_way_comparison + + template + _GLIBCXX20_CONSTEXPR + pair<_InputIterator1, _InputIterator2> + __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _BinaryPredicate __binary_pred) + { + while (__first1 != __last1 && __binary_pred(__first1, __first2)) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using @c == and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } + +#if __cplusplus > 201103L + + template + _GLIBCXX20_CONSTEXPR + pair<_InputIterator1, _InputIterator2> + __mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __binary_pred) + { + while (__first1 != __last1 && __first2 != __last2 + && __binary_pred(__first1, __first2)) + { + ++__first1; + ++__first2; + } + return pair<_InputIterator1, _InputIterator2>(__first1, __first2); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using @c == and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_InputIterator1>::value_type, + typename iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } + + /** + * @brief Finds the places in ranges which don't match. + * @ingroup non_mutating_algorithms + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @param __binary_pred A binary predicate @link functors + * functor@endlink. + * @return A pair of iterators pointing to the first mismatch. + * + * This compares the elements of two ranges using the binary_pred + * parameter, and returns a pair + * of iterators. The first iterator points into the first range, the + * second iterator points into the second range, and the elements pointed + * to by the iterators are not equal. + */ + template + _GLIBCXX20_CONSTEXPR + inline pair<_InputIterator1, _InputIterator2> + mismatch(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _InputIterator2 __last2, + _BinaryPredicate __binary_pred) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return _GLIBCXX_STD_A::__mismatch(__first1, __last1, __first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__binary_pred)); + } +#endif + +_GLIBCXX_END_NAMESPACE_ALGO + + /// This is an overload used by find algos for the Input Iterator case. + template + _GLIBCXX20_CONSTEXPR + inline _InputIterator + __find_if(_InputIterator __first, _InputIterator __last, + _Predicate __pred, input_iterator_tag) + { + while (__first != __last && !__pred(__first)) + ++__first; + return __first; + } + + /// This is an overload used by find algos for the RAI case. + template + _GLIBCXX20_CONSTEXPR + _RandomAccessIterator + __find_if(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Predicate __pred, random_access_iterator_tag) + { + typename iterator_traits<_RandomAccessIterator>::difference_type + __trip_count = (__last - __first) >> 2; + + for (; __trip_count > 0; --__trip_count) + { + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + + if (__pred(__first)) + return __first; + ++__first; + } + + switch (__last - __first) + { + case 3: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 2: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 1: + if (__pred(__first)) + return __first; + ++__first; + // FALLTHRU + case 0: + default: + return __last; + } + } + + template + _GLIBCXX20_CONSTEXPR + inline _Iterator + __find_if(_Iterator __first, _Iterator __last, _Predicate __pred) + { + return __find_if(__first, __last, __pred, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + __count_if(_InputIterator __first, _InputIterator __last, _Predicate __pred) + { + typename iterator_traits<_InputIterator>::difference_type __n = 0; + for (; __first != __last; ++__first) + if (__pred(__first)) + ++__n; + return __n; + } + +#if __cplusplus >= 201103L + template + _GLIBCXX20_CONSTEXPR + bool + __is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2, _BinaryPredicate __pred) + { + // Efficiently compare identical prefixes: O(N) if sequences + // have the same elements in the same order. + for (; __first1 != __last1; ++__first1, (void)++__first2) + if (!__pred(__first1, __first2)) + break; + + if (__first1 == __last1) + return true; + + // Establish __last2 assuming equal ranges by iterating over the + // rest of the list. + _ForwardIterator2 __last2 = __first2; + std::advance(__last2, std::distance(__first1, __last1)); + for (_ForwardIterator1 __scan = __first1; __scan != __last1; ++__scan) + { + if (__scan != std::__find_if(__first1, __scan, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan))) + continue; // We've seen this one before. + + auto __matches + = std::__count_if(__first2, __last2, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)); + if (0 == __matches || + std::__count_if(__scan, __last1, + __gnu_cxx::__ops::__iter_comp_iter(__pred, __scan)) + != __matches) + return false; + } + return true; + } + + /** + * @brief Checks whether a permutation of the second sequence is equal + * to the first sequence. + * @ingroup non_mutating_algorithms + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @return true if there exists a permutation of the elements in the range + * [__first2, __first2 + (__last1 - __first1)), beginning with + * ForwardIterator2 begin, such that equal(__first1, __last1, begin) + * returns true; otherwise, returns false. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_permutation(_ForwardIterator1 __first1, _ForwardIterator1 __last1, + _ForwardIterator2 __first2) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator1>) + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator2>) + __glibcxx_function_requires(_EqualOpConcept< + typename iterator_traits<_ForwardIterator1>::value_type, + typename iterator_traits<_ForwardIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + + return std::__is_permutation(__first1, __last1, __first2, + __gnu_cxx::__ops::__iter_equal_to_iter()); + } +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h b/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h new file mode 100644 index 000000000..f245e52b2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_bvector.h @@ -0,0 +1,1363 @@ +// vector specialization -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1999 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_bvector.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{vector} + */ + +#ifndef _STL_BVECTOR_H +#define _STL_BVECTOR_H 1 + +#if __cplusplus >= 201103L +#include +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + typedef unsigned long _Bit_type; + enum { _S_word_bit = int(__CHAR_BIT__ * sizeof(_Bit_type)) }; + + struct _Bit_reference + { + _Bit_type * _M_p; + _Bit_type _M_mask; + + _Bit_reference(_Bit_type * __x, _Bit_type __y) + : _M_p(__x), _M_mask(__y) { } + + _Bit_reference() _GLIBCXX_NOEXCEPT : _M_p(0), _M_mask(0) { } + +#if __cplusplus >= 201103L + _Bit_reference(const _Bit_reference&) = default; +#endif + + operator bool() const _GLIBCXX_NOEXCEPT + { return !!(*_M_p & _M_mask); } + + _Bit_reference& + operator=(bool __x) _GLIBCXX_NOEXCEPT + { + if (__x) + *_M_p |= _M_mask; + else + *_M_p &= ~_M_mask; + return *this; + } + + _Bit_reference& + operator=(const _Bit_reference& __x) _GLIBCXX_NOEXCEPT + { return *this = bool(__x); } + + bool + operator==(const _Bit_reference& __x) const + { return bool(*this) == bool(__x); } + + bool + operator<(const _Bit_reference& __x) const + { return !bool(*this) && bool(__x); } + + void + flip() _GLIBCXX_NOEXCEPT + { *_M_p ^= _M_mask; } + }; + +#if __cplusplus >= 201103L + inline void + swap(_Bit_reference __x, _Bit_reference __y) noexcept + { + bool __tmp = __x; + __x = __y; + __y = __tmp; + } + + inline void + swap(_Bit_reference __x, bool& __y) noexcept + { + bool __tmp = __x; + __x = __y; + __y = __tmp; + } + + inline void + swap(bool& __x, _Bit_reference __y) noexcept + { + bool __tmp = __x; + __x = __y; + __y = __tmp; + } +#endif + + struct _Bit_iterator_base + : public std::iterator + { + _Bit_type * _M_p; + unsigned int _M_offset; + + _Bit_iterator_base(_Bit_type * __x, unsigned int __y) + : _M_p(__x), _M_offset(__y) { } + + void + _M_bump_up() + { + if (_M_offset++ == int(_S_word_bit) - 1) + { + _M_offset = 0; + ++_M_p; + } + } + + void + _M_bump_down() + { + if (_M_offset-- == 0) + { + _M_offset = int(_S_word_bit) - 1; + --_M_p; + } + } + + void + _M_incr(ptrdiff_t __i) + { + difference_type __n = __i + _M_offset; + _M_p += __n / int(_S_word_bit); + __n = __n % int(_S_word_bit); + if (__n < 0) + { + __n += int(_S_word_bit); + --_M_p; + } + _M_offset = static_cast(__n); + } + + friend _GLIBCXX20_CONSTEXPR bool + operator==(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return __x._M_p == __y._M_p && __x._M_offset == __y._M_offset; } + +#if __cpp_lib_three_way_comparison + friend constexpr strong_ordering + operator<=>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + noexcept + { + if (const auto __cmp = __x._M_p <=> __y._M_p; __cmp != 0) + return __cmp; + return __x._M_offset <=> __y._M_offset; + } +#else + friend bool + operator<(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { + return __x._M_p < __y._M_p + || (__x._M_p == __y._M_p && __x._M_offset < __y._M_offset); + } + + friend bool + operator!=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return !(__x == __y); } + + friend bool + operator>(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return __y < __x; } + + friend bool + operator<=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return !(__y < __x); } + + friend bool + operator>=(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { return !(__x < __y); } +#endif // three-way comparison + + friend ptrdiff_t + operator-(const _Bit_iterator_base& __x, const _Bit_iterator_base& __y) + { + return (int(_S_word_bit) * (__x._M_p - __y._M_p) + + __x._M_offset - __y._M_offset); + } + }; + + struct _Bit_iterator : public _Bit_iterator_base + { + typedef _Bit_reference reference; +#if __cplusplus > 201703L + typedef void pointer; +#else + typedef _Bit_reference* pointer; +#endif + typedef _Bit_iterator iterator; + + _Bit_iterator() : _Bit_iterator_base(0, 0) { } + + _Bit_iterator(_Bit_type * __x, unsigned int __y) + : _Bit_iterator_base(__x, __y) { } + + iterator + _M_const_cast() const + { return *this; } + + reference + operator*() const + { return reference(_M_p, 1UL << _M_offset); } + + iterator& + operator++() + { + _M_bump_up(); + return *this; + } + + iterator + operator++(int) + { + iterator __tmp = *this; + _M_bump_up(); + return __tmp; + } + + iterator& + operator--() + { + _M_bump_down(); + return *this; + } + + iterator + operator--(int) + { + iterator __tmp = *this; + _M_bump_down(); + return __tmp; + } + + iterator& + operator+=(difference_type __i) + { + _M_incr(__i); + return *this; + } + + iterator& + operator-=(difference_type __i) + { + *this += -__i; + return *this; + } + + reference + operator[](difference_type __i) const + { return *(*this + __i); } + + friend iterator + operator+(const iterator& __x, difference_type __n) + { + iterator __tmp = __x; + __tmp += __n; + return __tmp; + } + + friend iterator + operator+(difference_type __n, const iterator& __x) + { return __x + __n; } + + friend iterator + operator-(const iterator& __x, difference_type __n) + { + iterator __tmp = __x; + __tmp -= __n; + return __tmp; + } + }; + + struct _Bit_const_iterator : public _Bit_iterator_base + { + typedef bool reference; + typedef bool const_reference; +#if __cplusplus > 201703L + typedef void pointer; +#else + typedef const bool* pointer; +#endif + typedef _Bit_const_iterator const_iterator; + + _Bit_const_iterator() : _Bit_iterator_base(0, 0) { } + + _Bit_const_iterator(_Bit_type * __x, unsigned int __y) + : _Bit_iterator_base(__x, __y) { } + + _Bit_const_iterator(const _Bit_iterator& __x) + : _Bit_iterator_base(__x._M_p, __x._M_offset) { } + + _Bit_iterator + _M_const_cast() const + { return _Bit_iterator(_M_p, _M_offset); } + + const_reference + operator*() const + { return _Bit_reference(_M_p, 1UL << _M_offset); } + + const_iterator& + operator++() + { + _M_bump_up(); + return *this; + } + + const_iterator + operator++(int) + { + const_iterator __tmp = *this; + _M_bump_up(); + return __tmp; + } + + const_iterator& + operator--() + { + _M_bump_down(); + return *this; + } + + const_iterator + operator--(int) + { + const_iterator __tmp = *this; + _M_bump_down(); + return __tmp; + } + + const_iterator& + operator+=(difference_type __i) + { + _M_incr(__i); + return *this; + } + + const_iterator& + operator-=(difference_type __i) + { + *this += -__i; + return *this; + } + + const_reference + operator[](difference_type __i) const + { return *(*this + __i); } + + friend const_iterator + operator+(const const_iterator& __x, difference_type __n) + { + const_iterator __tmp = __x; + __tmp += __n; + return __tmp; + } + + friend const_iterator + operator-(const const_iterator& __x, difference_type __n) + { + const_iterator __tmp = __x; + __tmp -= __n; + return __tmp; + } + + friend const_iterator + operator+(difference_type __n, const const_iterator& __x) + { return __x + __n; } + }; + + inline void + __fill_bvector(_Bit_type * __v, + unsigned int __first, unsigned int __last, bool __x) + { + const _Bit_type __fmask = ~0ul << __first; + const _Bit_type __lmask = ~0ul >> (_S_word_bit - __last); + const _Bit_type __mask = __fmask & __lmask; + + if (__x) + *__v |= __mask; + else + *__v &= ~__mask; + } + + inline void + fill(_Bit_iterator __first, _Bit_iterator __last, const bool& __x) + { + if (__first._M_p != __last._M_p) + { + _Bit_type* __first_p = __first._M_p; + if (__first._M_offset != 0) + __fill_bvector(__first_p++, __first._M_offset, _S_word_bit, __x); + + __builtin_memset(__first_p, __x ? ~0 : 0, + (__last._M_p - __first_p) * sizeof(_Bit_type)); + + if (__last._M_offset != 0) + __fill_bvector(__last._M_p, 0, __last._M_offset, __x); + } + else if (__first._M_offset != __last._M_offset) + __fill_bvector(__first._M_p, __first._M_offset, __last._M_offset, __x); + } + + template + struct _Bvector_base + { + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Bit_type>::other _Bit_alloc_type; + typedef typename __gnu_cxx::__alloc_traits<_Bit_alloc_type> + _Bit_alloc_traits; + typedef typename _Bit_alloc_traits::pointer _Bit_pointer; + + struct _Bvector_impl_data + { + _Bit_iterator _M_start; + _Bit_iterator _M_finish; + _Bit_pointer _M_end_of_storage; + + _Bvector_impl_data() _GLIBCXX_NOEXCEPT + : _M_start(), _M_finish(), _M_end_of_storage() + { } + +#if __cplusplus >= 201103L + _Bvector_impl_data(_Bvector_impl_data&& __x) noexcept + : _M_start(__x._M_start), _M_finish(__x._M_finish) + , _M_end_of_storage(__x._M_end_of_storage) + { __x._M_reset(); } + + void + _M_move_data(_Bvector_impl_data&& __x) noexcept + { + this->_M_start = __x._M_start; + this->_M_finish = __x._M_finish; + this->_M_end_of_storage = __x._M_end_of_storage; + __x._M_reset(); + } +#endif + + void + _M_reset() _GLIBCXX_NOEXCEPT + { + _M_start = _M_finish = _Bit_iterator(); + _M_end_of_storage = _Bit_pointer(); + } + }; + + struct _Bvector_impl + : public _Bit_alloc_type, public _Bvector_impl_data + { + public: + _Bvector_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Bit_alloc_type>::value) + : _Bit_alloc_type() + { } + + _Bvector_impl(const _Bit_alloc_type& __a) _GLIBCXX_NOEXCEPT + : _Bit_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + _Bvector_impl(_Bvector_impl&&) = default; +#endif + + _Bit_type* + _M_end_addr() const _GLIBCXX_NOEXCEPT + { + if (this->_M_end_of_storage) + return std::__addressof(this->_M_end_of_storage[-1]) + 1; + return 0; + } + }; + + public: + typedef _Alloc allocator_type; + + _Bit_alloc_type& + _M_get_Bit_allocator() _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + const _Bit_alloc_type& + _M_get_Bit_allocator() const _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_get_Bit_allocator()); } + +#if __cplusplus >= 201103L + _Bvector_base() = default; +#else + _Bvector_base() { } +#endif + + _Bvector_base(const allocator_type& __a) + : _M_impl(__a) { } + +#if __cplusplus >= 201103L + _Bvector_base(_Bvector_base&&) = default; +#endif + + ~_Bvector_base() + { this->_M_deallocate(); } + + protected: + _Bvector_impl _M_impl; + + _Bit_pointer + _M_allocate(size_t __n) + { return _Bit_alloc_traits::allocate(_M_impl, _S_nword(__n)); } + + void + _M_deallocate() + { + if (_M_impl._M_start._M_p) + { + const size_t __n = _M_impl._M_end_addr() - _M_impl._M_start._M_p; + _Bit_alloc_traits::deallocate(_M_impl, + _M_impl._M_end_of_storage - __n, + __n); + _M_impl._M_reset(); + } + } + +#if __cplusplus >= 201103L + void + _M_move_data(_Bvector_base&& __x) noexcept + { _M_impl._M_move_data(std::move(__x._M_impl)); } +#endif + + static size_t + _S_nword(size_t __n) + { return (__n + int(_S_word_bit) - 1) / int(_S_word_bit); } + }; + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +// Declare a partial specialization of vector. +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * @brief A specialization of vector for booleans which offers fixed time + * access to individual elements in any order. + * + * @ingroup sequences + * + * @tparam _Alloc Allocator type. + * + * Note that vector does not actually meet the requirements for being + * a container. This is because the reference and pointer types are not + * really references and pointers to bool. See DR96 for details. @see + * vector for function documentation. + * + * In some terminology a %vector can be described as a dynamic + * C-style array, it offers fast and efficient access to individual + * elements in any order and saves the user from worrying about + * memory and size allocation. Subscripting ( @c [] ) access is + * also provided as with C-style arrays. + */ + template + class vector : protected _Bvector_base<_Alloc> + { + typedef _Bvector_base<_Alloc> _Base; + typedef typename _Base::_Bit_pointer _Bit_pointer; + typedef typename _Base::_Bit_alloc_traits _Bit_alloc_traits; + +#if __cplusplus >= 201103L + friend struct std::hash; +#endif + + public: + typedef bool value_type; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Bit_reference reference; + typedef bool const_reference; + typedef _Bit_reference* pointer; + typedef const bool* const_pointer; + typedef _Bit_iterator iterator; + typedef _Bit_const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef _Alloc allocator_type; + + allocator_type + get_allocator() const + { return _Base::get_allocator(); } + + protected: + using _Base::_M_allocate; + using _Base::_M_deallocate; + using _Base::_S_nword; + using _Base::_M_get_Bit_allocator; + + public: +#if __cplusplus >= 201103L + vector() = default; +#else + vector() { } +#endif + + explicit + vector(const allocator_type& __a) + : _Base(__a) { } + +#if __cplusplus >= 201103L + explicit + vector(size_type __n, const allocator_type& __a = allocator_type()) + : vector(__n, false, __a) + { } + + vector(size_type __n, const bool& __value, + const allocator_type& __a = allocator_type()) +#else + explicit + vector(size_type __n, const bool& __value = bool(), + const allocator_type& __a = allocator_type()) +#endif + : _Base(__a) + { + _M_initialize(__n); + _M_initialize_value(__value); + } + + vector(const vector& __x) + : _Base(_Bit_alloc_traits::_S_select_on_copy(__x._M_get_Bit_allocator())) + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); + } + +#if __cplusplus >= 201103L + vector(vector&&) = default; + + vector(vector&& __x, const allocator_type& __a) + noexcept(_Bit_alloc_traits::_S_always_equal()) + : _Base(__a) + { + if (__x.get_allocator() == __a) + this->_M_move_data(std::move(__x)); + else + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), begin()); + __x.clear(); + } + } + + vector(const vector& __x, const allocator_type& __a) + : _Base(__a) + { + _M_initialize(__x.size()); + _M_copy_aligned(__x.begin(), __x.end(), this->_M_impl._M_start); + } + + vector(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_initialize_range(__l.begin(), __l.end(), + random_access_iterator_tag()); + } +#endif + +#if __cplusplus >= 201103L + template> + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { _M_initialize_dispatch(__first, __last, __false_type()); } +#else + template + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } +#endif + + ~vector() _GLIBCXX_NOEXCEPT { } + + vector& + operator=(const vector& __x) + { + if (&__x == this) + return *this; +#if __cplusplus >= 201103L + if (_Bit_alloc_traits::_S_propagate_on_copy_assign()) + { + if (this->_M_get_Bit_allocator() != __x._M_get_Bit_allocator()) + { + this->_M_deallocate(); + std::__alloc_on_copy(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + _M_initialize(__x.size()); + } + else + std::__alloc_on_copy(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } +#endif + if (__x.size() > capacity()) + { + this->_M_deallocate(); + _M_initialize(__x.size()); + } + this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(), + begin()); + return *this; + } + +#if __cplusplus >= 201103L + vector& + operator=(vector&& __x) noexcept(_Bit_alloc_traits::_S_nothrow_move()) + { + if (_Bit_alloc_traits::_S_propagate_on_move_assign() + || this->_M_get_Bit_allocator() == __x._M_get_Bit_allocator()) + { + this->_M_deallocate(); + this->_M_move_data(std::move(__x)); + std::__alloc_on_move(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } + else + { + if (__x.size() > capacity()) + { + this->_M_deallocate(); + _M_initialize(__x.size()); + } + this->_M_impl._M_finish = _M_copy_aligned(__x.begin(), __x.end(), + begin()); + __x.clear(); + } + return *this; + } + + vector& + operator=(initializer_list __l) + { + this->assign (__l.begin(), __l.end()); + return *this; + } +#endif + + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + void + assign(size_type __n, const bool& __x) + { _M_fill_assign(__n, __x); } + +#if __cplusplus >= 201103L + template> + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#else + template + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + void + assign(initializer_list __l) + { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); } +#endif + + iterator + begin() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_start._M_p, 0); } + + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_start._M_p, 0); } + + iterator + end() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish; } + + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish; } + + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(begin()); } + +#if __cplusplus >= 201103L + const_iterator + cbegin() const noexcept + { return const_iterator(this->_M_impl._M_start._M_p, 0); } + + const_iterator + cend() const noexcept + { return this->_M_impl._M_finish; } + + const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } +#endif + + size_type + size() const _GLIBCXX_NOEXCEPT + { return size_type(end() - begin()); } + + size_type + max_size() const _GLIBCXX_NOEXCEPT + { + const size_type __isize = + __gnu_cxx::__numeric_traits::__max + - int(_S_word_bit) + 1; + const size_type __asize + = _Bit_alloc_traits::max_size(_M_get_Bit_allocator()); + return (__asize <= __isize / int(_S_word_bit) + ? __asize * int(_S_word_bit) : __isize); + } + + size_type + capacity() const _GLIBCXX_NOEXCEPT + { return size_type(const_iterator(this->_M_impl._M_end_addr(), 0) + - begin()); } + + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return begin() == end(); } + + reference + operator[](size_type __n) + { + return *iterator(this->_M_impl._M_start._M_p + + __n / int(_S_word_bit), __n % int(_S_word_bit)); + } + + const_reference + operator[](size_type __n) const + { + return *const_iterator(this->_M_impl._M_start._M_p + + __n / int(_S_word_bit), __n % int(_S_word_bit)); + } + + protected: + void + _M_range_check(size_type __n) const + { + if (__n >= this->size()) + __throw_out_of_range_fmt(__N("vector::_M_range_check: __n " + "(which is %zu) >= this->size() " + "(which is %zu)"), + __n, this->size()); + } + + public: + reference + at(size_type __n) + { _M_range_check(__n); return (*this)[__n]; } + + const_reference + at(size_type __n) const + { _M_range_check(__n); return (*this)[__n]; } + + void + reserve(size_type __n) + { + if (__n > max_size()) + __throw_length_error(__N("vector::reserve")); + if (capacity() < __n) + _M_reallocate(__n); + } + + reference + front() + { return *begin(); } + + const_reference + front() const + { return *begin(); } + + reference + back() + { return *(end() - 1); } + + const_reference + back() const + { return *(end() - 1); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + // N.B. DR 464 says nothing about vector but we need something + // here due to the way we are implementing DR 464 in the debug-mode + // vector class. + void + data() _GLIBCXX_NOEXCEPT { } + + void + push_back(bool __x) + { + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) + *this->_M_impl._M_finish++ = __x; + else + _M_insert_aux(end(), __x); + } + + void + swap(vector& __x) _GLIBCXX_NOEXCEPT + { + std::swap(this->_M_impl._M_start, __x._M_impl._M_start); + std::swap(this->_M_impl._M_finish, __x._M_impl._M_finish); + std::swap(this->_M_impl._M_end_of_storage, + __x._M_impl._M_end_of_storage); + _Bit_alloc_traits::_S_on_swap(_M_get_Bit_allocator(), + __x._M_get_Bit_allocator()); + } + + // [23.2.5]/1, third-to-last entry in synopsis listing + static void + swap(reference __x, reference __y) _GLIBCXX_NOEXCEPT + { + bool __tmp = __x; + __x = __y; + __y = __tmp; + } + + iterator +#if __cplusplus >= 201103L + insert(const_iterator __position, const bool& __x = bool()) +#else + insert(iterator __position, const bool& __x = bool()) +#endif + { + const difference_type __n = __position - begin(); + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr() + && __position == end()) + *this->_M_impl._M_finish++ = __x; + else + _M_insert_aux(__position._M_const_cast(), __x); + return begin() + __n; + } + +#if __cplusplus >= 201103L + template> + iterator + insert(const_iterator __position, + _InputIterator __first, _InputIterator __last) + { + difference_type __offset = __position - cbegin(); + _M_insert_dispatch(__position._M_const_cast(), + __first, __last, __false_type()); + return begin() + __offset; + } +#else + template + void + insert(iterator __position, + _InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_insert_dispatch(__position, __first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + iterator + insert(const_iterator __position, size_type __n, const bool& __x) + { + difference_type __offset = __position - cbegin(); + _M_fill_insert(__position._M_const_cast(), __n, __x); + return begin() + __offset; + } +#else + void + insert(iterator __position, size_type __n, const bool& __x) + { _M_fill_insert(__position, __n, __x); } +#endif + +#if __cplusplus >= 201103L + iterator + insert(const_iterator __p, initializer_list __l) + { return this->insert(__p, __l.begin(), __l.end()); } +#endif + + void + pop_back() + { --this->_M_impl._M_finish; } + + iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) +#else + erase(iterator __position) +#endif + { return _M_erase(__position._M_const_cast()); } + + iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) +#else + erase(iterator __first, iterator __last) +#endif + { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } + + void + resize(size_type __new_size, bool __x = bool()) + { + if (__new_size < size()) + _M_erase_at_end(begin() + difference_type(__new_size)); + else + insert(end(), __new_size - size(), __x); + } + +#if __cplusplus >= 201103L + void + shrink_to_fit() + { _M_shrink_to_fit(); } +#endif + + void + flip() _GLIBCXX_NOEXCEPT + { + _Bit_type * const __end = this->_M_impl._M_end_addr(); + for (_Bit_type * __p = this->_M_impl._M_start._M_p; __p != __end; ++__p) + *__p = ~*__p; + } + + void + clear() _GLIBCXX_NOEXCEPT + { _M_erase_at_end(begin()); } + +#if __cplusplus >= 201103L + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args) + { + push_back(bool(__args...)); +#if __cplusplus > 201402L + return back(); +#endif + } + + template + iterator + emplace(const_iterator __pos, _Args&&... __args) + { return insert(__pos, bool(__args...)); } +#endif + + protected: + // Precondition: __first._M_offset == 0 && __result._M_offset == 0. + iterator + _M_copy_aligned(const_iterator __first, const_iterator __last, + iterator __result) + { + _Bit_type* __q = std::copy(__first._M_p, __last._M_p, __result._M_p); + return std::copy(const_iterator(__last._M_p, 0), __last, + iterator(__q, 0)); + } + + void + _M_initialize(size_type __n) + { + if (__n) + { + _Bit_pointer __q = this->_M_allocate(__n); + this->_M_impl._M_end_of_storage = __q + _S_nword(__n); + this->_M_impl._M_start = iterator(std::__addressof(*__q), 0); + } + else + { + this->_M_impl._M_end_of_storage = _Bit_pointer(); + this->_M_impl._M_start = iterator(0, 0); + } + this->_M_impl._M_finish = this->_M_impl._M_start + difference_type(__n); + + } + + void + _M_initialize_value(bool __x) + { + if (_Bit_type* __p = this->_M_impl._M_start._M_p) + __builtin_memset(__p, __x ? ~0 : 0, + (this->_M_impl._M_end_addr() - __p) + * sizeof(_Bit_type)); + } + + void + _M_reallocate(size_type __n); + +#if __cplusplus >= 201103L + bool + _M_shrink_to_fit(); +#endif + + // Check whether it's an integral type. If so, it's not an iterator. + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { + _M_initialize(static_cast(__n)); + _M_initialize_value(__x); + } + + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { _M_initialize_range(__first, __last, + std::__iterator_category(__first)); } + + template + void + _M_initialize_range(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + for (; __first != __last; ++__first) + push_back(*__first); + } + + template + void + _M_initialize_range(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __n = std::distance(__first, __last); + _M_initialize(__n); + std::copy(__first, __last, this->_M_impl._M_start); + } + +#if __cplusplus < 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#endif + + void + _M_fill_assign(size_t __n, bool __x) + { + if (__n > size()) + { + _M_initialize_value(__x); + insert(end(), __n - size(), __x); + } + else + { + _M_erase_at_end(begin() + __n); + _M_initialize_value(__x); + } + } + + template + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + iterator __cur = begin(); + for (; __first != __last && __cur != end(); ++__cur, (void)++__first) + *__cur = *__first; + if (__first == __last) + _M_erase_at_end(__cur); + else + insert(end(), __first, __last); + } + + template + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __len = std::distance(__first, __last); + if (__len < size()) + _M_erase_at_end(std::copy(__first, __last, begin())); + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, size()); + std::copy(__first, __mid, begin()); + insert(end(), __mid, __last); + } + } + + // Check whether it's an integral type. If so, it's not an iterator. + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __x, + __true_type) + { _M_fill_insert(__pos, __n, __x); } + + template + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) + { _M_insert_range(__pos, __first, __last, + std::__iterator_category(__first)); } + + void + _M_fill_insert(iterator __position, size_type __n, bool __x); + + template + void + _M_insert_range(iterator __pos, _InputIterator __first, + _InputIterator __last, std::input_iterator_tag) + { + for (; __first != __last; ++__first) + { + __pos = insert(__pos, *__first); + ++__pos; + } + } + + template + void + _M_insert_range(iterator __position, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag); + + void + _M_insert_aux(iterator __position, bool __x); + + size_type + _M_check_len(size_type __n, const char* __s) const + { + if (max_size() - size() < __n) + __throw_length_error(__N(__s)); + + const size_type __len = size() + std::max(size(), __n); + return (__len < size() || __len > max_size()) ? max_size() : __len; + } + + void + _M_erase_at_end(iterator __pos) + { this->_M_impl._M_finish = __pos; } + + iterator + _M_erase(iterator __pos); + + iterator + _M_erase(iterator __first, iterator __last); + }; + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // DR 1182. + /// std::hash specialization for vector. + template + struct hash<_GLIBCXX_STD_C::vector> + : public __hash_base> + { + size_t + operator()(const _GLIBCXX_STD_C::vector&) const noexcept; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +}// namespace std + +#endif // C++11 + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_construct.h b/resources/sources/avr-libstdcpp/include/bits/stl_construct.h new file mode 100644 index 000000000..72a7cb471 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_construct.h @@ -0,0 +1,256 @@ +// nonstandard construct and destroy functions -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_construct.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_CONSTRUCT_H +#define _STL_CONSTRUCT_H 1 + +#include +#include +#include // for iterator_traits +#include // for advance + +/* This file provides the C++17 functions std::destroy_at, std::destroy, and + * std::destroy_n, and the C++20 function std::construct_at. + * It also provides std::_Construct, std::_Destroy,and std::_Destroy_n functions + * which are defined in all standard modes and so can be used in C++98-14 code. + * The _Destroy functions will dispatch to destroy_at during constant + * evaluation, because calls to that function are intercepted by the compiler + * to allow use in constant expressions. + */ + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201703L + template + _GLIBCXX20_CONSTEXPR inline void + destroy_at(_Tp* __location) + { + if constexpr (__cplusplus > 201703L && is_array_v<_Tp>) + { + for (auto& __x : *__location) + std::destroy_at(std::__addressof(__x)); + } + else + __location->~_Tp(); + } + +#if __cplusplus > 201703L + template + constexpr auto + construct_at(_Tp* __location, _Args&&... __args) + noexcept(noexcept(::new((void*)0) _Tp(std::declval<_Args>()...))) + -> decltype(::new((void*)0) _Tp(std::declval<_Args>()...)) + { return ::new((void*)__location) _Tp(std::forward<_Args>(__args)...); } +#endif // C++20 +#endif// C++17 + + /** + * Constructs an object in existing memory by invoking an allocated + * object's constructor with an initializer. + */ +#if __cplusplus >= 201103L + template + inline void + _Construct(_Tp* __p, _Args&&... __args) + { ::new(static_cast(__p)) _Tp(std::forward<_Args>(__args)...); } +#else + template + inline void + _Construct(_T1* __p, const _T2& __value) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_]allocator::construct + ::new(static_cast(__p)) _T1(__value); + } +#endif + + template + inline void + _Construct_novalue(_T1* __p) + { ::new(static_cast(__p)) _T1; } + + template + _GLIBCXX20_CONSTEXPR void + _Destroy(_ForwardIterator __first, _ForwardIterator __last); + + /** + * Destroy the object pointed to by a pointer type. + */ + template + _GLIBCXX14_CONSTEXPR inline void + _Destroy(_Tp* __pointer) + { +#if __cplusplus > 201703L + std::destroy_at(__pointer); +#else + __pointer->~_Tp(); +#endif + } + + template + struct _Destroy_aux + { + template + static _GLIBCXX20_CONSTEXPR void + __destroy(_ForwardIterator __first, _ForwardIterator __last) + { + for (; __first != __last; ++__first) + std::_Destroy(std::__addressof(*__first)); + } + }; + + template<> + struct _Destroy_aux + { + template + static void + __destroy(_ForwardIterator, _ForwardIterator) { } + }; + + /** + * Destroy a range of objects. If the value_type of the object has + * a trivial destructor, the compiler should optimize all of this + * away, otherwise the objects' destructors must be invoked. + */ + template + _GLIBCXX20_CONSTEXPR inline void + _Destroy(_ForwardIterator __first, _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; +#if __cplusplus >= 201103L + // A deleted destructor is trivial, this ensures we reject such types: + static_assert(is_destructible<_Value_type>::value, + "value type is destructible"); +#endif +#if __cplusplus > 201703L && defined __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return _Destroy_aux::__destroy(__first, __last); +#endif + std::_Destroy_aux<__has_trivial_destructor(_Value_type)>:: + __destroy(__first, __last); + } + + template + struct _Destroy_n_aux + { + template + static _GLIBCXX20_CONSTEXPR _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + for (; __count > 0; (void)++__first, --__count) + std::_Destroy(std::__addressof(*__first)); + return __first; + } + }; + + template<> + struct _Destroy_n_aux + { + template + static _ForwardIterator + __destroy_n(_ForwardIterator __first, _Size __count) + { + std::advance(__first, __count); + return __first; + } + }; + + /** + * Destroy a range of objects. If the value_type of the object has + * a trivial destructor, the compiler should optimize all of this + * away, otherwise the objects' destructors must be invoked. + */ + template + _GLIBCXX20_CONSTEXPR inline _ForwardIterator + _Destroy_n(_ForwardIterator __first, _Size __count) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _Value_type; +#if __cplusplus >= 201103L + // A deleted destructor is trivial, this ensures we reject such types: + static_assert(is_destructible<_Value_type>::value, + "value type is destructible"); +#endif +#if __cplusplus > 201703L && defined __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + return _Destroy_n_aux::__destroy_n(__first, __count); +#endif + return std::_Destroy_n_aux<__has_trivial_destructor(_Value_type)>:: + __destroy_n(__first, __count); + } + +#if __cplusplus >= 201703L + template + _GLIBCXX20_CONSTEXPR inline void + destroy(_ForwardIterator __first, _ForwardIterator __last) + { + std::_Destroy(__first, __last); + } + + template + _GLIBCXX20_CONSTEXPR inline _ForwardIterator + destroy_n(_ForwardIterator __first, _Size __count) + { + return std::_Destroy_n(__first, __count); + } +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_CONSTRUCT_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_deque.h b/resources/sources/avr-libstdcpp/include/bits/stl_deque.h new file mode 100644 index 000000000..3959dd789 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_deque.h @@ -0,0 +1,2330 @@ +// Deque implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_deque.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{deque} + */ + +#ifndef _STL_DEQUE_H +#define _STL_DEQUE_H 1 + +#include +#include +#include +#if __cplusplus >= 201103L +#include +#include // for __is_bitwise_relocatable +#endif +#if __cplusplus > 201703L +# include +#endif + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * @brief This function controls the size of memory nodes. + * @param __size The size of an element. + * @return The number (not byte size) of elements per node. + * + * This function started off as a compiler kludge from SGI, but + * seems to be a useful wrapper around a repeated constant + * expression. The @b 512 is tunable (and no other code needs to + * change), but no investigation has been done since inheriting the + * SGI code. Touch _GLIBCXX_DEQUE_BUF_SIZE only if you know what + * you are doing, however: changing it breaks the binary + * compatibility!! + */ + +#ifndef _GLIBCXX_DEQUE_BUF_SIZE +#define _GLIBCXX_DEQUE_BUF_SIZE 512 +#endif + + _GLIBCXX_CONSTEXPR inline size_t + __deque_buf_size(size_t __size) + { return (__size < _GLIBCXX_DEQUE_BUF_SIZE + ? size_t(_GLIBCXX_DEQUE_BUF_SIZE / __size) : size_t(1)); } + + + /** + * @brief A deque::iterator. + * + * Quite a bit of intelligence here. Much of the functionality of + * deque is actually passed off to this class. A deque holds two + * of these internally, marking its valid range. Access to + * elements is done as offsets of either of those two, relying on + * operator overloading in this class. + * + * All the functions are op overloads except for _M_set_node. + */ + template + struct _Deque_iterator + { +#if __cplusplus < 201103L + typedef _Deque_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Deque_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; + typedef _Tp* _Elt_pointer; + typedef _Tp** _Map_pointer; +#else + private: + template + using __iter = _Deque_iterator<_Tp, _CvTp&, __ptr_rebind<_Ptr, _CvTp>>; + public: + typedef __iter<_Tp> iterator; + typedef __iter const_iterator; + typedef __ptr_rebind<_Ptr, _Tp> _Elt_pointer; + typedef __ptr_rebind<_Ptr, _Elt_pointer> _Map_pointer; +#endif + + static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT + { return __deque_buf_size(sizeof(_Tp)); } + + typedef std::random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Deque_iterator _Self; + + _Elt_pointer _M_cur; + _Elt_pointer _M_first; + _Elt_pointer _M_last; + _Map_pointer _M_node; + + _Deque_iterator(_Elt_pointer __x, _Map_pointer __y) _GLIBCXX_NOEXCEPT + : _M_cur(__x), _M_first(*__y), + _M_last(*__y + _S_buffer_size()), _M_node(__y) { } + + _Deque_iterator() _GLIBCXX_NOEXCEPT + : _M_cur(), _M_first(), _M_last(), _M_node() { } + +#if __cplusplus < 201103L + // Conversion from iterator to const_iterator. + _Deque_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT + : _M_cur(__x._M_cur), _M_first(__x._M_first), + _M_last(__x._M_last), _M_node(__x._M_node) { } +#else + // Conversion from iterator to const_iterator. + template, + is_same<_Iter, iterator>>> + _Deque_iterator(const _Iter& __x) noexcept + : _M_cur(__x._M_cur), _M_first(__x._M_first), + _M_last(__x._M_last), _M_node(__x._M_node) { } + + _Deque_iterator(const _Deque_iterator& __x) noexcept + : _M_cur(__x._M_cur), _M_first(__x._M_first), + _M_last(__x._M_last), _M_node(__x._M_node) { } + + _Deque_iterator& operator=(const _Deque_iterator&) = default; +#endif + + iterator + _M_const_cast() const _GLIBCXX_NOEXCEPT + { return iterator(_M_cur, _M_node); } + + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *_M_cur; } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return _M_cur; } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + ++_M_cur; + if (_M_cur == _M_last) + { + _M_set_node(_M_node + 1); + _M_cur = _M_first; + } + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + ++*this; + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + if (_M_cur == _M_first) + { + _M_set_node(_M_node - 1); + _M_cur = _M_last; + } + --_M_cur; + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + --*this; + return __tmp; + } + + _Self& + operator+=(difference_type __n) _GLIBCXX_NOEXCEPT + { + const difference_type __offset = __n + (_M_cur - _M_first); + if (__offset >= 0 && __offset < difference_type(_S_buffer_size())) + _M_cur += __n; + else + { + const difference_type __node_offset = + __offset > 0 ? __offset / difference_type(_S_buffer_size()) + : -difference_type((-__offset - 1) + / _S_buffer_size()) - 1; + _M_set_node(_M_node + __node_offset); + _M_cur = _M_first + (__offset - __node_offset + * difference_type(_S_buffer_size())); + } + return *this; + } + + _Self& + operator-=(difference_type __n) _GLIBCXX_NOEXCEPT + { return *this += -__n; } + + reference + operator[](difference_type __n) const _GLIBCXX_NOEXCEPT + { return *(*this + __n); } + + /** + * Prepares to traverse new_node. Sets everything except + * _M_cur, which should therefore be set by the caller + * immediately afterwards, based on _M_first and _M_last. + */ + void + _M_set_node(_Map_pointer __new_node) _GLIBCXX_NOEXCEPT + { + _M_node = __new_node; + _M_first = *__new_node; + _M_last = _M_first + difference_type(_S_buffer_size()); + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_cur == __y._M_cur; } + + // Note: we also provide overloads whose operands are of the same type in + // order to avoid ambiguous overload resolution when std::rel_ops + // operators are in scope (for additional details, see libstdc++/3628) + template + friend bool + operator==(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return __x._M_cur == __y._M_cur; } + +#if __cpp_lib_three_way_comparison + friend strong_ordering + operator<=>(const _Self& __x, const _Self& __y) noexcept + { + if (const auto __cmp = __x._M_node <=> __y._M_node; __cmp != 0) + return __cmp; + return __x._M_cur <=> __y._M_cur; + } +#else + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return !(__x == __y); } + + template + friend bool + operator!=(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return !(__x == __y); } + + friend bool + operator<(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { + return (__x._M_node == __y._M_node) + ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); + } + + template + friend bool + operator<(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { + return (__x._M_node == __y._M_node) + ? (__x._M_cur < __y._M_cur) : (__x._M_node < __y._M_node); + } + + friend bool + operator>(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __y < __x; } + + template + friend bool + operator>(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return __y < __x; } + + friend bool + operator<=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return !(__y < __x); } + + template + friend bool + operator<=(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return !(__y < __x); } + + friend bool + operator>=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return !(__x < __y); } + + template + friend bool + operator>=(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) + _GLIBCXX_NOEXCEPT + { return !(__x < __y); } +#endif // three-way comparison + + friend difference_type + operator-(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { + return difference_type(_S_buffer_size()) + * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) + + (__y._M_last - __y._M_cur); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template + friend difference_type + operator-(const _Self& __x, + const _Deque_iterator<_Tp, _RefR, _PtrR>& __y) _GLIBCXX_NOEXCEPT + { + return difference_type(_S_buffer_size()) + * (__x._M_node - __y._M_node - 1) + (__x._M_cur - __x._M_first) + + (__y._M_last - __y._M_cur); + } + + friend _Self + operator+(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT + { + _Self __tmp = __x; + __tmp += __n; + return __tmp; + } + + friend _Self + operator-(const _Self& __x, difference_type __n) _GLIBCXX_NOEXCEPT + { + _Self __tmp = __x; + __tmp -= __n; + return __tmp; + } + + friend _Self + operator+(difference_type __n, const _Self& __x) _GLIBCXX_NOEXCEPT + { return __x + __n; } + }; + + /** + * Deque base class. This class provides the unified face for %deque's + * allocation. This class's constructor and destructor allocate and + * deallocate (but do not initialize) storage. This makes %exception + * safety easier. + * + * Nothing in this class ever constructs or destroys an actual Tp element. + * (Deque handles that itself.) Only/All memory management is performed + * here. + */ + template + class _Deque_base + { + protected: + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Tp>::other _Tp_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; + +#if __cplusplus < 201103L + typedef _Tp* _Ptr; + typedef const _Tp* _Ptr_const; +#else + typedef typename _Alloc_traits::pointer _Ptr; + typedef typename _Alloc_traits::const_pointer _Ptr_const; +#endif + + typedef typename _Alloc_traits::template rebind<_Ptr>::other + _Map_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Map_alloc_type> _Map_alloc_traits; + + typedef _Alloc allocator_type; + + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_get_Tp_allocator()); } + + typedef _Deque_iterator<_Tp, _Tp&, _Ptr> iterator; + typedef _Deque_iterator<_Tp, const _Tp&, _Ptr_const> const_iterator; + + _Deque_base() + : _M_impl() + { _M_initialize_map(0); } + + _Deque_base(size_t __num_elements) + : _M_impl() + { _M_initialize_map(__num_elements); } + + _Deque_base(const allocator_type& __a, size_t __num_elements) + : _M_impl(__a) + { _M_initialize_map(__num_elements); } + + _Deque_base(const allocator_type& __a) + : _M_impl(__a) + { /* Caller must initialize map. */ } + +#if __cplusplus >= 201103L + _Deque_base(_Deque_base&& __x) + : _M_impl(std::move(__x._M_get_Tp_allocator())) + { + _M_initialize_map(0); + if (__x._M_impl._M_map) + this->_M_impl._M_swap_data(__x._M_impl); + } + + _Deque_base(_Deque_base&& __x, const allocator_type& __a) + : _M_impl(std::move(__x._M_impl), _Tp_alloc_type(__a)) + { __x._M_initialize_map(0); } + + _Deque_base(_Deque_base&& __x, const allocator_type& __a, size_t __n) + : _M_impl(__a) + { + if (__x.get_allocator() == __a) + { + if (__x._M_impl._M_map) + { + _M_initialize_map(0); + this->_M_impl._M_swap_data(__x._M_impl); + } + } + else + { + _M_initialize_map(__n); + } + } +#endif + + ~_Deque_base() _GLIBCXX_NOEXCEPT; + + typedef typename iterator::_Map_pointer _Map_pointer; + + struct _Deque_impl_data + { + _Map_pointer _M_map; + size_t _M_map_size; + iterator _M_start; + iterator _M_finish; + + _Deque_impl_data() _GLIBCXX_NOEXCEPT + : _M_map(), _M_map_size(), _M_start(), _M_finish() + { } + +#if __cplusplus >= 201103L + _Deque_impl_data(const _Deque_impl_data&) = default; + _Deque_impl_data& + operator=(const _Deque_impl_data&) = default; + + _Deque_impl_data(_Deque_impl_data&& __x) noexcept + : _Deque_impl_data(__x) + { __x = _Deque_impl_data(); } +#endif + + void + _M_swap_data(_Deque_impl_data& __x) _GLIBCXX_NOEXCEPT + { + // Do not use std::swap(_M_start, __x._M_start), etc as it loses + // information used by TBAA. + std::swap(*this, __x); + } + }; + + // This struct encapsulates the implementation of the std::deque + // standard container and at the same time makes use of the EBO + // for empty allocators. + struct _Deque_impl + : public _Tp_alloc_type, public _Deque_impl_data + { + _Deque_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Tp_alloc_type>::value) + : _Tp_alloc_type() + { } + + _Deque_impl(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT + : _Tp_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + _Deque_impl(_Deque_impl&&) = default; + + _Deque_impl(_Tp_alloc_type&& __a) noexcept + : _Tp_alloc_type(std::move(__a)) + { } + + _Deque_impl(_Deque_impl&& __d, _Tp_alloc_type&& __a) + : _Tp_alloc_type(std::move(__a)), _Deque_impl_data(std::move(__d)) + { } +#endif + }; + + _Tp_alloc_type& + _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + const _Tp_alloc_type& + _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + _Map_alloc_type + _M_get_map_allocator() const _GLIBCXX_NOEXCEPT + { return _Map_alloc_type(_M_get_Tp_allocator()); } + + _Ptr + _M_allocate_node() + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits; + return _Traits::allocate(_M_impl, __deque_buf_size(sizeof(_Tp))); + } + + void + _M_deallocate_node(_Ptr __p) _GLIBCXX_NOEXCEPT + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Traits; + _Traits::deallocate(_M_impl, __p, __deque_buf_size(sizeof(_Tp))); + } + + _Map_pointer + _M_allocate_map(size_t __n) + { + _Map_alloc_type __map_alloc = _M_get_map_allocator(); + return _Map_alloc_traits::allocate(__map_alloc, __n); + } + + void + _M_deallocate_map(_Map_pointer __p, size_t __n) _GLIBCXX_NOEXCEPT + { + _Map_alloc_type __map_alloc = _M_get_map_allocator(); + _Map_alloc_traits::deallocate(__map_alloc, __p, __n); + } + + void _M_initialize_map(size_t); + void _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish); + void _M_destroy_nodes(_Map_pointer __nstart, + _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT; + enum { _S_initial_map_size = 8 }; + + _Deque_impl _M_impl; + }; + + template + _Deque_base<_Tp, _Alloc>:: + ~_Deque_base() _GLIBCXX_NOEXCEPT + { + if (this->_M_impl._M_map) + { + _M_destroy_nodes(this->_M_impl._M_start._M_node, + this->_M_impl._M_finish._M_node + 1); + _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); + } + } + + /** + * @brief Layout storage. + * @param __num_elements The count of T's for which to allocate space + * at first. + * @return Nothing. + * + * The initial underlying memory layout is a bit complicated... + */ + template + void + _Deque_base<_Tp, _Alloc>:: + _M_initialize_map(size_t __num_elements) + { + const size_t __num_nodes = (__num_elements / __deque_buf_size(sizeof(_Tp)) + + 1); + + this->_M_impl._M_map_size = std::max((size_t) _S_initial_map_size, + size_t(__num_nodes + 2)); + this->_M_impl._M_map = _M_allocate_map(this->_M_impl._M_map_size); + + // For "small" maps (needing less than _M_map_size nodes), allocation + // starts in the middle elements and grows outwards. So nstart may be + // the beginning of _M_map, but for small maps it may be as far in as + // _M_map+3. + + _Map_pointer __nstart = (this->_M_impl._M_map + + (this->_M_impl._M_map_size - __num_nodes) / 2); + _Map_pointer __nfinish = __nstart + __num_nodes; + + __try + { _M_create_nodes(__nstart, __nfinish); } + __catch(...) + { + _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); + this->_M_impl._M_map = _Map_pointer(); + this->_M_impl._M_map_size = 0; + __throw_exception_again; + } + + this->_M_impl._M_start._M_set_node(__nstart); + this->_M_impl._M_finish._M_set_node(__nfinish - 1); + this->_M_impl._M_start._M_cur = _M_impl._M_start._M_first; + this->_M_impl._M_finish._M_cur = (this->_M_impl._M_finish._M_first + + __num_elements + % __deque_buf_size(sizeof(_Tp))); + } + + template + void + _Deque_base<_Tp, _Alloc>:: + _M_create_nodes(_Map_pointer __nstart, _Map_pointer __nfinish) + { + _Map_pointer __cur; + __try + { + for (__cur = __nstart; __cur < __nfinish; ++__cur) + *__cur = this->_M_allocate_node(); + } + __catch(...) + { + _M_destroy_nodes(__nstart, __cur); + __throw_exception_again; + } + } + + template + void + _Deque_base<_Tp, _Alloc>:: + _M_destroy_nodes(_Map_pointer __nstart, + _Map_pointer __nfinish) _GLIBCXX_NOEXCEPT + { + for (_Map_pointer __n = __nstart; __n < __nfinish; ++__n) + _M_deallocate_node(*__n); + } + + /** + * @brief A standard container using fixed-size memory allocation and + * constant-time manipulation of elements at either end. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements. + * + * In previous HP/SGI versions of deque, there was an extra template + * parameter so users could control the node size. This extension turned + * out to violate the C++ standard (it can be detected using template + * template parameters), and it was removed. + * + * Here's how a deque manages memory. Each deque has 4 members: + * + * - Tp** _M_map + * - size_t _M_map_size + * - iterator _M_start, _M_finish + * + * map_size is at least 8. %map is an array of map_size + * pointers-to-@a nodes. (The name %map has nothing to do with the + * std::map class, and @b nodes should not be confused with + * std::list's usage of @a node.) + * + * A @a node has no specific type name as such, but it is referred + * to as @a node in this file. It is a simple array-of-Tp. If Tp + * is very large, there will be one Tp element per node (i.e., an + * @a array of one). For non-huge Tp's, node size is inversely + * related to Tp size: the larger the Tp, the fewer Tp's will fit + * in a node. The goal here is to keep the total size of a node + * relatively small and constant over different Tp's, to improve + * allocator efficiency. + * + * Not every pointer in the %map array will point to a node. If + * the initial number of elements in the deque is small, the + * /middle/ %map pointers will be valid, and the ones at the edges + * will be unused. This same situation will arise as the %map + * grows: available %map pointers, if any, will be on the ends. As + * new nodes are created, only a subset of the %map's pointers need + * to be copied @a outward. + * + * Class invariants: + * - For any nonsingular iterator i: + * - i.node points to a member of the %map array. (Yes, you read that + * correctly: i.node does not actually point to a node.) The member of + * the %map array is what actually points to the node. + * - i.first == *(i.node) (This points to the node (first Tp element).) + * - i.last == i.first + node_size + * - i.cur is a pointer in the range [i.first, i.last). NOTE: + * the implication of this is that i.cur is always a dereferenceable + * pointer, even if i is a past-the-end iterator. + * - Start and Finish are always nonsingular iterators. NOTE: this + * means that an empty deque must have one node, a deque with > + class deque : protected _Deque_base<_Tp, _Alloc> + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Tp>::value, + "std::deque must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::deque must have the same value_type as its allocator"); +# endif +#endif + + typedef _Deque_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef typename _Base::_Alloc_traits _Alloc_traits; + typedef typename _Base::_Map_pointer _Map_pointer; + + public: + typedef _Tp value_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + typedef typename _Base::iterator iterator; + typedef typename _Base::const_iterator const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + private: + static size_t _S_buffer_size() _GLIBCXX_NOEXCEPT + { return __deque_buf_size(sizeof(_Tp)); } + + // Functions controlling memory layout, and nothing else. + using _Base::_M_initialize_map; + using _Base::_M_create_nodes; + using _Base::_M_destroy_nodes; + using _Base::_M_allocate_node; + using _Base::_M_deallocate_node; + using _Base::_M_allocate_map; + using _Base::_M_deallocate_map; + using _Base::_M_get_Tp_allocator; + + /** + * A total of four data members accumulated down the hierarchy. + * May be accessed via _M_impl.* + */ + using _Base::_M_impl; + + public: + // [23.2.1.1] construct/copy/destroy + // (assign() and get_allocator() are also listed in this section) + + /** + * @brief Creates a %deque with no elements. + */ +#if __cplusplus >= 201103L + deque() = default; +#else + deque() { } +#endif + + /** + * @brief Creates a %deque with no elements. + * @param __a An allocator object. + */ + explicit + deque(const allocator_type& __a) + : _Base(__a, 0) { } + +#if __cplusplus >= 201103L + /** + * @brief Creates a %deque with default constructed elements. + * @param __n The number of elements to initially create. + * @param __a An allocator. + * + * This constructor fills the %deque with @a n default + * constructed elements. + */ + explicit + deque(size_type __n, const allocator_type& __a = allocator_type()) + : _Base(__a, _S_check_init_len(__n, __a)) + { _M_default_initialize(); } + + /** + * @brief Creates a %deque with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator. + * + * This constructor fills the %deque with @a __n copies of @a __value. + */ + deque(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) + : _Base(__a, _S_check_init_len(__n, __a)) + { _M_fill_initialize(__value); } +#else + /** + * @brief Creates a %deque with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator. + * + * This constructor fills the %deque with @a __n copies of @a __value. + */ + explicit + deque(size_type __n, const value_type& __value = value_type(), + const allocator_type& __a = allocator_type()) + : _Base(__a, _S_check_init_len(__n, __a)) + { _M_fill_initialize(__value); } +#endif + + /** + * @brief %Deque copy constructor. + * @param __x A %deque of identical element and allocator types. + * + * The newly-created %deque uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). + */ + deque(const deque& __x) + : _Base(_Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator()), + __x.size()) + { std::__uninitialized_copy_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); } + +#if __cplusplus >= 201103L + /** + * @brief %Deque move constructor. + * + * The newly-created %deque contains the exact contents of the + * moved instance. + * The contents of the moved instance are a valid, but unspecified + * %deque. + */ + deque(deque&&) = default; + + /// Copy constructor with alternative allocator + deque(const deque& __x, const allocator_type& __a) + : _Base(__a, __x.size()) + { std::__uninitialized_copy_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); } + + /// Move constructor with alternative allocator + deque(deque&& __x, const allocator_type& __a) + : deque(std::move(__x), __a, typename _Alloc_traits::is_always_equal{}) + { } + + private: + deque(deque&& __x, const allocator_type& __a, true_type) + : _Base(std::move(__x), __a) + { } + + deque(deque&& __x, const allocator_type& __a, false_type) + : _Base(std::move(__x), __a, __x.size()) + { + if (__x.get_allocator() != __a && !__x.empty()) + { + std::__uninitialized_move_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); + __x.clear(); + } + } + + public: + /** + * @brief Builds a %deque from an initializer list. + * @param __l An initializer_list. + * @param __a An allocator object. + * + * Create a %deque consisting of copies of the elements in the + * initializer_list @a __l. + * + * This will call the element type's copy constructor N times + * (where N is __l.size()) and do no memory reallocation. + */ + deque(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_range_initialize(__l.begin(), __l.end(), + random_access_iterator_tag()); + } +#endif + + /** + * @brief Builds a %deque from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __a An allocator object. + * + * Create a %deque consisting of copies of the elements from [__first, + * __last). + * + * If the iterators are forward, bidirectional, or random-access, then + * this will call the elements' copy constructor N times (where N is + * distance(__first,__last)) and do no memory reallocation. But if only + * input iterators are used, then this will do at most 2N calls to the + * copy constructor, and logN memory reallocations. + */ +#if __cplusplus >= 201103L + template> + deque(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#else + template + deque(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } +#endif + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~deque() + { _M_destroy_data(begin(), end(), _M_get_Tp_allocator()); } + + /** + * @brief %Deque assignment operator. + * @param __x A %deque of identical element and allocator types. + * + * All the elements of @a x are copied. + * + * The newly-created %deque uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). + */ + deque& + operator=(const deque& __x); + +#if __cplusplus >= 201103L + /** + * @brief %Deque move assignment operator. + * @param __x A %deque of identical element and allocator types. + * + * The contents of @a __x are moved into this deque (without copying, + * if the allocators permit it). + * @a __x is a valid, but unspecified %deque. + */ + deque& + operator=(deque&& __x) noexcept(_Alloc_traits::_S_always_equal()) + { + using __always_equal = typename _Alloc_traits::is_always_equal; + _M_move_assign1(std::move(__x), __always_equal{}); + return *this; + } + + /** + * @brief Assigns an initializer list to a %deque. + * @param __l An initializer_list. + * + * This function fills a %deque with copies of the elements in the + * initializer_list @a __l. + * + * Note that the assignment completely changes the %deque and that the + * resulting %deque's size is the same as the number of elements + * assigned. + */ + deque& + operator=(initializer_list __l) + { + _M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); + return *this; + } +#endif + + /** + * @brief Assigns a given value to a %deque. + * @param __n Number of elements to be assigned. + * @param __val Value to be assigned. + * + * This function fills a %deque with @a n copies of the given + * value. Note that the assignment completely changes the + * %deque and that the resulting %deque's size is the same as + * the number of elements assigned. + */ + void + assign(size_type __n, const value_type& __val) + { _M_fill_assign(__n, __val); } + + /** + * @brief Assigns a range to a %deque. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function fills a %deque with copies of the elements in the + * range [__first,__last). + * + * Note that the assignment completely changes the %deque and that the + * resulting %deque's size is the same as the number of elements + * assigned. + */ +#if __cplusplus >= 201103L + template> + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#else + template + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Assigns an initializer list to a %deque. + * @param __l An initializer_list. + * + * This function fills a %deque with copies of the elements in the + * initializer_list @a __l. + * + * Note that the assignment completely changes the %deque and that the + * resulting %deque's size is the same as the number of elements + * assigned. + */ + void + assign(initializer_list __l) + { _M_assign_aux(__l.begin(), __l.end(), random_access_iterator_tag()); } +#endif + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return _Base::get_allocator(); } + + // iterators + /** + * Returns a read/write iterator that points to the first element in the + * %deque. Iteration is done in ordinary element order. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_start; } + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %deque. Iteration is done in ordinary element order. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_start; } + + /** + * Returns a read/write iterator that points one past the last + * element in the %deque. Iteration is done in ordinary + * element order. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish; } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %deque. Iteration is done in + * ordinary element order. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish; } + + /** + * Returns a read/write reverse iterator that points to the + * last element in the %deque. Iteration is done in reverse + * element order. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to the last element in the %deque. Iteration is done in + * reverse element order. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read/write reverse iterator that points to one + * before the first element in the %deque. Iteration is done + * in reverse element order. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(this->_M_impl._M_start); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to one before the first element in the %deque. Iteration is + * done in reverse element order. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(this->_M_impl._M_start); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %deque. Iteration is done in ordinary element order. + */ + const_iterator + cbegin() const noexcept + { return this->_M_impl._M_start; } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %deque. Iteration is done in + * ordinary element order. + */ + const_iterator + cend() const noexcept + { return this->_M_impl._M_finish; } + + /** + * Returns a read-only (constant) reverse iterator that points + * to the last element in the %deque. Iteration is done in + * reverse element order. + */ + const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to one before the first element in the %deque. Iteration is + * done in reverse element order. + */ + const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(this->_M_impl._M_start); } +#endif + + // [23.2.1.2] capacity + /** Returns the number of elements in the %deque. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish - this->_M_impl._M_start; } + + /** Returns the size() of the largest possible %deque. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _S_max_size(_M_get_Tp_allocator()); } + +#if __cplusplus >= 201103L + /** + * @brief Resizes the %deque to the specified number of elements. + * @param __new_size Number of elements the %deque should contain. + * + * This function will %resize the %deque to the specified + * number of elements. If the number is smaller than the + * %deque's current size the %deque is truncated, otherwise + * default constructed elements are appended. + */ + void + resize(size_type __new_size) + { + const size_type __len = size(); + if (__new_size > __len) + _M_default_append(__new_size - __len); + else if (__new_size < __len) + _M_erase_at_end(this->_M_impl._M_start + + difference_type(__new_size)); + } + + /** + * @brief Resizes the %deque to the specified number of elements. + * @param __new_size Number of elements the %deque should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %deque to the specified + * number of elements. If the number is smaller than the + * %deque's current size the %deque is truncated, otherwise the + * %deque is extended and new elements are populated with given + * data. + */ + void + resize(size_type __new_size, const value_type& __x) +#else + /** + * @brief Resizes the %deque to the specified number of elements. + * @param __new_size Number of elements the %deque should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %deque to the specified + * number of elements. If the number is smaller than the + * %deque's current size the %deque is truncated, otherwise the + * %deque is extended and new elements are populated with given + * data. + */ + void + resize(size_type __new_size, value_type __x = value_type()) +#endif + { + const size_type __len = size(); + if (__new_size > __len) + _M_fill_insert(this->_M_impl._M_finish, __new_size - __len, __x); + else if (__new_size < __len) + _M_erase_at_end(this->_M_impl._M_start + + difference_type(__new_size)); + } + +#if __cplusplus >= 201103L + /** A non-binding request to reduce memory use. */ + void + shrink_to_fit() noexcept + { _M_shrink_to_fit(); } +#endif + + /** + * Returns true if the %deque is empty. (Thus begin() would + * equal end().) + */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_finish == this->_M_impl._M_start; } + + // element access + /** + * @brief Subscript access to the data contained in the %deque. + * @param __n The index of the element for which data should be + * accessed. + * @return Read/write reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and + * out_of_range lookups are not defined. (For checked lookups + * see at().) + */ + reference + operator[](size_type __n) _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_subscript(__n); + return this->_M_impl._M_start[difference_type(__n)]; + } + + /** + * @brief Subscript access to the data contained in the %deque. + * @param __n The index of the element for which data should be + * accessed. + * @return Read-only (constant) reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and + * out_of_range lookups are not defined. (For checked lookups + * see at().) + */ + const_reference + operator[](size_type __n) const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_subscript(__n); + return this->_M_impl._M_start[difference_type(__n)]; + } + + protected: + /// Safety check used only from at(). + void + _M_range_check(size_type __n) const + { + if (__n >= this->size()) + __throw_out_of_range_fmt(__N("deque::_M_range_check: __n " + "(which is %zu)>= this->size() " + "(which is %zu)"), + __n, this->size()); + } + + public: + /** + * @brief Provides access to the data contained in the %deque. + * @param __n The index of the element for which data should be + * accessed. + * @return Read/write reference to data. + * @throw std::out_of_range If @a __n is an invalid index. + * + * This function provides for safer data access. The parameter + * is first checked that it is in the range of the deque. The + * function throws out_of_range if the check fails. + */ + reference + at(size_type __n) + { + _M_range_check(__n); + return (*this)[__n]; + } + + /** + * @brief Provides access to the data contained in the %deque. + * @param __n The index of the element for which data should be + * accessed. + * @return Read-only (constant) reference to data. + * @throw std::out_of_range If @a __n is an invalid index. + * + * This function provides for safer data access. The parameter is first + * checked that it is in the range of the deque. The function throws + * out_of_range if the check fails. + */ + const_reference + at(size_type __n) const + { + _M_range_check(__n); + return (*this)[__n]; + } + + /** + * Returns a read/write reference to the data at the first + * element of the %deque. + */ + reference + front() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *begin(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %deque. + */ + const_reference + front() const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *begin(); + } + + /** + * Returns a read/write reference to the data at the last element of the + * %deque. + */ + reference + back() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + iterator __tmp = end(); + --__tmp; + return *__tmp; + } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %deque. + */ + const_reference + back() const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + const_iterator __tmp = end(); + --__tmp; + return *__tmp; + } + + // [23.2.1.2] modifiers + /** + * @brief Add data to the front of the %deque. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the front of the %deque and assigns the given + * data to it. Due to the nature of a %deque this operation + * can be done in constant time. + */ + void + push_front(const value_type& __x) + { + if (this->_M_impl._M_start._M_cur != this->_M_impl._M_start._M_first) + { + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_start._M_cur - 1, + __x); + --this->_M_impl._M_start._M_cur; + } + else + _M_push_front_aux(__x); + } + +#if __cplusplus >= 201103L + void + push_front(value_type&& __x) + { emplace_front(std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_front(_Args&&... __args); +#endif + + /** + * @brief Add data to the end of the %deque. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the end of the %deque and assigns the given data + * to it. Due to the nature of a %deque this operation can be + * done in constant time. + */ + void + push_back(const value_type& __x) + { + if (this->_M_impl._M_finish._M_cur + != this->_M_impl._M_finish._M_last - 1) + { + _Alloc_traits::construct(this->_M_impl, + this->_M_impl._M_finish._M_cur, __x); + ++this->_M_impl._M_finish._M_cur; + } + else + _M_push_back_aux(__x); + } + +#if __cplusplus >= 201103L + void + push_back(value_type&& __x) + { emplace_back(std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args); +#endif + + /** + * @brief Removes first element. + * + * This is a typical stack operation. It shrinks the %deque by one. + * + * Note that no data is returned, and if the first element's data is + * needed, it should be retrieved before pop_front() is called. + */ + void + pop_front() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + if (this->_M_impl._M_start._M_cur + != this->_M_impl._M_start._M_last - 1) + { + _Alloc_traits::destroy(_M_get_Tp_allocator(), + this->_M_impl._M_start._M_cur); + ++this->_M_impl._M_start._M_cur; + } + else + _M_pop_front_aux(); + } + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %deque by one. + * + * Note that no data is returned, and if the last element's data is + * needed, it should be retrieved before pop_back() is called. + */ + void + pop_back() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + if (this->_M_impl._M_finish._M_cur + != this->_M_impl._M_finish._M_first) + { + --this->_M_impl._M_finish._M_cur; + _Alloc_traits::destroy(_M_get_Tp_allocator(), + this->_M_impl._M_finish._M_cur); + } + else + _M_pop_back_aux(); + } + +#if __cplusplus >= 201103L + /** + * @brief Inserts an object in %deque before specified iterator. + * @param __position A const_iterator into the %deque. + * @param __args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) before the specified location. + */ + template + iterator + emplace(const_iterator __position, _Args&&... __args); + + /** + * @brief Inserts given value into %deque before specified iterator. + * @param __position A const_iterator into the %deque. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before the + * specified location. + */ + iterator + insert(const_iterator __position, const value_type& __x); +#else + /** + * @brief Inserts given value into %deque before specified iterator. + * @param __position An iterator into the %deque. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before the + * specified location. + */ + iterator + insert(iterator __position, const value_type& __x); +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts given rvalue into %deque before specified iterator. + * @param __position A const_iterator into the %deque. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given rvalue before the + * specified location. + */ + iterator + insert(const_iterator __position, value_type&& __x) + { return emplace(__position, std::move(__x)); } + + /** + * @brief Inserts an initializer list into the %deque. + * @param __p An iterator into the %deque. + * @param __l An initializer_list. + * @return An iterator that points to the inserted data. + * + * This function will insert copies of the data in the + * initializer_list @a __l into the %deque before the location + * specified by @a __p. This is known as list insert. + */ + iterator + insert(const_iterator __p, initializer_list __l) + { + auto __offset = __p - cbegin(); + _M_range_insert_aux(__p._M_const_cast(), __l.begin(), __l.end(), + std::random_access_iterator_tag()); + return begin() + __offset; + } + + /** + * @brief Inserts a number of copies of given data into the %deque. + * @param __position A const_iterator into the %deque. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a specified number of copies of the given + * data before the location specified by @a __position. + */ + iterator + insert(const_iterator __position, size_type __n, const value_type& __x) + { + difference_type __offset = __position - cbegin(); + _M_fill_insert(__position._M_const_cast(), __n, __x); + return begin() + __offset; + } +#else + /** + * @brief Inserts a number of copies of given data into the %deque. + * @param __position An iterator into the %deque. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * + * This function will insert a specified number of copies of the given + * data before the location specified by @a __position. + */ + void + insert(iterator __position, size_type __n, const value_type& __x) + { _M_fill_insert(__position, __n, __x); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a range into the %deque. + * @param __position A const_iterator into the %deque. + * @param __first An input iterator. + * @param __last An input iterator. + * @return An iterator that points to the inserted data. + * + * This function will insert copies of the data in the range + * [__first,__last) into the %deque before the location specified + * by @a __position. This is known as range insert. + */ + template> + iterator + insert(const_iterator __position, _InputIterator __first, + _InputIterator __last) + { + difference_type __offset = __position - cbegin(); + _M_range_insert_aux(__position._M_const_cast(), __first, __last, + std::__iterator_category(__first)); + return begin() + __offset; + } +#else + /** + * @brief Inserts a range into the %deque. + * @param __position An iterator into the %deque. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function will insert copies of the data in the range + * [__first,__last) into the %deque before the location specified + * by @a __position. This is known as range insert. + */ + template + void + insert(iterator __position, _InputIterator __first, + _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_insert_dispatch(__position, __first, __last, _Integral()); + } +#endif + + /** + * @brief Remove element at given position. + * @param __position Iterator pointing to element to be erased. + * @return An iterator pointing to the next element (or end()). + * + * This function will erase the element at the given position and thus + * shorten the %deque by one. + * + * The user is cautioned that + * this function only erases the element, and that if the element is + * itself a pointer, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) +#else + erase(iterator __position) +#endif + { return _M_erase(__position._M_const_cast()); } + + /** + * @brief Remove a range of elements. + * @param __first Iterator pointing to the first element to be erased. + * @param __last Iterator pointing to one past the last element to be + * erased. + * @return An iterator pointing to the element pointed to by @a last + * prior to erasing (or end()). + * + * This function will erase the elements in the range + * [__first,__last) and shorten the %deque accordingly. + * + * The user is cautioned that + * this function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) +#else + erase(iterator __first, iterator __last) +#endif + { return _M_erase(__first._M_const_cast(), __last._M_const_cast()); } + + /** + * @brief Swaps data with another %deque. + * @param __x A %deque of the same element and allocator types. + * + * This exchanges the elements between two deques in constant time. + * (Four pointers, so it should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(d1,d2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(deque& __x) _GLIBCXX_NOEXCEPT + { +#if __cplusplus >= 201103L + __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value + || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()); +#endif + _M_impl._M_swap_data(__x._M_impl); + _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + } + + /** + * Erases all the elements. Note that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_erase_at_end(begin()); } + + protected: + // Internal constructor functions follow. + +#if __cplusplus < 201103L + // called by the range constructor to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { + _M_initialize_map(_S_check_init_len(static_cast(__n), + _M_get_Tp_allocator())); + _M_fill_initialize(__x); + } + + // called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#endif + + static size_t + _S_check_init_len(size_t __n, const allocator_type& __a) + { + if (__n > _S_max_size(__a)) + __throw_length_error( + __N("cannot create std::deque larger than max_size()")); + return __n; + } + + static size_type + _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT + { + const size_t __diffmax = __gnu_cxx::__numeric_traits::__max; + const size_t __allocmax = _Alloc_traits::max_size(__a); + return (std::min)(__diffmax, __allocmax); + } + + // called by the second initialize_dispatch above + //@{ + /** + * @brief Fills the deque with whatever is in [first,last). + * @param __first An input iterator. + * @param __last An input iterator. + * @return Nothing. + * + * If the iterators are actually forward iterators (or better), then the + * memory layout can be done all at once. Else we move forward using + * push_back on each value from the iterator. + */ + template + void + _M_range_initialize(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag); + + // called by the second initialize_dispatch above + template + void + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag); + //@} + + /** + * @brief Fills the %deque with copies of value. + * @param __value Initial value. + * @return Nothing. + * @pre _M_start and _M_finish have already been initialized, + * but none of the %deque's elements have yet been constructed. + * + * This function is called only when the user provides an explicit size + * (with or without an explicit exemplar value). + */ + void + _M_fill_initialize(const value_type& __value); + +#if __cplusplus >= 201103L + // called by deque(n). + void + _M_default_initialize(); +#endif + + // Internal assign functions follow. The *_aux functions do the actual + // assignment work for the range versions. + +#if __cplusplus < 201103L + // called by the range assign to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + + // called by the range assign to implement [23.1.1]/9 + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } +#endif + + // called by the second assign_dispatch above + template + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag); + + // called by the second assign_dispatch above + template + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __len = std::distance(__first, __last); + if (__len > size()) + { + _ForwardIterator __mid = __first; + std::advance(__mid, size()); + std::copy(__first, __mid, begin()); + _M_range_insert_aux(end(), __mid, __last, + std::__iterator_category(__first)); + } + else + _M_erase_at_end(std::copy(__first, __last, begin())); + } + + // Called by assign(n,t), and the range assign when it turns out + // to be the same thing. + void + _M_fill_assign(size_type __n, const value_type& __val) + { + if (__n > size()) + { + std::fill(begin(), end(), __val); + _M_fill_insert(end(), __n - size(), __val); + } + else + { + _M_erase_at_end(begin() + difference_type(__n)); + std::fill(begin(), end(), __val); + } + } + + //@{ + /// Helper functions for push_* and pop_*. +#if __cplusplus < 201103L + void _M_push_back_aux(const value_type&); + + void _M_push_front_aux(const value_type&); +#else + template + void _M_push_back_aux(_Args&&... __args); + + template + void _M_push_front_aux(_Args&&... __args); +#endif + + void _M_pop_back_aux(); + + void _M_pop_front_aux(); + //@} + + // Internal insert functions follow. The *_aux functions do the actual + // insertion work when all shortcuts fail. + +#if __cplusplus < 201103L + // called by the range insert to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_insert_dispatch(iterator __pos, + _Integer __n, _Integer __x, __true_type) + { _M_fill_insert(__pos, __n, __x); } + + // called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, + _InputIterator __first, _InputIterator __last, + __false_type) + { + _M_range_insert_aux(__pos, __first, __last, + std::__iterator_category(__first)); + } +#endif + + // called by the second insert_dispatch above + template + void + _M_range_insert_aux(iterator __pos, _InputIterator __first, + _InputIterator __last, std::input_iterator_tag); + + // called by the second insert_dispatch above + template + void + _M_range_insert_aux(iterator __pos, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag); + + // Called by insert(p,n,x), and the range insert when it turns out to be + // the same thing. Can use fill functions in optimal situations, + // otherwise passes off to insert_aux(p,n,x). + void + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); + + // called by insert(p,x) +#if __cplusplus < 201103L + iterator + _M_insert_aux(iterator __pos, const value_type& __x); +#else + template + iterator + _M_insert_aux(iterator __pos, _Args&&... __args); +#endif + + // called by insert(p,n,x) via fill_insert + void + _M_insert_aux(iterator __pos, size_type __n, const value_type& __x); + + // called by range_insert_aux for forward iterators + template + void + _M_insert_aux(iterator __pos, + _ForwardIterator __first, _ForwardIterator __last, + size_type __n); + + + // Internal erase functions follow. + + void + _M_destroy_data_aux(iterator __first, iterator __last); + + // Called by ~deque(). + // NB: Doesn't deallocate the nodes. + template + void + _M_destroy_data(iterator __first, iterator __last, const _Alloc1&) + { _M_destroy_data_aux(__first, __last); } + + void + _M_destroy_data(iterator __first, iterator __last, + const std::allocator<_Tp>&) + { + if (!__has_trivial_destructor(value_type)) + _M_destroy_data_aux(__first, __last); + } + + // Called by erase(q1, q2). + void + _M_erase_at_begin(iterator __pos) + { + _M_destroy_data(begin(), __pos, _M_get_Tp_allocator()); + _M_destroy_nodes(this->_M_impl._M_start._M_node, __pos._M_node); + this->_M_impl._M_start = __pos; + } + + // Called by erase(q1, q2), resize(), clear(), _M_assign_aux, + // _M_fill_assign, operator=. + void + _M_erase_at_end(iterator __pos) + { + _M_destroy_data(__pos, end(), _M_get_Tp_allocator()); + _M_destroy_nodes(__pos._M_node + 1, + this->_M_impl._M_finish._M_node + 1); + this->_M_impl._M_finish = __pos; + } + + iterator + _M_erase(iterator __pos); + + iterator + _M_erase(iterator __first, iterator __last); + +#if __cplusplus >= 201103L + // Called by resize(sz). + void + _M_default_append(size_type __n); + + bool + _M_shrink_to_fit(); +#endif + + //@{ + /// Memory-handling helpers for the previous internal insert functions. + iterator + _M_reserve_elements_at_front(size_type __n) + { + const size_type __vacancies = this->_M_impl._M_start._M_cur + - this->_M_impl._M_start._M_first; + if (__n > __vacancies) + _M_new_elements_at_front(__n - __vacancies); + return this->_M_impl._M_start - difference_type(__n); + } + + iterator + _M_reserve_elements_at_back(size_type __n) + { + const size_type __vacancies = (this->_M_impl._M_finish._M_last + - this->_M_impl._M_finish._M_cur) - 1; + if (__n > __vacancies) + _M_new_elements_at_back(__n - __vacancies); + return this->_M_impl._M_finish + difference_type(__n); + } + + void + _M_new_elements_at_front(size_type __new_elements); + + void + _M_new_elements_at_back(size_type __new_elements); + //@} + + + //@{ + /** + * @brief Memory-handling helpers for the major %map. + * + * Makes sure the _M_map has space for new nodes. Does not + * actually add the nodes. Can invalidate _M_map pointers. + * (And consequently, %deque iterators.) + */ + void + _M_reserve_map_at_back(size_type __nodes_to_add = 1) + { + if (__nodes_to_add + 1 > this->_M_impl._M_map_size + - (this->_M_impl._M_finish._M_node - this->_M_impl._M_map)) + _M_reallocate_map(__nodes_to_add, false); + } + + void + _M_reserve_map_at_front(size_type __nodes_to_add = 1) + { + if (__nodes_to_add > size_type(this->_M_impl._M_start._M_node + - this->_M_impl._M_map)) + _M_reallocate_map(__nodes_to_add, true); + } + + void + _M_reallocate_map(size_type __nodes_to_add, bool __add_at_front); + //@} + +#if __cplusplus >= 201103L + // Constant-time, nothrow move assignment when source object's memory + // can be moved because the allocators are equal. + void + _M_move_assign1(deque&& __x, /* always equal: */ true_type) noexcept + { + this->_M_impl._M_swap_data(__x._M_impl); + __x.clear(); + std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); + } + + // When the allocators are not equal the operation could throw, because + // we might need to allocate a new map for __x after moving from it + // or we might need to allocate new elements for *this. + void + _M_move_assign1(deque&& __x, /* always equal: */ false_type) + { + constexpr bool __move_storage = + _Alloc_traits::_S_propagate_on_move_assign(); + _M_move_assign2(std::move(__x), __bool_constant<__move_storage>()); + } + + // Destroy all elements and deallocate all memory, then replace + // with elements created from __args. + template + void + _M_replace_map(_Args&&... __args) + { + // Create new data first, so if allocation fails there are no effects. + deque __newobj(std::forward<_Args>(__args)...); + // Free existing storage using existing allocator. + clear(); + _M_deallocate_node(*begin()._M_node); // one node left after clear() + _M_deallocate_map(this->_M_impl._M_map, this->_M_impl._M_map_size); + this->_M_impl._M_map = nullptr; + this->_M_impl._M_map_size = 0; + // Take ownership of replacement memory. + this->_M_impl._M_swap_data(__newobj._M_impl); + } + + // Do move assignment when the allocator propagates. + void + _M_move_assign2(deque&& __x, /* propagate: */ true_type) + { + // Make a copy of the original allocator state. + auto __alloc = __x._M_get_Tp_allocator(); + // The allocator propagates so storage can be moved from __x, + // leaving __x in a valid empty state with a moved-from allocator. + _M_replace_map(std::move(__x)); + // Move the corresponding allocator state too. + _M_get_Tp_allocator() = std::move(__alloc); + } + + // Do move assignment when it may not be possible to move source + // object's memory, resulting in a linear-time operation. + void + _M_move_assign2(deque&& __x, /* propagate: */ false_type) + { + if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator()) + { + // The allocators are equal so storage can be moved from __x, + // leaving __x in a valid empty state with its current allocator. + _M_replace_map(std::move(__x), __x.get_allocator()); + } + else + { + // The rvalue's allocator cannot be moved and is not equal, + // so we need to individually move each element. + _M_assign_aux(std::make_move_iterator(__x.begin()), + std::make_move_iterator(__x.end()), + std::random_access_iterator_tag()); + __x.clear(); + } + } +#endif + }; + +#if __cpp_deduction_guides >= 201606 + template::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + deque(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> deque<_ValT, _Allocator>; +#endif + + /** + * @brief Deque equality comparison. + * @param __x A %deque. + * @param __y A %deque of the same type as @a __x. + * @return True iff the size and elements of the deques are equal. + * + * This is an equivalence relation. It is linear in the size of the + * deques. Deques are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return __x.size() == __y.size() + && std::equal(__x.begin(), __x.end(), __y.begin()); } + +#if __cpp_lib_three_way_comparison + /** + * @brief Deque ordering relation. + * @param __x A `deque`. + * @param __y A `deque` of the same type as `__x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Tp> + operator<=>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + /** + * @brief Deque ordering relation. + * @param __x A %deque. + * @param __y A %deque of the same type as @a __x. + * @return True iff @a x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * deques. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } + + /// Based on operator== + template + inline bool + operator!=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const deque<_Tp, _Alloc>& __x, const deque<_Tp, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::deque::swap(). + template + inline void + swap(deque<_Tp,_Alloc>& __x, deque<_Tp,_Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +#undef _GLIBCXX_DEQUE_BUF_SIZE + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus >= 201103L + // std::allocator is safe, but it is not the only allocator + // for which this is valid. + template + struct __is_bitwise_relocatable<_GLIBCXX_STD_C::deque<_Tp>> + : true_type { }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_DEQUE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_function.h b/resources/sources/avr-libstdcpp/include/bits/stl_function.h new file mode 100644 index 000000000..77f8ccb05 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_function.h @@ -0,0 +1,1395 @@ +// Functor implementations -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_function.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{functional} + */ + +#ifndef _STL_FUNCTION_H +#define _STL_FUNCTION_H 1 + +#if __cplusplus > 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // 20.3.1 base classes + /** @defgroup functors Function Objects + * @ingroup utilities + * + * Function objects, or @e functors, are objects with an @c operator() + * defined and accessible. They can be passed as arguments to algorithm + * templates and used in place of a function pointer. Not only is the + * resulting expressiveness of the library increased, but the generated + * code can be more efficient than what you might write by hand. When we + * refer to @a functors, then, generally we include function pointers in + * the description as well. + * + * Often, functors are only created as temporaries passed to algorithm + * calls, rather than being created as named variables. + * + * Two examples taken from the standard itself follow. To perform a + * by-element addition of two vectors @c a and @c b containing @c double, + * and put the result in @c a, use + * \code + * transform (a.begin(), a.end(), b.begin(), a.begin(), plus()); + * \endcode + * To negate every element in @c a, use + * \code + * transform(a.begin(), a.end(), a.begin(), negate()); + * \endcode + * The addition and negation functions will be inlined directly. + * + * The standard functors are derived from structs named @c unary_function + * and @c binary_function. These two classes contain nothing but typedefs, + * to aid in generic (template) programming. If you write your own + * functors, you might consider doing the same. + * + * @{ + */ + /** + * This is one of the @link functors functor base classes@endlink. + */ + template + struct unary_function + { + /// @c argument_type is the type of the argument + typedef _Arg argument_type; + + /// @c result_type is the return type + typedef _Result result_type; + }; + + /** + * This is one of the @link functors functor base classes@endlink. + */ + template + struct binary_function + { + /// @c first_argument_type is the type of the first argument + typedef _Arg1 first_argument_type; + + /// @c second_argument_type is the type of the second argument + typedef _Arg2 second_argument_type; + + /// @c result_type is the return type + typedef _Result result_type; + }; + /** @} */ + + // 20.3.2 arithmetic + /** @defgroup arithmetic_functors Arithmetic Classes + * @ingroup functors + * + * Because basic math often needs to be done during an algorithm, + * the library provides functors for those operations. See the + * documentation for @link functors the base classes@endlink + * for examples of their use. + * + * @{ + */ + +#if __cplusplus > 201103L + struct __is_transparent; // undefined + + template + struct plus; + + template + struct minus; + + template + struct multiplies; + + template + struct divides; + + template + struct modulus; + + template + struct negate; +#endif + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct plus : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x + __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct minus : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x - __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct multiplies : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x * __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct divides : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x / __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct modulus : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x % __y; } + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template + struct negate : public unary_function<_Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x) const + { return -__x; } + }; + +#if __cplusplus > 201103L + +#define __cpp_lib_transparent_operators 201510 + + template<> + struct plus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) + std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) + std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) + std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct minus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) - std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) - std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) - std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct multiplies + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) * std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) * std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) * std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct divides + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) / std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) / std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) / std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct modulus + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) % std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) % std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) % std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link arithmetic_functors math functors@endlink. + template<> + struct negate + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(-std::forward<_Tp>(__t))) + -> decltype(-std::forward<_Tp>(__t)) + { return -std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif + /** @} */ + + // 20.3.3 comparisons + /** @defgroup comparison_functors Comparison Classes + * @ingroup functors + * + * The library provides six wrapper functors for all the basic comparisons + * in C++, like @c <. + * + * @{ + */ +#if __cplusplus > 201103L + template + struct equal_to; + + template + struct not_equal_to; + + template + struct greater; + + template + struct less; + + template + struct greater_equal; + + template + struct less_equal; +#endif + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct equal_to : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x == __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct not_equal_to : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x != __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct greater : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x > __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct less : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x < __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct greater_equal : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x >= __y; } + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template + struct less_equal : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x <= __y; } + }; + + // Partial specialization of std::greater for pointers. + template + struct greater<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) +#else + if (__builtin_constant_p(__x > __y)) +#endif + return __x > __y; +#endif + return (__UINTPTR_TYPE__)__x > (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::less for pointers. + template + struct less<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) +#else + if (__builtin_constant_p(__x < __y)) +#endif + return __x < __y; +#endif + return (__UINTPTR_TYPE__)__x < (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::greater_equal for pointers. + template + struct greater_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) +#else + if (__builtin_constant_p(__x >= __y)) +#endif + return __x >= __y; +#endif + return (__UINTPTR_TYPE__)__x >= (__UINTPTR_TYPE__)__y; + } + }; + + // Partial specialization of std::less_equal for pointers. + template + struct less_equal<_Tp*> : public binary_function<_Tp*, _Tp*, bool> + { + _GLIBCXX14_CONSTEXPR bool + operator()(_Tp* __x, _Tp* __y) const _GLIBCXX_NOTHROW + { +#if __cplusplus >= 201402L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) +#else + if (__builtin_constant_p(__x <= __y)) +#endif + return __x <= __y; +#endif + return (__UINTPTR_TYPE__)__x <= (__UINTPTR_TYPE__)__y; + } + }; + +#if __cplusplus >= 201402L + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct equal_to + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) == std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) == std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) == std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct not_equal_to + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) != std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) != std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) != std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct greater + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) > std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) > std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return greater>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) > std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return greater{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator> member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator>(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator>(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator> for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator>(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator>(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct less + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) < std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) < std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return less>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) < std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return less{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator< member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator<(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator<(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator< for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator<(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator<(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct greater_equal + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) >= std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) >= std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return greater_equal>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) >= std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return greater_equal{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator>= member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator>=(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator>=(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator>= for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator>=(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator>=(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; + + /// One of the @link comparison_functors comparison functors@endlink. + template<> + struct less_equal + { + template + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) <= std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) <= std::forward<_Up>(__u)) + { + return _S_cmp(std::forward<_Tp>(__t), std::forward<_Up>(__u), + __ptr_cmp<_Tp, _Up>{}); + } + + template + constexpr bool + operator()(_Tp* __t, _Up* __u) const noexcept + { return less_equal>{}(__t, __u); } + + typedef __is_transparent is_transparent; + + private: + template + static constexpr decltype(auto) + _S_cmp(_Tp&& __t, _Up&& __u, false_type) + { return std::forward<_Tp>(__t) <= std::forward<_Up>(__u); } + + template + static constexpr bool + _S_cmp(_Tp&& __t, _Up&& __u, true_type) noexcept + { + return less_equal{}( + static_cast(std::forward<_Tp>(__t)), + static_cast(std::forward<_Up>(__u))); + } + + // True if there is no viable operator<= member function. + template + struct __not_overloaded2 : true_type { }; + + // False if we can call T.operator<=(U) + template + struct __not_overloaded2<_Tp, _Up, __void_t< + decltype(std::declval<_Tp>().operator<=(std::declval<_Up>()))>> + : false_type { }; + + // True if there is no overloaded operator<= for these operands. + template + struct __not_overloaded : __not_overloaded2<_Tp, _Up> { }; + + // False if we can call operator<=(T,U) + template + struct __not_overloaded<_Tp, _Up, __void_t< + decltype(operator<=(std::declval<_Tp>(), std::declval<_Up>()))>> + : false_type { }; + + template + using __ptr_cmp = __and_<__not_overloaded<_Tp, _Up>, + is_convertible<_Tp, const volatile void*>, + is_convertible<_Up, const volatile void*>>; + }; +#endif // C++14 + /** @} */ + + // 20.3.4 logical operations + /** @defgroup logical_functors Boolean Operations Classes + * @ingroup functors + * + * Here are wrapper functors for Boolean operations: @c &&, @c ||, + * and @c !. + * + * @{ + */ +#if __cplusplus > 201103L + template + struct logical_and; + + template + struct logical_or; + + template + struct logical_not; +#endif + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_and : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x && __y; } + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_or : public binary_function<_Tp, _Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x, const _Tp& __y) const + { return __x || __y; } + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template + struct logical_not : public unary_function<_Tp, bool> + { + _GLIBCXX14_CONSTEXPR + bool + operator()(const _Tp& __x) const + { return !__x; } + }; + +#if __cplusplus > 201103L + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_and + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) && std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) && std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) && std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_or + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) || std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) || std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) || std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + /// One of the @link logical_functors Boolean operations functors@endlink. + template<> + struct logical_not + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(!std::forward<_Tp>(__t))) + -> decltype(!std::forward<_Tp>(__t)) + { return !std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif + /** @} */ + +#if __cplusplus > 201103L + template + struct bit_and; + + template + struct bit_or; + + template + struct bit_xor; + + template + struct bit_not; +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 660. Missing Bitwise Operations. + template + struct bit_and : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x & __y; } + }; + + template + struct bit_or : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x | __y; } + }; + + template + struct bit_xor : public binary_function<_Tp, _Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x, const _Tp& __y) const + { return __x ^ __y; } + }; + + template + struct bit_not : public unary_function<_Tp, _Tp> + { + _GLIBCXX14_CONSTEXPR + _Tp + operator()(const _Tp& __x) const + { return ~__x; } + }; + +#if __cplusplus > 201103L + template <> + struct bit_and + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) & std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) & std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) & std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_or + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) | std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) | std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) | std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_xor + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u))) + -> decltype(std::forward<_Tp>(__t) ^ std::forward<_Up>(__u)) + { return std::forward<_Tp>(__t) ^ std::forward<_Up>(__u); } + + typedef __is_transparent is_transparent; + }; + + template <> + struct bit_not + { + template + _GLIBCXX14_CONSTEXPR + auto + operator()(_Tp&& __t) const + noexcept(noexcept(~std::forward<_Tp>(__t))) + -> decltype(~std::forward<_Tp>(__t)) + { return ~std::forward<_Tp>(__t); } + + typedef __is_transparent is_transparent; + }; +#endif + + // 20.3.5 negators + /** @defgroup negators Negators + * @ingroup functors + * + * The functions @c not1 and @c not2 each take a predicate functor + * and return an instance of @c unary_negate or + * @c binary_negate, respectively. These classes are functors whose + * @c operator() performs the stored predicate function and then returns + * the negation of the result. + * + * For example, given a vector of integers and a trivial predicate, + * \code + * struct IntGreaterThanThree + * : public std::unary_function + * { + * bool operator() (int x) { return x > 3; } + * }; + * + * std::find_if (v.begin(), v.end(), not1(IntGreaterThanThree())); + * \endcode + * The call to @c find_if will locate the first index (i) of @c v for which + * !(v[i] > 3) is true. + * + * The not1/unary_negate combination works on predicates taking a single + * argument. The not2/binary_negate combination works on predicates which + * take two arguments. + * + * @{ + */ + /// One of the @link negators negation functors@endlink. + template + class unary_negate + : public unary_function + { + protected: + _Predicate _M_pred; + + public: + _GLIBCXX14_CONSTEXPR + explicit + unary_negate(const _Predicate& __x) : _M_pred(__x) { } + + _GLIBCXX14_CONSTEXPR + bool + operator()(const typename _Predicate::argument_type& __x) const + { return !_M_pred(__x); } + }; + + /// One of the @link negators negation functors@endlink. + template + _GLIBCXX14_CONSTEXPR + inline unary_negate<_Predicate> + not1(const _Predicate& __pred) + { return unary_negate<_Predicate>(__pred); } + + /// One of the @link negators negation functors@endlink. + template + class binary_negate + : public binary_function + { + protected: + _Predicate _M_pred; + + public: + _GLIBCXX14_CONSTEXPR + explicit + binary_negate(const _Predicate& __x) : _M_pred(__x) { } + + _GLIBCXX14_CONSTEXPR + bool + operator()(const typename _Predicate::first_argument_type& __x, + const typename _Predicate::second_argument_type& __y) const + { return !_M_pred(__x, __y); } + }; + + /// One of the @link negators negation functors@endlink. + template + _GLIBCXX14_CONSTEXPR + inline binary_negate<_Predicate> + not2(const _Predicate& __pred) + { return binary_negate<_Predicate>(__pred); } + /** @} */ + + // 20.3.7 adaptors pointers functions + /** @defgroup pointer_adaptors Adaptors for pointers to functions + * @ingroup functors + * + * The advantage of function objects over pointers to functions is that + * the objects in the standard library declare nested typedefs describing + * their argument and result types with uniform names (e.g., @c result_type + * from the base classes @c unary_function and @c binary_function). + * Sometimes those typedefs are required, not just optional. + * + * Adaptors are provided to turn pointers to unary (single-argument) and + * binary (double-argument) functions into function objects. The + * long-winded functor @c pointer_to_unary_function is constructed with a + * function pointer @c f, and its @c operator() called with argument @c x + * returns @c f(x). The functor @c pointer_to_binary_function does the same + * thing, but with a double-argument @c f and @c operator(). + * + * The function @c ptr_fun takes a pointer-to-function @c f and constructs + * an instance of the appropriate functor. + * + * @{ + */ + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + class pointer_to_unary_function : public unary_function<_Arg, _Result> + { + protected: + _Result (*_M_ptr)(_Arg); + + public: + pointer_to_unary_function() { } + + explicit + pointer_to_unary_function(_Result (*__x)(_Arg)) + : _M_ptr(__x) { } + + _Result + operator()(_Arg __x) const + { return _M_ptr(__x); } + }; + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + inline pointer_to_unary_function<_Arg, _Result> + ptr_fun(_Result (*__x)(_Arg)) + { return pointer_to_unary_function<_Arg, _Result>(__x); } + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + class pointer_to_binary_function + : public binary_function<_Arg1, _Arg2, _Result> + { + protected: + _Result (*_M_ptr)(_Arg1, _Arg2); + + public: + pointer_to_binary_function() { } + + explicit + pointer_to_binary_function(_Result (*__x)(_Arg1, _Arg2)) + : _M_ptr(__x) { } + + _Result + operator()(_Arg1 __x, _Arg2 __y) const + { return _M_ptr(__x, __y); } + }; + + /// One of the @link pointer_adaptors adaptors for function pointers@endlink. + template + inline pointer_to_binary_function<_Arg1, _Arg2, _Result> + ptr_fun(_Result (*__x)(_Arg1, _Arg2)) + { return pointer_to_binary_function<_Arg1, _Arg2, _Result>(__x); } + /** @} */ + + template + struct _Identity + : public unary_function<_Tp, _Tp> + { + _Tp& + operator()(_Tp& __x) const + { return __x; } + + const _Tp& + operator()(const _Tp& __x) const + { return __x; } + }; + + // Partial specialization, avoids confusing errors in e.g. std::set. + template struct _Identity : _Identity<_Tp> { }; + + template + struct _Select1st + : public unary_function<_Pair, typename _Pair::first_type> + { + typename _Pair::first_type& + operator()(_Pair& __x) const + { return __x.first; } + + const typename _Pair::first_type& + operator()(const _Pair& __x) const + { return __x.first; } + +#if __cplusplus >= 201103L + template + typename _Pair2::first_type& + operator()(_Pair2& __x) const + { return __x.first; } + + template + const typename _Pair2::first_type& + operator()(const _Pair2& __x) const + { return __x.first; } +#endif + }; + + template + struct _Select2nd + : public unary_function<_Pair, typename _Pair::second_type> + { + typename _Pair::second_type& + operator()(_Pair& __x) const + { return __x.second; } + + const typename _Pair::second_type& + operator()(const _Pair& __x) const + { return __x.second; } + }; + + // 20.3.8 adaptors pointers members + /** @defgroup memory_adaptors Adaptors for pointers to members + * @ingroup functors + * + * There are a total of 8 = 2^3 function objects in this family. + * (1) Member functions taking no arguments vs member functions taking + * one argument. + * (2) Call through pointer vs call through reference. + * (3) Const vs non-const member function. + * + * All of this complexity is in the function objects themselves. You can + * ignore it by using the helper function mem_fun and mem_fun_ref, + * which create whichever type of adaptor is appropriate. + * + * @{ + */ + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class mem_fun_t : public unary_function<_Tp*, _Ret> + { + public: + explicit + mem_fun_t(_Ret (_Tp::*__pf)()) + : _M_f(__pf) { } + + _Ret + operator()(_Tp* __p) const + { return (__p->*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)(); + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class const_mem_fun_t : public unary_function + { + public: + explicit + const_mem_fun_t(_Ret (_Tp::*__pf)() const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp* __p) const + { return (__p->*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)() const; + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class mem_fun_ref_t : public unary_function<_Tp, _Ret> + { + public: + explicit + mem_fun_ref_t(_Ret (_Tp::*__pf)()) + : _M_f(__pf) { } + + _Ret + operator()(_Tp& __r) const + { return (__r.*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)(); + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class const_mem_fun_ref_t : public unary_function<_Tp, _Ret> + { + public: + explicit + const_mem_fun_ref_t(_Ret (_Tp::*__pf)() const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp& __r) const + { return (__r.*_M_f)(); } + + private: + _Ret (_Tp::*_M_f)() const; + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class mem_fun1_t : public binary_function<_Tp*, _Arg, _Ret> + { + public: + explicit + mem_fun1_t(_Ret (_Tp::*__pf)(_Arg)) + : _M_f(__pf) { } + + _Ret + operator()(_Tp* __p, _Arg __x) const + { return (__p->*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg); + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class const_mem_fun1_t : public binary_function + { + public: + explicit + const_mem_fun1_t(_Ret (_Tp::*__pf)(_Arg) const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp* __p, _Arg __x) const + { return (__p->*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg) const; + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class mem_fun1_ref_t : public binary_function<_Tp, _Arg, _Ret> + { + public: + explicit + mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg)) + : _M_f(__pf) { } + + _Ret + operator()(_Tp& __r, _Arg __x) const + { return (__r.*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg); + }; + + /// One of the @link memory_adaptors adaptors for member + /// pointers@endlink. + template + class const_mem_fun1_ref_t : public binary_function<_Tp, _Arg, _Ret> + { + public: + explicit + const_mem_fun1_ref_t(_Ret (_Tp::*__pf)(_Arg) const) + : _M_f(__pf) { } + + _Ret + operator()(const _Tp& __r, _Arg __x) const + { return (__r.*_M_f)(__x); } + + private: + _Ret (_Tp::*_M_f)(_Arg) const; + }; + + // Mem_fun adaptor helper functions. There are only two: + // mem_fun and mem_fun_ref. + template + inline mem_fun_t<_Ret, _Tp> + mem_fun(_Ret (_Tp::*__f)()) + { return mem_fun_t<_Ret, _Tp>(__f); } + + template + inline const_mem_fun_t<_Ret, _Tp> + mem_fun(_Ret (_Tp::*__f)() const) + { return const_mem_fun_t<_Ret, _Tp>(__f); } + + template + inline mem_fun_ref_t<_Ret, _Tp> + mem_fun_ref(_Ret (_Tp::*__f)()) + { return mem_fun_ref_t<_Ret, _Tp>(__f); } + + template + inline const_mem_fun_ref_t<_Ret, _Tp> + mem_fun_ref(_Ret (_Tp::*__f)() const) + { return const_mem_fun_ref_t<_Ret, _Tp>(__f); } + + template + inline mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun(_Ret (_Tp::*__f)(_Arg)) + { return mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + inline const_mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun(_Ret (_Tp::*__f)(_Arg) const) + { return const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + inline mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun_ref(_Ret (_Tp::*__f)(_Arg)) + { return mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + + template + inline const_mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun_ref(_Ret (_Tp::*__f)(_Arg) const) + { return const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + + /** @} */ + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if (__cplusplus < 201103L) || _GLIBCXX_USE_DEPRECATED +# include +#endif + +#endif /* _STL_FUNCTION_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_heap.h b/resources/sources/avr-libstdcpp/include/bits/stl_heap.h new file mode 100644 index 000000000..52e3a3b44 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_heap.h @@ -0,0 +1,583 @@ +// Heap implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_heap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{queue} + */ + +#ifndef _STL_HEAP_H +#define _STL_HEAP_H 1 + +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup heap_algorithms Heap + * @ingroup sorting_algorithms + */ + + template + _GLIBCXX20_CONSTEXPR + _Distance + __is_heap_until(_RandomAccessIterator __first, _Distance __n, + _Compare& __comp) + { + _Distance __parent = 0; + for (_Distance __child = 1; __child < __n; ++__child) + { + if (__comp(__first + __parent, __first + __child)) + return __child; + if ((__child & 1) == 0) + ++__parent; + } + return __n; + } + + // __is_heap, a predicate testing whether or not a range is a heap. + // This function is an extension, not part of the C++ standard. + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _Distance __n) + { + __gnu_cxx::__ops::_Iter_less_iter __comp; + return std::__is_heap_until(__first, __n, __comp) == __n; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _Compare __comp, _Distance __n) + { + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __n, __cmp) == __n; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { return std::__is_heap(__first, std::distance(__first, __last)); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + return std::__is_heap(__first, _GLIBCXX_MOVE(__comp), + std::distance(__first, __last)); + } + + // Heap-manipulation functions: push_heap, pop_heap, make_heap, sort_heap, + // + is_heap and is_heap_until in C++0x. + + template + _GLIBCXX20_CONSTEXPR + void + __push_heap(_RandomAccessIterator __first, + _Distance __holeIndex, _Distance __topIndex, _Tp __value, + _Compare& __comp) + { + _Distance __parent = (__holeIndex - 1) / 2; + while (__holeIndex > __topIndex && __comp(__first + __parent, __value)) + { + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __parent)); + __holeIndex = __parent; + __parent = (__holeIndex - 1) / 2; + } + *(__first + __holeIndex) = _GLIBCXX_MOVE(__value); + } + + /** + * @brief Push an element onto a heap. + * @param __first Start of heap. + * @param __last End of heap + element. + * @ingroup heap_algorithms + * + * This operation pushes the element at last-1 onto the valid heap + * over the range [__first,__last-1). After completion, + * [__first,__last) is a valid heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept<_ValueType>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last - 1); + + __gnu_cxx::__ops::_Iter_less_val __comp; + _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); + std::__push_heap(__first, _DistanceType((__last - __first) - 1), + _DistanceType(0), _GLIBCXX_MOVE(__value), __comp); + } + + /** + * @brief Push an element onto a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap + element. + * @param __comp Comparison functor. + * @ingroup heap_algorithms + * + * This operation pushes the element at __last-1 onto the valid + * heap over the range [__first,__last-1). After completion, + * [__first,__last) is a valid heap. Compare operations are + * performed using comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + push_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_heap_pred(__first, __last - 1, __comp); + + __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) + __cmp(_GLIBCXX_MOVE(__comp)); + _ValueType __value = _GLIBCXX_MOVE(*(__last - 1)); + std::__push_heap(__first, _DistanceType((__last - __first) - 1), + _DistanceType(0), _GLIBCXX_MOVE(__value), __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __adjust_heap(_RandomAccessIterator __first, _Distance __holeIndex, + _Distance __len, _Tp __value, _Compare __comp) + { + const _Distance __topIndex = __holeIndex; + _Distance __secondChild = __holeIndex; + while (__secondChild < (__len - 1) / 2) + { + __secondChild = 2 * (__secondChild + 1); + if (__comp(__first + __secondChild, + __first + (__secondChild - 1))) + __secondChild--; + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + __secondChild)); + __holeIndex = __secondChild; + } + if ((__len & 1) == 0 && __secondChild == (__len - 2) / 2) + { + __secondChild = 2 * (__secondChild + 1); + *(__first + __holeIndex) = _GLIBCXX_MOVE(*(__first + + (__secondChild - 1))); + __holeIndex = __secondChild - 1; + } + __decltype(__gnu_cxx::__ops::__iter_comp_val(_GLIBCXX_MOVE(__comp))) + __cmp(_GLIBCXX_MOVE(__comp)); + std::__push_heap(__first, __holeIndex, __topIndex, + _GLIBCXX_MOVE(__value), __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + inline void + __pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _RandomAccessIterator __result, _Compare& __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + _ValueType __value = _GLIBCXX_MOVE(*__result); + *__result = _GLIBCXX_MOVE(*__first); + std::__adjust_heap(__first, _DistanceType(0), + _DistanceType(__last - __first), + _GLIBCXX_MOVE(__value), __comp); + } + + /** + * @brief Pop an element off a heap. + * @param __first Start of heap. + * @param __last End of heap. + * @pre [__first, __last) is a valid, non-empty range. + * @ingroup heap_algorithms + * + * This operation pops the top of the heap. The elements __first + * and __last-1 are swapped and [__first,__last-1) is made into a + * heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + pop_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_non_empty_range(__first, __last); + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last); + + if (__last - __first > 1) + { + --__last; + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__pop_heap(__first, __last, __last, __comp); + } + } + + /** + * @brief Pop an element off a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation pops the top of the heap. The elements __first + * and __last-1 are swapped and [__first,__last-1) is made into a + * heap. Comparisons are made using comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + pop_heap(_RandomAccessIterator __first, + _RandomAccessIterator __last, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_non_empty_range(__first, __last); + __glibcxx_requires_heap_pred(__first, __last, __comp); + + if (__last - __first > 1) + { + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + --__last; + std::__pop_heap(__first, __last, __last, __cmp); + } + } + + template + _GLIBCXX20_CONSTEXPR + void + __make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare& __comp) + { + typedef typename iterator_traits<_RandomAccessIterator>::value_type + _ValueType; + typedef typename iterator_traits<_RandomAccessIterator>::difference_type + _DistanceType; + + if (__last - __first < 2) + return; + + const _DistanceType __len = __last - __first; + _DistanceType __parent = (__len - 2) / 2; + while (true) + { + _ValueType __value = _GLIBCXX_MOVE(*(__first + __parent)); + std::__adjust_heap(__first, __parent, __len, _GLIBCXX_MOVE(__value), + __comp); + if (__parent == 0) + return; + __parent--; + } + } + + /** + * @brief Construct a heap over a range. + * @param __first Start of heap. + * @param __last End of heap. + * @ingroup heap_algorithms + * + * This operation makes the elements in [__first,__last) into a heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__make_heap(__first, __last, __comp); + } + + /** + * @brief Construct a heap over a range using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation makes the elements in [__first,__last) into a heap. + * Comparisons are made using __comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + make_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + std::__make_heap(__first, __last, __cmp); + } + + template + _GLIBCXX20_CONSTEXPR + void + __sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare& __comp) + { + while (__last - __first > 1) + { + --__last; + std::__pop_heap(__first, __last, __last, __comp); + } + } + + /** + * @brief Sort a heap. + * @param __first Start of heap. + * @param __last End of heap. + * @ingroup heap_algorithms + * + * This operation sorts the valid heap in the range [__first,__last). + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + __glibcxx_requires_heap(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + std::__sort_heap(__first, __last, __comp); + } + + /** + * @brief Sort a heap using comparison functor. + * @param __first Start of heap. + * @param __last End of heap. + * @param __comp Comparison functor to use. + * @ingroup heap_algorithms + * + * This operation sorts the valid heap in the range [__first,__last). + * Comparisons are made using __comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline void + sort_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + __glibcxx_requires_heap_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + std::__sort_heap(__first, __last, __cmp); + } + +#if __cplusplus >= 201103L + /** + * @brief Search the end of a heap. + * @param __first Start of range. + * @param __last End of range. + * @return An iterator pointing to the first element not in the heap. + * @ingroup heap_algorithms + * + * This operation returns the last iterator i in [__first, __last) for which + * the range [__first, i) is a heap. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive(__first, __last); + + __gnu_cxx::__ops::_Iter_less_iter __comp; + return __first + + std::__is_heap_until(__first, std::distance(__first, __last), __comp); + } + + /** + * @brief Search the end of a heap using comparison functor. + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor to use. + * @return An iterator pointing to the first element not in the heap. + * @ingroup heap_algorithms + * + * This operation returns the last iterator i in [__first, __last) for which + * the range [__first, i) is a heap. Comparisons are made using __comp. + */ + template + _GLIBCXX20_CONSTEXPR + inline _RandomAccessIterator + is_heap_until(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return __first + + std::__is_heap_until(__first, std::distance(__first, __last), __cmp); + } + + /** + * @brief Determines whether a range is a heap. + * @param __first Start of range. + * @param __last End of range. + * @return True if range is a heap, false otherwise. + * @ingroup heap_algorithms + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { return std::is_heap_until(__first, __last) == __last; } + + /** + * @brief Determines whether a range is a heap using comparison functor. + * @param __first Start of range. + * @param __last End of range. + * @param __comp Comparison functor to use. + * @return True if range is a heap, false otherwise. + * @ingroup heap_algorithms + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_irreflexive_pred(__first, __last, __comp); + + const auto __dist = std::distance(__first, __last); + typedef __decltype(__comp) _Cmp; + __gnu_cxx::__ops::_Iter_comp_iter<_Cmp> __cmp(_GLIBCXX_MOVE(__comp)); + return std::__is_heap_until(__first, __dist, __cmp) == __dist; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_HEAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h new file mode 100644 index 000000000..7d293ce3f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_iterator.h @@ -0,0 +1,2238 @@ +// Iterators -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file implements reverse_iterator, back_insert_iterator, + * front_insert_iterator, insert_iterator, __normal_iterator, and their + * supporting functions and overloaded operators. + */ + +#ifndef _STL_ITERATOR_H +#define _STL_ITERATOR_H 1 + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +# include +#endif + +#if __cplusplus > 201703L +# define __cpp_lib_array_constexpr 201811L +# define __cpp_lib_constexpr_iterator 201811L +#elif __cplusplus == 201703L +# define __cpp_lib_array_constexpr 201803L +#endif + +#if __cplusplus > 201703L +# include +# include +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup iterators + * @{ + */ + +#if __cplusplus > 201703L && __cpp_lib_concepts + namespace __detail + { + // Weaken iterator_category _Cat to _Limit if it is derived from that, + // otherwise use _Otherwise. + template + using __clamp_iter_cat + = conditional_t, _Limit, _Otherwise>; + } +#endif + + // 24.4.1 Reverse iterators + /** + * Bidirectional and random access iterators have corresponding reverse + * %iterator adaptors that iterate through the data structure in the + * opposite direction. They have the same signatures as the corresponding + * iterators. The fundamental relation between a reverse %iterator and its + * corresponding %iterator @c i is established by the identity: + * @code + * &*(reverse_iterator(i)) == &*(i - 1) + * @endcode + * + * This mapping is dictated by the fact that while there is always a + * pointer past the end of an array, there might not be a valid pointer + * before the beginning of an array. [24.4.1]/1,2 + * + * Reverse iterators can be tricky and surprising at first. Their + * semantics make sense, however, and the trickiness is a side effect of + * the requirement that the iterators must be safe. + */ + template + class reverse_iterator + : public iterator::iterator_category, + typename iterator_traits<_Iterator>::value_type, + typename iterator_traits<_Iterator>::difference_type, + typename iterator_traits<_Iterator>::pointer, + typename iterator_traits<_Iterator>::reference> + { + protected: + _Iterator current; + + typedef iterator_traits<_Iterator> __traits_type; + + public: + typedef _Iterator iterator_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::pointer pointer; + typedef typename __traits_type::reference reference; + +#if __cplusplus > 201703L && __cpp_lib_concepts + using iterator_concept + = conditional_t, + random_access_iterator_tag, + bidirectional_iterator_tag>; + using iterator_category + = __detail::__clamp_iter_cat; +#endif + + /** + * The default constructor value-initializes member @p current. + * If it is a pointer, that means it is zero-initialized. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 235 No specification of default ctor for reverse_iterator + // 1012. reverse_iterator default ctor should value initialize + _GLIBCXX17_CONSTEXPR + reverse_iterator() : current() { } + + /** + * This %iterator will move in the opposite direction that @p x does. + */ + explicit _GLIBCXX17_CONSTEXPR + reverse_iterator(iterator_type __x) : current(__x) { } + + /** + * The copy constructor is normal. + */ + _GLIBCXX17_CONSTEXPR + reverse_iterator(const reverse_iterator& __x) + : current(__x.current) { } + +#if __cplusplus >= 201103L + reverse_iterator& operator=(const reverse_iterator&) = default; +#endif + + /** + * A %reverse_iterator across other types can be copied if the + * underlying %iterator can be converted to the type of @c current. + */ + template + _GLIBCXX17_CONSTEXPR + reverse_iterator(const reverse_iterator<_Iter>& __x) + : current(__x.base()) { } + + /** + * @return @c current, the %iterator used for underlying work. + */ + _GLIBCXX17_CONSTEXPR iterator_type + base() const + { return current; } + + /** + * @return A reference to the value at @c --current + * + * This requires that @c --current is dereferenceable. + * + * @warning This implementation requires that for an iterator of the + * underlying iterator type, @c x, a reference obtained by + * @c *x remains valid after @c x has been modified or + * destroyed. This is a bug: http://gcc.gnu.org/PR51823 + */ + _GLIBCXX17_CONSTEXPR reference + operator*() const + { + _Iterator __tmp = current; + return *--__tmp; + } + + /** + * @return A pointer to the value at @c --current + * + * This requires that @c --current is dereferenceable. + */ + _GLIBCXX17_CONSTEXPR pointer + operator->() const +#if __cplusplus > 201703L && __cpp_concepts >= 201907L + requires is_pointer_v<_Iterator> + || requires(const _Iterator __i) { __i.operator->(); } +#endif + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 1052. operator-> should also support smart pointers + _Iterator __tmp = current; + --__tmp; + return _S_to_pointer(__tmp); + } + + /** + * @return @c *this + * + * Decrements the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator++() + { + --current; + return *this; + } + + /** + * @return The original value of @c *this + * + * Decrements the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator++(int) + { + reverse_iterator __tmp = *this; + --current; + return __tmp; + } + + /** + * @return @c *this + * + * Increments the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator--() + { + ++current; + return *this; + } + + /** + * @return A reverse_iterator with the previous value of @c *this + * + * Increments the underlying iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator--(int) + { + reverse_iterator __tmp = *this; + ++current; + return __tmp; + } + + /** + * @return A reverse_iterator that refers to @c current - @a __n + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator+(difference_type __n) const + { return reverse_iterator(current - __n); } + + /** + * @return *this + * + * Moves the underlying iterator backwards @a __n steps. + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator+=(difference_type __n) + { + current -= __n; + return *this; + } + + /** + * @return A reverse_iterator that refers to @c current - @a __n + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator + operator-(difference_type __n) const + { return reverse_iterator(current + __n); } + + /** + * @return *this + * + * Moves the underlying iterator forwards @a __n steps. + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reverse_iterator& + operator-=(difference_type __n) + { + current += __n; + return *this; + } + + /** + * @return The value at @c current - @a __n - 1 + * + * The underlying iterator must be a Random Access Iterator. + */ + _GLIBCXX17_CONSTEXPR reference + operator[](difference_type __n) const + { return *(*this + __n); } + +#if __cplusplus > 201703L && __cpp_lib_concepts + friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const reverse_iterator& __i) + noexcept(is_nothrow_copy_constructible_v<_Iterator> + && noexcept(ranges::iter_move(--std::declval<_Iterator&>()))) + { + auto __tmp = __i.base(); + return ranges::iter_move(--__tmp); + } + + template _Iter2> + friend constexpr void + iter_swap(const reverse_iterator& __x, + const reverse_iterator<_Iter2>& __y) + noexcept(is_nothrow_copy_constructible_v<_Iterator> + && is_nothrow_copy_constructible_v<_Iter2> + && noexcept(ranges::iter_swap(--std::declval<_Iterator&>(), + --std::declval<_Iter2&>()))) + { + auto __xtmp = __x.base(); + auto __ytmp = __y.base(); + ranges::iter_swap(--__xtmp, --__ytmp); + } +#endif + + private: + template + static _GLIBCXX17_CONSTEXPR _Tp* + _S_to_pointer(_Tp* __p) + { return __p; } + + template + static _GLIBCXX17_CONSTEXPR pointer + _S_to_pointer(_Tp __t) + { return __t.operator->(); } + }; + + //@{ + /** + * @param __x A %reverse_iterator. + * @param __y A %reverse_iterator. + * @return A simple bool. + * + * Reverse iterators forward comparisons to their underlying base() + * iterators. + * + */ +#if __cplusplus <= 201703L || ! defined __cpp_lib_concepts + template + inline _GLIBCXX17_CONSTEXPR bool + operator==(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __x.base() == __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() < __x.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x == __y); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y < __x; } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__y < __x); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return !(__x < __y); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 280. Comparison of reverse_iterator to const reverse_iterator. + template + inline _GLIBCXX17_CONSTEXPR bool + operator==(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __x.base() == __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() < __x.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__x == __y); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y < __x; } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__y < __x); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return !(__x < __y); } +#else // C++20 + template + constexpr bool + operator==(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() == __y.base() } -> convertible_to; } + { return __x.base() == __y.base(); } + + template + constexpr bool + operator!=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() != __y.base() } -> convertible_to; } + { return __x.base() != __y.base(); } + + template + constexpr bool + operator<(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() > __y.base() } -> convertible_to; } + { return __x.base() > __y.base(); } + + template + constexpr bool + operator>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() < __y.base() } -> convertible_to; } + { return __x.base() < __y.base(); } + + template + constexpr bool + operator<=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() >= __y.base() } -> convertible_to; } + { return __x.base() >= __y.base(); } + + template + constexpr bool + operator>=(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + requires requires { { __x.base() <= __y.base() } -> convertible_to; } + { return __x.base() <= __y.base(); } + + template _IteratorR> + constexpr compare_three_way_result_t<_IteratorL, _IteratorR> + operator<=>(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() <=> __x.base(); } +#endif // C++20 + //@} + +#if __cplusplus < 201103L + template + inline typename reverse_iterator<_Iterator>::difference_type + operator-(const reverse_iterator<_Iterator>& __x, + const reverse_iterator<_Iterator>& __y) + { return __y.base() - __x.base(); } + + template + inline typename reverse_iterator<_IteratorL>::difference_type + operator-(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + { return __y.base() - __x.base(); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 685. reverse_iterator/move_iterator difference has invalid signatures + template + inline _GLIBCXX17_CONSTEXPR auto + operator-(const reverse_iterator<_IteratorL>& __x, + const reverse_iterator<_IteratorR>& __y) + -> decltype(__y.base() - __x.base()) + { return __y.base() - __x.base(); } +#endif + + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + operator+(typename reverse_iterator<_Iterator>::difference_type __n, + const reverse_iterator<_Iterator>& __x) + { return reverse_iterator<_Iterator>(__x.base() - __n); } + +#if __cplusplus >= 201103L + // Same as C++14 make_reverse_iterator but used in C++11 mode too. + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + __make_reverse_iterator(_Iterator __i) + { return reverse_iterator<_Iterator>(__i); } + +# if __cplusplus >= 201402L +# define __cpp_lib_make_reverse_iterator 201402 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 2285. make_reverse_iterator + /// Generator function for reverse_iterator. + template + inline _GLIBCXX17_CONSTEXPR reverse_iterator<_Iterator> + make_reverse_iterator(_Iterator __i) + { return reverse_iterator<_Iterator>(__i); } + +# if __cplusplus > 201703L && defined __cpp_lib_concepts + template + requires (!sized_sentinel_for<_Iterator1, _Iterator2>) + inline constexpr bool + disable_sized_sentinel_for, + reverse_iterator<_Iterator2>> = true; +# endif // C++20 +# endif // C++14 + + template + _GLIBCXX20_CONSTEXPR + auto + __niter_base(reverse_iterator<_Iterator> __it) + -> decltype(__make_reverse_iterator(__niter_base(__it.base()))) + { return __make_reverse_iterator(__niter_base(__it.base())); } + + template + struct __is_move_iterator > + : __is_move_iterator<_Iterator> + { }; + + template + _GLIBCXX20_CONSTEXPR + auto + __miter_base(reverse_iterator<_Iterator> __it) + -> decltype(__make_reverse_iterator(__miter_base(__it.base()))) + { return __make_reverse_iterator(__miter_base(__it.base())); } +#endif // C++11 + + // 24.4.2.2.1 back_insert_iterator + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator appends it to the container using + * push_back. + * + * Tip: Using the back_inserter function to create these iterators can + * save typing. + */ + template + class back_insert_iterator + : public iterator + { + protected: + _Container* container; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; + + constexpr back_insert_iterator() noexcept : container(nullptr) { } +#endif + + /// The only way to create this %iterator is with a container. + explicit _GLIBCXX20_CONSTEXPR + back_insert_iterator(_Container& __x) + : container(std::__addressof(__x)) { } + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator doesn't really have a @a position in the + * container (you can think of the position as being permanently at + * the end, if you like). Assigning a value to the %iterator will + * always append the value to the end of the container. + */ +#if __cplusplus < 201103L + back_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_back(__value); + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator=(const typename _Container::value_type& __value) + { + container->push_back(__value); + return *this; + } + + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator=(typename _Container::value_type&& __value) + { + container->push_back(std::move(__value)); + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + back_insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + back_insert_iterator + operator++(int) + { return *this; } + }; + + /** + * @param __x A container of arbitrary type. + * @return An instance of back_insert_iterator working on @p __x. + * + * This wrapper function helps in creating back_insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template + _GLIBCXX20_CONSTEXPR + inline back_insert_iterator<_Container> + back_inserter(_Container& __x) + { return back_insert_iterator<_Container>(__x); } + + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator prepends it to the container using + * push_front. + * + * Tip: Using the front_inserter function to create these iterators can + * save typing. + */ + template + class front_insert_iterator + : public iterator + { + protected: + _Container* container; + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; +#if __cplusplus > 201703L + using difference_type = ptrdiff_t; + + constexpr front_insert_iterator() noexcept : container(nullptr) { } +#endif + + /// The only way to create this %iterator is with a container. + explicit _GLIBCXX20_CONSTEXPR + front_insert_iterator(_Container& __x) + : container(std::__addressof(__x)) { } + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator doesn't really have a @a position in the + * container (you can think of the position as being permanently at + * the front, if you like). Assigning a value to the %iterator will + * always prepend the value to the front of the container. + */ +#if __cplusplus < 201103L + front_insert_iterator& + operator=(typename _Container::const_reference __value) + { + container->push_front(__value); + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator=(const typename _Container::value_type& __value) + { + container->push_front(__value); + return *this; + } + + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator=(typename _Container::value_type&& __value) + { + container->push_front(std::move(__value)); + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + front_insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + front_insert_iterator + operator++(int) + { return *this; } + }; + + /** + * @param __x A container of arbitrary type. + * @return An instance of front_insert_iterator working on @p x. + * + * This wrapper function helps in creating front_insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ + template + _GLIBCXX20_CONSTEXPR + inline front_insert_iterator<_Container> + front_inserter(_Container& __x) + { return front_insert_iterator<_Container>(__x); } + + /** + * @brief Turns assignment into insertion. + * + * These are output iterators, constructed from a container-of-T. + * Assigning a T to the iterator inserts it in the container at the + * %iterator's position, rather than overwriting the value at that + * position. + * + * (Sequences will actually insert a @e copy of the value before the + * %iterator's position.) + * + * Tip: Using the inserter function to create these iterators can + * save typing. + */ + template + class insert_iterator + : public iterator + { +#if __cplusplus > 201703L && defined __cpp_lib_concepts + using _Iter = std::__detail::__range_iter_t<_Container>; + + protected: + _Container* container = nullptr; + _Iter iter = _Iter(); +#else + typedef typename _Container::iterator _Iter; + + protected: + _Container* container; + _Iter iter; +#endif + + public: + /// A nested typedef for the type of whatever container you used. + typedef _Container container_type; + +#if __cplusplus > 201703L && defined __cpp_lib_concepts + using difference_type = ptrdiff_t; + + insert_iterator() = default; +#endif + + /** + * The only way to create this %iterator is with a container and an + * initial position (a normal %iterator into the container). + */ + _GLIBCXX20_CONSTEXPR + insert_iterator(_Container& __x, _Iter __i) + : container(std::__addressof(__x)), iter(__i) {} + + /** + * @param __value An instance of whatever type + * container_type::const_reference is; presumably a + * reference-to-const T for container. + * @return This %iterator, for chained operations. + * + * This kind of %iterator maintains its own position in the + * container. Assigning a value to the %iterator will insert the + * value into the container at the place before the %iterator. + * + * The position is maintained such that subsequent assignments will + * insert values immediately after one another. For example, + * @code + * // vector v contains A and Z + * + * insert_iterator i (v, ++v.begin()); + * i = 1; + * i = 2; + * i = 3; + * + * // vector v contains A, 1, 2, 3, and Z + * @endcode + */ +#if __cplusplus < 201103L + insert_iterator& + operator=(typename _Container::const_reference __value) + { + iter = container->insert(iter, __value); + ++iter; + return *this; + } +#else + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator=(const typename _Container::value_type& __value) + { + iter = container->insert(iter, __value); + ++iter; + return *this; + } + + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator=(typename _Container::value_type&& __value) + { + iter = container->insert(iter, std::move(__value)); + ++iter; + return *this; + } +#endif + + /// Simply returns *this. + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator*() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator++() + { return *this; } + + /// Simply returns *this. (This %iterator does not @a move.) + _GLIBCXX20_CONSTEXPR + insert_iterator& + operator++(int) + { return *this; } + }; + + /** + * @param __x A container of arbitrary type. + * @param __i An iterator into the container. + * @return An instance of insert_iterator working on @p __x. + * + * This wrapper function helps in creating insert_iterator instances. + * Typing the name of the %iterator requires knowing the precise full + * type of the container, which can be tedious and impedes generic + * programming. Using this function lets you take advantage of automatic + * template parameter deduction, making the compiler match the correct + * types for you. + */ +#if __cplusplus > 201703L && defined __cpp_lib_concepts + template + constexpr insert_iterator<_Container> + inserter(_Container& __x, std::__detail::__range_iter_t<_Container> __i) + { return insert_iterator<_Container>(__x, __i); } +#else + template + inline insert_iterator<_Container> + inserter(_Container& __x, _Iterator __i) + { + return insert_iterator<_Container>(__x, + typename _Container::iterator(__i)); + } +#endif + + // @} group iterators + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // This iterator adapter is @a normal in the sense that it does not + // change the semantics of any of the operators of its iterator + // parameter. Its primary purpose is to convert an iterator that is + // not a class, e.g. a pointer, into an iterator that is a class. + // The _Container parameter exists solely so that different containers + // using this template can instantiate different types, even if the + // _Iterator parameter is the same. + template + class __normal_iterator + { + protected: + _Iterator _M_current; + + typedef std::iterator_traits<_Iterator> __traits_type; + + public: + typedef _Iterator iterator_type; + typedef typename __traits_type::iterator_category iterator_category; + typedef typename __traits_type::value_type value_type; + typedef typename __traits_type::difference_type difference_type; + typedef typename __traits_type::reference reference; + typedef typename __traits_type::pointer pointer; + +#if __cplusplus > 201703L && __cpp_lib_concepts + using iterator_concept = std::__detail::__iter_concept<_Iterator>; +#endif + + _GLIBCXX_CONSTEXPR __normal_iterator() _GLIBCXX_NOEXCEPT + : _M_current(_Iterator()) { } + + explicit _GLIBCXX20_CONSTEXPR + __normal_iterator(const _Iterator& __i) _GLIBCXX_NOEXCEPT + : _M_current(__i) { } + + // Allow iterator to const_iterator conversion + template + _GLIBCXX20_CONSTEXPR + __normal_iterator(const __normal_iterator<_Iter, + typename __enable_if< + (std::__are_same<_Iter, typename _Container::pointer>::__value), + _Container>::__type>& __i) _GLIBCXX_NOEXCEPT + : _M_current(__i.base()) { } + + // Forward iterator requirements + _GLIBCXX20_CONSTEXPR + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *_M_current; } + + _GLIBCXX20_CONSTEXPR + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return _M_current; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator++() _GLIBCXX_NOEXCEPT + { + ++_M_current; + return *this; + } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator++(int) _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current++); } + + // Bidirectional iterator requirements + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator--() _GLIBCXX_NOEXCEPT + { + --_M_current; + return *this; + } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator--(int) _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current--); } + + // Random access iterator requirements + _GLIBCXX20_CONSTEXPR + reference + operator[](difference_type __n) const _GLIBCXX_NOEXCEPT + { return _M_current[__n]; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator+=(difference_type __n) _GLIBCXX_NOEXCEPT + { _M_current += __n; return *this; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator+(difference_type __n) const _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current + __n); } + + _GLIBCXX20_CONSTEXPR + __normal_iterator& + operator-=(difference_type __n) _GLIBCXX_NOEXCEPT + { _M_current -= __n; return *this; } + + _GLIBCXX20_CONSTEXPR + __normal_iterator + operator-(difference_type __n) const _GLIBCXX_NOEXCEPT + { return __normal_iterator(_M_current - __n); } + + _GLIBCXX20_CONSTEXPR + const _Iterator& + base() const _GLIBCXX_NOEXCEPT + { return _M_current; } + }; + + // Note: In what follows, the left- and right-hand-side iterators are + // allowed to vary in types (conceptually in cv-qualification) so that + // comparison between cv-qualified and non-cv-qualified iterators be + // valid. However, the greedy and unfriendly operators in std::rel_ops + // will make overload resolution ambiguous (when in scope) if we don't + // provide overloads whose operands are of the same type. Can someone + // remind me what generic programming is about? -- Gaby + +#if __cpp_lib_three_way_comparison + template + requires requires (_IteratorL __lhs, _IteratorR __rhs) + { { __lhs == __rhs } -> std::convertible_to; } + constexpr bool + operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + noexcept(noexcept(__lhs.base() == __rhs.base())) + { return __lhs.base() == __rhs.base(); } + + template + constexpr std::__detail::__synth3way_t<_IteratorR, _IteratorL> + operator<=>(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + noexcept(noexcept(std::__detail::__synth3way(__lhs.base(), __rhs.base()))) + { return std::__detail::__synth3way(__lhs.base(), __rhs.base()); } +#else + // Forward iterator requirements + template + _GLIBCXX20_CONSTEXPR + inline bool + operator==(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() == __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator==(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() == __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() != __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator!=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() != __rhs.base(); } + + // Random access iterator requirements + template + inline bool + operator<(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() < __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator<(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() < __rhs.base(); } + + template + inline bool + operator>(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() > __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator>(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() > __rhs.base(); } + + template + inline bool + operator<=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() <= __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator<=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() <= __rhs.base(); } + + template + inline bool + operator>=(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() >= __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + operator>=(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() >= __rhs.base(); } +#endif // three-way comparison + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // According to the resolution of DR179 not only the various comparison + // operators but also operator- must accept mixed iterator/const_iterator + // parameters. + template +#if __cplusplus >= 201103L + // DR 685. + _GLIBCXX20_CONSTEXPR + inline auto + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) noexcept + -> decltype(__lhs.base() - __rhs.base()) +#else + inline typename __normal_iterator<_IteratorL, _Container>::difference_type + operator-(const __normal_iterator<_IteratorL, _Container>& __lhs, + const __normal_iterator<_IteratorR, _Container>& __rhs) +#endif + { return __lhs.base() - __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline typename __normal_iterator<_Iterator, _Container>::difference_type + operator-(const __normal_iterator<_Iterator, _Container>& __lhs, + const __normal_iterator<_Iterator, _Container>& __rhs) + _GLIBCXX_NOEXCEPT + { return __lhs.base() - __rhs.base(); } + + template + _GLIBCXX20_CONSTEXPR + inline __normal_iterator<_Iterator, _Container> + operator+(typename __normal_iterator<_Iterator, _Container>::difference_type + __n, const __normal_iterator<_Iterator, _Container>& __i) + _GLIBCXX_NOEXCEPT + { return __normal_iterator<_Iterator, _Container>(__i.base() + __n); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + _GLIBCXX20_CONSTEXPR + _Iterator + __niter_base(__gnu_cxx::__normal_iterator<_Iterator, _Container> __it) + _GLIBCXX_NOEXCEPT_IF(std::is_nothrow_copy_constructible<_Iterator>::value) + { return __it.base(); } + +#if __cplusplus >= 201103L + /** + * @addtogroup iterators + * @{ + */ + +#if __cplusplus > 201703L && __cpp_lib_concepts + template + class move_sentinel + { + public: + constexpr + move_sentinel() + noexcept(is_nothrow_default_constructible_v<_Sent>) + : _M_last() { } + + constexpr explicit + move_sentinel(_Sent __s) + noexcept(is_nothrow_move_constructible_v<_Sent>) + : _M_last(std::move(__s)) { } + + template requires convertible_to + constexpr + move_sentinel(const move_sentinel<_S2>& __s) + noexcept(is_nothrow_constructible_v<_Sent, const _S2&>) + : _M_last(__s.base()) + { } + + template requires assignable_from<_Sent&, const _S2&> + constexpr move_sentinel& + operator=(const move_sentinel<_S2>& __s) + noexcept(is_nothrow_assignable_v<_Sent, const _S2&>) + { + _M_last = __s.base(); + return *this; + } + + constexpr _Sent + base() const + noexcept(is_nothrow_copy_constructible_v<_Sent>) + { return _M_last; } + + private: + _Sent _M_last; + }; +#endif // C++20 + + // 24.4.3 Move iterators + /** + * Class template move_iterator is an iterator adapter with the same + * behavior as the underlying iterator except that its dereference + * operator implicitly converts the value returned by the underlying + * iterator's dereference operator to an rvalue reference. Some + * generic algorithms can be called with move iterators to replace + * copying with moving. + */ + template + class move_iterator + { + _Iterator _M_current; + + using __traits_type = iterator_traits<_Iterator>; +#if __cplusplus > 201703L && __cpp_lib_concepts + using __base_cat = typename __traits_type::iterator_category; +#else + using __base_ref = typename __traits_type::reference; +#endif + + public: + using iterator_type = _Iterator; + +#if __cplusplus > 201703L && __cpp_lib_concepts + using iterator_concept = input_iterator_tag; + using iterator_category + = __detail::__clamp_iter_cat<__base_cat, random_access_iterator_tag>; + using value_type = iter_value_t<_Iterator>; + using difference_type = iter_difference_t<_Iterator>; + using pointer = _Iterator; + using reference = iter_rvalue_reference_t<_Iterator>; +#else + typedef typename __traits_type::iterator_category iterator_category; + typedef typename __traits_type::value_type value_type; + typedef typename __traits_type::difference_type difference_type; + // NB: DR 680. + typedef _Iterator pointer; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2106. move_iterator wrapping iterators returning prvalues + typedef typename conditional::value, + typename remove_reference<__base_ref>::type&&, + __base_ref>::type reference; +#endif + + _GLIBCXX17_CONSTEXPR + move_iterator() + : _M_current() { } + + explicit _GLIBCXX17_CONSTEXPR + move_iterator(iterator_type __i) + : _M_current(std::move(__i)) { } + + template + _GLIBCXX17_CONSTEXPR + move_iterator(const move_iterator<_Iter>& __i) + : _M_current(__i.base()) { } + +#if __cplusplus <= 201703L + _GLIBCXX17_CONSTEXPR iterator_type + base() const + { return _M_current; } +#else + constexpr iterator_type + base() const & +#if __cpp_lib_concepts + requires copy_constructible +#endif + { return _M_current; } + + constexpr iterator_type + base() && + { return std::move(_M_current); } +#endif + + _GLIBCXX17_CONSTEXPR reference + operator*() const +#if __cplusplus > 201703L && __cpp_lib_concepts + { return ranges::iter_move(_M_current); } +#else + { return static_cast(*_M_current); } +#endif + + _GLIBCXX17_CONSTEXPR pointer + operator->() const + { return _M_current; } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator++() + { + ++_M_current; + return *this; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator++(int) + { + move_iterator __tmp = *this; + ++_M_current; + return __tmp; + } + +#if __cpp_lib_concepts + constexpr void + operator++(int) requires (!forward_iterator<_Iterator>) + { ++_M_current; } +#endif + + _GLIBCXX17_CONSTEXPR move_iterator& + operator--() + { + --_M_current; + return *this; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator--(int) + { + move_iterator __tmp = *this; + --_M_current; + return __tmp; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator+(difference_type __n) const + { return move_iterator(_M_current + __n); } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator+=(difference_type __n) + { + _M_current += __n; + return *this; + } + + _GLIBCXX17_CONSTEXPR move_iterator + operator-(difference_type __n) const + { return move_iterator(_M_current - __n); } + + _GLIBCXX17_CONSTEXPR move_iterator& + operator-=(difference_type __n) + { + _M_current -= __n; + return *this; + } + + _GLIBCXX17_CONSTEXPR reference + operator[](difference_type __n) const +#if __cplusplus > 201703L && __cpp_lib_concepts + { return ranges::iter_move(_M_current + __n); } +#else + { return std::move(_M_current[__n]); } +#endif + +#if __cplusplus > 201703L && __cpp_lib_concepts + template _Sent> + friend constexpr bool + operator==(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { return __x.base() == __y.base(); } + + template _Sent> + friend constexpr iter_difference_t<_Iterator> + operator-(const move_sentinel<_Sent>& __x, const move_iterator& __y) + { return __x.base() - __y.base(); } + + template _Sent> + friend constexpr iter_difference_t<_Iterator> + operator-(const move_iterator& __x, const move_sentinel<_Sent>& __y) + { return __x.base() - __y.base(); } + + friend constexpr iter_rvalue_reference_t<_Iterator> + iter_move(const move_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + template _Iter2> + friend constexpr void + iter_swap(const move_iterator& __x, const move_iterator<_Iter2>& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + { return ranges::iter_swap(__x._M_current, __y._M_current); } +#endif // C++20 + }; + + template + inline _GLIBCXX17_CONSTEXPR bool + operator==(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __x.base() == __y.base() } -> convertible_to; } +#endif + { return __x.base() == __y.base(); } + +#if __cpp_lib_three_way_comparison + template _IteratorR> + constexpr compare_three_way_result_t<_IteratorL, _IteratorR> + operator<=>(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + { return __x.base() <=> __y.base(); } +#else + template + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + { return !(__x == __y); } +#endif + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __x.base() < __y.base() } -> convertible_to; } +#endif + { return __x.base() < __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __y.base() < __x.base() } -> convertible_to; } +#endif + { return !(__y < __x); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __y.base() < __x.base() } -> convertible_to; } +#endif + { return __y < __x; } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) +#if __cplusplus > 201703L && __cpp_lib_concepts + requires requires { { __x.base() < __y.base() } -> convertible_to; } +#endif + { return !(__x < __y); } + +#if ! (__cplusplus > 201703L && __cpp_lib_concepts) + // Note: See __normal_iterator operators note from Gaby to understand + // why we have these extra overloads for some move_iterator operators. + + // These extra overloads are not needed in C++20, because the ones above + // are constrained with a requires-clause and so overload resolution will + // prefer them to greedy unconstrained function templates. + + template + inline _GLIBCXX17_CONSTEXPR bool + operator==(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __x.base() == __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator!=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__x == __y); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __x.base() < __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator<=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__y < __x); } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return __y < __x; } + + template + inline _GLIBCXX17_CONSTEXPR bool + operator>=(const move_iterator<_Iterator>& __x, + const move_iterator<_Iterator>& __y) + { return !(__x < __y); } +#endif // ! C++20 + + // DR 685. + template + inline _GLIBCXX17_CONSTEXPR auto + operator-(const move_iterator<_IteratorL>& __x, + const move_iterator<_IteratorR>& __y) + -> decltype(__x.base() - __y.base()) + { return __x.base() - __y.base(); } + + template + inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> + operator+(typename move_iterator<_Iterator>::difference_type __n, + const move_iterator<_Iterator>& __x) + { return __x + __n; } + + template + inline _GLIBCXX17_CONSTEXPR move_iterator<_Iterator> + make_move_iterator(_Iterator __i) + { return move_iterator<_Iterator>(std::move(__i)); } + + template::value_type>::value, + _Iterator, move_iterator<_Iterator>>::type> + inline _GLIBCXX17_CONSTEXPR _ReturnType + __make_move_if_noexcept_iterator(_Iterator __i) + { return _ReturnType(__i); } + + // Overload for pointers that matches std::move_if_noexcept more closely, + // returning a constant iterator when we don't want to move. + template::value, + const _Tp*, move_iterator<_Tp*>>::type> + inline _GLIBCXX17_CONSTEXPR _ReturnType + __make_move_if_noexcept_iterator(_Tp* __i) + { return _ReturnType(__i); } + +#if __cplusplus > 201703L && __cpp_lib_concepts + // [iterators.common] Common iterators + + namespace __detail + { + template + concept __common_iter_has_arrow = indirectly_readable + && (requires(const _It& __it) { __it.operator->(); } + || is_reference_v> + || constructible_from, iter_reference_t<_It>>); + + } // namespace __detail + + /// An iterator/sentinel adaptor for representing a non-common range. + template _Sent> + requires (!same_as<_It, _Sent>) && copyable<_It> + class common_iterator + { + template + static constexpr bool + _S_noexcept1() + { + if constexpr (is_trivially_default_constructible_v<_Tp>) + return is_nothrow_assignable_v<_Tp, _Up>; + else + return is_nothrow_constructible_v<_Tp, _Up>; + } + + template + static constexpr bool + _S_noexcept() + { return _S_noexcept1<_It, _It2>() && _S_noexcept1<_Sent, _Sent2>(); } + + class _Proxy + { + iter_value_t<_It> _M_keep; + + _Proxy(iter_reference_t<_It>&& __x) + : _M_keep(std::move(__x)) { } + + friend class common_iterator; + + public: + const iter_value_t<_It>* + operator->() const + { return std::__addressof(_M_keep); } + }; + + public: + constexpr + common_iterator() + noexcept(is_nothrow_default_constructible_v<_It>) + : _M_it(), _M_index(0) + { } + + constexpr + common_iterator(_It __i) + noexcept(is_nothrow_move_constructible_v<_It>) + : _M_it(std::move(__i)), _M_index(0) + { } + + constexpr + common_iterator(_Sent __s) + noexcept(is_nothrow_move_constructible_v<_Sent>) + : _M_sent(std::move(__s)), _M_index(1) + { } + + template + requires convertible_to + && convertible_to + constexpr + common_iterator(const common_iterator<_It2, _Sent2>& __x) + noexcept(_S_noexcept()) + : _M_valueless(), _M_index(__x._M_index) + { + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = std::move(__x._M_it); + else + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = std::move(__x._M_sent); + else + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + } + } + + constexpr + common_iterator(const common_iterator& __x) + noexcept(_S_noexcept()) + : _M_valueless(), _M_index(__x._M_index) + { + if (_M_index == 0) + { + if constexpr (is_trivially_default_constructible_v<_It>) + _M_it = std::move(__x._M_it); + else + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + } + else if (_M_index == 1) + { + if constexpr (is_trivially_default_constructible_v<_Sent>) + _M_sent = std::move(__x._M_sent); + else + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + } + } + + common_iterator& + operator=(const common_iterator& __x) + noexcept(is_nothrow_copy_assignable_v<_It> + && is_nothrow_copy_assignable_v<_Sent> + && is_nothrow_copy_constructible_v<_It> + && is_nothrow_copy_constructible_v<_Sent>) + { + return this->operator=<_It, _Sent>(__x); + } + + template + requires convertible_to + && convertible_to + && assignable_from<_It&, const _It2&> + && assignable_from<_Sent&, const _Sent2&> + common_iterator& + operator=(const common_iterator<_It2, _Sent2>& __x) + noexcept(is_nothrow_constructible_v<_It, const _It2&> + && is_nothrow_constructible_v<_Sent, const _Sent2&> + && is_nothrow_assignable_v<_It, const _It2&> + && is_nothrow_assignable_v<_Sent, const _Sent2&>) + { + switch(_M_index << 2 | __x._M_index) + { + case 0b0000: + _M_it = __x._M_it; + break; + case 0b0101: + _M_sent = __x._M_sent; + break; + case 0b0001: + _M_it.~_It(); + _M_index = -1; + [[fallthrough]]; + case 0b1001: + ::new((void*)std::__addressof(_M_sent)) _Sent(__x._M_sent); + _M_index = 1; + break; + case 0b0100: + _M_sent.~_Sent(); + _M_index = -1; + [[fallthrough]]; + case 0b1000: + ::new((void*)std::__addressof(_M_it)) _It(__x._M_it); + _M_index = 0; + break; + default: + __glibcxx_assert(__x._M_has_value()); + __builtin_unreachable(); + } + return *this; + } + + ~common_iterator() + { + switch (_M_index) + { + case 0: + _M_it.~_It(); + break; + case 1: + _M_sent.~_Sent(); + break; + } + } + + decltype(auto) + operator*() + { + __glibcxx_assert(_M_index == 0); + return *_M_it; + } + + decltype(auto) + operator*() const requires __detail::__dereferenceable + { + __glibcxx_assert(_M_index == 0); + return *_M_it; + } + + decltype(auto) + operator->() const requires __detail::__common_iter_has_arrow<_It> + { + __glibcxx_assert(_M_index == 0); + if constexpr (is_pointer_v<_It> || requires { _M_it.operator->(); }) + return _M_it; + else if constexpr (is_reference_v>) + { + auto&& __tmp = *_M_it; + return std::__addressof(__tmp); + } + else + return _Proxy{*_M_it}; + } + + common_iterator& + operator++() + { + __glibcxx_assert(_M_index == 0); + ++_M_it; + return *this; + } + + decltype(auto) + operator++(int) + { + __glibcxx_assert(_M_index == 0); + if constexpr (forward_iterator<_It>) + { + common_iterator __tmp = *this; + ++*this; + return __tmp; + } + else + return _M_it++; + } + + template _Sent2> + requires sentinel_for<_Sent, _It2> + friend bool + operator==(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0000: + case 0b0101: + return true; + case 0b0001: + return __x._M_it == __y._M_sent; + case 0b0100: + return __x._M_sent == __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + template _Sent2> + requires sentinel_for<_Sent, _It2> && equality_comparable_with<_It, _It2> + friend bool + operator==(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0101: + return true; + case 0b0000: + return __x._M_it == __y._M_it; + case 0b0001: + return __x._M_it == __y._M_sent; + case 0b0100: + return __x._M_sent == __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + template _It2, sized_sentinel_for<_It> _Sent2> + requires sized_sentinel_for<_Sent, _It2> + friend iter_difference_t<_It2> + operator-(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + { + switch(__x._M_index << 2 | __y._M_index) + { + case 0b0101: + return 0; + case 0b0000: + return __x._M_it - __y._M_it; + case 0b0001: + return __x._M_it - __y._M_sent; + case 0b0100: + return __x._M_sent - __y._M_it; + default: + __glibcxx_assert(__x._M_has_value()); + __glibcxx_assert(__y._M_has_value()); + __builtin_unreachable(); + } + } + + friend iter_rvalue_reference_t<_It> + iter_move(const common_iterator& __i) + noexcept(noexcept(ranges::iter_move(std::declval()))) + requires input_iterator<_It> + { + __glibcxx_assert(__i._M_index == 0); + return ranges::iter_move(__i._M_it); + } + + template _It2, typename _Sent2> + friend void + iter_swap(const common_iterator& __x, + const common_iterator<_It2, _Sent2>& __y) + noexcept(noexcept(ranges::iter_swap(std::declval(), + std::declval()))) + { + __glibcxx_assert(__x._M_index == 0); + __glibcxx_assert(__y._M_index == 0); + return ranges::iter_swap(__x._M_it, __y._M_it); + } + + private: + template _Sent2> + friend class common_iterator; + + bool _M_has_value() const noexcept { return _M_index < 2; } + + union + { + _It _M_it; + _Sent _M_sent; + unsigned char _M_valueless; + }; + unsigned char _M_index; // 0==_M_it, 1==_M_sent, 2==valueless + }; + + template + struct incrementable_traits> + { + using difference_type = iter_difference_t<_It>; + }; + + namespace __detail + { + // FIXME: This has to be at namespace-scope because of PR 92103. + template + struct __common_iter_ptr + { + using type = void; + }; + + template + requires __detail::__common_iter_has_arrow<_It> + struct __common_iter_ptr<_It, _Sent> + { + using common_iterator = std::common_iterator<_It, _Sent>; + + using type + = decltype(std::declval().operator->()); + }; + } // namespace __detail + + template + struct iterator_traits> + { + using iterator_concept = conditional_t, + forward_iterator_tag, input_iterator_tag>; + using iterator_category = __detail::__clamp_iter_cat< + typename iterator_traits<_It>::iterator_category, + forward_iterator_tag, input_iterator_tag>; + using value_type = iter_value_t<_It>; + using difference_type = iter_difference_t<_It>; + using pointer = typename __detail::__common_iter_ptr<_It, _Sent>::type; + using reference = iter_reference_t<_It>; + }; + + // [iterators.counted] Counted iterators + + /// An iterator adaptor that keeps track of the distance to the end. + template + class counted_iterator + { + public: + using iterator_type = _It; + + constexpr counted_iterator() = default; + + constexpr + counted_iterator(_It __i, iter_difference_t<_It> __n) + : _M_current(std::move(__i)), _M_length(__n) + { __glibcxx_assert(__n >= 0); } + + template + requires convertible_to + constexpr + counted_iterator(const counted_iterator<_It2>& __x) + : _M_current(__x._M_current), _M_length(__x._M_length) + { } + + template + requires assignable_from<_It&, const _It2&> + constexpr counted_iterator& + operator=(const counted_iterator<_It2>& __x) + { + _M_current = __x._M_current; + _M_length = __x._M_length; + return *this; + } + + constexpr _It + base() const & + noexcept(is_nothrow_copy_constructible_v<_It>) + requires copy_constructible<_It> + { return _M_current; } + + constexpr _It + base() && + noexcept(is_nothrow_move_constructible_v<_It>) + { return std::move(_M_current); } + + constexpr iter_difference_t<_It> + count() const noexcept { return _M_length; } + + constexpr decltype(auto) + operator*() + noexcept(noexcept(*_M_current)) + { return *_M_current; } + + constexpr decltype(auto) + operator*() const + noexcept(noexcept(*_M_current)) + requires __detail::__dereferenceable + { return *_M_current; } + + constexpr counted_iterator& + operator++() + { + __glibcxx_assert(_M_length > 0); + ++_M_current; + --_M_length; + return *this; + } + + decltype(auto) + operator++(int) + { + __glibcxx_assert(_M_length > 0); + --_M_length; + __try + { + return _M_current++; + } __catch(...) { + ++_M_length; + __throw_exception_again; + } + + } + + constexpr counted_iterator + operator++(int) requires forward_iterator<_It> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr counted_iterator& + operator--() requires bidirectional_iterator<_It> + { + --_M_current; + ++_M_length; + return *this; + } + + constexpr counted_iterator + operator--(int) requires bidirectional_iterator<_It> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr counted_iterator + operator+(iter_difference_t<_It> __n) const + requires random_access_iterator<_It> + { return counted_iterator(_M_current + __n, _M_length - __n); } + + friend constexpr counted_iterator + operator+(iter_difference_t<_It> __n, const counted_iterator& __x) + requires random_access_iterator<_It> + { return __x + __n; } + + constexpr counted_iterator& + operator+=(iter_difference_t<_It> __n) + requires random_access_iterator<_It> + { + __glibcxx_assert(__n <= _M_length); + _M_current += __n; + _M_length -= __n; + return *this; + } + + constexpr counted_iterator + operator-(iter_difference_t<_It> __n) const + requires random_access_iterator<_It> + { return counted_iterator(_M_current - __n, _M_length + __n); } + + template _It2> + friend constexpr iter_difference_t<_It2> + operator-(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __y._M_length - __x._M_length; } + + friend constexpr iter_difference_t<_It> + operator-(const counted_iterator& __x, default_sentinel_t) + { return -__x._M_length; } + + friend constexpr iter_difference_t<_It> + operator-(default_sentinel_t, const counted_iterator& __y) + { return __y._M_length; } + + constexpr counted_iterator& + operator-=(iter_difference_t<_It> __n) + requires random_access_iterator<_It> + { + __glibcxx_assert(-__n <= _M_length); + _M_current -= __n; + _M_length += __n; + return *this; + } + + constexpr decltype(auto) + operator[](iter_difference_t<_It> __n) const + noexcept(noexcept(_M_current[__n])) + requires random_access_iterator<_It> + { + __glibcxx_assert(__n < _M_length); + return _M_current[__n]; + } + + template _It2> + friend constexpr bool + operator==(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __x._M_length == __y._M_length; } + + friend constexpr bool + operator==(const counted_iterator& __x, default_sentinel_t) + { return __x._M_length == 0; } + + template _It2> + friend constexpr strong_ordering + operator<=>(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + { return __y._M_length <=> __x._M_length; } + + private: + template friend class counted_iterator; + + _It _M_current = _It(); + iter_difference_t<_It> _M_length = 0; + + friend constexpr iter_rvalue_reference_t<_It> + iter_move(const counted_iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + requires input_iterator<_It> + { return ranges::iter_move(__i._M_current); } + + template _It2> + friend constexpr void + iter_swap(const counted_iterator& __x, + const counted_iterator<_It2>& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + { ranges::iter_swap(__x._M_current, __y._M_current); } + }; + + template + struct incrementable_traits> + { + using difference_type = iter_difference_t<_It>; + }; + + template + struct iterator_traits> : iterator_traits<_It> + { + using pointer = void; + }; +#endif // C++20 + + // @} group iterators + + template + auto + __niter_base(move_iterator<_Iterator> __it) + -> decltype(make_move_iterator(__niter_base(__it.base()))) + { return make_move_iterator(__niter_base(__it.base())); } + + template + struct __is_move_iterator > + { + enum { __value = 1 }; + typedef __true_type __type; + }; + + template + auto + __miter_base(move_iterator<_Iterator> __it) + -> decltype(__miter_base(__it.base())) + { return __miter_base(__it.base()); } + +#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) std::make_move_iterator(_Iter) +#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) \ + std::__make_move_if_noexcept_iterator(_Iter) +#else +#define _GLIBCXX_MAKE_MOVE_ITERATOR(_Iter) (_Iter) +#define _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(_Iter) (_Iter) +#endif // C++11 + +#if __cpp_deduction_guides >= 201606 + // These helper traits are used for deduction guides + // of associative containers. + template + using __iter_key_t = remove_const_t< + typename iterator_traits<_InputIterator>::value_type::first_type>; + + template + using __iter_val_t = + typename iterator_traits<_InputIterator>::value_type::second_type; + + template + struct pair; + + template + using __iter_to_alloc_t = + pair>, + __iter_val_t<_InputIterator>>; +#endif // __cpp_deduction_guides + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h new file mode 100644 index 000000000..076b7781c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_funcs.h @@ -0,0 +1,239 @@ +// Functions used by iterators -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator_base_funcs.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file contains all of the general iterator-related utility + * functions, such as distance() and advance(). + */ + +#ifndef _STL_ITERATOR_BASE_FUNCS_H +#define _STL_ITERATOR_BASE_FUNCS_H 1 + +#pragma GCC system_header + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + // Forward declaration for the overloads of __distance. + template struct _List_iterator; + template struct _List_const_iterator; +_GLIBCXX_END_NAMESPACE_CONTAINER + + template + inline _GLIBCXX14_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + __distance(_InputIterator __first, _InputIterator __last, + input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + + typename iterator_traits<_InputIterator>::difference_type __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } + + template + inline _GLIBCXX14_CONSTEXPR + typename iterator_traits<_RandomAccessIterator>::difference_type + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + return __last - __first; + } + +#if _GLIBCXX_USE_CXX11_ABI + // Forward declaration because of the qualified call in distance. + template + ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_iterator<_Tp>, + _GLIBCXX_STD_C::_List_iterator<_Tp>, + input_iterator_tag); + + template + ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp>, + _GLIBCXX_STD_C::_List_const_iterator<_Tp>, + input_iterator_tag); +#endif + + /** + * @brief A generalization of pointer arithmetic. + * @param __first An input iterator. + * @param __last An input iterator. + * @return The distance between them. + * + * Returns @c n such that __first + n == __last. This requires + * that @p __last must be reachable from @p __first. Note that @c + * n may be negative. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. + */ + template + inline _GLIBCXX17_CONSTEXPR + typename iterator_traits<_InputIterator>::difference_type + distance(_InputIterator __first, _InputIterator __last) + { + // concept requirements -- taken care of in __distance + return std::__distance(__first, __last, + std::__iterator_category(__first)); + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_InputIterator& __i, _Distance __n, input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_assert(__n >= 0); + while (__n--) + ++__i; + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_BidirectionalIterator& __i, _Distance __n, + bidirectional_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + if (__n > 0) + while (__n--) + ++__i; + else + while (__n++) + --__i; + } + + template + inline _GLIBCXX14_CONSTEXPR void + __advance(_RandomAccessIterator& __i, _Distance __n, + random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + if (__builtin_constant_p(__n) && __n == 1) + ++__i; + else if (__builtin_constant_p(__n) && __n == -1) + --__i; + else + __i += __n; + } + + /** + * @brief A generalization of pointer arithmetic. + * @param __i An input iterator. + * @param __n The @a delta by which to change @p __i. + * @return Nothing. + * + * This increments @p i by @p n. For bidirectional and random access + * iterators, @p __n may be negative, in which case @p __i is decremented. + * + * For random access iterators, this uses their @c + and @c - operations + * and are constant time. For other %iterator classes they are linear time. + */ + template + inline _GLIBCXX17_CONSTEXPR void + advance(_InputIterator& __i, _Distance __n) + { + // concept requirements -- taken care of in __advance + typename iterator_traits<_InputIterator>::difference_type __d = __n; + std::__advance(__i, __d, std::__iterator_category(__i)); + } + +#if __cplusplus >= 201103L + + template + inline _GLIBCXX17_CONSTEXPR _InputIterator + next(_InputIterator __x, typename + iterator_traits<_InputIterator>::difference_type __n = 1) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + std::advance(__x, __n); + return __x; + } + + template + inline _GLIBCXX17_CONSTEXPR _BidirectionalIterator + prev(_BidirectionalIterator __x, typename + iterator_traits<_BidirectionalIterator>::difference_type __n = 1) + { + // concept requirements + __glibcxx_function_requires(_BidirectionalIteratorConcept< + _BidirectionalIterator>) + std::advance(__x, -__n); + return __x; + } + +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_ITERATOR_BASE_FUNCS_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h new file mode 100644 index 000000000..aa02af59d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_iterator_base_types.h @@ -0,0 +1,271 @@ +// Types used in iterator implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_iterator_base_types.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{iterator} + * + * This file contains all of the general iterator-related utility types, + * such as iterator_traits and struct iterator. + */ + +#ifndef _STL_ITERATOR_BASE_TYPES_H +#define _STL_ITERATOR_BASE_TYPES_H 1 + +#pragma GCC system_header + +#include + +#if __cplusplus >= 201103L +# include // For __void_t, is_convertible +#endif + +#if __cplusplus > 201703L && __cpp_concepts >= 201907L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup iterators Iterators + * Abstractions for uniform iterating through various underlying types. + */ + //@{ + + /** + * @defgroup iterator_tags Iterator Tags + * These are empty types, used to distinguish different iterators. The + * distinction is not made by what they contain, but simply by what they + * are. Different underlying algorithms can then be used based on the + * different operations supported by different iterator types. + */ + //@{ + /// Marking input iterators. + struct input_iterator_tag { }; + + /// Marking output iterators. + struct output_iterator_tag { }; + + /// Forward iterators support a superset of input iterator operations. + struct forward_iterator_tag : public input_iterator_tag { }; + + /// Bidirectional iterators support a superset of forward iterator + /// operations. + struct bidirectional_iterator_tag : public forward_iterator_tag { }; + + /// Random-access iterators support a superset of bidirectional + /// iterator operations. + struct random_access_iterator_tag : public bidirectional_iterator_tag { }; + +#if __cplusplus > 201703L + /// Contiguous iterators point to objects stored contiguously in memory. + struct contiguous_iterator_tag : public random_access_iterator_tag { }; +#endif + //@} + + /** + * @brief Common %iterator class. + * + * This class does nothing but define nested typedefs. %Iterator classes + * can inherit from this class to save some work. The typedefs are then + * used in specializations and overloading. + * + * In particular, there are no default implementations of requirements + * such as @c operator++ and the like. (How could there be?) + */ + template + struct iterator + { + /// One of the @link iterator_tags tag types@endlink. + typedef _Category iterator_category; + /// The type "pointed to" by the iterator. + typedef _Tp value_type; + /// Distance between iterators is represented as this type. + typedef _Distance difference_type; + /// This type represents a pointer-to-value_type. + typedef _Pointer pointer; + /// This type represents a reference-to-value_type. + typedef _Reference reference; + }; + + /** + * @brief Traits class for iterators. + * + * This class does nothing but define nested typedefs. The general + * version simply @a forwards the nested typedefs from the Iterator + * argument. Specialized versions for pointers and pointers-to-const + * provide tighter, more correct semantics. + */ + template + struct iterator_traits; + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2408. SFINAE-friendly common_type/iterator_traits is missing in C++14 + template> + struct __iterator_traits { }; + +#if ! __cpp_lib_concepts + + template + struct __iterator_traits<_Iterator, + __void_t> + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; +#endif // ! concepts + + template + struct iterator_traits + : public __iterator_traits<_Iterator> { }; + +#else // ! C++11 + template + struct iterator_traits + { + typedef typename _Iterator::iterator_category iterator_category; + typedef typename _Iterator::value_type value_type; + typedef typename _Iterator::difference_type difference_type; + typedef typename _Iterator::pointer pointer; + typedef typename _Iterator::reference reference; + }; +#endif // C++11 + +#if __cplusplus > 201703L + /// Partial specialization for object pointer types. + template +#if __cpp_concepts >= 201907L + requires is_object_v<_Tp> +#endif + struct iterator_traits<_Tp*> + { + using iterator_concept = contiguous_iterator_tag; + using iterator_category = random_access_iterator_tag; + using value_type = remove_cv_t<_Tp>; + using difference_type = ptrdiff_t; + using pointer = _Tp*; + using reference = _Tp&; + }; +#else + /// Partial specialization for pointer types. + template + struct iterator_traits<_Tp*> + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef _Tp* pointer; + typedef _Tp& reference; + }; + + /// Partial specialization for const pointer types. + template + struct iterator_traits + { + typedef random_access_iterator_tag iterator_category; + typedef _Tp value_type; + typedef ptrdiff_t difference_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + }; +#endif + + /** + * This function is not a part of the C++ standard but is syntactic + * sugar for internal library use only. + */ + template + inline _GLIBCXX_CONSTEXPR + typename iterator_traits<_Iter>::iterator_category + __iterator_category(const _Iter&) + { return typename iterator_traits<_Iter>::iterator_category(); } + + //@} + +#if __cplusplus >= 201103L + template + using __iterator_category_t + = typename iterator_traits<_Iter>::iterator_category; + + template + using _RequireInputIter = + __enable_if_t, + input_iterator_tag>::value>; + + template> + struct __is_random_access_iter + : is_base_of + { + typedef is_base_of _Base; + enum { __value = _Base::value }; + }; +#else + template, + typename _Cat = typename _Traits::iterator_category> + struct __is_random_access_iter + { enum { __value = __is_base_of(random_access_iterator_tag, _Cat) }; }; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_ITERATOR_BASE_TYPES_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_list.h b/resources/sources/avr-libstdcpp/include/bits/stl_list.h new file mode 100644 index 000000000..e7135e3e7 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_list.h @@ -0,0 +1,2127 @@ +// List implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_list.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{list} + */ + +#ifndef _STL_LIST_H +#define _STL_LIST_H 1 + +#include +#include +#if __cplusplus >= 201103L +#include +#include +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + namespace __detail + { + // Supporting structures are split into common and templated + // types; the latter publicly inherits from the former in an + // effort to reduce code duplication. This results in some + // "needless" static_cast'ing later on, but it's all safe + // downcasting. + + /// Common part of a node in the %list. + struct _List_node_base + { + _List_node_base* _M_next; + _List_node_base* _M_prev; + + static void + swap(_List_node_base& __x, _List_node_base& __y) _GLIBCXX_USE_NOEXCEPT; + + void + _M_transfer(_List_node_base* const __first, + _List_node_base* const __last) _GLIBCXX_USE_NOEXCEPT; + + void + _M_reverse() _GLIBCXX_USE_NOEXCEPT; + + void + _M_hook(_List_node_base* const __position) _GLIBCXX_USE_NOEXCEPT; + + void + _M_unhook() _GLIBCXX_USE_NOEXCEPT; + }; + + /// The %list node header. + struct _List_node_header : public _List_node_base + { +#if _GLIBCXX_USE_CXX11_ABI + std::size_t _M_size; +#endif + + _List_node_header() _GLIBCXX_NOEXCEPT + { _M_init(); } + +#if __cplusplus >= 201103L + _List_node_header(_List_node_header&& __x) noexcept + : _List_node_base{ __x._M_next, __x._M_prev } +# if _GLIBCXX_USE_CXX11_ABI + , _M_size(__x._M_size) +# endif + { + if (__x._M_base()->_M_next == __x._M_base()) + this->_M_next = this->_M_prev = this; + else + { + this->_M_next->_M_prev = this->_M_prev->_M_next = this->_M_base(); + __x._M_init(); + } + } + + void + _M_move_nodes(_List_node_header&& __x) + { + _List_node_base* const __xnode = __x._M_base(); + if (__xnode->_M_next == __xnode) + _M_init(); + else + { + _List_node_base* const __node = this->_M_base(); + __node->_M_next = __xnode->_M_next; + __node->_M_prev = __xnode->_M_prev; + __node->_M_next->_M_prev = __node->_M_prev->_M_next = __node; +# if _GLIBCXX_USE_CXX11_ABI + _M_size = __x._M_size; +# endif + __x._M_init(); + } + } +#endif + + void + _M_init() _GLIBCXX_NOEXCEPT + { + this->_M_next = this->_M_prev = this; +#if _GLIBCXX_USE_CXX11_ABI + this->_M_size = 0; +#endif + } + + private: + _List_node_base* _M_base() { return this; } + }; + } // namespace detail + +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /// An actual node in the %list. + template + struct _List_node : public __detail::_List_node_base + { +#if __cplusplus >= 201103L + __gnu_cxx::__aligned_membuf<_Tp> _M_storage; + _Tp* _M_valptr() { return _M_storage._M_ptr(); } + _Tp const* _M_valptr() const { return _M_storage._M_ptr(); } +#else + _Tp _M_data; + _Tp* _M_valptr() { return std::__addressof(_M_data); } + _Tp const* _M_valptr() const { return std::__addressof(_M_data); } +#endif + }; + + /** + * @brief A list::iterator. + * + * All the functions are op overloads. + */ + template + struct _List_iterator + { + typedef _List_iterator<_Tp> _Self; + typedef _List_node<_Tp> _Node; + + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef _Tp* pointer; + typedef _Tp& reference; + + _List_iterator() _GLIBCXX_NOEXCEPT + : _M_node() { } + + explicit + _List_iterator(__detail::_List_node_base* __x) _GLIBCXX_NOEXCEPT + : _M_node(__x) { } + + _Self + _M_const_cast() const _GLIBCXX_NOEXCEPT + { return *this; } + + // Must downcast from _List_node_base to _List_node to get to value. + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *static_cast<_Node*>(_M_node)->_M_valptr(); } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return static_cast<_Node*>(_M_node)->_M_valptr(); } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + _M_node = _M_node->_M_next; + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _M_node->_M_next; + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + _M_node = _M_node->_M_prev; + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _M_node->_M_prev; + return __tmp; + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node == __y._M_node; } + +#if __cpp_impl_three_way_comparison < 201907L + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node != __y._M_node; } +#endif + + // The only member points to the %list element. + __detail::_List_node_base* _M_node; + }; + + /** + * @brief A list::const_iterator. + * + * All the functions are op overloads. + */ + template + struct _List_const_iterator + { + typedef _List_const_iterator<_Tp> _Self; + typedef const _List_node<_Tp> _Node; + typedef _List_iterator<_Tp> iterator; + + typedef ptrdiff_t difference_type; + typedef std::bidirectional_iterator_tag iterator_category; + typedef _Tp value_type; + typedef const _Tp* pointer; + typedef const _Tp& reference; + + _List_const_iterator() _GLIBCXX_NOEXCEPT + : _M_node() { } + + explicit + _List_const_iterator(const __detail::_List_node_base* __x) + _GLIBCXX_NOEXCEPT + : _M_node(__x) { } + + _List_const_iterator(const iterator& __x) _GLIBCXX_NOEXCEPT + : _M_node(__x._M_node) { } + + iterator + _M_const_cast() const _GLIBCXX_NOEXCEPT + { return iterator(const_cast<__detail::_List_node_base*>(_M_node)); } + + // Must downcast from List_node_base to _List_node to get to value. + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *static_cast<_Node*>(_M_node)->_M_valptr(); } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return static_cast<_Node*>(_M_node)->_M_valptr(); } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + _M_node = _M_node->_M_next; + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _M_node->_M_next; + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + _M_node = _M_node->_M_prev; + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _M_node->_M_prev; + return __tmp; + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node == __y._M_node; } + +#if __cpp_impl_three_way_comparison < 201907L + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node != __y._M_node; } +#endif + + // The only member points to the %list element. + const __detail::_List_node_base* _M_node; + }; + +_GLIBCXX_BEGIN_NAMESPACE_CXX11 + /// See bits/stl_deque.h's _Deque_base for an explanation. + template + class _List_base + { + protected: + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Tp>::other _Tp_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tp_alloc_traits; + typedef typename _Tp_alloc_traits::template + rebind<_List_node<_Tp> >::other _Node_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Node_alloc_type> _Node_alloc_traits; + +#if !_GLIBCXX_INLINE_VERSION + static size_t + _S_distance(const __detail::_List_node_base* __first, + const __detail::_List_node_base* __last) + { + size_t __n = 0; + while (__first != __last) + { + __first = __first->_M_next; + ++__n; + } + return __n; + } +#endif + + struct _List_impl + : public _Node_alloc_type + { + __detail::_List_node_header _M_node; + + _List_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Node_alloc_type>::value) + : _Node_alloc_type() + { } + + _List_impl(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT + : _Node_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + _List_impl(_List_impl&&) = default; + + _List_impl(_Node_alloc_type&& __a, _List_impl&& __x) + : _Node_alloc_type(std::move(__a)), _M_node(std::move(__x._M_node)) + { } + + _List_impl(_Node_alloc_type&& __a) noexcept + : _Node_alloc_type(std::move(__a)) + { } +#endif + }; + + _List_impl _M_impl; + +#if _GLIBCXX_USE_CXX11_ABI + size_t _M_get_size() const { return _M_impl._M_node._M_size; } + + void _M_set_size(size_t __n) { _M_impl._M_node._M_size = __n; } + + void _M_inc_size(size_t __n) { _M_impl._M_node._M_size += __n; } + + void _M_dec_size(size_t __n) { _M_impl._M_node._M_size -= __n; } + +# if !_GLIBCXX_INLINE_VERSION + size_t + _M_distance(const __detail::_List_node_base* __first, + const __detail::_List_node_base* __last) const + { return _S_distance(__first, __last); } + + // return the stored size + size_t _M_node_count() const { return _M_get_size(); } +# endif +#else + // dummy implementations used when the size is not stored + size_t _M_get_size() const { return 0; } + void _M_set_size(size_t) { } + void _M_inc_size(size_t) { } + void _M_dec_size(size_t) { } + +# if !_GLIBCXX_INLINE_VERSION + size_t _M_distance(const void*, const void*) const { return 0; } + + // count the number of nodes + size_t _M_node_count() const + { + return _S_distance(_M_impl._M_node._M_next, + std::__addressof(_M_impl._M_node)); + } +# endif +#endif + + typename _Node_alloc_traits::pointer + _M_get_node() + { return _Node_alloc_traits::allocate(_M_impl, 1); } + + void + _M_put_node(typename _Node_alloc_traits::pointer __p) _GLIBCXX_NOEXCEPT + { _Node_alloc_traits::deallocate(_M_impl, __p, 1); } + + public: + typedef _Alloc allocator_type; + + _Node_alloc_type& + _M_get_Node_allocator() _GLIBCXX_NOEXCEPT + { return _M_impl; } + + const _Node_alloc_type& + _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT + { return _M_impl; } + +#if __cplusplus >= 201103L + _List_base() = default; +#else + _List_base() { } +#endif + + _List_base(const _Node_alloc_type& __a) _GLIBCXX_NOEXCEPT + : _M_impl(__a) + { } + +#if __cplusplus >= 201103L + _List_base(_List_base&&) = default; + +# if !_GLIBCXX_INLINE_VERSION + _List_base(_List_base&& __x, _Node_alloc_type&& __a) + : _M_impl(std::move(__a)) + { + if (__x._M_get_Node_allocator() == _M_get_Node_allocator()) + _M_move_nodes(std::move(__x)); + // else caller must move individual elements. + } +# endif + + // Used when allocator is_always_equal. + _List_base(_Node_alloc_type&& __a, _List_base&& __x) + : _M_impl(std::move(__a), std::move(__x._M_impl)) + { } + + // Used when allocator !is_always_equal. + _List_base(_Node_alloc_type&& __a) + : _M_impl(std::move(__a)) + { } + + void + _M_move_nodes(_List_base&& __x) + { _M_impl._M_node._M_move_nodes(std::move(__x._M_impl._M_node)); } +#endif + + // This is what actually destroys the list. + ~_List_base() _GLIBCXX_NOEXCEPT + { _M_clear(); } + + void + _M_clear() _GLIBCXX_NOEXCEPT; + + void + _M_init() _GLIBCXX_NOEXCEPT + { this->_M_impl._M_node._M_init(); } + }; + + /** + * @brief A standard container with linear time access to elements, + * and fixed time insertion/deletion at any point in the sequence. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements with the + * %exception of @c at and @c operator[]. + * + * This is a @e doubly @e linked %list. Traversal up and down the + * %list requires linear time, but adding and removing elements (or + * @e nodes) is done in constant time, regardless of where the + * change takes place. Unlike std::vector and std::deque, + * random-access iterators are not provided, so subscripting ( @c + * [] ) access is not allowed. For algorithms which only need + * sequential access, this lack makes no difference. + * + * Also unlike the other standard containers, std::list provides + * specialized algorithms %unique to linked lists, such as + * splicing, sorting, and in-place reversal. + * + * A couple points on memory allocation for list: + * + * First, we never actually allocate a Tp, we allocate + * List_node's and trust [20.1.5]/4 to DTRT. This is to ensure + * that after elements from %list are spliced into + * %list, destroying the memory of the second %list is a + * valid operation, i.e., Alloc1 giveth and Alloc2 taketh away. + * + * Second, a %list conceptually represented as + * @code + * A <---> B <---> C <---> D + * @endcode + * is actually circular; a link exists between A and D. The %list + * class holds (as its only data member) a private list::iterator + * pointing to @e D, not to @e A! To get to the head of the %list, + * we start at the tail and move forward by one. When this member + * iterator's next/previous pointers refer to itself, the %list is + * %empty. + */ + template > + class list : protected _List_base<_Tp, _Alloc> + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Tp>::value, + "std::list must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::list must have the same value_type as its allocator"); +# endif +#endif + + typedef _List_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef typename _Base::_Tp_alloc_traits _Tp_alloc_traits; + typedef typename _Base::_Node_alloc_type _Node_alloc_type; + typedef typename _Base::_Node_alloc_traits _Node_alloc_traits; + + public: + typedef _Tp value_type; + typedef typename _Tp_alloc_traits::pointer pointer; + typedef typename _Tp_alloc_traits::const_pointer const_pointer; + typedef typename _Tp_alloc_traits::reference reference; + typedef typename _Tp_alloc_traits::const_reference const_reference; + typedef _List_iterator<_Tp> iterator; + typedef _List_const_iterator<_Tp> const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + protected: + // Note that pointers-to-_Node's can be ctor-converted to + // iterator types. + typedef _List_node<_Tp> _Node; + + using _Base::_M_impl; + using _Base::_M_put_node; + using _Base::_M_get_node; + using _Base::_M_get_Node_allocator; + + /** + * @param __args An instance of user data. + * + * Allocates space for a new node and constructs a copy of + * @a __args in it. + */ +#if __cplusplus < 201103L + _Node* + _M_create_node(const value_type& __x) + { + _Node* __p = this->_M_get_node(); + __try + { + _Tp_alloc_type __alloc(_M_get_Node_allocator()); + __alloc.construct(__p->_M_valptr(), __x); + } + __catch(...) + { + _M_put_node(__p); + __throw_exception_again; + } + return __p; + } +#else + template + _Node* + _M_create_node(_Args&&... __args) + { + auto __p = this->_M_get_node(); + auto& __alloc = _M_get_Node_allocator(); + __allocated_ptr<_Node_alloc_type> __guard{__alloc, __p}; + _Node_alloc_traits::construct(__alloc, __p->_M_valptr(), + std::forward<_Args>(__args)...); + __guard = nullptr; + return __p; + } +#endif + +#if _GLIBCXX_USE_CXX11_ABI + static size_t + _S_distance(const_iterator __first, const_iterator __last) + { return std::distance(__first, __last); } + + // return the stored size + size_t + _M_node_count() const + { return this->_M_get_size(); } +#else + // dummy implementations used when the size is not stored + static size_t + _S_distance(const_iterator, const_iterator) + { return 0; } + + // count the number of nodes + size_t + _M_node_count() const + { return std::distance(begin(), end()); } +#endif + + public: + // [23.2.2.1] construct/copy/destroy + // (assign() and get_allocator() are also listed in this section) + + /** + * @brief Creates a %list with no elements. + */ +#if __cplusplus >= 201103L + list() = default; +#else + list() { } +#endif + + /** + * @brief Creates a %list with no elements. + * @param __a An allocator object. + */ + explicit + list(const allocator_type& __a) _GLIBCXX_NOEXCEPT + : _Base(_Node_alloc_type(__a)) { } + +#if __cplusplus >= 201103L + /** + * @brief Creates a %list with default constructed elements. + * @param __n The number of elements to initially create. + * @param __a An allocator object. + * + * This constructor fills the %list with @a __n default + * constructed elements. + */ + explicit + list(size_type __n, const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_default_initialize(__n); } + + /** + * @brief Creates a %list with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator object. + * + * This constructor fills the %list with @a __n copies of @a __value. + */ + list(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_fill_initialize(__n, __value); } +#else + /** + * @brief Creates a %list with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator object. + * + * This constructor fills the %list with @a __n copies of @a __value. + */ + explicit + list(size_type __n, const value_type& __value = value_type(), + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_fill_initialize(__n, __value); } +#endif + + /** + * @brief %List copy constructor. + * @param __x A %list of identical element and allocator types. + * + * The newly-created %list uses a copy of the allocation object used + * by @a __x (unless the allocator traits dictate a different object). + */ + list(const list& __x) + : _Base(_Node_alloc_traits:: + _S_select_on_copy(__x._M_get_Node_allocator())) + { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } + +#if __cplusplus >= 201103L + /** + * @brief %List move constructor. + * + * The newly-created %list contains the exact contents of the moved + * instance. The contents of the moved instance are a valid, but + * unspecified %list. + */ + list(list&&) = default; + + /** + * @brief Builds a %list from an initializer_list + * @param __l An initializer_list of value_type. + * @param __a An allocator object. + * + * Create a %list consisting of copies of the elements in the + * initializer_list @a __l. This is linear in __l.size(). + */ + list(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_initialize_dispatch(__l.begin(), __l.end(), __false_type()); } + + list(const list& __x, const allocator_type& __a) + : _Base(_Node_alloc_type(__a)) + { _M_initialize_dispatch(__x.begin(), __x.end(), __false_type()); } + + private: + list(list&& __x, const allocator_type& __a, true_type) noexcept + : _Base(_Node_alloc_type(__a), std::move(__x)) + { } + + list(list&& __x, const allocator_type& __a, false_type) + : _Base(_Node_alloc_type(__a)) + { + if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator()) + this->_M_move_nodes(std::move(__x)); + else + insert(begin(), std::__make_move_if_noexcept_iterator(__x.begin()), + std::__make_move_if_noexcept_iterator(__x.end())); + } + + public: + list(list&& __x, const allocator_type& __a) + noexcept(_Node_alloc_traits::_S_always_equal()) + : list(std::move(__x), __a, + typename _Node_alloc_traits::is_always_equal{}) + { } +#endif + + /** + * @brief Builds a %list from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __a An allocator object. + * + * Create a %list consisting of copies of the elements from + * [@a __first,@a __last). This is linear in N (where N is + * distance(@a __first,@a __last)). + */ +#if __cplusplus >= 201103L + template> + list(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { _M_initialize_dispatch(__first, __last, __false_type()); } +#else + template + list(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(_Node_alloc_type(__a)) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + /** + * No explicit dtor needed as the _Base dtor takes care of + * things. The _Base dtor only erases the elements, and note + * that if the elements themselves are pointers, the pointed-to + * memory is not touched in any way. Managing the pointer is + * the user's responsibility. + */ + ~list() = default; +#endif + + /** + * @brief %List assignment operator. + * @param __x A %list of identical element and allocator types. + * + * All the elements of @a __x are copied. + * + * Whether the allocator is copied depends on the allocator traits. + */ + list& + operator=(const list& __x); + +#if __cplusplus >= 201103L + /** + * @brief %List move assignment operator. + * @param __x A %list of identical element and allocator types. + * + * The contents of @a __x are moved into this %list (without copying). + * + * Afterwards @a __x is a valid, but unspecified %list + * + * Whether the allocator is moved depends on the allocator traits. + */ + list& + operator=(list&& __x) + noexcept(_Node_alloc_traits::_S_nothrow_move()) + { + constexpr bool __move_storage = + _Node_alloc_traits::_S_propagate_on_move_assign() + || _Node_alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); + return *this; + } + + /** + * @brief %List initializer list assignment operator. + * @param __l An initializer_list of value_type. + * + * Replace the contents of the %list with copies of the elements + * in the initializer_list @a __l. This is linear in l.size(). + */ + list& + operator=(initializer_list __l) + { + this->assign(__l.begin(), __l.end()); + return *this; + } +#endif + + /** + * @brief Assigns a given value to a %list. + * @param __n Number of elements to be assigned. + * @param __val Value to be assigned. + * + * This function fills a %list with @a __n copies of the given + * value. Note that the assignment completely changes the %list + * and that the resulting %list's size is the same as the number + * of elements assigned. + */ + void + assign(size_type __n, const value_type& __val) + { _M_fill_assign(__n, __val); } + + /** + * @brief Assigns a range to a %list. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function fills a %list with copies of the elements in the + * range [@a __first,@a __last). + * + * Note that the assignment completely changes the %list and + * that the resulting %list's size is the same as the number of + * elements assigned. + */ +#if __cplusplus >= 201103L + template> + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_dispatch(__first, __last, __false_type()); } +#else + template + void + assign(_InputIterator __first, _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Assigns an initializer_list to a %list. + * @param __l An initializer_list of value_type. + * + * Replace the contents of the %list with copies of the elements + * in the initializer_list @a __l. This is linear in __l.size(). + */ + void + assign(initializer_list __l) + { this->_M_assign_dispatch(__l.begin(), __l.end(), __false_type()); } +#endif + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_Base::_M_get_Node_allocator()); } + + // iterators + /** + * Returns a read/write iterator that points to the first element in the + * %list. Iteration is done in ordinary element order. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_node._M_next); } + + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %list. Iteration is done in ordinary + * element order. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_node._M_next); } + + /** + * Returns a read/write iterator that points one past the last + * element in the %list. Iteration is done in ordinary element + * order. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return iterator(&this->_M_impl._M_node); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %list. Iteration is done in ordinary + * element order. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return const_iterator(&this->_M_impl._M_node); } + + /** + * Returns a read/write reverse iterator that points to the last + * element in the %list. Iteration is done in reverse element + * order. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points to + * the last element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(end()); } + + /** + * Returns a read/write reverse iterator that points to one + * before the first element in the %list. Iteration is done in + * reverse element order. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(begin()); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(begin()); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %list. Iteration is done in ordinary + * element order. + */ + const_iterator + cbegin() const noexcept + { return const_iterator(this->_M_impl._M_node._M_next); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %list. Iteration is done in ordinary + * element order. + */ + const_iterator + cend() const noexcept + { return const_iterator(&this->_M_impl._M_node); } + + /** + * Returns a read-only (constant) reverse iterator that points to + * the last element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first element in the %list. Iteration is done in reverse + * element order. + */ + const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } +#endif + + // [23.2.2.2] capacity + /** + * Returns true if the %list is empty. (Thus begin() would equal + * end().) + */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_node._M_next == &this->_M_impl._M_node; } + + /** Returns the number of elements in the %list. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_node_count(); } + + /** Returns the size() of the largest possible %list. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _Node_alloc_traits::max_size(_M_get_Node_allocator()); } + +#if __cplusplus >= 201103L + /** + * @brief Resizes the %list to the specified number of elements. + * @param __new_size Number of elements the %list should contain. + * + * This function will %resize the %list to the specified number + * of elements. If the number is smaller than the %list's + * current size the %list is truncated, otherwise default + * constructed elements are appended. + */ + void + resize(size_type __new_size); + + /** + * @brief Resizes the %list to the specified number of elements. + * @param __new_size Number of elements the %list should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %list to the specified number + * of elements. If the number is smaller than the %list's + * current size the %list is truncated, otherwise the %list is + * extended and new elements are populated with given data. + */ + void + resize(size_type __new_size, const value_type& __x); +#else + /** + * @brief Resizes the %list to the specified number of elements. + * @param __new_size Number of elements the %list should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %list to the specified number + * of elements. If the number is smaller than the %list's + * current size the %list is truncated, otherwise the %list is + * extended and new elements are populated with given data. + */ + void + resize(size_type __new_size, value_type __x = value_type()); +#endif + + // element access + /** + * Returns a read/write reference to the data at the first + * element of the %list. + */ + reference + front() _GLIBCXX_NOEXCEPT + { return *begin(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %list. + */ + const_reference + front() const _GLIBCXX_NOEXCEPT + { return *begin(); } + + /** + * Returns a read/write reference to the data at the last element + * of the %list. + */ + reference + back() _GLIBCXX_NOEXCEPT + { + iterator __tmp = end(); + --__tmp; + return *__tmp; + } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %list. + */ + const_reference + back() const _GLIBCXX_NOEXCEPT + { + const_iterator __tmp = end(); + --__tmp; + return *__tmp; + } + + // [23.2.2.3] modifiers + /** + * @brief Add data to the front of the %list. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the front of the %list and assigns the given data + * to it. Due to the nature of a %list this operation can be + * done in constant time, and does not invalidate iterators and + * references. + */ + void + push_front(const value_type& __x) + { this->_M_insert(begin(), __x); } + +#if __cplusplus >= 201103L + void + push_front(value_type&& __x) + { this->_M_insert(begin(), std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_front(_Args&&... __args) + { + this->_M_insert(begin(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return front(); +#endif + } +#endif + + /** + * @brief Removes first element. + * + * This is a typical stack operation. It shrinks the %list by + * one. Due to the nature of a %list this operation can be done + * in constant time, and only invalidates iterators/references to + * the element being removed. + * + * Note that no data is returned, and if the first element's data + * is needed, it should be retrieved before pop_front() is + * called. + */ + void + pop_front() _GLIBCXX_NOEXCEPT + { this->_M_erase(begin()); } + + /** + * @brief Add data to the end of the %list. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the end of the %list and assigns the given data to + * it. Due to the nature of a %list this operation can be done + * in constant time, and does not invalidate iterators and + * references. + */ + void + push_back(const value_type& __x) + { this->_M_insert(end(), __x); } + +#if __cplusplus >= 201103L + void + push_back(value_type&& __x) + { this->_M_insert(end(), std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args) + { + this->_M_insert(end(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif + } +#endif + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %list by + * one. Due to the nature of a %list this operation can be done + * in constant time, and only invalidates iterators/references to + * the element being removed. + * + * Note that no data is returned, and if the last element's data + * is needed, it should be retrieved before pop_back() is called. + */ + void + pop_back() _GLIBCXX_NOEXCEPT + { this->_M_erase(iterator(this->_M_impl._M_node._M_prev)); } + +#if __cplusplus >= 201103L + /** + * @brief Constructs object in %list before specified iterator. + * @param __position A const_iterator into the %list. + * @param __args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) before the specified + * location. Due to the nature of a %list this operation can + * be done in constant time, and does not invalidate iterators + * and references. + */ + template + iterator + emplace(const_iterator __position, _Args&&... __args); + + /** + * @brief Inserts given value into %list before specified iterator. + * @param __position A const_iterator into the %list. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before + * the specified location. Due to the nature of a %list this + * operation can be done in constant time, and does not + * invalidate iterators and references. + */ + iterator + insert(const_iterator __position, const value_type& __x); +#else + /** + * @brief Inserts given value into %list before specified iterator. + * @param __position An iterator into the %list. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before + * the specified location. Due to the nature of a %list this + * operation can be done in constant time, and does not + * invalidate iterators and references. + */ + iterator + insert(iterator __position, const value_type& __x); +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts given rvalue into %list before specified iterator. + * @param __position A const_iterator into the %list. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given rvalue before + * the specified location. Due to the nature of a %list this + * operation can be done in constant time, and does not + * invalidate iterators and references. + */ + iterator + insert(const_iterator __position, value_type&& __x) + { return emplace(__position, std::move(__x)); } + + /** + * @brief Inserts the contents of an initializer_list into %list + * before specified const_iterator. + * @param __p A const_iterator into the %list. + * @param __l An initializer_list of value_type. + * @return An iterator pointing to the first element inserted + * (or __position). + * + * This function will insert copies of the data in the + * initializer_list @a l into the %list before the location + * specified by @a p. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + iterator + insert(const_iterator __p, initializer_list __l) + { return this->insert(__p, __l.begin(), __l.end()); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a number of copies of given data into the %list. + * @param __position A const_iterator into the %list. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * @return An iterator pointing to the first element inserted + * (or __position). + * + * This function will insert a specified number of copies of the + * given data before the location specified by @a position. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + iterator + insert(const_iterator __position, size_type __n, const value_type& __x); +#else + /** + * @brief Inserts a number of copies of given data into the %list. + * @param __position An iterator into the %list. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * + * This function will insert a specified number of copies of the + * given data before the location specified by @a position. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + void + insert(iterator __position, size_type __n, const value_type& __x) + { + list __tmp(__n, __x, get_allocator()); + splice(__position, __tmp); + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a range into the %list. + * @param __position A const_iterator into the %list. + * @param __first An input iterator. + * @param __last An input iterator. + * @return An iterator pointing to the first element inserted + * (or __position). + * + * This function will insert copies of the data in the range [@a + * first,@a last) into the %list before the location specified by + * @a position. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + template> + iterator + insert(const_iterator __position, _InputIterator __first, + _InputIterator __last); +#else + /** + * @brief Inserts a range into the %list. + * @param __position An iterator into the %list. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function will insert copies of the data in the range [@a + * first,@a last) into the %list before the location specified by + * @a position. + * + * This operation is linear in the number of elements inserted and + * does not invalidate iterators and references. + */ + template + void + insert(iterator __position, _InputIterator __first, + _InputIterator __last) + { + list __tmp(__first, __last, get_allocator()); + splice(__position, __tmp); + } +#endif + + /** + * @brief Remove element at given position. + * @param __position Iterator pointing to element to be erased. + * @return An iterator pointing to the next element (or end()). + * + * This function will erase the element at the given position and thus + * shorten the %list by one. + * + * Due to the nature of a %list this operation can be done in + * constant time, and only invalidates iterators/references to + * the element being removed. The user is also cautioned that + * this function only erases the element, and that if the element + * is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) noexcept; +#else + erase(iterator __position); +#endif + + /** + * @brief Remove a range of elements. + * @param __first Iterator pointing to the first element to be erased. + * @param __last Iterator pointing to one past the last element to be + * erased. + * @return An iterator pointing to the element pointed to by @a last + * prior to erasing (or end()). + * + * This function will erase the elements in the range @a + * [first,last) and shorten the %list accordingly. + * + * This operation is linear time in the size of the range and only + * invalidates iterators/references to the element being removed. + * The user is also cautioned that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) noexcept +#else + erase(iterator __first, iterator __last) +#endif + { + while (__first != __last) + __first = erase(__first); + return __last._M_const_cast(); + } + + /** + * @brief Swaps data with another %list. + * @param __x A %list of the same element and allocator types. + * + * This exchanges the elements between two lists in constant + * time. Note that the global std::swap() function is + * specialized such that std::swap(l1,l2) will feed to this + * function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(list& __x) _GLIBCXX_NOEXCEPT + { + __detail::_List_node_base::swap(this->_M_impl._M_node, + __x._M_impl._M_node); + + size_t __xsize = __x._M_get_size(); + __x._M_set_size(this->_M_get_size()); + this->_M_set_size(__xsize); + + _Node_alloc_traits::_S_on_swap(this->_M_get_Node_allocator(), + __x._M_get_Node_allocator()); + } + + /** + * Erases all the elements. Note that this function only erases + * the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { + _Base::_M_clear(); + _Base::_M_init(); + } + + // [23.2.2.4] list operations + /** + * @brief Insert contents of another %list. + * @param __position Iterator referencing the element to insert before. + * @param __x Source list. + * + * The elements of @a __x are inserted in constant time in front of + * the element referenced by @a __position. @a __x becomes an empty + * list. + * + * Requires this != @a __x. + */ + void +#if __cplusplus >= 201103L + splice(const_iterator __position, list&& __x) noexcept +#else + splice(iterator __position, list& __x) +#endif + { + if (!__x.empty()) + { + _M_check_equal_allocators(__x); + + this->_M_transfer(__position._M_const_cast(), + __x.begin(), __x.end()); + + this->_M_inc_size(__x._M_get_size()); + __x._M_set_size(0); + } + } + +#if __cplusplus >= 201103L + void + splice(const_iterator __position, list& __x) noexcept + { splice(__position, std::move(__x)); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Insert element from another %list. + * @param __position Const_iterator referencing the element to + * insert before. + * @param __x Source list. + * @param __i Const_iterator referencing the element to move. + * + * Removes the element in list @a __x referenced by @a __i and + * inserts it into the current list before @a __position. + */ + void + splice(const_iterator __position, list&& __x, const_iterator __i) noexcept +#else + /** + * @brief Insert element from another %list. + * @param __position Iterator referencing the element to insert before. + * @param __x Source list. + * @param __i Iterator referencing the element to move. + * + * Removes the element in list @a __x referenced by @a __i and + * inserts it into the current list before @a __position. + */ + void + splice(iterator __position, list& __x, iterator __i) +#endif + { + iterator __j = __i._M_const_cast(); + ++__j; + if (__position == __i || __position == __j) + return; + + if (this != std::__addressof(__x)) + _M_check_equal_allocators(__x); + + this->_M_transfer(__position._M_const_cast(), + __i._M_const_cast(), __j); + + this->_M_inc_size(1); + __x._M_dec_size(1); + } + +#if __cplusplus >= 201103L + /** + * @brief Insert element from another %list. + * @param __position Const_iterator referencing the element to + * insert before. + * @param __x Source list. + * @param __i Const_iterator referencing the element to move. + * + * Removes the element in list @a __x referenced by @a __i and + * inserts it into the current list before @a __position. + */ + void + splice(const_iterator __position, list& __x, const_iterator __i) noexcept + { splice(__position, std::move(__x), __i); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Insert range from another %list. + * @param __position Const_iterator referencing the element to + * insert before. + * @param __x Source list. + * @param __first Const_iterator referencing the start of range in x. + * @param __last Const_iterator referencing the end of range in x. + * + * Removes elements in the range [__first,__last) and inserts them + * before @a __position in constant time. + * + * Undefined if @a __position is in [__first,__last). + */ + void + splice(const_iterator __position, list&& __x, const_iterator __first, + const_iterator __last) noexcept +#else + /** + * @brief Insert range from another %list. + * @param __position Iterator referencing the element to insert before. + * @param __x Source list. + * @param __first Iterator referencing the start of range in x. + * @param __last Iterator referencing the end of range in x. + * + * Removes elements in the range [__first,__last) and inserts them + * before @a __position in constant time. + * + * Undefined if @a __position is in [__first,__last). + */ + void + splice(iterator __position, list& __x, iterator __first, + iterator __last) +#endif + { + if (__first != __last) + { + if (this != std::__addressof(__x)) + _M_check_equal_allocators(__x); + + size_t __n = _S_distance(__first, __last); + this->_M_inc_size(__n); + __x._M_dec_size(__n); + + this->_M_transfer(__position._M_const_cast(), + __first._M_const_cast(), + __last._M_const_cast()); + } + } + +#if __cplusplus >= 201103L + /** + * @brief Insert range from another %list. + * @param __position Const_iterator referencing the element to + * insert before. + * @param __x Source list. + * @param __first Const_iterator referencing the start of range in x. + * @param __last Const_iterator referencing the end of range in x. + * + * Removes elements in the range [__first,__last) and inserts them + * before @a __position in constant time. + * + * Undefined if @a __position is in [__first,__last). + */ + void + splice(const_iterator __position, list& __x, const_iterator __first, + const_iterator __last) noexcept + { splice(__position, std::move(__x), __first, __last); } +#endif + + private: +#if __cplusplus > 201703L +# define __cpp_lib_list_remove_return_type 201806L + typedef size_type __remove_return_type; +# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG \ + __attribute__((__abi_tag__("__cxx20"))) +#else + typedef void __remove_return_type; +# define _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG +#endif + public: + + /** + * @brief Remove all elements equal to value. + * @param __value The value to remove. + * + * Removes every element in the list equal to @a value. + * Remaining elements stay in list order. Note that this + * function only erases the elements, and that if the elements + * themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type + remove(const _Tp& __value); + + /** + * @brief Remove all elements satisfying a predicate. + * @tparam _Predicate Unary predicate function or object. + * + * Removes every element in the list for which the predicate + * returns true. Remaining elements stay in list order. Note + * that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + template + __remove_return_type + remove_if(_Predicate); + + /** + * @brief Remove consecutive duplicate elements. + * + * For each consecutive set of elements with the same value, + * remove all but the first one. Remaining elements stay in + * list order. Note that this function only erases the + * elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + */ + _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG + __remove_return_type + unique(); + + /** + * @brief Remove consecutive elements satisfying a predicate. + * @tparam _BinaryPredicate Binary predicate function or object. + * + * For each consecutive set of elements [first,last) that + * satisfy predicate(first,i) where i is an iterator in + * [first,last), remove all but the first one. Remaining + * elements stay in list order. Note that this function only + * erases the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + template + __remove_return_type + unique(_BinaryPredicate); + +#undef _GLIBCXX_LIST_REMOVE_RETURN_TYPE_TAG + + /** + * @brief Merge sorted lists. + * @param __x Sorted list to merge. + * + * Assumes that both @a __x and this list are sorted according to + * operator<(). Merges elements of @a __x into this list in + * sorted order, leaving @a __x empty when complete. Elements in + * this list precede elements in @a __x that are equal. + */ +#if __cplusplus >= 201103L + void + merge(list&& __x); + + void + merge(list& __x) + { merge(std::move(__x)); } +#else + void + merge(list& __x); +#endif + + /** + * @brief Merge sorted lists according to comparison function. + * @tparam _StrictWeakOrdering Comparison function defining + * sort order. + * @param __x Sorted list to merge. + * @param __comp Comparison functor. + * + * Assumes that both @a __x and this list are sorted according to + * StrictWeakOrdering. Merges elements of @a __x into this list + * in sorted order, leaving @a __x empty when complete. Elements + * in this list precede elements in @a __x that are equivalent + * according to StrictWeakOrdering(). + */ +#if __cplusplus >= 201103L + template + void + merge(list&& __x, _StrictWeakOrdering __comp); + + template + void + merge(list& __x, _StrictWeakOrdering __comp) + { merge(std::move(__x), __comp); } +#else + template + void + merge(list& __x, _StrictWeakOrdering __comp); +#endif + + /** + * @brief Reverse the elements in list. + * + * Reverse the order of elements in the list in linear time. + */ + void + reverse() _GLIBCXX_NOEXCEPT + { this->_M_impl._M_node._M_reverse(); } + + /** + * @brief Sort the elements. + * + * Sorts the elements of this list in NlogN time. Equivalent + * elements remain in list order. + */ + void + sort(); + + /** + * @brief Sort the elements according to comparison function. + * + * Sorts the elements of this list in NlogN time. Equivalent + * elements remain in list order. + */ + template + void + sort(_StrictWeakOrdering); + + protected: + // Internal constructor functions follow. + + // Called by the range constructor to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_initialize_dispatch(_Integer __n, _Integer __x, __true_type) + { _M_fill_initialize(static_cast(__n), __x); } + + // Called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else + push_back(*__first); +#endif + } + + // Called by list(n,v,a), and the range constructor when it turns out + // to be the same thing. + void + _M_fill_initialize(size_type __n, const value_type& __x) + { + for (; __n; --__n) + push_back(__x); + } + +#if __cplusplus >= 201103L + // Called by list(n). + void + _M_default_initialize(size_type __n) + { + for (; __n; --__n) + emplace_back(); + } + + // Called by resize(sz). + void + _M_default_append(size_type __n); +#endif + + // Internal assign functions follow. + + // Called by the range assign to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + + // Called by the range assign to implement [23.1.1]/9 + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type); + + // Called by assign(n,t), and the range assign when it turns out + // to be the same thing. + void + _M_fill_assign(size_type __n, const value_type& __val); + + + // Moves the elements from [first,last) before position. + void + _M_transfer(iterator __position, iterator __first, iterator __last) + { __position._M_node->_M_transfer(__first._M_node, __last._M_node); } + + // Inserts new element at position given and with value given. +#if __cplusplus < 201103L + void + _M_insert(iterator __position, const value_type& __x) + { + _Node* __tmp = _M_create_node(__x); + __tmp->_M_hook(__position._M_node); + this->_M_inc_size(1); + } +#else + template + void + _M_insert(iterator __position, _Args&&... __args) + { + _Node* __tmp = _M_create_node(std::forward<_Args>(__args)...); + __tmp->_M_hook(__position._M_node); + this->_M_inc_size(1); + } +#endif + + // Erases element at position given. + void + _M_erase(iterator __position) _GLIBCXX_NOEXCEPT + { + this->_M_dec_size(1); + __position._M_node->_M_unhook(); + _Node* __n = static_cast<_Node*>(__position._M_node); +#if __cplusplus >= 201103L + _Node_alloc_traits::destroy(_M_get_Node_allocator(), __n->_M_valptr()); +#else + _Tp_alloc_type(_M_get_Node_allocator()).destroy(__n->_M_valptr()); +#endif + + _M_put_node(__n); + } + + // To implement the splice (and merge) bits of N1599. + void + _M_check_equal_allocators(list& __x) _GLIBCXX_NOEXCEPT + { + if (std::__alloc_neq:: + _S_do_it(_M_get_Node_allocator(), __x._M_get_Node_allocator())) + __builtin_abort(); + } + + // Used to implement resize. + const_iterator + _M_resize_pos(size_type& __new_size) const; + +#if __cplusplus >= 201103L + void + _M_move_assign(list&& __x, true_type) noexcept + { + this->_M_clear(); + this->_M_move_nodes(std::move(__x)); + std::__alloc_on_move(this->_M_get_Node_allocator(), + __x._M_get_Node_allocator()); + } + + void + _M_move_assign(list&& __x, false_type) + { + if (__x._M_get_Node_allocator() == this->_M_get_Node_allocator()) + _M_move_assign(std::move(__x), true_type{}); + else + // The rvalue's allocator cannot be moved, or is not equal, + // so we need to individually move each element. + _M_assign_dispatch(std::make_move_iterator(__x.begin()), + std::make_move_iterator(__x.end()), + __false_type{}); + } +#endif + }; + +#if __cpp_deduction_guides >= 201606 + template::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + list(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> list<_ValT, _Allocator>; +#endif + +_GLIBCXX_END_NAMESPACE_CXX11 + + /** + * @brief List equality comparison. + * @param __x A %list. + * @param __y A %list of the same type as @a __x. + * @return True iff the size and elements of the lists are equal. + * + * This is an equivalence relation. It is linear in the size of + * the lists. Lists are considered equivalent if their sizes are + * equal, and if corresponding elements compare equal. + */ + template + inline bool + operator==(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { +#if _GLIBCXX_USE_CXX11_ABI + if (__x.size() != __y.size()) + return false; +#endif + + typedef typename list<_Tp, _Alloc>::const_iterator const_iterator; + const_iterator __end1 = __x.end(); + const_iterator __end2 = __y.end(); + + const_iterator __i1 = __x.begin(); + const_iterator __i2 = __y.begin(); + while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) + { + ++__i1; + ++__i2; + } + return __i1 == __end1 && __i2 == __end2; + } + +#if __cpp_lib_three_way_comparison +/** + * @brief List ordering relation. + * @param __x A `list`. + * @param __y A `list` of the same type as `__x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Tp> + operator<=>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + /** + * @brief List ordering relation. + * @param __x A %list. + * @param __y A %list of the same type as @a __x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * lists. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } + + /// Based on operator== + template + inline bool + operator!=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const list<_Tp, _Alloc>& __x, const list<_Tp, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::list::swap(). + template + inline void + swap(list<_Tp, _Alloc>& __x, list<_Tp, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if _GLIBCXX_USE_CXX11_ABI + + // Detect when distance is used to compute the size of the whole list. + template + inline ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_iterator<_Tp> __first, + _GLIBCXX_STD_C::_List_iterator<_Tp> __last, + input_iterator_tag __tag) + { + typedef _GLIBCXX_STD_C::_List_const_iterator<_Tp> _CIter; + return std::__distance(_CIter(__first), _CIter(__last), __tag); + } + + template + inline ptrdiff_t + __distance(_GLIBCXX_STD_C::_List_const_iterator<_Tp> __first, + _GLIBCXX_STD_C::_List_const_iterator<_Tp> __last, + input_iterator_tag) + { + typedef __detail::_List_node_header _Sentinel; + _GLIBCXX_STD_C::_List_const_iterator<_Tp> __beyond = __last; + ++__beyond; + const bool __whole = __first == __beyond; + if (__builtin_constant_p (__whole) && __whole) + return static_cast(__last._M_node)->_M_size; + + ptrdiff_t __n = 0; + while (__first != __last) + { + ++__first; + ++__n; + } + return __n; + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_LIST_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_map.h b/resources/sources/avr-libstdcpp/include/bits/stl_map.h new file mode 100644 index 000000000..2772d1146 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_map.h @@ -0,0 +1,1568 @@ +// Map implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_map.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{map} + */ + +#ifndef _STL_MAP_H +#define _STL_MAP_H 1 + +#include +#include +#if __cplusplus >= 201103L +#include +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + class multimap; + + /** + * @brief A standard container made up of (key,value) pairs, which can be + * retrieved based on a key, in logarithmic time. + * + * @ingroup associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Compare Comparison function object type, defaults to less<_Key>. + * @tparam _Alloc Allocator type, defaults to + * allocator. + * + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using unique keys). + * For a @c map the key_type is Key, the mapped_type is T, and the + * value_type is std::pair. + * + * Maps support bidirectional iterators. + * + * The private tree data is declared exactly the same way for map and + * multimap; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + */ + template , + typename _Alloc = std::allocator > > + class map + { + public: + typedef _Key key_type; + typedef _Tp mapped_type; + typedef std::pair value_type; + typedef _Compare key_compare; + typedef _Alloc allocator_type; + + private: +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires4(_Compare, bool, _Key, _Key, + _BinaryFunctionConcept) + __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L +#if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::map must have the same value_type as its allocator"); +#endif +#endif + + public: + class value_compare + : public std::binary_function + { + friend class map<_Key, _Tp, _Compare, _Alloc>; + protected: + _Compare comp; + + value_compare(_Compare __c) + : comp(__c) { } + + public: + bool operator()(const value_type& __x, const value_type& __y) const + { return comp(__x.first, __y.first); } + }; + + private: + /// This turns a red-black tree into a [multi]map. + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind::other _Pair_alloc_type; + + typedef _Rb_tree, + key_compare, _Pair_alloc_type> _Rep_type; + + /// The actual tree structure. + _Rep_type _M_t; + + typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits; + + public: + // many of these are specified differently in ISO, but the following are + // "functionally equivalent" + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + typedef typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; + using insert_return_type = typename _Rep_type::insert_return_type; +#endif + + // [23.3.1.1] construct/copy/destroy + // (get_allocator() is also listed in this section) + + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + map() : _M_t() { } +#else + map() = default; +#endif + + /** + * @brief Creates a %map with no elements. + * @param __comp A comparison object. + * @param __a An allocator object. + */ + explicit + map(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) { } + + /** + * @brief %Map copy constructor. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + map(const map& __x) + : _M_t(__x._M_t) { } +#else + map(const map&) = default; + + /** + * @brief %Map move constructor. + * + * The newly-created %map contains the exact contents of the moved + * instance. The moved instance is a valid, but unspecified, %map. + */ + map(map&&) = default; + + /** + * @brief Builds a %map from an initializer_list. + * @param __l An initializer_list. + * @param __comp A comparison object. + * @param __a An allocator object. + * + * Create a %map consisting of copies of the elements in the + * initializer_list @a __l. + * This is linear in N if the range is already sorted, and NlogN + * otherwise (where N is @a __l.size()). + */ + map(initializer_list __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) + { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } + + /// Allocator-extended default constructor. + explicit + map(const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) { } + + /// Allocator-extended copy constructor. + map(const map& __m, const allocator_type& __a) + : _M_t(__m._M_t, _Pair_alloc_type(__a)) { } + + /// Allocator-extended move constructor. + map(map&& __m, const allocator_type& __a) + noexcept(is_nothrow_copy_constructible<_Compare>::value + && _Alloc_traits::_S_always_equal()) + : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { } + + /// Allocator-extended initialier-list constructor. + map(initializer_list __l, const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) + { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } + + /// Allocator-extended range constructor. + template + map(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) + { _M_t._M_insert_range_unique(__first, __last); } +#endif + + /** + * @brief Builds a %map from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * + * Create a %map consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is + * already sorted, and NlogN otherwise (where N is + * distance(__first,__last)). + */ + template + map(_InputIterator __first, _InputIterator __last) + : _M_t() + { _M_t._M_insert_range_unique(__first, __last); } + + /** + * @brief Builds a %map from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %map consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is + * already sorted, and NlogN otherwise (where N is + * distance(__first,__last)). + */ + template + map(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) + { _M_t._M_insert_range_unique(__first, __last); } + +#if __cplusplus >= 201103L + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~map() = default; +#endif + + /** + * @brief %Map assignment operator. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + map& + operator=(const map& __x) + { + _M_t = __x._M_t; + return *this; + } +#else + map& + operator=(const map&) = default; + + /// Move assignment operator. + map& + operator=(map&&) = default; + + /** + * @brief %Map list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %map with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %map and + * that the resulting %map's size is the same as the number + * of elements assigned. + */ + map& + operator=(initializer_list __l) + { + _M_t._M_assign_unique(__l.begin(), __l.end()); + return *this; + } +#endif + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_t.get_allocator()); } + + // iterators + /** + * Returns a read/write iterator that points to the first pair in the + * %map. + * Iteration is done in ascending order according to the keys. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %map. Iteration is done in ascending order according to the + * keys. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read/write iterator that points one past the last + * pair in the %map. Iteration is done in ascending order + * according to the keys. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %map. Iteration is done in ascending order according to + * the keys. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read/write reverse iterator that points to the last pair in + * the %map. Iteration is done in descending order according to the + * keys. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %map. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first pair in the %map. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %map. Iteration is done in descending + * order according to the keys. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %map. Iteration is done in ascending order according to the + * keys. + */ + const_iterator + cbegin() const noexcept + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %map. Iteration is done in ascending order according to + * the keys. + */ + const_iterator + cend() const noexcept + { return _M_t.end(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %map. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator + crbegin() const noexcept + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %map. Iteration is done in descending + * order according to the keys. + */ + const_reverse_iterator + crend() const noexcept + { return _M_t.rend(); } +#endif + + // capacity + /** Returns true if the %map is empty. (Thus begin() would equal + * end().) + */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_t.empty(); } + + /** Returns the size of the %map. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_t.size(); } + + /** Returns the maximum size of the %map. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _M_t.max_size(); } + + // [23.3.1.2] element access + /** + * @brief Subscript ( @c [] ) access to %map data. + * @param __k The key for which data should be retrieved. + * @return A reference to the data of the (key,data) %pair. + * + * Allows for easy lookup with the subscript ( @c [] ) + * operator. Returns data associated with the key specified in + * subscript. If the key does not exist, a pair with that key + * is created using default values, which is then returned. + * + * Lookup requires logarithmic time. + */ + mapped_type& + operator[](const key_type& __k) + { + // concept requirements + __glibcxx_function_requires(_DefaultConstructibleConcept) + + iterator __i = lower_bound(__k); + // __i->first is greater than or equivalent to __k. + if (__i == end() || key_comp()(__k, (*__i).first)) +#if __cplusplus >= 201103L + __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct, + std::tuple(__k), + std::tuple<>()); +#else + __i = insert(__i, value_type(__k, mapped_type())); +#endif + return (*__i).second; + } + +#if __cplusplus >= 201103L + mapped_type& + operator[](key_type&& __k) + { + // concept requirements + __glibcxx_function_requires(_DefaultConstructibleConcept) + + iterator __i = lower_bound(__k); + // __i->first is greater than or equivalent to __k. + if (__i == end() || key_comp()(__k, (*__i).first)) + __i = _M_t._M_emplace_hint_unique(__i, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::tuple<>()); + return (*__i).second; + } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + /** + * @brief Access to %map data. + * @param __k The key for which data should be retrieved. + * @return A reference to the data whose key is equivalent to @a __k, if + * such a data is present in the %map. + * @throw std::out_of_range If no such data is present. + */ + mapped_type& + at(const key_type& __k) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + __throw_out_of_range(__N("map::at")); + return (*__i).second; + } + + const mapped_type& + at(const key_type& __k) const + { + const_iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + __throw_out_of_range(__N("map::at")); + return (*__i).second; + } + + // modifiers +#if __cplusplus >= 201103L + /** + * @brief Attempts to build and insert a std::pair into the %map. + * + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to build and insert a (key, value) %pair into + * the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * + * Insertion requires logarithmic time. + */ + template + std::pair + emplace(_Args&&... __args) + { return _M_t._M_emplace_unique(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to build and insert a std::pair into the %map. + * + * @param __pos An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * @return An iterator that points to the element with key of the + * std::pair built from @a __args (may or may not be that + * std::pair). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { + return _M_t._M_emplace_hint_unique(__pos, + std::forward<_Args>(__args)...); + } +#endif + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_unique(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); } + + template + friend class std::_Rb_tree_merge_helper; + + template + void + merge(map<_Key, _Tp, _Cmp2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(map<_Key, _Tp, _Cmp2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(multimap<_Key, _Tp, _Cmp2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(multimap<_Key, _Tp, _Cmp2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus > 201402L +#define __cpp_lib_map_try_emplace 201411 + /** + * @brief Attempts to build and insert a std::pair into the %map. + * + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __args Arguments used to generate the .second for a new pair + * instance. + * + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to build and insert a (key, value) %pair into + * the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * If a %pair is not inserted, this function has no effect. + * + * Insertion requires logarithmic time. + */ + template + pair + try_emplace(const key_type& __k, _Args&&... __args) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return {__i, true}; + } + return {__i, false}; + } + + // move-capable overload + template + pair + try_emplace(key_type&& __k, _Args&&... __args) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return {__i, true}; + } + return {__i, false}; + } + + /** + * @brief Attempts to build and insert a std::pair into the %map. + * + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __args Arguments used to generate the .second for a new pair + * instance. + * @return An iterator that points to the element with key of the + * std::pair built from @a __args (may or may not be that + * std::pair). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument + * try_emplace() does. However, if insertion did not take place, + * this function has no effect. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + try_emplace(const_iterator __hint, const key_type& __k, + _Args&&... __args) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + __i = emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + else + __i = iterator(__true_hint.first); + return __i; + } + + // move-capable overload + template + iterator + try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + __i = emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + else + __i = iterator(__true_hint.first); + return __i; + } +#endif + + /** + * @brief Attempts to insert a std::pair into the %map. + * @param __x Pair to be inserted (see std::make_pair for easy + * creation of pairs). + * + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is + * a bool that is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * + * Insertion requires logarithmic time. + * @{ + */ + std::pair + insert(const value_type& __x) + { return _M_t._M_insert_unique(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + std::pair + insert(value_type&& __x) + { return _M_t._M_insert_unique(std::move(__x)); } + + template + __enable_if_t::value, + pair> + insert(_Pair&& __x) + { return _M_t._M_emplace_unique(std::forward<_Pair>(__x)); } +#endif + // @} + +#if __cplusplus >= 201103L + /** + * @brief Attempts to insert a list of std::pairs into the %map. + * @param __list A std::initializer_list of pairs to be + * inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(std::initializer_list __list) + { insert(__list.begin(), __list.end()); } +#endif + + /** + * @brief Attempts to insert a std::pair into the %map. + * @param __position An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + + * This function is not concerned about whether the insertion + * took place, and thus does not return a boolean like the + * single-argument insert() does. Note that the first + * parameter is only a hint and can potentially improve the + * performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + * @{ + */ + iterator +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { return _M_t._M_insert_unique_(__position, __x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_unique_(__position, std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(const_iterator __position, _Pair&& __x) + { + return _M_t._M_emplace_hint_unique(__position, + std::forward<_Pair>(__x)); + } +#endif + // @} + + /** + * @brief Template function that attempts to insert a range of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_range_unique(__first, __last); } + +#if __cplusplus > 201402L + /** + * @brief Attempts to insert or assign a std::pair into the %map. + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __obj Argument used to generate the .second for a pair + * instance. + * + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is + * a bool that is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * If the %pair was already in the %map, the .second of the %pair + * is assigned from __obj. + * + * Insertion requires logarithmic time. + */ + template + pair + insert_or_assign(const key_type& __k, _Obj&& __obj) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } + + // move-capable overload + template + pair + insert_or_assign(key_type&& __k, _Obj&& __obj) + { + iterator __i = lower_bound(__k); + if (__i == end() || key_comp()(__k, (*__i).first)) + { + __i = emplace_hint(__i, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } + + /** + * @brief Attempts to insert or assign a std::pair into the %map. + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __obj Argument used to generate the .second for a pair + * instance. + * + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + * This function attempts to insert a (key, value) %pair into the %map. + * A %map relies on unique keys and thus a %pair is only inserted if its + * first element (the key) is not already present in the %map. + * If the %pair was already in the %map, the .second of the %pair + * is assigned from __obj. + * + * Insertion requires logarithmic time. + */ + template + iterator + insert_or_assign(const_iterator __hint, + const key_type& __k, _Obj&& __obj) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + { + return emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + __i = iterator(__true_hint.first); + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } + + // move-capable overload + template + iterator + insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) + { + iterator __i; + auto __true_hint = _M_t._M_get_insert_hint_unique_pos(__hint, __k); + if (__true_hint.second) + { + return emplace_hint(iterator(__true_hint.second), + std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + __i = iterator(__true_hint.first); + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases an element from a %map. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given + * iterator, from a %map. Note that this function only erases + * the element, and that if the element is itself a pointer, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + * + * @{ + */ + iterator + erase(const_iterator __position) + { return _M_t.erase(__position); } + + // LWG 2059 + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(iterator __position) + { return _M_t.erase(__position); } + // @} +#else + /** + * @brief Erases an element from a %map. + * @param __position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given + * iterator, from a %map. Note that this function only erases + * the element, and that if the element is itself a pointer, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + */ + void + erase(iterator __position) + { _M_t.erase(__position); } +#endif + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * a %map. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_t.erase(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [first,last) range of elements from a %map. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from a %map. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_t.erase(__first, __last); } +#else + /** + * @brief Erases a [__first,__last) range of elements from a %map. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * + * This function erases a sequence of elements from a %map. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } +#endif + + /** + * @brief Swaps data with another %map. + * @param __x A %map of the same element and allocator types. + * + * This exchanges the elements between two maps in constant + * time. (It is only swapping a pointer, an integer, and an + * instance of the @c Compare type (which itself is often + * stateless and empty), so it should be quite fast.) Note + * that the global std::swap() function is specialized such + * that std::swap(m1,m2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(map& __x) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { _M_t.swap(__x._M_t); } + + /** + * Erases all elements in a %map. Note that this function only + * erases the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_t.clear(); } + + // observers + /** + * Returns the key comparison object out of which the %map was + * constructed. + */ + key_compare + key_comp() const + { return _M_t.key_comp(); } + + /** + * Returns a value comparison object, built from the key comparison + * object out of which the %map was constructed. + */ + value_compare + value_comp() const + { return value_compare(_M_t.key_comp()); } + + // [23.3.1.3] map operations + + //@{ + /** + * @brief Tries to locate an element in a %map. + * @param __x Key of (key, value) %pair to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after %pair. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + + iterator + find(const key_type& __x) + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x)) + { return _M_t._M_find_tr(__x); } +#endif + //@} + + //@{ + /** + * @brief Tries to locate an element in a %map. + * @param __x Key of (key, value) %pair to be located. + * @return Read-only (constant) iterator pointing to sought-after + * element, or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns a constant + * iterator pointing to the sought after %pair. If unsuccessful it + * returns the past-the-end ( @c end() ) iterator. + */ + + const_iterator + find(const key_type& __x) const + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x)) + { return _M_t._M_find_tr(__x); } +#endif + //@} + + //@{ + /** + * @brief Finds the number of elements with given key. + * @param __x Key of (key, value) pairs to be located. + * @return Number of elements with specified key. + * + * This function only makes sense for multimaps; for map the result will + * either be 0 (not present) or 1 (present). + */ + size_type + count(const key_type& __x) const + { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } + +#if __cplusplus > 201103L + template + auto + count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) + { return _M_t._M_count_tr(__x); } +#endif + //@} + +#if __cplusplus > 201703L + //@{ + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of (key, value) pairs to be located. + * @return True if there is an element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_t.find(__x) != _M_t.end(); } + + template + auto + contains(const _Kt& __x) const + -> decltype(_M_t._M_find_tr(__x), void(), true) + { return _M_t._M_find_tr(__x) != _M_t.end(); } + //@} +#endif + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to first element equal to or greater + * than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first element + * equal to or greater than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + const_iterator + lower_bound(const key_type& __x) const + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to the first element + * greater than key, or end(). + */ + iterator + upper_bound(const key_type& __x) + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first iterator + * greater than key, or end(). + */ + const_iterator + upper_bound(const key_type& __x) const + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key of (key, value) pairs to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + * + * This function probably only makes sense for multimaps. + */ + std::pair + equal_range(const key_type& __x) + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key of (key, value) pairs to be located. + * @return Pair of read-only (constant) iterators that possibly points + * to the subsequence matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + * + * This function probably only makes sense for multimaps. + */ + std::pair + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) const + -> decltype(pair( + _M_t._M_equal_range_tr(__x))) + { + return pair( + _M_t._M_equal_range_tr(__x)); + } +#endif + //@} + + template + friend bool + operator==(const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); + +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t> + operator<=>(const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); +#else + template + friend bool + operator<(const map<_K1, _T1, _C1, _A1>&, + const map<_K1, _T1, _C1, _A1>&); +#endif + }; + + +#if __cpp_deduction_guides >= 201606 + + template>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + map(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + _Compare, _Allocator>; + + template, + typename _Allocator = allocator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + map(initializer_list>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> map<_Key, _Tp, _Compare, _Allocator>; + + template , + typename = _RequireAllocator<_Allocator>> + map(_InputIterator, _InputIterator, _Allocator) + -> map<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + less<__iter_key_t<_InputIterator>>, _Allocator>; + + template> + map(initializer_list>, _Allocator) + -> map<_Key, _Tp, less<_Key>, _Allocator>; + +#endif // deduction guides + + /** + * @brief Map equality comparison. + * @param __x A %map. + * @param __y A %map of the same type as @a x. + * @return True iff the size and elements of the maps are equal. + * + * This is an equivalence relation. It is linear in the size of the + * maps. Maps are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t == __y._M_t; } + +#if __cpp_lib_three_way_comparison + /** + * @brief Map ordering relation. + * @param __x A `map`. + * @param __y A `map` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t> + operator<=>(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else + /** + * @brief Map ordering relation. + * @param __x A %map. + * @param __y A %map of the same type as @a x. + * @return True iff @a x is lexicographically less than @a y. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t < __y._M_t; } + + /// Based on operator== + template + inline bool + operator!=(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const map<_Key, _Tp, _Compare, _Alloc>& __x, + const map<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::map::swap(). + template + inline void + swap(map<_Key, _Tp, _Compare, _Alloc>& __x, + map<_Key, _Tp, _Compare, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::map access to internals of compatible maps. + template + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::map<_Key, _Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_MAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h b/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h new file mode 100644 index 000000000..65f4d0117 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_multimap.h @@ -0,0 +1,1233 @@ +// Multimap implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_multimap.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{map} + */ + +#ifndef _STL_MULTIMAP_H +#define _STL_MULTIMAP_H 1 + +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + class map; + + /** + * @brief A standard container made up of (key,value) pairs, which can be + * retrieved based on a key, in logarithmic time. + * + * @ingroup associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Compare Comparison function object type, defaults to less<_Key>. + * @tparam _Alloc Allocator type, defaults to + * allocator. + * + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using equivalent + * keys). For a @c multimap the key_type is Key, the mapped_type + * is T, and the value_type is std::pair. + * + * Multimaps support bidirectional iterators. + * + * The private tree data is declared exactly the same way for map and + * multimap; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + */ + template , + typename _Alloc = std::allocator > > + class multimap + { + public: + typedef _Key key_type; + typedef _Tp mapped_type; + typedef std::pair value_type; + typedef _Compare key_compare; + typedef _Alloc allocator_type; + + private: +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires4(_Compare, bool, _Key, _Key, + _BinaryFunctionConcept) + __glibcxx_class_requires2(value_type, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L +#if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::multimap must have the same value_type as its allocator"); +#endif +#endif + + public: + class value_compare + : public std::binary_function + { + friend class multimap<_Key, _Tp, _Compare, _Alloc>; + protected: + _Compare comp; + + value_compare(_Compare __c) + : comp(__c) { } + + public: + bool operator()(const value_type& __x, const value_type& __y) const + { return comp(__x.first, __y.first); } + }; + + private: + /// This turns a red-black tree into a [multi]map. + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind::other _Pair_alloc_type; + + typedef _Rb_tree, + key_compare, _Pair_alloc_type> _Rep_type; + /// The actual tree structure. + _Rep_type _M_t; + + typedef __gnu_cxx::__alloc_traits<_Pair_alloc_type> _Alloc_traits; + + public: + // many of these are specified differently in ISO, but the following are + // "functionally equivalent" + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + typedef typename _Rep_type::iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + typedef typename _Rep_type::reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; +#endif + + // [23.3.2] construct/copy/destroy + // (get_allocator() is also listed in this section) + + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + multimap() : _M_t() { } +#else + multimap() = default; +#endif + + /** + * @brief Creates a %multimap with no elements. + * @param __comp A comparison object. + * @param __a An allocator object. + */ + explicit + multimap(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) { } + + /** + * @brief %Multimap copy constructor. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + multimap(const multimap& __x) + : _M_t(__x._M_t) { } +#else + multimap(const multimap&) = default; + + /** + * @brief %Multimap move constructor. + * + * The newly-created %multimap contains the exact contents of the + * moved instance. The moved instance is a valid, but unspecified + * %multimap. + */ + multimap(multimap&&) = default; + + /** + * @brief Builds a %multimap from an initializer_list. + * @param __l An initializer_list. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %multimap consisting of copies of the elements from + * the initializer_list. This is linear in N if the list is already + * sorted, and NlogN otherwise (where N is @a __l.size()). + */ + multimap(initializer_list __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) + { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } + + /// Allocator-extended default constructor. + explicit + multimap(const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) { } + + /// Allocator-extended copy constructor. + multimap(const multimap& __m, const allocator_type& __a) + : _M_t(__m._M_t, _Pair_alloc_type(__a)) { } + + /// Allocator-extended move constructor. + multimap(multimap&& __m, const allocator_type& __a) + noexcept(is_nothrow_copy_constructible<_Compare>::value + && _Alloc_traits::_S_always_equal()) + : _M_t(std::move(__m._M_t), _Pair_alloc_type(__a)) { } + + /// Allocator-extended initialier-list constructor. + multimap(initializer_list __l, const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) + { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } + + /// Allocator-extended range constructor. + template + multimap(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : _M_t(_Pair_alloc_type(__a)) + { _M_t._M_insert_range_equal(__first, __last); } +#endif + + /** + * @brief Builds a %multimap from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * + * Create a %multimap consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(__first,__last)). + */ + template + multimap(_InputIterator __first, _InputIterator __last) + : _M_t() + { _M_t._M_insert_range_equal(__first, __last); } + + /** + * @brief Builds a %multimap from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %multimap consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(__first,__last)). + */ + template + multimap(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Pair_alloc_type(__a)) + { _M_t._M_insert_range_equal(__first, __last); } + +#if __cplusplus >= 201103L + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~multimap() = default; +#endif + + /** + * @brief %Multimap assignment operator. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + multimap& + operator=(const multimap& __x) + { + _M_t = __x._M_t; + return *this; + } +#else + multimap& + operator=(const multimap&) = default; + + /// Move assignment operator. + multimap& + operator=(multimap&&) = default; + + /** + * @brief %Multimap list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %multimap with copies of the elements + * in the initializer list @a __l. + * + * Note that the assignment completely changes the %multimap and + * that the resulting %multimap's size is the same as the number + * of elements assigned. + */ + multimap& + operator=(initializer_list __l) + { + _M_t._M_assign_equal(__l.begin(), __l.end()); + return *this; + } +#endif + + /// Get a copy of the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_t.get_allocator()); } + + // iterators + /** + * Returns a read/write iterator that points to the first pair in the + * %multimap. Iteration is done in ascending order according to the + * keys. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %multimap. Iteration is done in ascending order according to + * the keys. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read/write iterator that points one past the last pair in + * the %multimap. Iteration is done in ascending order according to the + * keys. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %multimap. Iteration is done in ascending order according + * to the keys. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read/write reverse iterator that points to the last pair in + * the %multimap. Iteration is done in descending order according to the + * keys. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %multimap. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read/write reverse iterator that points to one before the + * first pair in the %multimap. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %multimap. Iteration is done in + * descending order according to the keys. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first pair + * in the %multimap. Iteration is done in ascending order according to + * the keys. + */ + const_iterator + cbegin() const noexcept + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * pair in the %multimap. Iteration is done in ascending order according + * to the keys. + */ + const_iterator + cend() const noexcept + { return _M_t.end(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %multimap. Iteration is done in descending order + * according to the keys. + */ + const_reverse_iterator + crbegin() const noexcept + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to one + * before the first pair in the %multimap. Iteration is done in + * descending order according to the keys. + */ + const_reverse_iterator + crend() const noexcept + { return _M_t.rend(); } +#endif + + // capacity + /** Returns true if the %multimap is empty. */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_t.empty(); } + + /** Returns the size of the %multimap. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_t.size(); } + + /** Returns the maximum size of the %multimap. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _M_t.max_size(); } + + // modifiers +#if __cplusplus >= 201103L + /** + * @brief Build and insert a std::pair into the %multimap. + * + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * + * @return An iterator that points to the inserted (key,value) pair. + * + * This function builds and inserts a (key, value) %pair into the + * %multimap. + * Contrary to a std::map the %multimap does not rely on unique keys and + * thus multiple pairs with the same key can be inserted. + * + * Insertion requires logarithmic time. + */ + template + iterator + emplace(_Args&&... __args) + { return _M_t._M_emplace_equal(std::forward<_Args>(__args)...); } + + /** + * @brief Builds and inserts a std::pair into the %multimap. + * + * @param __pos An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the %multimap. + * Contrary to a std::map the %multimap does not rely on unique keys and + * thus multiple pairs with the same key can be inserted. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { + return _M_t._M_emplace_hint_equal(__pos, + std::forward<_Args>(__args)...); + } +#endif + + /** + * @brief Inserts a std::pair into the %multimap. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the %multimap. + * Contrary to a std::map the %multimap does not rely on unique keys and + * thus multiple pairs with the same key can be inserted. + * + * Insertion requires logarithmic time. + * @{ + */ + iterator + insert(const value_type& __x) + { return _M_t._M_insert_equal(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(value_type&& __x) + { return _M_t._M_insert_equal(std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(_Pair&& __x) + { return _M_t._M_emplace_equal(std::forward<_Pair>(__x)); } +#endif + // @} + + /** + * @brief Inserts a std::pair into the %multimap. + * @param __position An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the inserted (key,value) pair. + * + * This function inserts a (key, value) pair into the %multimap. + * Contrary to a std::map the %multimap does not rely on unique keys and + * thus multiple pairs with the same key can be inserted. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires logarithmic time (if the hint is not taken). + * @{ + */ + iterator +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { return _M_t._M_insert_equal_(__position, __x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_equal_(__position, std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(const_iterator __position, _Pair&& __x) + { + return _M_t._M_emplace_hint_equal(__position, + std::forward<_Pair>(__x)); + } +#endif + // @} + + /** + * @brief A template function that attempts to insert a range + * of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_range_equal(__first, __last); } + +#if __cplusplus >= 201103L + /** + * @brief Attempts to insert a list of std::pairs into the %multimap. + * @param __l A std::initializer_list of pairs to be + * inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { this->insert(__l.begin(), __l.end()); } +#endif + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_equal(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); } + + template + friend class std::_Rb_tree_merge_helper; + + template + void + merge(multimap<_Key, _Tp, _Cmp2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(multimap<_Key, _Tp, _Cmp2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(map<_Key, _Tp, _Cmp2, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(map<_Key, _Tp, _Cmp2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases an element from a %multimap. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from a %multimap. Note that this function only erases the element, + * and that if the element is itself a pointer, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + * + * @{ + */ + iterator + erase(const_iterator __position) + { return _M_t.erase(__position); } + + // LWG 2059. + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(iterator __position) + { return _M_t.erase(__position); } + // @} +#else + /** + * @brief Erases an element from a %multimap. + * @param __position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, + * from a %multimap. Note that this function only erases the element, + * and that if the element is itself a pointer, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __position) + { _M_t.erase(__position); } +#endif + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all elements located by the given key from a + * %multimap. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_t.erase(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [first,last) range of elements from a %multimap. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to be + * erased . + * @return The iterator @a __last. + * + * This function erases a sequence of elements from a %multimap. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_t.erase(__first, __last); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [first,last) range of elements from a %multimap. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * + * This function erases a sequence of elements from a %multimap. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } +#endif + + /** + * @brief Swaps data with another %multimap. + * @param __x A %multimap of the same element and allocator types. + * + * This exchanges the elements between two multimaps in constant time. + * (It is only swapping a pointer, an integer, and an instance of + * the @c Compare type (which itself is often stateless and empty), so it + * should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(m1,m2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(multimap& __x) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { _M_t.swap(__x._M_t); } + + /** + * Erases all elements in a %multimap. Note that this function only + * erases the elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_t.clear(); } + + // observers + /** + * Returns the key comparison object out of which the %multimap + * was constructed. + */ + key_compare + key_comp() const + { return _M_t.key_comp(); } + + /** + * Returns a value comparison object, built from the key comparison + * object out of which the %multimap was constructed. + */ + value_compare + value_comp() const + { return value_compare(_M_t.key_comp()); } + + // multimap operations + + //@{ + /** + * @brief Tries to locate an element in a %multimap. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to sought-after element, + * or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after %pair. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) -> decltype(_M_t._M_find_tr(__x)) + { return _M_t._M_find_tr(__x); } +#endif + //@} + + //@{ + /** + * @brief Tries to locate an element in a %multimap. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to sought-after + * element, or end() if not found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns a constant + * iterator pointing to the sought after %pair. If unsuccessful it + * returns the past-the-end ( @c end() ) iterator. + */ + const_iterator + find(const key_type& __x) const + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) const -> decltype(_M_t._M_find_tr(__x)) + { return _M_t._M_find_tr(__x); } +#endif + //@} + + //@{ + /** + * @brief Finds the number of elements with given key. + * @param __x Key of (key, value) pairs to be located. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const + { return _M_t.count(__x); } + +#if __cplusplus > 201103L + template + auto + count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) + { return _M_t._M_count_tr(__x); } +#endif + //@} + +#if __cplusplus > 201703L + //@{ + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of (key, value) pairs to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_t.find(__x) != _M_t.end(); } + + template + auto + contains(const _Kt& __x) const + -> decltype(_M_t._M_find_tr(__x), void(), true) + { return _M_t._M_find_tr(__x) != _M_t.end(); } + //@} +#endif + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to first element equal to or greater + * than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first element + * equal to or greater than key, or end(). + * + * This function returns the first element of a subsequence of + * elements that matches the given key. If unsuccessful the + * iterator will point to the next greatest element or, if no + * such greater element exists, to end(). + */ + const_iterator + lower_bound(const key_type& __x) const + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Iterator pointing to the first element + * greater than key, or end(). + */ + iterator + upper_bound(const key_type& __x) + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key of (key, value) pair to be located. + * @return Read-only (constant) iterator pointing to first iterator + * greater than key, or end(). + */ + const_iterator + upper_bound(const key_type& __x) const + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key of (key, value) pairs to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + */ + std::pair + equal_range(const key_type& __x) + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key of (key, value) pairs to be located. + * @return Pair of read-only (constant) iterators that possibly points + * to the subsequence matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + */ + std::pair + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) const + -> decltype(pair( + _M_t._M_equal_range_tr(__x))) + { + return pair( + _M_t._M_equal_range_tr(__x)); + } +#endif + //@} + + template + friend bool + operator==(const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); + +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t> + operator<=>(const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); +#else + template + friend bool + operator<(const multimap<_K1, _T1, _C1, _A1>&, + const multimap<_K1, _T1, _C1, _A1>&); +#endif + }; + +#if __cpp_deduction_guides >= 201606 + + template>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + multimap(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + _Compare, _Allocator>; + + template, + typename _Allocator = allocator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + multimap(initializer_list>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multimap<_Key, _Tp, _Compare, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + multimap(_InputIterator, _InputIterator, _Allocator) + -> multimap<__iter_key_t<_InputIterator>, __iter_val_t<_InputIterator>, + less<__iter_key_t<_InputIterator>>, _Allocator>; + + template> + multimap(initializer_list>, _Allocator) + -> multimap<_Key, _Tp, less<_Key>, _Allocator>; + +#endif // deduction guides + + /** + * @brief Multimap equality comparison. + * @param __x A %multimap. + * @param __y A %multimap of the same type as @a __x. + * @return True iff the size and elements of the maps are equal. + * + * This is an equivalence relation. It is linear in the size of the + * multimaps. Multimaps are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t == __y._M_t; } + +#if __cpp_lib_three_way_comparison + /** + * @brief Multimap ordering relation. + * @param __x A `multimap`. + * @param __y A `multimap` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t> + operator<=>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else + /** + * @brief Multimap ordering relation. + * @param __x A %multimap. + * @param __y A %multimap of the same type as @a __x. + * @return True iff @a x is lexicographically less than @a y. + * + * This is a total ordering relation. It is linear in the size of the + * multimaps. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __x._M_t < __y._M_t; } + + /// Based on operator== + template + inline bool + operator!=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const multimap<_Key, _Tp, _Compare, _Alloc>& __x, + const multimap<_Key, _Tp, _Compare, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::multimap::swap(). + template + inline void + swap(multimap<_Key, _Tp, _Compare, _Alloc>& __x, + multimap<_Key, _Tp, _Compare, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::multimap access to internals of compatible maps. + template + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::map<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multimap<_Key, _Val, _Cmp2, _Alloc>& __map) + { return __map._M_t; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_MULTIMAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h b/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h new file mode 100644 index 000000000..bf6ae7de0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_multiset.h @@ -0,0 +1,1075 @@ +// Multiset implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_multiset.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{set} + */ + +#ifndef _STL_MULTISET_H +#define _STL_MULTISET_H 1 + +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + class set; + + /** + * @brief A standard container made up of elements, which can be retrieved + * in logarithmic time. + * + * @ingroup associative_containers + * + * + * @tparam _Key Type of key objects. + * @tparam _Compare Comparison function object type, defaults to less<_Key>. + * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using equivalent + * keys). For a @c multiset the key_type and value_type are Key. + * + * Multisets support bidirectional iterators. + * + * The private tree data is declared exactly the same way for set and + * multiset; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + */ + template , + typename _Alloc = std::allocator<_Key> > + class multiset + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Key, _SGIAssignableConcept) +# endif + __glibcxx_class_requires4(_Compare, bool, _Key, _Key, + _BinaryFunctionConcept) + __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Key>::value, + "std::multiset must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::multiset must have the same value_type as its allocator"); +# endif +#endif + + public: + // typedefs: + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; + typedef _Alloc allocator_type; + + private: + /// This turns a red-black tree into a [multi]set. + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Key>::other _Key_alloc_type; + + typedef _Rb_tree, + key_compare, _Key_alloc_type> _Rep_type; + /// The actual tree structure. + _Rep_type _M_t; + + typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits; + + public: + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 103. set::iterator is required to be modifiable, + // but this allows modification of keys. + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; +#endif + + // allocation/deallocation + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + multiset() : _M_t() { } +#else + multiset() = default; +#endif + + /** + * @brief Creates a %multiset with no elements. + * @param __comp Comparator to use. + * @param __a An allocator object. + */ + explicit + multiset(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) { } + + /** + * @brief Builds a %multiset from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * + * Create a %multiset consisting of copies of the elements from + * [first,last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(__first,__last)). + */ + template + multiset(_InputIterator __first, _InputIterator __last) + : _M_t() + { _M_t._M_insert_range_equal(__first, __last); } + + /** + * @brief Builds a %multiset from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %multiset consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is already sorted, + * and NlogN otherwise (where N is distance(__first,__last)). + */ + template + multiset(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) + { _M_t._M_insert_range_equal(__first, __last); } + + /** + * @brief %Multiset copy constructor. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + multiset(const multiset& __x) + : _M_t(__x._M_t) { } +#else + multiset(const multiset&) = default; + + /** + * @brief %Multiset move constructor. + * + * The newly-created %multiset contains the exact contents of the + * moved instance. The moved instance is a valid, but unspecified + * %multiset. + */ + multiset(multiset&&) = default; + + /** + * @brief Builds a %multiset from an initializer_list. + * @param __l An initializer_list. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %multiset consisting of copies of the elements from + * the list. This is linear in N if the list is already sorted, + * and NlogN otherwise (where N is @a __l.size()). + */ + multiset(initializer_list __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) + { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } + + /// Allocator-extended default constructor. + explicit + multiset(const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) { } + + /// Allocator-extended copy constructor. + multiset(const multiset& __m, const allocator_type& __a) + : _M_t(__m._M_t, _Key_alloc_type(__a)) { } + + /// Allocator-extended move constructor. + multiset(multiset&& __m, const allocator_type& __a) + noexcept(is_nothrow_copy_constructible<_Compare>::value + && _Alloc_traits::_S_always_equal()) + : _M_t(std::move(__m._M_t), _Key_alloc_type(__a)) { } + + /// Allocator-extended initialier-list constructor. + multiset(initializer_list __l, const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) + { _M_t._M_insert_range_equal(__l.begin(), __l.end()); } + + /// Allocator-extended range constructor. + template + multiset(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) + { _M_t._M_insert_range_equal(__first, __last); } + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~multiset() = default; +#endif + + /** + * @brief %Multiset assignment operator. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + multiset& + operator=(const multiset& __x) + { + _M_t = __x._M_t; + return *this; + } +#else + multiset& + operator=(const multiset&) = default; + + /// Move assignment operator. + multiset& + operator=(multiset&&) = default; + + /** + * @brief %Multiset list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %multiset with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %multiset and + * that the resulting %multiset's size is the same as the number + * of elements assigned. + */ + multiset& + operator=(initializer_list __l) + { + _M_t._M_assign_equal(__l.begin(), __l.end()); + return *this; + } +#endif + + // accessors: + + /// Returns the comparison object. + key_compare + key_comp() const + { return _M_t.key_comp(); } + /// Returns the comparison object. + value_compare + value_comp() const + { return _M_t.key_comp(); } + /// Returns the memory allocation object. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_t.get_allocator()); } + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %multiset. Iteration is done in ascending order + * according to the keys. + */ + iterator + begin() const _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %multiset. Iteration is done in ascending order + * according to the keys. + */ + iterator + end() const _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last element in the %multiset. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last element in the %multiset. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %multiset. Iteration is done in ascending order + * according to the keys. + */ + iterator + cbegin() const noexcept + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %multiset. Iteration is done in ascending order + * according to the keys. + */ + iterator + cend() const noexcept + { return _M_t.end(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last element in the %multiset. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + crbegin() const noexcept + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last element in the %multiset. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + crend() const noexcept + { return _M_t.rend(); } +#endif + + /// Returns true if the %set is empty. + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_t.empty(); } + + /// Returns the size of the %set. + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_t.size(); } + + /// Returns the maximum size of the %set. + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _M_t.max_size(); } + + /** + * @brief Swaps data with another %multiset. + * @param __x A %multiset of the same element and allocator types. + * + * This exchanges the elements between two multisets in constant time. + * (It is only swapping a pointer, an integer, and an instance of the @c + * Compare type (which itself is often stateless and empty), so it should + * be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(s1,s2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(multiset& __x) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { _M_t.swap(__x._M_t); } + + // insert/erase +#if __cplusplus >= 201103L + /** + * @brief Builds and inserts an element into the %multiset. + * @param __args Arguments used to generate the element instance to be + * inserted. + * @return An iterator that points to the inserted element. + * + * This function inserts an element into the %multiset. Contrary + * to a std::set the %multiset does not rely on unique keys and thus + * multiple copies of the same element can be inserted. + * + * Insertion requires logarithmic time. + */ + template + iterator + emplace(_Args&&... __args) + { return _M_t._M_emplace_equal(std::forward<_Args>(__args)...); } + + /** + * @brief Builds and inserts an element into the %multiset. + * @param __pos An iterator that serves as a hint as to where the + * element should be inserted. + * @param __args Arguments used to generate the element instance to be + * inserted. + * @return An iterator that points to the inserted element. + * + * This function inserts an element into the %multiset. Contrary + * to a std::set the %multiset does not rely on unique keys and thus + * multiple copies of the same element can be inserted. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { + return _M_t._M_emplace_hint_equal(__pos, + std::forward<_Args>(__args)...); + } +#endif + + /** + * @brief Inserts an element into the %multiset. + * @param __x Element to be inserted. + * @return An iterator that points to the inserted element. + * + * This function inserts an element into the %multiset. Contrary + * to a std::set the %multiset does not rely on unique keys and thus + * multiple copies of the same element can be inserted. + * + * Insertion requires logarithmic time. + */ + iterator + insert(const value_type& __x) + { return _M_t._M_insert_equal(__x); } + +#if __cplusplus >= 201103L + iterator + insert(value_type&& __x) + { return _M_t._M_insert_equal(std::move(__x)); } +#endif + + /** + * @brief Inserts an element into the %multiset. + * @param __position An iterator that serves as a hint as to where the + * element should be inserted. + * @param __x Element to be inserted. + * @return An iterator that points to the inserted element. + * + * This function inserts an element into the %multiset. Contrary + * to a std::set the %multiset does not rely on unique keys and thus + * multiple copies of the same element can be inserted. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + iterator + insert(const_iterator __position, const value_type& __x) + { return _M_t._M_insert_equal_(__position, __x); } + +#if __cplusplus >= 201103L + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_equal_(__position, std::move(__x)); } +#endif + + /** + * @brief A template function that tries to insert a range of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_range_equal(__first, __last); } + +#if __cplusplus >= 201103L + /** + * @brief Attempts to insert a list of elements into the %multiset. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { this->insert(__l.begin(), __l.end()); } +#endif + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_equal(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_equal(__hint, std::move(__nh)); } + + template + friend class std::_Rb_tree_merge_helper; + + template + void + merge(multiset<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(multiset<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(set<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_equal(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(set<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases an element from a %multiset. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from a %multiset. Note that this function only erases the element, + * and that if the element is itself a pointer, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __position) + { return _M_t.erase(__position); } +#else + /** + * @brief Erases an element from a %multiset. + * @param __position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, + * from a %multiset. Note that this function only erases the element, + * and that if the element is itself a pointer, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __position) + { _M_t.erase(__position); } +#endif + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all elements located by the given key from a + * %multiset. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_t.erase(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [first,last) range of elements from a %multiset. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a last. + * + * This function erases a sequence of elements from a %multiset. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_t.erase(__first, __last); } +#else + /** + * @brief Erases a [first,last) range of elements from a %multiset. + * @param first Iterator pointing to the start of the range to be + * erased. + * @param last Iterator pointing to the end of the range to be erased. + * + * This function erases a sequence of elements from a %multiset. + * Note that this function only erases the elements, and that if + * the elements themselves are pointers, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } +#endif + + /** + * Erases all elements in a %multiset. Note that this function only + * erases the elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_t.clear(); } + + // multiset operations: + + //@{ + /** + * @brief Finds the number of elements with given key. + * @param __x Key of elements to be located. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const + { return _M_t.count(__x); } + +#if __cplusplus > 201103L + template + auto + count(const _Kt& __x) const -> decltype(_M_t._M_count_tr(__x)) + { return _M_t._M_count_tr(__x); } +#endif + //@} + +#if __cplusplus > 201703L + //@{ + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_t.find(__x) != _M_t.end(); } + + template + auto + contains(const _Kt& __x) const + -> decltype(_M_t._M_find_tr(__x), void(), true) + { return _M_t._M_find_tr(__x) != _M_t.end(); } + //@} +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + //@{ + /** + * @brief Tries to locate an element in a %set. + * @param __x Element to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_t.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) + -> decltype(iterator{_M_t._M_find_tr(__x)}) + { return iterator{_M_t._M_find_tr(__x)}; } + + template + auto + find(const _Kt& __x) const + -> decltype(const_iterator{_M_t._M_find_tr(__x)}) + { return const_iterator{_M_t._M_find_tr(__x)}; } +#endif + //@} + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key to be located. + * @return Iterator pointing to first element equal to or greater + * than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) + { return _M_t.lower_bound(__x); } + + const_iterator + lower_bound(const key_type& __x) const + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } + + template + auto + lower_bound(const _Kt& __x) const + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key to be located. + * @return Iterator pointing to the first element + * greater than key, or end(). + */ + iterator + upper_bound(const key_type& __x) + { return _M_t.upper_bound(__x); } + + const_iterator + upper_bound(const key_type& __x) const + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } + + template + auto + upper_bound(const _Kt& __x) const + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + * + * This function probably only makes sense for multisets. + */ + std::pair + equal_range(const key_type& __x) + { return _M_t.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } + + template + auto + equal_range(const _Kt& __x) const + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } +#endif + //@} + + template + friend bool + operator==(const multiset<_K1, _C1, _A1>&, + const multiset<_K1, _C1, _A1>&); + +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t<_K1> + operator<=>(const multiset<_K1, _C1, _A1>&, + const multiset<_K1, _C1, _A1>&); +#else + template + friend bool + operator< (const multiset<_K1, _C1, _A1>&, + const multiset<_K1, _C1, _A1>&); +#endif + }; + +#if __cpp_deduction_guides >= 201606 + + template::value_type>, + typename _Allocator = + allocator::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + multiset(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset::value_type, + _Compare, _Allocator>; + + template, + typename _Allocator = allocator<_Key>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + multiset(initializer_list<_Key>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> multiset<_Key, _Compare, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + multiset(_InputIterator, _InputIterator, _Allocator) + -> multiset::value_type, + less::value_type>, + _Allocator>; + + template> + multiset(initializer_list<_Key>, _Allocator) + -> multiset<_Key, less<_Key>, _Allocator>; + +#endif // deduction guides + + /** + * @brief Multiset equality comparison. + * @param __x A %multiset. + * @param __y A %multiset of the same type as @a __x. + * @return True iff the size and elements of the multisets are equal. + * + * This is an equivalence relation. It is linear in the size of the + * multisets. + * Multisets are considered equivalent if their sizes are equal, and if + * corresponding elements compare equal. + */ + template + inline bool + operator==(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return __x._M_t == __y._M_t; } + +#if __cpp_lib_three_way_comparison + /** + * @brief Multiset ordering relation. + * @param __x A `multiset`. + * @param __y A `multiset` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Key> + operator<=>(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else + /** + * @brief Multiset ordering relation. + * @param __x A %multiset. + * @param __y A %multiset of the same type as @a __x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * sets. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return __x._M_t < __y._M_t; } + + /// Returns !(x == y). + template + inline bool + operator!=(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return !(__x == __y); } + + /// Returns y < x. + template + inline bool + operator>(const multiset<_Key,_Compare,_Alloc>& __x, + const multiset<_Key,_Compare,_Alloc>& __y) + { return __y < __x; } + + /// Returns !(y < x) + template + inline bool + operator<=(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return !(__y < __x); } + + /// Returns !(x < y) + template + inline bool + operator>=(const multiset<_Key, _Compare, _Alloc>& __x, + const multiset<_Key, _Compare, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::multiset::swap(). + template + inline void + swap(multiset<_Key, _Compare, _Alloc>& __x, + multiset<_Key, _Compare, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::multiset access to internals of compatible sets. + template + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::multiset<_Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_MULTISET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h b/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h new file mode 100644 index 000000000..f95c86a0d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_numeric.h @@ -0,0 +1,413 @@ +// Numeric functions implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_numeric.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{numeric} + */ + +#ifndef _STL_NUMERIC_H +#define _STL_NUMERIC_H 1 + +#include +#include +#include // For _GLIBCXX_MOVE + + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @defgroup numeric_ops Generalized Numeric operations + * @ingroup algorithms + */ + +#if __cplusplus >= 201103L + /** + * @brief Create a range of sequentially increasing values. + * + * For each element in the range @p [first,last) assigns @p value and + * increments @p value as if by @p ++value. + * + * @param __first Start of range. + * @param __last End of range. + * @param __value Starting value. + * @return Nothing. + * @ingroup numeric_ops + */ + template + _GLIBCXX20_CONSTEXPR + void + iota(_ForwardIterator __first, _ForwardIterator __last, _Tp __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept< + _ForwardIterator>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + { + *__first = __value; + ++__value; + } + } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION + +_GLIBCXX_BEGIN_NAMESPACE_ALGO + +#if __cplusplus > 201703L +// _GLIBCXX_RESOLVE_LIB_DEFECTS +// DR 2055. std::move in std::accumulate and other algorithms +# define _GLIBCXX_MOVE_IF_20(_E) std::move(_E) +#else +# define _GLIBCXX_MOVE_IF_20(_E) _E +#endif + + /// @addtogroup numeric_ops + /// @{ + + /** + * @brief Accumulate values in a range. + * + * Accumulates the values in the range [first,last) using operator+(). The + * initial value is @a init. The values are processed in order. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @return The final sum. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + accumulate(_InputIterator __first, _InputIterator __last, _Tp __init) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + __init = _GLIBCXX_MOVE_IF_20(__init) + *__first; + return __init; + } + + /** + * @brief Accumulate values in a range with operation. + * + * Accumulates the values in the range `[first,last)` using the function + * object `__binary_op`. The initial value is `__init`. The values are + * processed in order. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op Function object to accumulate with. + * @return The final sum. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + accumulate(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_requires_valid_range(__first, __last); + + for (; __first != __last; ++__first) + __init = __binary_op(_GLIBCXX_MOVE_IF_20(__init), *__first); + return __init; + } + + /** + * @brief Compute inner product of two ranges. + * + * Starting with an initial value of @p __init, multiplies successive + * elements from the two ranges and adds each product into the accumulated + * value using operator+(). The values in the ranges are processed in + * order. + * + * @param __first1 Start of range 1. + * @param __last1 End of range 1. + * @param __first2 Start of range 2. + * @param __init Starting value to add other values to. + * @return The final inner product. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + inner_product(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + __init = _GLIBCXX_MOVE_IF_20(__init) + (*__first1 * *__first2); + return __init; + } + + /** + * @brief Compute inner product of two ranges. + * + * Starting with an initial value of @p __init, applies @p __binary_op2 to + * successive elements from the two ranges and accumulates each result into + * the accumulated value using @p __binary_op1. The values in the ranges are + * processed in order. + * + * @param __first1 Start of range 1. + * @param __last1 End of range 1. + * @param __first2 Start of range 2. + * @param __init Starting value to add other values to. + * @param __binary_op1 Function object to accumulate with. + * @param __binary_op2 Function object to apply to pairs of input values. + * @return The final inner product. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + inner_product(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init, + _BinaryOperation1 __binary_op1, + _BinaryOperation2 __binary_op2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_requires_valid_range(__first1, __last1); + + for (; __first1 != __last1; ++__first1, (void)++__first2) + __init = __binary_op1(_GLIBCXX_MOVE_IF_20(__init), + __binary_op2(*__first1, *__first2)); + return __init; + } + + /** + * @brief Return list of partial sums + * + * Accumulates the values in the range [first,last) using the @c + operator. + * As each successive input value is added into the total, that partial sum + * is written to @p __result. Therefore, the first value in @p __result is + * the first value of the input, the second value in @p __result is the sum + * of the first and second input values, and so on. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @return Iterator pointing just beyond the values written to __result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + partial_sum(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + __value = _GLIBCXX_MOVE_IF_20(__value) + *__first; + *++__result = __value; + } + return ++__result; + } + + /** + * @brief Return list of partial sums + * + * Accumulates the values in the range [first,last) using @p __binary_op. + * As each successive input value is added into the total, that partial sum + * is written to @p __result. Therefore, the first value in @p __result is + * the first value of the input, the second value in @p __result is the sum + * of the first and second input values, and so on. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @param __binary_op Function object. + * @return Iterator pointing just beyond the values written to __result. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + partial_sum(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + __value = __binary_op(_GLIBCXX_MOVE_IF_20(__value), *__first); + *++__result = __value; + } + return ++__result; + } + + /** + * @brief Return differences between adjacent values. + * + * Computes the difference between adjacent values in the range + * [first,last) using operator-() and writes the result to @p __result. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sums. + * @return Iterator pointing just beyond the values written to result. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 539. partial_sum and adjacent_difference should mention requirements + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + adjacent_difference(_InputIterator __first, + _InputIterator __last, _OutputIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + _ValueType __tmp = *__first; + *++__result = __tmp - _GLIBCXX_MOVE_IF_20(__value); + __value = _GLIBCXX_MOVE(__tmp); + } + return ++__result; + } + + /** + * @brief Return differences between adjacent values. + * + * Computes the difference between adjacent values in the range + * [__first,__last) using the function object @p __binary_op and writes the + * result to @p __result. + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Output sum. + * @param __binary_op Function object. + * @return Iterator pointing just beyond the values written to result. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS + * DR 539. partial_sum and adjacent_difference should mention requirements + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + adjacent_difference(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + typedef typename iterator_traits<_InputIterator>::value_type _ValueType; + + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + _ValueType>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return __result; + _ValueType __value = *__first; + *__result = __value; + while (++__first != __last) + { + _ValueType __tmp = *__first; + *++__result = __binary_op(__tmp, _GLIBCXX_MOVE_IF_20(__value)); + __value = _GLIBCXX_MOVE(__tmp); + } + return ++__result; + } + + // @} group numeric_ops + +#undef _GLIBCXX_MOVE_IF_20 + +_GLIBCXX_END_NAMESPACE_ALGO +} // namespace std + +#endif /* _STL_NUMERIC_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_pair.h b/resources/sources/avr-libstdcpp/include/bits/stl_pair.h new file mode 100644 index 000000000..491c59907 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_pair.h @@ -0,0 +1,586 @@ +// Pair implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_pair.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + */ + +#ifndef _STL_PAIR_H +#define _STL_PAIR_H 1 + +#include // for std::move / std::forward, and std::swap + +#if __cplusplus >= 201103L +# include // for std::__decay_and_strip, std::is_reference_v +#endif +#if __cplusplus > 201703L +# include +# define __cpp_lib_constexpr_utility 201811L +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + +#if __cplusplus >= 201103L + /// Tag type for piecewise construction of std::pair objects. + struct piecewise_construct_t { explicit piecewise_construct_t() = default; }; + + /// Tag for piecewise construction of std::pair objects. + _GLIBCXX17_INLINE constexpr piecewise_construct_t piecewise_construct = + piecewise_construct_t(); + + /// @cond undocumented + + // Forward declarations. + template + class tuple; + + template + struct _Index_tuple; + + // Concept utility functions, reused in conditionally-explicit + // constructors. + // See PR 70437, don't look at is_constructible or + // is_convertible if the types are the same to + // avoid querying those properties for incomplete types. + template + struct _PCC + { + template + static constexpr bool _ConstructiblePair() + { + return __and_, + is_constructible<_T2, const _U2&>>::value; + } + + template + static constexpr bool _ImplicitlyConvertiblePair() + { + return __and_, + is_convertible>::value; + } + + template + static constexpr bool _MoveConstructiblePair() + { + return __and_, + is_constructible<_T2, _U2&&>>::value; + } + + template + static constexpr bool _ImplicitlyMoveConvertiblePair() + { + return __and_, + is_convertible<_U2&&, _T2>>::value; + } + + template + static constexpr bool _CopyMovePair() + { + using __do_converts = __and_, + is_convertible<_U2&&, _T2>>; + using __converts = typename conditional<__implicit, + __do_converts, + __not_<__do_converts>>::type; + return __and_, + is_constructible<_T2, _U2&&>, + __converts + >::value; + } + + template + static constexpr bool _MoveCopyPair() + { + using __do_converts = __and_, + is_convertible>; + using __converts = typename conditional<__implicit, + __do_converts, + __not_<__do_converts>>::type; + return __and_, + is_constructible<_T2, const _U2&&>, + __converts + >::value; + } + }; + + template + struct _PCC + { + template + static constexpr bool _ConstructiblePair() + { + return false; + } + + template + static constexpr bool _ImplicitlyConvertiblePair() + { + return false; + } + + template + static constexpr bool _MoveConstructiblePair() + { + return false; + } + + template + static constexpr bool _ImplicitlyMoveConvertiblePair() + { + return false; + } + }; +#endif // C++11 + + template class __pair_base + { +#if __cplusplus >= 201103L + template friend struct pair; + __pair_base() = default; + ~__pair_base() = default; + __pair_base(const __pair_base&) = default; + __pair_base& operator=(const __pair_base&) = delete; +#endif // C++11 + }; + + /// @endcond + + /** + * @brief Struct holding two objects of arbitrary type. + * + * @tparam _T1 Type of first object. + * @tparam _T2 Type of second object. + * + * + */ + template + struct pair + : private __pair_base<_T1, _T2> + { + typedef _T1 first_type; ///< The type of the `first` member + typedef _T2 second_type; ///< The type of the `second` member + + _T1 first; ///< The first member + _T2 second; ///< The second member + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 265. std::pair::pair() effects overly restrictive + /** The default constructor creates @c first and @c second using their + * respective default constructors. */ +#if __cplusplus >= 201103L + template , + __is_implicitly_default_constructible<_U2>> + ::value, bool>::type = true> +#endif + _GLIBCXX_CONSTEXPR pair() + : first(), second() { } + +#if __cplusplus >= 201103L + template , + is_default_constructible<_U2>, + __not_< + __and_<__is_implicitly_default_constructible<_U1>, + __is_implicitly_default_constructible<_U2>>>> + ::value, bool>::type = false> + explicit constexpr pair() + : first(), second() { } +#endif + +#if __cplusplus < 201103L + /// Two objects may be passed to a @c pair constructor to be copied. + pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } +#else + // Shortcut for constraining the templates that don't take pairs. + /// @cond undocumented + using _PCCP = _PCC; + /// @endcond + + /// Construct from two const lvalues, allowing implicit conversions. + template() + && _PCCP::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } + + /// Construct from two const lvalues, disallowing implicit conversions. + template() + && !_PCCP::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(const _T1& __a, const _T2& __b) + : first(__a), second(__b) { } +#endif + +#if __cplusplus < 201103L + /// There is also a templated constructor to convert from other pairs. + template + pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) { } +#else + // Shortcut for constraining the templates that take pairs. + /// @cond undocumented + template + using _PCCFP = _PCC::value + || !is_same<_T2, _U2>::value, + _T1, _T2>; + /// @endcond + + template::template + _ConstructiblePair<_U1, _U2>() + && _PCCFP<_U1, _U2>::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) { } + + template::template + _ConstructiblePair<_U1, _U2>() + && !_PCCFP<_U1, _U2>::template + _ImplicitlyConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(const pair<_U1, _U2>& __p) + : first(__p.first), second(__p.second) { } +#endif + +#if __cplusplus >= 201103L + constexpr pair(const pair&) = default; ///< Copy constructor + constexpr pair(pair&&) = default; ///< Move constructor + + // DR 811. + template(), + bool>::type=true> + constexpr pair(_U1&& __x, const _T2& __y) + : first(std::forward<_U1>(__x)), second(__y) { } + + template(), + bool>::type=false> + explicit constexpr pair(_U1&& __x, const _T2& __y) + : first(std::forward<_U1>(__x)), second(__y) { } + + template(), + bool>::type=true> + constexpr pair(const _T1& __x, _U2&& __y) + : first(__x), second(std::forward<_U2>(__y)) { } + + template(), + bool>::type=false> + explicit pair(const _T1& __x, _U2&& __y) + : first(__x), second(std::forward<_U2>(__y)) { } + + template() + && _PCCP::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(_U1&& __x, _U2&& __y) + : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } + + template() + && !_PCCP::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(_U1&& __x, _U2&& __y) + : first(std::forward<_U1>(__x)), second(std::forward<_U2>(__y)) { } + + + template::template + _MoveConstructiblePair<_U1, _U2>() + && _PCCFP<_U1, _U2>::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=true> + constexpr pair(pair<_U1, _U2>&& __p) + : first(std::forward<_U1>(__p.first)), + second(std::forward<_U2>(__p.second)) { } + + template::template + _MoveConstructiblePair<_U1, _U2>() + && !_PCCFP<_U1, _U2>::template + _ImplicitlyMoveConvertiblePair<_U1, _U2>(), + bool>::type=false> + explicit constexpr pair(pair<_U1, _U2>&& __p) + : first(std::forward<_U1>(__p.first)), + second(std::forward<_U2>(__p.second)) { } + + template + _GLIBCXX20_CONSTEXPR + pair(piecewise_construct_t, tuple<_Args1...>, tuple<_Args2...>); + + _GLIBCXX20_CONSTEXPR pair& + operator=(typename conditional< + __and_, + is_copy_assignable<_T2>>::value, + const pair&, const __nonesuch&>::type __p) + { + first = __p.first; + second = __p.second; + return *this; + } + + _GLIBCXX20_CONSTEXPR pair& + operator=(typename conditional< + __and_, + is_move_assignable<_T2>>::value, + pair&&, __nonesuch&&>::type __p) + noexcept(__and_, + is_nothrow_move_assignable<_T2>>::value) + { + first = std::forward(__p.first); + second = std::forward(__p.second); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + typename enable_if<__and_, + is_assignable<_T2&, const _U2&>>::value, + pair&>::type + operator=(const pair<_U1, _U2>& __p) + { + first = __p.first; + second = __p.second; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + typename enable_if<__and_, + is_assignable<_T2&, _U2&&>>::value, + pair&>::type + operator=(pair<_U1, _U2>&& __p) + { + first = std::forward<_U1>(__p.first); + second = std::forward<_U2>(__p.second); + return *this; + } + + /// Swap the first members and then the second members. + _GLIBCXX20_CONSTEXPR void + swap(pair& __p) + noexcept(__and_<__is_nothrow_swappable<_T1>, + __is_nothrow_swappable<_T2>>::value) + { + using std::swap; + swap(first, __p.first); + swap(second, __p.second); + } + + private: + template + _GLIBCXX20_CONSTEXPR + pair(tuple<_Args1...>&, tuple<_Args2...>&, + _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>); +#endif // C++11 + }; + + /// @relates pair @{ + +#if __cpp_deduction_guides >= 201606 + template pair(_T1, _T2) -> pair<_T1, _T2>; +#endif + + /// Two pairs of the same type are equal iff their members are equal. + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __x.first == __y.first && __x.second == __y.second; } + +#if __cpp_lib_three_way_comparison && __cpp_lib_concepts + template + constexpr common_comparison_category_t<__detail::__synth3way_t<_T1>, + __detail::__synth3way_t<_T2>> + operator<=>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { + if (auto __c = __detail::__synth3way(__x.first, __y.first); __c != 0) + return __c; + return __detail::__synth3way(__x.second, __y.second); + } +#else + /** Defines a lexicographical order for pairs. + * + * For two pairs of the same type, `P` is ordered before `Q` if + * `P.first` is less than `Q.first`, or if `P.first` and `Q.first` + * are equivalent (neither is less than the other) and `P.second` is less + * than `Q.second`. + */ + template + inline _GLIBCXX_CONSTEXPR bool + operator<(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __x.first < __y.first + || (!(__y.first < __x.first) && __x.second < __y.second); } + + /// Uses @c operator== to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__x == __y); } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator>(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return __y < __x; } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator<=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__y < __x); } + + /// Uses @c operator< to find the result. + template + inline _GLIBCXX_CONSTEXPR bool + operator>=(const pair<_T1, _T2>& __x, const pair<_T1, _T2>& __y) + { return !(__x < __y); } +#endif // !(three_way_comparison && concepts) + +#if __cplusplus >= 201103L + /** Swap overload for pairs. Calls std::pair::swap(). + * + * @note This std::swap overload is not declared in C++03 mode, + * which has performance implications, e.g. see https://gcc.gnu.org/PR38466 + */ + template + _GLIBCXX20_CONSTEXPR inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_T1>, + __is_swappable<_T2>>::value>::type +#else + void +#endif + swap(pair<_T1, _T2>& __x, pair<_T1, _T2>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + typename enable_if, + __is_swappable<_T2>>::value>::type + swap(pair<_T1, _T2>&, pair<_T1, _T2>&) = delete; +#endif +#endif // __cplusplus >= 201103L + + // @} relates pair + + /** + * @brief A convenience wrapper for creating a pair from two objects. + * @param __x The first object. + * @param __y The second object. + * @return A newly-constructed pair<> object of the appropriate type. + * + * The C++98 standard says the objects are passed by reference-to-const, + * but C++03 says they are passed by value (this was LWG issue #181). + * + * Since C++11 they have been passed by forwarding reference and then + * forwarded to the new members of the pair. To create a pair with a + * member of reference type, pass a `reference_wrapper` to this function. + */ + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 181. make_pair() unintended behavior +#if __cplusplus >= 201103L + // NB: DR 706. + template + constexpr pair::__type, + typename __decay_and_strip<_T2>::__type> + make_pair(_T1&& __x, _T2&& __y) + { + typedef typename __decay_and_strip<_T1>::__type __ds_type1; + typedef typename __decay_and_strip<_T2>::__type __ds_type2; + typedef pair<__ds_type1, __ds_type2> __pair_type; + return __pair_type(std::forward<_T1>(__x), std::forward<_T2>(__y)); + } +#else + template + inline pair<_T1, _T2> + make_pair(_T1 __x, _T2 __y) + { return pair<_T1, _T2>(__x, __y); } +#endif + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_PAIR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_queue.h b/resources/sources/avr-libstdcpp/include/bits/stl_queue.h new file mode 100644 index 000000000..8635d4267 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_queue.h @@ -0,0 +1,753 @@ +// Queue implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_queue.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{queue} + */ + +#ifndef _STL_QUEUE_H +#define _STL_QUEUE_H 1 + +#include +#include +#if __cplusplus >= 201103L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief A standard container giving FIFO behavior. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Sequence Type of underlying sequence, defaults to deque<_Tp>. + * + * Meets many of the requirements of a + * container, + * but does not define anything to do with iterators. Very few of the + * other standard container interfaces are defined. + * + * This is not a true container, but an @e adaptor. It holds another + * container, and provides a wrapper interface to that container. The + * wrapper is what enforces strict first-in-first-out %queue behavior. + * + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::deque, but it can be any type + * that supports @c front, @c back, @c push_back, and @c pop_front, + * such as std::list or an appropriate user-defined type. + * + * Members not found in @a normal containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c push and + * @c pop, which are standard %queue/FIFO operations. + */ + template > + class queue + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Sequence::value_type _Sequence_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires(_Sequence, _FrontInsertionSequenceConcept) + __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) + __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) +#endif + + template + friend bool + operator==(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); + + template + friend bool + operator<(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); + +#if __cpp_lib_three_way_comparison + template + friend compare_three_way_result_t<_Seq1> + operator<=>(const queue<_Tp1, _Seq1>&, const queue<_Tp1, _Seq1>&); +#endif + +#if __cplusplus >= 201103L + template + using _Uses = typename + enable_if::value>::type; + +#if __cplusplus >= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2566. Requirements on the first template parameter of container + // adaptors + static_assert(is_same<_Tp, typename _Sequence::value_type>::value, + "value_type must be the same as the underlying container"); +#endif // C++17 +#endif // C++11 + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + protected: + /* Maintainers wondering why this isn't uglified as per style + * guidelines should note that this name is specified in the standard, + * C++98 [23.2.3.1]. + * (Why? Presumably for the same reason that it's protected instead + * of private: to allow derivation. But none of the other + * containers allow for derivation. Odd.) + */ + /// @c c is the underlying container. + _Sequence c; + + public: + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + explicit + queue(const _Sequence& __c = _Sequence()) + : c(__c) { } +#else + template::value>::type> + queue() + : c() { } + + explicit + queue(const _Sequence& __c) + : c(__c) { } + + explicit + queue(_Sequence&& __c) + : c(std::move(__c)) { } + + template> + explicit + queue(const _Alloc& __a) + : c(__a) { } + + template> + queue(const _Sequence& __c, const _Alloc& __a) + : c(__c, __a) { } + + template> + queue(_Sequence&& __c, const _Alloc& __a) + : c(std::move(__c), __a) { } + + template> + queue(const queue& __q, const _Alloc& __a) + : c(__q.c, __a) { } + + template> + queue(queue&& __q, const _Alloc& __a) + : c(std::move(__q.c), __a) { } +#endif + + /** + * Returns true if the %queue is empty. + */ + _GLIBCXX_NODISCARD bool + empty() const + { return c.empty(); } + + /** Returns the number of elements in the %queue. */ + size_type + size() const + { return c.size(); } + + /** + * Returns a read/write reference to the data at the first + * element of the %queue. + */ + reference + front() + { + __glibcxx_requires_nonempty(); + return c.front(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %queue. + */ + const_reference + front() const + { + __glibcxx_requires_nonempty(); + return c.front(); + } + + /** + * Returns a read/write reference to the data at the last + * element of the %queue. + */ + reference + back() + { + __glibcxx_requires_nonempty(); + return c.back(); + } + + /** + * Returns a read-only (constant) reference to the data at the last + * element of the %queue. + */ + const_reference + back() const + { + __glibcxx_requires_nonempty(); + return c.back(); + } + + /** + * @brief Add data to the end of the %queue. + * @param __x Data to be added. + * + * This is a typical %queue operation. The function creates an + * element at the end of the %queue and assigns the given data + * to it. The time complexity of the operation depends on the + * underlying sequence. + */ + void + push(const value_type& __x) + { c.push_back(__x); } + +#if __cplusplus >= 201103L + void + push(value_type&& __x) + { c.push_back(std::move(__x)); } + +#if __cplusplus > 201402L + template + decltype(auto) + emplace(_Args&&... __args) + { return c.emplace_back(std::forward<_Args>(__args)...); } +#else + template + void + emplace(_Args&&... __args) + { c.emplace_back(std::forward<_Args>(__args)...); } +#endif +#endif + + /** + * @brief Removes first element. + * + * This is a typical %queue operation. It shrinks the %queue by one. + * The time complexity of the operation depends on the underlying + * sequence. + * + * Note that no data is returned, and if the first element's + * data is needed, it should be retrieved before pop() is + * called. + */ + void + pop() + { + __glibcxx_requires_nonempty(); + c.pop_front(); + } + +#if __cplusplus >= 201103L + void + swap(queue& __q) +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + noexcept(__is_nothrow_swappable<_Sequence>::value) +#else + noexcept(__is_nothrow_swappable<_Tp>::value) +#endif + { + using std::swap; + swap(c, __q.c); + } +#endif // __cplusplus >= 201103L + }; + +#if __cpp_deduction_guides >= 201606 + template> + queue(_Container) -> queue; + + template, + typename = _RequireAllocator<_Allocator>> + queue(_Container, _Allocator) + -> queue; +#endif + + /** + * @brief Queue equality comparison. + * @param __x A %queue. + * @param __y A %queue of the same type as @a __x. + * @return True iff the size and elements of the queues are equal. + * + * This is an equivalence relation. Complexity and semantics depend on the + * underlying sequence type, but the expected rules are: this relation is + * linear in the size of the sequences, and queues are considered equivalent + * if their sequences compare equal. + */ + template + inline bool + operator==(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return __x.c == __y.c; } + + /** + * @brief Queue ordering relation. + * @param __x A %queue. + * @param __y A %queue of the same type as @a x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is an total ordering relation. Complexity and semantics + * depend on the underlying sequence type, but the expected rules + * are: this relation is linear in the size of the sequences, the + * elements must be comparable with @c <, and + * std::lexicographical_compare() is usually used to make the + * determination. + */ + template + inline bool + operator<(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return __x.c < __y.c; } + + /// Based on operator== + template + inline bool + operator!=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return !(__x < __y); } + +#if __cpp_lib_three_way_comparison + template + inline compare_three_way_result_t<_Seq> + operator<=>(const queue<_Tp, _Seq>& __x, const queue<_Tp, _Seq>& __y) + { return __x.c <=> __y.c; } +#endif + +#if __cplusplus >= 201103L + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Seq>::value>::type +#else + void +#endif + swap(queue<_Tp, _Seq>& __x, queue<_Tp, _Seq>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + struct uses_allocator, _Alloc> + : public uses_allocator<_Seq, _Alloc>::type { }; +#endif // __cplusplus >= 201103L + + /** + * @brief A standard container automatically sorting its contents. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Sequence Type of underlying sequence, defaults to vector<_Tp>. + * @tparam _Compare Comparison function object type, defaults to + * less<_Sequence::value_type>. + * + * This is not a true container, but an @e adaptor. It holds + * another container, and provides a wrapper interface to that + * container. The wrapper is what enforces priority-based sorting + * and %queue behavior. Very few of the standard container/sequence + * interface requirements are met (e.g., iterators). + * + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::vector, but it can be + * any type that supports @c front(), @c push_back, @c pop_back, + * and random-access iterators, such as std::deque or an + * appropriate user-defined type. + * + * The third template parameter supplies the means of making + * priority comparisons. It defaults to @c less but + * can be anything defining a strict weak ordering. + * + * Members not found in @a normal containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c + * push, @c pop, and @c top, which are standard %queue operations. + * + * @note No equality/comparison operators are provided for + * %priority_queue. + * + * @note Sorting of the elements takes place as they are added to, + * and removed from, the %priority_queue using the + * %priority_queue's member functions. If you access the elements + * by other means, and change their data such that the sorting + * order would be different, the %priority_queue will not re-sort + * the elements for you. (How could it know to do so?) + */ + template, + typename _Compare = less > + class priority_queue + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Sequence::value_type _Sequence_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires(_Sequence, _SequenceConcept) + __glibcxx_class_requires(_Sequence, _RandomAccessContainerConcept) + __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) + __glibcxx_class_requires4(_Compare, bool, _Tp, _Tp, + _BinaryFunctionConcept) +#endif + +#if __cplusplus >= 201103L + template + using _Uses = typename + enable_if::value>::type; + +#if __cplusplus >= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2566. Requirements on the first template parameter of container + // adaptors + static_assert(is_same<_Tp, typename _Sequence::value_type>::value, + "value_type must be the same as the underlying container"); +#endif // C++17 +#endif // C++11 + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 2684. priority_queue lacking comparator typedef + typedef _Compare value_compare; + + protected: + // See queue::c for notes on these names. + _Sequence c; + _Compare comp; + + public: + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + explicit + priority_queue(const _Compare& __x = _Compare(), + const _Sequence& __s = _Sequence()) + : c(__s), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } +#else + template, + is_default_constructible<_Seq>>::value>::type> + priority_queue() + : c(), comp() { } + + explicit + priority_queue(const _Compare& __x, const _Sequence& __s) + : c(__s), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } + + explicit + priority_queue(const _Compare& __x, _Sequence&& __s = _Sequence()) + : c(std::move(__s)), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } + + template> + explicit + priority_queue(const _Alloc& __a) + : c(__a), comp() { } + + template> + priority_queue(const _Compare& __x, const _Alloc& __a) + : c(__a), comp(__x) { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2537. Constructors [...] taking allocators should call make_heap + template> + priority_queue(const _Compare& __x, const _Sequence& __c, + const _Alloc& __a) + : c(__c, __a), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } + + template> + priority_queue(const _Compare& __x, _Sequence&& __c, const _Alloc& __a) + : c(std::move(__c), __a), comp(__x) + { std::make_heap(c.begin(), c.end(), comp); } + + template> + priority_queue(const priority_queue& __q, const _Alloc& __a) + : c(__q.c, __a), comp(__q.comp) { } + + template> + priority_queue(priority_queue&& __q, const _Alloc& __a) + : c(std::move(__q.c), __a), comp(std::move(__q.comp)) { } +#endif + + /** + * @brief Builds a %queue from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __x A comparison functor describing a strict weak ordering. + * @param __s An initial sequence with which to start. + * + * Begins by copying @a __s, inserting a copy of the elements + * from @a [first,last) into the copy of @a __s, then ordering + * the copy according to @a __x. + * + * For more information on function objects, see the + * documentation on @link functors functor base + * classes@endlink. + */ +#if __cplusplus < 201103L + template + priority_queue(_InputIterator __first, _InputIterator __last, + const _Compare& __x = _Compare(), + const _Sequence& __s = _Sequence()) + : c(__s), comp(__x) + { + __glibcxx_requires_valid_range(__first, __last); + c.insert(c.end(), __first, __last); + std::make_heap(c.begin(), c.end(), comp); + } +#else + template + priority_queue(_InputIterator __first, _InputIterator __last, + const _Compare& __x, + const _Sequence& __s) + : c(__s), comp(__x) + { + __glibcxx_requires_valid_range(__first, __last); + c.insert(c.end(), __first, __last); + std::make_heap(c.begin(), c.end(), comp); + } + + template + priority_queue(_InputIterator __first, _InputIterator __last, + const _Compare& __x = _Compare(), + _Sequence&& __s = _Sequence()) + : c(std::move(__s)), comp(__x) + { + __glibcxx_requires_valid_range(__first, __last); + c.insert(c.end(), __first, __last); + std::make_heap(c.begin(), c.end(), comp); + } +#endif + + /** + * Returns true if the %queue is empty. + */ + _GLIBCXX_NODISCARD bool + empty() const + { return c.empty(); } + + /** Returns the number of elements in the %queue. */ + size_type + size() const + { return c.size(); } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %queue. + */ + const_reference + top() const + { + __glibcxx_requires_nonempty(); + return c.front(); + } + + /** + * @brief Add data to the %queue. + * @param __x Data to be added. + * + * This is a typical %queue operation. + * The time complexity of the operation depends on the underlying + * sequence. + */ + void + push(const value_type& __x) + { + c.push_back(__x); + std::push_heap(c.begin(), c.end(), comp); + } + +#if __cplusplus >= 201103L + void + push(value_type&& __x) + { + c.push_back(std::move(__x)); + std::push_heap(c.begin(), c.end(), comp); + } + + template + void + emplace(_Args&&... __args) + { + c.emplace_back(std::forward<_Args>(__args)...); + std::push_heap(c.begin(), c.end(), comp); + } +#endif + + /** + * @brief Removes first element. + * + * This is a typical %queue operation. It shrinks the %queue + * by one. The time complexity of the operation depends on the + * underlying sequence. + * + * Note that no data is returned, and if the first element's + * data is needed, it should be retrieved before pop() is + * called. + */ + void + pop() + { + __glibcxx_requires_nonempty(); + std::pop_heap(c.begin(), c.end(), comp); + c.pop_back(); + } + +#if __cplusplus >= 201103L + void + swap(priority_queue& __pq) + noexcept(__and_< +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + __is_nothrow_swappable<_Sequence>, +#else + __is_nothrow_swappable<_Tp>, +#endif + __is_nothrow_swappable<_Compare> + >::value) + { + using std::swap; + swap(c, __pq.c); + swap(comp, __pq.comp); + } +#endif // __cplusplus >= 201103L + }; + +#if __cpp_deduction_guides >= 201606 + template, + typename = _RequireNotAllocator<_Container>> + priority_queue(_Compare, _Container) + -> priority_queue; + + template::value_type, + typename _Compare = less<_ValT>, + typename _Container = vector<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireNotAllocator<_Container>> + priority_queue(_InputIterator, _InputIterator, _Compare = _Compare(), + _Container = _Container()) + -> priority_queue<_ValT, _Container, _Compare>; + + template, + typename = _RequireNotAllocator<_Container>, + typename = _RequireAllocator<_Allocator>> + priority_queue(_Compare, _Container, _Allocator) + -> priority_queue; +#endif + + // No equality/comparison operators are provided for priority_queue. + +#if __cplusplus >= 201103L + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_Sequence>, + __is_swappable<_Compare>>::value>::type +#else + void +#endif + swap(priority_queue<_Tp, _Sequence, _Compare>& __x, + priority_queue<_Tp, _Sequence, _Compare>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + struct uses_allocator, _Alloc> + : public uses_allocator<_Sequence, _Alloc>::type { }; +#endif // __cplusplus >= 201103L + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_QUEUE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h b/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h new file mode 100644 index 000000000..df7a5f9df --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_raw_storage_iter.h @@ -0,0 +1,123 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_raw_storage_iter.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_RAW_STORAGE_ITERATOR_H +#define _STL_RAW_STORAGE_ITERATOR_H 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * This iterator class lets algorithms store their results into + * uninitialized memory. + */ + template + class raw_storage_iterator + : public iterator + { + protected: + _OutputIterator _M_iter; + + public: + explicit + raw_storage_iterator(_OutputIterator __x) + : _M_iter(__x) {} + + raw_storage_iterator& + operator*() { return *this; } + + raw_storage_iterator& + operator=(const _Tp& __element) + { + std::_Construct(std::__addressof(*_M_iter), __element); + return *this; + } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2127. Move-construction with raw_storage_iterator + raw_storage_iterator& + operator=(_Tp&& __element) + { + std::_Construct(std::__addressof(*_M_iter), std::move(__element)); + return *this; + } +#endif + + raw_storage_iterator& + operator++() + { + ++_M_iter; + return *this; + } + + raw_storage_iterator + operator++(int) + { + raw_storage_iterator __tmp = *this; + ++_M_iter; + return __tmp; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2454. Add raw_storage_iterator::base() member + _OutputIterator base() const { return _M_iter; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_relops.h b/resources/sources/avr-libstdcpp/include/bits/stl_relops.h new file mode 100644 index 000000000..3b0afea8a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_relops.h @@ -0,0 +1,133 @@ +// std::rel_ops implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the, 2009 Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * Copyright (c) 1996,1997 + * Silicon Graphics + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file bits/stl_relops.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{utility} + * + * Inclusion of this file has been removed from + * all of the other STL headers for safety reasons, except std_utility.h. + * For more information, see the thread of about twenty messages starting + * with http://gcc.gnu.org/ml/libstdc++/2001-01/msg00223.html, or + * http://gcc.gnu.org/onlinedocs/libstdc++/faq.html#faq.ambiguous_overloads + * + * Short summary: the rel_ops operators should be avoided for the present. + */ + +#ifndef _STL_RELOPS_H +#define _STL_RELOPS_H 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + namespace rel_ops + { + /** @namespace std::rel_ops + * @brief The generated relational operators are sequestered here. + */ + + /** + * @brief Defines @c != for arbitrary types, in terms of @c ==. + * @param __x A thing. + * @param __y Another thing. + * @return __x != __y + * + * This function uses @c == to determine its result. + */ + template + inline bool + operator!=(const _Tp& __x, const _Tp& __y) + { return !(__x == __y); } + + /** + * @brief Defines @c > for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x > __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator>(const _Tp& __x, const _Tp& __y) + { return __y < __x; } + + /** + * @brief Defines @c <= for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x <= __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator<=(const _Tp& __x, const _Tp& __y) + { return !(__y < __x); } + + /** + * @brief Defines @c >= for arbitrary types, in terms of @c <. + * @param __x A thing. + * @param __y Another thing. + * @return __x >= __y + * + * This function uses @c < to determine its result. + */ + template + inline bool + operator>=(const _Tp& __x, const _Tp& __y) + { return !(__x < __y); } + } // namespace rel_ops + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_RELOPS_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_set.h b/resources/sources/avr-libstdcpp/include/bits/stl_set.h new file mode 100644 index 000000000..da4266508 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_set.h @@ -0,0 +1,1086 @@ +// Set implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_set.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{set} + */ + +#ifndef _STL_SET_H +#define _STL_SET_H 1 + +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + class multiset; + + /** + * @brief A standard container made up of unique keys, which can be + * retrieved in logarithmic time. + * + * @ingroup associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Compare Comparison function object type, defaults to less<_Key>. + * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * + * Meets the requirements of a container, a + * reversible container, and an + * associative container (using unique keys). + * + * Sets support bidirectional iterators. + * + * The private tree data is declared exactly the same way for set and + * multiset; the distinction is made entirely in how the tree functions are + * called (*_unique versus *_equal, same as the standard). + */ + template, + typename _Alloc = std::allocator<_Key> > + class set + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Key, _SGIAssignableConcept) +# endif + __glibcxx_class_requires4(_Compare, bool, _Key, _Key, + _BinaryFunctionConcept) + __glibcxx_class_requires2(_Key, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Key>::value, + "std::set must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::set must have the same value_type as its allocator"); +# endif +#endif + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef _Key key_type; + typedef _Key value_type; + typedef _Compare key_compare; + typedef _Compare value_compare; + typedef _Alloc allocator_type; + //@} + + private: + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Key>::other _Key_alloc_type; + + typedef _Rb_tree, + key_compare, _Key_alloc_type> _Rep_type; + _Rep_type _M_t; // Red-black tree representing set. + + typedef __gnu_cxx::__alloc_traits<_Key_alloc_type> _Alloc_traits; + + public: + //@{ + /// Iterator-related typedefs. + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 103. set::iterator is required to be modifiable, + // but this allows modification of keys. + typedef typename _Rep_type::const_iterator iterator; + typedef typename _Rep_type::const_iterator const_iterator; + typedef typename _Rep_type::const_reverse_iterator reverse_iterator; + typedef typename _Rep_type::const_reverse_iterator const_reverse_iterator; + typedef typename _Rep_type::size_type size_type; + typedef typename _Rep_type::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Rep_type::node_type; + using insert_return_type = typename _Rep_type::insert_return_type; +#endif + + // allocation/deallocation + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + set() : _M_t() { } +#else + set() = default; +#endif + + /** + * @brief Creates a %set with no elements. + * @param __comp Comparator to use. + * @param __a An allocator object. + */ + explicit + set(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) { } + + /** + * @brief Builds a %set from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * + * Create a %set consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is + * already sorted, and NlogN otherwise (where N is + * distance(__first,__last)). + */ + template + set(_InputIterator __first, _InputIterator __last) + : _M_t() + { _M_t._M_insert_range_unique(__first, __last); } + + /** + * @brief Builds a %set from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %set consisting of copies of the elements from + * [__first,__last). This is linear in N if the range is + * already sorted, and NlogN otherwise (where N is + * distance(__first,__last)). + */ + template + set(_InputIterator __first, _InputIterator __last, + const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) + { _M_t._M_insert_range_unique(__first, __last); } + + /** + * @brief %Set copy constructor. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + set(const set& __x) + : _M_t(__x._M_t) { } +#else + set(const set&) = default; + + /** + * @brief %Set move constructor + * + * The newly-created %set contains the exact contents of the moved + * instance. The moved instance is a valid, but unspecified, %set. + */ + set(set&&) = default; + + /** + * @brief Builds a %set from an initializer_list. + * @param __l An initializer_list. + * @param __comp A comparison functor. + * @param __a An allocator object. + * + * Create a %set consisting of copies of the elements in the list. + * This is linear in N if the list is already sorted, and NlogN + * otherwise (where N is @a __l.size()). + */ + set(initializer_list __l, + const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _M_t(__comp, _Key_alloc_type(__a)) + { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } + + /// Allocator-extended default constructor. + explicit + set(const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) { } + + /// Allocator-extended copy constructor. + set(const set& __x, const allocator_type& __a) + : _M_t(__x._M_t, _Key_alloc_type(__a)) { } + + /// Allocator-extended move constructor. + set(set&& __x, const allocator_type& __a) + noexcept(is_nothrow_copy_constructible<_Compare>::value + && _Alloc_traits::_S_always_equal()) + : _M_t(std::move(__x._M_t), _Key_alloc_type(__a)) { } + + /// Allocator-extended initialier-list constructor. + set(initializer_list __l, const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) + { _M_t._M_insert_range_unique(__l.begin(), __l.end()); } + + /// Allocator-extended range constructor. + template + set(_InputIterator __first, _InputIterator __last, + const allocator_type& __a) + : _M_t(_Key_alloc_type(__a)) + { _M_t._M_insert_range_unique(__first, __last); } + + /** + * The dtor only erases the elements, and note that if the elements + * themselves are pointers, the pointed-to memory is not touched in any + * way. Managing the pointer is the user's responsibility. + */ + ~set() = default; +#endif + + /** + * @brief %Set assignment operator. + * + * Whether the allocator is copied depends on the allocator traits. + */ +#if __cplusplus < 201103L + set& + operator=(const set& __x) + { + _M_t = __x._M_t; + return *this; + } +#else + set& + operator=(const set&) = default; + + /// Move assignment operator. + set& + operator=(set&&) = default; + + /** + * @brief %Set list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %set with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %set and + * that the resulting %set's size is the same as the number + * of elements assigned. + */ + set& + operator=(initializer_list __l) + { + _M_t._M_assign_unique(__l.begin(), __l.end()); + return *this; + } +#endif + + // accessors: + + /// Returns the comparison object with which the %set was constructed. + key_compare + key_comp() const + { return _M_t.key_comp(); } + /// Returns the comparison object with which the %set was constructed. + value_compare + value_comp() const + { return _M_t.key_comp(); } + /// Returns the allocator object with which the %set was constructed. + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_t.get_allocator()); } + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %set. Iteration is done in ascending order according + * to the keys. + */ + iterator + begin() const _GLIBCXX_NOEXCEPT + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %set. Iteration is done in ascending order according + * to the keys. + */ + iterator + end() const _GLIBCXX_NOEXCEPT + { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points to the last + * element in the %set. Iteration is done in descending order according + * to the keys. + */ + reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %set. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return _M_t.rend(); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %set. Iteration is done in ascending order according + * to the keys. + */ + iterator + cbegin() const noexcept + { return _M_t.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %set. Iteration is done in ascending order according + * to the keys. + */ + iterator + cend() const noexcept + { return _M_t.end(); } + + /** + * Returns a read-only (constant) iterator that points to the last + * element in the %set. Iteration is done in descending order according + * to the keys. + */ + reverse_iterator + crbegin() const noexcept + { return _M_t.rbegin(); } + + /** + * Returns a read-only (constant) reverse iterator that points to the + * last pair in the %set. Iteration is done in descending order + * according to the keys. + */ + reverse_iterator + crend() const noexcept + { return _M_t.rend(); } +#endif + + /// Returns true if the %set is empty. + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_t.empty(); } + + /// Returns the size of the %set. + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_t.size(); } + + /// Returns the maximum size of the %set. + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _M_t.max_size(); } + + /** + * @brief Swaps data with another %set. + * @param __x A %set of the same element and allocator types. + * + * This exchanges the elements between two sets in constant + * time. (It is only swapping a pointer, an integer, and an + * instance of the @c Compare type (which itself is often + * stateless and empty), so it should be quite fast.) Note + * that the global std::swap() function is specialized such + * that std::swap(s1,s2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(set& __x) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { _M_t.swap(__x._M_t); } + + // insert/erase +#if __cplusplus >= 201103L + /** + * @brief Attempts to build and insert an element into the %set. + * @param __args Arguments used to generate an element. + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted element, and the second is a bool + * that is true if the element was actually inserted. + * + * This function attempts to build and insert an element into the %set. + * A %set relies on unique keys and thus an element is only inserted if + * it is not already present in the %set. + * + * Insertion requires logarithmic time. + */ + template + std::pair + emplace(_Args&&... __args) + { return _M_t._M_emplace_unique(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to insert an element into the %set. + * @param __pos An iterator that serves as a hint as to where the + * element should be inserted. + * @param __args Arguments used to generate the element to be + * inserted. + * @return An iterator that points to the element with key equivalent to + * the one generated from @a __args (may or may not be the + * element itself). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { + return _M_t._M_emplace_hint_unique(__pos, + std::forward<_Args>(__args)...); + } +#endif + + /** + * @brief Attempts to insert an element into the %set. + * @param __x Element to be inserted. + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted element, and the second is a bool + * that is true if the element was actually inserted. + * + * This function attempts to insert an element into the %set. A %set + * relies on unique keys and thus an element is only inserted if it is + * not already present in the %set. + * + * Insertion requires logarithmic time. + */ + std::pair + insert(const value_type& __x) + { + std::pair __p = + _M_t._M_insert_unique(__x); + return std::pair(__p.first, __p.second); + } + +#if __cplusplus >= 201103L + std::pair + insert(value_type&& __x) + { + std::pair __p = + _M_t._M_insert_unique(std::move(__x)); + return std::pair(__p.first, __p.second); + } +#endif + + /** + * @brief Attempts to insert an element into the %set. + * @param __position An iterator that serves as a hint as to where the + * element should be inserted. + * @param __x Element to be inserted. + * @return An iterator that points to the element with key of + * @a __x (may or may not be the element passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument insert() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires logarithmic time (if the hint is not taken). + */ + iterator + insert(const_iterator __position, const value_type& __x) + { return _M_t._M_insert_unique_(__position, __x); } + +#if __cplusplus >= 201103L + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_t._M_insert_unique_(__position, std::move(__x)); } +#endif + + /** + * @brief A template function that attempts to insert a range + * of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_t._M_insert_range_unique(__first, __last); } + +#if __cplusplus >= 201103L + /** + * @brief Attempts to insert a list of elements into the %set. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { this->insert(__l.begin(), __l.end()); } +#endif + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_t.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __x) + { return _M_t.extract(__x); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_t._M_reinsert_node_unique(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_t._M_reinsert_node_hint_unique(__hint, std::move(__nh)); } + + template + friend class std::_Rb_tree_merge_helper; + + template + void + merge(set<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(set<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(multiset<_Key, _Compare1, _Alloc>& __source) + { + using _Merge_helper = _Rb_tree_merge_helper; + _M_t._M_merge_unique(_Merge_helper::_S_get_tree(__source)); + } + + template + void + merge(multiset<_Key, _Compare1, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases an element from a %set. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from a %set. Note that this function only erases the element, and + * that if the element is itself a pointer, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __position) + { return _M_t.erase(__position); } +#else + /** + * @brief Erases an element from a %set. + * @param position An iterator pointing to the element to be erased. + * + * This function erases an element, pointed to by the given iterator, + * from a %set. Note that this function only erases the element, and + * that if the element is itself a pointer, the pointed-to memory is not + * touched in any way. Managing the pointer is the user's + * responsibility. + */ + void + erase(iterator __position) + { _M_t.erase(__position); } +#endif + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * a %set. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_t.erase(__x); } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + /** + * @brief Erases a [__first,__last) range of elements from a %set. + * @param __first Iterator pointing to the start of the range to be + * erased. + + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from a %set. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_t.erase(__first, __last); } +#else + /** + * @brief Erases a [first,last) range of elements from a %set. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * + * This function erases a sequence of elements from a %set. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + erase(iterator __first, iterator __last) + { _M_t.erase(__first, __last); } +#endif + + /** + * Erases all elements in a %set. Note that this function only erases + * the elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_t.clear(); } + + // set operations: + + //@{ + /** + * @brief Finds the number of elements. + * @param __x Element to located. + * @return Number of elements with specified key. + * + * This function only makes sense for multisets; for set the result will + * either be 0 (not present) or 1 (present). + */ + size_type + count(const key_type& __x) const + { return _M_t.find(__x) == _M_t.end() ? 0 : 1; } + +#if __cplusplus > 201103L + template + auto + count(const _Kt& __x) const + -> decltype(_M_t._M_count_tr(__x)) + { return _M_t._M_count_tr(__x); } +#endif + //@} + +#if __cplusplus > 201703L + //@{ + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is an element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_t.find(__x) != _M_t.end(); } + + template + auto + contains(const _Kt& __x) const + -> decltype(_M_t._M_find_tr(__x), void(), true) + { return _M_t._M_find_tr(__x) != _M_t.end(); } + //@} +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 214. set::find() missing const overload + //@{ + /** + * @brief Tries to locate an element in a %set. + * @param __x Element to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_t.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_t.find(__x); } + +#if __cplusplus > 201103L + template + auto + find(const _Kt& __x) + -> decltype(iterator{_M_t._M_find_tr(__x)}) + { return iterator{_M_t._M_find_tr(__x)}; } + + template + auto + find(const _Kt& __x) const + -> decltype(const_iterator{_M_t._M_find_tr(__x)}) + { return const_iterator{_M_t._M_find_tr(__x)}; } +#endif + //@} + + //@{ + /** + * @brief Finds the beginning of a subsequence matching given key. + * @param __x Key to be located. + * @return Iterator pointing to first element equal to or greater + * than key, or end(). + * + * This function returns the first element of a subsequence of elements + * that matches the given key. If unsuccessful it returns an iterator + * pointing to the first element that has a greater value than given key + * or end() if no such element exists. + */ + iterator + lower_bound(const key_type& __x) + { return _M_t.lower_bound(__x); } + + const_iterator + lower_bound(const key_type& __x) const + { return _M_t.lower_bound(__x); } + +#if __cplusplus > 201103L + template + auto + lower_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_lower_bound_tr(__x))) + { return iterator(_M_t._M_lower_bound_tr(__x)); } + + template + auto + lower_bound(const _Kt& __x) const + -> decltype(const_iterator(_M_t._M_lower_bound_tr(__x))) + { return const_iterator(_M_t._M_lower_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds the end of a subsequence matching given key. + * @param __x Key to be located. + * @return Iterator pointing to the first element + * greater than key, or end(). + */ + iterator + upper_bound(const key_type& __x) + { return _M_t.upper_bound(__x); } + + const_iterator + upper_bound(const key_type& __x) const + { return _M_t.upper_bound(__x); } + +#if __cplusplus > 201103L + template + auto + upper_bound(const _Kt& __x) + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return iterator(_M_t._M_upper_bound_tr(__x)); } + + template + auto + upper_bound(const _Kt& __x) const + -> decltype(iterator(_M_t._M_upper_bound_tr(__x))) + { return const_iterator(_M_t._M_upper_bound_tr(__x)); } +#endif + //@} + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function is equivalent to + * @code + * std::make_pair(c.lower_bound(val), + * c.upper_bound(val)) + * @endcode + * (but is faster than making the calls separately). + * + * This function probably only makes sense for multisets. + */ + std::pair + equal_range(const key_type& __x) + { return _M_t.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_t.equal_range(__x); } + +#if __cplusplus > 201103L + template + auto + equal_range(const _Kt& __x) + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } + + template + auto + equal_range(const _Kt& __x) const + -> decltype(pair(_M_t._M_equal_range_tr(__x))) + { return pair(_M_t._M_equal_range_tr(__x)); } +#endif + //@} + + template + friend bool + operator==(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); + +#if __cpp_lib_three_way_comparison + template + friend __detail::__synth3way_t<_K1> + operator<=>(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); +#else + template + friend bool + operator<(const set<_K1, _C1, _A1>&, const set<_K1, _C1, _A1>&); +#endif + }; + +#if __cpp_deduction_guides >= 201606 + + template::value_type>, + typename _Allocator = + allocator::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + set(_InputIterator, _InputIterator, + _Compare = _Compare(), _Allocator = _Allocator()) + -> set::value_type, + _Compare, _Allocator>; + + template, + typename _Allocator = allocator<_Key>, + typename = _RequireNotAllocator<_Compare>, + typename = _RequireAllocator<_Allocator>> + set(initializer_list<_Key>, + _Compare = _Compare(), _Allocator = _Allocator()) + -> set<_Key, _Compare, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + set(_InputIterator, _InputIterator, _Allocator) + -> set::value_type, + less::value_type>, + _Allocator>; + + template> + set(initializer_list<_Key>, _Allocator) + -> set<_Key, less<_Key>, _Allocator>; + +#endif // deduction guides + + /** + * @brief Set equality comparison. + * @param __x A %set. + * @param __y A %set of the same type as @a x. + * @return True iff the size and elements of the sets are equal. + * + * This is an equivalence relation. It is linear in the size of the sets. + * Sets are considered equivalent if their sizes are equal, and if + * corresponding elements compare equal. + */ + template + inline bool + operator==(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __x._M_t == __y._M_t; } + +#if __cpp_lib_three_way_comparison + /** + * @brief Set ordering relation. + * @param __x A `set`. + * @param __y A `set` of the same type as `x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * This is a total ordering relation. It is linear in the size of the + * maps. The elements must be comparable with @c <. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Key> + operator<=>(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __x._M_t <=> __y._M_t; } +#else + /** + * @brief Set ordering relation. + * @param __x A %set. + * @param __y A %set of the same type as @a x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * sets. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __x._M_t < __y._M_t; } + + /// Returns !(x == y). + template + inline bool + operator!=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return !(__x == __y); } + + /// Returns y < x. + template + inline bool + operator>(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return __y < __x; } + + /// Returns !(y < x) + template + inline bool + operator<=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return !(__y < __x); } + + /// Returns !(x < y) + template + inline bool + operator>=(const set<_Key, _Compare, _Alloc>& __x, + const set<_Key, _Compare, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::set::swap(). + template + inline void + swap(set<_Key, _Compare, _Alloc>& __x, set<_Key, _Compare, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::set access to internals of compatible sets. + template + struct + _Rb_tree_merge_helper<_GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>, _Cmp2> + { + private: + friend class _GLIBCXX_STD_C::set<_Val, _Cmp1, _Alloc>; + + static auto& + _S_get_tree(_GLIBCXX_STD_C::set<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + + static auto& + _S_get_tree(_GLIBCXX_STD_C::multiset<_Val, _Cmp2, _Alloc>& __set) + { return __set._M_t; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} //namespace std +#endif /* _STL_SET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_stack.h b/resources/sources/avr-libstdcpp/include/bits/stl_stack.h new file mode 100644 index 000000000..1ce98a94a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_stack.h @@ -0,0 +1,392 @@ +// Stack implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_stack.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{stack} + */ + +#ifndef _STL_STACK_H +#define _STL_STACK_H 1 + +#include +#include +#if __cplusplus >= 201103L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief A standard container giving FILO behavior. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Sequence Type of underlying sequence, defaults to deque<_Tp>. + * + * Meets many of the requirements of a + * container, + * but does not define anything to do with iterators. Very few of the + * other standard container interfaces are defined. + * + * This is not a true container, but an @e adaptor. It holds + * another container, and provides a wrapper interface to that + * container. The wrapper is what enforces strict + * first-in-last-out %stack behavior. + * + * The second template parameter defines the type of the underlying + * sequence/container. It defaults to std::deque, but it can be + * any type that supports @c back, @c push_back, and @c pop_back, + * such as std::list, std::vector, or an appropriate user-defined + * type. + * + * Members not found in @a normal containers are @c container_type, + * which is a typedef for the second Sequence parameter, and @c + * push, @c pop, and @c top, which are standard %stack/FILO + * operations. + */ + template > + class stack + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // concept requirements + typedef typename _Sequence::value_type _Sequence_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) + __glibcxx_class_requires(_Sequence, _BackInsertionSequenceConcept) +# endif + __glibcxx_class_requires2(_Tp, _Sequence_value_type, _SameTypeConcept) +#endif + + template + friend bool + operator==(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); + + template + friend bool + operator<(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); + +#if __cpp_lib_three_way_comparison + template + friend compare_three_way_result_t<_Seq1> + operator<=>(const stack<_Tp1, _Seq1>&, const stack<_Tp1, _Seq1>&); +#endif + +#if __cplusplus >= 201103L + template + using _Uses = typename + enable_if::value>::type; + +#if __cplusplus >= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2566. Requirements on the first template parameter of container + // adaptors + static_assert(is_same<_Tp, typename _Sequence::value_type>::value, + "value_type must be the same as the underlying container"); +#endif // C++17 +#endif // C++11 + + public: + typedef typename _Sequence::value_type value_type; + typedef typename _Sequence::reference reference; + typedef typename _Sequence::const_reference const_reference; + typedef typename _Sequence::size_type size_type; + typedef _Sequence container_type; + + protected: + // See queue::c for notes on this name. + _Sequence c; + + public: + // XXX removed old def ctor, added def arg to this one to match 14882 + /** + * @brief Default constructor creates no elements. + */ +#if __cplusplus < 201103L + explicit + stack(const _Sequence& __c = _Sequence()) + : c(__c) { } +#else + template::value>::type> + stack() + : c() { } + + explicit + stack(const _Sequence& __c) + : c(__c) { } + + explicit + stack(_Sequence&& __c) + : c(std::move(__c)) { } + + template> + explicit + stack(const _Alloc& __a) + : c(__a) { } + + template> + stack(const _Sequence& __c, const _Alloc& __a) + : c(__c, __a) { } + + template> + stack(_Sequence&& __c, const _Alloc& __a) + : c(std::move(__c), __a) { } + + template> + stack(const stack& __q, const _Alloc& __a) + : c(__q.c, __a) { } + + template> + stack(stack&& __q, const _Alloc& __a) + : c(std::move(__q.c), __a) { } +#endif + + /** + * Returns true if the %stack is empty. + */ + _GLIBCXX_NODISCARD bool + empty() const + { return c.empty(); } + + /** Returns the number of elements in the %stack. */ + size_type + size() const + { return c.size(); } + + /** + * Returns a read/write reference to the data at the first + * element of the %stack. + */ + reference + top() + { + __glibcxx_requires_nonempty(); + return c.back(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %stack. + */ + const_reference + top() const + { + __glibcxx_requires_nonempty(); + return c.back(); + } + + /** + * @brief Add data to the top of the %stack. + * @param __x Data to be added. + * + * This is a typical %stack operation. The function creates an + * element at the top of the %stack and assigns the given data + * to it. The time complexity of the operation depends on the + * underlying sequence. + */ + void + push(const value_type& __x) + { c.push_back(__x); } + +#if __cplusplus >= 201103L + void + push(value_type&& __x) + { c.push_back(std::move(__x)); } + +#if __cplusplus > 201402L + template + decltype(auto) + emplace(_Args&&... __args) + { return c.emplace_back(std::forward<_Args>(__args)...); } +#else + template + void + emplace(_Args&&... __args) + { c.emplace_back(std::forward<_Args>(__args)...); } +#endif +#endif + + /** + * @brief Removes first element. + * + * This is a typical %stack operation. It shrinks the %stack + * by one. The time complexity of the operation depends on the + * underlying sequence. + * + * Note that no data is returned, and if the first element's + * data is needed, it should be retrieved before pop() is + * called. + */ + void + pop() + { + __glibcxx_requires_nonempty(); + c.pop_back(); + } + +#if __cplusplus >= 201103L + void + swap(stack& __s) +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + noexcept(__is_nothrow_swappable<_Sequence>::value) +#else + noexcept(__is_nothrow_swappable<_Tp>::value) +#endif + { + using std::swap; + swap(c, __s.c); + } +#endif // __cplusplus >= 201103L + }; + +#if __cpp_deduction_guides >= 201606 + template> + stack(_Container) -> stack; + + template, + typename = _RequireAllocator<_Allocator>> + stack(_Container, _Allocator) + -> stack; +#endif + + /** + * @brief Stack equality comparison. + * @param __x A %stack. + * @param __y A %stack of the same type as @a __x. + * @return True iff the size and elements of the stacks are equal. + * + * This is an equivalence relation. Complexity and semantics + * depend on the underlying sequence type, but the expected rules + * are: this relation is linear in the size of the sequences, and + * stacks are considered equivalent if their sequences compare + * equal. + */ + template + inline bool + operator==(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return __x.c == __y.c; } + + /** + * @brief Stack ordering relation. + * @param __x A %stack. + * @param __y A %stack of the same type as @a x. + * @return True iff @a x is lexicographically less than @a __y. + * + * This is an total ordering relation. Complexity and semantics + * depend on the underlying sequence type, but the expected rules + * are: this relation is linear in the size of the sequences, the + * elements must be comparable with @c <, and + * std::lexicographical_compare() is usually used to make the + * determination. + */ + template + inline bool + operator<(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return __x.c < __y.c; } + + /// Based on operator== + template + inline bool + operator!=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return !(__x < __y); } + +#if __cpp_lib_three_way_comparison + template + inline compare_three_way_result_t<_Seq> + operator<=>(const stack<_Tp, _Seq>& __x, const stack<_Tp, _Seq>& __y) + { return __x.c <=> __y.c; } +#endif + +#if __cplusplus >= 201103L + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Seq>::value>::type +#else + void +#endif + swap(stack<_Tp, _Seq>& __x, stack<_Tp, _Seq>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + struct uses_allocator, _Alloc> + : public uses_allocator<_Seq, _Alloc>::type { }; +#endif // __cplusplus >= 201103L + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_STACK_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h b/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h new file mode 100644 index 000000000..f6f179604 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_tempbuf.h @@ -0,0 +1,284 @@ +// Temporary buffer implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_tempbuf.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_TEMPBUF_H +#define _STL_TEMPBUF_H 1 + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + namespace __detail + { + template + inline void + __return_temporary_buffer(_Tp* __p, + size_t __len __attribute__((__unused__))) + { +#if __cpp_sized_deallocation + ::operator delete(__p, __len * sizeof(_Tp)); +#else + ::operator delete(__p); +#endif + } + } + + /** + * @brief Allocates a temporary buffer. + * @param __len The number of objects of type Tp. + * @return See full description. + * + * Reinventing the wheel, but this time with prettier spokes! + * + * This function tries to obtain storage for @c __len adjacent Tp + * objects. The objects themselves are not constructed, of course. + * A pair<> is returned containing the buffer s address and + * capacity (in the units of sizeof(_Tp)), or a pair of 0 values if + * no storage can be obtained. Note that the capacity obtained + * may be less than that requested if the memory is unavailable; + * you should compare len with the .second return value. + * + * Provides the nothrow exception guarantee. + */ + template + pair<_Tp*, ptrdiff_t> + get_temporary_buffer(ptrdiff_t __len) _GLIBCXX_NOEXCEPT + { + const ptrdiff_t __max = + __gnu_cxx::__numeric_traits::__max / sizeof(_Tp); + if (__len > __max) + __len = __max; + + while (__len > 0) + { + _Tp* __tmp = static_cast<_Tp*>(::operator new(__len * sizeof(_Tp), + std::nothrow)); + if (__tmp != 0) + return std::pair<_Tp*, ptrdiff_t>(__tmp, __len); + __len /= 2; + } + return std::pair<_Tp*, ptrdiff_t>(static_cast<_Tp*>(0), 0); + } + + /** + * @brief The companion to get_temporary_buffer(). + * @param __p A buffer previously allocated by get_temporary_buffer. + * @return None. + * + * Frees the memory pointed to by __p. + */ + template + inline void + return_temporary_buffer(_Tp* __p) + { ::operator delete(__p); } + + /** + * This class is used in two places: stl_algo.h and ext/memory, + * where it is wrapped as the temporary_buffer class. See + * temporary_buffer docs for more notes. + */ + template + class _Temporary_buffer + { + // concept requirements + __glibcxx_class_requires(_ForwardIterator, _ForwardIteratorConcept) + + public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef pointer iterator; + typedef ptrdiff_t size_type; + + protected: + size_type _M_original_len; + size_type _M_len; + pointer _M_buffer; + + public: + /// As per Table mumble. + size_type + size() const + { return _M_len; } + + /// Returns the size requested by the constructor; may be >size(). + size_type + requested_size() const + { return _M_original_len; } + + /// As per Table mumble. + iterator + begin() + { return _M_buffer; } + + /// As per Table mumble. + iterator + end() + { return _M_buffer + _M_len; } + + /** + * Constructs a temporary buffer of a size somewhere between + * zero and the given length. + */ + _Temporary_buffer(_ForwardIterator __seed, size_type __original_len); + + ~_Temporary_buffer() + { + std::_Destroy(_M_buffer, _M_buffer + _M_len); + std::__detail::__return_temporary_buffer(_M_buffer, _M_len); + } + + private: + // Disable copy constructor and assignment operator. + _Temporary_buffer(const _Temporary_buffer&); + + void + operator=(const _Temporary_buffer&); + }; + + + template + struct __uninitialized_construct_buf_dispatch + { + template + static void + __ucr(_Pointer __first, _Pointer __last, + _ForwardIterator __seed) + { + if (__first == __last) + return; + + _Pointer __cur = __first; + __try + { + std::_Construct(std::__addressof(*__first), + _GLIBCXX_MOVE(*__seed)); + _Pointer __prev = __cur; + ++__cur; + for(; __cur != __last; ++__cur, ++__prev) + std::_Construct(std::__addressof(*__cur), + _GLIBCXX_MOVE(*__prev)); + *__seed = _GLIBCXX_MOVE(*__prev); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_construct_buf_dispatch + { + template + static void + __ucr(_Pointer, _Pointer, _ForwardIterator) { } + }; + + // Constructs objects in the range [first, last). + // Note that while these new objects will take valid values, + // their exact value is not defined. In particular they may + // be 'moved from'. + // + // While *__seed may be altered during this algorithm, it will have + // the same value when the algorithm finishes, unless one of the + // constructions throws. + // + // Requirements: _Pointer::value_type(_Tp&&) is valid. + template + inline void + __uninitialized_construct_buf(_Pointer __first, _Pointer __last, + _ForwardIterator __seed) + { + typedef typename std::iterator_traits<_Pointer>::value_type + _ValueType; + + std::__uninitialized_construct_buf_dispatch< + __has_trivial_constructor(_ValueType)>:: + __ucr(__first, __last, __seed); + } + + template + _Temporary_buffer<_ForwardIterator, _Tp>:: + _Temporary_buffer(_ForwardIterator __seed, size_type __original_len) + : _M_original_len(__original_len), _M_len(0), _M_buffer(0) + { + std::pair __p( + std::get_temporary_buffer(_M_original_len)); + + if (__p.first) + { + __try + { + std::__uninitialized_construct_buf(__p.first, __p.first + __p.second, + __seed); + _M_buffer = __p.first; + _M_len = __p.second; + } + __catch(...) + { + std::__detail::__return_temporary_buffer(__p.first, __p.second); + __throw_exception_again; + } + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_TEMPBUF_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_tree.h b/resources/sources/avr-libstdcpp/include/bits/stl_tree.h new file mode 100644 index 000000000..5be15afa2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_tree.h @@ -0,0 +1,2644 @@ +// RB tree implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + */ + +/** @file bits/stl_tree.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{map,set} + */ + +#ifndef _STL_TREE_H +#define _STL_TREE_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include +#if __cplusplus >= 201103L +# include +#endif +#if __cplusplus > 201402L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus > 201103L +# define __cpp_lib_generic_associative_lookup 201304 +#endif + + // Red-black tree class, designed for use in implementing STL + // associative containers (set, multiset, map, and multimap). The + // insertion and deletion algorithms are based on those in Cormen, + // Leiserson, and Rivest, Introduction to Algorithms (MIT Press, + // 1990), except that + // + // (1) the header cell is maintained with links not only to the root + // but also to the leftmost node of the tree, to enable constant + // time begin(), and to the rightmost node of the tree, to enable + // linear time performance when used with the generic set algorithms + // (set_union, etc.) + // + // (2) when a node being deleted has two children its successor node + // is relinked into its place, rather than copied, so that the only + // iterators invalidated are those referring to the deleted node. + + enum _Rb_tree_color { _S_red = false, _S_black = true }; + + struct _Rb_tree_node_base + { + typedef _Rb_tree_node_base* _Base_ptr; + typedef const _Rb_tree_node_base* _Const_Base_ptr; + + _Rb_tree_color _M_color; + _Base_ptr _M_parent; + _Base_ptr _M_left; + _Base_ptr _M_right; + + static _Base_ptr + _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } + + static _Const_Base_ptr + _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { + while (__x->_M_left != 0) __x = __x->_M_left; + return __x; + } + + static _Base_ptr + _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + + static _Const_Base_ptr + _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { + while (__x->_M_right != 0) __x = __x->_M_right; + return __x; + } + }; + + // Helper type offering value initialization guarantee on the compare functor. + template + struct _Rb_tree_key_compare + { + _Key_compare _M_key_compare; + + _Rb_tree_key_compare() + _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Key_compare>::value) + : _M_key_compare() + { } + + _Rb_tree_key_compare(const _Key_compare& __comp) + : _M_key_compare(__comp) + { } + +#if __cplusplus >= 201103L + // Copy constructor added for consistency with C++98 mode. + _Rb_tree_key_compare(const _Rb_tree_key_compare&) = default; + + _Rb_tree_key_compare(_Rb_tree_key_compare&& __x) + noexcept(is_nothrow_copy_constructible<_Key_compare>::value) + : _M_key_compare(__x._M_key_compare) + { } +#endif + }; + + // Helper type to manage default initialization of node count and header. + struct _Rb_tree_header + { + _Rb_tree_node_base _M_header; + size_t _M_node_count; // Keeps track of size of tree. + + _Rb_tree_header() _GLIBCXX_NOEXCEPT + { + _M_header._M_color = _S_red; + _M_reset(); + } + +#if __cplusplus >= 201103L + _Rb_tree_header(_Rb_tree_header&& __x) noexcept + { + if (__x._M_header._M_parent != nullptr) + _M_move_data(__x); + else + { + _M_header._M_color = _S_red; + _M_reset(); + } + } +#endif + + void + _M_move_data(_Rb_tree_header& __from) + { + _M_header._M_color = __from._M_header._M_color; + _M_header._M_parent = __from._M_header._M_parent; + _M_header._M_left = __from._M_header._M_left; + _M_header._M_right = __from._M_header._M_right; + _M_header._M_parent->_M_parent = &_M_header; + _M_node_count = __from._M_node_count; + + __from._M_reset(); + } + + void + _M_reset() + { + _M_header._M_parent = 0; + _M_header._M_left = &_M_header; + _M_header._M_right = &_M_header; + _M_node_count = 0; + } + }; + + template + struct _Rb_tree_node : public _Rb_tree_node_base + { + typedef _Rb_tree_node<_Val>* _Link_type; + +#if __cplusplus < 201103L + _Val _M_value_field; + + _Val* + _M_valptr() + { return std::__addressof(_M_value_field); } + + const _Val* + _M_valptr() const + { return std::__addressof(_M_value_field); } +#else + __gnu_cxx::__aligned_membuf<_Val> _M_storage; + + _Val* + _M_valptr() + { return _M_storage._M_ptr(); } + + const _Val* + _M_valptr() const + { return _M_storage._M_ptr(); } +#endif + }; + + _GLIBCXX_PURE _Rb_tree_node_base* + _Rb_tree_increment(_Rb_tree_node_base* __x) throw (); + + _GLIBCXX_PURE const _Rb_tree_node_base* + _Rb_tree_increment(const _Rb_tree_node_base* __x) throw (); + + _GLIBCXX_PURE _Rb_tree_node_base* + _Rb_tree_decrement(_Rb_tree_node_base* __x) throw (); + + _GLIBCXX_PURE const _Rb_tree_node_base* + _Rb_tree_decrement(const _Rb_tree_node_base* __x) throw (); + + template + struct _Rb_tree_iterator + { + typedef _Tp value_type; + typedef _Tp& reference; + typedef _Tp* pointer; + + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + + typedef _Rb_tree_iterator<_Tp> _Self; + typedef _Rb_tree_node_base::_Base_ptr _Base_ptr; + typedef _Rb_tree_node<_Tp>* _Link_type; + + _Rb_tree_iterator() _GLIBCXX_NOEXCEPT + : _M_node() { } + + explicit + _Rb_tree_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT + : _M_node(__x) { } + + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *static_cast<_Link_type>(_M_node)->_M_valptr(); } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type> (_M_node)->_M_valptr(); } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + _M_node = _Rb_tree_increment(_M_node); + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _Rb_tree_increment(_M_node); + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + _M_node = _Rb_tree_decrement(_M_node); + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _Rb_tree_decrement(_M_node); + return __tmp; + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node == __y._M_node; } + +#if ! __cpp_lib_three_way_comparison + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node != __y._M_node; } +#endif + + _Base_ptr _M_node; + }; + + template + struct _Rb_tree_const_iterator + { + typedef _Tp value_type; + typedef const _Tp& reference; + typedef const _Tp* pointer; + + typedef _Rb_tree_iterator<_Tp> iterator; + + typedef bidirectional_iterator_tag iterator_category; + typedef ptrdiff_t difference_type; + + typedef _Rb_tree_const_iterator<_Tp> _Self; + typedef _Rb_tree_node_base::_Const_Base_ptr _Base_ptr; + typedef const _Rb_tree_node<_Tp>* _Link_type; + + _Rb_tree_const_iterator() _GLIBCXX_NOEXCEPT + : _M_node() { } + + explicit + _Rb_tree_const_iterator(_Base_ptr __x) _GLIBCXX_NOEXCEPT + : _M_node(__x) { } + + _Rb_tree_const_iterator(const iterator& __it) _GLIBCXX_NOEXCEPT + : _M_node(__it._M_node) { } + + iterator + _M_const_cast() const _GLIBCXX_NOEXCEPT + { return iterator(const_cast(_M_node)); } + + reference + operator*() const _GLIBCXX_NOEXCEPT + { return *static_cast<_Link_type>(_M_node)->_M_valptr(); } + + pointer + operator->() const _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type>(_M_node)->_M_valptr(); } + + _Self& + operator++() _GLIBCXX_NOEXCEPT + { + _M_node = _Rb_tree_increment(_M_node); + return *this; + } + + _Self + operator++(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _Rb_tree_increment(_M_node); + return __tmp; + } + + _Self& + operator--() _GLIBCXX_NOEXCEPT + { + _M_node = _Rb_tree_decrement(_M_node); + return *this; + } + + _Self + operator--(int) _GLIBCXX_NOEXCEPT + { + _Self __tmp = *this; + _M_node = _Rb_tree_decrement(_M_node); + return __tmp; + } + + friend bool + operator==(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node == __y._M_node; } + +#if ! __cpp_lib_three_way_comparison + friend bool + operator!=(const _Self& __x, const _Self& __y) _GLIBCXX_NOEXCEPT + { return __x._M_node != __y._M_node; } +#endif + + _Base_ptr _M_node; + }; + + void + _Rb_tree_insert_and_rebalance(const bool __insert_left, + _Rb_tree_node_base* __x, + _Rb_tree_node_base* __p, + _Rb_tree_node_base& __header) throw (); + + _Rb_tree_node_base* + _Rb_tree_rebalance_for_erase(_Rb_tree_node_base* const __z, + _Rb_tree_node_base& __header) throw (); + +#if __cplusplus >= 201402L + template> + struct __has_is_transparent + { }; + + template + struct __has_is_transparent<_Cmp, _SfinaeType, + __void_t> + { typedef void type; }; + + template + using __has_is_transparent_t + = typename __has_is_transparent<_Cmp, _SfinaeType>::type; +#endif + +#if __cplusplus > 201402L + template + struct _Rb_tree_merge_helper { }; +#endif + + template > + class _Rb_tree + { + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Rb_tree_node<_Val> >::other _Node_allocator; + + typedef __gnu_cxx::__alloc_traits<_Node_allocator> _Alloc_traits; + + protected: + typedef _Rb_tree_node_base* _Base_ptr; + typedef const _Rb_tree_node_base* _Const_Base_ptr; + typedef _Rb_tree_node<_Val>* _Link_type; + typedef const _Rb_tree_node<_Val>* _Const_Link_type; + + private: + // Functor recycling a pool of nodes and using allocation once the pool + // is empty. + struct _Reuse_or_alloc_node + { + _Reuse_or_alloc_node(_Rb_tree& __t) + : _M_root(__t._M_root()), _M_nodes(__t._M_rightmost()), _M_t(__t) + { + if (_M_root) + { + _M_root->_M_parent = 0; + + if (_M_nodes->_M_left) + _M_nodes = _M_nodes->_M_left; + } + else + _M_nodes = 0; + } + +#if __cplusplus >= 201103L + _Reuse_or_alloc_node(const _Reuse_or_alloc_node&) = delete; +#endif + + ~_Reuse_or_alloc_node() + { _M_t._M_erase(static_cast<_Link_type>(_M_root)); } + + template + _Link_type +#if __cplusplus < 201103L + operator()(const _Arg& __arg) +#else + operator()(_Arg&& __arg) +#endif + { + _Link_type __node = static_cast<_Link_type>(_M_extract()); + if (__node) + { + _M_t._M_destroy_node(__node); + _M_t._M_construct_node(__node, _GLIBCXX_FORWARD(_Arg, __arg)); + return __node; + } + + return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); + } + + private: + _Base_ptr + _M_extract() + { + if (!_M_nodes) + return _M_nodes; + + _Base_ptr __node = _M_nodes; + _M_nodes = _M_nodes->_M_parent; + if (_M_nodes) + { + if (_M_nodes->_M_right == __node) + { + _M_nodes->_M_right = 0; + + if (_M_nodes->_M_left) + { + _M_nodes = _M_nodes->_M_left; + + while (_M_nodes->_M_right) + _M_nodes = _M_nodes->_M_right; + + if (_M_nodes->_M_left) + _M_nodes = _M_nodes->_M_left; + } + } + else // __node is on the left. + _M_nodes->_M_left = 0; + } + else + _M_root = 0; + + return __node; + } + + _Base_ptr _M_root; + _Base_ptr _M_nodes; + _Rb_tree& _M_t; + }; + + // Functor similar to the previous one but without any pool of nodes to + // recycle. + struct _Alloc_node + { + _Alloc_node(_Rb_tree& __t) + : _M_t(__t) { } + + template + _Link_type +#if __cplusplus < 201103L + operator()(const _Arg& __arg) const +#else + operator()(_Arg&& __arg) const +#endif + { return _M_t._M_create_node(_GLIBCXX_FORWARD(_Arg, __arg)); } + + private: + _Rb_tree& _M_t; + }; + + public: + typedef _Key key_type; + typedef _Val value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + _Node_allocator& + _M_get_Node_allocator() _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + const _Node_allocator& + _M_get_Node_allocator() const _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_get_Node_allocator()); } + + protected: + _Link_type + _M_get_node() + { return _Alloc_traits::allocate(_M_get_Node_allocator(), 1); } + + void + _M_put_node(_Link_type __p) _GLIBCXX_NOEXCEPT + { _Alloc_traits::deallocate(_M_get_Node_allocator(), __p, 1); } + +#if __cplusplus < 201103L + void + _M_construct_node(_Link_type __node, const value_type& __x) + { + __try + { get_allocator().construct(__node->_M_valptr(), __x); } + __catch(...) + { + _M_put_node(__node); + __throw_exception_again; + } + } + + _Link_type + _M_create_node(const value_type& __x) + { + _Link_type __tmp = _M_get_node(); + _M_construct_node(__tmp, __x); + return __tmp; + } +#else + template + void + _M_construct_node(_Link_type __node, _Args&&... __args) + { + __try + { + ::new(__node) _Rb_tree_node<_Val>; + _Alloc_traits::construct(_M_get_Node_allocator(), + __node->_M_valptr(), + std::forward<_Args>(__args)...); + } + __catch(...) + { + __node->~_Rb_tree_node<_Val>(); + _M_put_node(__node); + __throw_exception_again; + } + } + + template + _Link_type + _M_create_node(_Args&&... __args) + { + _Link_type __tmp = _M_get_node(); + _M_construct_node(__tmp, std::forward<_Args>(__args)...); + return __tmp; + } +#endif + + void + _M_destroy_node(_Link_type __p) _GLIBCXX_NOEXCEPT + { +#if __cplusplus < 201103L + get_allocator().destroy(__p->_M_valptr()); +#else + _Alloc_traits::destroy(_M_get_Node_allocator(), __p->_M_valptr()); + __p->~_Rb_tree_node<_Val>(); +#endif + } + + void + _M_drop_node(_Link_type __p) _GLIBCXX_NOEXCEPT + { + _M_destroy_node(__p); + _M_put_node(__p); + } + + template + _Link_type + _M_clone_node(_Const_Link_type __x, _NodeGen& __node_gen) + { + _Link_type __tmp = __node_gen(*__x->_M_valptr()); + __tmp->_M_color = __x->_M_color; + __tmp->_M_left = 0; + __tmp->_M_right = 0; + return __tmp; + } + + protected: +#if _GLIBCXX_INLINE_VERSION + template +#else + // Unused _Is_pod_comparator is kept as it is part of mangled name. + template +#endif + struct _Rb_tree_impl + : public _Node_allocator + , public _Rb_tree_key_compare<_Key_compare> + , public _Rb_tree_header + { + typedef _Rb_tree_key_compare<_Key_compare> _Base_key_compare; + + _Rb_tree_impl() + _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Node_allocator>::value + && is_nothrow_default_constructible<_Base_key_compare>::value ) + : _Node_allocator() + { } + + _Rb_tree_impl(const _Rb_tree_impl& __x) + : _Node_allocator(_Alloc_traits::_S_select_on_copy(__x)) + , _Base_key_compare(__x._M_key_compare) + { } + +#if __cplusplus < 201103L + _Rb_tree_impl(const _Key_compare& __comp, const _Node_allocator& __a) + : _Node_allocator(__a), _Base_key_compare(__comp) + { } +#else + _Rb_tree_impl(_Rb_tree_impl&&) = default; + + explicit + _Rb_tree_impl(_Node_allocator&& __a) + : _Node_allocator(std::move(__a)) + { } + + _Rb_tree_impl(_Rb_tree_impl&& __x, _Node_allocator&& __a) + : _Node_allocator(std::move(__a)), + _Base_key_compare(std::move(__x)), + _Rb_tree_header(std::move(__x)) + { } + + _Rb_tree_impl(const _Key_compare& __comp, _Node_allocator&& __a) + : _Node_allocator(std::move(__a)), _Base_key_compare(__comp) + { } +#endif + }; + + _Rb_tree_impl<_Compare> _M_impl; + + protected: + _Base_ptr& + _M_root() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_parent; } + + _Const_Base_ptr + _M_root() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_parent; } + + _Base_ptr& + _M_leftmost() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_left; } + + _Const_Base_ptr + _M_leftmost() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_left; } + + _Base_ptr& + _M_rightmost() _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_right; } + + _Const_Base_ptr + _M_rightmost() const _GLIBCXX_NOEXCEPT + { return this->_M_impl._M_header._M_right; } + + _Link_type + _M_begin() _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type>(this->_M_impl._M_header._M_parent); } + + _Const_Link_type + _M_begin() const _GLIBCXX_NOEXCEPT + { + return static_cast<_Const_Link_type> + (this->_M_impl._M_header._M_parent); + } + + _Base_ptr + _M_end() _GLIBCXX_NOEXCEPT + { return &this->_M_impl._M_header; } + + _Const_Base_ptr + _M_end() const _GLIBCXX_NOEXCEPT + { return &this->_M_impl._M_header; } + + static const _Key& + _S_key(_Const_Link_type __x) + { +#if __cplusplus >= 201103L + // If we're asking for the key we're presumably using the comparison + // object, and so this is a good place to sanity check it. + static_assert(__is_invocable<_Compare&, const _Key&, const _Key&>{}, + "comparison object must be invocable " + "with two arguments of key type"); +# if __cplusplus >= 201703L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2542. Missing const requirements for associative containers + if constexpr (__is_invocable<_Compare&, const _Key&, const _Key&>{}) + static_assert( + is_invocable_v, + "comparison object must be invocable as const"); +# endif // C++17 +#endif // C++11 + + return _KeyOfValue()(*__x->_M_valptr()); + } + + static _Link_type + _S_left(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type>(__x->_M_left); } + + static _Const_Link_type + _S_left(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return static_cast<_Const_Link_type>(__x->_M_left); } + + static _Link_type + _S_right(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return static_cast<_Link_type>(__x->_M_right); } + + static _Const_Link_type + _S_right(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return static_cast<_Const_Link_type>(__x->_M_right); } + + static const _Key& + _S_key(_Const_Base_ptr __x) + { return _S_key(static_cast<_Const_Link_type>(__x)); } + + static _Base_ptr + _S_minimum(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return _Rb_tree_node_base::_S_minimum(__x); } + + static _Const_Base_ptr + _S_minimum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return _Rb_tree_node_base::_S_minimum(__x); } + + static _Base_ptr + _S_maximum(_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return _Rb_tree_node_base::_S_maximum(__x); } + + static _Const_Base_ptr + _S_maximum(_Const_Base_ptr __x) _GLIBCXX_NOEXCEPT + { return _Rb_tree_node_base::_S_maximum(__x); } + + public: + typedef _Rb_tree_iterator iterator; + typedef _Rb_tree_const_iterator const_iterator; + + typedef std::reverse_iterator reverse_iterator; + typedef std::reverse_iterator const_reverse_iterator; + +#if __cplusplus > 201402L + using node_type = _Node_handle<_Key, _Val, _Node_allocator>; + using insert_return_type = _Node_insert_return< + conditional_t, const_iterator, iterator>, + node_type>; +#endif + + pair<_Base_ptr, _Base_ptr> + _M_get_insert_unique_pos(const key_type& __k); + + pair<_Base_ptr, _Base_ptr> + _M_get_insert_equal_pos(const key_type& __k); + + pair<_Base_ptr, _Base_ptr> + _M_get_insert_hint_unique_pos(const_iterator __pos, + const key_type& __k); + + pair<_Base_ptr, _Base_ptr> + _M_get_insert_hint_equal_pos(const_iterator __pos, + const key_type& __k); + + private: +#if __cplusplus >= 201103L + template + iterator + _M_insert_(_Base_ptr __x, _Base_ptr __y, _Arg&& __v, _NodeGen&); + + iterator + _M_insert_node(_Base_ptr __x, _Base_ptr __y, _Link_type __z); + + template + iterator + _M_insert_lower(_Base_ptr __y, _Arg&& __v); + + template + iterator + _M_insert_equal_lower(_Arg&& __x); + + iterator + _M_insert_lower_node(_Base_ptr __p, _Link_type __z); + + iterator + _M_insert_equal_lower_node(_Link_type __z); +#else + template + iterator + _M_insert_(_Base_ptr __x, _Base_ptr __y, + const value_type& __v, _NodeGen&); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 233. Insertion hints in associative containers. + iterator + _M_insert_lower(_Base_ptr __y, const value_type& __v); + + iterator + _M_insert_equal_lower(const value_type& __x); +#endif + + template + _Link_type + _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen&); + + template + _Link_type + _M_copy(const _Rb_tree& __x, _NodeGen& __gen) + { + _Link_type __root = _M_copy(__x._M_begin(), _M_end(), __gen); + _M_leftmost() = _S_minimum(__root); + _M_rightmost() = _S_maximum(__root); + _M_impl._M_node_count = __x._M_impl._M_node_count; + return __root; + } + + _Link_type + _M_copy(const _Rb_tree& __x) + { + _Alloc_node __an(*this); + return _M_copy(__x, __an); + } + + void + _M_erase(_Link_type __x); + + iterator + _M_lower_bound(_Link_type __x, _Base_ptr __y, + const _Key& __k); + + const_iterator + _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y, + const _Key& __k) const; + + iterator + _M_upper_bound(_Link_type __x, _Base_ptr __y, + const _Key& __k); + + const_iterator + _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y, + const _Key& __k) const; + + public: + // allocation/deallocation +#if __cplusplus < 201103L + _Rb_tree() { } +#else + _Rb_tree() = default; +#endif + + _Rb_tree(const _Compare& __comp, + const allocator_type& __a = allocator_type()) + : _M_impl(__comp, _Node_allocator(__a)) { } + + _Rb_tree(const _Rb_tree& __x) + : _M_impl(__x._M_impl) + { + if (__x._M_root() != 0) + _M_root() = _M_copy(__x); + } + +#if __cplusplus >= 201103L + _Rb_tree(const allocator_type& __a) + : _M_impl(_Node_allocator(__a)) + { } + + _Rb_tree(const _Rb_tree& __x, const allocator_type& __a) + : _M_impl(__x._M_impl._M_key_compare, _Node_allocator(__a)) + { + if (__x._M_root() != nullptr) + _M_root() = _M_copy(__x); + } + + _Rb_tree(_Rb_tree&&) = default; + + _Rb_tree(_Rb_tree&& __x, const allocator_type& __a) + : _Rb_tree(std::move(__x), _Node_allocator(__a)) + { } + + private: + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, true_type) + noexcept(is_nothrow_default_constructible<_Compare>::value) + : _M_impl(std::move(__x._M_impl), std::move(__a)) + { } + + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a, false_type) + : _M_impl(__x._M_impl._M_key_compare, std::move(__a)) + { + if (__x._M_root() != nullptr) + _M_move_data(__x, false_type{}); + } + + public: + _Rb_tree(_Rb_tree&& __x, _Node_allocator&& __a) + noexcept( noexcept( + _Rb_tree(std::declval<_Rb_tree&&>(), std::declval<_Node_allocator&&>(), + std::declval())) ) + : _Rb_tree(std::move(__x), std::move(__a), + typename _Alloc_traits::is_always_equal{}) + { } +#endif + + ~_Rb_tree() _GLIBCXX_NOEXCEPT + { _M_erase(_M_begin()); } + + _Rb_tree& + operator=(const _Rb_tree& __x); + + // Accessors. + _Compare + key_comp() const + { return _M_impl._M_key_compare; } + + iterator + begin() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_header._M_left); } + + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_header._M_left); } + + iterator + end() _GLIBCXX_NOEXCEPT + { return iterator(&this->_M_impl._M_header); } + + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return const_iterator(&this->_M_impl._M_header); } + + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(end()); } + + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(end()); } + + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(begin()); } + + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(begin()); } + + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return _M_impl._M_node_count == 0; } + + size_type + size() const _GLIBCXX_NOEXCEPT + { return _M_impl._M_node_count; } + + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _Alloc_traits::max_size(_M_get_Node_allocator()); } + + void + swap(_Rb_tree& __t) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value); + + // Insert/erase. +#if __cplusplus >= 201103L + template + pair + _M_insert_unique(_Arg&& __x); + + template + iterator + _M_insert_equal(_Arg&& __x); + + template + iterator + _M_insert_unique_(const_iterator __pos, _Arg&& __x, _NodeGen&); + + template + iterator + _M_insert_unique_(const_iterator __pos, _Arg&& __x) + { + _Alloc_node __an(*this); + return _M_insert_unique_(__pos, std::forward<_Arg>(__x), __an); + } + + template + iterator + _M_insert_equal_(const_iterator __pos, _Arg&& __x, _NodeGen&); + + template + iterator + _M_insert_equal_(const_iterator __pos, _Arg&& __x) + { + _Alloc_node __an(*this); + return _M_insert_equal_(__pos, std::forward<_Arg>(__x), __an); + } + + template + pair + _M_emplace_unique(_Args&&... __args); + + template + iterator + _M_emplace_equal(_Args&&... __args); + + template + iterator + _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args); + + template + iterator + _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args); + + template + using __same_value_type + = is_same::value_type>; + + template + __enable_if_t<__same_value_type<_InputIterator>::value> + _M_insert_range_unique(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_insert_unique_(end(), *__first, __an); + } + + template + __enable_if_t::value> + _M_insert_range_unique(_InputIterator __first, _InputIterator __last) + { + for (; __first != __last; ++__first) + _M_emplace_unique(*__first); + } + + template + __enable_if_t<__same_value_type<_InputIterator>::value> + _M_insert_range_equal(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_insert_equal_(end(), *__first, __an); + } + + template + __enable_if_t::value> + _M_insert_range_equal(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_emplace_equal(*__first); + } +#else + pair + _M_insert_unique(const value_type& __x); + + iterator + _M_insert_equal(const value_type& __x); + + template + iterator + _M_insert_unique_(const_iterator __pos, const value_type& __x, + _NodeGen&); + + iterator + _M_insert_unique_(const_iterator __pos, const value_type& __x) + { + _Alloc_node __an(*this); + return _M_insert_unique_(__pos, __x, __an); + } + + template + iterator + _M_insert_equal_(const_iterator __pos, const value_type& __x, + _NodeGen&); + iterator + _M_insert_equal_(const_iterator __pos, const value_type& __x) + { + _Alloc_node __an(*this); + return _M_insert_equal_(__pos, __x, __an); + } + + template + void + _M_insert_range_unique(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_insert_unique_(end(), *__first, __an); + } + + template + void + _M_insert_range_equal(_InputIterator __first, _InputIterator __last) + { + _Alloc_node __an(*this); + for (; __first != __last; ++__first) + _M_insert_equal_(end(), *__first, __an); + } +#endif + + private: + void + _M_erase_aux(const_iterator __position); + + void + _M_erase_aux(const_iterator __first, const_iterator __last); + + public: +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __position) + { + __glibcxx_assert(__position != end()); + const_iterator __result = __position; + ++__result; + _M_erase_aux(__position); + return __result._M_const_cast(); + } + + // LWG 2059. + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(iterator __position) + { + __glibcxx_assert(__position != end()); + iterator __result = __position; + ++__result; + _M_erase_aux(__position); + return __result; + } +#else + void + erase(iterator __position) + { + __glibcxx_assert(__position != end()); + _M_erase_aux(__position); + } + + void + erase(const_iterator __position) + { + __glibcxx_assert(__position != end()); + _M_erase_aux(__position); + } +#endif + + size_type + erase(const key_type& __x); + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 130. Associative erase should return an iterator. + _GLIBCXX_ABI_TAG_CXX11 + iterator + erase(const_iterator __first, const_iterator __last) + { + _M_erase_aux(__first, __last); + return __last._M_const_cast(); + } +#else + void + erase(iterator __first, iterator __last) + { _M_erase_aux(__first, __last); } + + void + erase(const_iterator __first, const_iterator __last) + { _M_erase_aux(__first, __last); } +#endif + + void + clear() _GLIBCXX_NOEXCEPT + { + _M_erase(_M_begin()); + _M_impl._M_reset(); + } + + // Set operations. + iterator + find(const key_type& __k); + + const_iterator + find(const key_type& __k) const; + + size_type + count(const key_type& __k) const; + + iterator + lower_bound(const key_type& __k) + { return _M_lower_bound(_M_begin(), _M_end(), __k); } + + const_iterator + lower_bound(const key_type& __k) const + { return _M_lower_bound(_M_begin(), _M_end(), __k); } + + iterator + upper_bound(const key_type& __k) + { return _M_upper_bound(_M_begin(), _M_end(), __k); } + + const_iterator + upper_bound(const key_type& __k) const + { return _M_upper_bound(_M_begin(), _M_end(), __k); } + + pair + equal_range(const key_type& __k); + + pair + equal_range(const key_type& __k) const; + +#if __cplusplus >= 201402L + template> + iterator + _M_find_tr(const _Kt& __k) + { + const _Rb_tree* __const_this = this; + return __const_this->_M_find_tr(__k)._M_const_cast(); + } + + template> + const_iterator + _M_find_tr(const _Kt& __k) const + { + auto __j = _M_lower_bound_tr(__k); + if (__j != end() && _M_impl._M_key_compare(__k, _S_key(__j._M_node))) + __j = end(); + return __j; + } + + template> + size_type + _M_count_tr(const _Kt& __k) const + { + auto __p = _M_equal_range_tr(__k); + return std::distance(__p.first, __p.second); + } + + template> + iterator + _M_lower_bound_tr(const _Kt& __k) + { + const _Rb_tree* __const_this = this; + return __const_this->_M_lower_bound_tr(__k)._M_const_cast(); + } + + template> + const_iterator + _M_lower_bound_tr(const _Kt& __k) const + { + auto __x = _M_begin(); + auto __y = _M_end(); + while (__x != 0) + if (!_M_impl._M_key_compare(_S_key(__x), __k)) + { + __y = __x; + __x = _S_left(__x); + } + else + __x = _S_right(__x); + return const_iterator(__y); + } + + template> + iterator + _M_upper_bound_tr(const _Kt& __k) + { + const _Rb_tree* __const_this = this; + return __const_this->_M_upper_bound_tr(__k)._M_const_cast(); + } + + template> + const_iterator + _M_upper_bound_tr(const _Kt& __k) const + { + auto __x = _M_begin(); + auto __y = _M_end(); + while (__x != 0) + if (_M_impl._M_key_compare(__k, _S_key(__x))) + { + __y = __x; + __x = _S_left(__x); + } + else + __x = _S_right(__x); + return const_iterator(__y); + } + + template> + pair + _M_equal_range_tr(const _Kt& __k) + { + const _Rb_tree* __const_this = this; + auto __ret = __const_this->_M_equal_range_tr(__k); + return { __ret.first._M_const_cast(), __ret.second._M_const_cast() }; + } + + template> + pair + _M_equal_range_tr(const _Kt& __k) const + { + auto __low = _M_lower_bound_tr(__k); + auto __high = __low; + auto& __cmp = _M_impl._M_key_compare; + while (__high != end() && !__cmp(__k, _S_key(__high._M_node))) + ++__high; + return { __low, __high }; + } +#endif + + // Debugging. + bool + __rb_verify() const; + +#if __cplusplus >= 201103L + _Rb_tree& + operator=(_Rb_tree&&) + noexcept(_Alloc_traits::_S_nothrow_move() + && is_nothrow_move_assignable<_Compare>::value); + + template + void + _M_assign_unique(_Iterator, _Iterator); + + template + void + _M_assign_equal(_Iterator, _Iterator); + + private: + // Move elements from container with equal allocator. + void + _M_move_data(_Rb_tree& __x, true_type) + { _M_impl._M_move_data(__x._M_impl); } + + // Move elements from container with possibly non-equal allocator, + // which might result in a copy not a move. + void + _M_move_data(_Rb_tree&, false_type); + + // Move assignment from container with equal allocator. + void + _M_move_assign(_Rb_tree&, true_type); + + // Move assignment from container with possibly non-equal allocator, + // which might result in a copy not a move. + void + _M_move_assign(_Rb_tree&, false_type); +#endif + +#if __cplusplus > 201402L + public: + /// Re-insert an extracted node. + insert_return_type + _M_reinsert_node_unique(node_type&& __nh) + { + insert_return_type __ret; + if (__nh.empty()) + __ret.position = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + + auto __res = _M_get_insert_unique_pos(__nh._M_key()); + if (__res.second) + { + __ret.position + = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + __nh._M_ptr = nullptr; + __ret.inserted = true; + } + else + { + __ret.node = std::move(__nh); + __ret.position = iterator(__res.first); + __ret.inserted = false; + } + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_equal(node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_equal_pos(__nh._M_key()); + if (__res.second) + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + else + __ret = _M_insert_equal_lower_node(__nh._M_ptr); + __nh._M_ptr = nullptr; + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_hint_unique(const_iterator __hint, node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_hint_unique_pos(__hint, __nh._M_key()); + if (__res.second) + { + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + __nh._M_ptr = nullptr; + } + else + __ret = iterator(__res.first); + } + return __ret; + } + + /// Re-insert an extracted node. + iterator + _M_reinsert_node_hint_equal(const_iterator __hint, node_type&& __nh) + { + iterator __ret; + if (__nh.empty()) + __ret = end(); + else + { + __glibcxx_assert(_M_get_Node_allocator() == *__nh._M_alloc); + auto __res = _M_get_insert_hint_equal_pos(__hint, __nh._M_key()); + if (__res.second) + __ret = _M_insert_node(__res.first, __res.second, __nh._M_ptr); + else + __ret = _M_insert_equal_lower_node(__nh._M_ptr); + __nh._M_ptr = nullptr; + } + return __ret; + } + + /// Extract a node. + node_type + extract(const_iterator __pos) + { + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_const_cast()._M_node, _M_impl._M_header); + --_M_impl._M_node_count; + return { static_cast<_Link_type>(__ptr), _M_get_Node_allocator() }; + } + + /// Extract a node. + node_type + extract(const key_type& __k) + { + node_type __nh; + auto __pos = find(__k); + if (__pos != end()) + __nh = extract(const_iterator(__pos)); + return __nh; + } + + template + using _Compatible_tree + = _Rb_tree<_Key, _Val, _KeyOfValue, _Compare2, _Alloc>; + + template + friend class _Rb_tree_merge_helper; + + /// Merge from a compatible container into one with unique keys. + template + void + _M_merge_unique(_Compatible_tree<_Compare2>& __src) noexcept + { + using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>; + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + auto __res = _M_get_insert_unique_pos(_KeyOfValue()(*__pos)); + if (__res.second) + { + auto& __src_impl = _Merge_helper::_S_get_impl(__src); + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_node, __src_impl._M_header); + --__src_impl._M_node_count; + _M_insert_node(__res.first, __res.second, + static_cast<_Link_type>(__ptr)); + } + } + } + + /// Merge from a compatible container into one with equivalent keys. + template + void + _M_merge_equal(_Compatible_tree<_Compare2>& __src) noexcept + { + using _Merge_helper = _Rb_tree_merge_helper<_Rb_tree, _Compare2>; + for (auto __i = __src.begin(), __end = __src.end(); __i != __end;) + { + auto __pos = __i++; + auto __res = _M_get_insert_equal_pos(_KeyOfValue()(*__pos)); + if (__res.second) + { + auto& __src_impl = _Merge_helper::_S_get_impl(__src); + auto __ptr = _Rb_tree_rebalance_for_erase( + __pos._M_node, __src_impl._M_header); + --__src_impl._M_node_count; + _M_insert_node(__res.first, __res.second, + static_cast<_Link_type>(__ptr)); + } + } + } +#endif // C++17 + + friend bool + operator==(const _Rb_tree& __x, const _Rb_tree& __y) + { + return __x.size() == __y.size() + && std::equal(__x.begin(), __x.end(), __y.begin()); + } + +#if __cpp_lib_three_way_comparison + friend auto + operator<=>(const _Rb_tree& __x, const _Rb_tree& __y) + { + if constexpr (requires { typename __detail::__synth3way_t<_Val>; }) + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + friend bool + operator<(const _Rb_tree& __x, const _Rb_tree& __y) + { + return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); + } + + friend bool _GLIBCXX_DEPRECATED + operator!=(const _Rb_tree& __x, const _Rb_tree& __y) + { return !(__x == __y); } + + friend bool _GLIBCXX_DEPRECATED + operator>(const _Rb_tree& __x, const _Rb_tree& __y) + { return __y < __x; } + + friend bool _GLIBCXX_DEPRECATED + operator<=(const _Rb_tree& __x, const _Rb_tree& __y) + { return !(__y < __x); } + + friend bool _GLIBCXX_DEPRECATED + operator>=(const _Rb_tree& __x, const _Rb_tree& __y) + { return !(__x < __y); } +#endif + }; + + template + inline void + swap(_Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __x, + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& __y) + { __x.swap(__y); } + +#if __cplusplus >= 201103L + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_move_data(_Rb_tree& __x, false_type) + { + if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) + _M_move_data(__x, true_type()); + else + { + _Alloc_node __an(*this); + auto __lbd = + [&__an](const value_type& __cval) + { + auto& __val = const_cast(__cval); + return __an(std::move_if_noexcept(__val)); + }; + _M_root() = _M_copy(__x, __lbd); + } + } + + template + inline void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_move_assign(_Rb_tree& __x, true_type) + { + clear(); + if (__x._M_root() != nullptr) + _M_move_data(__x, true_type()); + std::__alloc_on_move(_M_get_Node_allocator(), + __x._M_get_Node_allocator()); + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_move_assign(_Rb_tree& __x, false_type) + { + if (_M_get_Node_allocator() == __x._M_get_Node_allocator()) + return _M_move_assign(__x, true_type{}); + + // Try to move each node reusing existing nodes and copying __x nodes + // structure. + _Reuse_or_alloc_node __roan(*this); + _M_impl._M_reset(); + if (__x._M_root() != nullptr) + { + auto __lbd = + [&__roan](const value_type& __cval) + { + auto& __val = const_cast(__cval); + return __roan(std::move(__val)); + }; + _M_root() = _M_copy(__x, __lbd); + __x.clear(); + } + } + + template + inline _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + operator=(_Rb_tree&& __x) + noexcept(_Alloc_traits::_S_nothrow_move() + && is_nothrow_move_assignable<_Compare>::value) + { + _M_impl._M_key_compare = std::move(__x._M_impl._M_key_compare); + _M_move_assign(__x, __bool_constant<_Alloc_traits::_S_nothrow_move()>()); + return *this; + } + + template + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_assign_unique(_Iterator __first, _Iterator __last) + { + _Reuse_or_alloc_node __roan(*this); + _M_impl._M_reset(); + for (; __first != __last; ++__first) + _M_insert_unique_(end(), *__first, __roan); + } + + template + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_assign_equal(_Iterator __first, _Iterator __last) + { + _Reuse_or_alloc_node __roan(*this); + _M_impl._M_reset(); + for (; __first != __last; ++__first) + _M_insert_equal_(end(), *__first, __roan); + } +#endif + + template + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>& + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + operator=(const _Rb_tree& __x) + { + if (this != &__x) + { + // Note that _Key may be a constant type. +#if __cplusplus >= 201103L + if (_Alloc_traits::_S_propagate_on_copy_assign()) + { + auto& __this_alloc = this->_M_get_Node_allocator(); + auto& __that_alloc = __x._M_get_Node_allocator(); + if (!_Alloc_traits::_S_always_equal() + && __this_alloc != __that_alloc) + { + // Replacement allocator cannot free existing storage, we need + // to erase nodes first. + clear(); + std::__alloc_on_copy(__this_alloc, __that_alloc); + } + } +#endif + + _Reuse_or_alloc_node __roan(*this); + _M_impl._M_reset(); + _M_impl._M_key_compare = __x._M_impl._M_key_compare; + if (__x._M_root() != 0) + _M_root() = _M_copy(__x, __roan); + } + + return *this; + } + + template +#if __cplusplus >= 201103L + template +#else + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_(_Base_ptr __x, _Base_ptr __p, +#if __cplusplus >= 201103L + _Arg&& __v, +#else + const _Val& __v, +#endif + _NodeGen& __node_gen) + { + bool __insert_left = (__x != 0 || __p == _M_end() + || _M_impl._M_key_compare(_KeyOfValue()(__v), + _S_key(__p))); + + _Link_type __z = __node_gen(_GLIBCXX_FORWARD(_Arg, __v)); + + _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, + this->_M_impl._M_header); + ++_M_impl._M_node_count; + return iterator(__z); + } + + template +#if __cplusplus >= 201103L + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: +#if __cplusplus >= 201103L + _M_insert_lower(_Base_ptr __p, _Arg&& __v) +#else + _M_insert_lower(_Base_ptr __p, const _Val& __v) +#endif + { + bool __insert_left = (__p == _M_end() + || !_M_impl._M_key_compare(_S_key(__p), + _KeyOfValue()(__v))); + + _Link_type __z = _M_create_node(_GLIBCXX_FORWARD(_Arg, __v)); + + _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, + this->_M_impl._M_header); + ++_M_impl._M_node_count; + return iterator(__z); + } + + template +#if __cplusplus >= 201103L + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: +#if __cplusplus >= 201103L + _M_insert_equal_lower(_Arg&& __v) +#else + _M_insert_equal_lower(const _Val& __v) +#endif + { + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + while (__x != 0) + { + __y = __x; + __x = !_M_impl._M_key_compare(_S_key(__x), _KeyOfValue()(__v)) ? + _S_left(__x) : _S_right(__x); + } + return _M_insert_lower(__y, _GLIBCXX_FORWARD(_Arg, __v)); + } + + template + template + typename _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>::_Link_type + _Rb_tree<_Key, _Val, _KoV, _Compare, _Alloc>:: + _M_copy(_Const_Link_type __x, _Base_ptr __p, _NodeGen& __node_gen) + { + // Structural copy. __x and __p must be non-null. + _Link_type __top = _M_clone_node(__x, __node_gen); + __top->_M_parent = __p; + + __try + { + if (__x->_M_right) + __top->_M_right = _M_copy(_S_right(__x), __top, __node_gen); + __p = __top; + __x = _S_left(__x); + + while (__x != 0) + { + _Link_type __y = _M_clone_node(__x, __node_gen); + __p->_M_left = __y; + __y->_M_parent = __p; + if (__x->_M_right) + __y->_M_right = _M_copy(_S_right(__x), __y, __node_gen); + __p = __y; + __x = _S_left(__x); + } + } + __catch(...) + { + _M_erase(__top); + __throw_exception_again; + } + return __top; + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_erase(_Link_type __x) + { + // Erase without rebalancing. + while (__x != 0) + { + _M_erase(_S_right(__x)); + _Link_type __y = _S_left(__x); + _M_drop_node(__x); + __x = __y; + } + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_lower_bound(_Link_type __x, _Base_ptr __y, + const _Key& __k) + { + while (__x != 0) + if (!_M_impl._M_key_compare(_S_key(__x), __k)) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + return iterator(__y); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::const_iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_lower_bound(_Const_Link_type __x, _Const_Base_ptr __y, + const _Key& __k) const + { + while (__x != 0) + if (!_M_impl._M_key_compare(_S_key(__x), __k)) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + return const_iterator(__y); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_upper_bound(_Link_type __x, _Base_ptr __y, + const _Key& __k) + { + while (__x != 0) + if (_M_impl._M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + return iterator(__y); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::const_iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_upper_bound(_Const_Link_type __x, _Const_Base_ptr __y, + const _Key& __k) const + { + while (__x != 0) + if (_M_impl._M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + __x = _S_right(__x); + return const_iterator(__y); + } + + template + pair::iterator, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + equal_range(const _Key& __k) + { + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + while (__x != 0) + { + if (_M_impl._M_key_compare(_S_key(__x), __k)) + __x = _S_right(__x); + else if (_M_impl._M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + { + _Link_type __xu(__x); + _Base_ptr __yu(__y); + __y = __x, __x = _S_left(__x); + __xu = _S_right(__xu); + return pair(_M_lower_bound(__x, __y, __k), + _M_upper_bound(__xu, __yu, __k)); + } + } + return pair(iterator(__y), + iterator(__y)); + } + + template + pair::const_iterator, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::const_iterator> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + equal_range(const _Key& __k) const + { + _Const_Link_type __x = _M_begin(); + _Const_Base_ptr __y = _M_end(); + while (__x != 0) + { + if (_M_impl._M_key_compare(_S_key(__x), __k)) + __x = _S_right(__x); + else if (_M_impl._M_key_compare(__k, _S_key(__x))) + __y = __x, __x = _S_left(__x); + else + { + _Const_Link_type __xu(__x); + _Const_Base_ptr __yu(__y); + __y = __x, __x = _S_left(__x); + __xu = _S_right(__xu); + return pair(_M_lower_bound(__x, __y, __k), + _M_upper_bound(__xu, __yu, __k)); + } + } + return pair(const_iterator(__y), + const_iterator(__y)); + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + swap(_Rb_tree& __t) + _GLIBCXX_NOEXCEPT_IF(__is_nothrow_swappable<_Compare>::value) + { + if (_M_root() == 0) + { + if (__t._M_root() != 0) + _M_impl._M_move_data(__t._M_impl); + } + else if (__t._M_root() == 0) + __t._M_impl._M_move_data(_M_impl); + else + { + std::swap(_M_root(),__t._M_root()); + std::swap(_M_leftmost(),__t._M_leftmost()); + std::swap(_M_rightmost(),__t._M_rightmost()); + + _M_root()->_M_parent = _M_end(); + __t._M_root()->_M_parent = __t._M_end(); + std::swap(this->_M_impl._M_node_count, __t._M_impl._M_node_count); + } + // No need to swap header's color as it does not change. + std::swap(this->_M_impl._M_key_compare, __t._M_impl._M_key_compare); + + _Alloc_traits::_S_on_swap(_M_get_Node_allocator(), + __t._M_get_Node_allocator()); + } + + template + pair::_Base_ptr, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::_Base_ptr> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_get_insert_unique_pos(const key_type& __k) + { + typedef pair<_Base_ptr, _Base_ptr> _Res; + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + bool __comp = true; + while (__x != 0) + { + __y = __x; + __comp = _M_impl._M_key_compare(__k, _S_key(__x)); + __x = __comp ? _S_left(__x) : _S_right(__x); + } + iterator __j = iterator(__y); + if (__comp) + { + if (__j == begin()) + return _Res(__x, __y); + else + --__j; + } + if (_M_impl._M_key_compare(_S_key(__j._M_node), __k)) + return _Res(__x, __y); + return _Res(__j._M_node, 0); + } + + template + pair::_Base_ptr, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::_Base_ptr> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_get_insert_equal_pos(const key_type& __k) + { + typedef pair<_Base_ptr, _Base_ptr> _Res; + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + while (__x != 0) + { + __y = __x; + __x = _M_impl._M_key_compare(__k, _S_key(__x)) ? + _S_left(__x) : _S_right(__x); + } + return _Res(__x, __y); + } + + template +#if __cplusplus >= 201103L + template +#endif + pair::iterator, bool> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: +#if __cplusplus >= 201103L + _M_insert_unique(_Arg&& __v) +#else + _M_insert_unique(const _Val& __v) +#endif + { + typedef pair _Res; + pair<_Base_ptr, _Base_ptr> __res + = _M_get_insert_unique_pos(_KeyOfValue()(__v)); + + if (__res.second) + { + _Alloc_node __an(*this); + return _Res(_M_insert_(__res.first, __res.second, + _GLIBCXX_FORWARD(_Arg, __v), __an), + true); + } + + return _Res(iterator(__res.first), false); + } + + template +#if __cplusplus >= 201103L + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: +#if __cplusplus >= 201103L + _M_insert_equal(_Arg&& __v) +#else + _M_insert_equal(const _Val& __v) +#endif + { + pair<_Base_ptr, _Base_ptr> __res + = _M_get_insert_equal_pos(_KeyOfValue()(__v)); + _Alloc_node __an(*this); + return _M_insert_(__res.first, __res.second, + _GLIBCXX_FORWARD(_Arg, __v), __an); + } + + template + pair::_Base_ptr, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::_Base_ptr> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_get_insert_hint_unique_pos(const_iterator __position, + const key_type& __k) + { + iterator __pos = __position._M_const_cast(); + typedef pair<_Base_ptr, _Base_ptr> _Res; + + // end() + if (__pos._M_node == _M_end()) + { + if (size() > 0 + && _M_impl._M_key_compare(_S_key(_M_rightmost()), __k)) + return _Res(0, _M_rightmost()); + else + return _M_get_insert_unique_pos(__k); + } + else if (_M_impl._M_key_compare(__k, _S_key(__pos._M_node))) + { + // First, try before... + iterator __before = __pos; + if (__pos._M_node == _M_leftmost()) // begin() + return _Res(_M_leftmost(), _M_leftmost()); + else if (_M_impl._M_key_compare(_S_key((--__before)._M_node), __k)) + { + if (_S_right(__before._M_node) == 0) + return _Res(0, __before._M_node); + else + return _Res(__pos._M_node, __pos._M_node); + } + else + return _M_get_insert_unique_pos(__k); + } + else if (_M_impl._M_key_compare(_S_key(__pos._M_node), __k)) + { + // ... then try after. + iterator __after = __pos; + if (__pos._M_node == _M_rightmost()) + return _Res(0, _M_rightmost()); + else if (_M_impl._M_key_compare(__k, _S_key((++__after)._M_node))) + { + if (_S_right(__pos._M_node) == 0) + return _Res(0, __pos._M_node); + else + return _Res(__after._M_node, __after._M_node); + } + else + return _M_get_insert_unique_pos(__k); + } + else + // Equivalent keys. + return _Res(__pos._M_node, 0); + } + + template +#if __cplusplus >= 201103L + template +#else + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_unique_(const_iterator __position, +#if __cplusplus >= 201103L + _Arg&& __v, +#else + const _Val& __v, +#endif + _NodeGen& __node_gen) + { + pair<_Base_ptr, _Base_ptr> __res + = _M_get_insert_hint_unique_pos(__position, _KeyOfValue()(__v)); + + if (__res.second) + return _M_insert_(__res.first, __res.second, + _GLIBCXX_FORWARD(_Arg, __v), + __node_gen); + return iterator(__res.first); + } + + template + pair::_Base_ptr, + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::_Base_ptr> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_get_insert_hint_equal_pos(const_iterator __position, const key_type& __k) + { + iterator __pos = __position._M_const_cast(); + typedef pair<_Base_ptr, _Base_ptr> _Res; + + // end() + if (__pos._M_node == _M_end()) + { + if (size() > 0 + && !_M_impl._M_key_compare(__k, _S_key(_M_rightmost()))) + return _Res(0, _M_rightmost()); + else + return _M_get_insert_equal_pos(__k); + } + else if (!_M_impl._M_key_compare(_S_key(__pos._M_node), __k)) + { + // First, try before... + iterator __before = __pos; + if (__pos._M_node == _M_leftmost()) // begin() + return _Res(_M_leftmost(), _M_leftmost()); + else if (!_M_impl._M_key_compare(__k, _S_key((--__before)._M_node))) + { + if (_S_right(__before._M_node) == 0) + return _Res(0, __before._M_node); + else + return _Res(__pos._M_node, __pos._M_node); + } + else + return _M_get_insert_equal_pos(__k); + } + else + { + // ... then try after. + iterator __after = __pos; + if (__pos._M_node == _M_rightmost()) + return _Res(0, _M_rightmost()); + else if (!_M_impl._M_key_compare(_S_key((++__after)._M_node), __k)) + { + if (_S_right(__pos._M_node) == 0) + return _Res(0, __pos._M_node); + else + return _Res(__after._M_node, __after._M_node); + } + else + return _Res(0, 0); + } + } + + template +#if __cplusplus >= 201103L + template +#else + template +#endif + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_equal_(const_iterator __position, +#if __cplusplus >= 201103L + _Arg&& __v, +#else + const _Val& __v, +#endif + _NodeGen& __node_gen) + { + pair<_Base_ptr, _Base_ptr> __res + = _M_get_insert_hint_equal_pos(__position, _KeyOfValue()(__v)); + + if (__res.second) + return _M_insert_(__res.first, __res.second, + _GLIBCXX_FORWARD(_Arg, __v), + __node_gen); + + return _M_insert_equal_lower(_GLIBCXX_FORWARD(_Arg, __v)); + } + +#if __cplusplus >= 201103L + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_node(_Base_ptr __x, _Base_ptr __p, _Link_type __z) + { + bool __insert_left = (__x != 0 || __p == _M_end() + || _M_impl._M_key_compare(_S_key(__z), + _S_key(__p))); + + _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, + this->_M_impl._M_header); + ++_M_impl._M_node_count; + return iterator(__z); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_lower_node(_Base_ptr __p, _Link_type __z) + { + bool __insert_left = (__p == _M_end() + || !_M_impl._M_key_compare(_S_key(__p), + _S_key(__z))); + + _Rb_tree_insert_and_rebalance(__insert_left, __z, __p, + this->_M_impl._M_header); + ++_M_impl._M_node_count; + return iterator(__z); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_insert_equal_lower_node(_Link_type __z) + { + _Link_type __x = _M_begin(); + _Base_ptr __y = _M_end(); + while (__x != 0) + { + __y = __x; + __x = !_M_impl._M_key_compare(_S_key(__x), _S_key(__z)) ? + _S_left(__x) : _S_right(__x); + } + return _M_insert_lower_node(__y, __z); + } + + template + template + pair::iterator, bool> + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_emplace_unique(_Args&&... __args) + { + _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); + + __try + { + typedef pair _Res; + auto __res = _M_get_insert_unique_pos(_S_key(__z)); + if (__res.second) + return _Res(_M_insert_node(__res.first, __res.second, __z), true); + + _M_drop_node(__z); + return _Res(iterator(__res.first), false); + } + __catch(...) + { + _M_drop_node(__z); + __throw_exception_again; + } + } + + template + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_emplace_equal(_Args&&... __args) + { + _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); + + __try + { + auto __res = _M_get_insert_equal_pos(_S_key(__z)); + return _M_insert_node(__res.first, __res.second, __z); + } + __catch(...) + { + _M_drop_node(__z); + __throw_exception_again; + } + } + + template + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_emplace_hint_unique(const_iterator __pos, _Args&&... __args) + { + _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); + + __try + { + auto __res = _M_get_insert_hint_unique_pos(__pos, _S_key(__z)); + + if (__res.second) + return _M_insert_node(__res.first, __res.second, __z); + + _M_drop_node(__z); + return iterator(__res.first); + } + __catch(...) + { + _M_drop_node(__z); + __throw_exception_again; + } + } + + template + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_emplace_hint_equal(const_iterator __pos, _Args&&... __args) + { + _Link_type __z = _M_create_node(std::forward<_Args>(__args)...); + + __try + { + auto __res = _M_get_insert_hint_equal_pos(__pos, _S_key(__z)); + + if (__res.second) + return _M_insert_node(__res.first, __res.second, __z); + + return _M_insert_equal_lower_node(__z); + } + __catch(...) + { + _M_drop_node(__z); + __throw_exception_again; + } + } +#endif + + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_erase_aux(const_iterator __position) + { + _Link_type __y = + static_cast<_Link_type>(_Rb_tree_rebalance_for_erase + (const_cast<_Base_ptr>(__position._M_node), + this->_M_impl._M_header)); + _M_drop_node(__y); + --_M_impl._M_node_count; + } + + template + void + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + _M_erase_aux(const_iterator __first, const_iterator __last) + { + if (__first == begin() && __last == end()) + clear(); + else + while (__first != __last) + _M_erase_aux(__first++); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + erase(const _Key& __x) + { + pair __p = equal_range(__x); + const size_type __old_size = size(); + _M_erase_aux(__p.first, __p.second); + return __old_size - size(); + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + find(const _Key& __k) + { + iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k); + return (__j == end() + || _M_impl._M_key_compare(__k, + _S_key(__j._M_node))) ? end() : __j; + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, + _Compare, _Alloc>::const_iterator + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + find(const _Key& __k) const + { + const_iterator __j = _M_lower_bound(_M_begin(), _M_end(), __k); + return (__j == end() + || _M_impl._M_key_compare(__k, + _S_key(__j._M_node))) ? end() : __j; + } + + template + typename _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>::size_type + _Rb_tree<_Key, _Val, _KeyOfValue, _Compare, _Alloc>:: + count(const _Key& __k) const + { + pair __p = equal_range(__k); + const size_type __n = std::distance(__p.first, __p.second); + return __n; + } + + _GLIBCXX_PURE unsigned int + _Rb_tree_black_count(const _Rb_tree_node_base* __node, + const _Rb_tree_node_base* __root) throw (); + + template + bool + _Rb_tree<_Key,_Val,_KeyOfValue,_Compare,_Alloc>::__rb_verify() const + { + if (_M_impl._M_node_count == 0 || begin() == end()) + return _M_impl._M_node_count == 0 && begin() == end() + && this->_M_impl._M_header._M_left == _M_end() + && this->_M_impl._M_header._M_right == _M_end(); + + unsigned int __len = _Rb_tree_black_count(_M_leftmost(), _M_root()); + for (const_iterator __it = begin(); __it != end(); ++__it) + { + _Const_Link_type __x = static_cast<_Const_Link_type>(__it._M_node); + _Const_Link_type __L = _S_left(__x); + _Const_Link_type __R = _S_right(__x); + + if (__x->_M_color == _S_red) + if ((__L && __L->_M_color == _S_red) + || (__R && __R->_M_color == _S_red)) + return false; + + if (__L && _M_impl._M_key_compare(_S_key(__x), _S_key(__L))) + return false; + if (__R && _M_impl._M_key_compare(_S_key(__R), _S_key(__x))) + return false; + + if (!__L && !__R && _Rb_tree_black_count(__x, _M_root()) != __len) + return false; + } + + if (_M_leftmost() != _Rb_tree_node_base::_S_minimum(_M_root())) + return false; + if (_M_rightmost() != _Rb_tree_node_base::_S_maximum(_M_root())) + return false; + return true; + } + +#if __cplusplus > 201402L + // Allow access to internals of compatible _Rb_tree specializations. + template + struct _Rb_tree_merge_helper<_Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>, + _Cmp2> + { + private: + friend class _Rb_tree<_Key, _Val, _Sel, _Cmp1, _Alloc>; + + static auto& + _S_get_impl(_Rb_tree<_Key, _Val, _Sel, _Cmp2, _Alloc>& __tree) + { return __tree._M_impl; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h b/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h new file mode 100644 index 000000000..3109a8946 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_uninitialized.h @@ -0,0 +1,1041 @@ +// Raw memory manipulators -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_uninitialized.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _STL_UNINITIALIZED_H +#define _STL_UNINITIALIZED_H 1 + +#if __cplusplus > 201402L +#include +#endif + +#if __cplusplus >= 201103L +#include +#endif + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @addtogroup memory + * @{ + */ + + /// @cond undocumented + + template + struct __uninitialized_copy + { + template + static _ForwardIterator + __uninit_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + _ForwardIterator __cur = __result; + __try + { + for (; __first != __last; ++__first, (void)++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_copy + { + template + static _ForwardIterator + __uninit_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { return std::copy(__first, __last, __result); } + }; + + /// @endcond + + /** + * @brief Copies the range [first,last) into result. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return __result + (__first - __last) + * + * Like copy(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_copy(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + typedef typename iterator_traits<_InputIterator>::value_type + _ValueType1; + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType2; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // Trivial types can have deleted copy constructor, but the std::copy + // optimization that uses memmove would happily "copy" them anyway. + static_assert(is_constructible<_ValueType2, decltype(*__first)>::value, + "result type must be constructible from value type of input range"); + + typedef typename iterator_traits<_InputIterator>::reference _RefType1; + typedef typename iterator_traits<_ForwardIterator>::reference _RefType2; + // Trivial types can have deleted assignment, so using std::copy + // would be ill-formed. Require assignability before using std::copy: + const bool __assignable = is_assignable<_RefType2, _RefType1>::value; +#endif + + return std::__uninitialized_copy<__is_trivial(_ValueType1) + && __is_trivial(_ValueType2) + && __assignable>:: + __uninit_copy(__first, __last, __result); + } + + /// @cond undocumented + + template + struct __uninitialized_fill + { + template + static void + __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct(std::__addressof(*__cur), __x); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_fill + { + template + static void + __uninit_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { std::fill(__first, __last, __x); } + }; + + /// @endcond + + /** + * @brief Copies the value x into the range [first,last). + * @param __first An input iterator. + * @param __last An input iterator. + * @param __x The source value. + * @return Nothing. + * + * Like fill(), but does not require an initialized output range. + */ + template + inline void + uninitialized_fill(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // Trivial types can have deleted copy constructor, but the std::fill + // optimization that uses memmove would happily "copy" them anyway. + static_assert(is_constructible<_ValueType, const _Tp&>::value, + "result type must be constructible from input type"); + + // Trivial types can have deleted assignment, so using std::fill + // would be ill-formed. Require assignability before using std::fill: + const bool __assignable = is_copy_assignable<_ValueType>::value; +#endif + + std::__uninitialized_fill<__is_trivial(_ValueType) && __assignable>:: + __uninit_fill(__first, __last, __x); + } + + /// @cond undocumented + + template + struct __uninitialized_fill_n + { + template + static _ForwardIterator + __uninit_fill_n(_ForwardIterator __first, _Size __n, + const _Tp& __x) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct(std::__addressof(*__cur), __x); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_fill_n + { + template + static _ForwardIterator + __uninit_fill_n(_ForwardIterator __first, _Size __n, + const _Tp& __x) + { return std::fill_n(__first, __n, __x); } + }; + + /// @endcond + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 1339. uninitialized_fill_n should return the end of its range + /** + * @brief Copies the value x into the range [first,first+n). + * @param __first An input iterator. + * @param __n The number of copies to make. + * @param __x The source value. + * @return Nothing. + * + * Like fill_n(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_fill_n(_ForwardIterator __first, _Size __n, const _Tp& __x) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; +#if __cplusplus < 201103L + const bool __assignable = true; +#else + // Trivial types can have deleted copy constructor, but the std::fill + // optimization that uses memmove would happily "copy" them anyway. + static_assert(is_constructible<_ValueType, const _Tp&>::value, + "result type must be constructible from input type"); + + // Trivial types can have deleted assignment, so using std::fill + // would be ill-formed. Require assignability before using std::fill: + const bool __assignable = is_copy_assignable<_ValueType>::value; +#endif + return __uninitialized_fill_n<__is_trivial(_ValueType) && __assignable>:: + __uninit_fill_n(__first, __n, __x); + } + + /// @cond undocumented + + // Extensions: versions of uninitialized_copy, uninitialized_fill, + // and uninitialized_fill_n that take an allocator parameter. + // We dispatch back to the standard versions when we're given the + // default allocator. For nondefault allocators we do not use + // any of the POD optimizations. + + template + _ForwardIterator + __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + { + _ForwardIterator __cur = __result; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __first != __last; ++__first, (void)++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_copy_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, allocator<_Tp>&) + { return std::uninitialized_copy(__first, __last, __result); } + + template + inline _ForwardIterator + __uninitialized_move_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + { + return std::__uninitialized_copy_a(_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), + __result, __alloc); + } + + template + inline _ForwardIterator + __uninitialized_move_if_noexcept_a(_InputIterator __first, + _InputIterator __last, + _ForwardIterator __result, + _Allocator& __alloc) + { + return std::__uninitialized_copy_a + (_GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(__last), __result, __alloc); + } + + template + void + __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x, _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __cur != __last; ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), __x); + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline void + __uninitialized_fill_a(_ForwardIterator __first, _ForwardIterator __last, + const _Tp& __x, allocator<_Tp2>&) + { std::uninitialized_fill(__first, __last, __x); } + + template + _ForwardIterator + __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, + const _Tp& __x, _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __n > 0; --__n, (void) ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur), __x); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_fill_n_a(_ForwardIterator __first, _Size __n, + const _Tp& __x, allocator<_Tp2>&) + { return std::uninitialized_fill_n(__first, __n, __x); } + + + // Extensions: __uninitialized_copy_move, __uninitialized_move_copy, + // __uninitialized_fill_move, __uninitialized_move_fill. + // All of these algorithms take a user-supplied allocator, which is used + // for construction and destruction. + + // __uninitialized_copy_move + // Copies [first1, last1) into [result, result + (last1 - first1)), and + // move [first2, last2) into + // [result, result + (last1 - first1) + (last2 - first2)). + template + inline _ForwardIterator + __uninitialized_copy_move(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _ForwardIterator __result, + _Allocator& __alloc) + { + _ForwardIterator __mid = std::__uninitialized_copy_a(__first1, __last1, + __result, + __alloc); + __try + { + return std::__uninitialized_move_a(__first2, __last2, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_move_copy + // Moves [first1, last1) into [result, result + (last1 - first1)), and + // copies [first2, last2) into + // [result, result + (last1 - first1) + (last2 - first2)). + template + inline _ForwardIterator + __uninitialized_move_copy(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2, + _ForwardIterator __result, + _Allocator& __alloc) + { + _ForwardIterator __mid = std::__uninitialized_move_a(__first1, __last1, + __result, + __alloc); + __try + { + return std::__uninitialized_copy_a(__first2, __last2, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_fill_move + // Fills [result, mid) with x, and moves [first, last) into + // [mid, mid + (last - first)). + template + inline _ForwardIterator + __uninitialized_fill_move(_ForwardIterator __result, _ForwardIterator __mid, + const _Tp& __x, _InputIterator __first, + _InputIterator __last, _Allocator& __alloc) + { + std::__uninitialized_fill_a(__result, __mid, __x, __alloc); + __try + { + return std::__uninitialized_move_a(__first, __last, __mid, __alloc); + } + __catch(...) + { + std::_Destroy(__result, __mid, __alloc); + __throw_exception_again; + } + } + + // __uninitialized_move_fill + // Moves [first1, last1) into [first2, first2 + (last1 - first1)), and + // fills [first2 + (last1 - first1), last2) with x. + template + inline void + __uninitialized_move_fill(_InputIterator __first1, _InputIterator __last1, + _ForwardIterator __first2, + _ForwardIterator __last2, const _Tp& __x, + _Allocator& __alloc) + { + _ForwardIterator __mid2 = std::__uninitialized_move_a(__first1, __last1, + __first2, + __alloc); + __try + { + std::__uninitialized_fill_a(__mid2, __last2, __x, __alloc); + } + __catch(...) + { + std::_Destroy(__first2, __mid2, __alloc); + __throw_exception_again; + } + } + + /// @endcond + +#if __cplusplus >= 201103L + /// @cond undocumented + + // Extensions: __uninitialized_default, __uninitialized_default_n, + // __uninitialized_default_a, __uninitialized_default_n_a. + + template + struct __uninitialized_default_1 + { + template + static void + __uninit_default(_ForwardIterator __first, _ForwardIterator __last) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct(std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_1 + { + template + static void + __uninit_default(_ForwardIterator __first, _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + std::fill(__first, __last, _ValueType()); + } + }; + + template + struct __uninitialized_default_n_1 + { + template + static _ForwardIterator + __uninit_default_n(_ForwardIterator __first, _Size __n) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_n_1 + { + template + static _ForwardIterator + __uninit_default_n(_ForwardIterator __first, _Size __n) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + return std::fill_n(__first, __n, _ValueType()); + } + }; + + // __uninitialized_default + // Fills [first, last) with std::distance(first, last) default + // constructed value_types(s). + template + inline void + __uninitialized_default(_ForwardIterator __first, + _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; + + std::__uninitialized_default_1<__is_trivial(_ValueType) + && __assignable>:: + __uninit_default(__first, __last); + } + + // __uninitialized_default_n + // Fills [first, first + n) with n default constructed value_type(s). + template + inline _ForwardIterator + __uninitialized_default_n(_ForwardIterator __first, _Size __n) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + // trivial types can have deleted assignment + const bool __assignable = is_copy_assignable<_ValueType>::value; + + return __uninitialized_default_n_1<__is_trivial(_ValueType) + && __assignable>:: + __uninit_default_n(__first, __n); + } + + + // __uninitialized_default_a + // Fills [first, last) with std::distance(first, last) default + // constructed value_types(s), constructed with the allocator alloc. + template + void + __uninitialized_default_a(_ForwardIterator __first, + _ForwardIterator __last, + _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __cur != __last; ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline void + __uninitialized_default_a(_ForwardIterator __first, + _ForwardIterator __last, + allocator<_Tp>&) + { std::__uninitialized_default(__first, __last); } + + + // __uninitialized_default_n_a + // Fills [first, first + n) with n default constructed value_types(s), + // constructed with the allocator alloc. + template + _ForwardIterator + __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, + _Allocator& __alloc) + { + _ForwardIterator __cur = __first; + __try + { + typedef __gnu_cxx::__alloc_traits<_Allocator> __traits; + for (; __n > 0; --__n, (void) ++__cur) + __traits::construct(__alloc, std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_default_n_a(_ForwardIterator __first, _Size __n, + allocator<_Tp>&) + { return std::__uninitialized_default_n(__first, __n); } + + template + struct __uninitialized_default_novalue_1 + { + template + static void + __uninit_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + _ForwardIterator __cur = __first; + __try + { + for (; __cur != __last; ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_novalue_1 + { + template + static void + __uninit_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + } + }; + + template + struct __uninitialized_default_novalue_n_1 + { + template + static _ForwardIterator + __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) + { + _ForwardIterator __cur = __first; + __try + { + for (; __n > 0; --__n, (void) ++__cur) + std::_Construct_novalue(std::__addressof(*__cur)); + return __cur; + } + __catch(...) + { + std::_Destroy(__first, __cur); + __throw_exception_again; + } + } + }; + + template<> + struct __uninitialized_default_novalue_n_1 + { + template + static _ForwardIterator + __uninit_default_novalue_n(_ForwardIterator __first, _Size __n) + { return std::next(__first, __n); } + }; + + // __uninitialized_default_novalue + // Fills [first, last) with std::distance(first, last) default-initialized + // value_types(s). + template + inline void + __uninitialized_default_novalue(_ForwardIterator __first, + _ForwardIterator __last) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + std::__uninitialized_default_novalue_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue(__first, __last); + } + + // __uninitialized_default_n + // Fills [first, first + n) with n default-initialized value_type(s). + template + inline _ForwardIterator + __uninitialized_default_novalue_n(_ForwardIterator __first, _Size __n) + { + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType; + + return __uninitialized_default_novalue_n_1< + is_trivially_default_constructible<_ValueType>::value>:: + __uninit_default_novalue_n(__first, __n); + } + + template + _ForwardIterator + __uninitialized_copy_n(_InputIterator __first, _Size __n, + _ForwardIterator __result, input_iterator_tag) + { + _ForwardIterator __cur = __result; + __try + { + for (; __n > 0; --__n, (void) ++__first, ++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return __cur; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + inline _ForwardIterator + __uninitialized_copy_n(_RandomAccessIterator __first, _Size __n, + _ForwardIterator __result, + random_access_iterator_tag) + { return std::uninitialized_copy(__first, __first + __n, __result); } + + template + pair<_InputIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result, input_iterator_tag) + { + _ForwardIterator __cur = __result; + __try + { + for (; __n > 0; --__n, (void) ++__first, ++__cur) + std::_Construct(std::__addressof(*__cur), *__first); + return {__first, __cur}; + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + inline pair<_RandomAccessIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_RandomAccessIterator __first, _Size __n, + _ForwardIterator __result, + random_access_iterator_tag) + { + auto __second_res = uninitialized_copy(__first, __first + __n, __result); + auto __first_res = std::next(__first, __n); + return {__first_res, __second_res}; + } + + /// @endcond + + /** + * @brief Copies the range [first,first+n) into result. + * @param __first An input iterator. + * @param __n The number of elements to copy. + * @param __result An output iterator. + * @return __result + __n + * + * Like copy_n(), but does not require an initialized output range. + */ + template + inline _ForwardIterator + uninitialized_copy_n(_InputIterator __first, _Size __n, + _ForwardIterator __result) + { return std::__uninitialized_copy_n(__first, __n, __result, + std::__iterator_category(__first)); } + + /// @cond undocumented + template + inline pair<_InputIterator, _ForwardIterator> + __uninitialized_copy_n_pair(_InputIterator __first, _Size __n, + _ForwardIterator __result) + { + return + std::__uninitialized_copy_n_pair(__first, __n, __result, + std::__iterator_category(__first)); + } + /// @endcond +#endif + +#if __cplusplus >= 201703L +# define __cpp_lib_raw_memory_algorithms 201606L + + /** + * @brief Default-initializes objects in the range [first,last). + * @param __first A forward iterator. + * @param __last A forward iterator. + */ + template + inline void + uninitialized_default_construct(_ForwardIterator __first, + _ForwardIterator __last) + { + __uninitialized_default_novalue(__first, __last); + } + + /** + * @brief Default-initializes objects in the range [first,first+count). + * @param __first A forward iterator. + * @param __count The number of objects to construct. + * @return __first + __count + */ + template + inline _ForwardIterator + uninitialized_default_construct_n(_ForwardIterator __first, _Size __count) + { + return __uninitialized_default_novalue_n(__first, __count); + } + + /** + * @brief Value-initializes objects in the range [first,last). + * @param __first A forward iterator. + * @param __last A forward iterator. + */ + template + inline void + uninitialized_value_construct(_ForwardIterator __first, + _ForwardIterator __last) + { + return __uninitialized_default(__first, __last); + } + + /** + * @brief Value-initializes objects in the range [first,first+count). + * @param __first A forward iterator. + * @param __count The number of objects to construct. + * @return __result + __count + */ + template + inline _ForwardIterator + uninitialized_value_construct_n(_ForwardIterator __first, _Size __count) + { + return __uninitialized_default_n(__first, __count); + } + + /** + * @brief Move-construct from the range [first,last) into result. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __result An output iterator. + * @return __result + (__first - __last) + */ + template + inline _ForwardIterator + uninitialized_move(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result) + { + return std::uninitialized_copy + (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + _GLIBCXX_MAKE_MOVE_ITERATOR(__last), __result); + } + + /** + * @brief Move-construct from the range [first,first+count) into result. + * @param __first An input iterator. + * @param __count The number of objects to initialize. + * @param __result An output iterator. + * @return __result + __count + */ + template + inline pair<_InputIterator, _ForwardIterator> + uninitialized_move_n(_InputIterator __first, _Size __count, + _ForwardIterator __result) + { + auto __res = std::__uninitialized_copy_n_pair + (_GLIBCXX_MAKE_MOVE_ITERATOR(__first), + __count, __result); + return {__res.first.base(), __res.second}; + } +#endif // C++17 + +#if __cplusplus >= 201103L + /// @cond undocumented + + template + inline void + __relocate_object_a(_Tp* __restrict __dest, _Up* __restrict __orig, + _Allocator& __alloc) + noexcept(noexcept(std::allocator_traits<_Allocator>::construct(__alloc, + __dest, std::move(*__orig))) + && noexcept(std::allocator_traits<_Allocator>::destroy( + __alloc, std::__addressof(*__orig)))) + { + typedef std::allocator_traits<_Allocator> __traits; + __traits::construct(__alloc, __dest, std::move(*__orig)); + __traits::destroy(__alloc, std::__addressof(*__orig)); + } + + // This class may be specialized for specific types. + // Also known as is_trivially_relocatable. + template + struct __is_bitwise_relocatable + : is_trivial<_Tp> { }; + + template + inline __enable_if_t::value, _Tp*> + __relocate_a_1(_Tp* __first, _Tp* __last, + _Tp* __result, allocator<_Up>&) noexcept + { + ptrdiff_t __count = __last - __first; + if (__count > 0) + __builtin_memmove(__result, __first, __count * sizeof(_Tp)); + return __result + __count; + } + + template + inline _ForwardIterator + __relocate_a_1(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + noexcept(noexcept(std::__relocate_object_a(std::addressof(*__result), + std::addressof(*__first), + __alloc))) + { + typedef typename iterator_traits<_InputIterator>::value_type + _ValueType; + typedef typename iterator_traits<_ForwardIterator>::value_type + _ValueType2; + static_assert(std::is_same<_ValueType, _ValueType2>::value, + "relocation is only possible for values of the same type"); + _ForwardIterator __cur = __result; + for (; __first != __last; ++__first, (void)++__cur) + std::__relocate_object_a(std::__addressof(*__cur), + std::__addressof(*__first), __alloc); + return __cur; + } + + template + inline _ForwardIterator + __relocate_a(_InputIterator __first, _InputIterator __last, + _ForwardIterator __result, _Allocator& __alloc) + noexcept(noexcept(__relocate_a_1(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result), __alloc))) + { + return __relocate_a_1(std::__niter_base(__first), + std::__niter_base(__last), + std::__niter_base(__result), __alloc); + } + + /// @endcond +#endif + + // @} group memory + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _STL_UNINITIALIZED_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/stl_vector.h b/resources/sources/avr-libstdcpp/include/bits/stl_vector.h new file mode 100644 index 000000000..d3f1b1fae --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/stl_vector.h @@ -0,0 +1,1985 @@ +// Vector implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/stl_vector.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{vector} + */ + +#ifndef _STL_VECTOR_H +#define _STL_VECTOR_H 1 + +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif +#if __cplusplus > 201703L +# include +#endif + +#include + +#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR +extern "C" void +__sanitizer_annotate_contiguous_container(const void*, const void*, + const void*, const void*); +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /// See bits/stl_deque.h's _Deque_base for an explanation. + template + struct _Vector_base + { + typedef typename __gnu_cxx::__alloc_traits<_Alloc>::template + rebind<_Tp>::other _Tp_alloc_type; + typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type>::pointer + pointer; + + struct _Vector_impl_data + { + pointer _M_start; + pointer _M_finish; + pointer _M_end_of_storage; + + _Vector_impl_data() _GLIBCXX_NOEXCEPT + : _M_start(), _M_finish(), _M_end_of_storage() + { } + +#if __cplusplus >= 201103L + _Vector_impl_data(_Vector_impl_data&& __x) noexcept + : _M_start(__x._M_start), _M_finish(__x._M_finish), + _M_end_of_storage(__x._M_end_of_storage) + { __x._M_start = __x._M_finish = __x._M_end_of_storage = pointer(); } +#endif + + void + _M_copy_data(_Vector_impl_data const& __x) _GLIBCXX_NOEXCEPT + { + _M_start = __x._M_start; + _M_finish = __x._M_finish; + _M_end_of_storage = __x._M_end_of_storage; + } + + void + _M_swap_data(_Vector_impl_data& __x) _GLIBCXX_NOEXCEPT + { + // Do not use std::swap(_M_start, __x._M_start), etc as it loses + // information used by TBAA. + _Vector_impl_data __tmp; + __tmp._M_copy_data(*this); + _M_copy_data(__x); + __x._M_copy_data(__tmp); + } + }; + + struct _Vector_impl + : public _Tp_alloc_type, public _Vector_impl_data + { + _Vector_impl() _GLIBCXX_NOEXCEPT_IF( + is_nothrow_default_constructible<_Tp_alloc_type>::value) + : _Tp_alloc_type() + { } + + _Vector_impl(_Tp_alloc_type const& __a) _GLIBCXX_NOEXCEPT + : _Tp_alloc_type(__a) + { } + +#if __cplusplus >= 201103L + // Not defaulted, to enforce noexcept(true) even when + // !is_nothrow_move_constructible<_Tp_alloc_type>. + _Vector_impl(_Vector_impl&& __x) noexcept + : _Tp_alloc_type(std::move(__x)), _Vector_impl_data(std::move(__x)) + { } + + _Vector_impl(_Tp_alloc_type&& __a) noexcept + : _Tp_alloc_type(std::move(__a)) + { } + + _Vector_impl(_Tp_alloc_type&& __a, _Vector_impl&& __rv) noexcept + : _Tp_alloc_type(std::move(__a)), _Vector_impl_data(std::move(__rv)) + { } +#endif + +#if _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR + template + struct _Asan + { + typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type> + ::size_type size_type; + + static void _S_shrink(_Vector_impl&, size_type) { } + static void _S_on_dealloc(_Vector_impl&) { } + + typedef _Vector_impl& _Reinit; + + struct _Grow + { + _Grow(_Vector_impl&, size_type) { } + void _M_grew(size_type) { } + }; + }; + + // Enable ASan annotations for memory obtained from std::allocator. + template + struct _Asan > + { + typedef typename __gnu_cxx::__alloc_traits<_Tp_alloc_type> + ::size_type size_type; + + // Adjust ASan annotation for [_M_start, _M_end_of_storage) to + // mark end of valid region as __curr instead of __prev. + static void + _S_adjust(_Vector_impl& __impl, pointer __prev, pointer __curr) + { + __sanitizer_annotate_contiguous_container(__impl._M_start, + __impl._M_end_of_storage, __prev, __curr); + } + + static void + _S_grow(_Vector_impl& __impl, size_type __n) + { _S_adjust(__impl, __impl._M_finish, __impl._M_finish + __n); } + + static void + _S_shrink(_Vector_impl& __impl, size_type __n) + { _S_adjust(__impl, __impl._M_finish + __n, __impl._M_finish); } + + static void + _S_on_dealloc(_Vector_impl& __impl) + { + if (__impl._M_start) + _S_adjust(__impl, __impl._M_finish, __impl._M_end_of_storage); + } + + // Used on reallocation to tell ASan unused capacity is invalid. + struct _Reinit + { + explicit _Reinit(_Vector_impl& __impl) : _M_impl(__impl) + { + // Mark unused capacity as valid again before deallocating it. + _S_on_dealloc(_M_impl); + } + + ~_Reinit() + { + // Mark unused capacity as invalid after reallocation. + if (_M_impl._M_start) + _S_adjust(_M_impl, _M_impl._M_end_of_storage, + _M_impl._M_finish); + } + + _Vector_impl& _M_impl; + +#if __cplusplus >= 201103L + _Reinit(const _Reinit&) = delete; + _Reinit& operator=(const _Reinit&) = delete; +#endif + }; + + // Tell ASan when unused capacity is initialized to be valid. + struct _Grow + { + _Grow(_Vector_impl& __impl, size_type __n) + : _M_impl(__impl), _M_n(__n) + { _S_grow(_M_impl, __n); } + + ~_Grow() { if (_M_n) _S_shrink(_M_impl, _M_n); } + + void _M_grew(size_type __n) { _M_n -= __n; } + +#if __cplusplus >= 201103L + _Grow(const _Grow&) = delete; + _Grow& operator=(const _Grow&) = delete; +#endif + private: + _Vector_impl& _M_impl; + size_type _M_n; + }; + }; + +#define _GLIBCXX_ASAN_ANNOTATE_REINIT \ + typename _Base::_Vector_impl::template _Asan<>::_Reinit const \ + __attribute__((__unused__)) __reinit_guard(this->_M_impl) +#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) \ + typename _Base::_Vector_impl::template _Asan<>::_Grow \ + __attribute__((__unused__)) __grow_guard(this->_M_impl, (n)) +#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) __grow_guard._M_grew(n) +#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) \ + _Base::_Vector_impl::template _Asan<>::_S_shrink(this->_M_impl, n) +#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC \ + _Base::_Vector_impl::template _Asan<>::_S_on_dealloc(this->_M_impl) +#else // ! (_GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR) +#define _GLIBCXX_ASAN_ANNOTATE_REINIT +#define _GLIBCXX_ASAN_ANNOTATE_GROW(n) +#define _GLIBCXX_ASAN_ANNOTATE_GREW(n) +#define _GLIBCXX_ASAN_ANNOTATE_SHRINK(n) +#define _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC +#endif // _GLIBCXX_SANITIZE_STD_ALLOCATOR && _GLIBCXX_SANITIZE_VECTOR + }; + + public: + typedef _Alloc allocator_type; + + _Tp_alloc_type& + _M_get_Tp_allocator() _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + const _Tp_alloc_type& + _M_get_Tp_allocator() const _GLIBCXX_NOEXCEPT + { return this->_M_impl; } + + allocator_type + get_allocator() const _GLIBCXX_NOEXCEPT + { return allocator_type(_M_get_Tp_allocator()); } + +#if __cplusplus >= 201103L + _Vector_base() = default; +#else + _Vector_base() { } +#endif + + _Vector_base(const allocator_type& __a) _GLIBCXX_NOEXCEPT + : _M_impl(__a) { } + + // Kept for ABI compatibility. +#if !_GLIBCXX_INLINE_VERSION + _Vector_base(size_t __n) + : _M_impl() + { _M_create_storage(__n); } +#endif + + _Vector_base(size_t __n, const allocator_type& __a) + : _M_impl(__a) + { _M_create_storage(__n); } + +#if __cplusplus >= 201103L + _Vector_base(_Vector_base&&) = default; + + // Kept for ABI compatibility. +# if !_GLIBCXX_INLINE_VERSION + _Vector_base(_Tp_alloc_type&& __a) noexcept + : _M_impl(std::move(__a)) { } + + _Vector_base(_Vector_base&& __x, const allocator_type& __a) + : _M_impl(__a) + { + if (__x.get_allocator() == __a) + this->_M_impl._M_swap_data(__x._M_impl); + else + { + size_t __n = __x._M_impl._M_finish - __x._M_impl._M_start; + _M_create_storage(__n); + } + } +# endif + + _Vector_base(const allocator_type& __a, _Vector_base&& __x) + : _M_impl(_Tp_alloc_type(__a), std::move(__x._M_impl)) + { } +#endif + + ~_Vector_base() _GLIBCXX_NOEXCEPT + { + _M_deallocate(_M_impl._M_start, + _M_impl._M_end_of_storage - _M_impl._M_start); + } + + public: + _Vector_impl _M_impl; + + pointer + _M_allocate(size_t __n) + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; + return __n != 0 ? _Tr::allocate(_M_impl, __n) : pointer(); + } + + void + _M_deallocate(pointer __p, size_t __n) + { + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Tr; + if (__p) + _Tr::deallocate(_M_impl, __p, __n); + } + + protected: + void + _M_create_storage(size_t __n) + { + this->_M_impl._M_start = this->_M_allocate(__n); + this->_M_impl._M_finish = this->_M_impl._M_start; + this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; + } + }; + + /** + * @brief A standard container which offers fixed time access to + * individual elements in any order. + * + * @ingroup sequences + * + * @tparam _Tp Type of element. + * @tparam _Alloc Allocator type, defaults to allocator<_Tp>. + * + * Meets the requirements of a container, a + * reversible container, and a + * sequence, including the + * optional sequence requirements with the + * %exception of @c push_front and @c pop_front. + * + * In some terminology a %vector can be described as a dynamic + * C-style array, it offers fast and efficient access to individual + * elements in any order and saves the user from worrying about + * memory and size allocation. Subscripting ( @c [] ) access is + * also provided as with C-style arrays. + */ + template > + class vector : protected _Vector_base<_Tp, _Alloc> + { +#ifdef _GLIBCXX_CONCEPT_CHECKS + // Concept requirements. + typedef typename _Alloc::value_type _Alloc_value_type; +# if __cplusplus < 201103L + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) +# endif + __glibcxx_class_requires2(_Tp, _Alloc_value_type, _SameTypeConcept) +#endif + +#if __cplusplus >= 201103L + static_assert(is_same::type, _Tp>::value, + "std::vector must have a non-const, non-volatile value_type"); +# if __cplusplus > 201703L || defined __STRICT_ANSI__ + static_assert(is_same::value, + "std::vector must have the same value_type as its allocator"); +# endif +#endif + + typedef _Vector_base<_Tp, _Alloc> _Base; + typedef typename _Base::_Tp_alloc_type _Tp_alloc_type; + typedef __gnu_cxx::__alloc_traits<_Tp_alloc_type> _Alloc_traits; + + public: + typedef _Tp value_type; + typedef typename _Base::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + typedef __gnu_cxx::__normal_iterator iterator; + typedef __gnu_cxx::__normal_iterator + const_iterator; + typedef std::reverse_iterator const_reverse_iterator; + typedef std::reverse_iterator reverse_iterator; + typedef size_t size_type; + typedef ptrdiff_t difference_type; + typedef _Alloc allocator_type; + + private: +#if __cplusplus >= 201103L + static constexpr bool + _S_nothrow_relocate(true_type) + { + return noexcept(std::__relocate_a(std::declval(), + std::declval(), + std::declval(), + std::declval<_Tp_alloc_type&>())); + } + + static constexpr bool + _S_nothrow_relocate(false_type) + { return false; } + + static constexpr bool + _S_use_relocate() + { + // Instantiating std::__relocate_a might cause an error outside the + // immediate context (in __relocate_object_a's noexcept-specifier), + // so only do it if we know the type can be move-inserted into *this. + return _S_nothrow_relocate(__is_move_insertable<_Tp_alloc_type>{}); + } + + static pointer + _S_do_relocate(pointer __first, pointer __last, pointer __result, + _Tp_alloc_type& __alloc, true_type) noexcept + { + return std::__relocate_a(__first, __last, __result, __alloc); + } + + static pointer + _S_do_relocate(pointer, pointer, pointer __result, + _Tp_alloc_type&, false_type) noexcept + { return __result; } + + static pointer + _S_relocate(pointer __first, pointer __last, pointer __result, + _Tp_alloc_type& __alloc) noexcept + { + using __do_it = __bool_constant<_S_use_relocate()>; + return _S_do_relocate(__first, __last, __result, __alloc, __do_it{}); + } +#endif // C++11 + + protected: + using _Base::_M_allocate; + using _Base::_M_deallocate; + using _Base::_M_impl; + using _Base::_M_get_Tp_allocator; + + public: + // [23.2.4.1] construct/copy/destroy + // (assign() and get_allocator() are also listed in this section) + + /** + * @brief Creates a %vector with no elements. + */ +#if __cplusplus >= 201103L + vector() = default; +#else + vector() { } +#endif + + /** + * @brief Creates a %vector with no elements. + * @param __a An allocator object. + */ + explicit + vector(const allocator_type& __a) _GLIBCXX_NOEXCEPT + : _Base(__a) { } + +#if __cplusplus >= 201103L + /** + * @brief Creates a %vector with default constructed elements. + * @param __n The number of elements to initially create. + * @param __a An allocator. + * + * This constructor fills the %vector with @a __n default + * constructed elements. + */ + explicit + vector(size_type __n, const allocator_type& __a = allocator_type()) + : _Base(_S_check_init_len(__n, __a), __a) + { _M_default_initialize(__n); } + + /** + * @brief Creates a %vector with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator. + * + * This constructor fills the %vector with @a __n copies of @a __value. + */ + vector(size_type __n, const value_type& __value, + const allocator_type& __a = allocator_type()) + : _Base(_S_check_init_len(__n, __a), __a) + { _M_fill_initialize(__n, __value); } +#else + /** + * @brief Creates a %vector with copies of an exemplar element. + * @param __n The number of elements to initially create. + * @param __value An element to copy. + * @param __a An allocator. + * + * This constructor fills the %vector with @a __n copies of @a __value. + */ + explicit + vector(size_type __n, const value_type& __value = value_type(), + const allocator_type& __a = allocator_type()) + : _Base(_S_check_init_len(__n, __a), __a) + { _M_fill_initialize(__n, __value); } +#endif + + /** + * @brief %Vector copy constructor. + * @param __x A %vector of identical element and allocator types. + * + * All the elements of @a __x are copied, but any unused capacity in + * @a __x will not be copied + * (i.e. capacity() == size() in the new %vector). + * + * The newly-created %vector uses a copy of the allocator object used + * by @a __x (unless the allocator traits dictate a different object). + */ + vector(const vector& __x) + : _Base(__x.size(), + _Alloc_traits::_S_select_on_copy(__x._M_get_Tp_allocator())) + { + this->_M_impl._M_finish = + std::__uninitialized_copy_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); + } + +#if __cplusplus >= 201103L + /** + * @brief %Vector move constructor. + * + * The newly-created %vector contains the exact contents of the + * moved instance. + * The contents of the moved instance are a valid, but unspecified + * %vector. + */ + vector(vector&&) noexcept = default; + + /// Copy constructor with alternative allocator + vector(const vector& __x, const allocator_type& __a) + : _Base(__x.size(), __a) + { + this->_M_impl._M_finish = + std::__uninitialized_copy_a(__x.begin(), __x.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); + } + + private: + vector(vector&& __rv, const allocator_type& __m, true_type) noexcept + : _Base(__m, std::move(__rv)) + { } + + vector(vector&& __rv, const allocator_type& __m, false_type) + : _Base(__m) + { + if (__rv.get_allocator() == __m) + this->_M_impl._M_swap_data(__rv._M_impl); + else if (!__rv.empty()) + { + this->_M_create_storage(__rv.size()); + this->_M_impl._M_finish = + std::__uninitialized_move_a(__rv.begin(), __rv.end(), + this->_M_impl._M_start, + _M_get_Tp_allocator()); + __rv.clear(); + } + } + + public: + /// Move constructor with alternative allocator + vector(vector&& __rv, const allocator_type& __m) + noexcept( noexcept( + vector(std::declval(), std::declval(), + std::declval())) ) + : vector(std::move(__rv), __m, typename _Alloc_traits::is_always_equal{}) + { } + + /** + * @brief Builds a %vector from an initializer list. + * @param __l An initializer_list. + * @param __a An allocator. + * + * Create a %vector consisting of copies of the elements in the + * initializer_list @a __l. + * + * This will call the element type's copy constructor N times + * (where N is @a __l.size()) and do no memory reallocation. + */ + vector(initializer_list __l, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_range_initialize(__l.begin(), __l.end(), + random_access_iterator_tag()); + } +#endif + + /** + * @brief Builds a %vector from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __a An allocator. + * + * Create a %vector consisting of copies of the elements from + * [first,last). + * + * If the iterators are forward, bidirectional, or + * random-access, then this will call the elements' copy + * constructor N times (where N is distance(first,last)) and do + * no memory reallocation. But if only input iterators are + * used, then this will do at most 2N calls to the copy + * constructor, and logN memory reallocations. + */ +#if __cplusplus >= 201103L + template> + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#else + template + vector(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_initialize_dispatch(__first, __last, _Integral()); + } +#endif + + /** + * The dtor only erases the elements, and note that if the + * elements themselves are pointers, the pointed-to memory is + * not touched in any way. Managing the pointer is the user's + * responsibility. + */ + ~vector() _GLIBCXX_NOEXCEPT + { + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_BEFORE_DEALLOC; + } + + /** + * @brief %Vector assignment operator. + * @param __x A %vector of identical element and allocator types. + * + * All the elements of @a __x are copied, but any unused capacity in + * @a __x will not be copied. + * + * Whether the allocator is copied depends on the allocator traits. + */ + vector& + operator=(const vector& __x); + +#if __cplusplus >= 201103L + /** + * @brief %Vector move assignment operator. + * @param __x A %vector of identical element and allocator types. + * + * The contents of @a __x are moved into this %vector (without copying, + * if the allocators permit it). + * Afterwards @a __x is a valid, but unspecified %vector. + * + * Whether the allocator is moved depends on the allocator traits. + */ + vector& + operator=(vector&& __x) noexcept(_Alloc_traits::_S_nothrow_move()) + { + constexpr bool __move_storage = + _Alloc_traits::_S_propagate_on_move_assign() + || _Alloc_traits::_S_always_equal(); + _M_move_assign(std::move(__x), __bool_constant<__move_storage>()); + return *this; + } + + /** + * @brief %Vector list assignment operator. + * @param __l An initializer_list. + * + * This function fills a %vector with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %vector and + * that the resulting %vector's size is the same as the number + * of elements assigned. + */ + vector& + operator=(initializer_list __l) + { + this->_M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); + return *this; + } +#endif + + /** + * @brief Assigns a given value to a %vector. + * @param __n Number of elements to be assigned. + * @param __val Value to be assigned. + * + * This function fills a %vector with @a __n copies of the given + * value. Note that the assignment completely changes the + * %vector and that the resulting %vector's size is the same as + * the number of elements assigned. + */ + void + assign(size_type __n, const value_type& __val) + { _M_fill_assign(__n, __val); } + + /** + * @brief Assigns a range to a %vector. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function fills a %vector with copies of the elements in the + * range [__first,__last). + * + * Note that the assignment completely changes the %vector and + * that the resulting %vector's size is the same as the number + * of elements assigned. + */ +#if __cplusplus >= 201103L + template> + void + assign(_InputIterator __first, _InputIterator __last) + { _M_assign_dispatch(__first, __last, __false_type()); } +#else + template + void + assign(_InputIterator __first, _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Assigns an initializer list to a %vector. + * @param __l An initializer_list. + * + * This function fills a %vector with copies of the elements in the + * initializer list @a __l. + * + * Note that the assignment completely changes the %vector and + * that the resulting %vector's size is the same as the number + * of elements assigned. + */ + void + assign(initializer_list __l) + { + this->_M_assign_aux(__l.begin(), __l.end(), + random_access_iterator_tag()); + } +#endif + + /// Get a copy of the memory allocation object. + using _Base::get_allocator; + + // iterators + /** + * Returns a read/write iterator that points to the first + * element in the %vector. Iteration is done in ordinary + * element order. + */ + iterator + begin() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_start); } + + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %vector. Iteration is done in ordinary + * element order. + */ + const_iterator + begin() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_start); } + + /** + * Returns a read/write iterator that points one past the last + * element in the %vector. Iteration is done in ordinary + * element order. + */ + iterator + end() _GLIBCXX_NOEXCEPT + { return iterator(this->_M_impl._M_finish); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %vector. Iteration is done in + * ordinary element order. + */ + const_iterator + end() const _GLIBCXX_NOEXCEPT + { return const_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read/write reverse iterator that points to the + * last element in the %vector. Iteration is done in reverse + * element order. + */ + reverse_iterator + rbegin() _GLIBCXX_NOEXCEPT + { return reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to the last element in the %vector. Iteration is done in + * reverse element order. + */ + const_reverse_iterator + rbegin() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(end()); } + + /** + * Returns a read/write reverse iterator that points to one + * before the first element in the %vector. Iteration is done + * in reverse element order. + */ + reverse_iterator + rend() _GLIBCXX_NOEXCEPT + { return reverse_iterator(begin()); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to one before the first element in the %vector. Iteration + * is done in reverse element order. + */ + const_reverse_iterator + rend() const _GLIBCXX_NOEXCEPT + { return const_reverse_iterator(begin()); } + +#if __cplusplus >= 201103L + /** + * Returns a read-only (constant) iterator that points to the + * first element in the %vector. Iteration is done in ordinary + * element order. + */ + const_iterator + cbegin() const noexcept + { return const_iterator(this->_M_impl._M_start); } + + /** + * Returns a read-only (constant) iterator that points one past + * the last element in the %vector. Iteration is done in + * ordinary element order. + */ + const_iterator + cend() const noexcept + { return const_iterator(this->_M_impl._M_finish); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to the last element in the %vector. Iteration is done in + * reverse element order. + */ + const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(end()); } + + /** + * Returns a read-only (constant) reverse iterator that points + * to one before the first element in the %vector. Iteration + * is done in reverse element order. + */ + const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(begin()); } +#endif + + // [23.2.4.2] capacity + /** Returns the number of elements in the %vector. */ + size_type + size() const _GLIBCXX_NOEXCEPT + { return size_type(this->_M_impl._M_finish - this->_M_impl._M_start); } + + /** Returns the size() of the largest possible %vector. */ + size_type + max_size() const _GLIBCXX_NOEXCEPT + { return _S_max_size(_M_get_Tp_allocator()); } + +#if __cplusplus >= 201103L + /** + * @brief Resizes the %vector to the specified number of elements. + * @param __new_size Number of elements the %vector should contain. + * + * This function will %resize the %vector to the specified + * number of elements. If the number is smaller than the + * %vector's current size the %vector is truncated, otherwise + * default constructed elements are appended. + */ + void + resize(size_type __new_size) + { + if (__new_size > size()) + _M_default_append(__new_size - size()); + else if (__new_size < size()) + _M_erase_at_end(this->_M_impl._M_start + __new_size); + } + + /** + * @brief Resizes the %vector to the specified number of elements. + * @param __new_size Number of elements the %vector should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %vector to the specified + * number of elements. If the number is smaller than the + * %vector's current size the %vector is truncated, otherwise + * the %vector is extended and new elements are populated with + * given data. + */ + void + resize(size_type __new_size, const value_type& __x) + { + if (__new_size > size()) + _M_fill_insert(end(), __new_size - size(), __x); + else if (__new_size < size()) + _M_erase_at_end(this->_M_impl._M_start + __new_size); + } +#else + /** + * @brief Resizes the %vector to the specified number of elements. + * @param __new_size Number of elements the %vector should contain. + * @param __x Data with which new elements should be populated. + * + * This function will %resize the %vector to the specified + * number of elements. If the number is smaller than the + * %vector's current size the %vector is truncated, otherwise + * the %vector is extended and new elements are populated with + * given data. + */ + void + resize(size_type __new_size, value_type __x = value_type()) + { + if (__new_size > size()) + _M_fill_insert(end(), __new_size - size(), __x); + else if (__new_size < size()) + _M_erase_at_end(this->_M_impl._M_start + __new_size); + } +#endif + +#if __cplusplus >= 201103L + /** A non-binding request to reduce capacity() to size(). */ + void + shrink_to_fit() + { _M_shrink_to_fit(); } +#endif + + /** + * Returns the total number of elements that the %vector can + * hold before needing to allocate more memory. + */ + size_type + capacity() const _GLIBCXX_NOEXCEPT + { return size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); } + + /** + * Returns true if the %vector is empty. (Thus begin() would + * equal end().) + */ + _GLIBCXX_NODISCARD bool + empty() const _GLIBCXX_NOEXCEPT + { return begin() == end(); } + + /** + * @brief Attempt to preallocate enough memory for specified number of + * elements. + * @param __n Number of elements required. + * @throw std::length_error If @a n exceeds @c max_size(). + * + * This function attempts to reserve enough memory for the + * %vector to hold the specified number of elements. If the + * number requested is more than max_size(), length_error is + * thrown. + * + * The advantage of this function is that if optimal code is a + * necessity and the user can determine the number of elements + * that will be required, the user can reserve the memory in + * %advance, and thus prevent a possible reallocation of memory + * and copying of %vector data. + */ + void + reserve(size_type __n); + + // element access + /** + * @brief Subscript access to the data contained in the %vector. + * @param __n The index of the element for which data should be + * accessed. + * @return Read/write reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and + * out_of_range lookups are not defined. (For checked lookups + * see at().) + */ + reference + operator[](size_type __n) _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_subscript(__n); + return *(this->_M_impl._M_start + __n); + } + + /** + * @brief Subscript access to the data contained in the %vector. + * @param __n The index of the element for which data should be + * accessed. + * @return Read-only (constant) reference to data. + * + * This operator allows for easy, array-style, data access. + * Note that data access with this operator is unchecked and + * out_of_range lookups are not defined. (For checked lookups + * see at().) + */ + const_reference + operator[](size_type __n) const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_subscript(__n); + return *(this->_M_impl._M_start + __n); + } + + protected: + /// Safety check used only from at(). + void + _M_range_check(size_type __n) const + { + if (__n >= this->size()) + __throw_out_of_range_fmt(__N("vector::_M_range_check: __n " + "(which is %zu) >= this->size() " + "(which is %zu)"), + __n, this->size()); + } + + public: + /** + * @brief Provides access to the data contained in the %vector. + * @param __n The index of the element for which data should be + * accessed. + * @return Read/write reference to data. + * @throw std::out_of_range If @a __n is an invalid index. + * + * This function provides for safer data access. The parameter + * is first checked that it is in the range of the vector. The + * function throws out_of_range if the check fails. + */ + reference + at(size_type __n) + { + _M_range_check(__n); + return (*this)[__n]; + } + + /** + * @brief Provides access to the data contained in the %vector. + * @param __n The index of the element for which data should be + * accessed. + * @return Read-only (constant) reference to data. + * @throw std::out_of_range If @a __n is an invalid index. + * + * This function provides for safer data access. The parameter + * is first checked that it is in the range of the vector. The + * function throws out_of_range if the check fails. + */ + const_reference + at(size_type __n) const + { + _M_range_check(__n); + return (*this)[__n]; + } + + /** + * Returns a read/write reference to the data at the first + * element of the %vector. + */ + reference + front() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *begin(); + } + + /** + * Returns a read-only (constant) reference to the data at the first + * element of the %vector. + */ + const_reference + front() const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *begin(); + } + + /** + * Returns a read/write reference to the data at the last + * element of the %vector. + */ + reference + back() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *(end() - 1); + } + + /** + * Returns a read-only (constant) reference to the data at the + * last element of the %vector. + */ + const_reference + back() const _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + return *(end() - 1); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 464. Suggestion for new member functions in standard containers. + // data access + /** + * Returns a pointer such that [data(), data() + size()) is a valid + * range. For a non-empty %vector, data() == &front(). + */ + _Tp* + data() _GLIBCXX_NOEXCEPT + { return _M_data_ptr(this->_M_impl._M_start); } + + const _Tp* + data() const _GLIBCXX_NOEXCEPT + { return _M_data_ptr(this->_M_impl._M_start); } + + // [23.2.4.3] modifiers + /** + * @brief Add data to the end of the %vector. + * @param __x Data to be added. + * + * This is a typical stack operation. The function creates an + * element at the end of the %vector and assigns the given data + * to it. Due to the nature of a %vector this operation can be + * done in constant time if the %vector has preallocated space + * available. + */ + void + push_back(const value_type& __x) + { + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + __x); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + _M_realloc_insert(end(), __x); + } + +#if __cplusplus >= 201103L + void + push_back(value_type&& __x) + { emplace_back(std::move(__x)); } + + template +#if __cplusplus > 201402L + reference +#else + void +#endif + emplace_back(_Args&&... __args); +#endif + + /** + * @brief Removes last element. + * + * This is a typical stack operation. It shrinks the %vector by one. + * + * Note that no data is returned, and if the last element's + * data is needed, it should be retrieved before pop_back() is + * called. + */ + void + pop_back() _GLIBCXX_NOEXCEPT + { + __glibcxx_requires_nonempty(); + --this->_M_impl._M_finish; + _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); + _GLIBCXX_ASAN_ANNOTATE_SHRINK(1); + } + +#if __cplusplus >= 201103L + /** + * @brief Inserts an object in %vector before specified iterator. + * @param __position A const_iterator into the %vector. + * @param __args Arguments. + * @return An iterator that points to the inserted data. + * + * This function will insert an object of type T constructed + * with T(std::forward(args)...) before the specified location. + * Note that this kind of operation could be expensive for a %vector + * and if it is frequently used the user should consider using + * std::list. + */ + template + iterator + emplace(const_iterator __position, _Args&&... __args) + { return _M_emplace_aux(__position, std::forward<_Args>(__args)...); } + + /** + * @brief Inserts given value into %vector before specified iterator. + * @param __position A const_iterator into the %vector. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before + * the specified location. Note that this kind of operation + * could be expensive for a %vector and if it is frequently + * used the user should consider using std::list. + */ + iterator + insert(const_iterator __position, const value_type& __x); +#else + /** + * @brief Inserts given value into %vector before specified iterator. + * @param __position An iterator into the %vector. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given value before + * the specified location. Note that this kind of operation + * could be expensive for a %vector and if it is frequently + * used the user should consider using std::list. + */ + iterator + insert(iterator __position, const value_type& __x); +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts given rvalue into %vector before specified iterator. + * @param __position A const_iterator into the %vector. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a copy of the given rvalue before + * the specified location. Note that this kind of operation + * could be expensive for a %vector and if it is frequently + * used the user should consider using std::list. + */ + iterator + insert(const_iterator __position, value_type&& __x) + { return _M_insert_rval(__position, std::move(__x)); } + + /** + * @brief Inserts an initializer_list into the %vector. + * @param __position An iterator into the %vector. + * @param __l An initializer_list. + * + * This function will insert copies of the data in the + * initializer_list @a l into the %vector before the location + * specified by @a position. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + iterator + insert(const_iterator __position, initializer_list __l) + { + auto __offset = __position - cbegin(); + _M_range_insert(begin() + __offset, __l.begin(), __l.end(), + std::random_access_iterator_tag()); + return begin() + __offset; + } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a number of copies of given data into the %vector. + * @param __position A const_iterator into the %vector. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * @return An iterator that points to the inserted data. + * + * This function will insert a specified number of copies of + * the given data before the location specified by @a position. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + iterator + insert(const_iterator __position, size_type __n, const value_type& __x) + { + difference_type __offset = __position - cbegin(); + _M_fill_insert(begin() + __offset, __n, __x); + return begin() + __offset; + } +#else + /** + * @brief Inserts a number of copies of given data into the %vector. + * @param __position An iterator into the %vector. + * @param __n Number of elements to be inserted. + * @param __x Data to be inserted. + * + * This function will insert a specified number of copies of + * the given data before the location specified by @a position. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + void + insert(iterator __position, size_type __n, const value_type& __x) + { _M_fill_insert(__position, __n, __x); } +#endif + +#if __cplusplus >= 201103L + /** + * @brief Inserts a range into the %vector. + * @param __position A const_iterator into the %vector. + * @param __first An input iterator. + * @param __last An input iterator. + * @return An iterator that points to the inserted data. + * + * This function will insert copies of the data in the range + * [__first,__last) into the %vector before the location specified + * by @a pos. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + template> + iterator + insert(const_iterator __position, _InputIterator __first, + _InputIterator __last) + { + difference_type __offset = __position - cbegin(); + _M_insert_dispatch(begin() + __offset, + __first, __last, __false_type()); + return begin() + __offset; + } +#else + /** + * @brief Inserts a range into the %vector. + * @param __position An iterator into the %vector. + * @param __first An input iterator. + * @param __last An input iterator. + * + * This function will insert copies of the data in the range + * [__first,__last) into the %vector before the location specified + * by @a pos. + * + * Note that this kind of operation could be expensive for a + * %vector and if it is frequently used the user should + * consider using std::list. + */ + template + void + insert(iterator __position, _InputIterator __first, + _InputIterator __last) + { + // Check whether it's an integral type. If so, it's not an iterator. + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_insert_dispatch(__position, __first, __last, _Integral()); + } +#endif + + /** + * @brief Remove element at given position. + * @param __position Iterator pointing to element to be erased. + * @return An iterator pointing to the next element (or end()). + * + * This function will erase the element at the given position and thus + * shorten the %vector by one. + * + * Note This operation could be expensive and if it is + * frequently used the user should consider using std::list. + * The user is also cautioned that this function only erases + * the element, and that if the element is itself a pointer, + * the pointed-to memory is not touched in any way. Managing + * the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __position) + { return _M_erase(begin() + (__position - cbegin())); } +#else + erase(iterator __position) + { return _M_erase(__position); } +#endif + + /** + * @brief Remove a range of elements. + * @param __first Iterator pointing to the first element to be erased. + * @param __last Iterator pointing to one past the last element to be + * erased. + * @return An iterator pointing to the element pointed to by @a __last + * prior to erasing (or end()). + * + * This function will erase the elements in the range + * [__first,__last) and shorten the %vector accordingly. + * + * Note This operation could be expensive and if it is + * frequently used the user should consider using std::list. + * The user is also cautioned that this function only erases + * the elements, and that if the elements themselves are + * pointers, the pointed-to memory is not touched in any way. + * Managing the pointer is the user's responsibility. + */ + iterator +#if __cplusplus >= 201103L + erase(const_iterator __first, const_iterator __last) + { + const auto __beg = begin(); + const auto __cbeg = cbegin(); + return _M_erase(__beg + (__first - __cbeg), __beg + (__last - __cbeg)); + } +#else + erase(iterator __first, iterator __last) + { return _M_erase(__first, __last); } +#endif + + /** + * @brief Swaps data with another %vector. + * @param __x A %vector of the same element and allocator types. + * + * This exchanges the elements between two vectors in constant time. + * (Three pointers, so it should be quite fast.) + * Note that the global std::swap() function is specialized such that + * std::swap(v1,v2) will feed to this function. + * + * Whether the allocators are swapped depends on the allocator traits. + */ + void + swap(vector& __x) _GLIBCXX_NOEXCEPT + { +#if __cplusplus >= 201103L + __glibcxx_assert(_Alloc_traits::propagate_on_container_swap::value + || _M_get_Tp_allocator() == __x._M_get_Tp_allocator()); +#endif + this->_M_impl._M_swap_data(__x._M_impl); + _Alloc_traits::_S_on_swap(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + } + + /** + * Erases all the elements. Note that this function only erases the + * elements, and that if the elements themselves are pointers, the + * pointed-to memory is not touched in any way. Managing the pointer is + * the user's responsibility. + */ + void + clear() _GLIBCXX_NOEXCEPT + { _M_erase_at_end(this->_M_impl._M_start); } + + protected: + /** + * Memory expansion handler. Uses the member allocation function to + * obtain @a n bytes of memory, and then copies [first,last) into it. + */ + template + pointer + _M_allocate_and_copy(size_type __n, + _ForwardIterator __first, _ForwardIterator __last) + { + pointer __result = this->_M_allocate(__n); + __try + { + std::__uninitialized_copy_a(__first, __last, __result, + _M_get_Tp_allocator()); + return __result; + } + __catch(...) + { + _M_deallocate(__result, __n); + __throw_exception_again; + } + } + + + // Internal constructor functions follow. + + // Called by the range constructor to implement [23.1.1]/9 + +#if __cplusplus < 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_initialize_dispatch(_Integer __n, _Integer __value, __true_type) + { + this->_M_impl._M_start = _M_allocate(_S_check_init_len( + static_cast(__n), _M_get_Tp_allocator())); + this->_M_impl._M_end_of_storage = + this->_M_impl._M_start + static_cast(__n); + _M_fill_initialize(static_cast(__n), __value); + } + + // Called by the range constructor to implement [23.1.1]/9 + template + void + _M_initialize_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { + _M_range_initialize(__first, __last, + std::__iterator_category(__first)); + } +#endif + + // Called by the second initialize_dispatch above + template + void + _M_range_initialize(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + __try { + for (; __first != __last; ++__first) +#if __cplusplus >= 201103L + emplace_back(*__first); +#else + push_back(*__first); +#endif + } __catch(...) { + clear(); + __throw_exception_again; + } + } + + // Called by the second initialize_dispatch above + template + void + _M_range_initialize(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __n = std::distance(__first, __last); + this->_M_impl._M_start + = this->_M_allocate(_S_check_init_len(__n, _M_get_Tp_allocator())); + this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; + this->_M_impl._M_finish = + std::__uninitialized_copy_a(__first, __last, + this->_M_impl._M_start, + _M_get_Tp_allocator()); + } + + // Called by the first initialize_dispatch above and by the + // vector(n,value,a) constructor. + void + _M_fill_initialize(size_type __n, const value_type& __value) + { + this->_M_impl._M_finish = + std::__uninitialized_fill_n_a(this->_M_impl._M_start, __n, __value, + _M_get_Tp_allocator()); + } + +#if __cplusplus >= 201103L + // Called by the vector(n) constructor. + void + _M_default_initialize(size_type __n) + { + this->_M_impl._M_finish = + std::__uninitialized_default_n_a(this->_M_impl._M_start, __n, + _M_get_Tp_allocator()); + } +#endif + + // Internal assign functions follow. The *_aux functions do the actual + // assignment work for the range versions. + + // Called by the range assign to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, __true_type) + { _M_fill_assign(__n, __val); } + + // Called by the range assign to implement [23.1.1]/9 + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + __false_type) + { _M_assign_aux(__first, __last, std::__iterator_category(__first)); } + + // Called by the second assign_dispatch above + template + void + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag); + + // Called by the second assign_dispatch above + template + void + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag); + + // Called by assign(n,t), and the range assign when it turns out + // to be the same thing. + void + _M_fill_assign(size_type __n, const value_type& __val); + + // Internal insert functions follow. + + // Called by the range insert to implement [23.1.1]/9 + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 438. Ambiguity in the "do the right thing" clause + template + void + _M_insert_dispatch(iterator __pos, _Integer __n, _Integer __val, + __true_type) + { _M_fill_insert(__pos, __n, __val); } + + // Called by the range insert to implement [23.1.1]/9 + template + void + _M_insert_dispatch(iterator __pos, _InputIterator __first, + _InputIterator __last, __false_type) + { + _M_range_insert(__pos, __first, __last, + std::__iterator_category(__first)); + } + + // Called by the second insert_dispatch above + template + void + _M_range_insert(iterator __pos, _InputIterator __first, + _InputIterator __last, std::input_iterator_tag); + + // Called by the second insert_dispatch above + template + void + _M_range_insert(iterator __pos, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag); + + // Called by insert(p,n,x), and the range insert when it turns out to be + // the same thing. + void + _M_fill_insert(iterator __pos, size_type __n, const value_type& __x); + +#if __cplusplus >= 201103L + // Called by resize(n). + void + _M_default_append(size_type __n); + + bool + _M_shrink_to_fit(); +#endif + +#if __cplusplus < 201103L + // Called by insert(p,x) + void + _M_insert_aux(iterator __position, const value_type& __x); + + void + _M_realloc_insert(iterator __position, const value_type& __x); +#else + // A value_type object constructed with _Alloc_traits::construct() + // and destroyed with _Alloc_traits::destroy(). + struct _Temporary_value + { + template + explicit + _Temporary_value(vector* __vec, _Args&&... __args) : _M_this(__vec) + { + _Alloc_traits::construct(_M_this->_M_impl, _M_ptr(), + std::forward<_Args>(__args)...); + } + + ~_Temporary_value() + { _Alloc_traits::destroy(_M_this->_M_impl, _M_ptr()); } + + value_type& + _M_val() { return *_M_ptr(); } + + private: + _Tp* + _M_ptr() { return reinterpret_cast<_Tp*>(&__buf); } + + vector* _M_this; + typename aligned_storage::type __buf; + }; + + // Called by insert(p,x) and other functions when insertion needs to + // reallocate or move existing elements. _Arg is either _Tp& or _Tp. + template + void + _M_insert_aux(iterator __position, _Arg&& __arg); + + template + void + _M_realloc_insert(iterator __position, _Args&&... __args); + + // Either move-construct at the end, or forward to _M_insert_aux. + iterator + _M_insert_rval(const_iterator __position, value_type&& __v); + + // Try to emplace at the end, otherwise forward to _M_insert_aux. + template + iterator + _M_emplace_aux(const_iterator __position, _Args&&... __args); + + // Emplacing an rvalue of the correct type can use _M_insert_rval. + iterator + _M_emplace_aux(const_iterator __position, value_type&& __v) + { return _M_insert_rval(__position, std::move(__v)); } +#endif + + // Called by _M_fill_insert, _M_insert_aux etc. + size_type + _M_check_len(size_type __n, const char* __s) const + { + if (max_size() - size() < __n) + __throw_length_error(__N(__s)); + + const size_type __len = size() + (std::max)(size(), __n); + return (__len < size() || __len > max_size()) ? max_size() : __len; + } + + // Called by constructors to check initial size. + static size_type + _S_check_init_len(size_type __n, const allocator_type& __a) + { + if (__n > _S_max_size(_Tp_alloc_type(__a))) + __throw_length_error( + __N("cannot create std::vector larger than max_size()")); + return __n; + } + + static size_type + _S_max_size(const _Tp_alloc_type& __a) _GLIBCXX_NOEXCEPT + { + // std::distance(begin(), end()) cannot be greater than PTRDIFF_MAX, + // and realistically we can't store more than PTRDIFF_MAX/sizeof(T) + // (even if std::allocator_traits::max_size says we can). + const size_t __diffmax + = __gnu_cxx::__numeric_traits::__max / sizeof(_Tp); + const size_t __allocmax = _Alloc_traits::max_size(__a); + return (std::min)(__diffmax, __allocmax); + } + + // Internal erase functions follow. + + // Called by erase(q1,q2), clear(), resize(), _M_fill_assign, + // _M_assign_aux. + void + _M_erase_at_end(pointer __pos) _GLIBCXX_NOEXCEPT + { + if (size_type __n = this->_M_impl._M_finish - __pos) + { + std::_Destroy(__pos, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish = __pos; + _GLIBCXX_ASAN_ANNOTATE_SHRINK(__n); + } + } + + iterator + _M_erase(iterator __position); + + iterator + _M_erase(iterator __first, iterator __last); + +#if __cplusplus >= 201103L + private: + // Constant-time move assignment when source object's memory can be + // moved, either because the source's allocator will move too + // or because the allocators are equal. + void + _M_move_assign(vector&& __x, true_type) noexcept + { + vector __tmp(get_allocator()); + this->_M_impl._M_swap_data(__x._M_impl); + __tmp._M_impl._M_swap_data(__x._M_impl); + std::__alloc_on_move(_M_get_Tp_allocator(), __x._M_get_Tp_allocator()); + } + + // Do move assignment when it might not be possible to move source + // object's memory, resulting in a linear-time operation. + void + _M_move_assign(vector&& __x, false_type) + { + if (__x._M_get_Tp_allocator() == this->_M_get_Tp_allocator()) + _M_move_assign(std::move(__x), true_type()); + else + { + // The rvalue's allocator cannot be moved and is not equal, + // so we need to individually move each element. + this->_M_assign_aux(std::make_move_iterator(__x.begin()), + std::make_move_iterator(__x.end()), + std::random_access_iterator_tag()); + __x.clear(); + } + } +#endif + + template + _Up* + _M_data_ptr(_Up* __ptr) const _GLIBCXX_NOEXCEPT + { return __ptr; } + +#if __cplusplus >= 201103L + template + typename std::pointer_traits<_Ptr>::element_type* + _M_data_ptr(_Ptr __ptr) const + { return empty() ? nullptr : std::__to_address(__ptr); } +#else + template + _Up* + _M_data_ptr(_Up* __ptr) _GLIBCXX_NOEXCEPT + { return __ptr; } + + template + value_type* + _M_data_ptr(_Ptr __ptr) + { return empty() ? (value_type*)0 : __ptr.operator->(); } + + template + const value_type* + _M_data_ptr(_Ptr __ptr) const + { return empty() ? (const value_type*)0 : __ptr.operator->(); } +#endif + }; + +#if __cpp_deduction_guides >= 201606 + template::value_type, + typename _Allocator = allocator<_ValT>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireAllocator<_Allocator>> + vector(_InputIterator, _InputIterator, _Allocator = _Allocator()) + -> vector<_ValT, _Allocator>; +#endif + + /** + * @brief Vector equality comparison. + * @param __x A %vector. + * @param __y A %vector of the same type as @a __x. + * @return True iff the size and elements of the vectors are equal. + * + * This is an equivalence relation. It is linear in the size of the + * vectors. Vectors are considered equivalent if their sizes are equal, + * and if corresponding elements compare equal. + */ + template + inline bool + operator==(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return (__x.size() == __y.size() + && std::equal(__x.begin(), __x.end(), __y.begin())); } + +#if __cpp_lib_three_way_comparison + /** + * @brief Vector ordering relation. + * @param __x A `vector`. + * @param __y A `vector` of the same type as `__x`. + * @return A value indicating whether `__x` is less than, equal to, + * greater than, or incomparable with `__y`. + * + * See `std::lexicographical_compare_three_way()` for how the determination + * is made. This operator is used to synthesize relational operators like + * `<` and `>=` etc. + */ + template + inline __detail::__synth3way_t<_Tp> + operator<=>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { + return std::lexicographical_compare_three_way(__x.begin(), __x.end(), + __y.begin(), __y.end(), + __detail::__synth3way); + } +#else + /** + * @brief Vector ordering relation. + * @param __x A %vector. + * @param __y A %vector of the same type as @a __x. + * @return True iff @a __x is lexicographically less than @a __y. + * + * This is a total ordering relation. It is linear in the size of the + * vectors. The elements must be comparable with @c <. + * + * See std::lexicographical_compare() for how the determination is made. + */ + template + inline bool + operator<(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return std::lexicographical_compare(__x.begin(), __x.end(), + __y.begin(), __y.end()); } + + /// Based on operator== + template + inline bool + operator!=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return !(__x == __y); } + + /// Based on operator< + template + inline bool + operator>(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return __y < __x; } + + /// Based on operator< + template + inline bool + operator<=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return !(__y < __x); } + + /// Based on operator< + template + inline bool + operator>=(const vector<_Tp, _Alloc>& __x, const vector<_Tp, _Alloc>& __y) + { return !(__x < __y); } +#endif // three-way comparison + + /// See std::vector::swap(). + template + inline void + swap(vector<_Tp, _Alloc>& __x, vector<_Tp, _Alloc>& __y) + _GLIBCXX_NOEXCEPT_IF(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus >= 201703L + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing a + // vector into a variant, but only if move assignment cannot throw. + template + struct _Never_valueless_alt<_GLIBCXX_STD_C::vector<_Tp, _Alloc>> + : std::is_nothrow_move_assignable<_GLIBCXX_STD_C::vector<_Tp, _Alloc>> + { }; + } // namespace __detail::__variant +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _STL_VECTOR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/string_view.tcc b/resources/sources/avr-libstdcpp/include/bits/string_view.tcc new file mode 100644 index 000000000..88d9371f1 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/string_view.tcc @@ -0,0 +1,229 @@ +// Components for manipulating non-owning sequences of characters -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/bits/string_view.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{string_view} + */ + +// +// N3762 basic_string_view library +// + +#ifndef _GLIBCXX_STRING_VIEW_TCC +#define _GLIBCXX_STRING_VIEW_TCC 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find(const _CharT* __str, size_type __pos, size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + + if (__n == 0) + return __pos <= this->_M_len ? __pos : npos; + + if (__n <= this->_M_len) + { + for (; __pos <= this->_M_len - __n; ++__pos) + if (traits_type::eq(this->_M_str[__pos], __str[0]) + && traits_type::compare(this->_M_str + __pos + 1, + __str + 1, __n - 1) == 0) + return __pos; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find(_CharT __c, size_type __pos) const noexcept + { + size_type __ret = npos; + if (__pos < this->_M_len) + { + const size_type __n = this->_M_len - __pos; + const _CharT* __p = traits_type::find(this->_M_str + __pos, __n, __c); + if (__p) + __ret = __p - this->_M_str; + } + return __ret; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + + if (__n <= this->_M_len) + { + __pos = std::min(size_type(this->_M_len - __n), __pos); + do + { + if (traits_type::compare(this->_M_str + __pos, __str, __n) == 0) + return __pos; + } + while (__pos-- > 0); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + rfind(_CharT __c, size_type __pos) const noexcept + { + size_type __size = this->_M_len; + if (__size > 0) + { + if (--__size > __pos) + __size = __pos; + for (++__size; __size-- > 0; ) + if (traits_type::eq(this->_M_str[__size], __c)) + return __size; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + for (; __n && __pos < this->_M_len; ++__pos) + { + const _CharT* __p = traits_type::find(__str, __n, + this->_M_str[__pos]); + if (__p) + return __pos; + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + size_type __size = this->size(); + if (__size && __n) + { + if (--__size > __pos) + __size = __pos; + do + { + if (traits_type::find(__str, __n, this->_M_str[__size])) + return __size; + } + while (__size-- != 0); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_not_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + for (; __pos < this->_M_len; ++__pos) + if (!traits_type::find(__str, __n, this->_M_str[__pos])) + return __pos; + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_first_not_of(_CharT __c, size_type __pos) const noexcept + { + for (; __pos < this->_M_len; ++__pos) + if (!traits_type::eq(this->_M_str[__pos], __c)) + return __pos; + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_not_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept + { + __glibcxx_requires_string_len(__str, __n); + size_type __size = this->_M_len; + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::find(__str, __n, this->_M_str[__size])) + return __size; + } + while (__size--); + } + return npos; + } + + template + constexpr typename basic_string_view<_CharT, _Traits>::size_type + basic_string_view<_CharT, _Traits>:: + find_last_not_of(_CharT __c, size_type __pos) const noexcept + { + size_type __size = this->_M_len; + if (__size) + { + if (--__size > __pos) + __size = __pos; + do + { + if (!traits_type::eq(this->_M_str[__size], __c)) + return __size; + } + while (__size--); + } + return npos; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // __cplusplus <= 201402L + +#endif // _GLIBCXX_STRING_VIEW_TCC diff --git a/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h b/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h new file mode 100644 index 000000000..e3d7934e9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/uniform_int_dist.h @@ -0,0 +1,395 @@ +// Class template uniform_int_distribution -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** + * @file bits/uniform_int_dist.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{random} + */ + +#ifndef _GLIBCXX_BITS_UNIFORM_INT_DIST_H +#define _GLIBCXX_BITS_UNIFORM_INT_DIST_H + +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#ifdef __cpp_lib_concepts + /// Requirements for a uniform random bit generator. + template + concept uniform_random_bit_generator + = invocable<_Gen&> && unsigned_integral> + && requires + { + { _Gen::min() } -> same_as>; + { _Gen::max() } -> same_as>; + requires bool_constant<(_Gen::min() < _Gen::max())>::value; + }; +#endif + + namespace __detail + { + /* Determine whether number is a power of 2. */ + template + inline bool + _Power_of_2(_Tp __x) + { + return ((__x - 1) & __x) == 0; + } + } + + /** + * @brief Uniform discrete distribution for random numbers. + * A discrete random distribution on the range @f$[min, max]@f$ with equal + * probability throughout the range. + */ + template + class uniform_int_distribution + { + static_assert(std::is_integral<_IntType>::value, + "template argument must be an integral type"); + + public: + /** The type of the range of the distribution. */ + typedef _IntType result_type; + /** Parameter type. */ + struct param_type + { + typedef uniform_int_distribution<_IntType> distribution_type; + + param_type() : param_type(0) { } + + explicit + param_type(_IntType __a, + _IntType __b = numeric_limits<_IntType>::max()) + : _M_a(__a), _M_b(__b) + { + __glibcxx_assert(_M_a <= _M_b); + } + + result_type + a() const + { return _M_a; } + + result_type + b() const + { return _M_b; } + + friend bool + operator==(const param_type& __p1, const param_type& __p2) + { return __p1._M_a == __p2._M_a && __p1._M_b == __p2._M_b; } + + friend bool + operator!=(const param_type& __p1, const param_type& __p2) + { return !(__p1 == __p2); } + + private: + _IntType _M_a; + _IntType _M_b; + }; + + public: + /** + * @brief Constructs a uniform distribution object. + */ + uniform_int_distribution() : uniform_int_distribution(0) { } + + /** + * @brief Constructs a uniform distribution object. + */ + explicit + uniform_int_distribution(_IntType __a, + _IntType __b = numeric_limits<_IntType>::max()) + : _M_param(__a, __b) + { } + + explicit + uniform_int_distribution(const param_type& __p) + : _M_param(__p) + { } + + /** + * @brief Resets the distribution state. + * + * Does nothing for the uniform integer distribution. + */ + void + reset() { } + + result_type + a() const + { return _M_param.a(); } + + result_type + b() const + { return _M_param.b(); } + + /** + * @brief Returns the parameter set of the distribution. + */ + param_type + param() const + { return _M_param; } + + /** + * @brief Sets the parameter set of the distribution. + * @param __param The new parameter set of the distribution. + */ + void + param(const param_type& __param) + { _M_param = __param; } + + /** + * @brief Returns the inclusive lower bound of the distribution range. + */ + result_type + min() const + { return this->a(); } + + /** + * @brief Returns the inclusive upper bound of the distribution range. + */ + result_type + max() const + { return this->b(); } + + /** + * @brief Generating functions. + */ + template + result_type + operator()(_UniformRandomNumberGenerator& __urng) + { return this->operator()(__urng, _M_param); } + + template + result_type + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __p); + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng) + { this->__generate(__f, __t, __urng, _M_param); } + + template + void + __generate(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + template + void + __generate(result_type* __f, result_type* __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p) + { this->__generate_impl(__f, __t, __urng, __p); } + + /** + * @brief Return true if two uniform integer distributions have + * the same parameters. + */ + friend bool + operator==(const uniform_int_distribution& __d1, + const uniform_int_distribution& __d2) + { return __d1._M_param == __d2._M_param; } + + private: + template + void + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __p); + + param_type _M_param; + }; + + template + template + typename uniform_int_distribution<_IntType>::result_type + uniform_int_distribution<_IntType>:: + operator()(_UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + typedef typename _UniformRandomNumberGenerator::result_type + _Gresult_type; + typedef typename std::make_unsigned::type __utype; + typedef typename std::common_type<_Gresult_type, __utype>::type + __uctype; + + const __uctype __urngmin = __urng.min(); + const __uctype __urngmax = __urng.max(); + const __uctype __urngrange = __urngmax - __urngmin; + const __uctype __urange + = __uctype(__param.b()) - __uctype(__param.a()); + + __uctype __ret; + + if (__urngrange > __urange) + { + // downscaling + const __uctype __uerange = __urange + 1; // __urange can be zero + const __uctype __scaling = __urngrange / __uerange; + const __uctype __past = __uerange * __scaling; + do + __ret = __uctype(__urng()) - __urngmin; + while (__ret >= __past); + __ret /= __scaling; + } + else if (__urngrange < __urange) + { + // upscaling + /* + Note that every value in [0, urange] + can be written uniquely as + + (urngrange + 1) * high + low + + where + + high in [0, urange / (urngrange + 1)] + + and + + low in [0, urngrange]. + */ + __uctype __tmp; // wraparound control + do + { + const __uctype __uerngrange = __urngrange + 1; + __tmp = (__uerngrange * operator() + (__urng, param_type(0, __urange / __uerngrange))); + __ret = __tmp + (__uctype(__urng()) - __urngmin); + } + while (__ret > __urange || __ret < __tmp); + } + else + __ret = __uctype(__urng()) - __urngmin; + + return __ret + __param.a(); + } + + + template + template + void + uniform_int_distribution<_IntType>:: + __generate_impl(_ForwardIterator __f, _ForwardIterator __t, + _UniformRandomNumberGenerator& __urng, + const param_type& __param) + { + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + typedef typename _UniformRandomNumberGenerator::result_type + _Gresult_type; + typedef typename std::make_unsigned::type __utype; + typedef typename std::common_type<_Gresult_type, __utype>::type + __uctype; + + const __uctype __urngmin = __urng.min(); + const __uctype __urngmax = __urng.max(); + const __uctype __urngrange = __urngmax - __urngmin; + const __uctype __urange + = __uctype(__param.b()) - __uctype(__param.a()); + + __uctype __ret; + + if (__urngrange > __urange) + { + if (__detail::_Power_of_2(__urngrange + 1) + && __detail::_Power_of_2(__urange + 1)) + { + while (__f != __t) + { + __ret = __uctype(__urng()) - __urngmin; + *__f++ = (__ret & __urange) + __param.a(); + } + } + else + { + // downscaling + const __uctype __uerange = __urange + 1; // __urange can be zero + const __uctype __scaling = __urngrange / __uerange; + const __uctype __past = __uerange * __scaling; + while (__f != __t) + { + do + __ret = __uctype(__urng()) - __urngmin; + while (__ret >= __past); + *__f++ = __ret / __scaling + __param.a(); + } + } + } + else if (__urngrange < __urange) + { + // upscaling + /* + Note that every value in [0, urange] + can be written uniquely as + + (urngrange + 1) * high + low + + where + + high in [0, urange / (urngrange + 1)] + + and + + low in [0, urngrange]. + */ + __uctype __tmp; // wraparound control + while (__f != __t) + { + do + { + const __uctype __uerngrange = __urngrange + 1; + __tmp = (__uerngrange * operator() + (__urng, param_type(0, __urange / __uerngrange))); + __ret = __tmp + (__uctype(__urng()) - __urngmin); + } + while (__ret > __urange || __ret < __tmp); + *__f++ = __ret; + } + } + else + while (__f != __t) + *__f++ = __uctype(__urng()) - __urngmin + __param.a(); + } + + // operator!= and operator<< and operator>> are defined in + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/unique_lock.h b/resources/sources/avr-libstdcpp/include/bits/unique_lock.h new file mode 100644 index 000000000..82eef44d6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/unique_lock.h @@ -0,0 +1,243 @@ +// std::unique_lock implementation -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unique_lock.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{mutex} + */ + +#ifndef _GLIBCXX_UNIQUE_LOCK_H +#define _GLIBCXX_UNIQUE_LOCK_H 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include // for std::swap + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** @brief A movable scoped lock type. + * + * A unique_lock controls mutex ownership within a scope. Ownership of the + * mutex can be delayed until after construction and can be transferred + * to another unique_lock by move construction or move assignment. If a + * mutex lock is owned when the destructor runs ownership will be released. + * + * @ingroup mutexes + */ + template + class unique_lock + { + public: + typedef _Mutex mutex_type; + + unique_lock() noexcept + : _M_device(0), _M_owns(false) + { } + + explicit unique_lock(mutex_type& __m) + : _M_device(std::__addressof(__m)), _M_owns(false) + { + lock(); + _M_owns = true; + } + + unique_lock(mutex_type& __m, defer_lock_t) noexcept + : _M_device(std::__addressof(__m)), _M_owns(false) + { } + + unique_lock(mutex_type& __m, try_to_lock_t) + : _M_device(std::__addressof(__m)), _M_owns(_M_device->try_lock()) + { } + + unique_lock(mutex_type& __m, adopt_lock_t) noexcept + : _M_device(std::__addressof(__m)), _M_owns(true) + { + // XXX calling thread owns mutex + } + + template + unique_lock(mutex_type& __m, + const chrono::time_point<_Clock, _Duration>& __atime) + : _M_device(std::__addressof(__m)), + _M_owns(_M_device->try_lock_until(__atime)) + { } + + template + unique_lock(mutex_type& __m, + const chrono::duration<_Rep, _Period>& __rtime) + : _M_device(std::__addressof(__m)), + _M_owns(_M_device->try_lock_for(__rtime)) + { } + + ~unique_lock() + { + if (_M_owns) + unlock(); + } + + unique_lock(const unique_lock&) = delete; + unique_lock& operator=(const unique_lock&) = delete; + + unique_lock(unique_lock&& __u) noexcept + : _M_device(__u._M_device), _M_owns(__u._M_owns) + { + __u._M_device = 0; + __u._M_owns = false; + } + + unique_lock& operator=(unique_lock&& __u) noexcept + { + if(_M_owns) + unlock(); + + unique_lock(std::move(__u)).swap(*this); + + __u._M_device = 0; + __u._M_owns = false; + + return *this; + } + + void + lock() + { + if (!_M_device) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + else + { + _M_device->lock(); + _M_owns = true; + } + } + + bool + try_lock() + { + if (!_M_device) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + else + { + _M_owns = _M_device->try_lock(); + return _M_owns; + } + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + if (!_M_device) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + else + { + _M_owns = _M_device->try_lock_until(__atime); + return _M_owns; + } + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + if (!_M_device) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + else + { + _M_owns = _M_device->try_lock_for(__rtime); + return _M_owns; + } + } + + void + unlock() + { + if (!_M_owns) + __throw_system_error(int(errc::operation_not_permitted)); + else if (_M_device) + { + _M_device->unlock(); + _M_owns = false; + } + } + + void + swap(unique_lock& __u) noexcept + { + std::swap(_M_device, __u._M_device); + std::swap(_M_owns, __u._M_owns); + } + + mutex_type* + release() noexcept + { + mutex_type* __ret = _M_device; + _M_device = 0; + _M_owns = false; + return __ret; + } + + bool + owns_lock() const noexcept + { return _M_owns; } + + explicit operator bool() const noexcept + { return owns_lock(); } + + mutex_type* + mutex() const noexcept + { return _M_device; } + + private: + mutex_type* _M_device; + bool _M_owns; + }; + + /// Swap overload for unique_lock objects. + /// @relates unique_lock + template + inline void + swap(unique_lock<_Mutex>& __x, unique_lock<_Mutex>& __y) noexcept + { __x.swap(__y); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 +#endif // _GLIBCXX_UNIQUE_LOCK_H diff --git a/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h b/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h new file mode 100644 index 000000000..0f100c593 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/unique_ptr.h @@ -0,0 +1,995 @@ +// unique_ptr implementation -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unique_ptr.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{memory} + */ + +#ifndef _UNIQUE_PTR_H +#define _UNIQUE_PTR_H 1 + +#include +#include +#include +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup pointer_abstractions + * @{ + */ + +#if _GLIBCXX_USE_DEPRECATED +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + template class auto_ptr; +#pragma GCC diagnostic pop +#endif + + /// Primary template of default_delete, used by unique_ptr for single objects + template + struct default_delete + { + /// Default constructor + constexpr default_delete() noexcept = default; + + /** @brief Converting constructor. + * + * Allows conversion from a deleter for objects of another type, `_Up`, + * only if `_Up*` is convertible to `_Tp*`. + */ + template>> + default_delete(const default_delete<_Up>&) noexcept { } + + /// Calls `delete __ptr` + void + operator()(_Tp* __ptr) const + { + static_assert(!is_void<_Tp>::value, + "can't delete pointer to incomplete type"); + static_assert(sizeof(_Tp)>0, + "can't delete pointer to incomplete type"); + delete __ptr; + } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 740 - omit specialization for array objects with a compile time length + + /// Specialization of default_delete for arrays, used by `unique_ptr` + template + struct default_delete<_Tp[]> + { + public: + /// Default constructor + constexpr default_delete() noexcept = default; + + /** @brief Converting constructor. + * + * Allows conversion from a deleter for arrays of another type, such as + * a const-qualified version of `_Tp`. + * + * Conversions from types derived from `_Tp` are not allowed because + * it is undefined to `delete[]` an array of derived types through a + * pointer to the base type. + */ + template>> + default_delete(const default_delete<_Up[]>&) noexcept { } + + /// Calls `delete[] __ptr` + template + typename enable_if::value>::type + operator()(_Up* __ptr) const + { + static_assert(sizeof(_Tp)>0, + "can't delete pointer to incomplete type"); + delete [] __ptr; + } + }; + + /// @cond undocumented + + // Manages the pointer and deleter of a unique_ptr + template + class __uniq_ptr_impl + { + template + struct _Ptr + { + using type = _Up*; + }; + + template + struct + _Ptr<_Up, _Ep, __void_t::type::pointer>> + { + using type = typename remove_reference<_Ep>::type::pointer; + }; + + public: + using _DeleterConstraint = enable_if< + __and_<__not_>, + is_default_constructible<_Dp>>::value>; + + using pointer = typename _Ptr<_Tp, _Dp>::type; + + static_assert( !is_rvalue_reference<_Dp>::value, + "unique_ptr's deleter type must be a function object type" + " or an lvalue reference type" ); + + __uniq_ptr_impl() = default; + __uniq_ptr_impl(pointer __p) : _M_t() { _M_ptr() = __p; } + + template + __uniq_ptr_impl(pointer __p, _Del&& __d) + : _M_t(__p, std::forward<_Del>(__d)) { } + + __uniq_ptr_impl(__uniq_ptr_impl&& __u) noexcept + : _M_t(std::move(__u._M_t)) + { __u._M_ptr() = nullptr; } + + __uniq_ptr_impl& operator=(__uniq_ptr_impl&& __u) noexcept + { + reset(__u.release()); + _M_deleter() = std::forward<_Dp>(__u._M_deleter()); + return *this; + } + + pointer& _M_ptr() { return std::get<0>(_M_t); } + pointer _M_ptr() const { return std::get<0>(_M_t); } + _Dp& _M_deleter() { return std::get<1>(_M_t); } + const _Dp& _M_deleter() const { return std::get<1>(_M_t); } + + void reset(pointer __p) noexcept + { + const pointer __old_p = _M_ptr(); + _M_ptr() = __p; + if (__old_p) + _M_deleter()(__old_p); + } + + pointer release() noexcept + { + pointer __p = _M_ptr(); + _M_ptr() = nullptr; + return __p; + } + + void + swap(__uniq_ptr_impl& __rhs) noexcept + { + using std::swap; + swap(this->_M_ptr(), __rhs._M_ptr()); + swap(this->_M_deleter(), __rhs._M_deleter()); + } + + private: + tuple _M_t; + }; + + // Defines move construction + assignment as either defaulted or deleted. + template ::value, + bool = is_move_assignable<_Dp>::value> + struct __uniq_ptr_data : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = default; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, true, false> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = default; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, false, true> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = delete; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = default; + }; + + template + struct __uniq_ptr_data<_Tp, _Dp, false, false> : __uniq_ptr_impl<_Tp, _Dp> + { + using __uniq_ptr_impl<_Tp, _Dp>::__uniq_ptr_impl; + __uniq_ptr_data(__uniq_ptr_data&&) = delete; + __uniq_ptr_data& operator=(__uniq_ptr_data&&) = delete; + }; + /// @endcond + + /// 20.7.1.2 unique_ptr for single objects. + template > + class unique_ptr + { + template + using _DeleterConstraint = + typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; + + __uniq_ptr_data<_Tp, _Dp> _M_t; + + public: + using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; + using element_type = _Tp; + using deleter_type = _Dp; + + private: + // helper template for detecting a safe conversion from another + // unique_ptr + template + using __safe_conversion_up = __and_< + is_convertible::pointer, pointer>, + __not_> + >; + + public: + // Constructors. + + /// Default constructor, creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr() noexcept + : _M_t() + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * + * The deleter will be value-initialized. + */ + template> + explicit + unique_ptr(pointer __p) noexcept + : _M_t(__p) + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p __d + */ + template>> + unique_ptr(pointer __p, const deleter_type& __d) noexcept + : _M_t(__p, __d) { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an object of @c element_type + * @param __d An rvalue reference to a (non-reference) deleter. + * + * The deleter will be initialized with @p std::move(__d) + */ + template>> + unique_ptr(pointer __p, + __enable_if_t::value, + _Del&&> __d) noexcept + : _M_t(__p, std::move(__d)) + { } + + template::type> + unique_ptr(pointer, + __enable_if_t::value, + _DelUnref&&>) = delete; + + /// Creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr(nullptr_t) noexcept + : _M_t() + { } + + // Move constructors. + + /// Move constructor. + unique_ptr(unique_ptr&&) = default; + + /** @brief Converting constructor from another type + * + * Requires that the pointer owned by @p __u is convertible to the + * type of pointer owned by this object, @p __u does not own an array, + * and @p __u has a compatible deleter type. + */ + template, + typename conditional::value, + is_same<_Ep, _Dp>, + is_convertible<_Ep, _Dp>>::type>> + unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept + : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) + { } + +#if _GLIBCXX_USE_DEPRECATED +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" + /// Converting constructor from @c auto_ptr + template, is_same<_Dp, default_delete<_Tp>>>> + unique_ptr(auto_ptr<_Up>&& __u) noexcept; +#pragma GCC diagnostic pop +#endif + + /// Destructor, invokes the deleter if the stored pointer is not null. + ~unique_ptr() noexcept + { + static_assert(__is_invocable::value, + "unique_ptr's deleter must be invocable with a pointer"); + auto& __ptr = _M_t._M_ptr(); + if (__ptr != nullptr) + get_deleter()(std::move(__ptr)); + __ptr = pointer(); + } + + // Assignment. + + /** @brief Move assignment operator. + * + * Invokes the deleter if this object owns a pointer. + */ + unique_ptr& operator=(unique_ptr&&) = default; + + /** @brief Assignment from another type. + * + * @param __u The object to transfer ownership from, which owns a + * convertible pointer to a non-array object. + * + * Invokes the deleter if this object owns a pointer. + */ + template + typename enable_if< __and_< + __safe_conversion_up<_Up, _Ep>, + is_assignable + >::value, + unique_ptr&>::type + operator=(unique_ptr<_Up, _Ep>&& __u) noexcept + { + reset(__u.release()); + get_deleter() = std::forward<_Ep>(__u.get_deleter()); + return *this; + } + + /// Reset the %unique_ptr to empty, invoking the deleter if necessary. + unique_ptr& + operator=(nullptr_t) noexcept + { + reset(); + return *this; + } + + // Observers. + + /// Dereference the stored pointer. + typename add_lvalue_reference::type + operator*() const + { + __glibcxx_assert(get() != pointer()); + return *get(); + } + + /// Return the stored pointer. + pointer + operator->() const noexcept + { + _GLIBCXX_DEBUG_PEDASSERT(get() != pointer()); + return get(); + } + + /// Return the stored pointer. + pointer + get() const noexcept + { return _M_t._M_ptr(); } + + /// Return a reference to the stored deleter. + deleter_type& + get_deleter() noexcept + { return _M_t._M_deleter(); } + + /// Return a reference to the stored deleter. + const deleter_type& + get_deleter() const noexcept + { return _M_t._M_deleter(); } + + /// Return @c true if the stored pointer is not null. + explicit operator bool() const noexcept + { return get() == pointer() ? false : true; } + + // Modifiers. + + /// Release ownership of any stored pointer. + pointer + release() noexcept + { return _M_t.release(); } + + /** @brief Replace the stored pointer. + * + * @param __p The new pointer to store. + * + * The deleter will be invoked if a pointer is already owned. + */ + void + reset(pointer __p = pointer()) noexcept + { + static_assert(__is_invocable::value, + "unique_ptr's deleter must be invocable with a pointer"); + _M_t.reset(std::move(__p)); + } + + /// Exchange the pointer and deleter with another object. + void + swap(unique_ptr& __u) noexcept + { + static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); + _M_t.swap(__u._M_t); + } + + // Disable copy from lvalue. + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + }; + + /// 20.7.1.3 unique_ptr for array objects with a runtime length + // [unique.ptr.runtime] + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 740 - omit specialization for array objects with a compile time length + template + class unique_ptr<_Tp[], _Dp> + { + template + using _DeleterConstraint = + typename __uniq_ptr_impl<_Tp, _Up>::_DeleterConstraint::type; + + __uniq_ptr_data<_Tp, _Dp> _M_t; + + template + using __remove_cv_t = typename remove_cv<_Up>::type; + + // like is_base_of<_Tp, _Up> but false if unqualified types are the same + template + using __is_derived_Tp + = __and_< is_base_of<_Tp, _Up>, + __not_, __remove_cv_t<_Up>>> >; + + public: + using pointer = typename __uniq_ptr_impl<_Tp, _Dp>::pointer; + using element_type = _Tp; + using deleter_type = _Dp; + + // helper template for detecting a safe conversion from another + // unique_ptr + template, + typename _UP_pointer = typename _UPtr::pointer, + typename _UP_element_type = typename _UPtr::element_type> + using __safe_conversion_up = __and_< + is_array<_Up>, + is_same, + is_same<_UP_pointer, _UP_element_type*>, + is_convertible<_UP_element_type(*)[], element_type(*)[]> + >; + + // helper template for detecting a safe conversion from a raw pointer + template + using __safe_conversion_raw = __and_< + __or_<__or_, + is_same<_Up, nullptr_t>>, + __and_, + is_same, + is_convertible< + typename remove_pointer<_Up>::type(*)[], + element_type(*)[]> + > + > + >; + + // Constructors. + + /// Default constructor, creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr() noexcept + : _M_t() + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * + * The deleter will be value-initialized. + */ + template, + typename = typename enable_if< + __safe_conversion_raw<_Up>::value, bool>::type> + explicit + unique_ptr(_Up __p) noexcept + : _M_t(__p) + { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p __d + */ + template, + is_copy_constructible<_Del>>> + unique_ptr(_Up __p, const deleter_type& __d) noexcept + : _M_t(__p, __d) { } + + /** Takes ownership of a pointer. + * + * @param __p A pointer to an array of a type safely convertible + * to an array of @c element_type + * @param __d A reference to a deleter. + * + * The deleter will be initialized with @p std::move(__d) + */ + template, + is_move_constructible<_Del>>> + unique_ptr(_Up __p, + __enable_if_t::value, + _Del&&> __d) noexcept + : _M_t(std::move(__p), std::move(__d)) + { } + + template::type, + typename = _Require<__safe_conversion_raw<_Up>>> + unique_ptr(_Up, + __enable_if_t::value, + _DelUnref&&>) = delete; + + /// Move constructor. + unique_ptr(unique_ptr&&) = default; + + /// Creates a unique_ptr that owns nothing. + template> + constexpr unique_ptr(nullptr_t) noexcept + : _M_t() + { } + + template, + typename conditional::value, + is_same<_Ep, _Dp>, + is_convertible<_Ep, _Dp>>::type>> + unique_ptr(unique_ptr<_Up, _Ep>&& __u) noexcept + : _M_t(__u.release(), std::forward<_Ep>(__u.get_deleter())) + { } + + /// Destructor, invokes the deleter if the stored pointer is not null. + ~unique_ptr() + { + auto& __ptr = _M_t._M_ptr(); + if (__ptr != nullptr) + get_deleter()(__ptr); + __ptr = pointer(); + } + + // Assignment. + + /** @brief Move assignment operator. + * + * Invokes the deleter if this object owns a pointer. + */ + unique_ptr& + operator=(unique_ptr&&) = default; + + /** @brief Assignment from another type. + * + * @param __u The object to transfer ownership from, which owns a + * convertible pointer to an array object. + * + * Invokes the deleter if this object owns a pointer. + */ + template + typename + enable_if<__and_<__safe_conversion_up<_Up, _Ep>, + is_assignable + >::value, + unique_ptr&>::type + operator=(unique_ptr<_Up, _Ep>&& __u) noexcept + { + reset(__u.release()); + get_deleter() = std::forward<_Ep>(__u.get_deleter()); + return *this; + } + + /// Reset the %unique_ptr to empty, invoking the deleter if necessary. + unique_ptr& + operator=(nullptr_t) noexcept + { + reset(); + return *this; + } + + // Observers. + + /// Access an element of owned array. + typename std::add_lvalue_reference::type + operator[](size_t __i) const + { + __glibcxx_assert(get() != pointer()); + return get()[__i]; + } + + /// Return the stored pointer. + pointer + get() const noexcept + { return _M_t._M_ptr(); } + + /// Return a reference to the stored deleter. + deleter_type& + get_deleter() noexcept + { return _M_t._M_deleter(); } + + /// Return a reference to the stored deleter. + const deleter_type& + get_deleter() const noexcept + { return _M_t._M_deleter(); } + + /// Return @c true if the stored pointer is not null. + explicit operator bool() const noexcept + { return get() == pointer() ? false : true; } + + // Modifiers. + + /// Release ownership of any stored pointer. + pointer + release() noexcept + { return _M_t.release(); } + + /** @brief Replace the stored pointer. + * + * @param __p The new pointer to store. + * + * The deleter will be invoked if a pointer is already owned. + */ + template , + __and_, + is_pointer<_Up>, + is_convertible< + typename remove_pointer<_Up>::type(*)[], + element_type(*)[] + > + > + > + >> + void + reset(_Up __p) noexcept + { _M_t.reset(std::move(__p)); } + + void reset(nullptr_t = nullptr) noexcept + { reset(pointer()); } + + /// Exchange the pointer and deleter with another object. + void + swap(unique_ptr& __u) noexcept + { + static_assert(__is_swappable<_Dp>::value, "deleter must be swappable"); + _M_t.swap(__u._M_t); + } + + // Disable copy from lvalue. + unique_ptr(const unique_ptr&) = delete; + unique_ptr& operator=(const unique_ptr&) = delete; + }; + + /// @relates unique_ptr @{ + + /// Swap overload for unique_ptr + template + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__is_swappable<_Dp>::value>::type +#else + void +#endif + swap(unique_ptr<_Tp, _Dp>& __x, + unique_ptr<_Tp, _Dp>& __y) noexcept + { __x.swap(__y); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + typename enable_if::value>::type + swap(unique_ptr<_Tp, _Dp>&, + unique_ptr<_Tp, _Dp>&) = delete; +#endif + + /// Equality operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator==(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return __x.get() == __y.get(); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator==(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept + { return !__x; } + +#ifndef __cpp_lib_three_way_comparison + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator==(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept + { return !__x; } + + /// Inequality operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator!=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return __x.get() != __y.get(); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator!=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) noexcept + { return (bool)__x; } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator!=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) noexcept + { return (bool)__x; } +#endif // three way comparison + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator<(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { + typedef typename + std::common_type::pointer, + typename unique_ptr<_Up, _Ep>::pointer>::type _CT; + return std::less<_CT>()(__x.get(), __y.get()); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator<(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + return std::less::pointer>()(__x.get(), + nullptr); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator<(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { + return std::less::pointer>()(nullptr, + __x.get()); + } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator<=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return !(__y < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator<=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { return !(nullptr < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator<=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { return !(__x < nullptr); } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator>(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return (__y < __x); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + return std::less::pointer>()(nullptr, + __x.get()); + } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { + return std::less::pointer>()(__x.get(), + nullptr); + } + + /// Relational operator for unique_ptr objects, compares the owned pointers + template + _GLIBCXX_NODISCARD inline bool + operator>=(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return !(__x < __y); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>=(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { return !(__x < nullptr); } + + /// unique_ptr comparison with nullptr + template + _GLIBCXX_NODISCARD inline bool + operator>=(nullptr_t, const unique_ptr<_Tp, _Dp>& __x) + { return !(nullptr < __x); } + +#ifdef __cpp_lib_three_way_comparison + template + requires three_way_comparable_with::pointer, + typename unique_ptr<_Up, _Ep>::pointer> + inline + compare_three_way_result_t::pointer, + typename unique_ptr<_Up, _Ep>::pointer> + operator<=>(const unique_ptr<_Tp, _Dp>& __x, + const unique_ptr<_Up, _Ep>& __y) + { return compare_three_way()(__x.get(), __y.get()); } + + template + requires three_way_comparable::pointer> + inline + compare_three_way_result_t::pointer> + operator<=>(const unique_ptr<_Tp, _Dp>& __x, nullptr_t) + { + using pointer = typename unique_ptr<_Tp, _Dp>::pointer; + return compare_three_way()(__x.get(), static_cast(nullptr)); + } +#endif + // @} relates unique_ptr + + /// @cond undocumented + template::__enable_hash_call> + struct __uniq_ptr_hash +#if ! _GLIBCXX_INLINE_VERSION + : private __poison_hash<_Ptr> +#endif + { + size_t + operator()(const _Up& __u) const + noexcept(noexcept(std::declval>()(std::declval<_Ptr>()))) + { return hash<_Ptr>()(__u.get()); } + }; + + template + struct __uniq_ptr_hash<_Up, _Ptr, false> + : private __poison_hash<_Ptr> + { }; + /// @endcond + + /// std::hash specialization for unique_ptr. + template + struct hash> + : public __hash_base>, + public __uniq_ptr_hash> + { }; + +#if __cplusplus >= 201402L + /// @relates unique_ptr @{ +#define __cpp_lib_make_unique 201304 + + /// @cond undocumented + + template + struct _MakeUniq + { typedef unique_ptr<_Tp> __single_object; }; + + template + struct _MakeUniq<_Tp[]> + { typedef unique_ptr<_Tp[]> __array; }; + + template + struct _MakeUniq<_Tp[_Bound]> + { struct __invalid_type { }; }; + + /// @endcond + + /// std::make_unique for single objects + template + inline typename _MakeUniq<_Tp>::__single_object + make_unique(_Args&&... __args) + { return unique_ptr<_Tp>(new _Tp(std::forward<_Args>(__args)...)); } + + /// std::make_unique for arrays of unknown bound + template + inline typename _MakeUniq<_Tp>::__array + make_unique(size_t __num) + { return unique_ptr<_Tp>(new remove_extent_t<_Tp>[__num]()); } + + /// Disable std::make_unique for arrays of known bound + template + inline typename _MakeUniq<_Tp>::__invalid_type + make_unique(_Args&&...) = delete; + // @} relates unique_ptr +#endif // C++14 + + // @} group pointer_abstractions + +#if __cplusplus >= 201703L + namespace __detail::__variant + { + template struct _Never_valueless_alt; // see + + // Provide the strong exception-safety guarantee when emplacing a + // unique_ptr into a variant. + template + struct _Never_valueless_alt> + : std::true_type + { }; + } // namespace __detail::__variant +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _UNIQUE_PTR_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/unordered_map.h b/resources/sources/avr-libstdcpp/include/bits/unordered_map.h new file mode 100644 index 000000000..0071d62e4 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/unordered_map.h @@ -0,0 +1,2171 @@ +// unordered_map implementation -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unordered_map.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{unordered_map} + */ + +#ifndef _UNORDERED_MAP_H +#define _UNORDERED_MAP_H + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /// Base types for unordered_map. + template + using __umap_traits = __detail::_Hashtable_traits<_Cache, false, true>; + + template, + typename _Pred = std::equal_to<_Key>, + typename _Alloc = std::allocator >, + typename _Tr = __umap_traits<__cache_default<_Key, _Hash>::value>> + using __umap_hashtable = _Hashtable<_Key, std::pair, + _Alloc, __detail::_Select1st, + _Pred, _Hash, + __detail::_Mod_range_hashing, + __detail::_Default_ranged_hash, + __detail::_Prime_rehash_policy, _Tr>; + + /// Base types for unordered_multimap. + template + using __ummap_traits = __detail::_Hashtable_traits<_Cache, false, false>; + + template, + typename _Pred = std::equal_to<_Key>, + typename _Alloc = std::allocator >, + typename _Tr = __ummap_traits<__cache_default<_Key, _Hash>::value>> + using __ummap_hashtable = _Hashtable<_Key, std::pair, + _Alloc, __detail::_Select1st, + _Pred, _Hash, + __detail::_Mod_range_hashing, + __detail::_Default_ranged_hash, + __detail::_Prime_rehash_policy, _Tr>; + + template + class unordered_multimap; + + /** + * @brief A standard container composed of unique keys (containing + * at most one of each key value) that associates values of another type + * with the keys. + * + * @ingroup unordered_associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Pred Predicate function object type, defaults + * to equal_to<_Value>. + * @tparam _Alloc Allocator type, defaults to + * std::allocator>. + * + * Meets the requirements of a container, and + * unordered associative container + * + * The resulting value type of the container is std::pair. + * + * Base is _Hashtable, dispatched at compile time via template + * alias __umap_hashtable. + */ + template, + typename _Pred = equal_to<_Key>, + typename _Alloc = allocator>> + class unordered_map + { + typedef __umap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable; + _Hashtable _M_h; + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef typename _Hashtable::key_type key_type; + typedef typename _Hashtable::value_type value_type; + typedef typename _Hashtable::mapped_type mapped_type; + typedef typename _Hashtable::hasher hasher; + typedef typename _Hashtable::key_equal key_equal; + typedef typename _Hashtable::allocator_type allocator_type; + //@} + + //@{ + /// Iterator-related typedefs. + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; + typedef typename _Hashtable::iterator iterator; + typedef typename _Hashtable::const_iterator const_iterator; + typedef typename _Hashtable::local_iterator local_iterator; + typedef typename _Hashtable::const_local_iterator const_local_iterator; + typedef typename _Hashtable::size_type size_type; + typedef typename _Hashtable::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; + using insert_return_type = typename _Hashtable::insert_return_type; +#endif + + //construct/destroy/copy + + /// Default constructor. + unordered_map() = default; + + /** + * @brief Default constructor creates no elements. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + */ + explicit + unordered_map(size_type __n, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__n, __hf, __eql, __a) + { } + + /** + * @brief Builds an %unordered_map from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_map consisting of copies of the elements from + * [__first,__last). This is linear in N (where N is + * distance(__first,__last)). + */ + template + unordered_map(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__first, __last, __n, __hf, __eql, __a) + { } + + /// Copy constructor. + unordered_map(const unordered_map&) = default; + + /// Move constructor. + unordered_map(unordered_map&&) = default; + + /** + * @brief Creates an %unordered_map with no elements. + * @param __a An allocator object. + */ + explicit + unordered_map(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_map to copy. + * @param __a An allocator object. + */ + unordered_map(const unordered_map& __umap, + const allocator_type& __a) + : _M_h(__umap._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_map to move. + * @param __a An allocator object. + */ + unordered_map(unordered_map&& __umap, + const allocator_type& __a) + : _M_h(std::move(__umap._M_h), __a) + { } + + /** + * @brief Builds an %unordered_map from an initializer_list. + * @param __l An initializer_list. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_map consisting of copies of the elements in the + * list. This is linear in N (where N is @a __l.size()). + */ + unordered_map(initializer_list __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__l, __n, __hf, __eql, __a) + { } + + unordered_map(size_type __n, const allocator_type& __a) + : unordered_map(__n, hasher(), key_equal(), __a) + { } + + unordered_map(size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_map(__n, __hf, key_equal(), __a) + { } + + template + unordered_map(_InputIterator __first, _InputIterator __last, + size_type __n, + const allocator_type& __a) + : unordered_map(__first, __last, __n, hasher(), key_equal(), __a) + { } + + template + unordered_map(_InputIterator __first, _InputIterator __last, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_map(__first, __last, __n, __hf, key_equal(), __a) + { } + + unordered_map(initializer_list __l, + size_type __n, + const allocator_type& __a) + : unordered_map(__l, __n, hasher(), key_equal(), __a) + { } + + unordered_map(initializer_list __l, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_map(__l, __n, __hf, key_equal(), __a) + { } + + /// Copy assignment operator. + unordered_map& + operator=(const unordered_map&) = default; + + /// Move assignment operator. + unordered_map& + operator=(unordered_map&&) = default; + + /** + * @brief %Unordered_map list assignment operator. + * @param __l An initializer_list. + * + * This function fills an %unordered_map with copies of the elements in + * the initializer list @a __l. + * + * Note that the assignment completely changes the %unordered_map and + * that the resulting %unordered_map's size is the same as the number + * of elements assigned. + */ + unordered_map& + operator=(initializer_list __l) + { + _M_h = __l; + return *this; + } + + /// Returns the allocator object used by the %unordered_map. + allocator_type + get_allocator() const noexcept + { return _M_h.get_allocator(); } + + // size and capacity: + + /// Returns true if the %unordered_map is empty. + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return _M_h.empty(); } + + /// Returns the size of the %unordered_map. + size_type + size() const noexcept + { return _M_h.size(); } + + /// Returns the maximum size of the %unordered_map. + size_type + max_size() const noexcept + { return _M_h.max_size(); } + + // iterators. + + /** + * Returns a read/write iterator that points to the first element in the + * %unordered_map. + */ + iterator + begin() noexcept + { return _M_h.begin(); } + + //@{ + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_map. + */ + const_iterator + begin() const noexcept + { return _M_h.begin(); } + + const_iterator + cbegin() const noexcept + { return _M_h.begin(); } + //@} + + /** + * Returns a read/write iterator that points one past the last element in + * the %unordered_map. + */ + iterator + end() noexcept + { return _M_h.end(); } + + //@{ + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_map. + */ + const_iterator + end() const noexcept + { return _M_h.end(); } + + const_iterator + cend() const noexcept + { return _M_h.end(); } + //@} + + // modifiers. + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_map. + * + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to build and insert a (key, value) %pair into + * the %unordered_map. + * An %unordered_map relies on unique keys and thus a %pair is only + * inserted if its first element (the key) is not already present in the + * %unordered_map. + * + * Insertion requires amortized constant time. + */ + template + std::pair + emplace(_Args&&... __args) + { return _M_h.emplace(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_map. + * + * @param __pos An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * @return An iterator that points to the element with key of the + * std::pair built from @a __args (may or may not be that + * std::pair). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator, node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)).position; } + +#define __cpp_lib_unordered_map_try_emplace 201411 + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_map. + * + * @param __k Key to use for finding a possibly existing pair in + * the unordered_map. + * @param __args Arguments used to generate the .second for a + * new pair instance. + * + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted pair, and the second is a bool that + * is true if the pair was actually inserted. + * + * This function attempts to build and insert a (key, value) %pair into + * the %unordered_map. + * An %unordered_map relies on unique keys and thus a %pair is only + * inserted if its first element (the key) is not already present in the + * %unordered_map. + * If a %pair is not inserted, this function has no effect. + * + * Insertion requires amortized constant time. + */ + template + pair + try_emplace(const key_type& __k, _Args&&... __args) + { + iterator __i = find(__k); + if (__i == end()) + { + __i = emplace(std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)) + .first; + return {__i, true}; + } + return {__i, false}; + } + + // move-capable overload + template + pair + try_emplace(key_type&& __k, _Args&&... __args) + { + iterator __i = find(__k); + if (__i == end()) + { + __i = emplace(std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)) + .first; + return {__i, true}; + } + return {__i, false}; + } + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_map. + * + * @param __hint An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __k Key to use for finding a possibly existing pair in + * the unordered_map. + * @param __args Arguments used to generate the .second for a + * new pair instance. + * @return An iterator that points to the element with key of the + * std::pair built from @a __args (may or may not be that + * std::pair). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. However, if insertion did not take place, + * this function has no effect. + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + template + iterator + try_emplace(const_iterator __hint, const key_type& __k, + _Args&&... __args) + { + iterator __i = find(__k); + if (__i == end()) + __i = emplace_hint(__hint, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return __i; + } + + // move-capable overload + template + iterator + try_emplace(const_iterator __hint, key_type&& __k, _Args&&... __args) + { + iterator __i = find(__k); + if (__i == end()) + __i = emplace_hint(__hint, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Args>(__args)...)); + return __i; + } +#endif // C++17 + + //@{ + /** + * @brief Attempts to insert a std::pair into the %unordered_map. + + * @param __x Pair to be inserted (see std::make_pair for easy + * creation of pairs). + * + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is + * a bool that is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the + * %unordered_map. An %unordered_map relies on unique keys and thus a + * %pair is only inserted if its first element (the key) is not already + * present in the %unordered_map. + * + * Insertion requires amortized constant time. + */ + std::pair + insert(const value_type& __x) + { return _M_h.insert(__x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + std::pair + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + + template + __enable_if_t::value, + pair> + insert(_Pair&& __x) + { return _M_h.emplace(std::forward<_Pair>(__x)); } + //@} + + //@{ + /** + * @brief Attempts to insert a std::pair into the %unordered_map. + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument insert() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + iterator + insert(const_iterator __hint, const value_type& __x) + { return _M_h.insert(__hint, __x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(const_iterator __hint, _Pair&& __x) + { return _M_h.emplace_hint(__hint, std::forward<_Pair>(__x)); } + //@} + + /** + * @brief A template function that attempts to insert a range of + * elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_h.insert(__first, __last); } + + /** + * @brief Attempts to insert a list of elements into the %unordered_map. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { _M_h.insert(__l); } + + +#if __cplusplus > 201402L + /** + * @brief Attempts to insert a std::pair into the %unordered_map. + * @param __k Key to use for finding a possibly existing pair in + * the map. + * @param __obj Argument used to generate the .second for a pair + * instance. + * + * @return A pair, of which the first element is an iterator that + * points to the possibly inserted pair, and the second is + * a bool that is true if the pair was actually inserted. + * + * This function attempts to insert a (key, value) %pair into the + * %unordered_map. An %unordered_map relies on unique keys and thus a + * %pair is only inserted if its first element (the key) is not already + * present in the %unordered_map. + * If the %pair was already in the %unordered_map, the .second of + * the %pair is assigned from __obj. + * + * Insertion requires amortized constant time. + */ + template + pair + insert_or_assign(const key_type& __k, _Obj&& __obj) + { + iterator __i = find(__k); + if (__i == end()) + { + __i = emplace(std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple(std::forward<_Obj>(__obj))) + .first; + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } + + // move-capable overload + template + pair + insert_or_assign(key_type&& __k, _Obj&& __obj) + { + iterator __i = find(__k); + if (__i == end()) + { + __i = emplace(std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple(std::forward<_Obj>(__obj))) + .first; + return {__i, true}; + } + (*__i).second = std::forward<_Obj>(__obj); + return {__i, false}; + } + + /** + * @brief Attempts to insert a std::pair into the %unordered_map. + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __k Key to use for finding a possibly existing pair in + * the unordered_map. + * @param __obj Argument used to generate the .second for a pair + * instance. + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument insert() + * does. + * If the %pair was already in the %unordered map, the .second of + * the %pair is assigned from __obj. + * Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + template + iterator + insert_or_assign(const_iterator __hint, const key_type& __k, + _Obj&& __obj) + { + iterator __i = find(__k); + if (__i == end()) + { + return emplace_hint(__hint, std::piecewise_construct, + std::forward_as_tuple(__k), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } + + // move-capable overload + template + iterator + insert_or_assign(const_iterator __hint, key_type&& __k, _Obj&& __obj) + { + iterator __i = find(__k); + if (__i == end()) + { + return emplace_hint(__hint, std::piecewise_construct, + std::forward_as_tuple(std::move(__k)), + std::forward_as_tuple( + std::forward<_Obj>(__obj))); + } + (*__i).second = std::forward<_Obj>(__obj); + return __i; + } +#endif + + //@{ + /** + * @brief Erases an element from an %unordered_map. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from an %unordered_map. + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __position) + { return _M_h.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_h.erase(__position); } + //@} + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * an %unordered_map. For an %unordered_map the result of this function + * can only be 0 (not present) or 1 (present). + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_h.erase(__x); } + + /** + * @brief Erases a [__first,__last) range of elements from an + * %unordered_map. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from an %unordered_map. + * Note that this function only erases the elements, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_h.erase(__first, __last); } + + /** + * Erases all elements in an %unordered_map. + * Note that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + clear() noexcept + { _M_h.clear(); } + + /** + * @brief Swaps data with another %unordered_map. + * @param __x An %unordered_map of the same element and allocator + * types. + * + * This exchanges the elements between two %unordered_map in constant + * time. + * Note that the global std::swap() function is specialized such that + * std::swap(m1,m2) will feed to this function. + */ + void + swap(unordered_map& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) + { _M_h.swap(__x._M_h); } + +#if __cplusplus > 201402L + template + friend class std::_Hash_merge_helper; + + template + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + + // observers. + + /// Returns the hash functor object with which the %unordered_map was + /// constructed. + hasher + hash_function() const + { return _M_h.hash_function(); } + + /// Returns the key comparison object with which the %unordered_map was + /// constructed. + key_equal + key_eq() const + { return _M_h.key_eq(); } + + // lookup. + + //@{ + /** + * @brief Tries to locate an element in an %unordered_map. + * @param __x Key to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_h.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_h.find(__x); } + //@} + + /** + * @brief Finds the number of elements. + * @param __x Key to count. + * @return Number of elements with specified key. + * + * This function only makes sense for %unordered_multimap; for + * %unordered_map the result will either be 0 (not present) or 1 + * (present). + */ + size_type + count(const key_type& __x) const + { return _M_h.count(__x); } + +#if __cplusplus > 201703L + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_h.find(__x) != _M_h.end(); } +#endif + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function probably only makes sense for %unordered_multimap. + */ + std::pair + equal_range(const key_type& __x) + { return _M_h.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_h.equal_range(__x); } + //@} + + //@{ + /** + * @brief Subscript ( @c [] ) access to %unordered_map data. + * @param __k The key for which data should be retrieved. + * @return A reference to the data of the (key,data) %pair. + * + * Allows for easy lookup with the subscript ( @c [] )operator. Returns + * data associated with the key specified in subscript. If the key does + * not exist, a pair with that key is created using default values, which + * is then returned. + * + * Lookup requires constant time. + */ + mapped_type& + operator[](const key_type& __k) + { return _M_h[__k]; } + + mapped_type& + operator[](key_type&& __k) + { return _M_h[std::move(__k)]; } + //@} + + //@{ + /** + * @brief Access to %unordered_map data. + * @param __k The key for which data should be retrieved. + * @return A reference to the data whose key is equal to @a __k, if + * such a data is present in the %unordered_map. + * @throw std::out_of_range If no such data is present. + */ + mapped_type& + at(const key_type& __k) + { return _M_h.at(__k); } + + const mapped_type& + at(const key_type& __k) const + { return _M_h.at(__k); } + //@} + + // bucket interface. + + /// Returns the number of buckets of the %unordered_map. + size_type + bucket_count() const noexcept + { return _M_h.bucket_count(); } + + /// Returns the maximum number of buckets of the %unordered_map. + size_type + max_bucket_count() const noexcept + { return _M_h.max_bucket_count(); } + + /* + * @brief Returns the number of elements in a given bucket. + * @param __n A bucket index. + * @return The number of elements in the bucket. + */ + size_type + bucket_size(size_type __n) const + { return _M_h.bucket_size(__n); } + + /* + * @brief Returns the bucket index of a given element. + * @param __key A key instance. + * @return The key bucket index. + */ + size_type + bucket(const key_type& __key) const + { return _M_h.bucket(__key); } + + /** + * @brief Returns a read/write iterator pointing to the first bucket + * element. + * @param __n The bucket index. + * @return A read/write local iterator. + */ + local_iterator + begin(size_type __n) + { return _M_h.begin(__n); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to the first + * bucket element. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + const_local_iterator + begin(size_type __n) const + { return _M_h.begin(__n); } + + const_local_iterator + cbegin(size_type __n) const + { return _M_h.cbegin(__n); } + //@} + + /** + * @brief Returns a read/write iterator pointing to one past the last + * bucket elements. + * @param __n The bucket index. + * @return A read/write local iterator. + */ + local_iterator + end(size_type __n) + { return _M_h.end(__n); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to one past + * the last bucket elements. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + const_local_iterator + end(size_type __n) const + { return _M_h.end(__n); } + + const_local_iterator + cend(size_type __n) const + { return _M_h.cend(__n); } + //@} + + // hash policy. + + /// Returns the average number of elements per bucket. + float + load_factor() const noexcept + { return _M_h.load_factor(); } + + /// Returns a positive number that the %unordered_map tries to keep the + /// load factor less than or equal to. + float + max_load_factor() const noexcept + { return _M_h.max_load_factor(); } + + /** + * @brief Change the %unordered_map maximum load factor. + * @param __z The new maximum load factor. + */ + void + max_load_factor(float __z) + { _M_h.max_load_factor(__z); } + + /** + * @brief May rehash the %unordered_map. + * @param __n The new number of buckets. + * + * Rehash will occur only if the new number of buckets respect the + * %unordered_map maximum load factor. + */ + void + rehash(size_type __n) + { _M_h.rehash(__n); } + + /** + * @brief Prepare the %unordered_map for a specified number of + * elements. + * @param __n Number of elements required. + * + * Same as rehash(ceil(n / max_load_factor())). + */ + void + reserve(size_type __n) + { _M_h.reserve(__n); } + + template + friend bool + operator==(const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&, + const unordered_map<_Key1, _Tp1, _Hash1, _Pred1, _Alloc1>&); + }; + +#if __cpp_deduction_guides >= 201606 + + template>, + typename _Pred = equal_to<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + _Hash, _Pred, _Allocator>; + + template, + typename _Pred = equal_to<_Key>, + typename _Allocator = allocator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list>, + typename unordered_map::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_map<_Key, _Tp, _Hash, _Pred, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map::size_type, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, + _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, + _Allocator>; + + template, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireAllocator<_Allocator>> + unordered_map(_InputIterator, _InputIterator, + typename unordered_map::size_type, + _Hash, _Allocator) + -> unordered_map<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template> + unordered_map(initializer_list>, + typename unordered_map::size_type, + _Allocator) + -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template> + unordered_map(initializer_list>, _Allocator) + -> unordered_map<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_map(initializer_list>, + typename unordered_map::size_type, + _Hash, _Allocator) + -> unordered_map<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; + +#endif + + /** + * @brief A standard container composed of equivalent keys + * (possibly containing multiple of each key value) that associates + * values of another type with the keys. + * + * @ingroup unordered_associative_containers + * + * @tparam _Key Type of key objects. + * @tparam _Tp Type of mapped objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Pred Predicate function object type, defaults + * to equal_to<_Value>. + * @tparam _Alloc Allocator type, defaults to + * std::allocator>. + * + * Meets the requirements of a container, and + * unordered associative container + * + * The resulting value type of the container is std::pair. + * + * Base is _Hashtable, dispatched at compile time via template + * alias __ummap_hashtable. + */ + template, + typename _Pred = equal_to<_Key>, + typename _Alloc = allocator>> + class unordered_multimap + { + typedef __ummap_hashtable<_Key, _Tp, _Hash, _Pred, _Alloc> _Hashtable; + _Hashtable _M_h; + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef typename _Hashtable::key_type key_type; + typedef typename _Hashtable::value_type value_type; + typedef typename _Hashtable::mapped_type mapped_type; + typedef typename _Hashtable::hasher hasher; + typedef typename _Hashtable::key_equal key_equal; + typedef typename _Hashtable::allocator_type allocator_type; + //@} + + //@{ + /// Iterator-related typedefs. + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; + typedef typename _Hashtable::iterator iterator; + typedef typename _Hashtable::const_iterator const_iterator; + typedef typename _Hashtable::local_iterator local_iterator; + typedef typename _Hashtable::const_local_iterator const_local_iterator; + typedef typename _Hashtable::size_type size_type; + typedef typename _Hashtable::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; +#endif + + //construct/destroy/copy + + /// Default constructor. + unordered_multimap() = default; + + /** + * @brief Default constructor creates no elements. + * @param __n Mnimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + */ + explicit + unordered_multimap(size_type __n, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__n, __hf, __eql, __a) + { } + + /** + * @brief Builds an %unordered_multimap from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_multimap consisting of copies of the elements + * from [__first,__last). This is linear in N (where N is + * distance(__first,__last)). + */ + template + unordered_multimap(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__first, __last, __n, __hf, __eql, __a) + { } + + /// Copy constructor. + unordered_multimap(const unordered_multimap&) = default; + + /// Move constructor. + unordered_multimap(unordered_multimap&&) = default; + + /** + * @brief Creates an %unordered_multimap with no elements. + * @param __a An allocator object. + */ + explicit + unordered_multimap(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_multimap to copy. + * @param __a An allocator object. + */ + unordered_multimap(const unordered_multimap& __ummap, + const allocator_type& __a) + : _M_h(__ummap._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_multimap to move. + * @param __a An allocator object. + */ + unordered_multimap(unordered_multimap&& __ummap, + const allocator_type& __a) + : _M_h(std::move(__ummap._M_h), __a) + { } + + /** + * @brief Builds an %unordered_multimap from an initializer_list. + * @param __l An initializer_list. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_multimap consisting of copies of the elements in + * the list. This is linear in N (where N is @a __l.size()). + */ + unordered_multimap(initializer_list __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__l, __n, __hf, __eql, __a) + { } + + unordered_multimap(size_type __n, const allocator_type& __a) + : unordered_multimap(__n, hasher(), key_equal(), __a) + { } + + unordered_multimap(size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multimap(__n, __hf, key_equal(), __a) + { } + + template + unordered_multimap(_InputIterator __first, _InputIterator __last, + size_type __n, + const allocator_type& __a) + : unordered_multimap(__first, __last, __n, hasher(), key_equal(), __a) + { } + + template + unordered_multimap(_InputIterator __first, _InputIterator __last, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multimap(__first, __last, __n, __hf, key_equal(), __a) + { } + + unordered_multimap(initializer_list __l, + size_type __n, + const allocator_type& __a) + : unordered_multimap(__l, __n, hasher(), key_equal(), __a) + { } + + unordered_multimap(initializer_list __l, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multimap(__l, __n, __hf, key_equal(), __a) + { } + + /// Copy assignment operator. + unordered_multimap& + operator=(const unordered_multimap&) = default; + + /// Move assignment operator. + unordered_multimap& + operator=(unordered_multimap&&) = default; + + /** + * @brief %Unordered_multimap list assignment operator. + * @param __l An initializer_list. + * + * This function fills an %unordered_multimap with copies of the + * elements in the initializer list @a __l. + * + * Note that the assignment completely changes the %unordered_multimap + * and that the resulting %unordered_multimap's size is the same as the + * number of elements assigned. + */ + unordered_multimap& + operator=(initializer_list __l) + { + _M_h = __l; + return *this; + } + + /// Returns the allocator object used by the %unordered_multimap. + allocator_type + get_allocator() const noexcept + { return _M_h.get_allocator(); } + + // size and capacity: + + /// Returns true if the %unordered_multimap is empty. + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return _M_h.empty(); } + + /// Returns the size of the %unordered_multimap. + size_type + size() const noexcept + { return _M_h.size(); } + + /// Returns the maximum size of the %unordered_multimap. + size_type + max_size() const noexcept + { return _M_h.max_size(); } + + // iterators. + + /** + * Returns a read/write iterator that points to the first element in the + * %unordered_multimap. + */ + iterator + begin() noexcept + { return _M_h.begin(); } + + //@{ + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_multimap. + */ + const_iterator + begin() const noexcept + { return _M_h.begin(); } + + const_iterator + cbegin() const noexcept + { return _M_h.begin(); } + //@} + + /** + * Returns a read/write iterator that points one past the last element in + * the %unordered_multimap. + */ + iterator + end() noexcept + { return _M_h.end(); } + + //@{ + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_multimap. + */ + const_iterator + end() const noexcept + { return _M_h.end(); } + + const_iterator + cend() const noexcept + { return _M_h.end(); } + //@} + + // modifiers. + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_multimap. + * + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * + * @return An iterator that points to the inserted pair. + * + * This function attempts to build and insert a (key, value) %pair into + * the %unordered_multimap. + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace(_Args&&... __args) + { return _M_h.emplace(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to build and insert a std::pair into the + * %unordered_multimap. + * + * @param __pos An iterator that serves as a hint as to where the pair + * should be inserted. + * @param __args Arguments used to generate a new pair instance (see + * std::piecewise_contruct for passing arguments to each + * part of the pair constructor). + * @return An iterator that points to the element with key of the + * std::pair built from @a __args. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } + + //@{ + /** + * @brief Inserts a std::pair into the %unordered_multimap. + * @param __x Pair to be inserted (see std::make_pair for easy + * creation of pairs). + * + * @return An iterator that points to the inserted pair. + * + * Insertion requires amortized constant time. + */ + iterator + insert(const value_type& __x) + { return _M_h.insert(__x); } + + iterator + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(_Pair&& __x) + { return _M_h.emplace(std::forward<_Pair>(__x)); } + //@} + + //@{ + /** + * @brief Inserts a std::pair into the %unordered_multimap. + * @param __hint An iterator that serves as a hint as to where the + * pair should be inserted. + * @param __x Pair to be inserted (see std::make_pair for easy creation + * of pairs). + * @return An iterator that points to the element with key of + * @a __x (may or may not be the %pair passed in). + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * See + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * for more on @a hinting. + * + * Insertion requires amortized constant time. + */ + iterator + insert(const_iterator __hint, const value_type& __x) + { return _M_h.insert(__hint, __x); } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2354. Unnecessary copying when inserting into maps with braced-init + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + + template + __enable_if_t::value, iterator> + insert(const_iterator __hint, _Pair&& __x) + { return _M_h.emplace_hint(__hint, std::forward<_Pair>(__x)); } + //@} + + /** + * @brief A template function that attempts to insert a range of + * elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_h.insert(__first, __last); } + + /** + * @brief Attempts to insert a list of elements into the + * %unordered_multimap. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { _M_h.insert(__l); } + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } +#endif // C++17 + + //@{ + /** + * @brief Erases an element from an %unordered_multimap. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from an %unordered_multimap. + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __position) + { return _M_h.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_h.erase(__position); } + //@} + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of elements to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * an %unordered_multimap. + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_h.erase(__x); } + + /** + * @brief Erases a [__first,__last) range of elements from an + * %unordered_multimap. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from an + * %unordered_multimap. + * Note that this function only erases the elements, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_h.erase(__first, __last); } + + /** + * Erases all elements in an %unordered_multimap. + * Note that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + clear() noexcept + { _M_h.clear(); } + + /** + * @brief Swaps data with another %unordered_multimap. + * @param __x An %unordered_multimap of the same element and allocator + * types. + * + * This exchanges the elements between two %unordered_multimap in + * constant time. + * Note that the global std::swap() function is specialized such that + * std::swap(m1,m2) will feed to this function. + */ + void + swap(unordered_multimap& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) + { _M_h.swap(__x._M_h); } + +#if __cplusplus > 201402L + template + friend class std::_Hash_merge_helper; + + template + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_multimap<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_map<_Key, _Tp, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + + // observers. + + /// Returns the hash functor object with which the %unordered_multimap + /// was constructed. + hasher + hash_function() const + { return _M_h.hash_function(); } + + /// Returns the key comparison object with which the %unordered_multimap + /// was constructed. + key_equal + key_eq() const + { return _M_h.key_eq(); } + + // lookup. + + //@{ + /** + * @brief Tries to locate an element in an %unordered_multimap. + * @param __x Key to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_h.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_h.find(__x); } + //@} + + /** + * @brief Finds the number of elements. + * @param __x Key to count. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const + { return _M_h.count(__x); } + +#if __cplusplus > 201703L + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_h.find(__x) != _M_h.end(); } +#endif + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + */ + std::pair + equal_range(const key_type& __x) + { return _M_h.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_h.equal_range(__x); } + //@} + + // bucket interface. + + /// Returns the number of buckets of the %unordered_multimap. + size_type + bucket_count() const noexcept + { return _M_h.bucket_count(); } + + /// Returns the maximum number of buckets of the %unordered_multimap. + size_type + max_bucket_count() const noexcept + { return _M_h.max_bucket_count(); } + + /* + * @brief Returns the number of elements in a given bucket. + * @param __n A bucket index. + * @return The number of elements in the bucket. + */ + size_type + bucket_size(size_type __n) const + { return _M_h.bucket_size(__n); } + + /* + * @brief Returns the bucket index of a given element. + * @param __key A key instance. + * @return The key bucket index. + */ + size_type + bucket(const key_type& __key) const + { return _M_h.bucket(__key); } + + /** + * @brief Returns a read/write iterator pointing to the first bucket + * element. + * @param __n The bucket index. + * @return A read/write local iterator. + */ + local_iterator + begin(size_type __n) + { return _M_h.begin(__n); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to the first + * bucket element. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + const_local_iterator + begin(size_type __n) const + { return _M_h.begin(__n); } + + const_local_iterator + cbegin(size_type __n) const + { return _M_h.cbegin(__n); } + //@} + + /** + * @brief Returns a read/write iterator pointing to one past the last + * bucket elements. + * @param __n The bucket index. + * @return A read/write local iterator. + */ + local_iterator + end(size_type __n) + { return _M_h.end(__n); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to one past + * the last bucket elements. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + const_local_iterator + end(size_type __n) const + { return _M_h.end(__n); } + + const_local_iterator + cend(size_type __n) const + { return _M_h.cend(__n); } + //@} + + // hash policy. + + /// Returns the average number of elements per bucket. + float + load_factor() const noexcept + { return _M_h.load_factor(); } + + /// Returns a positive number that the %unordered_multimap tries to keep + /// the load factor less than or equal to. + float + max_load_factor() const noexcept + { return _M_h.max_load_factor(); } + + /** + * @brief Change the %unordered_multimap maximum load factor. + * @param __z The new maximum load factor. + */ + void + max_load_factor(float __z) + { _M_h.max_load_factor(__z); } + + /** + * @brief May rehash the %unordered_multimap. + * @param __n The new number of buckets. + * + * Rehash will occur only if the new number of buckets respect the + * %unordered_multimap maximum load factor. + */ + void + rehash(size_type __n) + { _M_h.rehash(__n); } + + /** + * @brief Prepare the %unordered_multimap for a specified number of + * elements. + * @param __n Number of elements required. + * + * Same as rehash(ceil(n / max_load_factor())). + */ + void + reserve(size_type __n) + { _M_h.reserve(__n); } + + template + friend bool + operator==(const unordered_multimap<_Key1, _Tp1, + _Hash1, _Pred1, _Alloc1>&, + const unordered_multimap<_Key1, _Tp1, + _Hash1, _Pred1, _Alloc1>&); + }; + +#if __cpp_deduction_guides >= 201606 + + template>, + typename _Pred = equal_to<__iter_key_t<_InputIterator>>, + typename _Allocator = allocator<__iter_to_alloc_t<_InputIterator>>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, _Pred, + _Allocator>; + + template, + typename _Pred = equal_to<_Key>, + typename _Allocator = allocator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list>, + unordered_multimap::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multimap<_Key, _Tp, _Hash, _Pred, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap::size_type, _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, + hash<__iter_key_t<_InputIterator>>, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(_InputIterator, _InputIterator, + unordered_multimap::size_type, _Hash, + _Allocator) + -> unordered_multimap<__iter_key_t<_InputIterator>, + __iter_val_t<_InputIterator>, _Hash, + equal_to<__iter_key_t<_InputIterator>>, _Allocator>; + + template> + unordered_multimap(initializer_list>, + unordered_multimap::size_type, + _Allocator) + -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template> + unordered_multimap(initializer_list>, _Allocator) + -> unordered_multimap<_Key, _Tp, hash<_Key>, equal_to<_Key>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multimap(initializer_list>, + unordered_multimap::size_type, + _Hash, _Allocator) + -> unordered_multimap<_Key, _Tp, _Hash, equal_to<_Key>, _Allocator>; + +#endif + + template + inline void + swap(unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + inline void + swap(unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + inline bool + operator==(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return __x._M_h._M_equal(__y._M_h); } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline bool + operator!=(const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_map<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } +#endif + + template + inline bool + operator==(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return __x._M_h._M_equal(__y._M_h); } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline bool + operator!=(const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __x, + const unordered_multimap<_Key, _Tp, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } +#endif + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::unordered_map access to internals of compatible maps. + template + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template + using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>; + template + using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>; + + friend unordered_map<_Key, _Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + + static auto& + _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + }; + + // Allow std::unordered_multimap access to internals of compatible maps. + template + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template + using unordered_map = _GLIBCXX_STD_C::unordered_map<_Tp...>; + template + using unordered_multimap = _GLIBCXX_STD_C::unordered_multimap<_Tp...>; + + friend unordered_multimap<_Key, _Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_map<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + + static auto& + _S_get_table(unordered_multimap<_Key, _Val, _Hash2, _Eq2, _Alloc>& __map) + { return __map._M_h; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _UNORDERED_MAP_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/unordered_set.h b/resources/sources/avr-libstdcpp/include/bits/unordered_set.h new file mode 100644 index 000000000..c9c9e9f38 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/unordered_set.h @@ -0,0 +1,1783 @@ +// unordered_set implementation -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/unordered_set.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{unordered_set} + */ + +#ifndef _UNORDERED_SET_H +#define _UNORDERED_SET_H + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /// Base types for unordered_set. + template + using __uset_traits = __detail::_Hashtable_traits<_Cache, true, true>; + + template, + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value>, + typename _Tr = __uset_traits<__cache_default<_Value, _Hash>::value>> + using __uset_hashtable = _Hashtable<_Value, _Value, _Alloc, + __detail::_Identity, _Pred, _Hash, + __detail::_Mod_range_hashing, + __detail::_Default_ranged_hash, + __detail::_Prime_rehash_policy, _Tr>; + + /// Base types for unordered_multiset. + template + using __umset_traits = __detail::_Hashtable_traits<_Cache, true, false>; + + template, + typename _Pred = std::equal_to<_Value>, + typename _Alloc = std::allocator<_Value>, + typename _Tr = __umset_traits<__cache_default<_Value, _Hash>::value>> + using __umset_hashtable = _Hashtable<_Value, _Value, _Alloc, + __detail::_Identity, + _Pred, _Hash, + __detail::_Mod_range_hashing, + __detail::_Default_ranged_hash, + __detail::_Prime_rehash_policy, _Tr>; + + template + class unordered_multiset; + + /** + * @brief A standard container composed of unique keys (containing + * at most one of each key value) in which the elements' keys are + * the elements themselves. + * + * @ingroup unordered_associative_containers + * + * @tparam _Value Type of key objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + + * @tparam _Pred Predicate function object type, defaults to + * equal_to<_Value>. + * + * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * + * Meets the requirements of a container, and + * unordered associative container + * + * Base is _Hashtable, dispatched at compile time via template + * alias __uset_hashtable. + */ + template, + typename _Pred = equal_to<_Value>, + typename _Alloc = allocator<_Value>> + class unordered_set + { + typedef __uset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; + _Hashtable _M_h; + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef typename _Hashtable::key_type key_type; + typedef typename _Hashtable::value_type value_type; + typedef typename _Hashtable::hasher hasher; + typedef typename _Hashtable::key_equal key_equal; + typedef typename _Hashtable::allocator_type allocator_type; + //@} + + //@{ + /// Iterator-related typedefs. + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; + typedef typename _Hashtable::iterator iterator; + typedef typename _Hashtable::const_iterator const_iterator; + typedef typename _Hashtable::local_iterator local_iterator; + typedef typename _Hashtable::const_local_iterator const_local_iterator; + typedef typename _Hashtable::size_type size_type; + typedef typename _Hashtable::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; + using insert_return_type = typename _Hashtable::insert_return_type; +#endif + + // construct/destroy/copy + + /// Default constructor. + unordered_set() = default; + + /** + * @brief Default constructor creates no elements. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + */ + explicit + unordered_set(size_type __n, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__n, __hf, __eql, __a) + { } + + /** + * @brief Builds an %unordered_set from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_set consisting of copies of the elements from + * [__first,__last). This is linear in N (where N is + * distance(__first,__last)). + */ + template + unordered_set(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__first, __last, __n, __hf, __eql, __a) + { } + + /// Copy constructor. + unordered_set(const unordered_set&) = default; + + /// Move constructor. + unordered_set(unordered_set&&) = default; + + /** + * @brief Creates an %unordered_set with no elements. + * @param __a An allocator object. + */ + explicit + unordered_set(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_set to copy. + * @param __a An allocator object. + */ + unordered_set(const unordered_set& __uset, + const allocator_type& __a) + : _M_h(__uset._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __uset Input %unordered_set to move. + * @param __a An allocator object. + */ + unordered_set(unordered_set&& __uset, + const allocator_type& __a) + : _M_h(std::move(__uset._M_h), __a) + { } + + /** + * @brief Builds an %unordered_set from an initializer_list. + * @param __l An initializer_list. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_set consisting of copies of the elements in the + * list. This is linear in N (where N is @a __l.size()). + */ + unordered_set(initializer_list __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__l, __n, __hf, __eql, __a) + { } + + unordered_set(size_type __n, const allocator_type& __a) + : unordered_set(__n, hasher(), key_equal(), __a) + { } + + unordered_set(size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_set(__n, __hf, key_equal(), __a) + { } + + template + unordered_set(_InputIterator __first, _InputIterator __last, + size_type __n, + const allocator_type& __a) + : unordered_set(__first, __last, __n, hasher(), key_equal(), __a) + { } + + template + unordered_set(_InputIterator __first, _InputIterator __last, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_set(__first, __last, __n, __hf, key_equal(), __a) + { } + + unordered_set(initializer_list __l, + size_type __n, + const allocator_type& __a) + : unordered_set(__l, __n, hasher(), key_equal(), __a) + { } + + unordered_set(initializer_list __l, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_set(__l, __n, __hf, key_equal(), __a) + { } + + /// Copy assignment operator. + unordered_set& + operator=(const unordered_set&) = default; + + /// Move assignment operator. + unordered_set& + operator=(unordered_set&&) = default; + + /** + * @brief %Unordered_set list assignment operator. + * @param __l An initializer_list. + * + * This function fills an %unordered_set with copies of the elements in + * the initializer list @a __l. + * + * Note that the assignment completely changes the %unordered_set and + * that the resulting %unordered_set's size is the same as the number + * of elements assigned. + */ + unordered_set& + operator=(initializer_list __l) + { + _M_h = __l; + return *this; + } + + /// Returns the allocator object used by the %unordered_set. + allocator_type + get_allocator() const noexcept + { return _M_h.get_allocator(); } + + // size and capacity: + + /// Returns true if the %unordered_set is empty. + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return _M_h.empty(); } + + /// Returns the size of the %unordered_set. + size_type + size() const noexcept + { return _M_h.size(); } + + /// Returns the maximum size of the %unordered_set. + size_type + max_size() const noexcept + { return _M_h.max_size(); } + + // iterators. + + //@{ + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_set. + */ + iterator + begin() noexcept + { return _M_h.begin(); } + + const_iterator + begin() const noexcept + { return _M_h.begin(); } + //@} + + //@{ + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_set. + */ + iterator + end() noexcept + { return _M_h.end(); } + + const_iterator + end() const noexcept + { return _M_h.end(); } + //@} + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_set. + */ + const_iterator + cbegin() const noexcept + { return _M_h.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_set. + */ + const_iterator + cend() const noexcept + { return _M_h.end(); } + + // modifiers. + + /** + * @brief Attempts to build and insert an element into the + * %unordered_set. + * @param __args Arguments used to generate an element. + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted element, and the second is a bool + * that is true if the element was actually inserted. + * + * This function attempts to build and insert an element into the + * %unordered_set. An %unordered_set relies on unique keys and thus an + * element is only inserted if it is not already present in the + * %unordered_set. + * + * Insertion requires amortized constant time. + */ + template + std::pair + emplace(_Args&&... __args) + { return _M_h.emplace(std::forward<_Args>(__args)...); } + + /** + * @brief Attempts to insert an element into the %unordered_set. + * @param __pos An iterator that serves as a hint as to where the + * element should be inserted. + * @param __args Arguments used to generate the element to be + * inserted. + * @return An iterator that points to the element with key equivalent to + * the one generated from @a __args (may or may not be the + * element itself). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument emplace() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } + + //@{ + /** + * @brief Attempts to insert an element into the %unordered_set. + * @param __x Element to be inserted. + * @return A pair, of which the first element is an iterator that points + * to the possibly inserted element, and the second is a bool + * that is true if the element was actually inserted. + * + * This function attempts to insert an element into the %unordered_set. + * An %unordered_set relies on unique keys and thus an element is only + * inserted if it is not already present in the %unordered_set. + * + * Insertion requires amortized constant time. + */ + std::pair + insert(const value_type& __x) + { return _M_h.insert(__x); } + + std::pair + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + //@} + + //@{ + /** + * @brief Attempts to insert an element into the %unordered_set. + * @param __hint An iterator that serves as a hint as to where the + * element should be inserted. + * @param __x Element to be inserted. + * @return An iterator that points to the element with key of + * @a __x (may or may not be the element passed in). + * + * This function is not concerned about whether the insertion took place, + * and thus does not return a boolean like the single-argument insert() + * does. Note that the first parameter is only a hint and can + * potentially improve the performance of the insertion process. A bad + * hint would cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires amortized constant. + */ + iterator + insert(const_iterator __hint, const value_type& __x) + { return _M_h.insert(__hint, __x); } + + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + //@} + + /** + * @brief A template function that attempts to insert a range of + * elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_h.insert(__first, __last); } + + /** + * @brief Attempts to insert a list of elements into the %unordered_set. + * @param __l A std::initializer_list of elements + * to be inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { _M_h.insert(__l); } + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + insert_return_type + insert(node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator, node_type&& __nh) + { return _M_h._M_reinsert_node(std::move(__nh)).position; } +#endif // C++17 + + //@{ + /** + * @brief Erases an element from an %unordered_set. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from an %unordered_set. Note that this function only erases the + * element, and that if the element is itself a pointer, the pointed-to + * memory is not touched in any way. Managing the pointer is the user's + * responsibility. + */ + iterator + erase(const_iterator __position) + { return _M_h.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_h.erase(__position); } + //@} + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * an %unordered_set. For an %unordered_set the result of this function + * can only be 0 (not present) or 1 (present). + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_h.erase(__x); } + + /** + * @brief Erases a [__first,__last) range of elements from an + * %unordered_set. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from an %unordered_set. + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_h.erase(__first, __last); } + + /** + * Erases all elements in an %unordered_set. Note that this function only + * erases the elements, and that if the elements themselves are pointers, + * the pointed-to memory is not touched in any way. Managing the pointer + * is the user's responsibility. + */ + void + clear() noexcept + { _M_h.clear(); } + + /** + * @brief Swaps data with another %unordered_set. + * @param __x An %unordered_set of the same element and allocator + * types. + * + * This exchanges the elements between two sets in constant time. + * Note that the global std::swap() function is specialized such that + * std::swap(s1,s2) will feed to this function. + */ + void + swap(unordered_set& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) + { _M_h.swap(__x._M_h); } + +#if __cplusplus > 201402L + template + friend class std::_Hash_merge_helper; + + template + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper = _Hash_merge_helper; + _M_h._M_merge_unique(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + + // observers. + + /// Returns the hash functor object with which the %unordered_set was + /// constructed. + hasher + hash_function() const + { return _M_h.hash_function(); } + + /// Returns the key comparison object with which the %unordered_set was + /// constructed. + key_equal + key_eq() const + { return _M_h.key_eq(); } + + // lookup. + + //@{ + /** + * @brief Tries to locate an element in an %unordered_set. + * @param __x Element to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_h.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_h.find(__x); } + //@} + + /** + * @brief Finds the number of elements. + * @param __x Element to located. + * @return Number of elements with specified key. + * + * This function only makes sense for unordered_multisets; for + * unordered_set the result will either be 0 (not present) or 1 + * (present). + */ + size_type + count(const key_type& __x) const + { return _M_h.count(__x); } + +#if __cplusplus > 201703L + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_h.find(__x) != _M_h.end(); } +#endif + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + * + * This function probably only makes sense for multisets. + */ + std::pair + equal_range(const key_type& __x) + { return _M_h.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_h.equal_range(__x); } + //@} + + // bucket interface. + + /// Returns the number of buckets of the %unordered_set. + size_type + bucket_count() const noexcept + { return _M_h.bucket_count(); } + + /// Returns the maximum number of buckets of the %unordered_set. + size_type + max_bucket_count() const noexcept + { return _M_h.max_bucket_count(); } + + /* + * @brief Returns the number of elements in a given bucket. + * @param __n A bucket index. + * @return The number of elements in the bucket. + */ + size_type + bucket_size(size_type __n) const + { return _M_h.bucket_size(__n); } + + /* + * @brief Returns the bucket index of a given element. + * @param __key A key instance. + * @return The key bucket index. + */ + size_type + bucket(const key_type& __key) const + { return _M_h.bucket(__key); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to the first + * bucket element. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + local_iterator + begin(size_type __n) + { return _M_h.begin(__n); } + + const_local_iterator + begin(size_type __n) const + { return _M_h.begin(__n); } + + const_local_iterator + cbegin(size_type __n) const + { return _M_h.cbegin(__n); } + //@} + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to one past + * the last bucket elements. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + local_iterator + end(size_type __n) + { return _M_h.end(__n); } + + const_local_iterator + end(size_type __n) const + { return _M_h.end(__n); } + + const_local_iterator + cend(size_type __n) const + { return _M_h.cend(__n); } + //@} + + // hash policy. + + /// Returns the average number of elements per bucket. + float + load_factor() const noexcept + { return _M_h.load_factor(); } + + /// Returns a positive number that the %unordered_set tries to keep the + /// load factor less than or equal to. + float + max_load_factor() const noexcept + { return _M_h.max_load_factor(); } + + /** + * @brief Change the %unordered_set maximum load factor. + * @param __z The new maximum load factor. + */ + void + max_load_factor(float __z) + { _M_h.max_load_factor(__z); } + + /** + * @brief May rehash the %unordered_set. + * @param __n The new number of buckets. + * + * Rehash will occur only if the new number of buckets respect the + * %unordered_set maximum load factor. + */ + void + rehash(size_type __n) + { _M_h.rehash(__n); } + + /** + * @brief Prepare the %unordered_set for a specified number of + * elements. + * @param __n Number of elements required. + * + * Same as rehash(ceil(n / max_load_factor())). + */ + void + reserve(size_type __n) + { _M_h.reserve(__n); } + + template + friend bool + operator==(const unordered_set<_Value1, _Hash1, _Pred1, _Alloc1>&, + const unordered_set<_Value1, _Hash1, _Pred1, _Alloc1>&); + }; + +#if __cpp_deduction_guides >= 201606 + + template::value_type>, + typename _Pred = + equal_to::value_type>, + typename _Allocator = + allocator::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set::value_type, + _Hash, _Pred, _Allocator>; + + template, + typename _Pred = equal_to<_Tp>, + typename _Allocator = allocator<_Tp>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), _Allocator = _Allocator()) + -> unordered_set<_Tp, _Hash, _Pred, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set::size_type, _Allocator) + -> unordered_set::value_type, + hash< + typename iterator_traits<_InputIterator>::value_type>, + equal_to< + typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireAllocator<_Allocator>> + unordered_set(_InputIterator, _InputIterator, + unordered_set::size_type, + _Hash, _Allocator) + -> unordered_set::value_type, + _Hash, + equal_to< + typename iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template> + unordered_set(initializer_list<_Tp>, + unordered_set::size_type, _Allocator) + -> unordered_set<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_set(initializer_list<_Tp>, + unordered_set::size_type, _Hash, _Allocator) + -> unordered_set<_Tp, _Hash, equal_to<_Tp>, _Allocator>; + +#endif + + /** + * @brief A standard container composed of equivalent keys + * (possibly containing multiple of each key value) in which the + * elements' keys are the elements themselves. + * + * @ingroup unordered_associative_containers + * + * @tparam _Value Type of key objects. + * @tparam _Hash Hashing function object type, defaults to hash<_Value>. + * @tparam _Pred Predicate function object type, defaults + * to equal_to<_Value>. + * @tparam _Alloc Allocator type, defaults to allocator<_Key>. + * + * Meets the requirements of a container, and + * unordered associative container + * + * Base is _Hashtable, dispatched at compile time via template + * alias __umset_hashtable. + */ + template, + typename _Pred = equal_to<_Value>, + typename _Alloc = allocator<_Value>> + class unordered_multiset + { + typedef __umset_hashtable<_Value, _Hash, _Pred, _Alloc> _Hashtable; + _Hashtable _M_h; + + public: + // typedefs: + //@{ + /// Public typedefs. + typedef typename _Hashtable::key_type key_type; + typedef typename _Hashtable::value_type value_type; + typedef typename _Hashtable::hasher hasher; + typedef typename _Hashtable::key_equal key_equal; + typedef typename _Hashtable::allocator_type allocator_type; + //@} + + //@{ + /// Iterator-related typedefs. + typedef typename _Hashtable::pointer pointer; + typedef typename _Hashtable::const_pointer const_pointer; + typedef typename _Hashtable::reference reference; + typedef typename _Hashtable::const_reference const_reference; + typedef typename _Hashtable::iterator iterator; + typedef typename _Hashtable::const_iterator const_iterator; + typedef typename _Hashtable::local_iterator local_iterator; + typedef typename _Hashtable::const_local_iterator const_local_iterator; + typedef typename _Hashtable::size_type size_type; + typedef typename _Hashtable::difference_type difference_type; + //@} + +#if __cplusplus > 201402L + using node_type = typename _Hashtable::node_type; +#endif + + // construct/destroy/copy + + /// Default constructor. + unordered_multiset() = default; + + /** + * @brief Default constructor creates no elements. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + */ + explicit + unordered_multiset(size_type __n, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__n, __hf, __eql, __a) + { } + + /** + * @brief Builds an %unordered_multiset from a range. + * @param __first An input iterator. + * @param __last An input iterator. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_multiset consisting of copies of the elements + * from [__first,__last). This is linear in N (where N is + * distance(__first,__last)). + */ + template + unordered_multiset(_InputIterator __first, _InputIterator __last, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__first, __last, __n, __hf, __eql, __a) + { } + + /// Copy constructor. + unordered_multiset(const unordered_multiset&) = default; + + /// Move constructor. + unordered_multiset(unordered_multiset&&) = default; + + /** + * @brief Builds an %unordered_multiset from an initializer_list. + * @param __l An initializer_list. + * @param __n Minimal initial number of buckets. + * @param __hf A hash functor. + * @param __eql A key equality functor. + * @param __a An allocator object. + * + * Create an %unordered_multiset consisting of copies of the elements in + * the list. This is linear in N (where N is @a __l.size()). + */ + unordered_multiset(initializer_list __l, + size_type __n = 0, + const hasher& __hf = hasher(), + const key_equal& __eql = key_equal(), + const allocator_type& __a = allocator_type()) + : _M_h(__l, __n, __hf, __eql, __a) + { } + + /// Copy assignment operator. + unordered_multiset& + operator=(const unordered_multiset&) = default; + + /// Move assignment operator. + unordered_multiset& + operator=(unordered_multiset&&) = default; + + /** + * @brief Creates an %unordered_multiset with no elements. + * @param __a An allocator object. + */ + explicit + unordered_multiset(const allocator_type& __a) + : _M_h(__a) + { } + + /* + * @brief Copy constructor with allocator argument. + * @param __uset Input %unordered_multiset to copy. + * @param __a An allocator object. + */ + unordered_multiset(const unordered_multiset& __umset, + const allocator_type& __a) + : _M_h(__umset._M_h, __a) + { } + + /* + * @brief Move constructor with allocator argument. + * @param __umset Input %unordered_multiset to move. + * @param __a An allocator object. + */ + unordered_multiset(unordered_multiset&& __umset, + const allocator_type& __a) + : _M_h(std::move(__umset._M_h), __a) + { } + + unordered_multiset(size_type __n, const allocator_type& __a) + : unordered_multiset(__n, hasher(), key_equal(), __a) + { } + + unordered_multiset(size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multiset(__n, __hf, key_equal(), __a) + { } + + template + unordered_multiset(_InputIterator __first, _InputIterator __last, + size_type __n, + const allocator_type& __a) + : unordered_multiset(__first, __last, __n, hasher(), key_equal(), __a) + { } + + template + unordered_multiset(_InputIterator __first, _InputIterator __last, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multiset(__first, __last, __n, __hf, key_equal(), __a) + { } + + unordered_multiset(initializer_list __l, + size_type __n, + const allocator_type& __a) + : unordered_multiset(__l, __n, hasher(), key_equal(), __a) + { } + + unordered_multiset(initializer_list __l, + size_type __n, const hasher& __hf, + const allocator_type& __a) + : unordered_multiset(__l, __n, __hf, key_equal(), __a) + { } + + /** + * @brief %Unordered_multiset list assignment operator. + * @param __l An initializer_list. + * + * This function fills an %unordered_multiset with copies of the elements + * in the initializer list @a __l. + * + * Note that the assignment completely changes the %unordered_multiset + * and that the resulting %unordered_multiset's size is the same as the + * number of elements assigned. + */ + unordered_multiset& + operator=(initializer_list __l) + { + _M_h = __l; + return *this; + } + + /// Returns the allocator object used by the %unordered_multiset. + allocator_type + get_allocator() const noexcept + { return _M_h.get_allocator(); } + + // size and capacity: + + /// Returns true if the %unordered_multiset is empty. + _GLIBCXX_NODISCARD bool + empty() const noexcept + { return _M_h.empty(); } + + /// Returns the size of the %unordered_multiset. + size_type + size() const noexcept + { return _M_h.size(); } + + /// Returns the maximum size of the %unordered_multiset. + size_type + max_size() const noexcept + { return _M_h.max_size(); } + + // iterators. + + //@{ + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_multiset. + */ + iterator + begin() noexcept + { return _M_h.begin(); } + + const_iterator + begin() const noexcept + { return _M_h.begin(); } + //@} + + //@{ + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_multiset. + */ + iterator + end() noexcept + { return _M_h.end(); } + + const_iterator + end() const noexcept + { return _M_h.end(); } + //@} + + /** + * Returns a read-only (constant) iterator that points to the first + * element in the %unordered_multiset. + */ + const_iterator + cbegin() const noexcept + { return _M_h.begin(); } + + /** + * Returns a read-only (constant) iterator that points one past the last + * element in the %unordered_multiset. + */ + const_iterator + cend() const noexcept + { return _M_h.end(); } + + // modifiers. + + /** + * @brief Builds and insert an element into the %unordered_multiset. + * @param __args Arguments used to generate an element. + * @return An iterator that points to the inserted element. + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace(_Args&&... __args) + { return _M_h.emplace(std::forward<_Args>(__args)...); } + + /** + * @brief Inserts an element into the %unordered_multiset. + * @param __pos An iterator that serves as a hint as to where the + * element should be inserted. + * @param __args Arguments used to generate the element to be + * inserted. + * @return An iterator that points to the inserted element. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires amortized constant time. + */ + template + iterator + emplace_hint(const_iterator __pos, _Args&&... __args) + { return _M_h.emplace_hint(__pos, std::forward<_Args>(__args)...); } + + //@{ + /** + * @brief Inserts an element into the %unordered_multiset. + * @param __x Element to be inserted. + * @return An iterator that points to the inserted element. + * + * Insertion requires amortized constant time. + */ + iterator + insert(const value_type& __x) + { return _M_h.insert(__x); } + + iterator + insert(value_type&& __x) + { return _M_h.insert(std::move(__x)); } + //@} + + //@{ + /** + * @brief Inserts an element into the %unordered_multiset. + * @param __hint An iterator that serves as a hint as to where the + * element should be inserted. + * @param __x Element to be inserted. + * @return An iterator that points to the inserted element. + * + * Note that the first parameter is only a hint and can potentially + * improve the performance of the insertion process. A bad hint would + * cause no gains in efficiency. + * + * For more on @a hinting, see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/associative.html#containers.associative.insert_hints + * + * Insertion requires amortized constant. + */ + iterator + insert(const_iterator __hint, const value_type& __x) + { return _M_h.insert(__hint, __x); } + + iterator + insert(const_iterator __hint, value_type&& __x) + { return _M_h.insert(__hint, std::move(__x)); } + //@} + + /** + * @brief A template function that inserts a range of elements. + * @param __first Iterator pointing to the start of the range to be + * inserted. + * @param __last Iterator pointing to the end of the range. + * + * Complexity similar to that of the range constructor. + */ + template + void + insert(_InputIterator __first, _InputIterator __last) + { _M_h.insert(__first, __last); } + + /** + * @brief Inserts a list of elements into the %unordered_multiset. + * @param __l A std::initializer_list of elements to be + * inserted. + * + * Complexity similar to that of the range constructor. + */ + void + insert(initializer_list __l) + { _M_h.insert(__l); } + +#if __cplusplus > 201402L + /// Extract a node. + node_type + extract(const_iterator __pos) + { + __glibcxx_assert(__pos != end()); + return _M_h.extract(__pos); + } + + /// Extract a node. + node_type + extract(const key_type& __key) + { return _M_h.extract(__key); } + + /// Re-insert an extracted node. + iterator + insert(node_type&& __nh) + { return _M_h._M_reinsert_node_multi(cend(), std::move(__nh)); } + + /// Re-insert an extracted node. + iterator + insert(const_iterator __hint, node_type&& __nh) + { return _M_h._M_reinsert_node_multi(__hint, std::move(__nh)); } +#endif // C++17 + + //@{ + /** + * @brief Erases an element from an %unordered_multiset. + * @param __position An iterator pointing to the element to be erased. + * @return An iterator pointing to the element immediately following + * @a __position prior to the element being erased. If no such + * element exists, end() is returned. + * + * This function erases an element, pointed to by the given iterator, + * from an %unordered_multiset. + * + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __position) + { return _M_h.erase(__position); } + + // LWG 2059. + iterator + erase(iterator __position) + { return _M_h.erase(__position); } + //@} + + + /** + * @brief Erases elements according to the provided key. + * @param __x Key of element to be erased. + * @return The number of elements erased. + * + * This function erases all the elements located by the given key from + * an %unordered_multiset. + * + * Note that this function only erases the element, and that if the + * element is itself a pointer, the pointed-to memory is not touched in + * any way. Managing the pointer is the user's responsibility. + */ + size_type + erase(const key_type& __x) + { return _M_h.erase(__x); } + + /** + * @brief Erases a [__first,__last) range of elements from an + * %unordered_multiset. + * @param __first Iterator pointing to the start of the range to be + * erased. + * @param __last Iterator pointing to the end of the range to + * be erased. + * @return The iterator @a __last. + * + * This function erases a sequence of elements from an + * %unordered_multiset. + * + * Note that this function only erases the element, and that if + * the element is itself a pointer, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + iterator + erase(const_iterator __first, const_iterator __last) + { return _M_h.erase(__first, __last); } + + /** + * Erases all elements in an %unordered_multiset. + * + * Note that this function only erases the elements, and that if the + * elements themselves are pointers, the pointed-to memory is not touched + * in any way. Managing the pointer is the user's responsibility. + */ + void + clear() noexcept + { _M_h.clear(); } + + /** + * @brief Swaps data with another %unordered_multiset. + * @param __x An %unordered_multiset of the same element and allocator + * types. + * + * This exchanges the elements between two sets in constant time. + * Note that the global std::swap() function is specialized such that + * std::swap(s1,s2) will feed to this function. + */ + void + swap(unordered_multiset& __x) + noexcept( noexcept(_M_h.swap(__x._M_h)) ) + { _M_h.swap(__x._M_h); } + +#if __cplusplus > 201402L + template + friend class std::_Hash_merge_helper; + + template + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_multiset<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } + + template + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>& __source) + { + using _Merge_helper + = _Hash_merge_helper; + _M_h._M_merge_multi(_Merge_helper::_S_get_table(__source)); + } + + template + void + merge(unordered_set<_Value, _H2, _P2, _Alloc>&& __source) + { merge(__source); } +#endif // C++17 + + // observers. + + /// Returns the hash functor object with which the %unordered_multiset + /// was constructed. + hasher + hash_function() const + { return _M_h.hash_function(); } + + /// Returns the key comparison object with which the %unordered_multiset + /// was constructed. + key_equal + key_eq() const + { return _M_h.key_eq(); } + + // lookup. + + //@{ + /** + * @brief Tries to locate an element in an %unordered_multiset. + * @param __x Element to be located. + * @return Iterator pointing to sought-after element, or end() if not + * found. + * + * This function takes a key and tries to locate the element with which + * the key matches. If successful the function returns an iterator + * pointing to the sought after element. If unsuccessful it returns the + * past-the-end ( @c end() ) iterator. + */ + iterator + find(const key_type& __x) + { return _M_h.find(__x); } + + const_iterator + find(const key_type& __x) const + { return _M_h.find(__x); } + //@} + + /** + * @brief Finds the number of elements. + * @param __x Element to located. + * @return Number of elements with specified key. + */ + size_type + count(const key_type& __x) const + { return _M_h.count(__x); } + +#if __cplusplus > 201703L + /** + * @brief Finds whether an element with the given key exists. + * @param __x Key of elements to be located. + * @return True if there is any element with the specified key. + */ + bool + contains(const key_type& __x) const + { return _M_h.find(__x) != _M_h.end(); } +#endif + + //@{ + /** + * @brief Finds a subsequence matching given key. + * @param __x Key to be located. + * @return Pair of iterators that possibly points to the subsequence + * matching given key. + */ + std::pair + equal_range(const key_type& __x) + { return _M_h.equal_range(__x); } + + std::pair + equal_range(const key_type& __x) const + { return _M_h.equal_range(__x); } + //@} + + // bucket interface. + + /// Returns the number of buckets of the %unordered_multiset. + size_type + bucket_count() const noexcept + { return _M_h.bucket_count(); } + + /// Returns the maximum number of buckets of the %unordered_multiset. + size_type + max_bucket_count() const noexcept + { return _M_h.max_bucket_count(); } + + /* + * @brief Returns the number of elements in a given bucket. + * @param __n A bucket index. + * @return The number of elements in the bucket. + */ + size_type + bucket_size(size_type __n) const + { return _M_h.bucket_size(__n); } + + /* + * @brief Returns the bucket index of a given element. + * @param __key A key instance. + * @return The key bucket index. + */ + size_type + bucket(const key_type& __key) const + { return _M_h.bucket(__key); } + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to the first + * bucket element. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + local_iterator + begin(size_type __n) + { return _M_h.begin(__n); } + + const_local_iterator + begin(size_type __n) const + { return _M_h.begin(__n); } + + const_local_iterator + cbegin(size_type __n) const + { return _M_h.cbegin(__n); } + //@} + + //@{ + /** + * @brief Returns a read-only (constant) iterator pointing to one past + * the last bucket elements. + * @param __n The bucket index. + * @return A read-only local iterator. + */ + local_iterator + end(size_type __n) + { return _M_h.end(__n); } + + const_local_iterator + end(size_type __n) const + { return _M_h.end(__n); } + + const_local_iterator + cend(size_type __n) const + { return _M_h.cend(__n); } + //@} + + // hash policy. + + /// Returns the average number of elements per bucket. + float + load_factor() const noexcept + { return _M_h.load_factor(); } + + /// Returns a positive number that the %unordered_multiset tries to keep the + /// load factor less than or equal to. + float + max_load_factor() const noexcept + { return _M_h.max_load_factor(); } + + /** + * @brief Change the %unordered_multiset maximum load factor. + * @param __z The new maximum load factor. + */ + void + max_load_factor(float __z) + { _M_h.max_load_factor(__z); } + + /** + * @brief May rehash the %unordered_multiset. + * @param __n The new number of buckets. + * + * Rehash will occur only if the new number of buckets respect the + * %unordered_multiset maximum load factor. + */ + void + rehash(size_type __n) + { _M_h.rehash(__n); } + + /** + * @brief Prepare the %unordered_multiset for a specified number of + * elements. + * @param __n Number of elements required. + * + * Same as rehash(ceil(n / max_load_factor())). + */ + void + reserve(size_type __n) + { _M_h.reserve(__n); } + + template + friend bool + operator==(const unordered_multiset<_Value1, _Hash1, _Pred1, _Alloc1>&, + const unordered_multiset<_Value1, _Hash1, _Pred1, _Alloc1>&); + }; + + +#if __cpp_deduction_guides >= 201606 + + template::value_type>, + typename _Pred = + equal_to::value_type>, + typename _Allocator = + allocator::value_type>, + typename = _RequireInputIter<_InputIterator>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multiset::value_type, + _Hash, _Pred, _Allocator>; + + template, + typename _Pred = equal_to<_Tp>, + typename _Allocator = allocator<_Tp>, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireNotAllocator<_Pred>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset::size_type = {}, + _Hash = _Hash(), _Pred = _Pred(), + _Allocator = _Allocator()) + -> unordered_multiset<_Tp, _Hash, _Pred, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset::size_type, _Allocator) + -> unordered_multiset::value_type, + hash::value_type>, + equal_to::value_type>, + _Allocator>; + + template, + typename = _RequireNotAllocatorOrIntegral<_Hash>, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(_InputIterator, _InputIterator, + unordered_multiset::size_type, + _Hash, _Allocator) + -> unordered_multiset::value_type, + _Hash, + equal_to< + typename + iterator_traits<_InputIterator>::value_type>, + _Allocator>; + + template> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset::size_type, _Allocator) + -> unordered_multiset<_Tp, hash<_Tp>, equal_to<_Tp>, _Allocator>; + + template, + typename = _RequireAllocator<_Allocator>> + unordered_multiset(initializer_list<_Tp>, + unordered_multiset::size_type, _Hash, _Allocator) + -> unordered_multiset<_Tp, _Hash, equal_to<_Tp>, _Allocator>; + +#endif + + template + inline void + swap(unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + inline void + swap(unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + + template + inline bool + operator==(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + { return __x._M_h._M_equal(__y._M_h); } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline bool + operator!=(const unordered_set<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_set<_Value, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } +#endif + + template + inline bool + operator==(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + { return __x._M_h._M_equal(__y._M_h); } + +#if __cpp_impl_three_way_comparison < 201907L + template + inline bool + operator!=(const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __x, + const unordered_multiset<_Value, _Hash, _Pred, _Alloc>& __y) + { return !(__x == __y); } +#endif + +_GLIBCXX_END_NAMESPACE_CONTAINER + +#if __cplusplus > 201402L + // Allow std::unordered_set access to internals of compatible sets. + template + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_set<_Val, _Hash1, _Eq1, _Alloc>, _Hash2, _Eq2> + { + private: + template + using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>; + template + using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>; + + friend unordered_set<_Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + + static auto& + _S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + }; + + // Allow std::unordered_multiset access to internals of compatible sets. + template + struct _Hash_merge_helper< + _GLIBCXX_STD_C::unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>, + _Hash2, _Eq2> + { + private: + template + using unordered_set = _GLIBCXX_STD_C::unordered_set<_Tp...>; + template + using unordered_multiset = _GLIBCXX_STD_C::unordered_multiset<_Tp...>; + + friend unordered_multiset<_Val, _Hash1, _Eq1, _Alloc>; + + static auto& + _S_get_table(unordered_set<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + + static auto& + _S_get_table(unordered_multiset<_Val, _Hash2, _Eq2, _Alloc>& __set) + { return __set._M_h; } + }; +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _UNORDERED_SET_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h b/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h new file mode 100644 index 000000000..1832d40d6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/uses_allocator.h @@ -0,0 +1,195 @@ +// Uses-allocator Construction -*- C++ -*- + +// Copyright (C) 2010-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +#ifndef _USES_ALLOCATOR_H +#define _USES_ALLOCATOR_H 1 + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // This is used for std::experimental::erased_type from Library Fundamentals. + struct __erased_type { }; + + // This also supports the "type-erased allocator" protocol from the + // Library Fundamentals TS, where allocator_type is erased_type. + // The second condition will always be false for types not using the TS. + template + using __is_erased_or_convertible + = __or_, is_same<_Tp, __erased_type>>; + + /// [allocator.tag] + struct allocator_arg_t { explicit allocator_arg_t() = default; }; + + _GLIBCXX17_INLINE constexpr allocator_arg_t allocator_arg = + allocator_arg_t(); + + template> + struct __uses_allocator_helper + : false_type { }; + + template + struct __uses_allocator_helper<_Tp, _Alloc, + __void_t> + : __is_erased_or_convertible<_Alloc, typename _Tp::allocator_type>::type + { }; + + /// [allocator.uses.trait] + template + struct uses_allocator + : __uses_allocator_helper<_Tp, _Alloc>::type + { }; + + struct __uses_alloc_base { }; + + struct __uses_alloc0 : __uses_alloc_base + { + struct _Sink { void _GLIBCXX20_CONSTEXPR operator=(const void*) { } } _M_a; + }; + + template + struct __uses_alloc1 : __uses_alloc_base { const _Alloc* _M_a; }; + + template + struct __uses_alloc2 : __uses_alloc_base { const _Alloc* _M_a; }; + + template + struct __uses_alloc; + + template + struct __uses_alloc + : conditional< + is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>::value, + __uses_alloc1<_Alloc>, + __uses_alloc2<_Alloc>>::type + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2586. Wrong value category used in scoped_allocator_adaptor::construct + static_assert(__or_< + is_constructible<_Tp, allocator_arg_t, const _Alloc&, _Args...>, + is_constructible<_Tp, _Args..., const _Alloc&>>::value, + "construction with an allocator must be possible" + " if uses_allocator is true"); + }; + + template + struct __uses_alloc + : __uses_alloc0 { }; + + template + using __uses_alloc_t = + __uses_alloc::value, _Tp, _Alloc, _Args...>; + + template + _GLIBCXX20_CONSTEXPR + inline __uses_alloc_t<_Tp, _Alloc, _Args...> + __use_alloc(const _Alloc& __a) + { + __uses_alloc_t<_Tp, _Alloc, _Args...> __ret; + __ret._M_a = std::__addressof(__a); + return __ret; + } + + template + void + __use_alloc(const _Alloc&&) = delete; + +#if __cplusplus > 201402L + template + inline constexpr bool uses_allocator_v = + uses_allocator<_Tp, _Alloc>::value; +#endif // C++17 + + template class _Predicate, + typename _Tp, typename _Alloc, typename... _Args> + struct __is_uses_allocator_predicate + : conditional::value, + __or_<_Predicate<_Tp, allocator_arg_t, _Alloc, _Args...>, + _Predicate<_Tp, _Args..., _Alloc>>, + _Predicate<_Tp, _Args...>>::type { }; + + template + struct __is_uses_allocator_constructible + : __is_uses_allocator_predicate + { }; + +#if __cplusplus >= 201402L + template + _GLIBCXX17_INLINE constexpr bool __is_uses_allocator_constructible_v = + __is_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; +#endif // C++14 + + template + struct __is_nothrow_uses_allocator_constructible + : __is_uses_allocator_predicate + { }; + + +#if __cplusplus >= 201402L + template + _GLIBCXX17_INLINE constexpr bool + __is_nothrow_uses_allocator_constructible_v = + __is_nothrow_uses_allocator_constructible<_Tp, _Alloc, _Args...>::value; +#endif // C++14 + + template + void __uses_allocator_construct_impl(__uses_alloc0 __a, _Tp* __ptr, + _Args&&... __args) + { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)...); } + + template + void __uses_allocator_construct_impl(__uses_alloc1<_Alloc> __a, _Tp* __ptr, + _Args&&... __args) + { + ::new ((void*)__ptr) _Tp(allocator_arg, *__a._M_a, + std::forward<_Args>(__args)...); + } + + template + void __uses_allocator_construct_impl(__uses_alloc2<_Alloc> __a, _Tp* __ptr, + _Args&&... __args) + { ::new ((void*)__ptr) _Tp(std::forward<_Args>(__args)..., *__a._M_a); } + + template + void __uses_allocator_construct(const _Alloc& __a, _Tp* __ptr, + _Args&&... __args) + { + std::__uses_allocator_construct_impl( + std::__use_alloc<_Tp, _Alloc, _Args...>(__a), __ptr, + std::forward<_Args>(__args)...); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif +#endif diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_after.h b/resources/sources/avr-libstdcpp/include/bits/valarray_after.h new file mode 100644 index 000000000..cf84e17e5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/valarray_after.h @@ -0,0 +1,556 @@ +// The template and inlines for the -*- C++ -*- internal _Meta class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/valarray_after.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _VALARRAY_AFTER_H +#define _VALARRAY_AFTER_H 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __detail +{ + // + // gslice_array closure. + // + template + class _GBase + { + public: + typedef typename _Dom::value_type value_type; + + _GBase (const _Dom& __e, const valarray& __i) + : _M_expr (__e), _M_index(__i) {} + + value_type + operator[] (size_t __i) const + { return _M_expr[_M_index[__i]]; } + + size_t + size () const + { return _M_index.size(); } + + private: + typename _ValArrayRef<_Dom>::__type _M_expr; + const valarray& _M_index; + }; + + template + class _GBase<_Array<_Tp> > + { + public: + typedef _Tp value_type; + + _GBase (_Array<_Tp> __a, const valarray& __i) + : _M_array (__a), _M_index(__i) {} + + value_type + operator[] (size_t __i) const + { return _M_array._M_data[_M_index[__i]]; } + + size_t + size () const + { return _M_index.size(); } + + private: + const _Array<_Tp> _M_array; + const valarray& _M_index; + }; + + template + struct _GClos<_Expr, _Dom> + : _GBase<_Dom> + { + typedef _GBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _GClos (const _Dom& __e, const valarray& __i) + : _Base (__e, __i) {} + }; + + template + struct _GClos<_ValArray, _Tp> + : _GBase<_Array<_Tp> > + { + typedef _GBase<_Array<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _GClos (_Array<_Tp> __a, const valarray& __i) + : _Base (__a, __i) {} + }; + + // + // indirect_array closure + // + template + class _IBase + { + public: + typedef typename _Dom::value_type value_type; + + _IBase (const _Dom& __e, const valarray& __i) + : _M_expr (__e), _M_index (__i) {} + + value_type + operator[] (size_t __i) const + { return _M_expr[_M_index[__i]]; } + + size_t + size() const + { return _M_index.size(); } + + private: + typename _ValArrayRef<_Dom>::__type _M_expr; + const valarray& _M_index; + }; + + template + struct _IClos<_Expr, _Dom> + : _IBase<_Dom> + { + typedef _IBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _IClos (const _Dom& __e, const valarray& __i) + : _Base (__e, __i) {} + }; + + template + struct _IClos<_ValArray, _Tp> + : _IBase > + { + typedef _IBase > _Base; + typedef _Tp value_type; + + _IClos (const valarray<_Tp>& __a, const valarray& __i) + : _Base (__a, __i) {} + }; +} // namespace __detail + + // + // class _Expr + // + template + class _Expr + { + public: + typedef _Tp value_type; + + _Expr(const _Clos&); + + const _Clos& operator()() const; + + value_type operator[](size_t) const; + valarray operator[](slice) const; + valarray operator[](const gslice&) const; + valarray operator[](const valarray&) const; + valarray operator[](const valarray&) const; + + _Expr<_UnClos<__unary_plus, std::_Expr, _Clos>, value_type> + operator+() const; + + _Expr<_UnClos<__negate, std::_Expr, _Clos>, value_type> + operator-() const; + + _Expr<_UnClos<__bitwise_not, std::_Expr, _Clos>, value_type> + operator~() const; + + _Expr<_UnClos<__logical_not, std::_Expr, _Clos>, bool> + operator!() const; + + size_t size() const; + value_type sum() const; + + valarray shift(int) const; + valarray cshift(int) const; + + value_type min() const; + value_type max() const; + + valarray apply(value_type (*)(const value_type&)) const; + valarray apply(value_type (*)(value_type)) const; + + private: + const _Clos _M_closure; + }; + + template + inline + _Expr<_Clos, _Tp>::_Expr(const _Clos& __c) : _M_closure(__c) {} + + template + inline const _Clos& + _Expr<_Clos, _Tp>::operator()() const + { return _M_closure; } + + template + inline _Tp + _Expr<_Clos, _Tp>::operator[](size_t __i) const + { return _M_closure[__i]; } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::operator[](slice __s) const + { + valarray<_Tp> __v = valarray<_Tp>(*this)[__s]; + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::operator[](const gslice& __gs) const + { + valarray<_Tp> __v = valarray<_Tp>(*this)[__gs]; + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::operator[](const valarray& __m) const + { + valarray<_Tp> __v = valarray<_Tp>(*this)[__m]; + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::operator[](const valarray& __i) const + { + valarray<_Tp> __v = valarray<_Tp>(*this)[__i]; + return __v; + } + + template + inline size_t + _Expr<_Clos, _Tp>::size() const + { return _M_closure.size(); } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::shift(int __n) const + { + valarray<_Tp> __v = valarray<_Tp>(*this).shift(__n); + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::cshift(int __n) const + { + valarray<_Tp> __v = valarray<_Tp>(*this).cshift(__n); + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::apply(_Tp __f(const _Tp&)) const + { + valarray<_Tp> __v = valarray<_Tp>(*this).apply(__f); + return __v; + } + + template + inline valarray<_Tp> + _Expr<_Clos, _Tp>::apply(_Tp __f(_Tp)) const + { + valarray<_Tp> __v = valarray<_Tp>(*this).apply(__f); + return __v; + } + + // XXX: replace this with a more robust summation algorithm. + template + inline _Tp + _Expr<_Clos, _Tp>::sum() const + { + size_t __n = _M_closure.size(); + if (__n == 0) + return _Tp(); + else + { + _Tp __s = _M_closure[--__n]; + while (__n != 0) + __s += _M_closure[--__n]; + return __s; + } + } + + template + inline _Tp + _Expr<_Clos, _Tp>::min() const + { return __valarray_min(_M_closure); } + + template + inline _Tp + _Expr<_Clos, _Tp>::max() const + { return __valarray_max(_M_closure); } + + template + inline _Expr<_UnClos<__logical_not, _Expr, _Dom>, bool> + _Expr<_Dom, _Tp>::operator!() const + { + typedef _UnClos<__logical_not, std::_Expr, _Dom> _Closure; + return _Expr<_Closure, bool>(_Closure(this->_M_closure)); + } + +#define _DEFINE_EXPR_UNARY_OPERATOR(_Op, _Name) \ + template \ + inline _Expr<_UnClos<_Name, std::_Expr, _Dom>, _Tp> \ + _Expr<_Dom, _Tp>::operator _Op() const \ + { \ + typedef _UnClos<_Name, std::_Expr, _Dom> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(this->_M_closure)); \ + } + + _DEFINE_EXPR_UNARY_OPERATOR(+, __unary_plus) + _DEFINE_EXPR_UNARY_OPERATOR(-, __negate) + _DEFINE_EXPR_UNARY_OPERATOR(~, __bitwise_not) + +#undef _DEFINE_EXPR_UNARY_OPERATOR + +#define _DEFINE_EXPR_BINARY_OPERATOR(_Op, _Name) \ + template \ + inline _Expr<_BinClos<_Name, _Expr, _Expr, _Dom1, _Dom2>, \ + typename __fun<_Name, typename _Dom1::value_type>::result_type> \ + operator _Op(const _Expr<_Dom1, typename _Dom1::value_type>& __v, \ + const _Expr<_Dom2, typename _Dom2::value_type>& __w) \ + { \ + typedef typename _Dom1::value_type _Arg; \ + typedef typename __fun<_Name, _Arg>::result_type _Value; \ + typedef _BinClos<_Name, _Expr, _Expr, _Dom1, _Dom2> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__v(), __w())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _Expr, _Constant, _Dom, \ + typename _Dom::value_type>, \ + typename __fun<_Name, typename _Dom::value_type>::result_type> \ + operator _Op(const _Expr<_Dom, typename _Dom::value_type>& __v, \ + const typename _Dom::value_type& __t) \ + { \ + typedef typename _Dom::value_type _Arg; \ + typedef typename __fun<_Name, _Arg>::result_type _Value; \ + typedef _BinClos<_Name, _Expr, _Constant, _Dom, _Arg> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__v(), __t)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _Constant, _Expr, \ + typename _Dom::value_type, _Dom>, \ + typename __fun<_Name, typename _Dom::value_type>::result_type> \ + operator _Op(const typename _Dom::value_type& __t, \ + const _Expr<_Dom, typename _Dom::value_type>& __v) \ + { \ + typedef typename _Dom::value_type _Arg; \ + typedef typename __fun<_Name, _Arg>::result_type _Value; \ + typedef _BinClos<_Name, _Constant, _Expr, _Arg, _Dom> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__t, __v())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _Expr, _ValArray, \ + _Dom, typename _Dom::value_type>, \ + typename __fun<_Name, typename _Dom::value_type>::result_type> \ + operator _Op(const _Expr<_Dom,typename _Dom::value_type>& __e, \ + const valarray& __v) \ + { \ + typedef typename _Dom::value_type _Arg; \ + typedef typename __fun<_Name, _Arg>::result_type _Value; \ + typedef _BinClos<_Name, _Expr, _ValArray, _Dom, _Arg> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__e(), __v)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _ValArray, _Expr, \ + typename _Dom::value_type, _Dom>, \ + typename __fun<_Name, typename _Dom::value_type>::result_type> \ + operator _Op(const valarray& __v, \ + const _Expr<_Dom, typename _Dom::value_type>& __e) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef typename __fun<_Name, _Tp>::result_type _Value; \ + typedef _BinClos<_Name, _ValArray, _Expr, _Tp, _Dom> _Closure; \ + return _Expr<_Closure, _Value>(_Closure(__v, __e ())); \ + } + + _DEFINE_EXPR_BINARY_OPERATOR(+, __plus) + _DEFINE_EXPR_BINARY_OPERATOR(-, __minus) + _DEFINE_EXPR_BINARY_OPERATOR(*, __multiplies) + _DEFINE_EXPR_BINARY_OPERATOR(/, __divides) + _DEFINE_EXPR_BINARY_OPERATOR(%, __modulus) + _DEFINE_EXPR_BINARY_OPERATOR(^, __bitwise_xor) + _DEFINE_EXPR_BINARY_OPERATOR(&, __bitwise_and) + _DEFINE_EXPR_BINARY_OPERATOR(|, __bitwise_or) + _DEFINE_EXPR_BINARY_OPERATOR(<<, __shift_left) + _DEFINE_EXPR_BINARY_OPERATOR(>>, __shift_right) + _DEFINE_EXPR_BINARY_OPERATOR(&&, __logical_and) + _DEFINE_EXPR_BINARY_OPERATOR(||, __logical_or) + _DEFINE_EXPR_BINARY_OPERATOR(==, __equal_to) + _DEFINE_EXPR_BINARY_OPERATOR(!=, __not_equal_to) + _DEFINE_EXPR_BINARY_OPERATOR(<, __less) + _DEFINE_EXPR_BINARY_OPERATOR(>, __greater) + _DEFINE_EXPR_BINARY_OPERATOR(<=, __less_equal) + _DEFINE_EXPR_BINARY_OPERATOR(>=, __greater_equal) + +#undef _DEFINE_EXPR_BINARY_OPERATOR + +#define _DEFINE_EXPR_UNARY_FUNCTION(_Name, _UName) \ + template \ + inline _Expr<_UnClos<_UName, _Expr, _Dom>, \ + typename _Dom::value_type> \ + _Name(const _Expr<_Dom, typename _Dom::value_type>& __e) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _UnClos<_UName, _Expr, _Dom> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__e())); \ + } \ + \ + template \ + inline _Expr<_UnClos<_UName, _ValArray, _Tp>, _Tp> \ + _Name(const valarray<_Tp>& __v) \ + { \ + typedef _UnClos<_UName, _ValArray, _Tp> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__v)); \ + } + + _DEFINE_EXPR_UNARY_FUNCTION(abs, _Abs) + _DEFINE_EXPR_UNARY_FUNCTION(cos, _Cos) + _DEFINE_EXPR_UNARY_FUNCTION(acos, _Acos) + _DEFINE_EXPR_UNARY_FUNCTION(cosh, _Cosh) + _DEFINE_EXPR_UNARY_FUNCTION(sin, _Sin) + _DEFINE_EXPR_UNARY_FUNCTION(asin, _Asin) + _DEFINE_EXPR_UNARY_FUNCTION(sinh, _Sinh) + _DEFINE_EXPR_UNARY_FUNCTION(tan, _Tan) + _DEFINE_EXPR_UNARY_FUNCTION(tanh, _Tanh) + _DEFINE_EXPR_UNARY_FUNCTION(atan, _Atan) + _DEFINE_EXPR_UNARY_FUNCTION(exp, _Exp) + _DEFINE_EXPR_UNARY_FUNCTION(log, _Log) + _DEFINE_EXPR_UNARY_FUNCTION(log10, _Log10) + _DEFINE_EXPR_UNARY_FUNCTION(sqrt, _Sqrt) + +#undef _DEFINE_EXPR_UNARY_FUNCTION + +#define _DEFINE_EXPR_BINARY_FUNCTION(_Fun, _UFun) \ + template \ + inline _Expr<_BinClos<_UFun, _Expr, _Expr, _Dom1, _Dom2>, \ + typename _Dom1::value_type> \ + _Fun(const _Expr<_Dom1, typename _Dom1::value_type>& __e1, \ + const _Expr<_Dom2, typename _Dom2::value_type>& __e2) \ + { \ + typedef typename _Dom1::value_type _Tp; \ + typedef _BinClos<_UFun, _Expr, _Expr, _Dom1, _Dom2> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__e1(), __e2())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _Expr, _ValArray, _Dom, \ + typename _Dom::value_type>, \ + typename _Dom::value_type> \ + _Fun(const _Expr<_Dom, typename _Dom::value_type>& __e, \ + const valarray& __v) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_UFun, _Expr, _ValArray, _Dom, _Tp> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__e(), __v)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _ValArray, _Expr, \ + typename _Dom::value_type, _Dom>, \ + typename _Dom::value_type> \ + _Fun(const valarray& __v, \ + const _Expr<_Dom, typename _Dom::value_type>& __e) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_UFun, _ValArray, _Expr, _Tp, _Dom> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__v, __e())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _Expr, _Constant, _Dom, \ + typename _Dom::value_type>, \ + typename _Dom::value_type> \ + _Fun(const _Expr<_Dom, typename _Dom::value_type>& __e, \ + const typename _Dom::value_type& __t) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_UFun, _Expr, _Constant, _Dom, _Tp> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__e(), __t)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _Constant, _Expr, \ + typename _Dom::value_type, _Dom>, \ + typename _Dom::value_type> \ + _Fun(const typename _Dom::value_type& __t, \ + const _Expr<_Dom, typename _Dom::value_type>& __e) \ + { \ + typedef typename _Dom::value_type _Tp; \ + typedef _BinClos<_UFun, _Constant, _Expr, _Tp, _Dom> _Closure; \ + return _Expr<_Closure, _Tp>(_Closure(__t, __e())); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _ValArray, _ValArray, _Tp, _Tp>, _Tp> \ + _Fun(const valarray<_Tp>& __v, const valarray<_Tp>& __w) \ + { \ + typedef _BinClos<_UFun, _ValArray, _ValArray, _Tp, _Tp> _Closure;\ + return _Expr<_Closure, _Tp>(_Closure(__v, __w)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _ValArray, _Constant, _Tp, _Tp>, _Tp> \ + _Fun(const valarray<_Tp>& __v, \ + const typename valarray<_Tp>::value_type& __t) \ + { \ + typedef _BinClos<_UFun, _ValArray, _Constant, _Tp, _Tp> _Closure;\ + return _Expr<_Closure, _Tp>(_Closure(__v, __t)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_UFun, _Constant, _ValArray, _Tp, _Tp>, _Tp> \ + _Fun(const typename valarray<_Tp>::value_type& __t, \ + const valarray<_Tp>& __v) \ + { \ + typedef _BinClos<_UFun, _Constant, _ValArray, _Tp, _Tp> _Closure;\ + return _Expr<_Closure, _Tp>(_Closure(__t, __v)); \ + } + +_DEFINE_EXPR_BINARY_FUNCTION(atan2, _Atan2) +_DEFINE_EXPR_BINARY_FUNCTION(pow, _Pow) + +#undef _DEFINE_EXPR_BINARY_FUNCTION + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _CPP_VALARRAY_AFTER_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_array.h b/resources/sources/avr-libstdcpp/include/bits/valarray_array.h new file mode 100644 index 000000000..041fbbe25 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/valarray_array.h @@ -0,0 +1,677 @@ +// The template and inlines for the -*- C++ -*- internal _Array helper class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/valarray_array.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _VALARRAY_ARRAY_H +#define _VALARRAY_ARRAY_H 1 + +#pragma GCC system_header + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // + // Helper functions on raw pointers + // + + // We get memory the old fashioned way + template + _Tp* + __valarray_get_storage(size_t) __attribute__((__malloc__)); + + template + inline _Tp* + __valarray_get_storage(size_t __n) + { return static_cast<_Tp*>(operator new(__n * sizeof(_Tp))); } + + // Return memory to the system + inline void + __valarray_release_memory(void* __p) + { operator delete(__p); } + + // Turn a raw-memory into an array of _Tp filled with _Tp() + // This is required in 'valarray v(n);' + template + struct _Array_default_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(_Tp* __b, _Tp* __e) + { + while (__b != __e) + new(__b++) _Tp(); + } + }; + + template + struct _Array_default_ctor<_Tp, true> + { + // For fundamental types, it suffices to say 'memset()' + inline static void + _S_do_it(_Tp* __b, _Tp* __e) + { __builtin_memset(__b, 0, (__e - __b) * sizeof(_Tp)); } + }; + + template + inline void + __valarray_default_construct(_Tp* __b, _Tp* __e) + { + _Array_default_ctor<_Tp, __is_scalar<_Tp>::__value>::_S_do_it(__b, __e); + } + + // Turn a raw-memory into an array of _Tp filled with __t + // This is the required in valarray v(n, t). Also + // used in valarray<>::resize(). + template + struct _Array_init_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t) + { + while (__b != __e) + new(__b++) _Tp(__t); + } + }; + + template + struct _Array_init_ctor<_Tp, true> + { + inline static void + _S_do_it(_Tp* __b, _Tp* __e, const _Tp __t) + { + while (__b != __e) + *__b++ = __t; + } + }; + + template + inline void + __valarray_fill_construct(_Tp* __b, _Tp* __e, const _Tp __t) + { + _Array_init_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __t); + } + + // + // copy-construct raw array [__o, *) from plain array [__b, __e) + // We can't just say 'memcpy()' + // + template + struct _Array_copy_ctor + { + // Please note that this isn't exception safe. But + // valarrays aren't required to be exception safe. + inline static void + _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) + { + while (__b != __e) + new(__o++) _Tp(*__b++); + } + }; + + template + struct _Array_copy_ctor<_Tp, true> + { + inline static void + _S_do_it(const _Tp* __b, const _Tp* __e, _Tp* __restrict__ __o) + { + if (__b) + __builtin_memcpy(__o, __b, (__e - __b) * sizeof(_Tp)); + } + }; + + template + inline void + __valarray_copy_construct(const _Tp* __b, const _Tp* __e, + _Tp* __restrict__ __o) + { + _Array_copy_ctor<_Tp, __is_trivial(_Tp)>::_S_do_it(__b, __e, __o); + } + + // copy-construct raw array [__o, *) from strided array __a[<__n : __s>] + template + inline void + __valarray_copy_construct (const _Tp* __restrict__ __a, size_t __n, + size_t __s, _Tp* __restrict__ __o) + { + if (__is_trivial(_Tp)) + while (__n--) + { + *__o++ = *__a; + __a += __s; + } + else + while (__n--) + { + new(__o++) _Tp(*__a); + __a += __s; + } + } + + // copy-construct raw array [__o, *) from indexed array __a[__i[<__n>]] + template + inline void + __valarray_copy_construct (const _Tp* __restrict__ __a, + const size_t* __restrict__ __i, + _Tp* __restrict__ __o, size_t __n) + { + if (__is_trivial(_Tp)) + while (__n--) + *__o++ = __a[*__i++]; + else + while (__n--) + new (__o++) _Tp(__a[*__i++]); + } + + // Do the necessary cleanup when we're done with arrays. + template + inline void + __valarray_destroy_elements(_Tp* __b, _Tp* __e) + { + if (!__is_trivial(_Tp)) + while (__b != __e) + { + __b->~_Tp(); + ++__b; + } + } + + // Fill a plain array __a[<__n>] with __t + template + inline void + __valarray_fill(_Tp* __restrict__ __a, size_t __n, const _Tp& __t) + { + while (__n--) + *__a++ = __t; + } + + // fill strided array __a[<__n-1 : __s>] with __t + template + inline void + __valarray_fill(_Tp* __restrict__ __a, size_t __n, + size_t __s, const _Tp& __t) + { + for (size_t __i = 0; __i < __n; ++__i, __a += __s) + *__a = __t; + } + + // fill indirect array __a[__i[<__n>]] with __i + template + inline void + __valarray_fill(_Tp* __restrict__ __a, const size_t* __restrict__ __i, + size_t __n, const _Tp& __t) + { + for (size_t __j = 0; __j < __n; ++__j, ++__i) + __a[*__i] = __t; + } + + // copy plain array __a[<__n>] in __b[<__n>] + // For non-fundamental types, it is wrong to say 'memcpy()' + template + struct _Array_copier + { + inline static void + _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) + { + while(__n--) + *__b++ = *__a++; + } + }; + + template + struct _Array_copier<_Tp, true> + { + inline static void + _S_do_it(const _Tp* __restrict__ __a, size_t __n, _Tp* __restrict__ __b) + { + if (__n != 0) + __builtin_memcpy(__b, __a, __n * sizeof (_Tp)); + } + }; + + // Copy a plain array __a[<__n>] into a play array __b[<>] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, size_t __n, + _Tp* __restrict__ __b) + { + _Array_copier<_Tp, __is_trivial(_Tp)>::_S_do_it(__a, __n, __b); + } + + // Copy strided array __a[<__n : __s>] in plain __b[<__n>] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, size_t __n, size_t __s, + _Tp* __restrict__ __b) + { + for (size_t __i = 0; __i < __n; ++__i, ++__b, __a += __s) + *__b = *__a; + } + + // Copy a plain array __a[<__n>] into a strided array __b[<__n : __s>] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, _Tp* __restrict__ __b, + size_t __n, size_t __s) + { + for (size_t __i = 0; __i < __n; ++__i, ++__a, __b += __s) + *__b = *__a; + } + + // Copy strided array __src[<__n : __s1>] into another + // strided array __dst[< : __s2>]. Their sizes must match. + template + inline void + __valarray_copy(const _Tp* __restrict__ __src, size_t __n, size_t __s1, + _Tp* __restrict__ __dst, size_t __s2) + { + for (size_t __i = 0; __i < __n; ++__i) + __dst[__i * __s2] = __src[__i * __s1]; + } + + // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, + const size_t* __restrict__ __i, + _Tp* __restrict__ __b, size_t __n) + { + for (size_t __j = 0; __j < __n; ++__j, ++__b, ++__i) + *__b = __a[*__i]; + } + + // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]] + template + inline void + __valarray_copy(const _Tp* __restrict__ __a, size_t __n, + _Tp* __restrict__ __b, const size_t* __restrict__ __i) + { + for (size_t __j = 0; __j < __n; ++__j, ++__a, ++__i) + __b[*__i] = *__a; + } + + // Copy the __n first elements of an indexed array __src[<__i>] into + // another indexed array __dst[<__j>]. + template + inline void + __valarray_copy(const _Tp* __restrict__ __src, size_t __n, + const size_t* __restrict__ __i, + _Tp* __restrict__ __dst, const size_t* __restrict__ __j) + { + for (size_t __k = 0; __k < __n; ++__k) + __dst[*__j++] = __src[*__i++]; + } + + // + // Compute the sum of elements in range [__f, __l) which must not be empty. + // This is a naive algorithm. It suffers from cancelling. + // In the future try to specialize for _Tp = float, double, long double + // using a more accurate algorithm. + // + template + inline _Tp + __valarray_sum(const _Tp* __f, const _Tp* __l) + { + _Tp __r = *__f++; + while (__f != __l) + __r += *__f++; + return __r; + } + + // Compute the min/max of an array-expression + template + inline typename _Ta::value_type + __valarray_min(const _Ta& __a) + { + size_t __s = __a.size(); + typedef typename _Ta::value_type _Value_type; + _Value_type __r = __s == 0 ? _Value_type() : __a[0]; + for (size_t __i = 1; __i < __s; ++__i) + { + _Value_type __t = __a[__i]; + if (__t < __r) + __r = __t; + } + return __r; + } + + template + inline typename _Ta::value_type + __valarray_max(const _Ta& __a) + { + size_t __s = __a.size(); + typedef typename _Ta::value_type _Value_type; + _Value_type __r = __s == 0 ? _Value_type() : __a[0]; + for (size_t __i = 1; __i < __s; ++__i) + { + _Value_type __t = __a[__i]; + if (__t > __r) + __r = __t; + } + return __r; + } + + // + // Helper class _Array, first layer of valarray abstraction. + // All operations on valarray should be forwarded to this class + // whenever possible. -- gdr + // + + template + struct _Array + { + explicit _Array(_Tp* const __restrict__); + explicit _Array(const valarray<_Tp>&); + _Array(const _Tp* __restrict__, size_t); + + _Tp* begin() const; + + _Tp* const __restrict__ _M_data; + }; + + + // Copy-construct plain array __b[<__n>] from indexed array __a[__i[<__n>]] + template + inline void + __valarray_copy_construct(_Array<_Tp> __a, _Array __i, + _Array<_Tp> __b, size_t __n) + { std::__valarray_copy_construct(__a._M_data, __i._M_data, + __b._M_data, __n); } + + // Copy-construct plain array __b[<__n>] from strided array __a[<__n : __s>] + template + inline void + __valarray_copy_construct(_Array<_Tp> __a, size_t __n, size_t __s, + _Array<_Tp> __b) + { std::__valarray_copy_construct(__a._M_data, __n, __s, __b._M_data); } + + template + inline void + __valarray_fill (_Array<_Tp> __a, size_t __n, const _Tp& __t) + { std::__valarray_fill(__a._M_data, __n, __t); } + + template + inline void + __valarray_fill(_Array<_Tp> __a, size_t __n, size_t __s, const _Tp& __t) + { std::__valarray_fill(__a._M_data, __n, __s, __t); } + + template + inline void + __valarray_fill(_Array<_Tp> __a, _Array __i, + size_t __n, const _Tp& __t) + { std::__valarray_fill(__a._M_data, __i._M_data, __n, __t); } + + // Copy a plain array __a[<__n>] into a play array __b[<>] + template + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) + { std::__valarray_copy(__a._M_data, __n, __b._M_data); } + + // Copy strided array __a[<__n : __s>] in plain __b[<__n>] + template + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s, _Array<_Tp> __b) + { std::__valarray_copy(__a._M_data, __n, __s, __b._M_data); } + + // Copy a plain array __a[<__n>] into a strided array __b[<__n : __s>] + template + inline void + __valarray_copy(_Array<_Tp> __a, _Array<_Tp> __b, size_t __n, size_t __s) + { __valarray_copy(__a._M_data, __b._M_data, __n, __s); } + + // Copy strided array __src[<__n : __s1>] into another + // strided array __dst[< : __s2>]. Their sizes must match. + template + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, size_t __s1, + _Array<_Tp> __b, size_t __s2) + { std::__valarray_copy(__a._M_data, __n, __s1, __b._M_data, __s2); } + + // Copy an indexed array __a[__i[<__n>]] in plain array __b[<__n>] + template + inline void + __valarray_copy(_Array<_Tp> __a, _Array __i, + _Array<_Tp> __b, size_t __n) + { std::__valarray_copy(__a._M_data, __i._M_data, __b._M_data, __n); } + + // Copy a plain array __a[<__n>] in an indexed array __b[__i[<__n>]] + template + inline void + __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, + _Array __i) + { std::__valarray_copy(__a._M_data, __n, __b._M_data, __i._M_data); } + + // Copy the __n first elements of an indexed array __src[<__i>] into + // another indexed array __dst[<__j>]. + template + inline void + __valarray_copy(_Array<_Tp> __src, size_t __n, _Array __i, + _Array<_Tp> __dst, _Array __j) + { + std::__valarray_copy(__src._M_data, __n, __i._M_data, + __dst._M_data, __j._M_data); + } + + template + inline + _Array<_Tp>::_Array(_Tp* const __restrict__ __p) + : _M_data (__p) {} + + template + inline + _Array<_Tp>::_Array(const valarray<_Tp>& __v) + : _M_data (__v._M_data) {} + + template + inline + _Array<_Tp>::_Array(const _Tp* __restrict__ __b, size_t __s) + : _M_data(__valarray_get_storage<_Tp>(__s)) + { std::__valarray_copy_construct(__b, __s, _M_data); } + + template + inline _Tp* + _Array<_Tp>::begin () const + { return _M_data; } + +#define _DEFINE_ARRAY_FUNCTION(_Op, _Name) \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, const _Tp& __t) \ + { \ + for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; ++__p) \ + *__p _Op##= __t; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b) \ + { \ + _Tp* __p = __a._M_data; \ + for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; ++__p, ++__q) \ + *__p _Op##= *__q; \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ + { \ + _Tp* __p(__a._M_data); \ + for (size_t __i = 0; __i < __n; ++__i, ++__p) \ + *__p _Op##= __e[__i]; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, size_t __s, \ + _Array<_Tp> __b) \ + { \ + _Tp* __q(__b._M_data); \ + for (_Tp* __p = __a._M_data; __p < __a._M_data + __s * __n; \ + __p += __s, ++__q) \ + *__p _Op##= *__q; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array<_Tp> __b, \ + size_t __n, size_t __s) \ + { \ + _Tp* __q(__b._M_data); \ + for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; \ + ++__p, __q += __s) \ + *__p _Op##= *__q; \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __s, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ + { \ + _Tp* __p(__a._M_data); \ + for (size_t __i = 0; __i < __n; ++__i, __p += __s) \ + *__p _Op##= __e[__i]; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array __i, \ + _Array<_Tp> __b, size_t __n) \ + { \ + _Tp* __q(__b._M_data); \ + for (size_t* __j = __i._M_data; __j < __i._M_data + __n; \ + ++__j, ++__q) \ + __a._M_data[*__j] _Op##= *__q; \ + } \ + \ + template \ + inline void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, \ + _Array<_Tp> __b, _Array __i) \ + { \ + _Tp* __p(__a._M_data); \ + for (size_t* __j = __i._M_data; __j<__i._M_data + __n; \ + ++__j, ++__p) \ + *__p _Op##= __b._M_data[*__j]; \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array __i, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ + { \ + size_t* __j(__i._M_data); \ + for (size_t __k = 0; __k<__n; ++__k, ++__j) \ + __a._M_data[*__j] _Op##= __e[__k]; \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array __m, \ + _Array<_Tp> __b, size_t __n) \ + { \ + bool* __ok(__m._M_data); \ + _Tp* __p(__a._M_data); \ + for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; \ + ++__q, ++__ok, ++__p) \ + { \ + while (! *__ok) \ + { \ + ++__ok; \ + ++__p; \ + } \ + *__p _Op##= *__q; \ + } \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, size_t __n, \ + _Array<_Tp> __b, _Array __m) \ + { \ + bool* __ok(__m._M_data); \ + _Tp* __q(__b._M_data); \ + for (_Tp* __p = __a._M_data; __p < __a._M_data + __n; \ + ++__p, ++__ok, ++__q) \ + { \ + while (! *__ok) \ + { \ + ++__ok; \ + ++__q; \ + } \ + *__p _Op##= *__q; \ + } \ + } \ + \ + template \ + void \ + _Array_augmented_##_Name(_Array<_Tp> __a, _Array __m, \ + const _Expr<_Dom, _Tp>& __e, size_t __n) \ + { \ + bool* __ok(__m._M_data); \ + _Tp* __p(__a._M_data); \ + for (size_t __i = 0; __i < __n; ++__i, ++__ok, ++__p) \ + { \ + while (! *__ok) \ + { \ + ++__ok; \ + ++__p; \ + } \ + *__p _Op##= __e[__i]; \ + } \ + } + + _DEFINE_ARRAY_FUNCTION(+, __plus) + _DEFINE_ARRAY_FUNCTION(-, __minus) + _DEFINE_ARRAY_FUNCTION(*, __multiplies) + _DEFINE_ARRAY_FUNCTION(/, __divides) + _DEFINE_ARRAY_FUNCTION(%, __modulus) + _DEFINE_ARRAY_FUNCTION(^, __bitwise_xor) + _DEFINE_ARRAY_FUNCTION(|, __bitwise_or) + _DEFINE_ARRAY_FUNCTION(&, __bitwise_and) + _DEFINE_ARRAY_FUNCTION(<<, __shift_left) + _DEFINE_ARRAY_FUNCTION(>>, __shift_right) + +#undef _DEFINE_ARRAY_FUNCTION + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +# include + +#endif /* _ARRAY_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc b/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc new file mode 100644 index 000000000..f97b780bc --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/valarray_array.tcc @@ -0,0 +1,244 @@ +// The template and inlines for the -*- C++ -*- internal _Array helper class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/valarray_array.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _VALARRAY_ARRAY_TCC +#define _VALARRAY_ARRAY_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + void + __valarray_fill(_Array<_Tp> __a, size_t __n, _Array __m, + const _Tp& __t) + { + _Tp* __p = __a._M_data; + bool* __ok (__m._M_data); + for (size_t __i=0; __i < __n; ++__i, ++__ok, ++__p) + { + while (!*__ok) + { + ++__ok; + ++__p; + } + *__p = __t; + } + } + + // Copy n elements of a into consecutive elements of b. When m is + // false, the corresponding element of a is skipped. m must contain + // at least n true elements. a must contain at least n elements and + // enough elements to match up with m through the nth true element + // of m. I.e. if n is 10, m has 15 elements with 5 false followed + // by 10 true, a must have 15 elements. + template + void + __valarray_copy(_Array<_Tp> __a, _Array __m, _Array<_Tp> __b, + size_t __n) + { + _Tp* __p (__a._M_data); + bool* __ok (__m._M_data); + for (_Tp* __q = __b._M_data; __q < __b._M_data + __n; + ++__q, ++__ok, ++__p) + { + while (! *__ok) + { + ++__ok; + ++__p; + } + *__q = *__p; + } + } + + // Copy n consecutive elements from a into elements of b. Elements + // of b are skipped if the corresponding element of m is false. m + // must contain at least n true elements. b must have at least as + // many elements as the index of the nth true element of m. I.e. if + // m has 15 elements with 5 false followed by 10 true, b must have + // at least 15 elements. + template + void + __valarray_copy(_Array<_Tp> __a, size_t __n, _Array<_Tp> __b, + _Array __m) + { + _Tp* __q (__b._M_data); + bool* __ok (__m._M_data); + for (_Tp* __p = __a._M_data; __p < __a._M_data+__n; + ++__p, ++__ok, ++__q) + { + while (! *__ok) + { + ++__ok; + ++__q; + } + *__q = *__p; + } + } + + // Copy n elements from a into elements of b. Elements of a are + // skipped if the corresponding element of m is false. Elements of + // b are skipped if the corresponding element of k is false. m and + // k must contain at least n true elements. a and b must have at + // least as many elements as the index of the nth true element of m. + template + void + __valarray_copy(_Array<_Tp> __a, _Array __m, size_t __n, + _Array<_Tp> __b, _Array __k) + { + _Tp* __p (__a._M_data); + _Tp* __q (__b._M_data); + bool* __srcok (__m._M_data); + bool* __dstok (__k._M_data); + for (size_t __i = 0; __i < __n; + ++__srcok, ++__p, ++__dstok, ++__q, ++__i) + { + while (! *__srcok) + { + ++__srcok; + ++__p; + } + while (! *__dstok) + { + ++__dstok; + ++__q; + } + *__q = *__p; + } + } + + // Copy n consecutive elements of e into consecutive elements of a. + // I.e. a[i] = e[i]. + template + void + __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, _Array<_Tp> __a) + { + _Tp* __p (__a._M_data); + for (size_t __i = 0; __i < __n; ++__i, ++__p) + *__p = __e[__i]; + } + + // Copy n consecutive elements of e into elements of a using stride + // s. I.e., a[0] = e[0], a[s] = e[1], a[2*s] = e[2]. + template + void + __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, size_t __s) + { + _Tp* __p (__a._M_data); + for (size_t __i = 0; __i < __n; ++__i, __p += __s) + *__p = __e[__i]; + } + + // Copy n consecutive elements of e into elements of a indexed by + // contents of i. I.e., a[i[0]] = e[0]. + template + void + __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, _Array __i) + { + size_t* __j (__i._M_data); + for (size_t __k = 0; __k < __n; ++__k, ++__j) + __a._M_data[*__j] = __e[__k]; + } + + // Copy n elements of e indexed by contents of f into elements of a + // indexed by contents of i. I.e., a[i[0]] = e[f[0]]. + template + void + __valarray_copy(_Array<_Tp> __e, _Array __f, + size_t __n, + _Array<_Tp> __a, _Array __i) + { + size_t* __g (__f._M_data); + size_t* __j (__i._M_data); + for (size_t __k = 0; __k < __n; ++__k, ++__j, ++__g) + __a._M_data[*__j] = __e._M_data[*__g]; + } + + // Copy n consecutive elements of e into elements of a. Elements of + // a are skipped if the corresponding element of m is false. m must + // have at least n true elements and a must have at least as many + // elements as the index of the nth true element of m. I.e. if m + // has 5 false followed by 10 true elements and n == 10, a must have + // at least 15 elements. + template + void + __valarray_copy(const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a, _Array __m) + { + bool* __ok (__m._M_data); + _Tp* __p (__a._M_data); + for (size_t __i = 0; __i < __n; ++__i, ++__ok, ++__p) + { + while (! *__ok) + { + ++__ok; + ++__p; + } + *__p = __e[__i]; + } + } + + + template + void + __valarray_copy_construct(const _Expr<_Dom, _Tp>& __e, size_t __n, + _Array<_Tp> __a) + { + _Tp* __p (__a._M_data); + for (size_t __i = 0; __i < __n; ++__i, ++__p) + new (__p) _Tp(__e[__i]); + } + + + template + void + __valarray_copy_construct(_Array<_Tp> __a, _Array __m, + _Array<_Tp> __b, size_t __n) + { + _Tp* __p (__a._M_data); + bool* __ok (__m._M_data); + for (_Tp* __q = __b._M_data; __q < __b._M_data+__n; ++__q, ++__ok, ++__p) + { + while (! *__ok) + { + ++__ok; + ++__p; + } + new (__q) _Tp(*__p); + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _VALARRAY_ARRAY_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bits/valarray_before.h b/resources/sources/avr-libstdcpp/include/bits/valarray_before.h new file mode 100644 index 000000000..5c1c1c82a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/valarray_before.h @@ -0,0 +1,758 @@ +// The template and inlines for the -*- C++ -*- internal _Meta class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file bits/valarray_before.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{valarray} + */ + +// Written by Gabriel Dos Reis + +#ifndef _VALARRAY_BEFORE_H +#define _VALARRAY_BEFORE_H 1 + +#pragma GCC system_header + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // + // Implementing a loosened valarray return value is tricky. + // First we need to meet 26.3.1/3: we should not add more than + // two levels of template nesting. Therefore we resort to template + // template to "flatten" loosened return value types. + // At some point we use partial specialization to remove one level + // template nesting due to _Expr<> + // + + // This class is NOT defined. It doesn't need to. + template class _Constant; + + // Implementations of unary functions applied to valarray<>s. + // I use hard-coded object functions here instead of a generic + // approach like pointers to function: + // 1) correctness: some functions take references, others values. + // we can't deduce the correct type afterwards. + // 2) efficiency -- object functions can be easily inlined + // 3) be Koenig-lookup-friendly + + struct _Abs + { + template + _Tp operator()(const _Tp& __t) const + { return abs(__t); } + }; + + struct _Cos + { + template + _Tp operator()(const _Tp& __t) const + { return cos(__t); } + }; + + struct _Acos + { + template + _Tp operator()(const _Tp& __t) const + { return acos(__t); } + }; + + struct _Cosh + { + template + _Tp operator()(const _Tp& __t) const + { return cosh(__t); } + }; + + struct _Sin + { + template + _Tp operator()(const _Tp& __t) const + { return sin(__t); } + }; + + struct _Asin + { + template + _Tp operator()(const _Tp& __t) const + { return asin(__t); } + }; + + struct _Sinh + { + template + _Tp operator()(const _Tp& __t) const + { return sinh(__t); } + }; + + struct _Tan + { + template + _Tp operator()(const _Tp& __t) const + { return tan(__t); } + }; + + struct _Atan + { + template + _Tp operator()(const _Tp& __t) const + { return atan(__t); } + }; + + struct _Tanh + { + template + _Tp operator()(const _Tp& __t) const + { return tanh(__t); } + }; + + struct _Exp + { + template + _Tp operator()(const _Tp& __t) const + { return exp(__t); } + }; + + struct _Log + { + template + _Tp operator()(const _Tp& __t) const + { return log(__t); } + }; + + struct _Log10 + { + template + _Tp operator()(const _Tp& __t) const + { return log10(__t); } + }; + + struct _Sqrt + { + template + _Tp operator()(const _Tp& __t) const + { return sqrt(__t); } + }; + + // In the past, we used to tailor operator applications semantics + // to the specialization of standard function objects (i.e. plus<>, etc.) + // That is incorrect. Therefore we provide our own surrogates. + + struct __unary_plus + { + template + _Tp operator()(const _Tp& __t) const + { return +__t; } + }; + + struct __negate + { + template + _Tp operator()(const _Tp& __t) const + { return -__t; } + }; + + struct __bitwise_not + { + template + _Tp operator()(const _Tp& __t) const + { return ~__t; } + }; + + struct __plus + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x + __y; } + }; + + struct __minus + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x - __y; } + }; + + struct __multiplies + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x * __y; } + }; + + struct __divides + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x / __y; } + }; + + struct __modulus + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x % __y; } + }; + + struct __bitwise_xor + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x ^ __y; } + }; + + struct __bitwise_and + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x & __y; } + }; + + struct __bitwise_or + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x | __y; } + }; + + struct __shift_left + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x << __y; } + }; + + struct __shift_right + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return __x >> __y; } + }; + + struct __logical_and + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x && __y; } + }; + + struct __logical_or + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x || __y; } + }; + + struct __logical_not + { + template + bool operator()(const _Tp& __x) const + { return !__x; } + }; + + struct __equal_to + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x == __y; } + }; + + struct __not_equal_to + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x != __y; } + }; + + struct __less + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x < __y; } + }; + + struct __greater + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x > __y; } + }; + + struct __less_equal + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x <= __y; } + }; + + struct __greater_equal + { + template + bool operator()(const _Tp& __x, const _Tp& __y) const + { return __x >= __y; } + }; + + // The few binary functions we miss. + struct _Atan2 + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return atan2(__x, __y); } + }; + + struct _Pow + { + template + _Tp operator()(const _Tp& __x, const _Tp& __y) const + { return pow(__x, __y); } + }; + + template + struct __fun_with_valarray + { + typedef _Tp result_type; + }; + + template + struct __fun_with_valarray<_Tp, false> + { + // No result type defined for invalid value types. + }; + + // We need these bits in order to recover the return type of + // some functions/operators now that we're no longer using + // function templates. + template + struct __fun : __fun_with_valarray<_Tp> + { + }; + + // several specializations for relational operators. + template + struct __fun<__logical_not, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__logical_and, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__logical_or, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__less, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__greater, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__less_equal, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__greater_equal, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__equal_to, _Tp> + { + typedef bool result_type; + }; + + template + struct __fun<__not_equal_to, _Tp> + { + typedef bool result_type; + }; + +namespace __detail +{ + // Closure types already have reference semantics and are often short-lived, + // so store them by value to avoid (some cases of) dangling references to + // out-of-scope temporaries. + template + struct _ValArrayRef + { typedef const _Tp __type; }; + + // Use real references for std::valarray objects. + template + struct _ValArrayRef< valarray<_Tp> > + { typedef const valarray<_Tp>& __type; }; + + // + // Apply function taking a value/const reference closure + // + + template + class _FunBase + { + public: + typedef typename _Dom::value_type value_type; + + _FunBase(const _Dom& __e, value_type __f(_Arg)) + : _M_expr(__e), _M_func(__f) {} + + value_type operator[](size_t __i) const + { return _M_func (_M_expr[__i]); } + + size_t size() const { return _M_expr.size ();} + + private: + typename _ValArrayRef<_Dom>::__type _M_expr; + value_type (*_M_func)(_Arg); + }; + + template + struct _ValFunClos<_Expr,_Dom> : _FunBase<_Dom, typename _Dom::value_type> + { + typedef _FunBase<_Dom, typename _Dom::value_type> _Base; + typedef typename _Base::value_type value_type; + typedef value_type _Tp; + + _ValFunClos(const _Dom& __e, _Tp __f(_Tp)) : _Base(__e, __f) {} + }; + + template + struct _ValFunClos<_ValArray,_Tp> : _FunBase, _Tp> + { + typedef _FunBase, _Tp> _Base; + typedef _Tp value_type; + + _ValFunClos(const valarray<_Tp>& __v, _Tp __f(_Tp)) : _Base(__v, __f) {} + }; + + template + struct _RefFunClos<_Expr, _Dom> + : _FunBase<_Dom, const typename _Dom::value_type&> + { + typedef _FunBase<_Dom, const typename _Dom::value_type&> _Base; + typedef typename _Base::value_type value_type; + typedef value_type _Tp; + + _RefFunClos(const _Dom& __e, _Tp __f(const _Tp&)) + : _Base(__e, __f) {} + }; + + template + struct _RefFunClos<_ValArray, _Tp> + : _FunBase, const _Tp&> + { + typedef _FunBase, const _Tp&> _Base; + typedef _Tp value_type; + + _RefFunClos(const valarray<_Tp>& __v, _Tp __f(const _Tp&)) + : _Base(__v, __f) {} + }; + + // + // Unary expression closure. + // + + template + class _UnBase + { + public: + typedef typename _Arg::value_type _Vt; + typedef typename __fun<_Oper, _Vt>::result_type value_type; + + _UnBase(const _Arg& __e) : _M_expr(__e) {} + + value_type operator[](size_t __i) const + { return _Oper()(_M_expr[__i]); } + + size_t size() const { return _M_expr.size(); } + + private: + typename _ValArrayRef<_Arg>::__type _M_expr; + }; + + template + struct _UnClos<_Oper, _Expr, _Dom> + : _UnBase<_Oper, _Dom> + { + typedef _Dom _Arg; + typedef _UnBase<_Oper, _Dom> _Base; + typedef typename _Base::value_type value_type; + + _UnClos(const _Arg& __e) : _Base(__e) {} + }; + + template + struct _UnClos<_Oper, _ValArray, _Tp> + : _UnBase<_Oper, valarray<_Tp> > + { + typedef valarray<_Tp> _Arg; + typedef _UnBase<_Oper, valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _UnClos(const _Arg& __e) : _Base(__e) {} + }; + + + // + // Binary expression closure. + // + + template + class _BinBase + { + public: + typedef typename _FirstArg::value_type _Vt; + typedef typename __fun<_Oper, _Vt>::result_type value_type; + + _BinBase(const _FirstArg& __e1, const _SecondArg& __e2) + : _M_expr1(__e1), _M_expr2(__e2) {} + + value_type operator[](size_t __i) const + { return _Oper()(_M_expr1[__i], _M_expr2[__i]); } + + size_t size() const { return _M_expr1.size(); } + + private: + typename _ValArrayRef<_FirstArg>::__type _M_expr1; + typename _ValArrayRef<_SecondArg>::__type _M_expr2; + }; + + + template + class _BinBase2 + { + public: + typedef typename _Clos::value_type _Vt; + typedef typename __fun<_Oper, _Vt>::result_type value_type; + + _BinBase2(const _Clos& __e, const _Vt& __t) + : _M_expr1(__e), _M_expr2(__t) {} + + value_type operator[](size_t __i) const + { return _Oper()(_M_expr1[__i], _M_expr2); } + + size_t size() const { return _M_expr1.size(); } + + private: + typename _ValArrayRef<_Clos>::__type _M_expr1; + _Vt _M_expr2; + }; + + template + class _BinBase1 + { + public: + typedef typename _Clos::value_type _Vt; + typedef typename __fun<_Oper, _Vt>::result_type value_type; + + _BinBase1(const _Vt& __t, const _Clos& __e) + : _M_expr1(__t), _M_expr2(__e) {} + + value_type operator[](size_t __i) const + { return _Oper()(_M_expr1, _M_expr2[__i]); } + + size_t size() const { return _M_expr2.size(); } + + private: + _Vt _M_expr1; + typename _ValArrayRef<_Clos>::__type _M_expr2; + }; + + template + struct _BinClos<_Oper, _Expr, _Expr, _Dom1, _Dom2> + : _BinBase<_Oper, _Dom1, _Dom2> + { + typedef _BinBase<_Oper, _Dom1, _Dom2> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Dom1& __e1, const _Dom2& __e2) : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _ValArray, _ValArray, _Tp, _Tp> + : _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > + { + typedef _BinBase<_Oper, valarray<_Tp>, valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const valarray<_Tp>& __v, const valarray<_Tp>& __w) + : _Base(__v, __w) {} + }; + + template + struct _BinClos<_Oper, _Expr, _ValArray, _Dom, typename _Dom::value_type> + : _BinBase<_Oper, _Dom, valarray > + { + typedef typename _Dom::value_type _Tp; + typedef _BinBase<_Oper,_Dom,valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Dom& __e1, const valarray<_Tp>& __e2) + : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _ValArray, _Expr, typename _Dom::value_type, _Dom> + : _BinBase<_Oper, valarray,_Dom> + { + typedef typename _Dom::value_type _Tp; + typedef _BinBase<_Oper, valarray<_Tp>, _Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const valarray<_Tp>& __e1, const _Dom& __e2) + : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _Expr, _Constant, _Dom, typename _Dom::value_type> + : _BinBase2<_Oper, _Dom> + { + typedef typename _Dom::value_type _Tp; + typedef _BinBase2<_Oper,_Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Dom& __e1, const _Tp& __e2) : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _Constant, _Expr, typename _Dom::value_type, _Dom> + : _BinBase1<_Oper, _Dom> + { + typedef typename _Dom::value_type _Tp; + typedef _BinBase1<_Oper, _Dom> _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Tp& __e1, const _Dom& __e2) : _Base(__e1, __e2) {} + }; + + template + struct _BinClos<_Oper, _ValArray, _Constant, _Tp, _Tp> + : _BinBase2<_Oper, valarray<_Tp> > + { + typedef _BinBase2<_Oper,valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const valarray<_Tp>& __v, const _Tp& __t) : _Base(__v, __t) {} + }; + + template + struct _BinClos<_Oper, _Constant, _ValArray, _Tp, _Tp> + : _BinBase1<_Oper, valarray<_Tp> > + { + typedef _BinBase1<_Oper, valarray<_Tp> > _Base; + typedef typename _Base::value_type value_type; + + _BinClos(const _Tp& __t, const valarray<_Tp>& __v) : _Base(__t, __v) {} + }; + + // + // slice_array closure. + // + template + class _SBase + { + public: + typedef typename _Dom::value_type value_type; + + _SBase (const _Dom& __e, const slice& __s) + : _M_expr (__e), _M_slice (__s) {} + + value_type + operator[] (size_t __i) const + { return _M_expr[_M_slice.start () + __i * _M_slice.stride ()]; } + + size_t + size() const + { return _M_slice.size (); } + + private: + typename _ValArrayRef<_Dom>::__type _M_expr; + const slice& _M_slice; + }; + + template + class _SBase<_Array<_Tp> > + { + public: + typedef _Tp value_type; + + _SBase (_Array<_Tp> __a, const slice& __s) + : _M_array (__a._M_data+__s.start()), _M_size (__s.size()), + _M_stride (__s.stride()) {} + + value_type + operator[] (size_t __i) const + { return _M_array._M_data[__i * _M_stride]; } + + size_t + size() const + { return _M_size; } + + private: + const _Array<_Tp> _M_array; + const size_t _M_size; + const size_t _M_stride; + }; + + template + struct _SClos<_Expr, _Dom> + : _SBase<_Dom> + { + typedef _SBase<_Dom> _Base; + typedef typename _Base::value_type value_type; + + _SClos (const _Dom& __e, const slice& __s) : _Base (__e, __s) {} + }; + + template + struct _SClos<_ValArray, _Tp> + : _SBase<_Array<_Tp> > + { + typedef _SBase<_Array<_Tp> > _Base; + typedef _Tp value_type; + + _SClos (_Array<_Tp> __a, const slice& __s) : _Base (__a, __s) {} + }; +} // namespace __detail + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _CPP_VALARRAY_BEFORE_H */ diff --git a/resources/sources/avr-libstdcpp/include/bits/vector.tcc b/resources/sources/avr-libstdcpp/include/bits/vector.tcc new file mode 100644 index 000000000..27e63388f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bits/vector.tcc @@ -0,0 +1,1008 @@ +// Vector implementation (out of line) -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file bits/vector.tcc + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{vector} + */ + +#ifndef _VECTOR_TCC +#define _VECTOR_TCC 1 + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + template + void + vector<_Tp, _Alloc>:: + reserve(size_type __n) + { + if (__n > this->max_size()) + __throw_length_error(__N("vector::reserve")); + if (this->capacity() < __n) + { + const size_type __old_size = size(); + pointer __tmp; +#if __cplusplus >= 201103L + if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) + { + __tmp = this->_M_allocate(__n); + _S_relocate(this->_M_impl._M_start, this->_M_impl._M_finish, + __tmp, _M_get_Tp_allocator()); + } + else +#endif + { + __tmp = _M_allocate_and_copy(__n, + _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_start), + _GLIBCXX_MAKE_MOVE_IF_NOEXCEPT_ITERATOR(this->_M_impl._M_finish)); + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + } + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __tmp; + this->_M_impl._M_finish = __tmp + __old_size; + this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __n; + } + } + +#if __cplusplus >= 201103L + template + template +#if __cplusplus > 201402L + typename vector<_Tp, _Alloc>::reference +#else + void +#endif + vector<_Tp, _Alloc>:: + emplace_back(_Args&&... __args) + { + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + _M_realloc_insert(end(), std::forward<_Args>(__args)...); +#if __cplusplus > 201402L + return back(); +#endif + } +#endif + + template + typename vector<_Tp, _Alloc>::iterator + vector<_Tp, _Alloc>:: +#if __cplusplus >= 201103L + insert(const_iterator __position, const value_type& __x) +#else + insert(iterator __position, const value_type& __x) +#endif + { + const size_type __n = __position - begin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == end()) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + __x); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + { +#if __cplusplus >= 201103L + const auto __pos = begin() + (__position - cbegin()); + // __x could be an existing element of this vector, so make a + // copy of it before _M_insert_aux moves elements around. + _Temporary_value __x_copy(this, __x); + _M_insert_aux(__pos, std::move(__x_copy._M_val())); +#else + _M_insert_aux(__position, __x); +#endif + } + else +#if __cplusplus >= 201103L + _M_realloc_insert(begin() + (__position - cbegin()), __x); +#else + _M_realloc_insert(__position, __x); +#endif + + return iterator(this->_M_impl._M_start + __n); + } + + template + typename vector<_Tp, _Alloc>::iterator + vector<_Tp, _Alloc>:: + _M_erase(iterator __position) + { + if (__position + 1 != end()) + _GLIBCXX_MOVE3(__position + 1, end(), __position); + --this->_M_impl._M_finish; + _Alloc_traits::destroy(this->_M_impl, this->_M_impl._M_finish); + _GLIBCXX_ASAN_ANNOTATE_SHRINK(1); + return __position; + } + + template + typename vector<_Tp, _Alloc>::iterator + vector<_Tp, _Alloc>:: + _M_erase(iterator __first, iterator __last) + { + if (__first != __last) + { + if (__last != end()) + _GLIBCXX_MOVE3(__last, end(), __first); + _M_erase_at_end(__first.base() + (end() - __last)); + } + return __first; + } + + template + vector<_Tp, _Alloc>& + vector<_Tp, _Alloc>:: + operator=(const vector<_Tp, _Alloc>& __x) + { + if (&__x != this) + { + _GLIBCXX_ASAN_ANNOTATE_REINIT; +#if __cplusplus >= 201103L + if (_Alloc_traits::_S_propagate_on_copy_assign()) + { + if (!_Alloc_traits::_S_always_equal() + && _M_get_Tp_allocator() != __x._M_get_Tp_allocator()) + { + // replacement allocator cannot free existing storage + this->clear(); + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = nullptr; + this->_M_impl._M_finish = nullptr; + this->_M_impl._M_end_of_storage = nullptr; + } + std::__alloc_on_copy(_M_get_Tp_allocator(), + __x._M_get_Tp_allocator()); + } +#endif + const size_type __xlen = __x.size(); + if (__xlen > capacity()) + { + pointer __tmp = _M_allocate_and_copy(__xlen, __x.begin(), + __x.end()); + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __tmp; + this->_M_impl._M_end_of_storage = this->_M_impl._M_start + __xlen; + } + else if (size() >= __xlen) + { + std::_Destroy(std::copy(__x.begin(), __x.end(), begin()), + end(), _M_get_Tp_allocator()); + } + else + { + std::copy(__x._M_impl._M_start, __x._M_impl._M_start + size(), + this->_M_impl._M_start); + std::__uninitialized_copy_a(__x._M_impl._M_start + size(), + __x._M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + } + this->_M_impl._M_finish = this->_M_impl._M_start + __xlen; + } + return *this; + } + + template + void + vector<_Tp, _Alloc>:: + _M_fill_assign(size_t __n, const value_type& __val) + { + if (__n > capacity()) + { + vector __tmp(__n, __val, _M_get_Tp_allocator()); + __tmp._M_impl._M_swap_data(this->_M_impl); + } + else if (__n > size()) + { + std::fill(begin(), end(), __val); + const size_type __add = __n - size(); + _GLIBCXX_ASAN_ANNOTATE_GROW(__add); + this->_M_impl._M_finish = + std::__uninitialized_fill_n_a(this->_M_impl._M_finish, + __add, __val, _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__add); + } + else + _M_erase_at_end(std::fill_n(this->_M_impl._M_start, __n, __val)); + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_assign_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + pointer __cur(this->_M_impl._M_start); + for (; __first != __last && __cur != this->_M_impl._M_finish; + ++__cur, (void)++__first) + *__cur = *__first; + if (__first == __last) + _M_erase_at_end(__cur); + else + _M_range_insert(end(), __first, __last, + std::__iterator_category(__first)); + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_assign_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + const size_type __len = std::distance(__first, __last); + + if (__len > capacity()) + { + _S_check_init_len(__len, _M_get_Tp_allocator()); + pointer __tmp(_M_allocate_and_copy(__len, __first, __last)); + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __tmp; + this->_M_impl._M_finish = this->_M_impl._M_start + __len; + this->_M_impl._M_end_of_storage = this->_M_impl._M_finish; + } + else if (size() >= __len) + _M_erase_at_end(std::copy(__first, __last, this->_M_impl._M_start)); + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, size()); + std::copy(__first, __mid, this->_M_impl._M_start); + const size_type __attribute__((__unused__)) __n = __len - size(); + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + this->_M_impl._M_finish = + std::__uninitialized_copy_a(__mid, __last, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + } + } + +#if __cplusplus >= 201103L + template + auto + vector<_Tp, _Alloc>:: + _M_insert_rval(const_iterator __position, value_type&& __v) -> iterator + { + const auto __n = __position - cbegin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == cend()) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::move(__v)); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + _M_insert_aux(begin() + __n, std::move(__v)); + else + _M_realloc_insert(begin() + __n, std::move(__v)); + + return iterator(this->_M_impl._M_start + __n); + } + + template + template + auto + vector<_Tp, _Alloc>:: + _M_emplace_aux(const_iterator __position, _Args&&... __args) + -> iterator + { + const auto __n = __position - cbegin(); + if (this->_M_impl._M_finish != this->_M_impl._M_end_of_storage) + if (__position == cend()) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + std::forward<_Args>(__args)...); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); + } + else + { + // We need to construct a temporary because something in __args... + // could alias one of the elements of the container and so we + // need to use it before _M_insert_aux moves elements around. + _Temporary_value __tmp(this, std::forward<_Args>(__args)...); + _M_insert_aux(begin() + __n, std::move(__tmp._M_val())); + } + else + _M_realloc_insert(begin() + __n, std::forward<_Args>(__args)...); + + return iterator(this->_M_impl._M_start + __n); + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_insert_aux(iterator __position, _Arg&& __arg) +#else + template + void + vector<_Tp, _Alloc>:: + _M_insert_aux(iterator __position, const _Tp& __x) +#endif + { + _GLIBCXX_ASAN_ANNOTATE_GROW(1); + _Alloc_traits::construct(this->_M_impl, this->_M_impl._M_finish, + _GLIBCXX_MOVE(*(this->_M_impl._M_finish - 1))); + ++this->_M_impl._M_finish; + _GLIBCXX_ASAN_ANNOTATE_GREW(1); +#if __cplusplus < 201103L + _Tp __x_copy = __x; +#endif + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + this->_M_impl._M_finish - 2, + this->_M_impl._M_finish - 1); +#if __cplusplus < 201103L + *__position = __x_copy; +#else + *__position = std::forward<_Arg>(__arg); +#endif + } + +#if __cplusplus >= 201103L + template + template + void + vector<_Tp, _Alloc>:: + _M_realloc_insert(iterator __position, _Args&&... __args) +#else + template + void + vector<_Tp, _Alloc>:: + _M_realloc_insert(iterator __position, const _Tp& __x) +#endif + { + const size_type __len = + _M_check_len(size_type(1), "vector::_M_realloc_insert"); + pointer __old_start = this->_M_impl._M_start; + pointer __old_finish = this->_M_impl._M_finish; + const size_type __elems_before = __position - begin(); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + __try + { + // The order of the three operations is dictated by the C++11 + // case, where the moves could alter a new element belonging + // to the existing vector. This is an issue only for callers + // taking the element by lvalue ref (see last bullet of C++11 + // [res.on.arguments]). + _Alloc_traits::construct(this->_M_impl, + __new_start + __elems_before, +#if __cplusplus >= 201103L + std::forward<_Args>(__args)...); +#else + __x); +#endif + __new_finish = pointer(); + +#if __cplusplus >= 201103L + if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) + { + __new_finish = _S_relocate(__old_start, __position.base(), + __new_start, _M_get_Tp_allocator()); + + ++__new_finish; + + __new_finish = _S_relocate(__position.base(), __old_finish, + __new_finish, _M_get_Tp_allocator()); + } + else +#endif + { + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__old_start, __position.base(), + __new_start, _M_get_Tp_allocator()); + + ++__new_finish; + + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__position.base(), __old_finish, + __new_finish, _M_get_Tp_allocator()); + } + } + __catch(...) + { + if (!__new_finish) + _Alloc_traits::destroy(this->_M_impl, + __new_start + __elems_before); + else + std::_Destroy(__new_start, __new_finish, _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } +#if __cplusplus >= 201103L + if _GLIBCXX17_CONSTEXPR (!_S_use_relocate()) +#endif + std::_Destroy(__old_start, __old_finish, _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(__old_start, + this->_M_impl._M_end_of_storage - __old_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + + template + void + vector<_Tp, _Alloc>:: + _M_fill_insert(iterator __position, size_type __n, const value_type& __x) + { + if (__n != 0) + { + if (size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_finish) >= __n) + { +#if __cplusplus < 201103L + value_type __x_copy = __x; +#else + _Temporary_value __tmp(this, __x); + value_type& __x_copy = __tmp._M_val(); +#endif + const size_type __elems_after = end() - __position; + pointer __old_finish(this->_M_impl._M_finish); + if (__elems_after > __n) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + std::__uninitialized_move_a(this->_M_impl._M_finish - __n, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __n; + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + __old_finish - __n, __old_finish); + std::fill(__position.base(), __position.base() + __n, + __x_copy); + } + else + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + this->_M_impl._M_finish = + std::__uninitialized_fill_n_a(this->_M_impl._M_finish, + __n - __elems_after, + __x_copy, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after); + std::__uninitialized_move_a(__position.base(), __old_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __elems_after; + _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after); + std::fill(__position.base(), __old_finish, __x_copy); + } + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_fill_insert"); + const size_type __elems_before = __position - begin(); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + __try + { + // See _M_realloc_insert above. + std::__uninitialized_fill_n_a(__new_start + __elems_before, + __n, __x, + _M_get_Tp_allocator()); + __new_finish = pointer(); + + __new_finish + = std::__uninitialized_move_if_noexcept_a + (this->_M_impl._M_start, __position.base(), + __new_start, _M_get_Tp_allocator()); + + __new_finish += __n; + + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__position.base(), this->_M_impl._M_finish, + __new_finish, _M_get_Tp_allocator()); + } + __catch(...) + { + if (!__new_finish) + std::_Destroy(__new_start + __elems_before, + __new_start + __elems_before + __n, + _M_get_Tp_allocator()); + else + std::_Destroy(__new_start, __new_finish, + _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + } + } + +#if __cplusplus >= 201103L + template + void + vector<_Tp, _Alloc>:: + _M_default_append(size_type __n) + { + if (__n != 0) + { + const size_type __size = size(); + size_type __navail = size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_finish); + + if (__size > max_size() || __navail > max_size() - __size) + __builtin_unreachable(); + + if (__navail >= __n) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + this->_M_impl._M_finish = + std::__uninitialized_default_n_a(this->_M_impl._M_finish, + __n, _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_default_append"); + pointer __new_start(this->_M_allocate(__len)); + if _GLIBCXX17_CONSTEXPR (_S_use_relocate()) + { + __try + { + std::__uninitialized_default_n_a(__new_start + __size, + __n, _M_get_Tp_allocator()); + } + __catch(...) + { + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + _S_relocate(this->_M_impl._M_start, this->_M_impl._M_finish, + __new_start, _M_get_Tp_allocator()); + } + else + { + pointer __destroy_from = pointer(); + __try + { + std::__uninitialized_default_n_a(__new_start + __size, + __n, _M_get_Tp_allocator()); + __destroy_from = __new_start + __size; + std::__uninitialized_move_if_noexcept_a( + this->_M_impl._M_start, this->_M_impl._M_finish, + __new_start, _M_get_Tp_allocator()); + } + __catch(...) + { + if (__destroy_from) + std::_Destroy(__destroy_from, __destroy_from + __n, + _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + } + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_start + __size + __n; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + } + } + + template + bool + vector<_Tp, _Alloc>:: + _M_shrink_to_fit() + { + if (capacity() == size()) + return false; + _GLIBCXX_ASAN_ANNOTATE_REINIT; + return std::__shrink_to_fit_aux::_S_do_it(*this); + } +#endif + + template + template + void + vector<_Tp, _Alloc>:: + _M_range_insert(iterator __pos, _InputIterator __first, + _InputIterator __last, std::input_iterator_tag) + { + if (__pos == end()) + { + for (; __first != __last; ++__first) + insert(end(), *__first); + } + else if (__first != __last) + { + vector __tmp(__first, __last, _M_get_Tp_allocator()); + insert(__pos, + _GLIBCXX_MAKE_MOVE_ITERATOR(__tmp.begin()), + _GLIBCXX_MAKE_MOVE_ITERATOR(__tmp.end())); + } + } + + template + template + void + vector<_Tp, _Alloc>:: + _M_range_insert(iterator __position, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag) + { + if (__first != __last) + { + const size_type __n = std::distance(__first, __last); + if (size_type(this->_M_impl._M_end_of_storage + - this->_M_impl._M_finish) >= __n) + { + const size_type __elems_after = end() - __position; + pointer __old_finish(this->_M_impl._M_finish); + if (__elems_after > __n) + { + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + std::__uninitialized_move_a(this->_M_impl._M_finish - __n, + this->_M_impl._M_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __n; + _GLIBCXX_ASAN_ANNOTATE_GREW(__n); + _GLIBCXX_MOVE_BACKWARD3(__position.base(), + __old_finish - __n, __old_finish); + std::copy(__first, __last, __position); + } + else + { + _ForwardIterator __mid = __first; + std::advance(__mid, __elems_after); + _GLIBCXX_ASAN_ANNOTATE_GROW(__n); + std::__uninitialized_copy_a(__mid, __last, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __n - __elems_after; + _GLIBCXX_ASAN_ANNOTATE_GREW(__n - __elems_after); + std::__uninitialized_move_a(__position.base(), + __old_finish, + this->_M_impl._M_finish, + _M_get_Tp_allocator()); + this->_M_impl._M_finish += __elems_after; + _GLIBCXX_ASAN_ANNOTATE_GREW(__elems_after); + std::copy(__first, __mid, __position); + } + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_range_insert"); + pointer __new_start(this->_M_allocate(__len)); + pointer __new_finish(__new_start); + __try + { + __new_finish + = std::__uninitialized_move_if_noexcept_a + (this->_M_impl._M_start, __position.base(), + __new_start, _M_get_Tp_allocator()); + __new_finish + = std::__uninitialized_copy_a(__first, __last, + __new_finish, + _M_get_Tp_allocator()); + __new_finish + = std::__uninitialized_move_if_noexcept_a + (__position.base(), this->_M_impl._M_finish, + __new_finish, _M_get_Tp_allocator()); + } + __catch(...) + { + std::_Destroy(__new_start, __new_finish, + _M_get_Tp_allocator()); + _M_deallocate(__new_start, __len); + __throw_exception_again; + } + std::_Destroy(this->_M_impl._M_start, this->_M_impl._M_finish, + _M_get_Tp_allocator()); + _GLIBCXX_ASAN_ANNOTATE_REINIT; + _M_deallocate(this->_M_impl._M_start, + this->_M_impl._M_end_of_storage + - this->_M_impl._M_start); + this->_M_impl._M_start = __new_start; + this->_M_impl._M_finish = __new_finish; + this->_M_impl._M_end_of_storage = __new_start + __len; + } + } + } + + + // vector + template + void + vector:: + _M_reallocate(size_type __n) + { + _Bit_pointer __q = this->_M_allocate(__n); + iterator __start(std::__addressof(*__q), 0); + iterator __finish(_M_copy_aligned(begin(), end(), __start)); + this->_M_deallocate(); + this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; + this->_M_impl._M_end_of_storage = __q + _S_nword(__n); + } + + template + void + vector:: + _M_fill_insert(iterator __position, size_type __n, bool __x) + { + if (__n == 0) + return; + if (capacity() - size() >= __n) + { + std::copy_backward(__position, end(), + this->_M_impl._M_finish + difference_type(__n)); + std::fill(__position, __position + difference_type(__n), __x); + this->_M_impl._M_finish += difference_type(__n); + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_fill_insert"); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); + std::fill(__i, __i + difference_type(__n), __x); + iterator __finish = std::copy(__position, end(), + __i + difference_type(__n)); + this->_M_deallocate(); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); + this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; + } + } + + template + template + void + vector:: + _M_insert_range(iterator __position, _ForwardIterator __first, + _ForwardIterator __last, std::forward_iterator_tag) + { + if (__first != __last) + { + size_type __n = std::distance(__first, __last); + if (capacity() - size() >= __n) + { + std::copy_backward(__position, end(), + this->_M_impl._M_finish + + difference_type(__n)); + std::copy(__first, __last, __position); + this->_M_impl._M_finish += difference_type(__n); + } + else + { + const size_type __len = + _M_check_len(__n, "vector::_M_insert_range"); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); + __i = std::copy(__first, __last, __i); + iterator __finish = std::copy(__position, end(), __i); + this->_M_deallocate(); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); + this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; + } + } + } + + template + void + vector:: + _M_insert_aux(iterator __position, bool __x) + { + if (this->_M_impl._M_finish._M_p != this->_M_impl._M_end_addr()) + { + std::copy_backward(__position, this->_M_impl._M_finish, + this->_M_impl._M_finish + 1); + *__position = __x; + ++this->_M_impl._M_finish; + } + else + { + const size_type __len = + _M_check_len(size_type(1), "vector::_M_insert_aux"); + _Bit_pointer __q = this->_M_allocate(__len); + iterator __start(std::__addressof(*__q), 0); + iterator __i = _M_copy_aligned(begin(), __position, __start); + *__i++ = __x; + iterator __finish = std::copy(__position, end(), __i); + this->_M_deallocate(); + this->_M_impl._M_end_of_storage = __q + _S_nword(__len); + this->_M_impl._M_start = __start; + this->_M_impl._M_finish = __finish; + } + } + + template + typename vector::iterator + vector:: + _M_erase(iterator __position) + { + if (__position + 1 != end()) + std::copy(__position + 1, end(), __position); + --this->_M_impl._M_finish; + return __position; + } + + template + typename vector::iterator + vector:: + _M_erase(iterator __first, iterator __last) + { + if (__first != __last) + _M_erase_at_end(std::copy(__last, end(), __first)); + return __first; + } + +#if __cplusplus >= 201103L + template + bool + vector:: + _M_shrink_to_fit() + { + if (capacity() - size() < int(_S_word_bit)) + return false; + __try + { + _M_reallocate(size()); + return true; + } + __catch(...) + { return false; } + } +#endif + +_GLIBCXX_END_NAMESPACE_CONTAINER +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + size_t + hash<_GLIBCXX_STD_C::vector>:: + operator()(const _GLIBCXX_STD_C::vector& __b) const noexcept + { + size_t __hash = 0; + using _GLIBCXX_STD_C::_S_word_bit; + using _GLIBCXX_STD_C::_Bit_type; + + const size_t __words = __b.size() / _S_word_bit; + if (__words) + { + const size_t __clength = __words * sizeof(_Bit_type); + __hash = std::_Hash_impl::hash(__b._M_impl._M_start._M_p, __clength); + } + + const size_t __extrabits = __b.size() % _S_word_bit; + if (__extrabits) + { + _Bit_type __hiword = *__b._M_impl._M_finish._M_p; + __hiword &= ~((~static_cast<_Bit_type>(0)) << __extrabits); + + const size_t __clength + = (__extrabits + __CHAR_BIT__ - 1) / __CHAR_BIT__; + if (__words) + __hash = std::_Hash_impl::hash(&__hiword, __clength, __hash); + else + __hash = std::_Hash_impl::hash(&__hiword, __clength); + } + + return __hash; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#undef _GLIBCXX_ASAN_ANNOTATE_REINIT +#undef _GLIBCXX_ASAN_ANNOTATE_GROW +#undef _GLIBCXX_ASAN_ANNOTATE_GREW +#undef _GLIBCXX_ASAN_ANNOTATE_SHRINK + +#endif /* _VECTOR_TCC */ diff --git a/resources/sources/avr-libstdcpp/include/bitset b/resources/sources/avr-libstdcpp/include/bitset new file mode 100644 index 000000000..dc3910ac6 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/bitset @@ -0,0 +1,1245 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/bitset + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_BITSET +#define _GLIBCXX_BITSET 1 + +#pragma GCC system_header + +#include // For invalid_argument, out_of_range, + // overflow_error +#include + +#if __cplusplus >= 201103L +# include +#endif + +#define _GLIBCXX_BITSET_BITS_PER_WORD (__CHAR_BIT__ * __SIZEOF_LONG__) +#define _GLIBCXX_BITSET_WORDS(__n) \ + ((__n) / _GLIBCXX_BITSET_BITS_PER_WORD + \ + ((__n) % _GLIBCXX_BITSET_BITS_PER_WORD == 0 ? 0 : 1)) + +#define _GLIBCXX_BITSET_BITS_PER_ULL (__CHAR_BIT__ * __SIZEOF_LONG_LONG__) + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_CONTAINER + + /** + * Base class, general case. It is a class invariant that _Nw will be + * nonnegative. + * + * See documentation for bitset. + */ + template + struct _Base_bitset + { + typedef unsigned long _WordT; + + /// 0 is the least significant word. + _WordT _M_w[_Nw]; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + : _M_w() { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long __val) noexcept + : _M_w{ _WordT(__val) +#if __SIZEOF_LONG_LONG__ > __SIZEOF_LONG__ + , _WordT(__val >> _GLIBCXX_BITSET_BITS_PER_WORD) +#endif + } { } +#else + _Base_bitset(unsigned long __val) + : _M_w() + { _M_w[0] = __val; } +#endif + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + _WordT& + _M_getword(size_t __pos) _GLIBCXX_NOEXCEPT + { return _M_w[_S_whichword(__pos)]; } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t __pos) const _GLIBCXX_NOEXCEPT + { return _M_w[_S_whichword(__pos)]; } + +#if __cplusplus >= 201103L + const _WordT* + _M_getdata() const noexcept + { return _M_w; } +#endif + + _WordT& + _M_hiword() _GLIBCXX_NOEXCEPT + { return _M_w[_Nw - 1]; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return _M_w[_Nw - 1]; } + + void + _M_do_and(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] &= __x._M_w[__i]; + } + + void + _M_do_or(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] |= __x._M_w[__i]; + } + + void + _M_do_xor(const _Base_bitset<_Nw>& __x) _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] ^= __x._M_w[__i]; + } + + void + _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT; + + void + _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT; + + void + _M_do_flip() _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] = ~_M_w[__i]; + } + + void + _M_do_set() _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + _M_w[__i] = ~static_cast<_WordT>(0); + } + + void + _M_do_reset() _GLIBCXX_NOEXCEPT + { __builtin_memset(_M_w, 0, _Nw * sizeof(_WordT)); } + + bool + _M_is_equal(const _Base_bitset<_Nw>& __x) const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; ++__i) + if (_M_w[__i] != __x._M_w[__i]) + return false; + return true; + } + + template + bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw - 1; __i++) + if (_M_w[__i] != ~static_cast<_WordT>(0)) + return false; + return _M_hiword() == (~static_cast<_WordT>(0) + >> (_Nw * _GLIBCXX_BITSET_BITS_PER_WORD + - _Nb)); + } + + bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + if (_M_w[__i] != static_cast<_WordT>(0)) + return true; + return false; + } + + size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { + size_t __result = 0; + for (size_t __i = 0; __i < _Nw; __i++) + __result += __builtin_popcountl(_M_w[__i]); + return __result; + } + + unsigned long + _M_do_to_ulong() const; + +#if __cplusplus >= 201103L + unsigned long long + _M_do_to_ullong() const; +#endif + + // find first "on" bit + size_t + _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT; + + // find the next "on" bit that follows "prev" + size_t + _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT; + }; + + // Definitions of non-inline functions from _Base_bitset. + template + void + _Base_bitset<_Nw>::_M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__shift != 0, 1)) + { + const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; + + if (__offset == 0) + for (size_t __n = _Nw - 1; __n >= __wshift; --__n) + _M_w[__n] = _M_w[__n - __wshift]; + else + { + const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD + - __offset); + for (size_t __n = _Nw - 1; __n > __wshift; --__n) + _M_w[__n] = ((_M_w[__n - __wshift] << __offset) + | (_M_w[__n - __wshift - 1] >> __sub_offset)); + _M_w[__wshift] = _M_w[0] << __offset; + } + + std::fill(_M_w + 0, _M_w + __wshift, static_cast<_WordT>(0)); + } + } + + template + void + _Base_bitset<_Nw>::_M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__shift != 0, 1)) + { + const size_t __wshift = __shift / _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __offset = __shift % _GLIBCXX_BITSET_BITS_PER_WORD; + const size_t __limit = _Nw - __wshift - 1; + + if (__offset == 0) + for (size_t __n = 0; __n <= __limit; ++__n) + _M_w[__n] = _M_w[__n + __wshift]; + else + { + const size_t __sub_offset = (_GLIBCXX_BITSET_BITS_PER_WORD + - __offset); + for (size_t __n = 0; __n < __limit; ++__n) + _M_w[__n] = ((_M_w[__n + __wshift] >> __offset) + | (_M_w[__n + __wshift + 1] << __sub_offset)); + _M_w[__limit] = _M_w[_Nw-1] >> __offset; + } + + std::fill(_M_w + __limit + 1, _M_w + _Nw, static_cast<_WordT>(0)); + } + } + + template + unsigned long + _Base_bitset<_Nw>::_M_do_to_ulong() const + { + for (size_t __i = 1; __i < _Nw; ++__i) + if (_M_w[__i]) + __throw_overflow_error(__N("_Base_bitset::_M_do_to_ulong")); + return _M_w[0]; + } + +#if __cplusplus >= 201103L + template + unsigned long long + _Base_bitset<_Nw>::_M_do_to_ullong() const + { + const bool __dw = sizeof(unsigned long long) > sizeof(unsigned long); + for (size_t __i = 1 + __dw; __i < _Nw; ++__i) + if (_M_w[__i]) + __throw_overflow_error(__N("_Base_bitset::_M_do_to_ullong")); + + if (__dw) + return _M_w[0] + (static_cast(_M_w[1]) + << _GLIBCXX_BITSET_BITS_PER_WORD); + return _M_w[0]; + } +#endif + + template + size_t + _Base_bitset<_Nw>:: + _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT + { + for (size_t __i = 0; __i < _Nw; __i++) + { + _WordT __thisword = _M_w[__i]; + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + } + // not found, so return an indication of failure. + return __not_found; + } + + template + size_t + _Base_bitset<_Nw>:: + _M_do_find_next(size_t __prev, size_t __not_found) const _GLIBCXX_NOEXCEPT + { + // make bound inclusive + ++__prev; + + // check out of bounds + if (__prev >= _Nw * _GLIBCXX_BITSET_BITS_PER_WORD) + return __not_found; + + // search first word + size_t __i = _S_whichword(__prev); + _WordT __thisword = _M_w[__i]; + + // mask off bits below bound + __thisword &= (~static_cast<_WordT>(0)) << _S_whichbit(__prev); + + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + + // check subsequent words + __i++; + for (; __i < _Nw; __i++) + { + __thisword = _M_w[__i]; + if (__thisword != static_cast<_WordT>(0)) + return (__i * _GLIBCXX_BITSET_BITS_PER_WORD + + __builtin_ctzl(__thisword)); + } + // not found, so return an indication of failure. + return __not_found; + } // end _M_do_find_next + + /** + * Base class, specialization for a single word. + * + * See documentation for bitset. + */ + template<> + struct _Base_bitset<1> + { + typedef unsigned long _WordT; + _WordT _M_w; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + : _M_w(0) + { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long __val) noexcept +#else + _Base_bitset(unsigned long __val) +#endif + : _M_w(__val) + { } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + _WordT& + _M_getword(size_t) _GLIBCXX_NOEXCEPT + { return _M_w; } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t) const _GLIBCXX_NOEXCEPT + { return _M_w; } + +#if __cplusplus >= 201103L + const _WordT* + _M_getdata() const noexcept + { return &_M_w; } +#endif + + _WordT& + _M_hiword() _GLIBCXX_NOEXCEPT + { return _M_w; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return _M_w; } + + void + _M_do_and(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w &= __x._M_w; } + + void + _M_do_or(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w |= __x._M_w; } + + void + _M_do_xor(const _Base_bitset<1>& __x) _GLIBCXX_NOEXCEPT + { _M_w ^= __x._M_w; } + + void + _M_do_left_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { _M_w <<= __shift; } + + void + _M_do_right_shift(size_t __shift) _GLIBCXX_NOEXCEPT + { _M_w >>= __shift; } + + void + _M_do_flip() _GLIBCXX_NOEXCEPT + { _M_w = ~_M_w; } + + void + _M_do_set() _GLIBCXX_NOEXCEPT + { _M_w = ~static_cast<_WordT>(0); } + + void + _M_do_reset() _GLIBCXX_NOEXCEPT + { _M_w = 0; } + + bool + _M_is_equal(const _Base_bitset<1>& __x) const _GLIBCXX_NOEXCEPT + { return _M_w == __x._M_w; } + + template + bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { return _M_w == (~static_cast<_WordT>(0) + >> (_GLIBCXX_BITSET_BITS_PER_WORD - _Nb)); } + + bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { return _M_w != 0; } + + size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { return __builtin_popcountl(_M_w); } + + unsigned long + _M_do_to_ulong() const _GLIBCXX_NOEXCEPT + { return _M_w; } + +#if __cplusplus >= 201103L + unsigned long long + _M_do_to_ullong() const noexcept + { return _M_w; } +#endif + + size_t + _M_do_find_first(size_t __not_found) const _GLIBCXX_NOEXCEPT + { + if (_M_w != 0) + return __builtin_ctzl(_M_w); + else + return __not_found; + } + + // find the next "on" bit that follows "prev" + size_t + _M_do_find_next(size_t __prev, size_t __not_found) const + _GLIBCXX_NOEXCEPT + { + ++__prev; + if (__prev >= ((size_t) _GLIBCXX_BITSET_BITS_PER_WORD)) + return __not_found; + + _WordT __x = _M_w >> __prev; + if (__x != 0) + return __builtin_ctzl(__x) + __prev; + else + return __not_found; + } + }; + + /** + * Base class, specialization for no storage (zero-length %bitset). + * + * See documentation for bitset. + */ + template<> + struct _Base_bitset<0> + { + typedef unsigned long _WordT; + + _GLIBCXX_CONSTEXPR _Base_bitset() _GLIBCXX_NOEXCEPT + { } + +#if __cplusplus >= 201103L + constexpr _Base_bitset(unsigned long long) noexcept +#else + _Base_bitset(unsigned long) +#endif + { } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichword(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos / _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbyte(size_t __pos) _GLIBCXX_NOEXCEPT + { return (__pos % _GLIBCXX_BITSET_BITS_PER_WORD) / __CHAR_BIT__; } + + static _GLIBCXX_CONSTEXPR size_t + _S_whichbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return __pos % _GLIBCXX_BITSET_BITS_PER_WORD; } + + static _GLIBCXX_CONSTEXPR _WordT + _S_maskbit(size_t __pos) _GLIBCXX_NOEXCEPT + { return (static_cast<_WordT>(1)) << _S_whichbit(__pos); } + + // This would normally give access to the data. The bounds-checking + // in the bitset class will prevent the user from getting this far, + // but (1) it must still return an lvalue to compile, and (2) the + // user might call _Unchecked_set directly, in which case this /needs/ + // to fail. Let's not penalize zero-length users unless they actually + // make an unchecked call; all the memory ugliness is therefore + // localized to this single should-never-get-this-far function. + _WordT& + _M_getword(size_t) _GLIBCXX_NOEXCEPT + { + __throw_out_of_range(__N("_Base_bitset::_M_getword")); + return *new _WordT; + } + + _GLIBCXX_CONSTEXPR _WordT + _M_getword(size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + + _GLIBCXX_CONSTEXPR _WordT + _M_hiword() const _GLIBCXX_NOEXCEPT + { return 0; } + + void + _M_do_and(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_or(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_xor(const _Base_bitset<0>&) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_left_shift(size_t) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_right_shift(size_t) _GLIBCXX_NOEXCEPT + { } + + void + _M_do_flip() _GLIBCXX_NOEXCEPT + { } + + void + _M_do_set() _GLIBCXX_NOEXCEPT + { } + + void + _M_do_reset() _GLIBCXX_NOEXCEPT + { } + + // Are all empty bitsets equal to each other? Are they equal to + // themselves? How to compare a thing which has no state? What is + // the sound of one zero-length bitset clapping? + bool + _M_is_equal(const _Base_bitset<0>&) const _GLIBCXX_NOEXCEPT + { return true; } + + template + bool + _M_are_all() const _GLIBCXX_NOEXCEPT + { return true; } + + bool + _M_is_any() const _GLIBCXX_NOEXCEPT + { return false; } + + size_t + _M_do_count() const _GLIBCXX_NOEXCEPT + { return 0; } + + unsigned long + _M_do_to_ulong() const _GLIBCXX_NOEXCEPT + { return 0; } + +#if __cplusplus >= 201103L + unsigned long long + _M_do_to_ullong() const noexcept + { return 0; } +#endif + + // Normally "not found" is the size, but that could also be + // misinterpreted as an index in this corner case. Oh well. + size_t + _M_do_find_first(size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + + size_t + _M_do_find_next(size_t, size_t) const _GLIBCXX_NOEXCEPT + { return 0; } + }; + + + // Helper class to zero out the unused high-order bits in the highest word. + template + struct _Sanitize + { + typedef unsigned long _WordT; + + static void + _S_do_sanitize(_WordT& __val) _GLIBCXX_NOEXCEPT + { __val &= ~((~static_cast<_WordT>(0)) << _Extrabits); } + }; + + template<> + struct _Sanitize<0> + { + typedef unsigned long _WordT; + + static void + _S_do_sanitize(_WordT) _GLIBCXX_NOEXCEPT { } + }; + +#if __cplusplus >= 201103L + template + struct _Sanitize_val + { + static constexpr unsigned long long + _S_do_sanitize_val(unsigned long long __val) + { return __val; } + }; + + template + struct _Sanitize_val<_Nb, true> + { + static constexpr unsigned long long + _S_do_sanitize_val(unsigned long long __val) + { return __val & ~((~static_cast(0)) << _Nb); } + }; +#endif + + /** + * @brief The %bitset class represents a @e fixed-size sequence of bits. + * @ingroup utilities + * + * (Note that %bitset does @e not meet the formal requirements of a + * container. Mainly, it lacks iterators.) + * + * The template argument, @a Nb, may be any non-negative number, + * specifying the number of bits (e.g., "0", "12", "1024*1024"). + * + * In the general unoptimized case, storage is allocated in word-sized + * blocks. Let B be the number of bits in a word, then (Nb+(B-1))/B + * words will be used for storage. B - Nb%B bits are unused. (They are + * the high-order bits in the highest word.) It is a class invariant + * that those unused bits are always zero. + * + * If you think of %bitset as a simple array of bits, be + * aware that your mental picture is reversed: a %bitset behaves + * the same way as bits in integers do, with the bit at index 0 in + * the least significant / right-hand position, and the bit at + * index Nb-1 in the most significant / left-hand position. + * Thus, unlike other containers, a %bitset's index counts from + * right to left, to put it very loosely. + * + * + * Also see: + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/ext_containers.html + * for a description of extensions. + * + * Most of the actual code isn't contained in %bitset<> itself, but in the + * base class _Base_bitset. The base class works with whole words, not with + * individual bits. This allows us to specialize _Base_bitset for the + * important special case where the %bitset is only a single word. + * + * Extra confusion can result due to the fact that the storage for + * _Base_bitset @e is a regular array, and is indexed as such. This is + * carefully encapsulated. + */ + template + class bitset + : private _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> + { + private: + typedef _Base_bitset<_GLIBCXX_BITSET_WORDS(_Nb)> _Base; + typedef unsigned long _WordT; + + void _M_check(size_t __position, const char *__s) const + { + if (__position >= _Nb) + __throw_out_of_range_fmt(__N("%s: __position (which is %zu) " + ">= _Nb (which is %zu)"), + __s, __position, _Nb); + } + + void + _M_do_sanitize() _GLIBCXX_NOEXCEPT + { + typedef _Sanitize<_Nb % _GLIBCXX_BITSET_BITS_PER_WORD> __sanitize_type; + __sanitize_type::_S_do_sanitize(this->_M_hiword()); + } + +#if __cplusplus >= 201103L + friend struct std::hash; +#endif + + public: + /** + * This encapsulates the concept of a single bit. An instance of this + * class is a proxy for an actual bit; this way the individual bit + * operations are done as faster word-size bitwise instructions. + * + * Most users will never need to use this class directly; conversions + * to and from bool are automatic and should be transparent. Overloaded + * operators help to preserve the illusion. + * + * (On a typical system, this bit %reference is 64 + * times the size of an actual bit. Ha.) + */ + class reference + { + friend class bitset; + + _WordT* _M_wp; + size_t _M_bpos; + + // left undefined + reference(); + + public: + reference(bitset& __b, size_t __pos) _GLIBCXX_NOEXCEPT + { + _M_wp = &__b._M_getword(__pos); + _M_bpos = _Base::_S_whichbit(__pos); + } + +#if __cplusplus >= 201103L + reference(const reference&) = default; +#endif + + ~reference() _GLIBCXX_NOEXCEPT + { } + + // For b[i] = __x; + reference& + operator=(bool __x) _GLIBCXX_NOEXCEPT + { + if (__x) + *_M_wp |= _Base::_S_maskbit(_M_bpos); + else + *_M_wp &= ~_Base::_S_maskbit(_M_bpos); + return *this; + } + + // For b[i] = b[__j]; + reference& + operator=(const reference& __j) _GLIBCXX_NOEXCEPT + { + if ((*(__j._M_wp) & _Base::_S_maskbit(__j._M_bpos))) + *_M_wp |= _Base::_S_maskbit(_M_bpos); + else + *_M_wp &= ~_Base::_S_maskbit(_M_bpos); + return *this; + } + + // Flips the bit + bool + operator~() const _GLIBCXX_NOEXCEPT + { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) == 0; } + + // For __x = b[i]; + operator bool() const _GLIBCXX_NOEXCEPT + { return (*(_M_wp) & _Base::_S_maskbit(_M_bpos)) != 0; } + + // For b[i].flip(); + reference& + flip() _GLIBCXX_NOEXCEPT + { + *_M_wp ^= _Base::_S_maskbit(_M_bpos); + return *this; + } + }; + friend class reference; + + // 23.3.5.1 constructors: + /// All bits set to zero. + _GLIBCXX_CONSTEXPR bitset() _GLIBCXX_NOEXCEPT + { } + + /// Initial bits bitwise-copied from a single word (others set to zero). +#if __cplusplus >= 201103L + constexpr bitset(unsigned long long __val) noexcept + : _Base(_Sanitize_val<_Nb>::_S_do_sanitize_val(__val)) { } +#else + bitset(unsigned long __val) + : _Base(__val) + { _M_do_sanitize(); } +#endif + + // 23.3.5.2 bitset operations: + //@{ + /** + * Operations on bitsets. + * @param __rhs A same-sized bitset. + * + * These should be self-explanatory. + */ + bitset<_Nb>& + operator&=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_and(__rhs); + return *this; + } + + bitset<_Nb>& + operator|=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_or(__rhs); + return *this; + } + + bitset<_Nb>& + operator^=(const bitset<_Nb>& __rhs) _GLIBCXX_NOEXCEPT + { + this->_M_do_xor(__rhs); + return *this; + } + //@} + + //@{ + /** + * Operations on bitsets. + * @param __position The number of places to shift. + * + * These should be self-explanatory. + */ + bitset<_Nb>& + operator<<=(size_t __position) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__position < _Nb, 1)) + { + this->_M_do_left_shift(__position); + this->_M_do_sanitize(); + } + else + this->_M_do_reset(); + return *this; + } + + bitset<_Nb>& + operator>>=(size_t __position) _GLIBCXX_NOEXCEPT + { + if (__builtin_expect(__position < _Nb, 1)) + { + this->_M_do_right_shift(__position); + this->_M_do_sanitize(); + } + else + this->_M_do_reset(); + return *this; + } + //@} + + //@{ + /** + * These versions of single-bit set, reset, flip, and test are + * extensions from the SGI version. They do no range checking. + * @ingroup SGIextensions + */ + bitset<_Nb>& + _Unchecked_set(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); + return *this; + } + + bitset<_Nb>& + _Unchecked_set(size_t __pos, int __val) _GLIBCXX_NOEXCEPT + { + if (__val) + this->_M_getword(__pos) |= _Base::_S_maskbit(__pos); + else + this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); + return *this; + } + + bitset<_Nb>& + _Unchecked_reset(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) &= ~_Base::_S_maskbit(__pos); + return *this; + } + + bitset<_Nb>& + _Unchecked_flip(size_t __pos) _GLIBCXX_NOEXCEPT + { + this->_M_getword(__pos) ^= _Base::_S_maskbit(__pos); + return *this; + } + + _GLIBCXX_CONSTEXPR bool + _Unchecked_test(size_t __pos) const _GLIBCXX_NOEXCEPT + { return ((this->_M_getword(__pos) & _Base::_S_maskbit(__pos)) + != static_cast<_WordT>(0)); } + //@} + + // Set, reset, and flip. + /** + * @brief Sets every bit to true. + */ + bitset<_Nb>& + set() _GLIBCXX_NOEXCEPT + { + this->_M_do_set(); + this->_M_do_sanitize(); + return *this; + } + + /** + * @brief Sets a given bit to a particular value. + * @param __position The index of the bit. + * @param __val Either true or false, defaults to true. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + bitset<_Nb>& + set(size_t __position, bool __val = true) + { + this->_M_check(__position, __N("bitset::set")); + return _Unchecked_set(__position, __val); + } + + /** + * @brief Sets every bit to false. + */ + bitset<_Nb>& + reset() _GLIBCXX_NOEXCEPT + { + this->_M_do_reset(); + return *this; + } + + /** + * @brief Sets a given bit to false. + * @param __position The index of the bit. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + * + * Same as writing @c set(pos,false). + */ + bitset<_Nb>& + reset(size_t __position) + { + this->_M_check(__position, __N("bitset::reset")); + return _Unchecked_reset(__position); + } + + /** + * @brief Toggles every bit to its opposite value. + */ + bitset<_Nb>& + flip() _GLIBCXX_NOEXCEPT + { + this->_M_do_flip(); + this->_M_do_sanitize(); + return *this; + } + + /** + * @brief Toggles a given bit to its opposite value. + * @param __position The index of the bit. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + bitset<_Nb>& + flip(size_t __position) + { + this->_M_check(__position, __N("bitset::flip")); + return _Unchecked_flip(__position); + } + + /// See the no-argument flip(). + bitset<_Nb> + operator~() const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this).flip(); } + + //@{ + /** + * @brief Array-indexing support. + * @param __position Index into the %bitset. + * @return A bool for a const %bitset. For non-const + * bitsets, an instance of the reference proxy class. + * @note These operators do no range checking and throw no exceptions, + * as required by DR 11 to the standard. + * + * _GLIBCXX_RESOLVE_LIB_DEFECTS Note that this implementation already + * resolves DR 11 (items 1 and 2), but does not do the range-checking + * required by that DR's resolution. -pme + * The DR has since been changed: range-checking is a precondition + * (users' responsibility), and these functions must not throw. -pme + */ + reference + operator[](size_t __position) + { return reference(*this, __position); } + + _GLIBCXX_CONSTEXPR bool + operator[](size_t __position) const + { return _Unchecked_test(__position); } + //@} + + /** + * @brief Returns a numerical interpretation of the %bitset. + * @return The integral equivalent of the bits. + * @throw std::overflow_error If there are too many bits to be + * represented in an @c unsigned @c long. + */ + unsigned long + to_ulong() const + { return this->_M_do_to_ulong(); } + +#if __cplusplus >= 201103L + unsigned long long + to_ullong() const + { return this->_M_do_to_ullong(); } +#endif + + /// Returns the number of bits which are set. + size_t + count() const _GLIBCXX_NOEXCEPT + { return this->_M_do_count(); } + + /// Returns the total number of bits. + _GLIBCXX_CONSTEXPR size_t + size() const _GLIBCXX_NOEXCEPT + { return _Nb; } + + //@{ + /// These comparisons for equality/inequality are, well, @e bitwise. + bool + operator==(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT + { return this->_M_is_equal(__rhs); } + +#if __cpp_impl_three_way_comparison < 201907L + bool + operator!=(const bitset<_Nb>& __rhs) const _GLIBCXX_NOEXCEPT + { return !this->_M_is_equal(__rhs); } +#endif + //@} + + /** + * @brief Tests the value of a bit. + * @param __position The index of a bit. + * @return The value at @a pos. + * @throw std::out_of_range If @a pos is bigger the size of the %set. + */ + bool + test(size_t __position) const + { + this->_M_check(__position, __N("bitset::test")); + return _Unchecked_test(__position); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 693. std::bitset::all() missing. + /** + * @brief Tests whether all the bits are on. + * @return True if all the bits are set. + */ + bool + all() const _GLIBCXX_NOEXCEPT + { return this->template _M_are_all<_Nb>(); } + + /** + * @brief Tests whether any of the bits are on. + * @return True if at least one bit is set. + */ + bool + any() const _GLIBCXX_NOEXCEPT + { return this->_M_is_any(); } + + /** + * @brief Tests whether any of the bits are on. + * @return True if none of the bits are set. + */ + bool + none() const _GLIBCXX_NOEXCEPT + { return !this->_M_is_any(); } + + //@{ + /// Self-explanatory. + bitset<_Nb> + operator<<(size_t __position) const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this) <<= __position; } + + bitset<_Nb> + operator>>(size_t __position) const _GLIBCXX_NOEXCEPT + { return bitset<_Nb>(*this) >>= __position; } + //@} + + /** + * @brief Finds the index of the first "on" bit. + * @return The index of the first bit set, or size() if not found. + * @ingroup SGIextensions + * @sa _Find_next + */ + size_t + _Find_first() const _GLIBCXX_NOEXCEPT + { return this->_M_do_find_first(_Nb); } + + /** + * @brief Finds the index of the next "on" bit after prev. + * @return The index of the next bit set, or size() if not found. + * @param __prev Where to start searching. + * @ingroup SGIextensions + * @sa _Find_first + */ + size_t + _Find_next(size_t __prev) const _GLIBCXX_NOEXCEPT + { return this->_M_do_find_next(__prev, _Nb); } + }; + + // 23.3.5.3 bitset operations: + //@{ + /** + * @brief Global bitwise operations on bitsets. + * @param __x A bitset. + * @param __y A bitset of the same size as @a __x. + * @return A new bitset. + * + * These should be self-explanatory. + */ + template + inline bitset<_Nb> + operator&(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result &= __y; + return __result; + } + + template + inline bitset<_Nb> + operator|(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result |= __y; + return __result; + } + + template + inline bitset<_Nb> + operator^(const bitset<_Nb>& __x, const bitset<_Nb>& __y) _GLIBCXX_NOEXCEPT + { + bitset<_Nb> __result(__x); + __result ^= __y; + return __result; + } + //@} + +_GLIBCXX_END_NAMESPACE_CONTAINER +} // namespace std + +#undef _GLIBCXX_BITSET_WORDS +#undef _GLIBCXX_BITSET_BITS_PER_WORD +#undef _GLIBCXX_BITSET_BITS_PER_ULL + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // DR 1182. + /// std::hash specialization for bitset. + template + struct hash<_GLIBCXX_STD_C::bitset<_Nb>> + : public __hash_base> + { + size_t + operator()(const _GLIBCXX_STD_C::bitset<_Nb>& __b) const noexcept + { + const size_t __clength = (_Nb + __CHAR_BIT__ - 1) / __CHAR_BIT__; + return std::_Hash_impl::hash(__b._M_getdata(), __clength); + } + }; + + template<> + struct hash<_GLIBCXX_STD_C::bitset<0>> + : public __hash_base> + { + size_t + operator()(const _GLIBCXX_STD_C::bitset<0>&) const noexcept + { return 0; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#endif /* _GLIBCXX_BITSET */ diff --git a/resources/sources/avr-libstdcpp/include/cassert b/resources/sources/avr-libstdcpp/include/cassert new file mode 100644 index 000000000..e1c0724b8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cassert @@ -0,0 +1,44 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cassert + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c assert.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 19.2 Assertions +// + +// No include guards on this header... + +#pragma GCC system_header + +#include +#include diff --git a/resources/sources/avr-libstdcpp/include/ccomplex b/resources/sources/avr-libstdcpp/include/ccomplex new file mode 100644 index 000000000..7a9044444 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ccomplex @@ -0,0 +1,42 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ccomplex + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CCOMPLEX +#define _GLIBCXX_CCOMPLEX 1 + +#if __cplusplus < 201103L +# include +#endif + +extern "C++" { +#include +} + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cctype b/resources/sources/avr-libstdcpp/include/cctype new file mode 100644 index 000000000..0881d47c8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cctype @@ -0,0 +1,94 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cctype + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c ctype.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CCTYPE +#define _GLIBCXX_CCTYPE 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef isalnum +#undef isalpha +#undef iscntrl +#undef isdigit +#undef isgraph +#undef islower +#undef isprint +#undef ispunct +#undef isspace +#undef isupper +#undef isxdigit +#undef tolower +#undef toupper + +namespace std +{ + using ::isalnum; + using ::isalpha; + using ::iscntrl; + using ::isdigit; + using ::isgraph; + using ::islower; + using ::isprint; + using ::ispunct; + using ::isspace; + using ::isupper; + using ::isxdigit; + using ::tolower; + using ::toupper; +} // namespace std + +#if __cplusplus >= 201103L + +#ifdef _GLIBCXX_USE_C99_CTYPE_TR1 + +#undef isblank + +namespace std +{ + using ::isblank; +} // namespace std + +#endif // _GLIBCXX_USE_C99_CTYPE_TR1 + +#endif // C++11 + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cerrno b/resources/sources/avr-libstdcpp/include/cerrno new file mode 100644 index 000000000..83cbf24a0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cerrno @@ -0,0 +1,52 @@ +// The -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cerrno + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c errno.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 19.3 Error numbers +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CERRNO +#define _GLIBCXX_CERRNO 1 + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef errno +#define errno errno +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cfenv b/resources/sources/avr-libstdcpp/include/cfenv new file mode 100644 index 000000000..376eea234 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cfenv @@ -0,0 +1,84 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cfenv + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_CFENV +#define _GLIBCXX_CFENV 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +#if _GLIBCXX_HAVE_FENV_H +# include +#endif + +#ifdef _GLIBCXX_USE_C99_FENV_TR1 + +#undef feclearexcept +#undef fegetexceptflag +#undef feraiseexcept +#undef fesetexceptflag +#undef fetestexcept +#undef fegetround +#undef fesetround +#undef fegetenv +#undef feholdexcept +#undef fesetenv +#undef feupdateenv + +namespace std +{ + // types + using ::fenv_t; + using ::fexcept_t; + + // functions + using ::feclearexcept; + using ::fegetexceptflag; + using ::feraiseexcept; + using ::fesetexceptflag; + using ::fetestexcept; + + using ::fegetround; + using ::fesetround; + + using ::fegetenv; + using ::feholdexcept; + using ::fesetenv; + using ::feupdateenv; +} // namespace std + +#endif // _GLIBCXX_USE_C99_FENV_TR1 + +#endif // C++11 + +#endif // _GLIBCXX_CFENV diff --git a/resources/sources/avr-libstdcpp/include/cfloat b/resources/sources/avr-libstdcpp/include/cfloat new file mode 100644 index 000000000..3c20ea8f9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cfloat @@ -0,0 +1,56 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cfloat + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c float.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.2.2 Implementation properties: C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CFLOAT +#define _GLIBCXX_CFLOAT 1 + +#if __cplusplus >= 201103L +# ifndef DECIMAL_DIG +# define DECIMAL_DIG __DECIMAL_DIG__ +# endif +# ifndef FLT_EVAL_METHOD +# define FLT_EVAL_METHOD __FLT_EVAL_METHOD__ +# endif +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/chrono b/resources/sources/avr-libstdcpp/include/chrono new file mode 100644 index 000000000..ad8507090 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/chrono @@ -0,0 +1,1131 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/chrono + * This is a Standard C++ Library header. + * @ingroup chrono + */ + +#ifndef _GLIBCXX_CHRONO +#define _GLIBCXX_CHRONO 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include // for literals support. +#if __cplusplus > 201703L +# include +# include +#endif +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup chrono Time + * @ingroup utilities + * + * Classes and functions for time. + * @{ + */ + + /** @namespace std::chrono + * @brief ISO C++ 2011 namespace for date and time utilities + */ + namespace chrono + { + template> + struct duration; + + template + struct time_point; + } + + // 20.11.4.3 specialization of common_type (for duration, sfinae-friendly) + + /// @cond undocumented + + template + struct __duration_common_type + { }; + + template + struct __duration_common_type<_CT, _Period1, _Period2, + __void_t> + { + private: + using __gcd_num = __static_gcd<_Period1::num, _Period2::num>; + using __gcd_den = __static_gcd<_Period1::den, _Period2::den>; + using __cr = typename _CT::type; + using __r = ratio<__gcd_num::value, + (_Period1::den / __gcd_den::value) * _Period2::den>; + + public: + using type = chrono::duration<__cr, __r>; + }; + + template + struct __duration_common_type<__failure_type, _Period1, _Period2> + { typedef __failure_type type; }; + + /// @endcond + + /// Specialization of common_type for chrono::duration types. + /// @relates duration + template + struct common_type, + chrono::duration<_Rep2, _Period2>> + : __duration_common_type, _Period1, _Period2> + { }; + + // 20.11.4.3 specialization of common_type (for time_point, sfinae-friendly) + + /// @cond undocumented + + template + struct __timepoint_common_type + { }; + + template + struct __timepoint_common_type<_CT, _Clock, __void_t> + { + using type = chrono::time_point<_Clock, typename _CT::type>; + }; + + /// @endcond + + /// Specialization of common_type for chrono::time_point types. + /// @relates time_point + template + struct common_type, + chrono::time_point<_Clock, _Duration2>> + : __timepoint_common_type, _Clock> + { }; + + // @} group chrono + + namespace chrono + { + /// @addtogroup chrono + /// @{ + + /// @cond undocumented + + // Primary template for duration_cast impl. + template + struct __duration_cast_impl + { + template + static constexpr _ToDur + __cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::rep __to_rep; + return _ToDur(static_cast<__to_rep>(static_cast<_CR>(__d.count()) + * static_cast<_CR>(_CF::num) + / static_cast<_CR>(_CF::den))); + } + }; + + template + struct __duration_cast_impl<_ToDur, _CF, _CR, true, true> + { + template + static constexpr _ToDur + __cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::rep __to_rep; + return _ToDur(static_cast<__to_rep>(__d.count())); + } + }; + + template + struct __duration_cast_impl<_ToDur, _CF, _CR, true, false> + { + template + static constexpr _ToDur + __cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::rep __to_rep; + return _ToDur(static_cast<__to_rep>( + static_cast<_CR>(__d.count()) / static_cast<_CR>(_CF::den))); + } + }; + + template + struct __duration_cast_impl<_ToDur, _CF, _CR, false, true> + { + template + static constexpr _ToDur + __cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::rep __to_rep; + return _ToDur(static_cast<__to_rep>( + static_cast<_CR>(__d.count()) * static_cast<_CR>(_CF::num))); + } + }; + + template + struct __is_duration + : std::false_type + { }; + + template + struct __is_duration> + : std::true_type + { }; + + template + using __enable_if_is_duration + = typename enable_if<__is_duration<_Tp>::value, _Tp>::type; + + template + using __disable_if_is_duration + = typename enable_if::value, _Tp>::type; + + /// @endcond + + /// duration_cast + template + constexpr __enable_if_is_duration<_ToDur> + duration_cast(const duration<_Rep, _Period>& __d) + { + typedef typename _ToDur::period __to_period; + typedef typename _ToDur::rep __to_rep; + typedef ratio_divide<_Period, __to_period> __cf; + typedef typename common_type<__to_rep, _Rep, intmax_t>::type + __cr; + typedef __duration_cast_impl<_ToDur, __cf, __cr, + __cf::num == 1, __cf::den == 1> __dc; + return __dc::__cast(__d); + } + + /// treat_as_floating_point + template + struct treat_as_floating_point + : is_floating_point<_Rep> + { }; + +#if __cplusplus > 201402L + template + inline constexpr bool treat_as_floating_point_v = + treat_as_floating_point<_Rep>::value; +#endif // C++17 + +#if __cplusplus > 201703L + template + struct is_clock; + + template + inline constexpr bool is_clock_v = is_clock<_Tp>::value; + +#if __cpp_lib_concepts + template + struct is_clock : false_type + { }; + + template + requires requires { + typename _Tp::rep; + typename _Tp::period; + typename _Tp::duration; + typename _Tp::time_point::clock; + typename _Tp::time_point::duration; + { &_Tp::is_steady } -> same_as; + { _Tp::now() } -> same_as; + requires same_as>; + requires same_as; + } + struct is_clock<_Tp> : true_type + { }; +#else + template + struct __is_clock_impl : false_type + { }; + + template + struct __is_clock_impl<_Tp, + void_t> + : __and_>, + is_same, + is_same, + is_same>::type + { }; + + template + struct is_clock : __is_clock_impl<_Tp>::type + { }; +#endif +#endif // C++20 + +#if __cplusplus >= 201703L +# define __cpp_lib_chrono 201611 + + template + constexpr __enable_if_is_duration<_ToDur> + floor(const duration<_Rep, _Period>& __d) + { + auto __to = chrono::duration_cast<_ToDur>(__d); + if (__to > __d) + return __to - _ToDur{1}; + return __to; + } + + template + constexpr __enable_if_is_duration<_ToDur> + ceil(const duration<_Rep, _Period>& __d) + { + auto __to = chrono::duration_cast<_ToDur>(__d); + if (__to < __d) + return __to + _ToDur{1}; + return __to; + } + + template + constexpr enable_if_t< + __and_<__is_duration<_ToDur>, + __not_>>::value, + _ToDur> + round(const duration<_Rep, _Period>& __d) + { + _ToDur __t0 = chrono::floor<_ToDur>(__d); + _ToDur __t1 = __t0 + _ToDur{1}; + auto __diff0 = __d - __t0; + auto __diff1 = __t1 - __d; + if (__diff0 == __diff1) + { + if (__t0.count() & 1) + return __t1; + return __t0; + } + else if (__diff0 < __diff1) + return __t0; + return __t1; + } + + template + constexpr + enable_if_t::is_signed, duration<_Rep, _Period>> + abs(duration<_Rep, _Period> __d) + { + if (__d >= __d.zero()) + return __d; + return -__d; + } +#endif // C++17 + + /// duration_values + template + struct duration_values + { + static constexpr _Rep + zero() noexcept + { return _Rep(0); } + + static constexpr _Rep + max() noexcept + { return numeric_limits<_Rep>::max(); } + + static constexpr _Rep + min() noexcept + { return numeric_limits<_Rep>::lowest(); } + }; + + /// @cond undocumented + + template + struct __is_ratio + : std::false_type + { }; + + template + struct __is_ratio> + : std::true_type + { }; + + /// @endcond + + /// duration + template + struct duration + { + private: + template + using __is_float = treat_as_floating_point<_Rep2>; + + // _Period2 is an exact multiple of _Period + template + using __is_harmonic + = __bool_constant::den == 1>; + + public: + + typedef _Rep rep; + typedef _Period period; + + static_assert(!__is_duration<_Rep>::value, "rep cannot be a duration"); + static_assert(__is_ratio<_Period>::value, + "period must be a specialization of ratio"); + static_assert(_Period::num > 0, "period must be positive"); + + // 20.11.5.1 construction / copy / destroy + constexpr duration() = default; + + duration(const duration&) = default; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3050. Conversion specification problem in chrono::duration + template, + __or_<__is_float, __not_<__is_float<_Rep2>>>>> + constexpr explicit duration(const _Rep2& __rep) + : __r(static_cast(__rep)) { } + + template, + __and_<__is_harmonic<_Period2>, + __not_<__is_float<_Rep2>>>>>> + constexpr duration(const duration<_Rep2, _Period2>& __d) + : __r(duration_cast(__d).count()) { } + + ~duration() = default; + duration& operator=(const duration&) = default; + + // 20.11.5.2 observer + constexpr rep + count() const + { return __r; } + + // 20.11.5.3 arithmetic + constexpr duration + operator+() const + { return *this; } + + constexpr duration + operator-() const + { return duration(-__r); } + + _GLIBCXX17_CONSTEXPR duration& + operator++() + { + ++__r; + return *this; + } + + _GLIBCXX17_CONSTEXPR duration + operator++(int) + { return duration(__r++); } + + _GLIBCXX17_CONSTEXPR duration& + operator--() + { + --__r; + return *this; + } + + _GLIBCXX17_CONSTEXPR duration + operator--(int) + { return duration(__r--); } + + _GLIBCXX17_CONSTEXPR duration& + operator+=(const duration& __d) + { + __r += __d.count(); + return *this; + } + + _GLIBCXX17_CONSTEXPR duration& + operator-=(const duration& __d) + { + __r -= __d.count(); + return *this; + } + + _GLIBCXX17_CONSTEXPR duration& + operator*=(const rep& __rhs) + { + __r *= __rhs; + return *this; + } + + _GLIBCXX17_CONSTEXPR duration& + operator/=(const rep& __rhs) + { + __r /= __rhs; + return *this; + } + + // DR 934. + template + _GLIBCXX17_CONSTEXPR + typename enable_if::value, + duration&>::type + operator%=(const rep& __rhs) + { + __r %= __rhs; + return *this; + } + + template + _GLIBCXX17_CONSTEXPR + typename enable_if::value, + duration&>::type + operator%=(const duration& __d) + { + __r %= __d.count(); + return *this; + } + + // 20.11.5.4 special values + static constexpr duration + zero() noexcept + { return duration(duration_values::zero()); } + + static constexpr duration + min() noexcept + { return duration(duration_values::min()); } + + static constexpr duration + max() noexcept + { return duration(duration_values::max()); } + + private: + rep __r; + }; + + /// @relates duration @{ + + /// The sum of two durations. + template + constexpr typename common_type, + duration<_Rep2, _Period2>>::type + operator+(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __cd; + return __cd(__cd(__lhs).count() + __cd(__rhs).count()); + } + + /// The difference between two durations. + template + constexpr typename common_type, + duration<_Rep2, _Period2>>::type + operator-(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __cd; + return __cd(__cd(__lhs).count() - __cd(__rhs).count()); + } + + /// @} + + /// @cond undocumented + + // SFINAE helper to obtain common_type<_Rep1, _Rep2> only if _Rep2 + // is implicitly convertible to it. + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3050. Conversion specification problem in chrono::duration constructor + template::type> + using __common_rep_t = typename + enable_if::value, _CRep>::type; + + /// @endcond + + /// @relates duration @{ + + /// Multiply a duration by a scalar value. + template + constexpr duration<__common_rep_t<_Rep1, _Rep2>, _Period> + operator*(const duration<_Rep1, _Period>& __d, const _Rep2& __s) + { + typedef duration::type, _Period> + __cd; + return __cd(__cd(__d).count() * __s); + } + + /// Multiply a duration by a scalar value. + template + constexpr duration<__common_rep_t<_Rep2, _Rep1>, _Period> + operator*(const _Rep1& __s, const duration<_Rep2, _Period>& __d) + { return __d * __s; } + + template + constexpr + duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period> + operator/(const duration<_Rep1, _Period>& __d, const _Rep2& __s) + { + typedef duration::type, _Period> + __cd; + return __cd(__cd(__d).count() / __s); + } + + template + constexpr typename common_type<_Rep1, _Rep2>::type + operator/(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __cd; + return __cd(__lhs).count() / __cd(__rhs).count(); + } + + // DR 934. + template + constexpr + duration<__common_rep_t<_Rep1, __disable_if_is_duration<_Rep2>>, _Period> + operator%(const duration<_Rep1, _Period>& __d, const _Rep2& __s) + { + typedef duration::type, _Period> + __cd; + return __cd(__cd(__d).count() % __s); + } + + template + constexpr typename common_type, + duration<_Rep2, _Period2>>::type + operator%(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __cd; + return __cd(__cd(__lhs).count() % __cd(__rhs).count()); + } + + // comparisons + + template + constexpr bool + operator==(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __ct; + return __ct(__lhs).count() == __ct(__rhs).count(); + } + + template + constexpr bool + operator<(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<__dur1,__dur2>::type __ct; + return __ct(__lhs).count() < __ct(__rhs).count(); + } + +#if __cpp_lib_three_way_comparison + template + requires three_way_comparable> + constexpr auto + operator<=>(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + using __ct = common_type_t, + duration<_Rep2, _Period2>>; + return __ct(__lhs).count() <=> __ct(__rhs).count(); + } +#else + template + constexpr bool + operator!=(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { return !(__lhs == __rhs); } +#endif + + template + constexpr bool + operator<=(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { return !(__rhs < __lhs); } + + template + constexpr bool + operator>(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { return __rhs < __lhs; } + + template + constexpr bool + operator>=(const duration<_Rep1, _Period1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { return !(__lhs < __rhs); } + + /// @} + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 +# define _GLIBCXX_CHRONO_INT64_T int64_t +#elif defined __INT64_TYPE__ +# define _GLIBCXX_CHRONO_INT64_T __INT64_TYPE__ +#else + static_assert(std::numeric_limits::digits >= 64, + "Representation type for nanoseconds must have at least 64 bits"); +# define _GLIBCXX_CHRONO_INT64_T long long +#endif + + /// nanoseconds + using nanoseconds = duration<_GLIBCXX_CHRONO_INT64_T, nano>; + + /// microseconds + using microseconds = duration<_GLIBCXX_CHRONO_INT64_T, micro>; + + /// milliseconds + using milliseconds = duration<_GLIBCXX_CHRONO_INT64_T, milli>; + + /// seconds + using seconds = duration<_GLIBCXX_CHRONO_INT64_T>; + + /// minutes + using minutes = duration<_GLIBCXX_CHRONO_INT64_T, ratio< 60>>; + + /// hours + using hours = duration<_GLIBCXX_CHRONO_INT64_T, ratio<3600>>; + +#if __cplusplus > 201703L + /// days + using days = duration<_GLIBCXX_CHRONO_INT64_T, ratio<86400>>; + + /// weeks + using weeks = duration<_GLIBCXX_CHRONO_INT64_T, ratio<604800>>; + + /// years + using years = duration<_GLIBCXX_CHRONO_INT64_T, ratio<31556952>>; + + /// months + using months = duration<_GLIBCXX_CHRONO_INT64_T, ratio<2629746>>; +#endif // C++20 + +#undef _GLIBCXX_CHRONO_INT64_T + + /// time_point + template + struct time_point + { + static_assert(__is_duration<_Dur>::value, + "duration must be a specialization of std::chrono::duration"); + + typedef _Clock clock; + typedef _Dur duration; + typedef typename duration::rep rep; + typedef typename duration::period period; + + constexpr time_point() : __d(duration::zero()) + { } + + constexpr explicit time_point(const duration& __dur) + : __d(__dur) + { } + + // conversions + template>> + constexpr time_point(const time_point& __t) + : __d(__t.time_since_epoch()) + { } + + // observer + constexpr duration + time_since_epoch() const + { return __d; } + + // arithmetic + _GLIBCXX17_CONSTEXPR time_point& + operator+=(const duration& __dur) + { + __d += __dur; + return *this; + } + + _GLIBCXX17_CONSTEXPR time_point& + operator-=(const duration& __dur) + { + __d -= __dur; + return *this; + } + + // special values + static constexpr time_point + min() noexcept + { return time_point(duration::min()); } + + static constexpr time_point + max() noexcept + { return time_point(duration::max()); } + + private: + duration __d; + }; + + /// time_point_cast + template + constexpr typename enable_if<__is_duration<_ToDur>::value, + time_point<_Clock, _ToDur>>::type + time_point_cast(const time_point<_Clock, _Dur>& __t) + { + typedef time_point<_Clock, _ToDur> __time_point; + return __time_point(duration_cast<_ToDur>(__t.time_since_epoch())); + } + +#if __cplusplus > 201402L + template + constexpr + enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>> + floor(const time_point<_Clock, _Dur>& __tp) + { + return time_point<_Clock, _ToDur>{ + chrono::floor<_ToDur>(__tp.time_since_epoch())}; + } + + template + constexpr + enable_if_t<__is_duration<_ToDur>::value, time_point<_Clock, _ToDur>> + ceil(const time_point<_Clock, _Dur>& __tp) + { + return time_point<_Clock, _ToDur>{ + chrono::ceil<_ToDur>(__tp.time_since_epoch())}; + } + + template + constexpr enable_if_t< + __and_<__is_duration<_ToDur>, + __not_>>::value, + time_point<_Clock, _ToDur>> + round(const time_point<_Clock, _Dur>& __tp) + { + return time_point<_Clock, _ToDur>{ + chrono::round<_ToDur>(__tp.time_since_epoch())}; + } +#endif // C++17 + + /// @relates time_point @{ + + /// Adjust a time point forwards by the given duration. + template + constexpr time_point<_Clock, + typename common_type<_Dur1, duration<_Rep2, _Period2>>::type> + operator+(const time_point<_Clock, _Dur1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<_Dur1,__dur2>::type __ct; + typedef time_point<_Clock, __ct> __time_point; + return __time_point(__lhs.time_since_epoch() + __rhs); + } + + /// Adjust a time point forwards by the given duration. + template + constexpr time_point<_Clock, + typename common_type, _Dur2>::type> + operator+(const duration<_Rep1, _Period1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { + typedef duration<_Rep1, _Period1> __dur1; + typedef typename common_type<__dur1,_Dur2>::type __ct; + typedef time_point<_Clock, __ct> __time_point; + return __time_point(__rhs.time_since_epoch() + __lhs); + } + + /// Adjust a time point backwards by the given duration. + template + constexpr time_point<_Clock, + typename common_type<_Dur1, duration<_Rep2, _Period2>>::type> + operator-(const time_point<_Clock, _Dur1>& __lhs, + const duration<_Rep2, _Period2>& __rhs) + { + typedef duration<_Rep2, _Period2> __dur2; + typedef typename common_type<_Dur1,__dur2>::type __ct; + typedef time_point<_Clock, __ct> __time_point; + return __time_point(__lhs.time_since_epoch() -__rhs); + } + + /// @} + + /// @relates time_point @{ + + /// The difference between two time points (as a duration) + template + constexpr typename common_type<_Dur1, _Dur2>::type + operator-(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __lhs.time_since_epoch() - __rhs.time_since_epoch(); } + + template + constexpr bool + operator==(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __lhs.time_since_epoch() == __rhs.time_since_epoch(); } + +#if __cpp_lib_three_way_comparison + template _Dur2> + constexpr auto + operator<=>(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __lhs.time_since_epoch() <=> __rhs.time_since_epoch(); } +#else + template + constexpr bool + operator!=(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return !(__lhs == __rhs); } +#endif + + template + constexpr bool + operator<(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __lhs.time_since_epoch() < __rhs.time_since_epoch(); } + + template + constexpr bool + operator<=(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return !(__rhs < __lhs); } + + template + constexpr bool + operator>(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return __rhs < __lhs; } + + template + constexpr bool + operator>=(const time_point<_Clock, _Dur1>& __lhs, + const time_point<_Clock, _Dur2>& __rhs) + { return !(__lhs < __rhs); } + + // @} + // @} + } // namespace chrono + +#if __cplusplus > 201103L + +#define __cpp_lib_chrono_udls 201304 + + inline namespace literals + { + /** ISO C++ 2014 namespace for suffixes for duration literals. + * + * These suffixes can be used to create `chrono::duration` values with + * tick periods of hours, minutes, seconds, milliseconds, microseconds + * or nanoseconds. For example, `std::chrono::seconds(5)` can be written + * as `5s` after making the suffix visible in the current scope. + * The suffixes can be made visible by a using-directive or + * using-declaration such as: + * - `using namespace std::chrono_literals;` + * - `using namespace std::literals;` + * - `using namespace std::chrono;` + * - `using namespace std;` + * - `using std::chrono_literals::operator""s;` + * + * The result of these suffixes on an integer literal is one of the + * standard typedefs such as `std::chrono::hours`. + * The result on a floating-point literal is a duration type with the + * specified tick period and an unspecified floating-point representation, + * for example `1.5e2ms` might be equivalent to + * `chrono::duration(1.5e2)`. + * + * @ingroup chrono + */ + inline namespace chrono_literals + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" + /// @cond undocumented + template + constexpr _Dur __check_overflow() + { + using _Val = __parse_int::_Parse_int<_Digits...>; + constexpr typename _Dur::rep __repval = _Val::value; + static_assert(__repval >= 0 && __repval == _Val::value, + "literal value cannot be represented by duration type"); + return _Dur(__repval); + } + /// @endcond + + /// Literal suffix for durations representing non-integer hours + constexpr chrono::duration> + operator""h(long double __hours) + { return chrono::duration>{__hours}; } + + /// Literal suffix for durations of type `std::chrono::hours` + template + constexpr chrono::hours + operator""h() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer minutes + constexpr chrono::duration> + operator""min(long double __mins) + { return chrono::duration>{__mins}; } + + /// Literal suffix for durations of type `std::chrono::minutes` + template + constexpr chrono::minutes + operator""min() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer seconds + constexpr chrono::duration + operator""s(long double __secs) + { return chrono::duration{__secs}; } + + /// Literal suffix for durations of type `std::chrono::seconds` + template + constexpr chrono::seconds + operator""s() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer milliseconds + constexpr chrono::duration + operator""ms(long double __msecs) + { return chrono::duration{__msecs}; } + + /// Literal suffix for durations of type `std::chrono::milliseconds` + template + constexpr chrono::milliseconds + operator""ms() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer microseconds + constexpr chrono::duration + operator""us(long double __usecs) + { return chrono::duration{__usecs}; } + + /// Literal suffix for durations of type `std::chrono::microseconds` + template + constexpr chrono::microseconds + operator""us() + { return __check_overflow(); } + + /// Literal suffix for durations representing non-integer nanoseconds + constexpr chrono::duration + operator""ns(long double __nsecs) + { return chrono::duration{__nsecs}; } + + /// Literal suffix for durations of type `std::chrono::nanoseconds` + template + constexpr chrono::nanoseconds + operator""ns() + { return __check_overflow(); } + +#pragma GCC diagnostic pop + } // inline namespace chrono_literals + } // inline namespace literals + + namespace chrono + { + using namespace literals::chrono_literals; + } // namespace chrono + +#endif // C++14 + + namespace chrono + { + class high_resolution_clock + { + public: + // The high_resolution_clock counter is steady. Each subsequent call + // of std::chrono::high_resolution_clock::now() returns a later time + // than any previous call. + static constexpr bool is_steady = true; + + // Defines the accuracy of the (hardware) high resolution clock. + using duration = chrono::microseconds; + using rep = duration::rep; + using period = duration::period; + using time_point = chrono::time_point; + + static auto to_time_t(const time_point& t) -> std::time_t + { + return static_cast(duration_cast(t.time_since_epoch()).count()); + } + + static auto from_time_t(std::time_t t) -> time_point + { + using local_from_type = chrono::time_point; + + return time_point_cast + ( + static_cast(chrono::seconds(t)) + ); + } + + // !!! PLATFORM AND OS SPECIFIC IMPLEMENTATION !!! + static auto now() noexcept -> time_point; + }; + + #if !defined(MODM_CHRONO_STEADY_CLOCK) + #define MODM_CHRONO_STEADY_CLOCK steady_clock + #endif + + // use high_resolution_clock as steady_clock + using MODM_CHRONO_STEADY_CLOCK = high_resolution_clock; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif //_GLIBCXX_CHRONO diff --git a/resources/sources/avr-libstdcpp/include/cinttypes b/resources/sources/avr-libstdcpp/include/cinttypes new file mode 100644 index 000000000..252ee6926 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cinttypes @@ -0,0 +1,55 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cinttypes + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_CINTTYPES +#define _GLIBCXX_CINTTYPES 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +// For 27.9.2/3 (see C99, Note 184) +#if _GLIBCXX_HAVE_INTTYPES_H +# ifndef __STDC_FORMAT_MACROS +# define _UNDEF__STDC_FORMAT_MACROS +# define __STDC_FORMAT_MACROS +# endif +# include +# ifdef _UNDEF__STDC_FORMAT_MACROS +# undef __STDC_FORMAT_MACROS +# undef _UNDEF__STDC_FORMAT_MACROS +# endif +#endif + +#endif // C++11 + +#endif // _GLIBCXX_CINTTYPES diff --git a/resources/sources/avr-libstdcpp/include/ciso646 b/resources/sources/avr-libstdcpp/include/ciso646 new file mode 100644 index 000000000..05c29e9fb --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ciso646 @@ -0,0 +1,38 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ciso646 + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c iso646.h, + * which is empty in C++. + */ +#ifndef _GLIBCXX_CISO646 +#define _GLIBCXX_CISO646 + +#pragma GCC system_header + +#include +#endif diff --git a/resources/sources/avr-libstdcpp/include/climits b/resources/sources/avr-libstdcpp/include/climits new file mode 100644 index 000000000..09e8fcba2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/climits @@ -0,0 +1,59 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/climits + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c limits.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.2.2 Implementation properties: C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CLIMITS +#define _GLIBCXX_CLIMITS 1 + +#ifndef LLONG_MIN +#define LLONG_MIN (-__LONG_LONG_MAX__ - 1) +#endif + +#ifndef LLONG_MAX +#define LLONG_MAX __LONG_LONG_MAX__ +#endif + +#ifndef ULLONG_MAX +#define ULLONG_MAX (__LONG_LONG_MAX__ * 2ULL + 1) +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cmath b/resources/sources/avr-libstdcpp/include/cmath index b83cba2e6..2232ef22b 100644 --- a/resources/sources/avr-libstdcpp/include/cmath +++ b/resources/sources/avr-libstdcpp/include/cmath @@ -1,20 +1,1924 @@ -// Minimal for AVR -#ifndef _AVR_CMATH -#define _AVR_CMATH -#include -#include -namespace std { - using ::fabs; using ::fabsf; using ::fmod; using ::fmodf; - using ::sqrt; using ::sqrtf; using ::floor; using ::floorf; - using ::ceil; using ::ceilf; using ::round; using ::roundf; - using ::pow; using ::powf; using ::log; using ::logf; using ::log10; - using ::exp; using ::expf; using ::sin; using ::cos; using ::tan; - using ::asin; using ::acos; using ::atan; using ::atan2; +// -*- C++ -*- C forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cmath + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c math.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 26.5 C library +// + +#pragma GCC system_header + +#include +#include +#include +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include_next +#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include + +#ifndef _GLIBCXX_CMATH +#define _GLIBCXX_CMATH 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef div +#undef acos +#undef asin +#undef atan +#undef atan2 +#undef ceil +#undef cos +#undef cosh +#undef exp +#undef fabs +#undef floor +#undef fmod +#undef frexp +#undef ldexp +#undef log +#undef log10 +#undef modf +#undef pow +#undef sin +#undef sinh +#undef sqrt +#undef tan +#undef tanh + +// Fix float math functions defined as macros in avr libc +#ifdef __AVR__ + +#undef cosf +#undef sinf +#undef tanf +#undef fabsf +#undef fmodf +#undef cbrtf +#undef hypotf +#undef squaref +#undef floorf +#undef ceilf +#undef frexpf +#undef ldexpf +#undef expf +#undef coshf +#undef sinhf +#undef tanhf +#undef acosf +#undef asinf +#undef atanf +#undef atan2f +#undef logf +#undef log10f +#undef powf +#undef isnanf +#undef isinff +#undef isfinitef +#undef copysignf +#undef signbitf +#undef fdimf +#undef fmaf +#undef fmaxf +#undef fminf +#undef truncf +#undef roundf +#undef lroundf +#undef lrintf + +extern "C" +{ + float cosf(float x); + float sinf(float x); + float tanf(float x); + float fabsf(float x); + float fmodf(float x, float y); + float cbrtf(float x); + float hypotf(float x, float y); + float squaref(float x); + float floorf(float x); + float ceilf(float x); + float frexpf(float value, int* exp); + float ldexpf(float x, int exp); + float expf(float x); + float coshf(float x); + float sinhf(float x); + float tanhf(float x); + float acosf(float x); + float asinf(float x); + float atanf(float x); + float atan2f(float y, float x); + float logf(float x); + float log10f(float x); + float powf(float x, float y); + int isnanf(float x); + int isinff(float x); + int isfinitef(float x); + float copysignf(float x, float y); + int signbitf(float x); + float fdimf(float x, float y); + float fmaf(float x, float y, float z); + float fmaxf(float x, float y); + float fminf(float x, float y); + float truncf(float x); + float roundf(float x); + long lroundf(float x); + long lrintf(float x); +} // extern "C" +#endif // __AVR__ + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::acos; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + acos(float __x) + { return __builtin_acosf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + acos(long double __x) + { return __builtin_acosl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + acos(_Tp __x) + { return __builtin_acos(__x); } + + using ::asin; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + asin(float __x) + { return __builtin_asinf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + asin(long double __x) + { return __builtin_asinl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + asin(_Tp __x) + { return __builtin_asin(__x); } + + using ::atan; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + atan(float __x) + { return __builtin_atanf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + atan(long double __x) + { return __builtin_atanl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + atan(_Tp __x) + { return __builtin_atan(__x); } + + using ::atan2; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + atan2(float __y, float __x) + { return __builtin_atan2f(__y, __x); } + + inline _GLIBCXX_CONSTEXPR long double + atan2(long double __y, long double __x) + { return __builtin_atan2l(__y, __x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + atan2(_Tp __y, _Up __x) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return atan2(__type(__y), __type(__x)); + } + + using ::ceil; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + ceil(float __x) + { return __builtin_ceilf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + ceil(long double __x) + { return __builtin_ceill(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + ceil(_Tp __x) + { return __builtin_ceil(__x); } + + using ::cos; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + cos(float __x) + { return __builtin_cosf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + cos(long double __x) + { return __builtin_cosl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + cos(_Tp __x) + { return __builtin_cos(__x); } + + using ::cosh; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + cosh(float __x) + { return __builtin_coshf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + cosh(long double __x) + { return __builtin_coshl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + cosh(_Tp __x) + { return __builtin_cosh(__x); } + + using ::exp; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + exp(float __x) + { return __builtin_expf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + exp(long double __x) + { return __builtin_expl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + exp(_Tp __x) + { return __builtin_exp(__x); } + + using ::fabs; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + fabs(float __x) + { return __builtin_fabsf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + fabs(long double __x) + { return __builtin_fabsl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + fabs(_Tp __x) + { return __builtin_fabs(__x); } + + using ::floor; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + floor(float __x) + { return __builtin_floorf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + floor(long double __x) + { return __builtin_floorl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + floor(_Tp __x) + { return __builtin_floor(__x); } + + using ::fmod; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + fmod(float __x, float __y) + { return __builtin_fmodf(__x, __y); } + + inline _GLIBCXX_CONSTEXPR long double + fmod(long double __x, long double __y) + { return __builtin_fmodl(__x, __y); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmod(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmod(__type(__x), __type(__y)); + } + + using ::frexp; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline float + frexp(float __x, int* __exp) + { return __builtin_frexpf(__x, __exp); } + + inline long double + frexp(long double __x, int* __exp) + { return __builtin_frexpl(__x, __exp); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + frexp(_Tp __x, int* __exp) + { return __builtin_frexp(__x, __exp); } + + using ::ldexp; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + ldexp(float __x, int __exp) + { return __builtin_ldexpf(__x, __exp); } + + inline _GLIBCXX_CONSTEXPR long double + ldexp(long double __x, int __exp) + { return __builtin_ldexpl(__x, __exp); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + ldexp(_Tp __x, int __exp) + { return __builtin_ldexp(__x, __exp); } + + using ::log; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + log(float __x) + { return __builtin_logf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + log(long double __x) + { return __builtin_logl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + log(_Tp __x) + { return __builtin_log(__x); } + + using ::log10; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + log10(float __x) + { return __builtin_log10f(__x); } + + inline _GLIBCXX_CONSTEXPR long double + log10(long double __x) + { return __builtin_log10l(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + log10(_Tp __x) + { return __builtin_log10(__x); } + + using ::modf; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline float + modf(float __x, float* __iptr) + { return __builtin_modff(__x, __iptr); } + + inline long double + modf(long double __x, long double* __iptr) + { return __builtin_modfl(__x, __iptr); } +#endif + + using ::pow; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + pow(float __x, float __y) + { return __builtin_powf(__x, __y); } + + inline _GLIBCXX_CONSTEXPR long double + pow(long double __x, long double __y) + { return __builtin_powl(__x, __y); } + +#if __cplusplus < 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 550. What should the return type of pow(float,int) be? + inline double + pow(double __x, int __i) + { return __builtin_powi(__x, __i); } + + inline float + pow(float __x, int __n) + { return __builtin_powif(__x, __n); } + + inline long double + pow(long double __x, int __n) + { return __builtin_powil(__x, __n); } +#endif +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + pow(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return pow(__type(__x), __type(__y)); + } + + using ::sin; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + sin(float __x) + { return __builtin_sinf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + sin(long double __x) + { return __builtin_sinl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + sin(_Tp __x) + { return __builtin_sin(__x); } + + using ::sinh; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + sinh(float __x) + { return __builtin_sinhf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + sinh(long double __x) + { return __builtin_sinhl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + sinh(_Tp __x) + { return __builtin_sinh(__x); } + + using ::sqrt; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + sqrt(float __x) + { return __builtin_sqrtf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + sqrt(long double __x) + { return __builtin_sqrtl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + sqrt(_Tp __x) + { return __builtin_sqrt(__x); } + + using ::tan; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + tan(float __x) + { return __builtin_tanf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + tan(long double __x) + { return __builtin_tanl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + tan(_Tp __x) + { return __builtin_tan(__x); } + + using ::tanh; + +#ifndef __CORRECT_ISO_CPP_MATH_H_PROTO + inline _GLIBCXX_CONSTEXPR float + tanh(float __x) + { return __builtin_tanhf(__x); } + + inline _GLIBCXX_CONSTEXPR long double + tanh(long double __x) + { return __builtin_tanhl(__x); } +#endif + + template + inline _GLIBCXX_CONSTEXPR + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + tanh(_Tp __x) + { return __builtin_tanh(__x); } + +#if _GLIBCXX_USE_C99_MATH +#if !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC + +// These are possible macros imported from C99-land. +#undef fpclassify +#undef isfinite +#undef isinf +#undef isnan +#undef isnormal +#undef signbit +#undef isgreater +#undef isgreaterequal +#undef isless +#undef islessequal +#undef islessgreater +#undef isunordered + +#if !defined(FP_NAN) && !defined(FP_INFINITE) && !defined(FP_ZERO) \ + && !defined(FP_SUBNORMAL) && !defined(FP_NORMAL) +#define FP_NAN 0 +#define FP_INFINITE 1 +#define FP_ZERO 2 +#define FP_SUBNORMAL 3 +#define FP_NORMAL 4 +#elif !defined(FP_NAN) || !defined(FP_INFINITE) || !defined(FP_ZERO) \ + || !defined(FP_SUBNORMAL) || !defined(FP_NORMAL) +#error "Some floating-point number classification macros are missing." +#error "Either define all of them or define none of them so that can do it." +#endif + +#if __cplusplus >= 201103L + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr int + fpclassify(float __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } + + constexpr int + fpclassify(double __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } + + constexpr int + fpclassify(long double __x) + { return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + int>::__type + fpclassify(_Tp __x) + { return __x != 0 ? FP_NORMAL : FP_ZERO; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isfinite(float __x) + { return __builtin_isfinite(__x); } + + constexpr bool + isfinite(double __x) + { return __builtin_isfinite(__x); } + + constexpr bool + isfinite(long double __x) + { return __builtin_isfinite(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + isfinite(_Tp __x) + { return true; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isinf(float __x) + { return __builtin_isinf(__x); } + +#if _GLIBCXX_HAVE_OBSOLETE_ISINF \ + && !_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC + using ::isinf; +#else + constexpr bool + isinf(double __x) + { return __builtin_isinf(__x); } +#endif + + constexpr bool + isinf(long double __x) + { return __builtin_isinf(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + isinf(_Tp __x) + { return false; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isnan(float __x) + { return __builtin_isnan(__x); } + +#if _GLIBCXX_HAVE_OBSOLETE_ISNAN \ + && !_GLIBCXX_NO_OBSOLETE_ISINF_ISNAN_DYNAMIC + using ::isnan; +#else + constexpr bool + isnan(double __x) + { return __builtin_isnan(__x); } +#endif + + constexpr bool + isnan(long double __x) + { return __builtin_isnan(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + isnan(_Tp __x) + { return false; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isnormal(float __x) + { return __builtin_isnormal(__x); } + + constexpr bool + isnormal(double __x) + { return __builtin_isnormal(__x); } + + constexpr bool + isnormal(long double __x) + { return __builtin_isnormal(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + isnormal(_Tp __x) + { return __x != 0 ? true : false; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + // Note: middle-end/36757 is fixed, __builtin_signbit is type-generic. + constexpr bool + signbit(float __x) + { return __builtin_signbit(__x); } + + constexpr bool + signbit(double __x) + { return __builtin_signbit(__x); } + + constexpr bool + signbit(long double __x) + { return __builtin_signbit(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + bool>::__type + signbit(_Tp __x) + { return __x < 0 ? true : false; } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isgreater(float __x, float __y) + { return __builtin_isgreater(__x, __y); } + + constexpr bool + isgreater(double __x, double __y) + { return __builtin_isgreater(__x, __y); } + + constexpr bool + isgreater(long double __x, long double __y) + { return __builtin_isgreater(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + isgreater(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_isgreater(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isgreaterequal(float __x, float __y) + { return __builtin_isgreaterequal(__x, __y); } + + constexpr bool + isgreaterequal(double __x, double __y) + { return __builtin_isgreaterequal(__x, __y); } + + constexpr bool + isgreaterequal(long double __x, long double __y) + { return __builtin_isgreaterequal(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + isgreaterequal(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_isgreaterequal(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isless(float __x, float __y) + { return __builtin_isless(__x, __y); } + + constexpr bool + isless(double __x, double __y) + { return __builtin_isless(__x, __y); } + + constexpr bool + isless(long double __x, long double __y) + { return __builtin_isless(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + isless(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_isless(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + islessequal(float __x, float __y) + { return __builtin_islessequal(__x, __y); } + + constexpr bool + islessequal(double __x, double __y) + { return __builtin_islessequal(__x, __y); } + + constexpr bool + islessequal(long double __x, long double __y) + { return __builtin_islessequal(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + islessequal(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_islessequal(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + islessgreater(float __x, float __y) + { return __builtin_islessgreater(__x, __y); } + + constexpr bool + islessgreater(double __x, double __y) + { return __builtin_islessgreater(__x, __y); } + + constexpr bool + islessgreater(long double __x, long double __y) + { return __builtin_islessgreater(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + islessgreater(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_islessgreater(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr bool + isunordered(float __x, float __y) + { return __builtin_isunordered(__x, __y); } + + constexpr bool + isunordered(double __x, double __y) + { return __builtin_isunordered(__x, __y); } + + constexpr bool + isunordered(long double __x, long double __y) + { return __builtin_isunordered(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename + __gnu_cxx::__enable_if<(__is_arithmetic<_Tp>::__value + && __is_arithmetic<_Up>::__value), bool>::__type + isunordered(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return __builtin_isunordered(__type(__x), __type(__y)); + } +#endif + +#else + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + fpclassify(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_fpclassify(FP_NAN, FP_INFINITE, FP_NORMAL, + FP_SUBNORMAL, FP_ZERO, __type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isfinite(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isfinite(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isinf(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isinf(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isnan(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isnan(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isnormal(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isnormal(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + signbit(_Tp __f) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_signbit(__type(__f)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isgreater(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isgreater(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isgreaterequal(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isgreaterequal(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isless(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isless(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + islessequal(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_islessequal(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + islessgreater(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_islessgreater(__type(__f1), __type(__f2)); + } + + template + inline typename __gnu_cxx::__enable_if<__is_arithmetic<_Tp>::__value, + int>::__type + isunordered(_Tp __f1, _Tp __f2) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __builtin_isunordered(__type(__f1), __type(__f2)); + } + +#endif // C++11 +#endif /* _GLIBCXX_USE_C99_FP_MACROS_DYNAMIC */ +#endif /* _GLIBCXX_USE_C99_MATH */ + +#if __cplusplus >= 201103L + +#ifdef _GLIBCXX_USE_C99_MATH_TR1 + +#undef acosh +#undef acoshf +#undef acoshl +#undef asinh +#undef asinhf +#undef asinhl +#undef atanh +#undef atanhf +#undef atanhl +#undef cbrt +#undef cbrtf +#undef cbrtl +#undef copysign +#undef copysignf +#undef copysignl +#undef erf +#undef erff +#undef erfl +#undef erfc +#undef erfcf +#undef erfcl +#undef exp2 +#undef exp2f +#undef exp2l +#undef expm1 +#undef expm1f +#undef expm1l +#undef fdim +#undef fdimf +#undef fdiml +#undef fma +#undef fmaf +#undef fmal +#undef fmax +#undef fmaxf +#undef fmaxl +#undef fmin +#undef fminf +#undef fminl +#undef hypot +#undef hypotf +#undef hypotl +#undef ilogb +#undef ilogbf +#undef ilogbl +#undef lgamma +#undef lgammaf +#undef lgammal +#ifndef _GLIBCXX_NO_C99_ROUNDING_FUNCS +#undef llrint +#undef llrintf +#undef llrintl +#undef llround +#undef llroundf +#undef llroundl +#endif +#undef log1p +#undef log1pf +#undef log1pl +#undef log2 +#undef log2f +#undef log2l +#undef logb +#undef logbf +#undef logbl +#undef lrint +#undef lrintf +#undef lrintl +#undef lround +#undef lroundf +#undef lroundl +#undef nan +#undef nanf +#undef nanl +#undef nearbyint +#undef nearbyintf +#undef nearbyintl +#undef nextafter +#undef nextafterf +#undef nextafterl +#undef nexttoward +#undef nexttowardf +#undef nexttowardl +#undef remainder +#undef remainderf +#undef remainderl +#undef remquo +#undef remquof +#undef remquol +#undef rint +#undef rintf +#undef rintl +#undef round +#undef roundf +#undef roundl +#undef scalbln +#undef scalblnf +#undef scalblnl +#undef scalbn +#undef scalbnf +#undef scalbnl +#undef tgamma +#undef tgammaf +#undef tgammal +#undef trunc +#undef truncf +#undef truncl + + // types + using double_t = double; + using float_t = float; + + // functions + + using ::cbrt; + inline float cbrtf(float __x) { return ::cbrt(__x); } + + using ::copysign; + inline float copysignf(float __x, float __y) { return ::copysign(__x, __y); } + + using ::fdim; + inline float fdimf(float __x, float __y) { return ::fdim(__x, __y); } + + using ::fma; + inline float fmaf(float __x, float __y, float __z) { return ::fma(__x, __y, __z); } + + using ::fmax; + inline float fmaxf(float __x, float __y) { return ::fmax(__x, __y); } + + using ::fmin; + inline float fminf(float __x, float __y) { return ::fmin(__x, __y); } + + using ::hypot; + inline float hypotf(float __x, float __y) { return ::hypot(__x, __y); } + +#ifndef _GLIBCXX_NO_C99_ROUNDING_FUNCS + using ::llrint; + using ::llrintf; + using ::llrintl; + + using ::llround; + using ::llroundf; + using ::llroundl; +#endif + + using ::lrint; + inline float lrintf(float __x) { return ::lrint(__x); } + + using ::lround; + inline float lroundf(float __x) { return ::lround(__x); } + + using ::round; + inline float roundf(float __x) { return ::round(__x); } + using ::trunc; - // abs overloads for float/double (Arduino's abs macro handles int only) - inline float abs(float x) { return fabsf(x); } - inline double abs(double x) { return fabs(x); } - inline long abs(long x) { return x < 0 ? -x : x; } - inline long long abs(long long x) { return x < 0 ? -x : x; } -} + inline float truncf(float __x) { return ::trunc(__x); } + + /// Additional overloads. +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + acosh(float __x) + { return __builtin_acoshf(__x); } + + constexpr long double + acosh(long double __x) + { return __builtin_acoshl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + acosh(_Tp __x) + { return __builtin_acosh(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + asinh(float __x) + { return __builtin_asinhf(__x); } + + constexpr long double + asinh(long double __x) + { return __builtin_asinhl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + asinh(_Tp __x) + { return __builtin_asinh(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + atanh(float __x) + { return __builtin_atanhf(__x); } + + constexpr long double + atanh(long double __x) + { return __builtin_atanhl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + atanh(_Tp __x) + { return __builtin_atanh(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + cbrt(float __x) + { return __builtin_cbrtf(__x); } + + constexpr long double + cbrt(long double __x) + { return __builtin_cbrtl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + cbrt(_Tp __x) + { return __builtin_cbrt(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + copysign(float __x, float __y) + { return __builtin_copysignf(__x, __y); } + + constexpr long double + copysign(long double __x, long double __y) + { return __builtin_copysignl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + copysign(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return copysign(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + erf(float __x) + { return __builtin_erff(__x); } + + constexpr long double + erf(long double __x) + { return __builtin_erfl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + erf(_Tp __x) + { return __builtin_erf(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + erfc(float __x) + { return __builtin_erfcf(__x); } + + constexpr long double + erfc(long double __x) + { return __builtin_erfcl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + erfc(_Tp __x) + { return __builtin_erfc(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + exp2(float __x) + { return __builtin_exp2f(__x); } + + constexpr long double + exp2(long double __x) + { return __builtin_exp2l(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + exp2(_Tp __x) + { return __builtin_exp2(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + expm1(float __x) + { return __builtin_expm1f(__x); } + + constexpr long double + expm1(long double __x) + { return __builtin_expm1l(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + expm1(_Tp __x) + { return __builtin_expm1(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + fdim(float __x, float __y) + { return __builtin_fdimf(__x, __y); } + + constexpr long double + fdim(long double __x, long double __y) + { return __builtin_fdiml(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fdim(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fdim(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + fma(float __x, float __y, float __z) + { return __builtin_fmaf(__x, __y, __z); } + + constexpr long double + fma(long double __x, long double __y, long double __z) + { return __builtin_fmal(__x, __y, __z); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type + fma(_Tp __x, _Up __y, _Vp __z) + { + typedef typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type __type; + return fma(__type(__x), __type(__y), __type(__z)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + fmax(float __x, float __y) + { return __builtin_fmaxf(__x, __y); } + + constexpr long double + fmax(long double __x, long double __y) + { return __builtin_fmaxl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmax(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmax(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + fmin(float __x, float __y) + { return __builtin_fminf(__x, __y); } + + constexpr long double + fmin(long double __x, long double __y) + { return __builtin_fminl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + fmin(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return fmin(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + hypot(float __x, float __y) + { return __builtin_hypotf(__x, __y); } + + constexpr long double + hypot(long double __x, long double __y) + { return __builtin_hypotl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + hypot(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return hypot(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr int + ilogb(float __x) + { return __builtin_ilogbf(__x); } + + constexpr int + ilogb(long double __x) + { return __builtin_ilogbl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr + typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + int>::__type + ilogb(_Tp __x) + { return __builtin_ilogb(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + lgamma(float __x) + { return __builtin_lgammaf(__x); } + + constexpr long double + lgamma(long double __x) + { return __builtin_lgammal(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + lgamma(_Tp __x) + { return __builtin_lgamma(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr long long + llrint(float __x) + { return __builtin_llrintf(__x); } + + constexpr long long + llrint(long double __x) + { return __builtin_llrintl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + long long>::__type + llrint(_Tp __x) + { return __builtin_llrint(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr long long + llround(float __x) + { return __builtin_llroundf(__x); } + + constexpr long long + llround(long double __x) + { return __builtin_llroundl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + long long>::__type + llround(_Tp __x) + { return __builtin_llround(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + log1p(float __x) + { return __builtin_log1pf(__x); } + + constexpr long double + log1p(long double __x) + { return __builtin_log1pl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + log1p(_Tp __x) + { return __builtin_log1p(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + // DR 568. + constexpr float + log2(float __x) + { return __builtin_log2f(__x); } + + constexpr long double + log2(long double __x) + { return __builtin_log2l(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + log2(_Tp __x) + { return __builtin_log2(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + logb(float __x) + { return __builtin_logbf(__x); } + + constexpr long double + logb(long double __x) + { return __builtin_logbl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + logb(_Tp __x) + { return __builtin_logb(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr long + lrint(float __x) + { return __builtin_lrintf(__x); } + + constexpr long + lrint(long double __x) + { return __builtin_lrintl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + long>::__type + lrint(_Tp __x) + { return __builtin_lrint(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr long + lround(float __x) + { return __builtin_lroundf(__x); } + + constexpr long + lround(long double __x) + { return __builtin_lroundl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + long>::__type + lround(_Tp __x) + { return __builtin_lround(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + nearbyint(float __x) + { return __builtin_nearbyintf(__x); } + + constexpr long double + nearbyint(long double __x) + { return __builtin_nearbyintl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + nearbyint(_Tp __x) + { return __builtin_nearbyint(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + nextafter(float __x, float __y) + { return __builtin_nextafterf(__x, __y); } + + constexpr long double + nextafter(long double __x, long double __y) + { return __builtin_nextafterl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + nextafter(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return nextafter(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + nexttoward(float __x, long double __y) + { return __builtin_nexttowardf(__x, __y); } + + constexpr long double + nexttoward(long double __x, long double __y) + { return __builtin_nexttowardl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + nexttoward(_Tp __x, long double __y) + { return __builtin_nexttoward(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + remainder(float __x, float __y) + { return __builtin_remainderf(__x, __y); } + + constexpr long double + remainder(long double __x, long double __y) + { return __builtin_remainderl(__x, __y); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + remainder(_Tp __x, _Up __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return remainder(__type(__x), __type(__y)); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + inline float + remquo(float __x, float __y, int* __pquo) + { return __builtin_remquof(__x, __y, __pquo); } + + inline long double + remquo(long double __x, long double __y, int* __pquo) + { return __builtin_remquol(__x, __y, __pquo); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + inline typename __gnu_cxx::__promote_2<_Tp, _Up>::__type + remquo(_Tp __x, _Up __y, int* __pquo) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return remquo(__type(__x), __type(__y), __pquo); + } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + rint(float __x) + { return __builtin_rintf(__x); } + + constexpr long double + rint(long double __x) + { return __builtin_rintl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + rint(_Tp __x) + { return __builtin_rint(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + round(float __x) + { return __builtin_roundf(__x); } + + constexpr long double + round(long double __x) + { return __builtin_roundl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + round(_Tp __x) + { return __builtin_round(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + scalbln(float __x, long __ex) + { return __builtin_scalblnf(__x, __ex); } + + constexpr long double + scalbln(long double __x, long __ex) + { return __builtin_scalblnl(__x, __ex); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + scalbln(_Tp __x, long __ex) + { return __builtin_scalbln(__x, __ex); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + scalbn(float __x, int __ex) + { return __builtin_scalbnf(__x, __ex); } + + constexpr long double + scalbn(long double __x, int __ex) + { return __builtin_scalbnl(__x, __ex); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + scalbn(_Tp __x, int __ex) + { return __builtin_scalbn(__x, __ex); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + tgamma(float __x) + { return __builtin_tgammaf(__x); } + + constexpr long double + tgamma(long double __x) + { return __builtin_tgammal(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + tgamma(_Tp __x) + { return __builtin_tgamma(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_FP + constexpr float + trunc(float __x) + { return __builtin_truncf(__x); } + + constexpr long double + trunc(long double __x) + { return __builtin_truncl(__x); } +#endif + +#ifndef __CORRECT_ISO_CPP11_MATH_H_PROTO_INT + template + constexpr typename __gnu_cxx::__enable_if<__is_integer<_Tp>::__value, + double>::__type + trunc(_Tp __x) + { return __builtin_trunc(__x); } +#endif + +#endif // _GLIBCXX_USE_C99_MATH_TR1 +#endif // C++11 + +#if __cplusplus > 201402L + + // [c.math.hypot3], three-dimensional hypotenuse +#define __cpp_lib_hypot 201603 + + template + inline _Tp + __hypot3(_Tp __x, _Tp __y, _Tp __z) + { + __x = std::abs(__x); + __y = std::abs(__y); + __z = std::abs(__z); + if (_Tp __a = __x < __y ? __y < __z ? __z : __y : __x < __z ? __z : __x) + return __a * std::sqrt((__x / __a) * (__x / __a) + + (__y / __a) * (__y / __a) + + (__z / __a) * (__z / __a)); + else + return {}; + } + + inline float + hypot(float __x, float __y, float __z) + { return std::__hypot3(__x, __y, __z); } + + inline double + hypot(double __x, double __y, double __z) + { return std::__hypot3(__x, __y, __z); } + + inline long double + hypot(long double __x, long double __y, long double __z) + { return std::__hypot3(__x, __y, __z); } + + template + typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type + hypot(_Tp __x, _Up __y, _Vp __z) + { + using __type = typename __gnu_cxx::__promote_3<_Tp, _Up, _Vp>::__type; + return std::__hypot3<__type>(__x, __y, __z); + } +#endif // C++17 + +#if __cplusplus > 201703L + // linear interpolation +# define __cpp_lib_interpolate 201902L + + template + constexpr _Fp + __lerp(_Fp __a, _Fp __b, _Fp __t) noexcept + { + if (__a <= 0 && __b >= 0 || __a >= 0 && __b <= 0) + return __t * __b + (1 - __t) * __a; + + if (__t == 1) + return __b; // exact + + // Exact at __t=0, monotonic except near __t=1, + // bounded, determinate, and consistent: + const _Fp __x = __a + __t * (__b - __a); + return __t > 1 == __b > __a + ? (__b < __x ? __x : __b) + : (__b > __x ? __x : __b); // monotonic near __t=1 + } + + constexpr float + lerp(float __a, float __b, float __t) noexcept + { return std::__lerp(__a, __b, __t); } + + constexpr double + lerp(double __a, double __b, double __t) noexcept + { return std::__lerp(__a, __b, __t); } + + constexpr long double + lerp(long double __a, long double __b, long double __t) noexcept + { return std::__lerp(__a, __b, __t); } +#endif // C++20 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +} // extern "C++" + #endif diff --git a/resources/sources/avr-libstdcpp/include/compare b/resources/sources/avr-libstdcpp/include/compare new file mode 100644 index 000000000..28dfe843e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/compare @@ -0,0 +1,919 @@ +// -*- C++ -*- operator<=> three-way comparison support. + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file compare + * This is a Standard C++ Library header. + */ + +#ifndef _COMPARE +#define _COMPARE + +#pragma GCC system_header + +#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L + +#pragma GCC visibility push(default) + +#include + +#if __cpp_lib_concepts +# define __cpp_lib_three_way_comparison 201907L +#endif + +namespace std +{ + // [cmp.categories], comparison category types + + namespace __cmp_cat + { + using type = signed char; + + enum class _Ord : type { equivalent = 0, less = -1, greater = 1 }; + + enum class _Ncmp : type { _Unordered = 2 }; + + struct __unspec + { + constexpr __unspec(__unspec*) noexcept { } + }; + } + + class partial_ordering + { + // less=0xff, equiv=0x00, greater=0x01, unordered=0x02 + __cmp_cat::type _M_value; + + constexpr explicit + partial_ordering(__cmp_cat::_Ord __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + constexpr explicit + partial_ordering(__cmp_cat::_Ncmp __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + friend class weak_ordering; + friend class strong_ordering; + + public: + // valid values + static const partial_ordering less; + static const partial_ordering equivalent; + static const partial_ordering greater; + static const partial_ordering unordered; + + // comparisons + friend constexpr bool + operator==(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + friend constexpr bool + operator==(partial_ordering, partial_ordering) noexcept = default; + + friend constexpr bool + operator< (partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == -1; } + + friend constexpr bool + operator> (partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 1; } + + friend constexpr bool + operator<=(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + friend constexpr bool + operator>=(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; } + + friend constexpr bool + operator< (__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __v._M_value == 1; } + + friend constexpr bool + operator> (__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __v._M_value == -1; } + + friend constexpr bool + operator<=(__cmp_cat::__unspec, partial_ordering __v) noexcept + { return __cmp_cat::type(__v._M_value & 1) == __v._M_value; } + + friend constexpr bool + operator>=(__cmp_cat::__unspec, partial_ordering __v) noexcept + { return 0 >= __v._M_value; } + + friend constexpr partial_ordering + operator<=>(partial_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + friend constexpr partial_ordering + operator<=>(__cmp_cat::__unspec, partial_ordering __v) noexcept + { + if (__v._M_value & 1) + return partial_ordering(__cmp_cat::_Ord(-__v._M_value)); + else + return __v; + } + }; + + // valid values' definitions + inline constexpr partial_ordering + partial_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr partial_ordering + partial_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr partial_ordering + partial_ordering::greater(__cmp_cat::_Ord::greater); + + inline constexpr partial_ordering + partial_ordering::unordered(__cmp_cat::_Ncmp::_Unordered); + + class weak_ordering + { + __cmp_cat::type _M_value; + + constexpr explicit + weak_ordering(__cmp_cat::_Ord __v) noexcept : _M_value(__cmp_cat::type(__v)) + { } + + friend class strong_ordering; + + public: + // valid values + static const weak_ordering less; + static const weak_ordering equivalent; + static const weak_ordering greater; + + constexpr operator partial_ordering() const noexcept + { return partial_ordering(__cmp_cat::_Ord(_M_value)); } + + // comparisons + friend constexpr bool + operator==(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + friend constexpr bool + operator==(weak_ordering, weak_ordering) noexcept = default; + + friend constexpr bool + operator< (weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value < 0; } + + friend constexpr bool + operator> (weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value > 0; } + + friend constexpr bool + operator<=(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + friend constexpr bool + operator>=(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value >= 0; } + + friend constexpr bool + operator< (__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 < __v._M_value; } + + friend constexpr bool + operator> (__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 > __v._M_value; } + + friend constexpr bool + operator<=(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 <= __v._M_value; } + + friend constexpr bool + operator>=(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return 0 >= __v._M_value; } + + friend constexpr weak_ordering + operator<=>(weak_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + friend constexpr weak_ordering + operator<=>(__cmp_cat::__unspec, weak_ordering __v) noexcept + { return weak_ordering(__cmp_cat::_Ord(-__v._M_value)); } + }; + + // valid values' definitions + inline constexpr weak_ordering + weak_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr weak_ordering + weak_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr weak_ordering + weak_ordering::greater(__cmp_cat::_Ord::greater); + + class strong_ordering + { + __cmp_cat::type _M_value; + + constexpr explicit + strong_ordering(__cmp_cat::_Ord __v) noexcept + : _M_value(__cmp_cat::type(__v)) + { } + + public: + // valid values + static const strong_ordering less; + static const strong_ordering equal; + static const strong_ordering equivalent; + static const strong_ordering greater; + + constexpr operator partial_ordering() const noexcept + { return partial_ordering(__cmp_cat::_Ord(_M_value)); } + + constexpr operator weak_ordering() const noexcept + { return weak_ordering(__cmp_cat::_Ord(_M_value)); } + + // comparisons + friend constexpr bool + operator==(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value == 0; } + + friend constexpr bool + operator==(strong_ordering, strong_ordering) noexcept = default; + + friend constexpr bool + operator< (strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value < 0; } + + friend constexpr bool + operator> (strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value > 0; } + + friend constexpr bool + operator<=(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value <= 0; } + + friend constexpr bool + operator>=(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v._M_value >= 0; } + + friend constexpr bool + operator< (__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 < __v._M_value; } + + friend constexpr bool + operator> (__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 > __v._M_value; } + + friend constexpr bool + operator<=(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 <= __v._M_value; } + + friend constexpr bool + operator>=(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return 0 >= __v._M_value; } + + friend constexpr strong_ordering + operator<=>(strong_ordering __v, __cmp_cat::__unspec) noexcept + { return __v; } + + friend constexpr strong_ordering + operator<=>(__cmp_cat::__unspec, strong_ordering __v) noexcept + { return strong_ordering(__cmp_cat::_Ord(-__v._M_value)); } + }; + + // valid values' definitions + inline constexpr strong_ordering + strong_ordering::less(__cmp_cat::_Ord::less); + + inline constexpr strong_ordering + strong_ordering::equal(__cmp_cat::_Ord::equivalent); + + inline constexpr strong_ordering + strong_ordering::equivalent(__cmp_cat::_Ord::equivalent); + + inline constexpr strong_ordering + strong_ordering::greater(__cmp_cat::_Ord::greater); + + + // named comparison functions + constexpr bool + is_eq(partial_ordering __cmp) noexcept + { return __cmp == 0; } + + constexpr bool + is_neq(partial_ordering __cmp) noexcept + { return __cmp != 0; } + + constexpr bool + is_lt (partial_ordering __cmp) noexcept + { return __cmp < 0; } + + constexpr bool + is_lteq(partial_ordering __cmp) noexcept + { return __cmp <= 0; } + + constexpr bool + is_gt (partial_ordering __cmp) noexcept + { return __cmp > 0; } + + constexpr bool + is_gteq(partial_ordering __cmp) noexcept + { return __cmp >= 0; } + + namespace __detail + { + template + inline constexpr unsigned __cmp_cat_id = 1; + template<> + inline constexpr unsigned __cmp_cat_id = 2; + template<> + inline constexpr unsigned __cmp_cat_id = 4; + template<> + inline constexpr unsigned __cmp_cat_id = 8; + + template + constexpr auto __common_cmp_cat() + { + constexpr unsigned __cats = (__cmp_cat_id<_Ts> | ...); + // If any Ti is not a comparison category type, U is void. + if constexpr (__cats & 1) + return; + // Otherwise, if at least one Ti is std::partial_ordering, + // U is std::partial_ordering. + else if constexpr (bool(__cats & __cmp_cat_id)) + return partial_ordering::equivalent; + // Otherwise, if at least one Ti is std::weak_ordering, + // U is std::weak_ordering. + else if constexpr (bool(__cats & __cmp_cat_id)) + return weak_ordering::equivalent; + // Otherwise, U is std::strong_ordering. + else + return strong_ordering::equivalent; + } + } // namespace __detail + + // [cmp.common], common comparison category type + template + struct common_comparison_category + { + using type = decltype(__detail::__common_cmp_cat<_Ts...>()); + }; + + // Partial specializations for one and zero argument cases. + + template + struct common_comparison_category<_Tp> + { using type = void; }; + + template<> + struct common_comparison_category + { using type = partial_ordering; }; + + template<> + struct common_comparison_category + { using type = weak_ordering; }; + + template<> + struct common_comparison_category + { using type = strong_ordering; }; + + template<> + struct common_comparison_category<> + { using type = strong_ordering; }; + + template + using common_comparison_category_t + = typename common_comparison_category<_Ts...>::type; + +#if __cpp_lib_concepts + namespace __detail + { + template + concept __compares_as + = same_as, _Cat>; + } // namespace __detail + + // [cmp.concept], concept three_way_comparable + template + concept three_way_comparable + = __detail::__weakly_eq_cmp_with<_Tp, _Tp> + && __detail::__partially_ordered_with<_Tp, _Tp> + && requires(const remove_reference_t<_Tp>& __a, + const remove_reference_t<_Tp>& __b) + { + { __a <=> __b } -> __detail::__compares_as<_Cat>; + }; + + template + concept three_way_comparable_with + = three_way_comparable<_Tp, _Cat> + && three_way_comparable<_Up, _Cat> + && common_reference_with&, + const remove_reference_t<_Up>&> + && three_way_comparable< + common_reference_t&, + const remove_reference_t<_Up>&>, _Cat> + && __detail::__weakly_eq_cmp_with<_Tp, _Up> + && __detail::__partially_ordered_with<_Tp, _Up> + && requires(const remove_reference_t<_Tp>& __t, + const remove_reference_t<_Up>& __u) + { + { __t <=> __u } -> __detail::__compares_as<_Cat>; + { __u <=> __t } -> __detail::__compares_as<_Cat>; + }; + + namespace __detail + { + template + using __cmp3way_res_t + = decltype(std::declval<_Tp>() <=> std::declval<_Up>()); + + // Implementation of std::compare_three_way_result. + // It is undefined for a program to add specializations of + // std::compare_three_way_result, so the std::compare_three_way_result_t + // alias ignores std::compare_three_way_result and uses + // __detail::__cmp3way_res_impl directly instead. + template + struct __cmp3way_res_impl + { }; + + template + requires requires { typename __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; } + struct __cmp3way_res_impl<_Tp, _Up> + { + using type = __cmp3way_res_t<__cref<_Tp>, __cref<_Up>>; + }; + } // namespace __detail + + /// [cmp.result], result of three-way comparison + template + struct compare_three_way_result + : __detail::__cmp3way_res_impl<_Tp, _Up> + { }; + + /// [cmp.result], result of three-way comparison + template + using compare_three_way_result_t + = typename __detail::__cmp3way_res_impl<_Tp, _Up>::type; + + namespace __detail + { + // BUILTIN-PTR-THREE-WAY(T, U) + template + concept __3way_builtin_ptr_cmp + = requires(_Tp&& __t, _Up&& __u) + { static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); } + && convertible_to<_Tp, const volatile void*> + && convertible_to<_Up, const volatile void*> + && ! requires(_Tp&& __t, _Up&& __u) + { operator<=>(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); } + && ! requires(_Tp&& __t, _Up&& __u) + { static_cast<_Tp&&>(__t).operator<=>(static_cast<_Up&&>(__u)); }; + } // namespace __detail + + // [cmp.object], typename compare_three_way + struct compare_three_way + { + template + requires three_way_comparable_with<_Tp, _Up> + || __detail::__3way_builtin_ptr_cmp<_Tp, _Up> + constexpr auto + operator()(_Tp&& __t, _Up&& __u) const + noexcept(noexcept(std::declval<_Tp>() <=> std::declval<_Up>())) + { + if constexpr (__detail::__3way_builtin_ptr_cmp<_Tp, _Up>) + { + auto __pt = static_cast(__t); + auto __pu = static_cast(__u); + if (__builtin_is_constant_evaluated()) + return __pt <=> __pu; + auto __it = reinterpret_cast<__UINTPTR_TYPE__>(__pt); + auto __iu = reinterpret_cast<__UINTPTR_TYPE__>(__pu); + return __it <=> __iu; + } + else + return static_cast<_Tp&&>(__t) <=> static_cast<_Up&&>(__u); + } + + using is_transparent = void; + }; + + namespace __cmp_cust + { + template + constexpr weak_ordering + __fp_weak_ordering(_Tp __e, _Tp __f) + { + // Returns an integer with the same sign as the argument, and magnitude + // indicating the classification: zero=1 subnorm=2 norm=3 inf=4 nan=5 + auto __cat = [](_Tp __fp) -> int { + const int __sign = __builtin_signbit(__fp) ? -1 : 1; + if (__builtin_isnormal(__fp)) + return (__fp == 0 ? 1 : 3) * __sign; + if (__builtin_isnan(__fp)) + return 5 * __sign; + if (int __inf = __builtin_isinf_sign(__fp)) + return 4 * __inf; + return 2 * __sign; + }; + + auto __po = __e <=> __f; + if (is_lt(__po)) + return weak_ordering::less; + else if (is_gt(__po)) + return weak_ordering::greater; + else if (__po == partial_ordering::equivalent) + return weak_ordering::equivalent; + else // unordered, at least one argument is NaN + { + // return -1 for negative nan, +1 for positive nan, 0 otherwise. + auto __isnan_sign = [](_Tp __fp) -> int { + return __builtin_isnan(__fp) + ? __builtin_signbit(__fp) ? -1 : 1 + : 0; + }; + auto __ord = __isnan_sign(__e) <=> __isnan_sign(__f); + if (is_eq(__ord)) + return weak_ordering::equivalent; + else if (is_lt(__ord)) + return weak_ordering::less; + else + return weak_ordering::greater; + } + } + + template + concept __adl_strong = requires(_Tp&& __t, _Up&& __u) + { + strong_ordering(strong_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + template + concept __adl_weak = requires(_Tp&& __t, _Up&& __u) + { + weak_ordering(weak_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + template + concept __adl_partial = requires(_Tp&& __t, _Up&& __u) + { + partial_ordering(partial_order(static_cast<_Tp&&>(__t), + static_cast<_Up&&>(__u))); + }; + + template + concept __cmp3way = requires(_Tp&& __t, _Up&& __u, compare_three_way __c) + { + _Ord(__c(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u))); + }; + + template + concept __strongly_ordered + = __adl_strong<_Tp, _Up> + // FIXME: || floating_point> + || __cmp3way; + + class _Strong_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (floating_point>) + return true; + else if constexpr (__adl_strong<_Tp, _Up>) + return noexcept(strong_ordering(strong_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + } + + friend class _Weak_order; + friend class _Strong_fallback; + + public: + template + requires __strongly_ordered<_Tp, _Up> + constexpr strong_ordering + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + /* FIXME: + if constexpr (floating_point>) + return __cmp_cust::__fp_strong_order(__e, __f); + else */ if constexpr (__adl_strong<_Tp, _Up>) + return strong_ordering(strong_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __weakly_ordered + = floating_point> + || __adl_weak<_Tp, _Up> + || __cmp3way + || __strongly_ordered<_Tp, _Up>; + + class _Weak_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (floating_point>) + return true; + else if constexpr (__adl_weak<_Tp, _Up>) + return noexcept(weak_ordering(weak_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order::_S_noexcept<_Tp, _Up>(); + } + + friend class _Partial_order; + friend class _Weak_fallback; + + public: + template + requires __weakly_ordered<_Tp, _Up> + constexpr weak_ordering + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (floating_point>) + return __cmp_cust::__fp_weak_ordering(__e, __f); + else if constexpr (__adl_weak<_Tp, _Up>) + return weak_ordering(weak_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __partially_ordered + = __adl_partial<_Tp, _Up> + || __cmp3way + || __weakly_ordered<_Tp, _Up>; + + class _Partial_order + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_partial<_Tp, _Up>) + return noexcept(partial_ordering(partial_order(std::declval<_Tp>(), + std::declval<_Up>()))); + else if constexpr (__cmp3way) + return noexcept(compare_three_way()(std::declval<_Tp>(), + std::declval<_Up>())); + else if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order::_S_noexcept<_Tp, _Up>(); + } + + friend class _Partial_fallback; + + public: + template + requires __partially_ordered<_Tp, _Up> + constexpr partial_ordering + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (__adl_partial<_Tp, _Up>) + return partial_ordering(partial_order(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f))); + else if constexpr (__cmp3way) + return compare_three_way()(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + } + }; + + template + concept __op_eq_lt = requires(_Tp&& __t, _Up&& __u) + { + { static_cast<_Tp&&>(__t) == static_cast<_Up&&>(__u) } + -> convertible_to; + { static_cast<_Tp&&>(__t) < static_cast<_Up&&>(__u) } + -> convertible_to; + }; + + class _Strong_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template + requires __strongly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> + constexpr decltype(auto) + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (__strongly_ordered<_Tp, _Up>) + return _Strong_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__op_eq_lt<_Tp, _Up>) + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? strong_ordering::equal + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? strong_ordering::less + : strong_ordering::greater; + } + }; + + class _Weak_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template + requires __weakly_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> + constexpr decltype(auto) + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (__weakly_ordered<_Tp, _Up>) + return _Weak_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__op_eq_lt<_Tp, _Up>) + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? weak_ordering::equivalent + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? weak_ordering::less + : weak_ordering::greater; + } + }; + + class _Partial_fallback + { + template + static constexpr bool + _S_noexcept() + { + if constexpr (__partially_ordered<_Tp, _Up>) + return _Partial_order::_S_noexcept<_Tp, _Up>(); + else + return noexcept(bool(std::declval<_Tp>() == std::declval<_Up>())) + && noexcept(bool(std::declval<_Tp>() < std::declval<_Up>())); + } + + public: + template + requires __partially_ordered<_Tp, _Up> || __op_eq_lt<_Tp, _Up> + constexpr decltype(auto) + operator()(_Tp&& __e, _Up&& __f) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + static_assert(same_as, decay_t<_Up>>); + + if constexpr (__partially_ordered<_Tp, _Up>) + return _Partial_order{}(static_cast<_Tp&&>(__e), + static_cast<_Up&&>(__f)); + else if constexpr (__op_eq_lt<_Tp, _Up>) + return static_cast<_Tp&&>(__e) == static_cast<_Up&&>(__f) + ? partial_ordering::equivalent + : static_cast<_Tp&&>(__e) < static_cast<_Up&&>(__f) + ? partial_ordering::less + : static_cast<_Up&&>(__f) < static_cast<_Tp&&>(__e) + ? partial_ordering::greater + : partial_ordering::unordered; + } + }; + } // namespace __cmp_cust + + // [cmp.alg], comparison algorithms + inline namespace __cmp_alg + { + inline constexpr __cmp_cust::_Strong_order strong_order{}; + + inline constexpr __cmp_cust::_Weak_order weak_order{}; + + inline constexpr __cmp_cust::_Partial_order partial_order{}; + + inline constexpr __cmp_cust::_Strong_fallback + compare_strong_order_fallback{}; + + inline constexpr __cmp_cust::_Weak_fallback + compare_weak_order_fallback{}; + + inline constexpr __cmp_cust::_Partial_fallback + compare_partial_order_fallback{}; + } + + namespace __detail + { + // [expos.only.func] synth-three-way + inline constexpr struct _Synth3way + { + template + static constexpr bool + _S_noexcept(const _Tp* __t = nullptr, const _Up* __u = nullptr) + { + if constexpr (three_way_comparable_with<_Tp, _Up>) + return noexcept(*__t <=> *__u); + else + return noexcept(*__t < *__u) && noexcept(*__u < *__t); + } + + template + constexpr auto + operator()(const _Tp& __t, const _Up& __u) const + noexcept(_S_noexcept<_Tp, _Up>()) + requires requires + { + { __t < __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + } + { + if constexpr (three_way_comparable_with<_Tp, _Up>) + return __t <=> __u; + else + { + if (__t < __u) + return weak_ordering::less; + else if (__u < __t) + return weak_ordering::greater; + else + return weak_ordering::equivalent; + } + } + } __synth3way = {}; + + // [expos.only.func] synth-three-way-result + template + using __synth3way_t + = decltype(__detail::__synth3way(std::declval<_Tp&>(), + std::declval<_Up&>())); + } // namespace __detail +#endif // concepts +} // namespace std + +#pragma GCC visibility pop + +#endif // C++20 + +#endif // _COMPARE diff --git a/resources/sources/avr-libstdcpp/include/complex b/resources/sources/avr-libstdcpp/include/complex new file mode 100644 index 000000000..52f59a19b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/complex @@ -0,0 +1,1931 @@ +// The template and inlines for the -*- C++ -*- complex number classes. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/complex + * This is a Standard C++ Library header. + */ + +// +// ISO C++ 14882: 26.2 Complex Numbers +// Note: this is not a conforming implementation. +// Initially implemented by Ulrich Drepper +// Improved by Gabriel Dos Reis +// + +#ifndef _GLIBCXX_COMPLEX +#define _GLIBCXX_COMPLEX 1 + +#pragma GCC system_header + +#include +#include +#include +#include + +// Get rid of a macro possibly defined in +#undef complex + +#if __cplusplus > 201703L +# define __cpp_lib_constexpr_complex 201711L +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup complex_numbers Complex Numbers + * @ingroup numerics + * + * Classes and functions for complex numbers. + * @{ + */ + + // Forward declarations. + template class complex; + template<> class complex; + template<> class complex; + template<> class complex; + + /// Return magnitude of @a z. + template _Tp abs(const complex<_Tp>&); + /// Return phase angle of @a z. + template _Tp arg(const complex<_Tp>&); + /// Return @a z magnitude squared. + template _Tp _GLIBCXX20_CONSTEXPR norm(const complex<_Tp>&); + + /// Return complex conjugate of @a z. + template + _GLIBCXX20_CONSTEXPR complex<_Tp> conj(const complex<_Tp>&); + /// Return complex with magnitude @a rho and angle @a theta. + template complex<_Tp> polar(const _Tp&, const _Tp& = 0); + + // Transcendentals: + /// Return complex cosine of @a z. + template complex<_Tp> cos(const complex<_Tp>&); + /// Return complex hyperbolic cosine of @a z. + template complex<_Tp> cosh(const complex<_Tp>&); + /// Return complex base e exponential of @a z. + template complex<_Tp> exp(const complex<_Tp>&); + /// Return complex natural logarithm of @a z. + template complex<_Tp> log(const complex<_Tp>&); + /// Return complex base 10 logarithm of @a z. + template complex<_Tp> log10(const complex<_Tp>&); + /// Return @a x to the @a y'th power. + template complex<_Tp> pow(const complex<_Tp>&, int); + /// Return @a x to the @a y'th power. + template complex<_Tp> pow(const complex<_Tp>&, const _Tp&); + /// Return @a x to the @a y'th power. + template complex<_Tp> pow(const complex<_Tp>&, + const complex<_Tp>&); + /// Return @a x to the @a y'th power. + template complex<_Tp> pow(const _Tp&, const complex<_Tp>&); + /// Return complex sine of @a z. + template complex<_Tp> sin(const complex<_Tp>&); + /// Return complex hyperbolic sine of @a z. + template complex<_Tp> sinh(const complex<_Tp>&); + /// Return complex square root of @a z. + template complex<_Tp> sqrt(const complex<_Tp>&); + /// Return complex tangent of @a z. + template complex<_Tp> tan(const complex<_Tp>&); + /// Return complex hyperbolic tangent of @a z. + template complex<_Tp> tanh(const complex<_Tp>&); + + + // 26.2.2 Primary template class complex + /** + * Template to represent complex numbers. + * + * Specializations for float, double, and long double are part of the + * library. Results with any other type are not guaranteed. + * + * @param Tp Type of real and imaginary values. + */ + template + struct complex + { + /// Value typedef. + typedef _Tp value_type; + + /// Default constructor. First parameter is x, second parameter is y. + /// Unspecified parameters default to 0. + _GLIBCXX_CONSTEXPR complex(const _Tp& __r = _Tp(), const _Tp& __i = _Tp()) + : _M_real(__r), _M_imag(__i) { } + + // Let the compiler synthesize the copy constructor +#if __cplusplus >= 201103L + constexpr complex(const complex&) = default; +#endif + + /// Converting constructor. + template + _GLIBCXX_CONSTEXPR complex(const complex<_Up>& __z) + : _M_real(__z.real()), _M_imag(__z.imag()) { } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX_ABI_TAG_CXX11 + constexpr _Tp + real() const { return _M_real; } + + _GLIBCXX_ABI_TAG_CXX11 + constexpr _Tp + imag() const { return _M_imag; } +#else + /// Return real part of complex number. + _Tp& + real() { return _M_real; } + + /// Return real part of complex number. + const _Tp& + real() const { return _M_real; } + + /// Return imaginary part of complex number. + _Tp& + imag() { return _M_imag; } + + /// Return imaginary part of complex number. + const _Tp& + imag() const { return _M_imag; } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX20_CONSTEXPR void + real(_Tp __val) { _M_real = __val; } + + _GLIBCXX20_CONSTEXPR void + imag(_Tp __val) { _M_imag = __val; } + + /// Assign a scalar to this complex number. + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const _Tp&); + + /// Add a scalar to this complex number. + // 26.2.5/1 + _GLIBCXX20_CONSTEXPR complex<_Tp>& + operator+=(const _Tp& __t) + { + _M_real += __t; + return *this; + } + + /// Subtract a scalar from this complex number. + // 26.2.5/3 + _GLIBCXX20_CONSTEXPR complex<_Tp>& + operator-=(const _Tp& __t) + { + _M_real -= __t; + return *this; + } + + /// Multiply this complex number by a scalar. + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const _Tp&); + /// Divide this complex number by a scalar. + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const _Tp&); + + // Let the compiler synthesize the copy assignment operator +#if __cplusplus >= 201103L + _GLIBCXX20_CONSTEXPR complex& operator=(const complex&) = default; +#endif + + /// Assign another complex number to this one. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator=(const complex<_Up>&); + /// Add another complex number to this one. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator+=(const complex<_Up>&); + /// Subtract another complex number from this one. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator-=(const complex<_Up>&); + /// Multiply this complex number by another. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator*=(const complex<_Up>&); + /// Divide this complex number by another. + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& operator/=(const complex<_Up>&); + + _GLIBCXX_CONSTEXPR complex __rep() const + { return *this; } + + private: + _Tp _M_real; + _Tp _M_imag; + }; + + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator=(const _Tp& __t) + { + _M_real = __t; + _M_imag = _Tp(); + return *this; + } + + // 26.2.5/5 + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator*=(const _Tp& __t) + { + _M_real *= __t; + _M_imag *= __t; + return *this; + } + + // 26.2.5/7 + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator/=(const _Tp& __t) + { + _M_real /= __t; + _M_imag /= __t; + return *this; + } + + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator=(const complex<_Up>& __z) + { + _M_real = __z.real(); + _M_imag = __z.imag(); + return *this; + } + + // 26.2.5/9 + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator+=(const complex<_Up>& __z) + { + _M_real += __z.real(); + _M_imag += __z.imag(); + return *this; + } + + // 26.2.5/11 + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator-=(const complex<_Up>& __z) + { + _M_real -= __z.real(); + _M_imag -= __z.imag(); + return *this; + } + + // 26.2.5/13 + // XXX: This is a grammar school implementation. + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator*=(const complex<_Up>& __z) + { + const _Tp __r = _M_real * __z.real() - _M_imag * __z.imag(); + _M_imag = _M_real * __z.imag() + _M_imag * __z.real(); + _M_real = __r; + return *this; + } + + // 26.2.5/15 + // XXX: This is a grammar school implementation. + template + template + _GLIBCXX20_CONSTEXPR complex<_Tp>& + complex<_Tp>::operator/=(const complex<_Up>& __z) + { + const _Tp __r = _M_real * __z.real() + _M_imag * __z.imag(); + const _Tp __n = std::norm(__z); + _M_imag = (_M_imag * __z.real() - _M_real * __z.imag()) / __n; + _M_real = __r / __n; + return *this; + } + + // Operators: + //@{ + /// Return new complex value @a x plus @a y. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator+(const complex<_Tp>& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r += __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator+(const complex<_Tp>& __x, const _Tp& __y) + { + complex<_Tp> __r = __x; + __r += __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator+(const _Tp& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __y; + __r += __x; + return __r; + } + //@} + + //@{ + /// Return new complex value @a x minus @a y. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator-(const complex<_Tp>& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r -= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator-(const complex<_Tp>& __x, const _Tp& __y) + { + complex<_Tp> __r = __x; + __r -= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator-(const _Tp& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = -__y; + __r += __x; + return __r; + } + //@} + + //@{ + /// Return new complex value @a x times @a y. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator*(const complex<_Tp>& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r *= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator*(const complex<_Tp>& __x, const _Tp& __y) + { + complex<_Tp> __r = __x; + __r *= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator*(const _Tp& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __y; + __r *= __x; + return __r; + } + //@} + + //@{ + /// Return new complex value @a x divided by @a y. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator/(const complex<_Tp>& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r /= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator/(const complex<_Tp>& __x, const _Tp& __y) + { + complex<_Tp> __r = __x; + __r /= __y; + return __r; + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator/(const _Tp& __x, const complex<_Tp>& __y) + { + complex<_Tp> __r = __x; + __r /= __y; + return __r; + } + //@} + + /// Return @a x. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator+(const complex<_Tp>& __x) + { return __x; } + + /// Return complex negation of @a x. + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + operator-(const complex<_Tp>& __x) + { return complex<_Tp>(-__x.real(), -__x.imag()); } + + //@{ + /// Return true if @a x is equal to @a y. + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __x.real() == __y.real() && __x.imag() == __y.imag(); } + + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const complex<_Tp>& __x, const _Tp& __y) + { return __x.real() == __y && __x.imag() == _Tp(); } + +#if !(__cpp_impl_three_way_comparison >= 201907L) + template + inline _GLIBCXX_CONSTEXPR bool + operator==(const _Tp& __x, const complex<_Tp>& __y) + { return __x == __y.real() && _Tp() == __y.imag(); } + //@} + + //@{ + /// Return false if @a x is equal to @a y. + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __x.real() != __y.real() || __x.imag() != __y.imag(); } + + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const complex<_Tp>& __x, const _Tp& __y) + { return __x.real() != __y || __x.imag() != _Tp(); } + + template + inline _GLIBCXX_CONSTEXPR bool + operator!=(const _Tp& __x, const complex<_Tp>& __y) + { return __x != __y.real() || _Tp() != __y.imag(); } +#endif + //@} + + // Values +#if __cplusplus >= 201103L + template + constexpr _Tp + real(const complex<_Tp>& __z) + { return __z.real(); } + + template + constexpr _Tp + imag(const complex<_Tp>& __z) + { return __z.imag(); } +#else + template + inline _Tp& + real(complex<_Tp>& __z) + { return __z.real(); } + + template + inline const _Tp& + real(const complex<_Tp>& __z) + { return __z.real(); } + + template + inline _Tp& + imag(complex<_Tp>& __z) + { return __z.imag(); } + + template + inline const _Tp& + imag(const complex<_Tp>& __z) + { return __z.imag(); } +#endif + + // 26.2.7/3 abs(__z): Returns the magnitude of __z. + template + inline _Tp + __complex_abs(const complex<_Tp>& __z) + { + _Tp __x = __z.real(); + _Tp __y = __z.imag(); + const _Tp __s = std::max(abs(__x), abs(__y)); + if (__s == _Tp()) // well ... + return __s; + __x /= __s; + __y /= __s; + return __s * sqrt(__x * __x + __y * __y); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline float + __complex_abs(__complex__ float __z) { return __builtin_cabsf(__z); } + + inline double + __complex_abs(__complex__ double __z) { return __builtin_cabs(__z); } + + inline long double + __complex_abs(const __complex__ long double& __z) + { return __builtin_cabsl(__z); } + + template + inline _Tp + abs(const complex<_Tp>& __z) { return __complex_abs(__z.__rep()); } +#else + template + inline _Tp + abs(const complex<_Tp>& __z) { return __complex_abs(__z); } +#endif + + + // 26.2.7/4: arg(__z): Returns the phase angle of __z. + template + inline _Tp + __complex_arg(const complex<_Tp>& __z) + { return atan2(__z.imag(), __z.real()); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline float + __complex_arg(__complex__ float __z) { return __builtin_cargf(__z); } + + inline double + __complex_arg(__complex__ double __z) { return __builtin_carg(__z); } + + inline long double + __complex_arg(const __complex__ long double& __z) + { return __builtin_cargl(__z); } + + template + inline _Tp + arg(const complex<_Tp>& __z) { return __complex_arg(__z.__rep()); } +#else + template + inline _Tp + arg(const complex<_Tp>& __z) { return __complex_arg(__z); } +#endif + + // 26.2.7/5: norm(__z) returns the squared magnitude of __z. + // As defined, norm() is -not- a norm is the common mathematical + // sense used in numerics. The helper class _Norm_helper<> tries to + // distinguish between builtin floating point and the rest, so as + // to deliver an answer as close as possible to the real value. + template + struct _Norm_helper + { + template + static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return __x * __x + __y * __y; + } + }; + + template<> + struct _Norm_helper + { + template + static inline _GLIBCXX20_CONSTEXPR _Tp _S_do_it(const complex<_Tp>& __z) + { + //_Tp __res = std::abs(__z); + //return __res * __res; + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return __x * __x + __y * __y; + } + }; + + template + inline _GLIBCXX20_CONSTEXPR _Tp + norm(const complex<_Tp>& __z) + { + return _Norm_helper<__is_floating<_Tp>::__value + && !_GLIBCXX_FAST_MATH>::_S_do_it(__z); + } + + template + inline complex<_Tp> + polar(const _Tp& __rho, const _Tp& __theta) + { + __glibcxx_assert( __rho >= 0 ); + return complex<_Tp>(__rho * cos(__theta), __rho * sin(__theta)); + } + + template + inline _GLIBCXX20_CONSTEXPR complex<_Tp> + conj(const complex<_Tp>& __z) + { return complex<_Tp>(__z.real(), -__z.imag()); } + + // Transcendentals + + // 26.2.8/1 cos(__z): Returns the cosine of __z. + template + inline complex<_Tp> + __complex_cos(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(cos(__x) * cosh(__y), -sin(__x) * sinh(__y)); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_cos(__complex__ float __z) { return __builtin_ccosf(__z); } + + inline __complex__ double + __complex_cos(__complex__ double __z) { return __builtin_ccos(__z); } + + inline __complex__ long double + __complex_cos(const __complex__ long double& __z) + { return __builtin_ccosl(__z); } + + template + inline complex<_Tp> + cos(const complex<_Tp>& __z) { return __complex_cos(__z.__rep()); } +#else + template + inline complex<_Tp> + cos(const complex<_Tp>& __z) { return __complex_cos(__z); } +#endif + + // 26.2.8/2 cosh(__z): Returns the hyperbolic cosine of __z. + template + inline complex<_Tp> + __complex_cosh(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(cosh(__x) * cos(__y), sinh(__x) * sin(__y)); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_cosh(__complex__ float __z) { return __builtin_ccoshf(__z); } + + inline __complex__ double + __complex_cosh(__complex__ double __z) { return __builtin_ccosh(__z); } + + inline __complex__ long double + __complex_cosh(const __complex__ long double& __z) + { return __builtin_ccoshl(__z); } + + template + inline complex<_Tp> + cosh(const complex<_Tp>& __z) { return __complex_cosh(__z.__rep()); } +#else + template + inline complex<_Tp> + cosh(const complex<_Tp>& __z) { return __complex_cosh(__z); } +#endif + + // 26.2.8/3 exp(__z): Returns the complex base e exponential of x + template + inline complex<_Tp> + __complex_exp(const complex<_Tp>& __z) + { return std::polar<_Tp>(exp(__z.real()), __z.imag()); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_exp(__complex__ float __z) { return __builtin_cexpf(__z); } + + inline __complex__ double + __complex_exp(__complex__ double __z) { return __builtin_cexp(__z); } + + inline __complex__ long double + __complex_exp(const __complex__ long double& __z) + { return __builtin_cexpl(__z); } + + template + inline complex<_Tp> + exp(const complex<_Tp>& __z) { return __complex_exp(__z.__rep()); } +#else + template + inline complex<_Tp> + exp(const complex<_Tp>& __z) { return __complex_exp(__z); } +#endif + + // 26.2.8/5 log(__z): Returns the natural complex logarithm of __z. + // The branch cut is along the negative axis. + template + inline complex<_Tp> + __complex_log(const complex<_Tp>& __z) + { return complex<_Tp>(log(std::abs(__z)), std::arg(__z)); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_log(__complex__ float __z) { return __builtin_clogf(__z); } + + inline __complex__ double + __complex_log(__complex__ double __z) { return __builtin_clog(__z); } + + inline __complex__ long double + __complex_log(const __complex__ long double& __z) + { return __builtin_clogl(__z); } + + template + inline complex<_Tp> + log(const complex<_Tp>& __z) { return __complex_log(__z.__rep()); } +#else + template + inline complex<_Tp> + log(const complex<_Tp>& __z) { return __complex_log(__z); } +#endif + + template + inline complex<_Tp> + log10(const complex<_Tp>& __z) + { return std::log(__z) / log(_Tp(10.0)); } + + // 26.2.8/10 sin(__z): Returns the sine of __z. + template + inline complex<_Tp> + __complex_sin(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(sin(__x) * cosh(__y), cos(__x) * sinh(__y)); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sin(__complex__ float __z) { return __builtin_csinf(__z); } + + inline __complex__ double + __complex_sin(__complex__ double __z) { return __builtin_csin(__z); } + + inline __complex__ long double + __complex_sin(const __complex__ long double& __z) + { return __builtin_csinl(__z); } + + template + inline complex<_Tp> + sin(const complex<_Tp>& __z) { return __complex_sin(__z.__rep()); } +#else + template + inline complex<_Tp> + sin(const complex<_Tp>& __z) { return __complex_sin(__z); } +#endif + + // 26.2.8/11 sinh(__z): Returns the hyperbolic sine of __z. + template + inline complex<_Tp> + __complex_sinh(const complex<_Tp>& __z) + { + const _Tp __x = __z.real(); + const _Tp __y = __z.imag(); + return complex<_Tp>(sinh(__x) * cos(__y), cosh(__x) * sin(__y)); + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sinh(__complex__ float __z) { return __builtin_csinhf(__z); } + + inline __complex__ double + __complex_sinh(__complex__ double __z) { return __builtin_csinh(__z); } + + inline __complex__ long double + __complex_sinh(const __complex__ long double& __z) + { return __builtin_csinhl(__z); } + + template + inline complex<_Tp> + sinh(const complex<_Tp>& __z) { return __complex_sinh(__z.__rep()); } +#else + template + inline complex<_Tp> + sinh(const complex<_Tp>& __z) { return __complex_sinh(__z); } +#endif + + // 26.2.8/13 sqrt(__z): Returns the complex square root of __z. + // The branch cut is on the negative axis. + template + complex<_Tp> + __complex_sqrt(const complex<_Tp>& __z) + { + _Tp __x = __z.real(); + _Tp __y = __z.imag(); + + if (__x == _Tp()) + { + _Tp __t = sqrt(abs(__y) / 2); + return complex<_Tp>(__t, __y < _Tp() ? -__t : __t); + } + else + { + _Tp __t = sqrt(2 * (std::abs(__z) + abs(__x))); + _Tp __u = __t / 2; + return __x > _Tp() + ? complex<_Tp>(__u, __y / __t) + : complex<_Tp>(abs(__y) / __t, __y < _Tp() ? -__u : __u); + } + } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_sqrt(__complex__ float __z) { return __builtin_csqrtf(__z); } + + inline __complex__ double + __complex_sqrt(__complex__ double __z) { return __builtin_csqrt(__z); } + + inline __complex__ long double + __complex_sqrt(const __complex__ long double& __z) + { return __builtin_csqrtl(__z); } + + template + inline complex<_Tp> + sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z.__rep()); } +#else + template + inline complex<_Tp> + sqrt(const complex<_Tp>& __z) { return __complex_sqrt(__z); } +#endif + + // 26.2.8/14 tan(__z): Return the complex tangent of __z. + + template + inline complex<_Tp> + __complex_tan(const complex<_Tp>& __z) + { return std::sin(__z) / std::cos(__z); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_tan(__complex__ float __z) { return __builtin_ctanf(__z); } + + inline __complex__ double + __complex_tan(__complex__ double __z) { return __builtin_ctan(__z); } + + inline __complex__ long double + __complex_tan(const __complex__ long double& __z) + { return __builtin_ctanl(__z); } + + template + inline complex<_Tp> + tan(const complex<_Tp>& __z) { return __complex_tan(__z.__rep()); } +#else + template + inline complex<_Tp> + tan(const complex<_Tp>& __z) { return __complex_tan(__z); } +#endif + + + // 26.2.8/15 tanh(__z): Returns the hyperbolic tangent of __z. + + template + inline complex<_Tp> + __complex_tanh(const complex<_Tp>& __z) + { return std::sinh(__z) / std::cosh(__z); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_tanh(__complex__ float __z) { return __builtin_ctanhf(__z); } + + inline __complex__ double + __complex_tanh(__complex__ double __z) { return __builtin_ctanh(__z); } + + inline __complex__ long double + __complex_tanh(const __complex__ long double& __z) + { return __builtin_ctanhl(__z); } + + template + inline complex<_Tp> + tanh(const complex<_Tp>& __z) { return __complex_tanh(__z.__rep()); } +#else + template + inline complex<_Tp> + tanh(const complex<_Tp>& __z) { return __complex_tanh(__z); } +#endif + + + // 26.2.8/9 pow(__x, __y): Returns the complex power base of __x + // raised to the __y-th power. The branch + // cut is on the negative axis. + template + complex<_Tp> + __complex_pow_unsigned(complex<_Tp> __x, unsigned __n) + { + complex<_Tp> __y = __n % 2 ? __x : complex<_Tp>(1); + + while (__n >>= 1) + { + __x *= __x; + if (__n % 2) + __y *= __x; + } + + return __y; + } + + // In C++11 mode we used to implement the resolution of + // DR 844. complex pow return type is ambiguous. + // thus the following overload was disabled in that mode. However, doing + // that causes all sorts of issues, see, for example: + // http://gcc.gnu.org/ml/libstdc++/2013-01/msg00058.html + // and also PR57974. + template + inline complex<_Tp> + pow(const complex<_Tp>& __z, int __n) + { + return __n < 0 + ? complex<_Tp>(1) / std::__complex_pow_unsigned(__z, -(unsigned)__n) + : std::__complex_pow_unsigned(__z, __n); + } + + template + complex<_Tp> + pow(const complex<_Tp>& __x, const _Tp& __y) + { +#if ! _GLIBCXX_USE_C99_COMPLEX + if (__x == _Tp()) + return _Tp(); +#endif + if (__x.imag() == _Tp() && __x.real() > _Tp()) + return pow(__x.real(), __y); + + complex<_Tp> __t = std::log(__x); + return std::polar<_Tp>(exp(__y * __t.real()), __y * __t.imag()); + } + + template + inline complex<_Tp> + __complex_pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __x == _Tp() ? _Tp() : std::exp(__y * std::log(__x)); } + +#if _GLIBCXX_USE_C99_COMPLEX + inline __complex__ float + __complex_pow(__complex__ float __x, __complex__ float __y) + { return __builtin_cpowf(__x, __y); } + + inline __complex__ double + __complex_pow(__complex__ double __x, __complex__ double __y) + { return __builtin_cpow(__x, __y); } + + inline __complex__ long double + __complex_pow(const __complex__ long double& __x, + const __complex__ long double& __y) + { return __builtin_cpowl(__x, __y); } + + template + inline complex<_Tp> + pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __complex_pow(__x.__rep(), __y.__rep()); } +#else + template + inline complex<_Tp> + pow(const complex<_Tp>& __x, const complex<_Tp>& __y) + { return __complex_pow(__x, __y); } +#endif + + template + inline complex<_Tp> + pow(const _Tp& __x, const complex<_Tp>& __y) + { + return __x > _Tp() ? std::polar<_Tp>(pow(__x, __y.real()), + __y.imag() * log(__x)) + : std::pow(complex<_Tp>(__x), __y); + } + + /// 26.2.3 complex specializations + /// complex specialization + template<> + struct complex + { + typedef float value_type; + typedef __complex__ float _ComplexT; + + _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } + + _GLIBCXX_CONSTEXPR complex(float __r = 0.0f, float __i = 0.0f) +#if __cplusplus >= 201103L + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif + + explicit _GLIBCXX_CONSTEXPR complex(const complex&); + explicit _GLIBCXX_CONSTEXPR complex(const complex&); + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + __attribute ((__abi_tag__ ("cxx11"))) + constexpr float + real() const { return __real__ _M_value; } + + __attribute ((__abi_tag__ ("cxx11"))) + constexpr float + imag() const { return __imag__ _M_value; } +#else + float& + real() { return __real__ _M_value; } + + const float& + real() const { return __real__ _M_value; } + + float& + imag() { return __imag__ _M_value; } + + const float& + imag() const { return __imag__ _M_value; } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX20_CONSTEXPR void + real(float __val) { __real__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR void + imag(float __val) { __imag__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR complex& + operator=(float __f) + { + _M_value = __f; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator+=(float __f) + { + _M_value += __f; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator-=(float __f) + { + _M_value -= __f; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator*=(float __f) + { + _M_value *= __f; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator/=(float __f) + { + _M_value /= __f; + return *this; + } + + // Let the compiler synthesize the copy and assignment + // operator. It always does a pretty good job. +#if __cplusplus >= 201103L + _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; +#endif + + template + _GLIBCXX20_CONSTEXPR complex& + operator=(const complex<_Tp>& __z) + { + __real__ _M_value = __z.real(); + __imag__ _M_value = __z.imag(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator+=(const complex<_Tp>& __z) + { + _M_value += __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator-=(const complex<_Tp>& __z) + { + _M_value -= __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator*=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value *= __t; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator/=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value /= __t; + return *this; + } + + _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } + + private: + _ComplexT _M_value; + }; + + /// 26.2.3 complex specializations + /// complex specialization + template<> + struct complex + { + typedef double value_type; + typedef __complex__ double _ComplexT; + + _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } + + _GLIBCXX_CONSTEXPR complex(double __r = 0.0, double __i = 0.0) +#if __cplusplus >= 201103L + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif + + _GLIBCXX_CONSTEXPR complex(const complex& __z) + : _M_value(__z.__rep()) { } + + explicit _GLIBCXX_CONSTEXPR complex(const complex&); + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + __attribute ((__abi_tag__ ("cxx11"))) + constexpr double + real() const { return __real__ _M_value; } + + __attribute ((__abi_tag__ ("cxx11"))) + constexpr double + imag() const { return __imag__ _M_value; } +#else + double& + real() { return __real__ _M_value; } + + const double& + real() const { return __real__ _M_value; } + + double& + imag() { return __imag__ _M_value; } + + const double& + imag() const { return __imag__ _M_value; } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX20_CONSTEXPR void + real(double __val) { __real__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR void + imag(double __val) { __imag__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR complex& + operator=(double __d) + { + _M_value = __d; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator+=(double __d) + { + _M_value += __d; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator-=(double __d) + { + _M_value -= __d; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator*=(double __d) + { + _M_value *= __d; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator/=(double __d) + { + _M_value /= __d; + return *this; + } + + // The compiler will synthesize this, efficiently. +#if __cplusplus >= 201103L + _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; +#endif + + template + _GLIBCXX20_CONSTEXPR complex& + operator=(const complex<_Tp>& __z) + { + _M_value = __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator+=(const complex<_Tp>& __z) + { + _M_value += __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator-=(const complex<_Tp>& __z) + { + _M_value -= __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator*=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value *= __t; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator/=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value /= __t; + return *this; + } + + _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } + + private: + _ComplexT _M_value; + }; + + /// 26.2.3 complex specializations + /// complex specialization + template<> + struct complex + { + typedef long double value_type; + typedef __complex__ long double _ComplexT; + + _GLIBCXX_CONSTEXPR complex(_ComplexT __z) : _M_value(__z) { } + + _GLIBCXX_CONSTEXPR complex(long double __r = 0.0L, + long double __i = 0.0L) +#if __cplusplus >= 201103L + : _M_value{ __r, __i } { } +#else + { + __real__ _M_value = __r; + __imag__ _M_value = __i; + } +#endif + + _GLIBCXX_CONSTEXPR complex(const complex& __z) + : _M_value(__z.__rep()) { } + + _GLIBCXX_CONSTEXPR complex(const complex& __z) + : _M_value(__z.__rep()) { } + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + __attribute ((__abi_tag__ ("cxx11"))) + constexpr long double + real() const { return __real__ _M_value; } + + __attribute ((__abi_tag__ ("cxx11"))) + constexpr long double + imag() const { return __imag__ _M_value; } +#else + long double& + real() { return __real__ _M_value; } + + const long double& + real() const { return __real__ _M_value; } + + long double& + imag() { return __imag__ _M_value; } + + const long double& + imag() const { return __imag__ _M_value; } +#endif + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // DR 387. std::complex over-encapsulated. + _GLIBCXX20_CONSTEXPR void + real(long double __val) { __real__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR void + imag(long double __val) { __imag__ _M_value = __val; } + + _GLIBCXX20_CONSTEXPR complex& + operator=(long double __r) + { + _M_value = __r; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator+=(long double __r) + { + _M_value += __r; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator-=(long double __r) + { + _M_value -= __r; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator*=(long double __r) + { + _M_value *= __r; + return *this; + } + + _GLIBCXX20_CONSTEXPR complex& + operator/=(long double __r) + { + _M_value /= __r; + return *this; + } + + // The compiler knows how to do this efficiently +#if __cplusplus >= 201103L + _GLIBCXX14_CONSTEXPR complex& operator=(const complex&) = default; +#endif + + template + _GLIBCXX20_CONSTEXPR complex& + operator=(const complex<_Tp>& __z) + { + _M_value = __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator+=(const complex<_Tp>& __z) + { + _M_value += __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator-=(const complex<_Tp>& __z) + { + _M_value -= __z.__rep(); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator*=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value *= __t; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR complex& + operator/=(const complex<_Tp>& __z) + { + const _ComplexT __t = __z.__rep(); + _M_value /= __t; + return *this; + } + + _GLIBCXX_CONSTEXPR _ComplexT __rep() const { return _M_value; } + + private: + _ComplexT _M_value; + }; + + // These bits have to be at the end of this file, so that the + // specializations have all been defined. + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } + + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } + + inline _GLIBCXX_CONSTEXPR + complex::complex(const complex& __z) + : _M_value(__z.__rep()) { } + + // @} group complex_numbers + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // See ext/type_traits.h for the primary template. + template + struct __promote_2, _Up> + { + public: + typedef std::complex::__type> __type; + }; + + template + struct __promote_2<_Tp, std::complex<_Up> > + { + public: + typedef std::complex::__type> __type; + }; + + template + struct __promote_2, std::complex<_Up> > + { + public: + typedef std::complex::__type> __type; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if __cplusplus >= 201103L + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Forward declarations. + template std::complex<_Tp> acos(const std::complex<_Tp>&); + template std::complex<_Tp> asin(const std::complex<_Tp>&); + template std::complex<_Tp> atan(const std::complex<_Tp>&); + + template std::complex<_Tp> acosh(const std::complex<_Tp>&); + template std::complex<_Tp> asinh(const std::complex<_Tp>&); + template std::complex<_Tp> atanh(const std::complex<_Tp>&); + // DR 595. + template _Tp fabs(const std::complex<_Tp>&); + + template + inline std::complex<_Tp> + __complex_acos(const std::complex<_Tp>& __z) + { + const std::complex<_Tp> __t = std::asin(__z); + const _Tp __pi_2 = 1.5707963267948966192313216916397514L; + return std::complex<_Tp>(__pi_2 - __t.real(), -__t.imag()); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_acos(__complex__ float __z) + { return __builtin_cacosf(__z); } + + inline __complex__ double + __complex_acos(__complex__ double __z) + { return __builtin_cacos(__z); } + + inline __complex__ long double + __complex_acos(const __complex__ long double& __z) + { return __builtin_cacosl(__z); } + + template + inline std::complex<_Tp> + acos(const std::complex<_Tp>& __z) + { return __complex_acos(__z.__rep()); } +#else + /// acos(__z) [8.1.2]. + // Effects: Behaves the same as C99 function cacos, defined + // in subclause 7.3.5.1. + template + inline std::complex<_Tp> + acos(const std::complex<_Tp>& __z) + { return __complex_acos(__z); } +#endif + + template + inline std::complex<_Tp> + __complex_asin(const std::complex<_Tp>& __z) + { + std::complex<_Tp> __t(-__z.imag(), __z.real()); + __t = std::asinh(__t); + return std::complex<_Tp>(__t.imag(), -__t.real()); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_asin(__complex__ float __z) + { return __builtin_casinf(__z); } + + inline __complex__ double + __complex_asin(__complex__ double __z) + { return __builtin_casin(__z); } + + inline __complex__ long double + __complex_asin(const __complex__ long double& __z) + { return __builtin_casinl(__z); } + + template + inline std::complex<_Tp> + asin(const std::complex<_Tp>& __z) + { return __complex_asin(__z.__rep()); } +#else + /// asin(__z) [8.1.3]. + // Effects: Behaves the same as C99 function casin, defined + // in subclause 7.3.5.2. + template + inline std::complex<_Tp> + asin(const std::complex<_Tp>& __z) + { return __complex_asin(__z); } +#endif + + template + std::complex<_Tp> + __complex_atan(const std::complex<_Tp>& __z) + { + const _Tp __r2 = __z.real() * __z.real(); + const _Tp __x = _Tp(1.0) - __r2 - __z.imag() * __z.imag(); + + _Tp __num = __z.imag() + _Tp(1.0); + _Tp __den = __z.imag() - _Tp(1.0); + + __num = __r2 + __num * __num; + __den = __r2 + __den * __den; + + return std::complex<_Tp>(_Tp(0.5) * atan2(_Tp(2.0) * __z.real(), __x), + _Tp(0.25) * log(__num / __den)); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_atan(__complex__ float __z) + { return __builtin_catanf(__z); } + + inline __complex__ double + __complex_atan(__complex__ double __z) + { return __builtin_catan(__z); } + + inline __complex__ long double + __complex_atan(const __complex__ long double& __z) + { return __builtin_catanl(__z); } + + template + inline std::complex<_Tp> + atan(const std::complex<_Tp>& __z) + { return __complex_atan(__z.__rep()); } +#else + /// atan(__z) [8.1.4]. + // Effects: Behaves the same as C99 function catan, defined + // in subclause 7.3.5.3. + template + inline std::complex<_Tp> + atan(const std::complex<_Tp>& __z) + { return __complex_atan(__z); } +#endif + + template + std::complex<_Tp> + __complex_acosh(const std::complex<_Tp>& __z) + { + // Kahan's formula. + return _Tp(2.0) * std::log(std::sqrt(_Tp(0.5) * (__z + _Tp(1.0))) + + std::sqrt(_Tp(0.5) * (__z - _Tp(1.0)))); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_acosh(__complex__ float __z) + { return __builtin_cacoshf(__z); } + + inline __complex__ double + __complex_acosh(__complex__ double __z) + { return __builtin_cacosh(__z); } + + inline __complex__ long double + __complex_acosh(const __complex__ long double& __z) + { return __builtin_cacoshl(__z); } + + template + inline std::complex<_Tp> + acosh(const std::complex<_Tp>& __z) + { return __complex_acosh(__z.__rep()); } +#else + /// acosh(__z) [8.1.5]. + // Effects: Behaves the same as C99 function cacosh, defined + // in subclause 7.3.6.1. + template + inline std::complex<_Tp> + acosh(const std::complex<_Tp>& __z) + { return __complex_acosh(__z); } +#endif + + template + std::complex<_Tp> + __complex_asinh(const std::complex<_Tp>& __z) + { + std::complex<_Tp> __t((__z.real() - __z.imag()) + * (__z.real() + __z.imag()) + _Tp(1.0), + _Tp(2.0) * __z.real() * __z.imag()); + __t = std::sqrt(__t); + + return std::log(__t + __z); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_asinh(__complex__ float __z) + { return __builtin_casinhf(__z); } + + inline __complex__ double + __complex_asinh(__complex__ double __z) + { return __builtin_casinh(__z); } + + inline __complex__ long double + __complex_asinh(const __complex__ long double& __z) + { return __builtin_casinhl(__z); } + + template + inline std::complex<_Tp> + asinh(const std::complex<_Tp>& __z) + { return __complex_asinh(__z.__rep()); } +#else + /// asinh(__z) [8.1.6]. + // Effects: Behaves the same as C99 function casin, defined + // in subclause 7.3.6.2. + template + inline std::complex<_Tp> + asinh(const std::complex<_Tp>& __z) + { return __complex_asinh(__z); } +#endif + + template + std::complex<_Tp> + __complex_atanh(const std::complex<_Tp>& __z) + { + const _Tp __i2 = __z.imag() * __z.imag(); + const _Tp __x = _Tp(1.0) - __i2 - __z.real() * __z.real(); + + _Tp __num = _Tp(1.0) + __z.real(); + _Tp __den = _Tp(1.0) - __z.real(); + + __num = __i2 + __num * __num; + __den = __i2 + __den * __den; + + return std::complex<_Tp>(_Tp(0.25) * (log(__num) - log(__den)), + _Tp(0.5) * atan2(_Tp(2.0) * __z.imag(), __x)); + } + +#if _GLIBCXX_USE_C99_COMPLEX_TR1 + inline __complex__ float + __complex_atanh(__complex__ float __z) + { return __builtin_catanhf(__z); } + + inline __complex__ double + __complex_atanh(__complex__ double __z) + { return __builtin_catanh(__z); } + + inline __complex__ long double + __complex_atanh(const __complex__ long double& __z) + { return __builtin_catanhl(__z); } + + template + inline std::complex<_Tp> + atanh(const std::complex<_Tp>& __z) + { return __complex_atanh(__z.__rep()); } +#else + /// atanh(__z) [8.1.7]. + // Effects: Behaves the same as C99 function catanh, defined + // in subclause 7.3.6.3. + template + inline std::complex<_Tp> + atanh(const std::complex<_Tp>& __z) + { return __complex_atanh(__z); } +#endif + + template + inline _Tp + /// fabs(__z) [8.1.8]. + // Effects: Behaves the same as C99 function cabs, defined + // in subclause 7.3.8.1. + fabs(const std::complex<_Tp>& __z) + { return std::abs(__z); } + + /// Additional overloads [8.1.9]. + template + inline typename __gnu_cxx::__promote<_Tp>::__type + arg(_Tp __x) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; +#if (_GLIBCXX11_USE_C99_MATH && !_GLIBCXX_USE_C99_FP_MACROS_DYNAMIC) + return std::signbit(__x) ? __type(3.1415926535897932384626433832795029L) + : __type(); +#else + return std::arg(std::complex<__type>(__x)); +#endif + } + + template + _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type + imag(_Tp) + { return _Tp(); } + + template + _GLIBCXX20_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type + norm(_Tp __x) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return __type(__x) * __type(__x); + } + + template + _GLIBCXX_CONSTEXPR inline typename __gnu_cxx::__promote<_Tp>::__type + real(_Tp __x) + { return __x; } + + template + inline std::complex::__type> + pow(const std::complex<_Tp>& __x, const _Up& __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return std::pow(std::complex<__type>(__x), __type(__y)); + } + + template + inline std::complex::__type> + pow(const _Tp& __x, const std::complex<_Up>& __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return std::pow(__type(__x), std::complex<__type>(__y)); + } + + template + inline std::complex::__type> + pow(const std::complex<_Tp>& __x, const std::complex<_Up>& __y) + { + typedef typename __gnu_cxx::__promote_2<_Tp, _Up>::__type __type; + return std::pow(std::complex<__type>(__x), + std::complex<__type>(__y)); + } + + // Forward declarations. + // DR 781. + template + std::complex<_Tp> proj(const std::complex<_Tp>&); + + // Generic implementation of std::proj, does not work for infinities. + template + inline std::complex<_Tp> + __complex_proj(const std::complex<_Tp>& __z) + { return __z; } + +#if _GLIBCXX_USE_C99_COMPLEX + inline complex + __complex_proj(const complex& __z) + { return __builtin_cprojf(__z.__rep()); } + + inline complex + __complex_proj(const complex& __z) + { return __builtin_cproj(__z.__rep()); } + + inline complex + __complex_proj(const complex& __z) + { return __builtin_cprojl(__z.__rep()); } +#elif defined _GLIBCXX_USE_C99_MATH_TR1 + inline complex + __complex_proj(const complex& __z) + { + if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) + return complex(__builtin_inff(), + __builtin_copysignf(0.0f, __z.imag())); + return __z; + } + + inline complex + __complex_proj(const complex& __z) + { + if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) + return complex(__builtin_inf(), + __builtin_copysign(0.0, __z.imag())); + return __z; + } + + inline complex + __complex_proj(const complex& __z) + { + if (__builtin_isinf(__z.real()) || __builtin_isinf(__z.imag())) + return complex(__builtin_infl(), + __builtin_copysignl(0.0l, __z.imag())); + return __z; + } +#endif + + template + inline std::complex<_Tp> + proj(const std::complex<_Tp>& __z) + { return __complex_proj(__z); } + + // Overload for scalars + template + inline std::complex::__type> + proj(_Tp __x) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return std::proj(std::complex<__type>(__x)); + } + + template + inline _GLIBCXX20_CONSTEXPR + std::complex::__type> + conj(_Tp __x) + { + typedef typename __gnu_cxx::__promote<_Tp>::__type __type; + return std::complex<__type>(__x, -__type()); + } + +#if __cplusplus > 201103L + +inline namespace literals { +inline namespace complex_literals { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" +#define __cpp_lib_complex_udls 201309 + + constexpr std::complex + operator""if(long double __num) + { return std::complex{0.0F, static_cast(__num)}; } + + constexpr std::complex + operator""if(unsigned long long __num) + { return std::complex{0.0F, static_cast(__num)}; } + + constexpr std::complex + operator""i(long double __num) + { return std::complex{0.0, static_cast(__num)}; } + + constexpr std::complex + operator""i(unsigned long long __num) + { return std::complex{0.0, static_cast(__num)}; } + + constexpr std::complex + operator""il(long double __num) + { return std::complex{0.0L, __num}; } + + constexpr std::complex + operator""il(unsigned long long __num) + { return std::complex{0.0L, static_cast(__num)}; } + +#pragma GCC diagnostic pop +} // inline namespace complex_literals +} // inline namespace literals + +#endif // C++14 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif /* _GLIBCXX_COMPLEX */ diff --git a/resources/sources/avr-libstdcpp/include/concepts b/resources/sources/avr-libstdcpp/include/concepts new file mode 100644 index 000000000..e710a5e6e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/concepts @@ -0,0 +1,367 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/concepts + * This is a Standard C++ Library header. + * @ingroup concepts + */ + +#ifndef _GLIBCXX_CONCEPTS +#define _GLIBCXX_CONCEPTS 1 + +#if __cplusplus > 201703L && __cpp_concepts >= 201907L + +#pragma GCC system_header + +/** + * @defgroup concepts Concepts + * @ingroup utilities + * + * Concepts for checking type requirements. + */ + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_concepts 202002L + + // [concepts.lang], language-related concepts + + namespace __detail + { + template + concept __same_as = std::is_same_v<_Tp, _Up>; + } // namespace __detail + + /// [concept.same], concept same_as + template + concept same_as + = __detail::__same_as<_Tp, _Up> && __detail::__same_as<_Up, _Tp>; + + /// [concept.derived], concept derived_from + template + concept derived_from = __is_base_of(_Base, _Derived) + && is_convertible_v; + + /// [concept.convertible], concept convertible_to + template + concept convertible_to = is_convertible_v<_From, _To> + && requires(add_rvalue_reference_t<_From> (&__f)()) { + static_cast<_To>(__f()); + }; + + /// [concept.commonref], concept common_reference_with + template + concept common_reference_with + = same_as, common_reference_t<_Up, _Tp>> + && convertible_to<_Tp, common_reference_t<_Tp, _Up>> + && convertible_to<_Up, common_reference_t<_Tp, _Up>>; + + /// [concept.common], concept common_with + template + concept common_with + = same_as, common_type_t<_Up, _Tp>> + && requires { + static_cast>(std::declval<_Tp>()); + static_cast>(std::declval<_Up>()); + } + && common_reference_with, + add_lvalue_reference_t> + && common_reference_with>, + common_reference_t< + add_lvalue_reference_t, + add_lvalue_reference_t>>; + + // [concepts.arithmetic], arithmetic concepts + + template + concept integral = is_integral_v<_Tp>; + + template + concept signed_integral = integral<_Tp> && is_signed_v<_Tp>; + + template + concept unsigned_integral = integral<_Tp> && !signed_integral<_Tp>; + + template + concept floating_point = is_floating_point_v<_Tp>; + + namespace __detail + { + template + using __cref = const remove_reference_t<_Tp>&; + + template + concept __class_or_enum + = is_class_v<_Tp> || is_union_v<_Tp> || is_enum_v<_Tp>; + } // namespace __detail + + /// [concept.assignable], concept assignable_from + template + concept assignable_from + = is_lvalue_reference_v<_Lhs> + && common_reference_with<__detail::__cref<_Lhs>, __detail::__cref<_Rhs>> + && requires(_Lhs __lhs, _Rhs&& __rhs) { + { __lhs = static_cast<_Rhs&&>(__rhs) } -> same_as<_Lhs>; + }; + + /// [concept.destructible], concept destructible + template + concept destructible = is_nothrow_destructible_v<_Tp>; + + /// [concept.constructible], concept constructible_from + template + concept constructible_from + = destructible<_Tp> && is_constructible_v<_Tp, _Args...>; + + /// [concept.defaultinitializable], concept default_initializable + template + concept default_initializable = constructible_from<_Tp> + && requires + { + _Tp{}; + (void) ::new _Tp; + }; + + /// [concept.moveconstructible], concept move_constructible + template + concept move_constructible + = constructible_from<_Tp, _Tp> && convertible_to<_Tp, _Tp>; + + /// [concept.copyconstructible], concept copy_constructible + template + concept copy_constructible + = move_constructible<_Tp> + && constructible_from<_Tp, _Tp&> && convertible_to<_Tp&, _Tp> + && constructible_from<_Tp, const _Tp&> && convertible_to + && constructible_from<_Tp, const _Tp> && convertible_to; + + // [concept.swappable], concept swappable + + namespace ranges + { + namespace __cust_swap + { + template void swap(_Tp&, _Tp&) = delete; + + template + concept __adl_swap + = (__detail::__class_or_enum> + || __detail::__class_or_enum>) + && requires(_Tp&& __t, _Up&& __u) { + swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + }; + + struct _Swap + { + private: + template + static constexpr bool + _S_noexcept() + { + if constexpr (__adl_swap<_Tp, _Up>) + return noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())); + else + return is_nothrow_move_constructible_v> + && is_nothrow_move_assignable_v>; + } + + public: + template + requires __adl_swap<_Tp, _Up> + || (same_as<_Tp, _Up> && is_lvalue_reference_v<_Tp> + && move_constructible> + && assignable_from<_Tp, remove_reference_t<_Tp>>) + constexpr void + operator()(_Tp&& __t, _Up&& __u) const + noexcept(_S_noexcept<_Tp, _Up>()) + { + if constexpr (__adl_swap<_Tp, _Up>) + swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + else + { + auto __tmp = static_cast&&>(__t); + __t = static_cast&&>(__u); + __u = static_cast&&>(__tmp); + } + } + + template + requires requires(const _Swap& __swap, _Tp& __e1, _Up& __e2) { + __swap(__e1, __e2); + } + constexpr void + operator()(_Tp (&__e1)[_Num], _Up (&__e2)[_Num]) const + noexcept(noexcept(std::declval()(*__e1, *__e2))) + { + for (size_t __n = 0; __n < _Num; ++__n) + (*this)(__e1[__n], __e2[__n]); + } + }; + } // namespace __cust_swap + + inline namespace __cust + { + inline constexpr __cust_swap::_Swap swap{}; + } // inline namespace __cust + } // namespace ranges + + template + concept swappable + = requires(_Tp& __a, _Tp& __b) { ranges::swap(__a, __b); }; + + template + concept swappable_with = common_reference_with<_Tp, _Up> + && requires(_Tp&& __t, _Up&& __u) { + ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Tp&&>(__t)); + ranges::swap(static_cast<_Up&&>(__u), static_cast<_Up&&>(__u)); + ranges::swap(static_cast<_Tp&&>(__t), static_cast<_Up&&>(__u)); + ranges::swap(static_cast<_Up&&>(__u), static_cast<_Tp&&>(__t)); + }; + + // [concepts.object], Object concepts + + template + concept movable = is_object_v<_Tp> && move_constructible<_Tp> + && assignable_from<_Tp&, _Tp> && swappable<_Tp>; + + template + concept copyable = copy_constructible<_Tp> && movable<_Tp> + && assignable_from<_Tp&, _Tp&> && assignable_from<_Tp&, const _Tp&> + && assignable_from<_Tp&, const _Tp>; + + template + concept semiregular = copyable<_Tp> && default_initializable<_Tp>; + + // [concepts.compare], comparison concepts + + // [concept.booleantestable], Boolean testability + namespace __detail + { + template + concept __boolean_testable_impl = convertible_to<_Tp, bool>; + + template + concept __boolean_testable + = __boolean_testable_impl<_Tp> + && requires(_Tp&& __t) + { { !static_cast<_Tp&&>(__t) } -> __boolean_testable_impl; }; + } // namespace __detail + + // [concept.equalitycomparable], concept equality_comparable + + namespace __detail + { + template + concept __weakly_eq_cmp_with + = requires(__detail::__cref<_Tp> __t, __detail::__cref<_Up> __u) { + { __t == __u } -> __boolean_testable; + { __t != __u } -> __boolean_testable; + { __u == __t } -> __boolean_testable; + { __u != __t } -> __boolean_testable; + }; + } // namespace __detail + + template + concept equality_comparable = __detail::__weakly_eq_cmp_with<_Tp, _Tp>; + + template + concept equality_comparable_with + = equality_comparable<_Tp> && equality_comparable<_Up> + && common_reference_with<__detail::__cref<_Tp>, __detail::__cref<_Up>> + && equality_comparable, + __detail::__cref<_Up>>> + && __detail::__weakly_eq_cmp_with<_Tp, _Up>; + + namespace __detail + { + template + concept __partially_ordered_with + = requires(const remove_reference_t<_Tp>& __t, + const remove_reference_t<_Up>& __u) { + { __t < __u } -> __boolean_testable; + { __t > __u } -> __boolean_testable; + { __t <= __u } -> __boolean_testable; + { __t >= __u } -> __boolean_testable; + { __u < __t } -> __boolean_testable; + { __u > __t } -> __boolean_testable; + { __u <= __t } -> __boolean_testable; + { __u >= __t } -> __boolean_testable; + }; + } // namespace __detail + + // [concept.totallyordered], concept totally_ordered + template + concept totally_ordered + = equality_comparable<_Tp> + && __detail::__partially_ordered_with<_Tp, _Tp>; + + template + concept totally_ordered_with + = totally_ordered<_Tp> && totally_ordered<_Up> + && equality_comparable_with<_Tp, _Up> + && totally_ordered, + __detail::__cref<_Up>>> + && __detail::__partially_ordered_with<_Tp, _Up>; + + template + concept regular = semiregular<_Tp> && equality_comparable<_Tp>; + + // [concepts.callable], callable concepts + + /// [concept.invocable], concept invocable + template + concept invocable = is_invocable_v<_Fn, _Args...>; + + /// [concept.regularinvocable], concept regular_invocable + template + concept regular_invocable = invocable<_Fn, _Args...>; + + /// [concept.predicate], concept predicate + template + concept predicate = regular_invocable<_Fn, _Args...> + && __detail::__boolean_testable>; + + /// [concept.relation], concept relation + template + concept relation + = predicate<_Rel, _Tp, _Tp> && predicate<_Rel, _Up, _Up> + && predicate<_Rel, _Tp, _Up> && predicate<_Rel, _Up, _Tp>; + + /// [concept.equiv], concept equivalence_relation + template + concept equivalence_relation = relation<_Rel, _Tp, _Up>; + + /// [concept.strictweakorder], concept strict_weak_order + template + concept strict_weak_order = relation<_Rel, _Tp, _Up>; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // C++2a + +#endif /* _GLIBCXX_CONCEPTS */ diff --git a/resources/sources/avr-libstdcpp/include/coroutine b/resources/sources/avr-libstdcpp/include/coroutine new file mode 100644 index 000000000..b40a3bcf9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/coroutine @@ -0,0 +1,303 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/coroutine + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_COROUTINE +#define _GLIBCXX_COROUTINE 1 + +#pragma GCC system_header + +// It is very likely that earlier versions would work, but they are untested. +#if __cplusplus >= 201402L + +#include + +/** + * @defgroup coroutines Coroutines + * + * Components for supporting coroutine implementations. + */ + +#if __cplusplus > 201703L && __cpp_impl_three_way_comparison >= 201907L +# include +# define _COROUTINES_USE_SPACESHIP 1 +#else +# include // for std::less +# define _COROUTINES_USE_SPACESHIP 0 +#endif + +namespace std _GLIBCXX_VISIBILITY (default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cpp_impl_coroutine + +#define __cpp_lib_coroutine 201902L + + inline namespace __n4861 { + + // 17.12.2 coroutine traits + /// [coroutine.traits] + /// [coroutine.traits.primary] + /// If _Result::promise_type is valid and denotes a type then the traits + /// have a single publicly accessible member, otherwise they are empty. + template + struct __coroutine_traits_impl {}; + + template + struct __coroutine_traits_impl<_Result, + __void_t> + { + using promise_type = typename _Result::promise_type; + }; + + template + struct coroutine_traits : __coroutine_traits_impl<_Result> {}; + + // 17.12.3 Class template coroutine_handle + /// [coroutine.handle] + template + struct coroutine_handle; + + template <> struct + coroutine_handle + { + public: + // 17.12.3.1, construct/reset + constexpr coroutine_handle() noexcept : _M_fr_ptr(0) {} + + constexpr coroutine_handle(std::nullptr_t __h) noexcept + : _M_fr_ptr(__h) + {} + + coroutine_handle& operator=(std::nullptr_t) noexcept + { + _M_fr_ptr = nullptr; + return *this; + } + + public: + // 17.12.3.2, export/import + constexpr void* address() const noexcept { return _M_fr_ptr; } + + constexpr static coroutine_handle from_address(void* __a) noexcept + { + coroutine_handle __self; + __self._M_fr_ptr = __a; + return __self; + } + + public: + // 17.12.3.3, observers + constexpr explicit operator bool() const noexcept + { + return bool(_M_fr_ptr); + } + + bool done() const noexcept { return __builtin_coro_done(_M_fr_ptr); } + + // 17.12.3.4, resumption + void operator()() const { resume(); } + + void resume() const { __builtin_coro_resume(_M_fr_ptr); } + + void destroy() const { __builtin_coro_destroy(_M_fr_ptr); } + + protected: + void* _M_fr_ptr; + }; + + // 17.12.3.6 Comparison operators + /// [coroutine.handle.compare] + constexpr bool operator==(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return __a.address() == __b.address(); + } + +#if _COROUTINES_USE_SPACESHIP + constexpr strong_ordering + operator<=>(coroutine_handle<> __a, coroutine_handle<> __b) noexcept + { return std::compare_three_way()(__a.address(), __b.address()); } +#else + // These are to enable operation with std=c++14,17. + constexpr bool operator!=(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return !(__a == __b); + } + + constexpr bool operator<(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return less()(__a.address(), __b.address()); + } + + constexpr bool operator>(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return __b < __a; + } + + constexpr bool operator<=(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return !(__a > __b); + } + + constexpr bool operator>=(coroutine_handle<> __a, + coroutine_handle<> __b) noexcept + { + return !(__a < __b); + } +#endif + + template + struct coroutine_handle : coroutine_handle<> + { + // 17.12.3.1, construct/reset + using coroutine_handle<>::coroutine_handle; + + static coroutine_handle from_promise(_Promise& p) + { + coroutine_handle __self; + __self._M_fr_ptr + = __builtin_coro_promise((char*) &p, __alignof(_Promise), true); + return __self; + } + + coroutine_handle& operator=(std::nullptr_t) noexcept + { + coroutine_handle<>::operator=(nullptr); + return *this; + } + + // 17.12.3.2, export/import + constexpr static coroutine_handle from_address(void* __a) + { + coroutine_handle __self; + __self._M_fr_ptr = __a; + return __self; + } + + // 17.12.3.5, promise accesss + _Promise& promise() const + { + void* __t + = __builtin_coro_promise (this->_M_fr_ptr, __alignof(_Promise), false); + return *static_cast<_Promise*>(__t); + } + }; + + /// [coroutine.noop] + struct noop_coroutine_promise + { + }; + + void __dummy_resume_destroy() __attribute__((__weak__)); + void __dummy_resume_destroy() {} + + struct __noop_coro_frame + { + void (*__r)() = __dummy_resume_destroy; + void (*__d)() = __dummy_resume_destroy; + struct noop_coroutine_promise __p; + } __noop_coro_fr __attribute__((__weak__)); + + // 17.12.4.1 Class noop_coroutine_promise + /// [coroutine.promise.noop] + template <> + struct coroutine_handle : public coroutine_handle<> + { + using _Promise = noop_coroutine_promise; + + public: + // 17.12.4.2.1, observers + constexpr explicit operator bool() const noexcept { return true; } + + constexpr bool done() const noexcept { return false; } + + // 17.12.4.2.2, resumption + void operator()() const noexcept {} + + void resume() const noexcept {} + + void destroy() const noexcept {} + + // 17.12.4.2.3, promise access + _Promise& promise() const + { + return *static_cast<_Promise*>( + __builtin_coro_promise(this->_M_fr_ptr, __alignof(_Promise), false)); + } + + // 17.12.4.2.4, address + private: + friend coroutine_handle noop_coroutine() noexcept; + + coroutine_handle() noexcept { this->_M_fr_ptr = (void*) &__noop_coro_fr; } + }; + + using noop_coroutine_handle = coroutine_handle; + + inline noop_coroutine_handle noop_coroutine() noexcept + { + return noop_coroutine_handle(); + } + + // 17.12.5 Trivial awaitables + /// [coroutine.trivial.awaitables] + struct suspend_always + { + bool await_ready() { return false; } + + void await_suspend(coroutine_handle<>) {} + + void await_resume() {} + }; + + struct suspend_never + { + bool await_ready() { return true; } + + void await_suspend(coroutine_handle<>) {} + + void await_resume() {} + }; + + } // namespace __n4861 + +#else +#error "the coroutine header requires -fcoroutines" +#endif + + _GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 (we are allowing use from at least this) + +#endif // _GLIBCXX_COROUTINE diff --git a/resources/sources/avr-libstdcpp/include/csetjmp b/resources/sources/avr-libstdcpp/include/csetjmp new file mode 100644 index 000000000..c3b77b023 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/csetjmp @@ -0,0 +1,61 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file csetjmp + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c setjmp.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CSETJMP +#define _GLIBCXX_CSETJMP 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef longjmp + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef setjmp +#define setjmp(env) setjmp (env) +#endif + +namespace std +{ + using ::jmp_buf; + using ::longjmp; +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/csignal b/resources/sources/avr-libstdcpp/include/csignal new file mode 100644 index 000000000..7a8841272 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/csignal @@ -0,0 +1,57 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file csignal + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c signal.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CSIGNAL +#define _GLIBCXX_CSIGNAL 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef raise + +namespace std +{ + using ::sig_atomic_t; + using ::signal; + using ::raise; +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cstdalign b/resources/sources/avr-libstdcpp/include/cstdalign new file mode 100644 index 000000000..b4c413a8a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdalign @@ -0,0 +1,44 @@ +// -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdalign + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CSTDALIGN +#define _GLIBCXX_CSTDALIGN 1 + +#if __cplusplus < 201103L +# include +#else +# include +# if _GLIBCXX_HAVE_STDALIGN_H +# include +# endif +#endif + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/cstdarg b/resources/sources/avr-libstdcpp/include/cstdarg new file mode 100644 index 000000000..749c85ec8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdarg @@ -0,0 +1,58 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdarg + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stdarg.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#undef __need___va_list +#include +#include + +#ifndef _GLIBCXX_CSTDARG +#define _GLIBCXX_CSTDARG 1 + +// Adhere to section 17.4.1.2 clause 5 of ISO 14882:1998 +#ifndef va_end +#define va_end(ap) va_end (ap) +#endif + +namespace std +{ + using ::va_list; +} // namespace std + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cstdbool b/resources/sources/avr-libstdcpp/include/cstdbool new file mode 100644 index 000000000..c76ecca3e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cstdbool @@ -0,0 +1,44 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdbool + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CSTDBOOL +#define _GLIBCXX_CSTDBOOL 1 + +#if __cplusplus < 201103L +# include +#else +# include +# if _GLIBCXX_HAVE_STDBOOL_H +# include +# endif +#endif + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/cstddef b/resources/sources/avr-libstdcpp/include/cstddef index 90cd0b111..ce9cd3e9d 100644 --- a/resources/sources/avr-libstdcpp/include/cstddef +++ b/resources/sources/avr-libstdcpp/include/cstddef @@ -1,10 +1,181 @@ -// Minimal for AVR -#ifndef _AVR_CSTDDEF -#define _AVR_CSTDDEF +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cstddef + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stddef.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 18.1 Types +// + +#ifndef _GLIBCXX_CSTDDEF +#define _GLIBCXX_CSTDDEF 1 + +#pragma GCC system_header + +#undef __need_wchar_t +#undef __need_ptrdiff_t +#undef __need_size_t +#undef __need_NULL +#undef __need_wint_t +#include #include -namespace std { - using ::size_t; - using ::ptrdiff_t; - using nullptr_t = decltype(nullptr); + +extern "C++" +{ +#if __cplusplus >= 201103L +namespace std +{ + // We handle size_t, ptrdiff_t, and nullptr_t in c++config.h. + using ::max_align_t; } +#endif // C++11 + +#if __cplusplus >= 201703L +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +#define __cpp_lib_byte 201603 + + /// std::byte + enum class byte : unsigned char {}; + + template struct __byte_operand { }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; +#ifdef _GLIBCXX_USE_WCHAR_T + template<> struct __byte_operand { using __type = byte; }; #endif +#ifdef _GLIBCXX_USE_CHAR8_T + template<> struct __byte_operand { using __type = byte; }; +#endif + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; + template<> struct __byte_operand { using __type = byte; }; +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_0> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_1> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> struct __byte_operand<__GLIBCXX_TYPE_INT_N_2> + { using __type = byte; }; + template<> struct __byte_operand + { using __type = byte; }; +#endif + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + template + struct __byte_operand + : __byte_operand<_IntegerType> { }; + + template + using __byte_op_t = typename __byte_operand<_IntegerType>::__type; + + template + constexpr __byte_op_t<_IntegerType> + operator<<(byte __b, _IntegerType __shift) noexcept + { return (byte)(unsigned char)((unsigned)__b << __shift); } + + template + constexpr __byte_op_t<_IntegerType> + operator>>(byte __b, _IntegerType __shift) noexcept + { return (byte)(unsigned char)((unsigned)__b >> __shift); } + + constexpr byte + operator|(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l | (unsigned)__r); } + + constexpr byte + operator&(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l & (unsigned)__r); } + + constexpr byte + operator^(byte __l, byte __r) noexcept + { return (byte)(unsigned char)((unsigned)__l ^ (unsigned)__r); } + + constexpr byte + operator~(byte __b) noexcept + { return (byte)(unsigned char)~(unsigned)__b; } + + template + constexpr __byte_op_t<_IntegerType>& + operator<<=(byte& __b, _IntegerType __shift) noexcept + { return __b = __b << __shift; } + + template + constexpr __byte_op_t<_IntegerType>& + operator>>=(byte& __b, _IntegerType __shift) noexcept + { return __b = __b >> __shift; } + + constexpr byte& + operator|=(byte& __l, byte __r) noexcept + { return __l = __l | __r; } + + constexpr byte& + operator&=(byte& __l, byte __r) noexcept + { return __l = __l & __r; } + + constexpr byte& + operator^=(byte& __l, byte __r) noexcept + { return __l = __l ^ __r; } + + template + constexpr _IntegerType + to_integer(__byte_op_t<_IntegerType> __b) noexcept + { return _IntegerType(__b); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 +} // extern "C++" + +#endif // _GLIBCXX_CSTDDEF diff --git a/resources/sources/avr-libstdcpp/include/cstdint b/resources/sources/avr-libstdcpp/include/cstdint index 30e620590..8e742fa7b 100644 --- a/resources/sources/avr-libstdcpp/include/cstdint +++ b/resources/sources/avr-libstdcpp/include/cstdint @@ -1,14 +1,91 @@ -// Minimal for AVR -- wraps into namespace std -#ifndef _AVR_CSTDINT -#define _AVR_CSTDINT -#include -namespace std { - using ::int8_t; using ::int16_t; using ::int32_t; using ::int64_t; - using ::uint8_t; using ::uint16_t; using ::uint32_t; using ::uint64_t; - using ::int_fast8_t; using ::int_fast16_t; using ::int_fast32_t; using ::int_fast64_t; - using ::uint_fast8_t; using ::uint_fast16_t; using ::uint_fast32_t; using ::uint_fast64_t; - using ::int_least8_t; using ::int_least16_t; using ::int_least32_t; using ::int_least64_t; - using ::uint_least8_t; using ::uint_least16_t; using ::uint_least32_t; using ::uint_least64_t; - using ::intmax_t; using ::uintmax_t; using ::intptr_t; using ::uintptr_t; -} +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdint + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_CSTDINT +#define _GLIBCXX_CSTDINT 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +#if _GLIBCXX_HAVE_STDINT_H +# include #endif + +namespace std +{ +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + using ::int8_t; + using ::int16_t; + using ::int32_t; + using ::int64_t; + + using ::int_fast8_t; + using ::int_fast16_t; + using ::int_fast32_t; + using ::int_fast64_t; + + using ::int_least8_t; + using ::int_least16_t; + using ::int_least32_t; + using ::int_least64_t; + + using ::intmax_t; + using ::intptr_t; + + using ::uint8_t; + using ::uint16_t; + using ::uint32_t; + using ::uint64_t; + + using ::uint_fast8_t; + using ::uint_fast16_t; + using ::uint_fast32_t; + using ::uint_fast64_t; + + using ::uint_least8_t; + using ::uint_least16_t; + using ::uint_least32_t; + using ::uint_least64_t; + + using ::uintmax_t; + using ::uintptr_t; +#else // !_GLIBCXX_USE_C99_STDINT_TR1 + // Define the minimum needed for , etc. + using intmax_t = __INTMAX_TYPE__; + using uintmax_t = __UINTMAX_TYPE__; +#endif // _GLIBCXX_USE_C99_STDINT_TR1 +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_CSTDINT diff --git a/resources/sources/avr-libstdcpp/include/cstdio b/resources/sources/avr-libstdcpp/include/cstdio index 4eccc4029..b1dad4e4b 100644 --- a/resources/sources/avr-libstdcpp/include/cstdio +++ b/resources/sources/avr-libstdcpp/include/cstdio @@ -1,6 +1,192 @@ -// Minimal for AVR -#ifndef _AVR_CSTDIO -#define _AVR_CSTDIO +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdio + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stdio.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 27.8.2 C Library files +// + +#pragma GCC system_header + +#include #include -namespace std { using ::snprintf; using ::sprintf; } + +#ifndef _GLIBCXX_CSTDIO +#define _GLIBCXX_CSTDIO 1 + +#if __cplusplus <= 201103L && !defined(_GLIBCXX_HAVE_GETS) +extern "C" char* gets (char* __s) __attribute__((__deprecated__)); +#endif + +// Get rid of those macros defined in in lieu of real functions. +#undef clearerr +#undef fclose +#undef feof +#undef ferror +#undef fflush +#undef fgetc +#undef fgetpos +#undef fgets +#undef fopen +#undef fprintf +#undef fputc +#undef fputs +#undef fread +#undef freopen +#undef fscanf +#undef fseek +#undef fsetpos +#undef ftell +#undef fwrite +#undef getc +#undef getchar +#if __cplusplus <= 201103L +# undef gets +#endif +#undef perror +#undef printf +#undef putc +#undef putchar +#undef puts +#undef remove +#undef rename +#undef rewind +#undef scanf +#undef setbuf +#undef setvbuf +#undef sprintf +#undef sscanf +#undef tmpfile +#undef tmpnam +#undef ungetc +#undef vfprintf +#undef vprintf +#undef vsprintf + +namespace std +{ + using ::FILE; + using ::fpos_t; + + using ::clearerr; + using ::fclose; + using ::feof; + using ::ferror; + using ::fflush; + using ::fgetc; + using ::fgetpos; + using ::fgets; + using ::fopen; + using ::fprintf; + using ::fputc; + using ::fputs; + using ::fread; + using ::freopen; + using ::fscanf; + using ::fseek; + using ::fsetpos; + using ::ftell; + using ::fwrite; + using ::getc; + using ::getchar; +#if __cplusplus <= 201103L + // LWG 2249 + using ::gets; +#endif + using ::perror; + using ::printf; + using ::putc; + using ::putchar; + using ::puts; + using ::remove; + using ::rename; + using ::rewind; + using ::scanf; + using ::setbuf; + using ::setvbuf; + using ::sprintf; + using ::sscanf; + using ::tmpfile; +#if _GLIBCXX_USE_TMPNAM + using ::tmpnam; +#endif + using ::ungetc; + using ::vfprintf; + using ::vprintf; + using ::vsprintf; +} // namespace + +#if _GLIBCXX_USE_C99_STDIO + +#undef snprintf +#undef vfscanf +#undef vscanf +#undef vsnprintf +#undef vsscanf + +namespace __gnu_cxx +{ +#if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC + extern "C" int + (snprintf)(char * __restrict, std::size_t, const char * __restrict, ...) + throw (); + extern "C" int + (vfscanf)(FILE * __restrict, const char * __restrict, __gnuc_va_list); + extern "C" int (vscanf)(const char * __restrict, __gnuc_va_list); + extern "C" int + (vsnprintf)(char * __restrict, std::size_t, const char * __restrict, + __gnuc_va_list) throw (); + extern "C" int + (vsscanf)(const char * __restrict, const char * __restrict, __gnuc_va_list) + throw (); +#endif + +#if !_GLIBCXX_USE_C99_DYNAMIC + using ::snprintf; + using ::vfscanf; + using ::vscanf; + using ::vsnprintf; +#endif +} // namespace __gnu_cxx + +namespace std +{ + using ::__gnu_cxx::snprintf; + using ::__gnu_cxx::vfscanf; + using ::__gnu_cxx::vscanf; + using ::__gnu_cxx::vsnprintf; +} // namespace std + +#endif // _GLIBCXX_USE_C99_STDIO + #endif diff --git a/resources/sources/avr-libstdcpp/include/cstdlib b/resources/sources/avr-libstdcpp/include/cstdlib index 740e04d46..c67f40145 100644 --- a/resources/sources/avr-libstdcpp/include/cstdlib +++ b/resources/sources/avr-libstdcpp/include/cstdlib @@ -1,21 +1,216 @@ -// Minimal for AVR -#ifndef _AVR_CSTDLIB -#define _AVR_CSTDLIB -#include +// -*- C++ -*- forwarding header. -// AVR libc doesn't have strtoll/strtoull -- provide minimal implementations -#ifdef __AVR__ -inline long long strtoll(const char* s, char** endp, int base) { - return (long long)strtol(s, endp, base); // truncated to 32-bit on AVR -} -inline unsigned long long strtoull(const char* s, char** endp, int base) { - return (unsigned long long)strtoul(s, endp, base); -} +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cstdlib + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c stdlib.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include + +#ifndef _GLIBCXX_CSTDLIB +#define _GLIBCXX_CSTDLIB 1 + +#if !_GLIBCXX_HOSTED +// The C standard does not require a freestanding implementation to +// provide . However, the C++ standard does still require +// -- but only the functionality mentioned in +// [lib.support.start.term]. + +#define EXIT_SUCCESS 0 +#define EXIT_FAILURE 1 + +namespace std +{ + extern "C" void abort(void) throw () _GLIBCXX_NORETURN; + extern "C" int atexit(void (*)(void)) throw (); + extern "C" void exit(int) throw () _GLIBCXX_NORETURN; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT + extern "C" int at_quick_exit(void (*)(void)) throw (); +# endif +# ifdef _GLIBCXX_HAVE_QUICK_EXIT + extern "C" void quick_exit(int) throw() _GLIBCXX_NORETURN; +# endif +#endif +} // namespace std + +#else + +// Need to ensure this finds the C library's not a libstdc++ +// wrapper that might already be installed later in the include search path. +#define _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include_next +#undef _GLIBCXX_INCLUDE_NEXT_C_HEADERS +#include + +// Get rid of those macros defined in in lieu of real functions. +#undef abort +#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) +# undef aligned_alloc +#endif +#undef atexit +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT +# undef at_quick_exit +# endif #endif +#undef atof +#undef atoi +#undef atol +#undef bsearch +#undef calloc +#undef div +#undef exit +#undef free +#undef getenv +#undef labs +#undef ldiv +#undef malloc +#undef mblen +#undef mbstowcs +#undef mbtowc +#undef qsort +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_QUICK_EXIT +# undef quick_exit +# endif +#endif +#undef rand +#undef realloc +#undef srand +#undef strtod +#undef strtol +#undef strtoul +#undef system +#undef wcstombs +#undef wctomb + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::div_t; + using ::ldiv_t; + + using ::abort; +#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_ALIGNED_ALLOC) + using ::aligned_alloc; +#endif + using ::atexit; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_AT_QUICK_EXIT + using ::at_quick_exit; +# endif +#endif + using ::atof; + using ::atoi; + using ::atol; + using ::bsearch; + using ::calloc; + using ::div; + using ::exit; + using ::free; + using ::getenv; + using ::labs; + using ::ldiv; + using ::malloc; +#ifdef _GLIBCXX_HAVE_MBSTATE_T + using ::mblen; + using ::mbstowcs; + using ::mbtowc; +#endif // _GLIBCXX_HAVE_MBSTATE_T + using ::qsort; +#if __cplusplus >= 201103L +# ifdef _GLIBCXX_HAVE_QUICK_EXIT + using ::quick_exit; +# endif +#endif + using ::rand; + using ::realloc; + using ::srand; + using ::strtod; + using ::strtol; + using ::strtoul; + using ::system; +#ifdef _GLIBCXX_USE_WCHAR_T + using ::wcstombs; + using ::wctomb; +#endif // _GLIBCXX_USE_WCHAR_T + +#ifndef __CORRECT_ISO_CPP_STDLIB_H_PROTO + inline ldiv_t + div(long __i, long __j) { return ldiv(__i, __j); } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#if _GLIBCXX_USE_C99_STDLIB + +#undef _Exit +#undef llabs +#undef lldiv +#undef atoll +#undef strtoll +#undef strtoull +#undef strtof +#undef strtold + +#endif // _GLIBCXX_USE_C99_STDLIB + +} // extern "C++" + +// OpenPLC: AVR libc lacks strtoll/strtoull (no 64-bit string conversion). +// Provide minimal shims so code that uses these (like STruC++ IEC STRING +// operations on LINT/ULINT) can link. Falls back to 32-bit strtol/strtoul +// which is sufficient for most PLC use cases. +#ifdef __AVR__ namespace std { - using ::malloc; using ::free; using ::abort; using ::abs; - using ::atoi; using ::atol; using ::strtol; using ::strtoul; - using ::strtod; using ::strtoll; using ::strtoull; + inline long long strtoll(const char* nptr, char** endptr, int base) { + return static_cast(::strtol(nptr, endptr, base)); + } + inline unsigned long long strtoull(const char* nptr, char** endptr, int base) { + return static_cast(::strtoul(nptr, endptr, base)); + } } #endif + +#endif // !_GLIBCXX_HOSTED + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cstring b/resources/sources/avr-libstdcpp/include/cstring index 1f3191134..02199a8e9 100644 --- a/resources/sources/avr-libstdcpp/include/cstring +++ b/resources/sources/avr-libstdcpp/include/cstring @@ -1,10 +1,126 @@ -// Minimal for AVR -#ifndef _AVR_CSTRING -#define _AVR_CSTRING +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file cstring + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c string.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.4.6 C library +// + +#pragma GCC system_header + +#include #include -namespace std { - using ::memcpy; using ::memset; using ::memmove; using ::memcmp; - using ::strlen; using ::strcmp; using ::strncmp; using ::strcpy; using ::strncpy; - using ::strstr; using ::strchr; using ::strrchr; using ::strcat; using ::strncat; -} + +#ifndef _GLIBCXX_CSTRING +#define _GLIBCXX_CSTRING 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef memchr +#undef memcmp +#undef memcpy +#undef memmove +#undef memset +#undef strcat +#undef strchr +#undef strcmp +#undef strcoll +#undef strcpy +#undef strcspn +#undef strerror +#undef strlen +#undef strncat +#undef strncmp +#undef strncpy +#undef strpbrk +#undef strrchr +#undef strspn +#undef strstr +#undef strtok +#undef strxfrm + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::memchr; + using ::memcmp; + using ::memcpy; + using ::memmove; + using ::memset; + using ::strcat; + using ::strcmp; + using ::strcoll; + using ::strcpy; + using ::strcspn; + using ::strerror; + using ::strlen; + using ::strncat; + using ::strncmp; + using ::strncpy; + using ::strspn; + using ::strtok; + using ::strxfrm; + using ::strchr; + using ::strpbrk; + using ::strrchr; + using ::strstr; + +#ifndef __CORRECT_ISO_CPP_STRING_H_PROTO + inline void* + memchr(void* __s, int __c, size_t __n) + { return __builtin_memchr(__s, __c, __n); } + + inline char* + strchr(char* __s, int __n) + { return __builtin_strchr(__s, __n); } + + inline char* + strpbrk(char* __s1, const char* __s2) + { return __builtin_strpbrk(__s1, __s2); } + + inline char* + strrchr(char* __s, int __n) + { return __builtin_strrchr(__s, __n); } + + inline char* + strstr(char* __s1, const char* __s2) + { return __builtin_strstr(__s1, __s2); } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + #endif diff --git a/resources/sources/avr-libstdcpp/include/ctgmath b/resources/sources/avr-libstdcpp/include/ctgmath new file mode 100644 index 000000000..6ee36036e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ctgmath @@ -0,0 +1,44 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ctgmath + * This is a Standard C++ Library header. + */ + +#pragma GCC system_header + +#ifndef _GLIBCXX_CTGMATH +#define _GLIBCXX_CTGMATH 1 + +#if __cplusplus < 201103L +# include +#else +# include +extern "C++" { +# include +} +#endif + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/ctime b/resources/sources/avr-libstdcpp/include/ctime new file mode 100644 index 000000000..abac94027 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ctime @@ -0,0 +1,84 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ctime + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c time.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 20.5 Date and time +// + +#pragma GCC system_header + +#include +#include + +#ifndef _GLIBCXX_CTIME +#define _GLIBCXX_CTIME 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef clock +#undef difftime +#undef mktime +#undef time +#undef asctime +#undef ctime +#undef gmtime +#undef localtime +#undef strftime + +namespace std +{ + using ::clock_t; + using ::time_t; + using ::tm; + + using ::clock; + using ::difftime; + using ::mktime; + using ::time; + using ::asctime; + using ::ctime; + using ::gmtime; + using ::localtime; + using ::strftime; +} // namespace + +#if __cplusplus >= 201703L && defined(_GLIBCXX_HAVE_TIMESPEC_GET) +#undef timespec_get +namespace std +{ + using ::timespec; + using ::timespec_get; +} // namespace std +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cuchar b/resources/sources/avr-libstdcpp/include/cuchar new file mode 100644 index 000000000..fc26715e2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cuchar @@ -0,0 +1,77 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 2015-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cuchar + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c uchar.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882:2011 21.8 +// + +#ifndef _GLIBCXX_CUCHAR +#define _GLIBCXX_CUCHAR 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +#if _GLIBCXX_USE_C11_UCHAR_CXX11 + +#include + +// Get rid of those macros defined in in lieu of real functions. +#undef mbrtoc16 +#undef c16rtomb +#undef mbrtoc32 +#undef c32rtomb + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::mbrtoc16; + using ::c16rtomb; + using ::mbrtoc32; + using ::c32rtomb; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // _GLIBCXX_USE_C11_UCHAR_CXX11 + +#endif // C++11 + +#endif // _GLIBCXX_CUCHAR diff --git a/resources/sources/avr-libstdcpp/include/cwchar b/resources/sources/avr-libstdcpp/include/cwchar new file mode 100644 index 000000000..21857fa2d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cwchar @@ -0,0 +1,306 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cwchar + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c wchar.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: 21.4 +// + +#pragma GCC system_header + +#include + +#if _GLIBCXX_HAVE_WCHAR_H +#include +#endif + +#ifndef _GLIBCXX_CWCHAR +#define _GLIBCXX_CWCHAR 1 + +// Need to do a bit of trickery here with mbstate_t as char_traits +// assumes it is in wchar.h, regardless of wchar_t specializations. +#ifndef _GLIBCXX_HAVE_MBSTATE_T +extern "C" +{ + typedef struct + { + int __fill[6]; + } mbstate_t; +} +#endif + +namespace std +{ + using ::mbstate_t; +} // namespace std + +// Get rid of those macros defined in in lieu of real functions. +#undef btowc +#undef fgetwc +#undef fgetws +#undef fputwc +#undef fputws +#undef fwide +#undef fwprintf +#undef fwscanf +#undef getwc +#undef getwchar +#undef mbrlen +#undef mbrtowc +#undef mbsinit +#undef mbsrtowcs +#undef putwc +#undef putwchar +#undef swprintf +#undef swscanf +#undef ungetwc +#undef vfwprintf +#if _GLIBCXX_HAVE_VFWSCANF +# undef vfwscanf +#endif +#undef vswprintf +#if _GLIBCXX_HAVE_VSWSCANF +# undef vswscanf +#endif +#undef vwprintf +#if _GLIBCXX_HAVE_VWSCANF +# undef vwscanf +#endif +#undef wcrtomb +#undef wcscat +#undef wcschr +#undef wcscmp +#undef wcscoll +#undef wcscpy +#undef wcscspn +#undef wcsftime +#undef wcslen +#undef wcsncat +#undef wcsncmp +#undef wcsncpy +#undef wcspbrk +#undef wcsrchr +#undef wcsrtombs +#undef wcsspn +#undef wcsstr +#undef wcstod +#if _GLIBCXX_HAVE_WCSTOF +# undef wcstof +#endif +#undef wcstok +#undef wcstol +#undef wcstoul +#undef wcsxfrm +#undef wctob +#undef wmemchr +#undef wmemcmp +#undef wmemcpy +#undef wmemmove +#undef wmemset +#undef wprintf +#undef wscanf + +#if _GLIBCXX_USE_WCHAR_T + +extern "C++" +{ +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using ::wint_t; + + using ::btowc; + using ::fgetwc; + using ::fgetws; + using ::fputwc; + using ::fputws; + using ::fwide; + using ::fwprintf; + using ::fwscanf; + using ::getwc; + using ::getwchar; + using ::mbrlen; + using ::mbrtowc; + using ::mbsinit; + using ::mbsrtowcs; + using ::putwc; + using ::putwchar; +#ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF + using ::swprintf; +#endif + using ::swscanf; + using ::ungetwc; + using ::vfwprintf; +#if _GLIBCXX_HAVE_VFWSCANF + using ::vfwscanf; +#endif +#ifndef _GLIBCXX_HAVE_BROKEN_VSWPRINTF + using ::vswprintf; +#endif +#if _GLIBCXX_HAVE_VSWSCANF + using ::vswscanf; +#endif + using ::vwprintf; +#if _GLIBCXX_HAVE_VWSCANF + using ::vwscanf; +#endif + using ::wcrtomb; + using ::wcscat; + using ::wcscmp; + using ::wcscoll; + using ::wcscpy; + using ::wcscspn; + using ::wcsftime; + using ::wcslen; + using ::wcsncat; + using ::wcsncmp; + using ::wcsncpy; + using ::wcsrtombs; + using ::wcsspn; + using ::wcstod; +#if _GLIBCXX_HAVE_WCSTOF + using ::wcstof; +#endif + using ::wcstok; + using ::wcstol; + using ::wcstoul; + using ::wcsxfrm; + using ::wctob; + using ::wmemcmp; + using ::wmemcpy; + using ::wmemmove; + using ::wmemset; + using ::wprintf; + using ::wscanf; + using ::wcschr; + using ::wcspbrk; + using ::wcsrchr; + using ::wcsstr; + using ::wmemchr; + +#ifndef __CORRECT_ISO_CPP_WCHAR_H_PROTO + inline wchar_t* + wcschr(wchar_t* __p, wchar_t __c) + { return wcschr(const_cast(__p), __c); } + + inline wchar_t* + wcspbrk(wchar_t* __s1, const wchar_t* __s2) + { return wcspbrk(const_cast(__s1), __s2); } + + inline wchar_t* + wcsrchr(wchar_t* __p, wchar_t __c) + { return wcsrchr(const_cast(__p), __c); } + + inline wchar_t* + wcsstr(wchar_t* __s1, const wchar_t* __s2) + { return wcsstr(const_cast(__s1), __s2); } + + inline wchar_t* + wmemchr(wchar_t* __p, wchar_t __c, size_t __n) + { return wmemchr(const_cast(__p), __c, __n); } +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#if _GLIBCXX_USE_C99_WCHAR + +#undef wcstold +#undef wcstoll +#undef wcstoull + +namespace __gnu_cxx +{ +#if _GLIBCXX_USE_C99_CHECK || _GLIBCXX_USE_C99_DYNAMIC + extern "C" long double + (wcstold)(const wchar_t * __restrict, wchar_t ** __restrict) throw (); +#endif +#if !_GLIBCXX_USE_C99_DYNAMIC + using ::wcstold; +#endif +#if _GLIBCXX_USE_C99_LONG_LONG_CHECK || _GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + extern "C" long long int + (wcstoll)(const wchar_t * __restrict, wchar_t ** __restrict, int) throw (); + extern "C" unsigned long long int + (wcstoull)(const wchar_t * __restrict, wchar_t ** __restrict, int) throw (); +#endif +#if !_GLIBCXX_USE_C99_LONG_LONG_DYNAMIC + using ::wcstoll; + using ::wcstoull; +#endif +} // namespace __gnu_cxx + +namespace std +{ + using ::__gnu_cxx::wcstold; + using ::__gnu_cxx::wcstoll; + using ::__gnu_cxx::wcstoull; +} // namespace + +#endif + +#endif //_GLIBCXX_USE_WCHAR_T + +#if __cplusplus >= 201103L + +#ifdef _GLIBCXX_USE_WCHAR_T + +namespace std +{ +#if _GLIBCXX_HAVE_WCSTOF + using std::wcstof; +#endif +#if _GLIBCXX_HAVE_VFWSCANF + using std::vfwscanf; +#endif +#if _GLIBCXX_HAVE_VSWSCANF + using std::vswscanf; +#endif +#if _GLIBCXX_HAVE_VWSCANF + using std::vwscanf; +#endif + +#if _GLIBCXX_USE_C99_WCHAR + using std::wcstold; + using std::wcstoll; + using std::wcstoull; +#endif +} // namespace + +#endif // _GLIBCXX_USE_WCHAR_T + +#endif // C++11 + +#endif diff --git a/resources/sources/avr-libstdcpp/include/cwctype b/resources/sources/avr-libstdcpp/include/cwctype new file mode 100644 index 000000000..5190ce81a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/cwctype @@ -0,0 +1,110 @@ +// -*- C++ -*- forwarding header. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/cwctype + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + * + * This is the C++ version of the Standard C Library header @c wctype.h, + * and its contents are (mostly) the same as that header, but are all + * contained in the namespace @c std (except for names which are defined + * as macros in C). + */ + +// +// ISO C++ 14882: +// + +#pragma GCC system_header + +#include + +#if _GLIBCXX_HAVE_WCTYPE_H + +#if __GLIBC__ == 2 && __GLIBC_MINOR__ < 10 +// Work around glibc BZ 9694 +#include +#endif + +#include +#endif // _GLIBCXX_HAVE_WCTYPE_H + +#ifndef _GLIBCXX_CWCTYPE +#define _GLIBCXX_CWCTYPE 1 + +// Get rid of those macros defined in in lieu of real functions. +#undef iswalnum +#undef iswalpha +#if _GLIBCXX_HAVE_ISWBLANK +# undef iswblank +#endif +#undef iswcntrl +#undef iswctype +#undef iswdigit +#undef iswgraph +#undef iswlower +#undef iswprint +#undef iswpunct +#undef iswspace +#undef iswupper +#undef iswxdigit +#undef towctrans +#undef towlower +#undef towupper +#undef wctrans +#undef wctype + +#if _GLIBCXX_USE_WCHAR_T + +namespace std +{ + using ::wctrans_t; + using ::wctype_t; + using ::wint_t; + + using ::iswalnum; + using ::iswalpha; +#if _GLIBCXX_HAVE_ISWBLANK + using ::iswblank; +#endif + using ::iswcntrl; + using ::iswctype; + using ::iswdigit; + using ::iswgraph; + using ::iswlower; + using ::iswprint; + using ::iswpunct; + using ::iswspace; + using ::iswupper; + using ::iswxdigit; + using ::towctrans; + using ::towlower; + using ::towupper; + using ::wctrans; + using ::wctype; +} // namespace + +#endif //_GLIBCXX_USE_WCHAR_T + +#endif // _GLIBCXX_CWCTYPE diff --git a/resources/sources/avr-libstdcpp/include/debug/assertions.h b/resources/sources/avr-libstdcpp/include/debug/assertions.h new file mode 100644 index 000000000..fb52e4414 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/assertions.h @@ -0,0 +1,68 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/assertions.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_ASSERTIONS_H +#define _GLIBCXX_DEBUG_ASSERTIONS_H 1 + +#ifndef _GLIBCXX_DEBUG + +# define _GLIBCXX_DEBUG_ASSERT(_Condition) +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) +# define _GLIBCXX_DEBUG_ONLY(_Statement) + +#endif + +#ifndef _GLIBCXX_ASSERTIONS +# define __glibcxx_requires_non_empty_range(_First,_Last) +# define __glibcxx_requires_nonempty() +# define __glibcxx_requires_subscript(_N) +#else + +// Verify that [_First, _Last) forms a non-empty iterator range. +# define __glibcxx_requires_non_empty_range(_First,_Last) \ + __glibcxx_assert(__builtin_expect(_First != _Last, true)) +# define __glibcxx_requires_subscript(_N) \ + __glibcxx_assert(__builtin_expect(_N < this->size(), true)) +// Verify that the container is nonempty +# define __glibcxx_requires_nonempty() \ + __glibcxx_assert(__builtin_expect(!this->empty(), true)) +#endif + +#ifdef _GLIBCXX_DEBUG +# define _GLIBCXX_DEBUG_ASSERT(_Condition) __glibcxx_assert(_Condition) + +# ifdef _GLIBCXX_DEBUG_PEDANTIC +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) _GLIBCXX_DEBUG_ASSERT(_Condition) +# else +# define _GLIBCXX_DEBUG_PEDASSERT(_Condition) +# endif + +# define _GLIBCXX_DEBUG_ONLY(_Statement) _Statement +#endif + +#endif // _GLIBCXX_DEBUG_ASSERTIONS diff --git a/resources/sources/avr-libstdcpp/include/debug/debug.h b/resources/sources/avr-libstdcpp/include/debug/debug.h new file mode 100644 index 000000000..5c858e1a8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/debug.h @@ -0,0 +1,137 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/debug.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MACRO_SWITCH_H +#define _GLIBCXX_DEBUG_MACRO_SWITCH_H 1 + +/** Macros and namespaces used by the implementation outside of debug + * wrappers to verify certain properties. The __glibcxx_requires_xxx + * macros are merely wrappers around the __glibcxx_check_xxx wrappers + * when we are compiling with debug mode, but disappear when we are + * in release mode so that there is no checking performed in, e.g., + * the standard library algorithms. +*/ + +#include + +// Debug mode namespaces. + +/** + * @namespace std::__debug + * @brief GNU debug code, replaces standard behavior with debug behavior. + */ +namespace std +{ + namespace __debug { } +} + +/** @namespace __gnu_debug + * @brief GNU debug classes for public use. +*/ +namespace __gnu_debug +{ + using namespace std::__debug; + + template + struct _Safe_iterator; +} + +#ifndef _GLIBCXX_DEBUG + +# define __glibcxx_requires_cond(_Cond,_Msg) +# define __glibcxx_requires_valid_range(_First,_Last) +# define __glibcxx_requires_can_increment(_First,_Size) +# define __glibcxx_requires_can_increment_range(_First1,_Last1,_First2) +# define __glibcxx_requires_can_decrement_range(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted(_First,_Last) +# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) +# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) +# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_heap(_First,_Last) +# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) +# define __glibcxx_requires_string(_String) +# define __glibcxx_requires_string_len(_String,_Len) +# define __glibcxx_requires_irreflexive(_First,_Last) +# define __glibcxx_requires_irreflexive2(_First,_Last) +# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) +# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) + +#else + +# include + +# define __glibcxx_requires_cond(_Cond,_Msg) _GLIBCXX_DEBUG_VERIFY(_Cond,_Msg) +# define __glibcxx_requires_valid_range(_First,_Last) \ + __glibcxx_check_valid_range(_First,_Last) +# define __glibcxx_requires_can_increment(_First,_Size) \ + __glibcxx_check_can_increment(_First,_Size) +# define __glibcxx_requires_can_increment_range(_First1,_Last1,_First2) \ + __glibcxx_check_can_increment_range(_First1,_Last1,_First2) +# define __glibcxx_requires_can_decrement_range(_First1,_Last1,_First2) \ + __glibcxx_check_can_decrement_range(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted(_First,_Last) \ + __glibcxx_check_sorted(_First,_Last) +# define __glibcxx_requires_sorted_pred(_First,_Last,_Pred) \ + __glibcxx_check_sorted_pred(_First,_Last,_Pred) +# define __glibcxx_requires_sorted_set(_First1,_Last1,_First2) \ + __glibcxx_check_sorted_set(_First1,_Last1,_First2) +# define __glibcxx_requires_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ + __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) +# define __glibcxx_requires_partitioned_lower(_First,_Last,_Value) \ + __glibcxx_check_partitioned_lower(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_upper(_First,_Last,_Value) \ + __glibcxx_check_partitioned_upper(_First,_Last,_Value) +# define __glibcxx_requires_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ + __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ + __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) +# define __glibcxx_requires_heap(_First,_Last) \ + __glibcxx_check_heap(_First,_Last) +# define __glibcxx_requires_heap_pred(_First,_Last,_Pred) \ + __glibcxx_check_heap_pred(_First,_Last,_Pred) +# define __glibcxx_requires_string(_String) __glibcxx_check_string(_String) +# define __glibcxx_requires_string_len(_String,_Len) \ + __glibcxx_check_string_len(_String,_Len) +# define __glibcxx_requires_irreflexive(_First,_Last) \ + __glibcxx_check_irreflexive(_First,_Last) +# define __glibcxx_requires_irreflexive2(_First,_Last) \ + __glibcxx_check_irreflexive2(_First,_Last) +# define __glibcxx_requires_irreflexive_pred(_First,_Last,_Pred) \ + __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) +# define __glibcxx_requires_irreflexive_pred2(_First,_Last,_Pred) \ + __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) + +# include + +#endif + +#endif // _GLIBCXX_DEBUG_MACRO_SWITCH_H diff --git a/resources/sources/avr-libstdcpp/include/debug/formatter.h b/resources/sources/avr-libstdcpp/include/debug/formatter.h new file mode 100644 index 000000000..bb9b3e565 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/formatter.h @@ -0,0 +1,593 @@ +// Debug-mode error formatting implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/formatter.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_FORMATTER_H +#define _GLIBCXX_DEBUG_FORMATTER_H 1 + +#include + +#if __cpp_rtti +# include +# define _GLIBCXX_TYPEID(_Type) &typeid(_Type) +#else +namespace std +{ + class type_info; +} +# define _GLIBCXX_TYPEID(_Type) 0 +#endif + +#if __cplusplus >= 201103L +namespace __gnu_cxx +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +template + class __normal_iterator; + +_GLIBCXX_END_NAMESPACE_VERSION +} + +namespace std +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +template + class reverse_iterator; + +template + class move_iterator; + +_GLIBCXX_END_NAMESPACE_VERSION +} +#endif + +namespace __gnu_debug +{ + using std::type_info; + + template + bool __check_singular(const _Iterator&); + + class _Safe_sequence_base; + + template + class _Safe_iterator; + + template + class _Safe_local_iterator; + + template + class _Safe_sequence; + + enum _Debug_msg_id + { + // General checks + __msg_valid_range, + __msg_insert_singular, + __msg_insert_different, + __msg_erase_bad, + __msg_erase_different, + __msg_subscript_oob, + __msg_empty, + __msg_unpartitioned, + __msg_unpartitioned_pred, + __msg_unsorted, + __msg_unsorted_pred, + __msg_not_heap, + __msg_not_heap_pred, + // std::bitset checks + __msg_bad_bitset_write, + __msg_bad_bitset_read, + __msg_bad_bitset_flip, + // std::list checks + __msg_self_splice, + __msg_splice_alloc, + __msg_splice_bad, + __msg_splice_other, + __msg_splice_overlap, + // iterator checks + __msg_init_singular, + __msg_init_copy_singular, + __msg_init_const_singular, + __msg_copy_singular, + __msg_bad_deref, + __msg_bad_inc, + __msg_bad_dec, + __msg_iter_subscript_oob, + __msg_advance_oob, + __msg_retreat_oob, + __msg_iter_compare_bad, + __msg_compare_different, + __msg_iter_order_bad, + __msg_order_different, + __msg_distance_bad, + __msg_distance_different, + // istream_iterator + __msg_deref_istream, + __msg_inc_istream, + // ostream_iterator + __msg_output_ostream, + // istreambuf_iterator + __msg_deref_istreambuf, + __msg_inc_istreambuf, + // forward_list + __msg_insert_after_end, + __msg_erase_after_bad, + __msg_valid_range2, + // unordered container local iterators + __msg_local_iter_compare_bad, + __msg_non_empty_range, + // self move assign + __msg_self_move_assign, + // unordered container buckets + __msg_bucket_index_oob, + __msg_valid_load_factor, + // others + __msg_equal_allocs, + __msg_insert_range_from_self, + __msg_irreflexive_ordering + }; + + class _Error_formatter + { + // Tags denoting the type of parameter for construction + struct _Is_iterator { }; + struct _Is_iterator_value_type { }; + struct _Is_sequence { }; + struct _Is_instance { }; + + public: + /// Whether an iterator is constant, mutable, or unknown + enum _Constness + { + __unknown_constness, + __const_iterator, + __mutable_iterator, + __last_constness + }; + + // The state of the iterator (fine-grained), if we know it. + enum _Iterator_state + { + __unknown_state, + __singular, // singular, may still be attached to a sequence + __begin, // dereferenceable, and at the beginning + __middle, // dereferenceable, not at the beginning + __end, // past-the-end, may be at beginning if sequence empty + __before_begin, // before begin + __rbegin, // dereferenceable, and at the reverse-beginning + __rmiddle, // reverse-dereferenceable, not at the reverse-beginning + __rend, // reverse-past-the-end + __last_state + }; + + // A parameter that may be referenced by an error message + struct _Parameter + { + enum + { + __unused_param, + __iterator, + __sequence, + __integer, + __string, + __instance, + __iterator_value_type + } _M_kind; + + struct _Type + { + const char* _M_name; + const type_info* _M_type; + }; + + struct _Instance : _Type + { + const void* _M_address; + }; + + union + { + // When _M_kind == __iterator + struct : _Instance + { + _Constness _M_constness; + _Iterator_state _M_state; + const void* _M_sequence; + const type_info* _M_seq_type; + } _M_iterator; + + // When _M_kind == __sequence + _Instance _M_sequence; + + // When _M_kind == __integer + struct + { + const char* _M_name; + long _M_value; + } _M_integer; + + // When _M_kind == __string + struct + { + const char* _M_name; + const char* _M_value; + } _M_string; + + // When _M_kind == __instance + _Instance _M_instance; + + // When _M_kind == __iterator_value_type + _Type _M_iterator_value_type; + } _M_variant; + + _Parameter() : _M_kind(__unused_param), _M_variant() { } + + _Parameter(long __value, const char* __name) + : _M_kind(__integer), _M_variant() + { + _M_variant._M_integer._M_name = __name; + _M_variant._M_integer._M_value = __value; + } + + _Parameter(const char* __value, const char* __name) + : _M_kind(__string), _M_variant() + { + _M_variant._M_string._M_name = __name; + _M_variant._M_string._M_value = __value; + } + + template + _Parameter(_Safe_iterator<_Iterator, _Sequence, _Category> const& __it, + const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); + _M_variant._M_iterator._M_constness = + __it._S_constant() ? __const_iterator : __mutable_iterator; + _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); + _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); + + if (__it._M_singular()) + _M_variant._M_iterator._M_state = __singular; + else + { + if (__it._M_is_before_begin()) + _M_variant._M_iterator._M_state = __before_begin; + else if (__it._M_is_end()) + _M_variant._M_iterator._M_state = __end; + else if (__it._M_is_begin()) + _M_variant._M_iterator._M_state = __begin; + else + _M_variant._M_iterator._M_state = __middle; + } + } + + template + _Parameter(_Safe_local_iterator<_Iterator, _Sequence> const& __it, + const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(_Iterator); + _M_variant._M_iterator._M_constness = + __it._S_constant() ? __const_iterator : __mutable_iterator; + _M_variant._M_iterator._M_sequence = __it._M_get_sequence(); + _M_variant._M_iterator._M_seq_type = _GLIBCXX_TYPEID(_Sequence); + + if (__it._M_singular()) + _M_variant._M_iterator._M_state = __singular; + else + { + if (__it._M_is_end()) + _M_variant._M_iterator._M_state = __end; + else if (__it._M_is_begin()) + _M_variant._M_iterator._M_state = __begin; + else + _M_variant._M_iterator._M_state = __middle; + } + } + + template + _Parameter(const _Type* const& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); + _M_variant._M_iterator._M_constness = __const_iterator; + _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + + template + _Parameter(_Type* const& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); + _M_variant._M_iterator._M_constness = __mutable_iterator; + _M_variant._M_iterator._M_state = __it ? __unknown_state : __singular; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + + template + _Parameter(_Iterator const& __it, const char* __name, _Is_iterator) + : _M_kind(__iterator), _M_variant() + { + _M_variant._M_iterator._M_name = __name; + _M_variant._M_iterator._M_address = std::__addressof(__it); + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); + _M_variant._M_iterator._M_constness = __unknown_constness; + _M_variant._M_iterator._M_state = + __gnu_debug::__check_singular(__it) ? __singular : __unknown_state; + _M_variant._M_iterator._M_sequence = 0; + _M_variant._M_iterator._M_seq_type = 0; + } + +#if __cplusplus >= 201103L + // The following constructors are only defined in C++11 to take + // advantage of the constructor delegation feature. + template + _Parameter( + __gnu_cxx::__normal_iterator<_Iterator, _Container> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } + + template + _Parameter(std::reverse_iterator<_Iterator> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { + _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); + _M_variant._M_iterator._M_state + = _S_reverse_state(_M_variant._M_iterator._M_state); + } + + template + _Parameter(std::reverse_iterator<_Safe_iterator<_Iterator, _Sequence, + _Category>> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { + _M_variant._M_iterator._M_type + = _GLIBCXX_TYPEID(std::reverse_iterator<_Iterator>); + _M_variant._M_iterator._M_state + = _S_reverse_state(_M_variant._M_iterator._M_state); + } + + template + _Parameter(std::move_iterator<_Iterator> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { _M_variant._M_iterator._M_type = _GLIBCXX_TYPEID(__it); } + + template + _Parameter(std::move_iterator<_Safe_iterator<_Iterator, _Sequence, + _Category>> const& __it, + const char* __name, _Is_iterator) + : _Parameter(__it.base(), __name, _Is_iterator{}) + { + _M_variant._M_iterator._M_type + = _GLIBCXX_TYPEID(std::move_iterator<_Iterator>); + } + + private: + _Iterator_state + _S_reverse_state(_Iterator_state __state) + { + switch (__state) + { + case __begin: + return __rend; + case __middle: + return __rmiddle; + case __end: + return __rbegin; + default: + return __state; + } + } + + public: +#endif + + template + _Parameter(const _Safe_sequence<_Sequence>& __seq, + const char* __name, _Is_sequence) + : _M_kind(__sequence), _M_variant() + { + _M_variant._M_sequence._M_name = __name; + _M_variant._M_sequence._M_address = + static_cast(std::__addressof(__seq)); + _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); + } + + template + _Parameter(const _Sequence& __seq, const char* __name, _Is_sequence) + : _M_kind(__sequence), _M_variant() + { + _M_variant._M_sequence._M_name = __name; + _M_variant._M_sequence._M_address = std::__addressof(__seq); + _M_variant._M_sequence._M_type = _GLIBCXX_TYPEID(_Sequence); + } + + template + _Parameter(const _Iterator& __it, const char* __name, + _Is_iterator_value_type) + : _M_kind(__iterator_value_type), _M_variant() + { + _M_variant._M_iterator_value_type._M_name = __name; + _M_variant._M_iterator_value_type._M_type = + _GLIBCXX_TYPEID(typename std::iterator_traits<_Iterator>::value_type); + } + + template + _Parameter(const _Type& __inst, const char* __name, _Is_instance) + : _M_kind(__instance), _M_variant() + { + _M_variant._M_instance._M_name = __name; + _M_variant._M_instance._M_address = &__inst; + _M_variant._M_instance._M_type = _GLIBCXX_TYPEID(_Type); + } + +#if !_GLIBCXX_INLINE_VERSION + void + _M_print_field(const _Error_formatter* __formatter, + const char* __name) const _GLIBCXX_DEPRECATED; + + void + _M_print_description(const _Error_formatter* __formatter) + const _GLIBCXX_DEPRECATED; +#endif + }; + + template + _Error_formatter& + _M_iterator(const _Iterator& __it, const char* __name = 0) + { + if (_M_num_parameters < std::size_t(__max_parameters)) + _M_parameters[_M_num_parameters++] = _Parameter(__it, __name, + _Is_iterator()); + return *this; + } + + template + _Error_formatter& + _M_iterator_value_type(const _Iterator& __it, + const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = + _Parameter(__it, __name, _Is_iterator_value_type()); + return *this; + } + + _Error_formatter& + _M_integer(long __value, const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); + return *this; + } + + _Error_formatter& + _M_string(const char* __value, const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = _Parameter(__value, __name); + return *this; + } + + template + _Error_formatter& + _M_sequence(const _Sequence& __seq, const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = _Parameter(__seq, __name, + _Is_sequence()); + return *this; + } + + template + _Error_formatter& + _M_instance(const _Type& __inst, const char* __name = 0) + { + if (_M_num_parameters < __max_parameters) + _M_parameters[_M_num_parameters++] = _Parameter(__inst, __name, + _Is_instance()); + return *this; + } + + _Error_formatter& + _M_message(const char* __text) + { _M_text = __text; return *this; } + + // Kept const qualifier for backward compatibility, to keep the same + // exported symbol. + _Error_formatter& + _M_message(_Debug_msg_id __id) const throw (); + + _GLIBCXX_NORETURN void + _M_error() const; + +#if !_GLIBCXX_INLINE_VERSION + template + void + _M_format_word(char*, int, const char*, _Tp) + const throw () _GLIBCXX_DEPRECATED; + + void + _M_print_word(const char* __word) const _GLIBCXX_DEPRECATED; + + void + _M_print_string(const char* __string) const _GLIBCXX_DEPRECATED; +#endif + + private: + _Error_formatter(const char* __file, unsigned int __line, + const char* __function) + : _M_file(__file), _M_line(__line), _M_num_parameters(0), _M_text(0) + , _M_function(__function) + { } + +#if !_GLIBCXX_INLINE_VERSION + void + _M_get_max_length() const throw () _GLIBCXX_DEPRECATED; +#endif + + enum { __max_parameters = 9 }; + + const char* _M_file; + unsigned int _M_line; + _Parameter _M_parameters[__max_parameters]; + unsigned int _M_num_parameters; + const char* _M_text; + const char* _M_function; + + public: + static _Error_formatter& + _S_at(const char* __file, unsigned int __line, const char* __function) + { + static _Error_formatter __formatter(__file, __line, __function); + return __formatter; + } + }; +} // namespace __gnu_debug + +#undef _GLIBCXX_TYPEID + +#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/functions.h b/resources/sources/avr-libstdcpp/include/debug/functions.h new file mode 100644 index 000000000..aaccc8dfe --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/functions.h @@ -0,0 +1,470 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/functions.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_FUNCTIONS_H +#define _GLIBCXX_DEBUG_FUNCTIONS_H 1 + +#include // for less + +#if __cplusplus >= 201103L +# include // for __miter_base +# include // for is_lvalue_reference and conditional. +#endif + +#include +#include + +namespace __gnu_debug +{ + template + struct _Insert_range_from_self_is_safe + { enum { __value = 0 }; }; + + template + struct _Is_contiguous_sequence : std::__false_type { }; + + /* Checks that [first, last) is a valid range, and then returns + * __first. This routine is useful when we can't use a separate + * assertion statement because, e.g., we are in a constructor. + */ + template + inline _InputIterator + __check_valid_range(const _InputIterator& __first, + const _InputIterator& __last, + const char* __file, + unsigned int __line, + const char* __function) + { + __glibcxx_check_valid_range_at(__first, __last, + __file, __line, __function); + return __first; + } + + /* Handle the case where __other is a pointer to _Sequence::value_type. */ + template + inline bool + __foreign_iterator_aux4( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + const typename _Sequence::value_type* __other) + { + typedef const typename _Sequence::value_type* _PointerType; + typedef std::less<_PointerType> _Less; +#if __cplusplus >= 201103L + constexpr _Less __l{}; +#else + const _Less __l = _Less(); +#endif + const _Sequence* __seq = __it._M_get_sequence(); + const _PointerType __begin = std::__addressof(*__seq->_M_base().begin()); + const _PointerType __end = std::__addressof(*(__seq->_M_base().end()-1)); + + // Check whether __other points within the contiguous storage. + return __l(__other, __begin) || __l(__end, __other); + } + + /* Fallback overload for when we can't tell, assume it is valid. */ + template + inline bool + __foreign_iterator_aux4( + const _Safe_iterator<_Iterator, _Sequence, _Category>&, ...) + { return true; } + + /* Handle sequences with contiguous storage */ + template + inline bool + __foreign_iterator_aux3( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + const _InputIterator& __other, const _InputIterator& __other_end, + std::__true_type) + { + if (__other == __other_end) + return true; // inserting nothing is safe even if not foreign iters + if (__it._M_get_sequence()->empty()) + return true; // can't be self-inserting if self is empty + return __foreign_iterator_aux4(__it, std::__addressof(*__other)); + } + + /* Handle non-contiguous containers, assume it is valid. */ + template + inline bool + __foreign_iterator_aux3( + const _Safe_iterator<_Iterator, _Sequence, _Category>&, + const _InputIterator&, const _InputIterator&, + std::__false_type) + { return true; } + + /** Handle debug iterators from the same type of container. */ + template + inline bool + __foreign_iterator_aux2( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + const _Safe_iterator<_OtherIterator, _Sequence, _Category>& __other, + const _Safe_iterator<_OtherIterator, _Sequence, _Category>&) + { return __it._M_get_sequence() != __other._M_get_sequence(); } + + /** Handle debug iterators from different types of container. */ + template + inline bool + __foreign_iterator_aux2( + const _Safe_iterator<_Iterator, _Sequence, _Category>&, + const _Safe_iterator<_OtherIterator, _OtherSequence, + _OtherCategory>&, + const _Safe_iterator<_OtherIterator, _OtherSequence, + _OtherCategory>&) + { return true; } + + /* Handle non-debug iterators. */ + template + inline bool + __foreign_iterator_aux2( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + const _InputIterator& __other, + const _InputIterator& __other_end) + { +#if __cplusplus < 201103L + typedef _Is_contiguous_sequence<_Sequence> __tag; +#else + using __lvalref = std::is_lvalue_reference< + typename std::iterator_traits<_InputIterator>::reference>; + using __contiguous = _Is_contiguous_sequence<_Sequence>; + using __tag = typename std::conditional<__lvalref::value, __contiguous, + std::__false_type>::type; +#endif + return __foreign_iterator_aux3(__it, __other, __other_end, __tag()); + } + + /* Handle the case where we aren't really inserting a range after all */ + template + inline bool + __foreign_iterator_aux( + const _Safe_iterator<_Iterator, _Sequence, _Category>&, + _Integral, _Integral, std::__true_type) + { return true; } + + /* Handle all iterators. */ + template + inline bool + __foreign_iterator_aux( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + _InputIterator __other, _InputIterator __other_end, + std::__false_type) + { + return _Insert_range_from_self_is_safe<_Sequence>::__value + || __foreign_iterator_aux2(__it, std::__miter_base(__other), + std::__miter_base(__other_end)); + } + + template + inline bool + __foreign_iterator( + const _Safe_iterator<_Iterator, _Sequence, _Category>& __it, + _InputIterator __other, _InputIterator __other_end) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + return __foreign_iterator_aux(__it, __other, __other_end, _Integral()); + } + + // Can't check if an input iterator sequence is sorted, because we + // can't step through the sequence. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_aux(const _InputIterator&, const _InputIterator&, + std::input_iterator_tag) + { return true; } + + // Can verify if a forward iterator sequence is in fact sorted using + // std::__is_sorted + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, + std::forward_iterator_tag) + { + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (*__next < *__first) + return false; + + return true; + } + + // Can't check if an input iterator sequence is sorted, because we can't step + // through the sequence. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_aux(const _InputIterator&, const _InputIterator&, + _Predicate, std::input_iterator_tag) + { return true; } + + // Can verify if a forward iterator sequence is in fact sorted using + // std::__is_sorted + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_aux(_ForwardIterator __first, _ForwardIterator __last, + _Predicate __pred, std::forward_iterator_tag) + { + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, (void)++__next) + if (__pred(*__next, *__first)) + return false; + + return true; + } + + // Determine if a sequence is sorted. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted(const _InputIterator& __first, const _InputIterator& __last) + { + return __check_sorted_aux(__first, __last, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted(const _InputIterator& __first, const _InputIterator& __last, + _Predicate __pred) + { + return __check_sorted_aux(__first, __last, __pred, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set_aux(const _InputIterator& __first, + const _InputIterator& __last, + std::__true_type) + { return __check_sorted(__first, __last); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set_aux(const _InputIterator&, + const _InputIterator&, + std::__false_type) + { return true; } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set_aux(const _InputIterator& __first, + const _InputIterator& __last, + _Predicate __pred, std::__true_type) + { return __check_sorted(__first, __last, __pred); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set_aux(const _InputIterator&, + const _InputIterator&, _Predicate, + std::__false_type) + { return true; } + + // ... special variant used in std::merge, std::includes, std::set_*. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set(const _InputIterator1& __first, + const _InputIterator1& __last, + const _InputIterator2&) + { + typedef typename std::iterator_traits<_InputIterator1>::value_type + _ValueType1; + typedef typename std::iterator_traits<_InputIterator2>::value_type + _ValueType2; + + typedef typename std::__are_same<_ValueType1, _ValueType2>::__type + _SameType; + return __check_sorted_set_aux(__first, __last, _SameType()); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_sorted_set(const _InputIterator1& __first, + const _InputIterator1& __last, + const _InputIterator2&, _Predicate __pred) + { + typedef typename std::iterator_traits<_InputIterator1>::value_type + _ValueType1; + typedef typename std::iterator_traits<_InputIterator2>::value_type + _ValueType2; + + typedef typename std::__are_same<_ValueType1, _ValueType2>::__type + _SameType; + return __check_sorted_set_aux(__first, __last, __pred, _SameType()); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 270. Binary search requirements overly strict + // Determine if a sequence is partitioned w.r.t. this element. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_partitioned_lower(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value) + { + while (__first != __last && *__first < __value) + ++__first; + if (__first != __last) + { + ++__first; + while (__first != __last && !(*__first < __value)) + ++__first; + } + return __first == __last; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_partitioned_upper(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value) + { + while (__first != __last && !(__value < *__first)) + ++__first; + if (__first != __last) + { + ++__first; + while (__first != __last && __value < *__first) + ++__first; + } + return __first == __last; + } + + // Determine if a sequence is partitioned w.r.t. this element. + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_partitioned_lower(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value, + _Pred __pred) + { + while (__first != __last && bool(__pred(*__first, __value))) + ++__first; + if (__first != __last) + { + ++__first; + while (__first != __last && !bool(__pred(*__first, __value))) + ++__first; + } + return __first == __last; + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __check_partitioned_upper(_ForwardIterator __first, + _ForwardIterator __last, const _Tp& __value, + _Pred __pred) + { + while (__first != __last && !bool(__pred(__value, *__first))) + ++__first; + if (__first != __last) + { + ++__first; + while (__first != __last && bool(__pred(__value, *__first))) + ++__first; + } + return __first == __last; + } + +#if __cplusplus >= 201103L + struct _Irreflexive_checker + { + template + static typename std::iterator_traits<_It>::reference + __deref(); + + template() < __deref<_It>())> + _GLIBCXX20_CONSTEXPR + static bool + _S_is_valid(_It __it) + { return !(*__it < *__it); } + + // Fallback method if operator doesn't exist. + template + _GLIBCXX20_CONSTEXPR + static bool + _S_is_valid(_Args...) + { return true; } + + template()(__deref<_It>(), __deref<_It>()))> + _GLIBCXX20_CONSTEXPR + static bool + _S_is_valid_pred(_It __it, _Pred __pred) + { return !__pred(*__it, *__it); } + + // Fallback method if predicate can't be invoked. + template + _GLIBCXX20_CONSTEXPR + static bool + _S_is_valid_pred(_Args...) + { return true; } + }; + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_irreflexive(_Iterator __it) + { return _Irreflexive_checker::_S_is_valid(__it); } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __is_irreflexive_pred(_Iterator __it, _Pred __pred) + { return _Irreflexive_checker::_S_is_valid_pred(__it, __pred); } +#endif + +} // namespace __gnu_debug + +#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/helper_functions.h b/resources/sources/avr-libstdcpp/include/debug/helper_functions.h new file mode 100644 index 000000000..62d530925 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/helper_functions.h @@ -0,0 +1,315 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/helper_functions.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H +#define _GLIBCXX_DEBUG_HELPER_FUNCTIONS_H 1 + +#include // for __addressof +#include // for iterator_traits, + // categories and _Iter_base +#include // for __is_integer + +#include // for pair + +namespace __gnu_debug +{ + template + class _Safe_iterator; + +#if __cplusplus >= 201103L + template + class _Safe_local_iterator; +#endif + + /** The precision to which we can calculate the distance between + * two iterators. + */ + enum _Distance_precision + { + __dp_none, // Not even an iterator type + __dp_equality, //< Can compare iterator equality, only + __dp_sign, //< Can determine equality and ordering + __dp_sign_max_size, //< __dp_sign and gives max range size + __dp_exact //< Can determine distance precisely + }; + + template::__type> + struct _Distance_traits + { + private: + typedef + typename std::iterator_traits<_Iterator>::difference_type _ItDiffType; + + template::__type> + struct _DiffTraits + { typedef _DiffType __type; }; + + template + struct _DiffTraits<_DiffType, std::__true_type> + { typedef std::ptrdiff_t __type; }; + + typedef typename _DiffTraits<_ItDiffType>::__type _DiffType; + + public: + typedef std::pair<_DiffType, _Distance_precision> __type; + }; + + template + struct _Distance_traits<_Integral, std::__true_type> + { typedef std::pair __type; }; + + /** Determine the distance between two iterators with some known + * precision. + */ + template + _GLIBCXX_CONSTEXPR + inline typename _Distance_traits<_Iterator>::__type + __get_distance(_Iterator __lhs, _Iterator __rhs, + std::random_access_iterator_tag) + { return std::make_pair(__rhs - __lhs, __dp_exact); } + + template + _GLIBCXX14_CONSTEXPR + inline typename _Distance_traits<_Iterator>::__type + __get_distance(_Iterator __lhs, _Iterator __rhs, + std::input_iterator_tag) + { + if (__lhs == __rhs) + return std::make_pair(0, __dp_exact); + + return std::make_pair(1, __dp_equality); + } + + template + _GLIBCXX_CONSTEXPR + inline typename _Distance_traits<_Iterator>::__type + __get_distance(_Iterator __lhs, _Iterator __rhs) + { return __get_distance(__lhs, __rhs, std::__iterator_category(__lhs)); } + + // An arbitrary iterator pointer is not singular. + inline bool + __check_singular_aux(const void*) { return false; } + + // We may have an iterator that derives from _Safe_iterator_base but isn't + // a _Safe_iterator. + template + inline bool + __check_singular(_Iterator const& __x) + { return __check_singular_aux(std::__addressof(__x)); } + + /** Non-NULL pointers are nonsingular. */ + template + inline bool + __check_singular(_Tp* const& __ptr) + { return __ptr == 0; } + + /** We say that integral types for a valid range, and defer to other + * routines to realize what to do with integral types instead of + * iterators. + */ + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_Integral, _Integral, std::__true_type) + { return true; } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __valid_range_aux(_Integral, _Integral, + typename _Distance_traits<_Integral>::__type& __dist, + std::__true_type) + { + __dist = std::make_pair(0, __dp_none); + return true; + } + + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::input_iterator_tag) + { + return __first == __last + || (!__check_singular(__first) && !__check_singular(__last)); + } + + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::random_access_iterator_tag) + { + return + __valid_range_aux(__first, __last, std::input_iterator_tag()) + && __first <= __last; + } + + /** We have iterators, so figure out what kind of iterators they are + * to see if we can check the range ahead of time. + */ + template + _GLIBCXX_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + std::__false_type) + { + return __valid_range_aux(__first, __last, + std::__iterator_category(__first)); + } + + template + _GLIBCXX20_CONSTEXPR + inline bool + __valid_range_aux(_InputIterator __first, _InputIterator __last, + typename _Distance_traits<_InputIterator>::__type& __dist, + std::__false_type) + { + if (!__valid_range_aux(__first, __last, std::input_iterator_tag())) + return false; + + __dist = __get_distance(__first, __last); + switch (__dist.second) + { + case __dp_none: + break; + case __dp_equality: + if (__dist.first == 0) + return true; + break; + case __dp_sign: + case __dp_sign_max_size: + case __dp_exact: + return __dist.first >= 0; + } + + // Can't tell so assume it is fine. + return true; + } + + /** Don't know what these iterators are, or if they are even + * iterators (we may get an integral type for InputIterator), so + * see if they are integral and pass them on to the next phase + * otherwise. + */ + template + _GLIBCXX20_CONSTEXPR + inline bool + __valid_range(_InputIterator __first, _InputIterator __last, + typename _Distance_traits<_InputIterator>::__type& __dist) + { +#ifdef __cpp_lib_is_constant_evaluated + if (std::is_constant_evaluated()) + // Detected by the compiler directly. + return true; +#endif + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + return __valid_range_aux(__first, __last, __dist, _Integral()); + } + + template + bool + __valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&, + const _Safe_iterator<_Iterator, _Sequence, _Category>&, + typename _Distance_traits<_Iterator>::__type&); + +#if __cplusplus >= 201103L + template + bool + __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&, + const _Safe_local_iterator<_Iterator, _Sequence>&, + typename _Distance_traits<_Iterator>::__type&); +#endif + + template + _GLIBCXX14_CONSTEXPR + inline bool + __valid_range(_InputIterator __first, _InputIterator __last) + { +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + if (__builtin_is_constant_evaluated()) + // Detected by the compiler directly. + return true; +#endif + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + return __valid_range_aux(__first, __last, _Integral()); + } + + template + bool + __valid_range(const _Safe_iterator<_Iterator, _Sequence, _Category>&, + const _Safe_iterator<_Iterator, _Sequence, _Category>&); + +#if __cplusplus >= 201103L + template + bool + __valid_range(const _Safe_local_iterator<_Iterator, _Sequence>&, + const _Safe_local_iterator<_Iterator, _Sequence>&); +#endif + + // Fallback method, always ok. + template + _GLIBCXX_CONSTEXPR + inline bool + __can_advance(_InputIterator, _Size) + { return true; } + + template + bool + __can_advance(const _Safe_iterator<_Iterator, _Sequence, _Category>&, + _Size); + + /** Helper function to extract base iterator of random access safe iterator + * in order to reduce performance impact of debug mode. Limited to random + * access iterator because it is the only category for which it is possible + * to check for correct iterators order in the __valid_range function + * thanks to the < operator. + */ + template + _GLIBCXX_CONSTEXPR + inline _Iterator + __base(_Iterator __it) + { return __it; } + +#if __cplusplus < 201103L + template + struct _Unsafe_type + { typedef _Iterator _Type; }; +#endif + + /* Remove debug mode safe iterator layer, if any. */ + template + inline _Iterator + __unsafe(_Iterator __it) + { return __it; } +} + +#endif diff --git a/resources/sources/avr-libstdcpp/include/debug/macros.h b/resources/sources/avr-libstdcpp/include/debug/macros.h new file mode 100644 index 000000000..73fb50d0c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/debug/macros.h @@ -0,0 +1,471 @@ +// Debugging support implementation -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file debug/macros.h + * This file is a GNU debug extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_DEBUG_MACROS_H +#define _GLIBCXX_DEBUG_MACROS_H 1 + +/** + * Macros used by the implementation to verify certain + * properties. These macros may only be used directly by the debug + * wrappers. Note that these are macros (instead of the more obviously + * @a correct choice of making them functions) because we need line and + * file information at the call site, to minimize the distance between + * the user error and where the error is reported. + * + */ +#if 0 /* defined _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED */ +# define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ + if (__builtin_is_constant_evaluated()) \ + /* FIXME: Compilation error here when !_Cond. */ \ + break; \ + if (! (_Cond)) \ + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ + ._ErrMsg._M_error() +#else +# define _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func) \ + if (! (_Cond)) \ + __gnu_debug::_Error_formatter::_S_at(_File, _Line, _Func) \ + ._ErrMsg._M_error() +#endif + +#define _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,_Func) \ + do \ + { \ + _GLIBCXX_DEBUG_VERIFY_COND_AT(_Cond,_ErrMsg,_File,_Line,_Func); \ + } while (false) + +#define _GLIBCXX_DEBUG_VERIFY_AT(_Cond,_ErrMsg,_File,_Line) \ + _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond,_ErrMsg,_File,_Line,__PRETTY_FUNCTION__) + +#define _GLIBCXX_DEBUG_VERIFY(_Cond,_ErrMsg) \ + _GLIBCXX_DEBUG_VERIFY_AT_F(_Cond, _ErrMsg, __FILE__, __LINE__, \ + __PRETTY_FUNCTION__) + +// Verify that [_First, _Last) forms a valid iterator range. +#define __glibcxx_check_valid_range(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last), \ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +#define __glibcxx_check_valid_range_at(_First,_Last,_File,_Line,_Func) \ +_GLIBCXX_DEBUG_VERIFY_AT_F(__gnu_debug::__valid_range(_First, _Last), \ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last), \ + _File,_Line,_Func) + +#define __glibcxx_check_valid_range2(_First,_Last,_Dist) \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__valid_range(_First, _Last, _Dist), \ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +#define __glibcxx_check_valid_constructor_range(_First,_Last) \ + __gnu_debug::__check_valid_range(_First, _Last, \ + __FILE__, __LINE__, __PRETTY_FUNCTION__) + +// Verify that [_First, _Last) forms a non-empty iterator range. +#define __glibcxx_check_non_empty_range(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(_First != _Last, \ + _M_message(__gnu_debug::__msg_non_empty_range) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +// Verify that [_First, _First + _Size) forms a valid range. +#define __glibcxx_check_can_increment(_First,_Size) \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__can_advance(_First, _Size), \ + _M_message(__gnu_debug::__msg_iter_subscript_oob) \ + ._M_iterator(_First, #_First) \ + ._M_integer(_Size, #_Size)) + +#define __glibcxx_check_can_increment_range(_First1,_Last1,_First2) \ + do \ + { \ + typename __gnu_debug::_Distance_traits<__decltype(_First1)>::__type __dist;\ + _GLIBCXX_DEBUG_VERIFY_COND_AT( \ + __gnu_debug::__valid_range(_First1, _Last1, __dist),\ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1), \ + __FILE__,__LINE__,__PRETTY_FUNCTION__); \ + _GLIBCXX_DEBUG_VERIFY_COND_AT( \ + __gnu_debug::__can_advance(_First2, __dist.first),\ + _M_message(__gnu_debug::__msg_iter_subscript_oob)\ + ._M_iterator(_First2, #_First2) \ + ._M_integer(__dist.first), \ + __FILE__,__LINE__,__PRETTY_FUNCTION__); \ + } while(false) + +#define __glibcxx_check_can_decrement_range(_First1,_Last1,_First2) \ + do \ + { \ + typename __gnu_debug::_Distance_traits<__decltype(_First1)>::__type __dist;\ + _GLIBCXX_DEBUG_VERIFY_COND_AT( \ + __gnu_debug::__valid_range(_First1, _Last1, __dist),\ + _M_message(__gnu_debug::__msg_valid_range) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1), \ + __FILE__,__LINE__,__PRETTY_FUNCTION__); \ + _GLIBCXX_DEBUG_VERIFY_COND_AT( \ + __gnu_debug::__can_advance(_First2, -__dist.first),\ + _M_message(__gnu_debug::__msg_iter_subscript_oob)\ + ._M_iterator(_First2, #_First2) \ + ._M_integer(-__dist.first), \ + __FILE__,__LINE__,__PRETTY_FUNCTION__); \ + } while(false) + +/** Verify that we can insert into *this with the iterator _Position. + * Insertion into a container at a specific position requires that + * the iterator be nonsingular, either dereferenceable or past-the-end, + * and that it reference the sequence we are inserting into. Note that + * this macro is only valid when the container is a_Safe_sequence and + * the iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert(_Position) \ +_GLIBCXX_DEBUG_VERIFY(!_Position._M_singular(), \ + _M_message(__gnu_debug::__msg_insert_singular) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_insert_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can insert into *this after the iterator _Position. + * Insertion into a container after a specific position requires that + * the iterator be nonsingular, either dereferenceable or before-begin, + * and that it reference the sequence we are inserting into. Note that + * this macro is only valid when the container is a_Safe_sequence and + * the iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert_after(_Position) \ +__glibcxx_check_insert(_Position); \ +_GLIBCXX_DEBUG_VERIFY(!_Position._M_is_end(), \ + _M_message(__gnu_debug::__msg_insert_after_end) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can insert the values in the iterator range + * [_First, _Last) into *this with the iterator _Position. Insertion + * into a container at a specific position requires that the iterator + * be nonsingular (i.e., either dereferenceable or past-the-end), + * that it reference the sequence we are inserting into, and that the + * iterator range [_First, _Last) is a valid (possibly empty) + * range which does not reference the sequence we are inserting into. + * Note that this macro is only valid when the container is a + * _Safe_sequence and the _Position iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert_range(_Position,_First,_Last,_Dist) \ +__glibcxx_check_valid_range2(_First,_Last,_Dist); \ +__glibcxx_check_insert(_Position); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\ + _M_message(__gnu_debug::__msg_insert_range_from_self)\ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_sequence(*this, "this")) + +/** Verify that we can insert the values in the iterator range + * [_First, _Last) into *this after the iterator _Position. Insertion + * into a container after a specific position requires that the iterator + * be nonsingular (i.e., either dereferenceable or past-the-end), + * that it reference the sequence we are inserting into, and that the + * iterator range [_First, _Last) is a valid (possibly empty) + * range which does not reference the sequence we are inserting into. + * Note that this macro is only valid when the container is a + * _Safe_sequence and the _Position iterator is a _Safe_iterator. +*/ +#define __glibcxx_check_insert_range_after(_Position,_First,_Last,_Dist)\ +__glibcxx_check_valid_range2(_First,_Last,_Dist); \ +__glibcxx_check_insert_after(_Position); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__foreign_iterator(_Position,_First,_Last),\ + _M_message(__gnu_debug::__msg_insert_range_from_self)\ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_sequence(*this, "this")) + +/** Verify that we can erase the element referenced by the iterator + * _Position. We can erase the element if the _Position iterator is + * dereferenceable and references this sequence. +*/ +#define __glibcxx_check_erase(_Position) \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_dereferenceable(), \ + _M_message(__gnu_debug::__msg_erase_bad) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can erase the element after the iterator + * _Position. We can erase the element if the _Position iterator is + * before a dereferenceable one and references this sequence. +*/ +#define __glibcxx_check_erase_after(_Position) \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_before_dereferenceable(), \ + _M_message(__gnu_debug::__msg_erase_after_bad) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)); \ +_GLIBCXX_DEBUG_VERIFY(_Position._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_Position, #_Position)) + +/** Verify that we can erase the elements in the iterator range + * [_First, _Last). We can erase the elements if [_First, _Last) is a + * valid iterator range within this sequence. +*/ +#define __glibcxx_check_erase_range(_First,_Last) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that we can erase the elements in the iterator range + * (_First, _Last). We can erase the elements if (_First, _Last) is a + * valid iterator range within this sequence. +*/ +#define __glibcxx_check_erase_range_after(_First,_Last) \ +_GLIBCXX_DEBUG_VERIFY(_First._M_can_compare(_Last), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_attached_to(this), \ + _M_message(__gnu_debug::__msg_erase_different) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First)); \ +_GLIBCXX_DEBUG_VERIFY(_First != _Last, \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(_First._M_incrementable(), \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)); \ +_GLIBCXX_DEBUG_VERIFY(!_Last._M_is_before_begin(), \ + _M_message(__gnu_debug::__msg_valid_range2) \ + ._M_sequence(*this, "this") \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) \ + +// Verify that the subscript _N is less than the container's size. +#define __glibcxx_check_subscript(_N) \ +_GLIBCXX_DEBUG_VERIFY(_N < this->size(), \ + _M_message(__gnu_debug::__msg_subscript_oob) \ + ._M_sequence(*this, "this") \ + ._M_integer(_N, #_N) \ + ._M_integer(this->size(), "size")) + +// Verify that the bucket _N is less than the container's buckets count. +#define __glibcxx_check_bucket_index(_N) \ +_GLIBCXX_DEBUG_VERIFY(_N < this->bucket_count(), \ + _M_message(__gnu_debug::__msg_bucket_index_oob) \ + ._M_sequence(*this, "this") \ + ._M_integer(_N, #_N) \ + ._M_integer(this->bucket_count(), "size")) + +// Verify that the container is nonempty +#define __glibcxx_check_nonempty() \ +_GLIBCXX_DEBUG_VERIFY(! this->empty(), \ + _M_message(__gnu_debug::__msg_empty) \ + ._M_sequence(*this, "this")) + +// Verify that a predicate is irreflexive +#define __glibcxx_check_irreflexive(_First,_Last) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last || !(*_First < *_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_iterator_value_type(_First, "< operator type")) + +#if __cplusplus >= 201103L +# define __glibcxx_check_irreflexive2(_First,_Last) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last \ + || __gnu_debug::__is_irreflexive(_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_iterator_value_type(_First, "< operator type")) +#else +# define __glibcxx_check_irreflexive2(_First,_Last) +#endif + +#define __glibcxx_check_irreflexive_pred(_First,_Last,_Pred) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last || !_Pred(*_First, *_First), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_instance(_Pred, "functor") \ + ._M_iterator_value_type(_First, "ordered type")) + +#if __cplusplus >= 201103L +# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) \ + _GLIBCXX_DEBUG_VERIFY(_First == _Last \ + ||__gnu_debug::__is_irreflexive_pred(_First, _Pred), \ + _M_message(__gnu_debug::__msg_irreflexive_ordering) \ + ._M_instance(_Pred, "functor") \ + ._M_iterator_value_type(_First, "ordered type")) +#else +# define __glibcxx_check_irreflexive_pred2(_First,_Last,_Pred) +#endif + +// Verify that the iterator range [_First, _Last) is sorted +#define __glibcxx_check_sorted(_First,_Last) \ +__glibcxx_check_valid_range(_First,_Last); \ +__glibcxx_check_irreflexive(_First,_Last); \ + _GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last)), \ + _M_message(__gnu_debug::__msg_unsorted) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that the iterator range [_First, _Last) is sorted by the + predicate _Pred. */ +#define __glibcxx_check_sorted_pred(_First,_Last,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +__glibcxx_check_irreflexive_pred(_First,_Last,_Pred); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_sorted( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Pred), \ + _M_message(__gnu_debug::__msg_unsorted_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred)) + +// Special variant for std::merge, std::includes, std::set_* +#define __glibcxx_check_sorted_set(_First1,_Last1,_First2) \ +__glibcxx_check_valid_range(_First1,_Last1); \ +_GLIBCXX_DEBUG_VERIFY( \ + __gnu_debug::__check_sorted_set(__gnu_debug::__base(_First1), \ + __gnu_debug::__base(_Last1), _First2),\ + _M_message(__gnu_debug::__msg_unsorted) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1)) + +// Likewise with a _Pred. +#define __glibcxx_check_sorted_set_pred(_First1,_Last1,_First2,_Pred) \ +__glibcxx_check_valid_range(_First1,_Last1); \ +_GLIBCXX_DEBUG_VERIFY( \ + __gnu_debug::__check_sorted_set(__gnu_debug::__base(_First1), \ + __gnu_debug::__base(_Last1), \ + _First2, _Pred), \ + _M_message(__gnu_debug::__msg_unsorted_pred) \ + ._M_iterator(_First1, #_First1) \ + ._M_iterator(_Last1, #_Last1) \ + ._M_string(#_Pred)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value. */ +#define __glibcxx_check_partitioned_lower(_First,_Last,_Value) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_lower( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Value), \ + _M_message(__gnu_debug::__msg_unpartitioned) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Value)) + +#define __glibcxx_check_partitioned_upper(_First,_Last,_Value) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Value), \ + _M_message(__gnu_debug::__msg_unpartitioned) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Value)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value and predicate _Pred. */ +#define __glibcxx_check_partitioned_lower_pred(_First,_Last,_Value,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_lower( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Value, _Pred), \ + _M_message(__gnu_debug::__msg_unpartitioned_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred) \ + ._M_string(#_Value)) + +/** Verify that the iterator range [_First, _Last) is partitioned + w.r.t. the value _Value and predicate _Pred. */ +#define __glibcxx_check_partitioned_upper_pred(_First,_Last,_Value,_Pred) \ +__glibcxx_check_valid_range(_First,_Last); \ +_GLIBCXX_DEBUG_VERIFY(__gnu_debug::__check_partitioned_upper( \ + __gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), _Value, _Pred), \ + _M_message(__gnu_debug::__msg_unpartitioned_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred) \ + ._M_string(#_Value)) + +// Verify that the iterator range [_First, _Last) is a heap +#define __glibcxx_check_heap(_First,_Last) \ + _GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last)), \ + _M_message(__gnu_debug::__msg_not_heap) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last)) + +/** Verify that the iterator range [_First, _Last) is a heap + w.r.t. the predicate _Pred. */ +#define __glibcxx_check_heap_pred(_First,_Last,_Pred) \ + _GLIBCXX_DEBUG_VERIFY(std::__is_heap(__gnu_debug::__base(_First), \ + __gnu_debug::__base(_Last), \ + _Pred), \ + _M_message(__gnu_debug::__msg_not_heap_pred) \ + ._M_iterator(_First, #_First) \ + ._M_iterator(_Last, #_Last) \ + ._M_string(#_Pred)) + +// Verify that the container is not self move assigned +#define __glibcxx_check_self_move_assign(_Other) \ +_GLIBCXX_DEBUG_VERIFY(this != &_Other, \ + _M_message(__gnu_debug::__msg_self_move_assign) \ + ._M_sequence(*this, "this")) + +// Verify that load factor is positive +#define __glibcxx_check_max_load_factor(_F) \ +_GLIBCXX_DEBUG_VERIFY(_F > 0.0f, \ + _M_message(__gnu_debug::__msg_valid_load_factor) \ + ._M_sequence(*this, "this")) + +#define __glibcxx_check_equal_allocs(_This, _Other) \ +_GLIBCXX_DEBUG_VERIFY(_This.get_allocator() == _Other.get_allocator(), \ + _M_message(__gnu_debug::__msg_equal_allocs) \ + ._M_sequence(_This, "this")) + +#define __glibcxx_check_string(_String) _GLIBCXX_DEBUG_PEDASSERT(_String != 0) +#define __glibcxx_check_string_len(_String,_Len) \ + _GLIBCXX_DEBUG_PEDASSERT(_String != 0 || _Len == 0) + +#endif diff --git a/resources/sources/avr-libstdcpp/include/decimal/decimal b/resources/sources/avr-libstdcpp/include/decimal/decimal new file mode 100644 index 000000000..8863d7e2a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/decimal/decimal @@ -0,0 +1,494 @@ +// -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file decimal/decimal + * This is a Standard C++ Library header. + */ + +// ISO/IEC TR 24733 +// Written by Janis Johnson + +#ifndef _GLIBCXX_DECIMAL +#define _GLIBCXX_DECIMAL 1 + +#pragma GCC system_header + +#include + +#ifndef _GLIBCXX_USE_DECIMAL_FLOAT +#error This file requires compiler and library support for ISO/IEC TR 24733 \ +that is currently not available. +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup decimal Decimal Floating-Point Arithmetic + * @ingroup numerics + * + * Classes and functions for decimal floating-point arithmetic. + * @{ + */ + + /** @namespace std::decimal + * @brief ISO/IEC TR 24733 Decimal floating-point arithmetic. + */ +namespace decimal +{ + class decimal32; + class decimal64; + class decimal128; + + // 3.2.5 Initialization from coefficient and exponent. + static decimal32 make_decimal32(long long __coeff, int __exp); + static decimal32 make_decimal32(unsigned long long __coeff, int __exp); + static decimal64 make_decimal64(long long __coeff, int __exp); + static decimal64 make_decimal64(unsigned long long __coeff, int __exp); + static decimal128 make_decimal128(long long __coeff, int __exp); + static decimal128 make_decimal128(unsigned long long __coeff, int __exp); + + /// Non-conforming extension: Conversion to integral type. + long long decimal32_to_long_long(decimal32 __d); + long long decimal64_to_long_long(decimal64 __d); + long long decimal128_to_long_long(decimal128 __d); + long long decimal_to_long_long(decimal32 __d); + long long decimal_to_long_long(decimal64 __d); + long long decimal_to_long_long(decimal128 __d); + + // 3.2.6 Conversion to generic floating-point type. + float decimal32_to_float(decimal32 __d); + float decimal64_to_float(decimal64 __d); + float decimal128_to_float(decimal128 __d); + float decimal_to_float(decimal32 __d); + float decimal_to_float(decimal64 __d); + float decimal_to_float(decimal128 __d); + + double decimal32_to_double(decimal32 __d); + double decimal64_to_double(decimal64 __d); + double decimal128_to_double(decimal128 __d); + double decimal_to_double(decimal32 __d); + double decimal_to_double(decimal64 __d); + double decimal_to_double(decimal128 __d); + + long double decimal32_to_long_double(decimal32 __d); + long double decimal64_to_long_double(decimal64 __d); + long double decimal128_to_long_double(decimal128 __d); + long double decimal_to_long_double(decimal32 __d); + long double decimal_to_long_double(decimal64 __d); + long double decimal_to_long_double(decimal128 __d); + + // 3.2.7 Unary arithmetic operators. + decimal32 operator+(decimal32 __rhs); + decimal64 operator+(decimal64 __rhs); + decimal128 operator+(decimal128 __rhs); + decimal32 operator-(decimal32 __rhs); + decimal64 operator-(decimal64 __rhs); + decimal128 operator-(decimal128 __rhs); + + // 3.2.8 Binary arithmetic operators. +#define _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(_Op, _T1, _T2, _T3) \ + _T1 operator _Op(_T2 __lhs, _T3 __rhs); +#define _DECLARE_DECIMAL_BINARY_OP_WITH_INT(_Op, _Tp) \ + _Tp operator _Op(_Tp __lhs, int __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned int __rhs); \ + _Tp operator _Op(_Tp __lhs, long __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned long __rhs); \ + _Tp operator _Op(_Tp __lhs, long long __rhs); \ + _Tp operator _Op(_Tp __lhs, unsigned long long __rhs); \ + _Tp operator _Op(int __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned int __lhs, _Tp __rhs); \ + _Tp operator _Op(long __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned long __lhs, _Tp __rhs); \ + _Tp operator _Op(long long __lhs, _Tp __rhs); \ + _Tp operator _Op(unsigned long long __lhs, _Tp __rhs); + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(+, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(-, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(*, decimal128) + + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal32, decimal32, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal32, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal32, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal64, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal32) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal64) + _DECLARE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal128) + _DECLARE_DECIMAL_BINARY_OP_WITH_INT(/, decimal128) + +#undef _DECLARE_DECIMAL_BINARY_OP_WITH_DEC +#undef _DECLARE_DECIMAL_BINARY_OP_WITH_INT + + // 3.2.9 Comparison operators. +#define _DECLARE_DECIMAL_COMPARISON(_Op, _Tp) \ + bool operator _Op(_Tp __lhs, decimal32 __rhs); \ + bool operator _Op(_Tp __lhs, decimal64 __rhs); \ + bool operator _Op(_Tp __lhs, decimal128 __rhs); \ + bool operator _Op(_Tp __lhs, int __rhs); \ + bool operator _Op(_Tp __lhs, unsigned int __rhs); \ + bool operator _Op(_Tp __lhs, long __rhs); \ + bool operator _Op(_Tp __lhs, unsigned long __rhs); \ + bool operator _Op(_Tp __lhs, long long __rhs); \ + bool operator _Op(_Tp __lhs, unsigned long long __rhs); \ + bool operator _Op(int __lhs, _Tp __rhs); \ + bool operator _Op(unsigned int __lhs, _Tp __rhs); \ + bool operator _Op(long __lhs, _Tp __rhs); \ + bool operator _Op(unsigned long __lhs, _Tp __rhs); \ + bool operator _Op(long long __lhs, _Tp __rhs); \ + bool operator _Op(unsigned long long __lhs, _Tp __rhs); + + _DECLARE_DECIMAL_COMPARISON(==, decimal32) + _DECLARE_DECIMAL_COMPARISON(==, decimal64) + _DECLARE_DECIMAL_COMPARISON(==, decimal128) + + _DECLARE_DECIMAL_COMPARISON(!=, decimal32) + _DECLARE_DECIMAL_COMPARISON(!=, decimal64) + _DECLARE_DECIMAL_COMPARISON(!=, decimal128) + + _DECLARE_DECIMAL_COMPARISON(<, decimal32) + _DECLARE_DECIMAL_COMPARISON(<, decimal64) + _DECLARE_DECIMAL_COMPARISON(<, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>=, decimal32) + _DECLARE_DECIMAL_COMPARISON(>=, decimal64) + _DECLARE_DECIMAL_COMPARISON(>=, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>, decimal32) + _DECLARE_DECIMAL_COMPARISON(>, decimal64) + _DECLARE_DECIMAL_COMPARISON(>, decimal128) + + _DECLARE_DECIMAL_COMPARISON(>=, decimal32) + _DECLARE_DECIMAL_COMPARISON(>=, decimal64) + _DECLARE_DECIMAL_COMPARISON(>=, decimal128) + +#undef _DECLARE_DECIMAL_COMPARISON + + /// 3.2.2 Class decimal32. + class decimal32 + { + public: + typedef float __decfloat32 __attribute__((mode(SD))); + + // 3.2.2.2 Construct/copy/destroy. + decimal32() : __val(0.e-101DF) {} + + // 3.2.2.3 Conversion from floating-point type. + explicit decimal32(decimal64 __d64); + explicit decimal32(decimal128 __d128); + explicit decimal32(float __r) : __val(__r) {} + explicit decimal32(double __r) : __val(__r) {} + explicit decimal32(long double __r) : __val(__r) {} + + // 3.2.2.4 Conversion from integral type. + decimal32(int __z) : __val(__z) {} + decimal32(unsigned int __z) : __val(__z) {} + decimal32(long __z) : __val(__z) {} + decimal32(unsigned long __z) : __val(__z) {} + decimal32(long long __z) : __val(__z) {} + decimal32(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal32(__decfloat32 __z) : __val(__z) {} + +#if __cplusplus >= 201103L + // 3.2.2.5 Conversion to integral type. + // Note: explicit per n3407. + explicit operator long long() const { return (long long)__val; } +#endif + + // 3.2.2.6 Increment and decrement operators. + decimal32& operator++() + { + __val += 1; + return *this; + } + + decimal32 operator++(int) + { + decimal32 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal32& operator--() + { + __val -= 1; + return *this; + } + + decimal32 operator--(int) + { + decimal32 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.2.7 Compound assignment. +#define _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(_Op) \ + decimal32& operator _Op(decimal32 __rhs); \ + decimal32& operator _Op(decimal64 __rhs); \ + decimal32& operator _Op(decimal128 __rhs); \ + decimal32& operator _Op(int __rhs); \ + decimal32& operator _Op(unsigned int __rhs); \ + decimal32& operator _Op(long __rhs); \ + decimal32& operator _Op(unsigned long __rhs); \ + decimal32& operator _Op(long long __rhs); \ + decimal32& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL32_COMPOUND_ASSIGNMENT + + private: + __decfloat32 __val; + + public: + __decfloat32 __getval(void) { return __val; } + void __setval(__decfloat32 __x) { __val = __x; } + }; + + /// 3.2.3 Class decimal64. + class decimal64 + { + public: + typedef float __decfloat64 __attribute__((mode(DD))); + + // 3.2.3.2 Construct/copy/destroy. + decimal64() : __val(0.e-398dd) {} + + // 3.2.3.3 Conversion from floating-point type. + decimal64(decimal32 d32); + explicit decimal64(decimal128 d128); + explicit decimal64(float __r) : __val(__r) {} + explicit decimal64(double __r) : __val(__r) {} + explicit decimal64(long double __r) : __val(__r) {} + + // 3.2.3.4 Conversion from integral type. + decimal64(int __z) : __val(__z) {} + decimal64(unsigned int __z) : __val(__z) {} + decimal64(long __z) : __val(__z) {} + decimal64(unsigned long __z) : __val(__z) {} + decimal64(long long __z) : __val(__z) {} + decimal64(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal64(__decfloat64 __z) : __val(__z) {} + +#if __cplusplus >= 201103L + // 3.2.3.5 Conversion to integral type. + // Note: explicit per n3407. + explicit operator long long() const { return (long long)__val; } +#endif + + // 3.2.3.6 Increment and decrement operators. + decimal64& operator++() + { + __val += 1; + return *this; + } + + decimal64 operator++(int) + { + decimal64 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal64& operator--() + { + __val -= 1; + return *this; + } + + decimal64 operator--(int) + { + decimal64 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.3.7 Compound assignment. +#define _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(_Op) \ + decimal64& operator _Op(decimal32 __rhs); \ + decimal64& operator _Op(decimal64 __rhs); \ + decimal64& operator _Op(decimal128 __rhs); \ + decimal64& operator _Op(int __rhs); \ + decimal64& operator _Op(unsigned int __rhs); \ + decimal64& operator _Op(long __rhs); \ + decimal64& operator _Op(unsigned long __rhs); \ + decimal64& operator _Op(long long __rhs); \ + decimal64& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL64_COMPOUND_ASSIGNMENT + + private: + __decfloat64 __val; + + public: + __decfloat64 __getval(void) { return __val; } + void __setval(__decfloat64 __x) { __val = __x; } + }; + + /// 3.2.4 Class decimal128. + class decimal128 + { + public: + typedef float __decfloat128 __attribute__((mode(TD))); + + // 3.2.4.2 Construct/copy/destroy. + decimal128() : __val(0.e-6176DL) {} + + // 3.2.4.3 Conversion from floating-point type. + decimal128(decimal32 d32); + decimal128(decimal64 d64); + explicit decimal128(float __r) : __val(__r) {} + explicit decimal128(double __r) : __val(__r) {} + explicit decimal128(long double __r) : __val(__r) {} + + + // 3.2.4.4 Conversion from integral type. + decimal128(int __z) : __val(__z) {} + decimal128(unsigned int __z) : __val(__z) {} + decimal128(long __z) : __val(__z) {} + decimal128(unsigned long __z) : __val(__z) {} + decimal128(long long __z) : __val(__z) {} + decimal128(unsigned long long __z) : __val(__z) {} + + /// Conforming extension: Conversion from scalar decimal type. + decimal128(__decfloat128 __z) : __val(__z) {} + +#if __cplusplus >= 201103L + // 3.2.4.5 Conversion to integral type. + // Note: explicit per n3407. + explicit operator long long() const { return (long long)__val; } +#endif + + // 3.2.4.6 Increment and decrement operators. + decimal128& operator++() + { + __val += 1; + return *this; + } + + decimal128 operator++(int) + { + decimal128 __tmp = *this; + __val += 1; + return __tmp; + } + + decimal128& operator--() + { + __val -= 1; + return *this; + } + + decimal128 operator--(int) + { + decimal128 __tmp = *this; + __val -= 1; + return __tmp; + } + + // 3.2.4.7 Compound assignment. +#define _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(_Op) \ + decimal128& operator _Op(decimal32 __rhs); \ + decimal128& operator _Op(decimal64 __rhs); \ + decimal128& operator _Op(decimal128 __rhs); \ + decimal128& operator _Op(int __rhs); \ + decimal128& operator _Op(unsigned int __rhs); \ + decimal128& operator _Op(long __rhs); \ + decimal128& operator _Op(unsigned long __rhs); \ + decimal128& operator _Op(long long __rhs); \ + decimal128& operator _Op(unsigned long long __rhs); + + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(+=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(-=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(*=) + _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT(/=) +#undef _DECLARE_DECIMAL128_COMPOUND_ASSIGNMENT + + private: + __decfloat128 __val; + + public: + __decfloat128 __getval(void) { return __val; } + void __setval(__decfloat128 __x) { __val = __x; } + }; + +#define _GLIBCXX_USE_DECIMAL_ 1 +} // namespace decimal + // @} group decimal + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#include + +#endif /* _GLIBCXX_DECIMAL */ diff --git a/resources/sources/avr-libstdcpp/include/decimal/decimal.h b/resources/sources/avr-libstdcpp/include/decimal/decimal.h new file mode 100644 index 000000000..50147e7e8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/decimal/decimal.h @@ -0,0 +1,469 @@ +// decimal classes -*- C++ -*- + +// Copyright (C) 2009-2020 Free Software Foundation, Inc. + +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file decimal/decimal.h + * This is an internal header file, included by other library headers. + * Do not attempt to use it directly. @headername{decimal} + */ + +// ISO/IEC TR 24733 +// Written by Janis Johnson + +#ifndef _GLIBCXX_DECIMAL_IMPL +#define _GLIBCXX_DECIMAL_IMPL 1 + +#pragma GCC system_header + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace decimal +{ + // ISO/IEC TR 24733 3.2.[234].1 Construct/copy/destroy. + + inline decimal32::decimal32(decimal64 __r) : __val(__r.__getval()) {} + inline decimal32::decimal32(decimal128 __r) : __val(__r.__getval()) {} + inline decimal64::decimal64(decimal32 __r) : __val(__r.__getval()) {} + inline decimal64::decimal64(decimal128 __r) : __val(__r.__getval()) {} + inline decimal128::decimal128(decimal32 __r) : __val(__r.__getval()) {} + inline decimal128::decimal128(decimal64 __r) : __val(__r.__getval()) {} + + // ISO/IEC TR 24733 3.2.[234].6 Compound assignment. + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, _T2) \ + inline _T1& _T1::operator _Op1(_T2 __rhs) \ + { \ + __setval(__getval() _Op2 __rhs.__getval()); \ + return *this; \ + } + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, _T2) \ + inline _T1& _T1::operator _Op1(_T2 __rhs) \ + { \ + __setval(__getval() _Op2 __rhs); \ + return *this; \ + } + +#define _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(_Op1, _Op2, _T1) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal32) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal64) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC(_Op1, _Op2, _T1, decimal128) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, int) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned int) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, long) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned long)\ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, long long) \ + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT(_Op1, _Op2, _T1, unsigned long long) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal32) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal32) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal64) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal64) + + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(+=, +, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(-=, -, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(*=, *, decimal128) + _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS(/=, /, decimal128) + +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_DEC +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENT_INT +#undef _DEFINE_DECIMAL_COMPOUND_ASSIGNMENTS + + // Extension: Conversion to integral type. + + inline long long decimal32_to_long_long(decimal32 __d) + { return (long long)__d.__getval(); } + + inline long long decimal64_to_long_long(decimal64 __d) + { return (long long)__d.__getval(); } + + inline long long decimal128_to_long_long(decimal128 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal32 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal64 __d) + { return (long long)__d.__getval(); } + + inline long long decimal_to_long_long(decimal128 __d) + { return (long long)__d.__getval(); } + + // ISO/IEC TR 24733 3.2.5 Initialization from coefficient and exponent. + + static decimal32 make_decimal32(long long __coeff, int __exponent) + { + decimal32 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DF; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DF; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal32 make_decimal32(unsigned long long __coeff, int __exponent) + { + decimal32 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DF; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DF; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal64 make_decimal64(long long __coeff, int __exponent) + { + decimal64 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DD; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DD; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal64 make_decimal64(unsigned long long __coeff, int __exponent) + { + decimal64 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DD; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DD; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal128 make_decimal128(long long __coeff, int __exponent) + { + decimal128 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DL; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DL; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + static decimal128 make_decimal128(unsigned long long __coeff, int __exponent) + { + decimal128 __decexp = 1, __multiplier; + + if (__exponent < 0) + { + __multiplier = 1.E-1DL; + __exponent = -__exponent; + } + else + __multiplier = 1.E1DL; + + for (int __i = 0; __i < __exponent; ++__i) + __decexp *= __multiplier; + + return __coeff * __decexp; + } + + // ISO/IEC TR 24733 3.2.6 Conversion to generic floating-point type. + + inline float decimal32_to_float(decimal32 __d) + { return (float)__d.__getval(); } + + inline float decimal64_to_float(decimal64 __d) + { return (float)__d.__getval(); } + + inline float decimal128_to_float(decimal128 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal32 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal64 __d) + { return (float)__d.__getval(); } + + inline float decimal_to_float(decimal128 __d) + { return (float)__d.__getval(); } + + inline double decimal32_to_double(decimal32 __d) + { return (double)__d.__getval(); } + + inline double decimal64_to_double(decimal64 __d) + { return (double)__d.__getval(); } + + inline double decimal128_to_double(decimal128 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal32 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal64 __d) + { return (double)__d.__getval(); } + + inline double decimal_to_double(decimal128 __d) + { return (double)__d.__getval(); } + + inline long double decimal32_to_long_double(decimal32 __d) + { return (long double)__d.__getval(); } + + inline long double decimal64_to_long_double(decimal64 __d) + { return (long double)__d.__getval(); } + + inline long double decimal128_to_long_double(decimal128 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal32 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal64 __d) + { return (long double)__d.__getval(); } + + inline long double decimal_to_long_double(decimal128 __d) + { return (long double)__d.__getval(); } + + // ISO/IEC TR 24733 3.2.7 Unary arithmetic operators. + +#define _DEFINE_DECIMAL_UNARY_OP(_Op, _Tp) \ + inline _Tp operator _Op(_Tp __rhs) \ + { \ + _Tp __tmp; \ + __tmp.__setval(_Op __rhs.__getval()); \ + return __tmp; \ + } + + _DEFINE_DECIMAL_UNARY_OP(+, decimal32) + _DEFINE_DECIMAL_UNARY_OP(+, decimal64) + _DEFINE_DECIMAL_UNARY_OP(+, decimal128) + _DEFINE_DECIMAL_UNARY_OP(-, decimal32) + _DEFINE_DECIMAL_UNARY_OP(-, decimal64) + _DEFINE_DECIMAL_UNARY_OP(-, decimal128) + +#undef _DEFINE_DECIMAL_UNARY_OP + + // ISO/IEC TR 24733 3.2.8 Binary arithmetic operators. + +#define _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(_Op, _T1, _T2, _T3) \ + inline _T1 operator _Op(_T2 __lhs, _T3 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_BOTH(_Op, _T1, _T2, _T3) \ + inline _T1 operator _Op(_T2 __lhs, _T3 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, _T2) \ + inline _T1 operator _Op(_T1 __lhs, _T2 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs.__getval() _Op __rhs); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, _T2) \ + inline _T1 operator _Op(_T2 __lhs, _T1 __rhs) \ + { \ + _T1 __retval; \ + __retval.__setval(__lhs _Op __rhs.__getval()); \ + return __retval; \ + } + +#define _DEFINE_DECIMAL_BINARY_OP_WITH_INT(_Op, _T1) \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, int); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned int); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, long long); \ + _DEFINE_DECIMAL_BINARY_OP_LHS(_Op, _T1, unsigned long long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, int); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned int); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, long long); \ + _DEFINE_DECIMAL_BINARY_OP_RHS(_Op, _T1, unsigned long long); \ + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(+, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(+, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(-, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(-, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(*, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(*, decimal128) + + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal32, decimal32, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal32, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal64, decimal64, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal32, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal64, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal32) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal64) + _DEFINE_DECIMAL_BINARY_OP_WITH_DEC(/, decimal128, decimal128, decimal128) + _DEFINE_DECIMAL_BINARY_OP_WITH_INT(/, decimal128) + +#undef _DEFINE_DECIMAL_BINARY_OP_WITH_DEC +#undef _DEFINE_DECIMAL_BINARY_OP_BOTH +#undef _DEFINE_DECIMAL_BINARY_OP_LHS +#undef _DEFINE_DECIMAL_BINARY_OP_RHS +#undef _DEFINE_DECIMAL_BINARY_OP_WITH_INT + + // ISO/IEC TR 24733 3.2.9 Comparison operators. + +#define _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs.__getval() _Op __rhs.__getval(); } + +#define _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs.__getval() _Op __rhs; } + +#define _DEFINE_DECIMAL_COMPARISON_RHS(_Op, _T1, _T2) \ + inline bool operator _Op(_T1 __lhs, _T2 __rhs) \ + { return __lhs _Op __rhs.__getval(); } + +#define _DEFINE_DECIMAL_COMPARISONS(_Op, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal32) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal64) \ + _DEFINE_DECIMAL_COMPARISON_BOTH(_Op, _Tp, decimal128) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, int) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned int) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, long long) \ + _DEFINE_DECIMAL_COMPARISON_LHS(_Op, _Tp, unsigned long long) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, int, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned int, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, long long, _Tp) \ + _DEFINE_DECIMAL_COMPARISON_RHS(_Op, unsigned long long, _Tp) + + _DEFINE_DECIMAL_COMPARISONS(==, decimal32) + _DEFINE_DECIMAL_COMPARISONS(==, decimal64) + _DEFINE_DECIMAL_COMPARISONS(==, decimal128) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(!=, decimal128) + _DEFINE_DECIMAL_COMPARISONS(<, decimal32) + _DEFINE_DECIMAL_COMPARISONS(<, decimal64) + _DEFINE_DECIMAL_COMPARISONS(<, decimal128) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(<=, decimal128) + _DEFINE_DECIMAL_COMPARISONS(>, decimal32) + _DEFINE_DECIMAL_COMPARISONS(>, decimal64) + _DEFINE_DECIMAL_COMPARISONS(>, decimal128) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal32) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal64) + _DEFINE_DECIMAL_COMPARISONS(>=, decimal128) + +#undef _DEFINE_DECIMAL_COMPARISON_BOTH +#undef _DEFINE_DECIMAL_COMPARISON_LHS +#undef _DEFINE_DECIMAL_COMPARISON_RHS +#undef _DEFINE_DECIMAL_COMPARISONS +} // namespace decimal + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif /* _GLIBCXX_DECIMAL_IMPL */ diff --git a/resources/sources/avr-libstdcpp/include/deque b/resources/sources/avr-libstdcpp/include/deque new file mode 100644 index 000000000..07e2c69d0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/deque @@ -0,0 +1,119 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/deque + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_DEQUE +#define _GLIBCXX_DEQUE 1 + +#pragma GCC system_header + +#include +#if __cplusplus > 201703L +# include // For remove and remove_if +#endif // C++20 +#include +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template + using deque = std::deque<_Tp, polymorphic_allocator<_Tp>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_erase_if 202002L + + template + inline typename deque<_Tp, _Alloc>::size_type + erase_if(deque<_Tp, _Alloc>& __cont, _Predicate __pred) + { + const auto __osz = __cont.size(); + __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred), + __cont.end()); + return __osz - __cont.size(); + } + + template + inline typename deque<_Tp, _Alloc>::size_type + erase(deque<_Tp, _Alloc>& __cont, const _Up& __value) + { + const auto __osz = __cont.size(); + __cont.erase(std::remove(__cont.begin(), __cont.end(), __value), + __cont.end()); + return __osz - __cont.size(); + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_DEQUE */ diff --git a/resources/sources/avr-libstdcpp/include/ext/algorithm b/resources/sources/avr-libstdcpp/include/ext/algorithm new file mode 100644 index 000000000..e7106fde4 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/algorithm @@ -0,0 +1,596 @@ +// Algorithm extensions -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/algorithm + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_ALGORITHM +#define _EXT_ALGORITHM 1 + +#pragma GCC system_header + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + //-------------------------------------------------- + // copy_n (not part of the C++ standard) + + template + std::pair<_InputIterator, _OutputIterator> + __copy_n(_InputIterator __first, _Size __count, + _OutputIterator __result, + std::input_iterator_tag) + { + for ( ; __count > 0; --__count) + { + *__result = *__first; + ++__first; + ++__result; + } + return std::pair<_InputIterator, _OutputIterator>(__first, __result); + } + + template + inline std::pair<_RAIterator, _OutputIterator> + __copy_n(_RAIterator __first, _Size __count, + _OutputIterator __result, + std::random_access_iterator_tag) + { + _RAIterator __last = __first + __count; + return std::pair<_RAIterator, _OutputIterator>(__last, std::copy(__first, + __last, + __result)); + } + + /** + * @brief Copies the range [first,first+count) into [result,result+count). + * @param __first An input iterator. + * @param __count The number of elements to copy. + * @param __result An output iterator. + * @return A std::pair composed of first+count and result+count. + * + * This is an SGI extension. + * This inline function will boil down to a call to @c memmove whenever + * possible. Failing that, if random access iterators are passed, then the + * loop count will be known (and therefore a candidate for compiler + * optimizations such as unrolling). + * @ingroup SGIextensions + */ + template + inline std::pair<_InputIterator, _OutputIterator> + copy_n(_InputIterator __first, _Size __count, _OutputIterator __result) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename std::iterator_traits<_InputIterator>::value_type>) + + return __gnu_cxx::__copy_n(__first, __count, __result, + std::__iterator_category(__first)); + } + + template + int + __lexicographical_compare_3way(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2) + { + while (__first1 != __last1 && __first2 != __last2) + { + if (*__first1 < *__first2) + return -1; + if (*__first2 < *__first1) + return 1; + ++__first1; + ++__first2; + } + if (__first2 == __last2) + return !(__first1 == __last1); + else + return -1; + } + + inline int + __lexicographical_compare_3way(const unsigned char* __first1, + const unsigned char* __last1, + const unsigned char* __first2, + const unsigned char* __last2) + { + const std::ptrdiff_t __len1 = __last1 - __first1; + const std::ptrdiff_t __len2 = __last2 - __first2; + const int __result = __builtin_memcmp(__first1, __first2, + (std::min)(__len1, __len2)); + return __result != 0 ? __result + : (__len1 == __len2 ? 0 : (__len1 < __len2 ? -1 : 1)); + } + + inline int + __lexicographical_compare_3way(const char* __first1, const char* __last1, + const char* __first2, const char* __last2) + { +#if CHAR_MAX == SCHAR_MAX + return __lexicographical_compare_3way((const signed char*) __first1, + (const signed char*) __last1, + (const signed char*) __first2, + (const signed char*) __last2); +#else + return __lexicographical_compare_3way((const unsigned char*) __first1, + (const unsigned char*) __last1, + (const unsigned char*) __first2, + (const unsigned char*) __last2); +#endif + } + + /** + * @brief @c memcmp on steroids. + * @param __first1 An input iterator. + * @param __last1 An input iterator. + * @param __first2 An input iterator. + * @param __last2 An input iterator. + * @return An int, as with @c memcmp. + * + * The return value will be less than zero if the first range is + * lexigraphically less than the second, greater than zero + * if the second range is lexigraphically less than the + * first, and zero otherwise. + * This is an SGI extension. + * @ingroup SGIextensions + */ + template + int + lexicographical_compare_3way(_InputIterator1 __first1, + _InputIterator1 __last1, + _InputIterator2 __first2, + _InputIterator2 __last2) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator1>) + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator2>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename std::iterator_traits<_InputIterator1>::value_type>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename std::iterator_traits<_InputIterator2>::value_type>) + __glibcxx_requires_valid_range(__first1, __last1); + __glibcxx_requires_valid_range(__first2, __last2); + + return __lexicographical_compare_3way(__first1, __last1, __first2, + __last2); + } + + // count and count_if: this version, whose return type is void, was present + // in the HP STL, and is retained as an extension for backward compatibility. + template + void + count(_InputIterator __first, _InputIterator __last, + const _Tp& __value, + _Size& __n) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_EqualityComparableConcept< + typename std::iterator_traits<_InputIterator>::value_type >) + __glibcxx_function_requires(_EqualityComparableConcept<_Tp>) + __glibcxx_requires_valid_range(__first, __last); + + for ( ; __first != __last; ++__first) + if (*__first == __value) + ++__n; + } + + template + void + count_if(_InputIterator __first, _InputIterator __last, + _Predicate __pred, + _Size& __n) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_UnaryPredicateConcept<_Predicate, + typename std::iterator_traits<_InputIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + for ( ; __first != __last; ++__first) + if (__pred(*__first)) + ++__n; + } + + // random_sample and random_sample_n (extensions, not part of the standard). + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + _OutputIterator + random_sample_n(_ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __out, const _Distance __n) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename std::iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + _Distance __remaining = std::distance(__first, __last); + _Distance __m = (std::min)(__n, __remaining); + + while (__m > 0) + { + if ((std::rand() % __remaining) < __m) + { + *__out = *__first; + ++__out; + --__m; + } + --__remaining; + ++__first; + } + return __out; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + _OutputIterator + random_sample_n(_ForwardIterator __first, _ForwardIterator __last, + _OutputIterator __out, const _Distance __n, + _RandomNumberGenerator& __rand) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_OutputIteratorConcept<_OutputIterator, + typename std::iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_function_requires(_UnaryFunctionConcept< + _RandomNumberGenerator, _Distance, _Distance>) + __glibcxx_requires_valid_range(__first, __last); + + _Distance __remaining = std::distance(__first, __last); + _Distance __m = (std::min)(__n, __remaining); + + while (__m > 0) + { + if (__rand(__remaining) < __m) + { + *__out = *__first; + ++__out; + --__m; + } + --__remaining; + ++__first; + } + return __out; + } + + template + _RandomAccessIterator + __random_sample(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __out, + const _Distance __n) + { + _Distance __m = 0; + _Distance __t = __n; + for ( ; __first != __last && __m < __n; ++__m, ++__first) + __out[__m] = *__first; + + while (__first != __last) + { + ++__t; + _Distance __M = std::rand() % (__t); + if (__M < __n) + __out[__M] = *__first; + ++__first; + } + return __out + __m; + } + + template + _RandomAccessIterator + __random_sample(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __out, + _RandomNumberGenerator& __rand, + const _Distance __n) + { + // concept requirements + __glibcxx_function_requires(_UnaryFunctionConcept< + _RandomNumberGenerator, _Distance, _Distance>) + + _Distance __m = 0; + _Distance __t = __n; + for ( ; __first != __last && __m < __n; ++__m, ++__first) + __out[__m] = *__first; + + while (__first != __last) + { + ++__t; + _Distance __M = __rand(__t); + if (__M < __n) + __out[__M] = *__first; + ++__first; + } + return __out + __m; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline _RandomAccessIterator + random_sample(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __out_first, + _RandomAccessIterator __out_last) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_valid_range(__out_first, __out_last); + + return __random_sample(__first, __last, + __out_first, __out_last - __out_first); + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline _RandomAccessIterator + random_sample(_InputIterator __first, _InputIterator __last, + _RandomAccessIterator __out_first, + _RandomAccessIterator __out_last, + _RandomNumberGenerator& __rand) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + __glibcxx_function_requires(_Mutable_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_requires_valid_range(__first, __last); + __glibcxx_requires_valid_range(__out_first, __out_last); + + return __random_sample(__first, __last, + __out_first, __rand, + __out_last - __out_first); + } + +#if __cplusplus >= 201103L + using std::is_heap; +#else + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename std::iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__is_heap(__first, __last - __first); + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline bool + is_heap(_RandomAccessIterator __first, _RandomAccessIterator __last, + _StrictWeakOrdering __comp) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering, + typename std::iterator_traits<_RandomAccessIterator>::value_type, + typename std::iterator_traits<_RandomAccessIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + return std::__is_heap(__first, __comp, __last - __first); + } +#endif + +#if __cplusplus >= 201103L + using std::is_sorted; +#else + // is_sorted, a predicated testing whether a range is sorted in + // nondescending order. This is an extension, not part of the C++ + // standard. + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_LessThanComparableConcept< + typename std::iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, ++__next) + if (*__next < *__first) + return false; + return true; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + bool + is_sorted(_ForwardIterator __first, _ForwardIterator __last, + _StrictWeakOrdering __comp) + { + // concept requirements + __glibcxx_function_requires(_ForwardIteratorConcept<_ForwardIterator>) + __glibcxx_function_requires(_BinaryPredicateConcept<_StrictWeakOrdering, + typename std::iterator_traits<_ForwardIterator>::value_type, + typename std::iterator_traits<_ForwardIterator>::value_type>) + __glibcxx_requires_valid_range(__first, __last); + + if (__first == __last) + return true; + + _ForwardIterator __next = __first; + for (++__next; __next != __last; __first = __next, ++__next) + if (__comp(*__next, *__first)) + return false; + return true; + } +#endif // C++11 + + /** + * @brief Find the median of three values. + * @param __a A value. + * @param __b A value. + * @param __c A value. + * @return One of @p a, @p b or @p c. + * + * If @c {l,m,n} is some convolution of @p {a,b,c} such that @c l<=m<=n + * then the value returned will be @c m. + * This is an SGI extension. + * @ingroup SGIextensions + */ + template + const _Tp& + __median(const _Tp& __a, const _Tp& __b, const _Tp& __c) + { + // concept requirements + __glibcxx_function_requires(_LessThanComparableConcept<_Tp>) + if (__a < __b) + if (__b < __c) + return __b; + else if (__a < __c) + return __c; + else + return __a; + else if (__a < __c) + return __a; + else if (__b < __c) + return __c; + else + return __b; + } + + /** + * @brief Find the median of three values using a predicate for comparison. + * @param __a A value. + * @param __b A value. + * @param __c A value. + * @param __comp A binary predicate. + * @return One of @p a, @p b or @p c. + * + * If @c {l,m,n} is some convolution of @p {a,b,c} such that @p comp(l,m) + * and @p comp(m,n) are both true then the value returned will be @c m. + * This is an SGI extension. + * @ingroup SGIextensions + */ + template + const _Tp& + __median(const _Tp& __a, const _Tp& __b, const _Tp& __c, _Compare __comp) + { + // concept requirements + __glibcxx_function_requires(_BinaryFunctionConcept<_Compare, bool, + _Tp, _Tp>) + if (__comp(__a, __b)) + if (__comp(__b, __c)) + return __b; + else if (__comp(__a, __c)) + return __c; + else + return __a; + else if (__comp(__a, __c)) + return __a; + else if (__comp(__b, __c)) + return __c; + else + return __b; + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _EXT_ALGORITHM */ diff --git a/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h b/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h new file mode 100644 index 000000000..667a9c084 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/aligned_buffer.h @@ -0,0 +1,125 @@ +// Aligned memory buffer -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/aligned_buffer.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _ALIGNED_BUFFER_H +#define _ALIGNED_BUFFER_H 1 + +#pragma GCC system_header + +#if __cplusplus >= 201103L +# include +#else +# include +#endif + +namespace __gnu_cxx +{ + // A utility type containing a POD object that can hold an object of type + // _Tp initialized via placement new or allocator_traits::construct. + // Intended for use as a data member subobject, use __aligned_buffer for + // complete objects. + template + struct __aligned_membuf + { + // Target macro ADJUST_FIELD_ALIGN can produce different alignment for + // types when used as class members. __aligned_membuf is intended + // for use as a class member, so align the buffer as for a class member. + // Since GCC 8 we could just use alignof(_Tp) instead, but older + // versions of non-GNU compilers might still need this trick. + struct _Tp2 { _Tp _M_t; }; + + alignas(__alignof__(_Tp2::_M_t)) unsigned char _M_storage[sizeof(_Tp)]; + + __aligned_membuf() = default; + + // Can be used to avoid value-initialization zeroing _M_storage. + __aligned_membuf(std::nullptr_t) { } + + void* + _M_addr() noexcept + { return static_cast(&_M_storage); } + + const void* + _M_addr() const noexcept + { return static_cast(&_M_storage); } + + _Tp* + _M_ptr() noexcept + { return static_cast<_Tp*>(_M_addr()); } + + const _Tp* + _M_ptr() const noexcept + { return static_cast(_M_addr()); } + }; + +#if _GLIBCXX_INLINE_VERSION + template + using __aligned_buffer = __aligned_membuf<_Tp>; +#else + // Similar to __aligned_membuf but aligned for complete objects, not members. + // This type is used in , , + // and , but ideally they would use __aligned_membuf + // instead, as it has smaller size for some types on some targets. + // This type is still used to avoid an ABI change. + template + struct __aligned_buffer + : std::aligned_storage + { + typename + std::aligned_storage::type _M_storage; + + __aligned_buffer() = default; + + // Can be used to avoid value-initialization + __aligned_buffer(std::nullptr_t) { } + + void* + _M_addr() noexcept + { + return static_cast(&_M_storage); + } + + const void* + _M_addr() const noexcept + { + return static_cast(&_M_storage); + } + + _Tp* + _M_ptr() noexcept + { return static_cast<_Tp*>(_M_addr()); } + + const _Tp* + _M_ptr() const noexcept + { return static_cast(_M_addr()); } + }; +#endif + +} // namespace + +#endif /* _ALIGNED_BUFFER_H */ diff --git a/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h b/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h new file mode 100644 index 000000000..3bbef9ec5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/alloc_traits.h @@ -0,0 +1,171 @@ +// Allocator traits -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/alloc_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_ALLOC_TRAITS_H +#define _EXT_ALLOC_TRAITS_H 1 + +#pragma GCC system_header + +# include +#if __cplusplus < 201103L +# include // for __alloc_swap +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** + * @brief Uniform interface to C++98 and C++11 allocators. + * @ingroup allocators +*/ +template + struct __alloc_traits +#if __cplusplus >= 201103L + : std::allocator_traits<_Alloc> +#endif + { + typedef _Alloc allocator_type; +#if __cplusplus >= 201103L + typedef std::allocator_traits<_Alloc> _Base_type; + typedef typename _Base_type::value_type value_type; + typedef typename _Base_type::pointer pointer; + typedef typename _Base_type::const_pointer const_pointer; + typedef typename _Base_type::size_type size_type; + typedef typename _Base_type::difference_type difference_type; + // C++11 allocators do not define reference or const_reference + typedef value_type& reference; + typedef const value_type& const_reference; + using _Base_type::allocate; + using _Base_type::deallocate; + using _Base_type::construct; + using _Base_type::destroy; + using _Base_type::max_size; + + private: + template + using __is_custom_pointer + = std::__and_, + std::__not_>>; + + public: + // overload construct for non-standard pointer types + template + static _GLIBCXX14_CONSTEXPR + std::__enable_if_t<__is_custom_pointer<_Ptr>::value> + construct(_Alloc& __a, _Ptr __p, _Args&&... __args) + noexcept(noexcept(_Base_type::construct(__a, std::__to_address(__p), + std::forward<_Args>(__args)...))) + { + _Base_type::construct(__a, std::__to_address(__p), + std::forward<_Args>(__args)...); + } + + // overload destroy for non-standard pointer types + template + static _GLIBCXX14_CONSTEXPR + std::__enable_if_t<__is_custom_pointer<_Ptr>::value> + destroy(_Alloc& __a, _Ptr __p) + noexcept(noexcept(_Base_type::destroy(__a, std::__to_address(__p)))) + { _Base_type::destroy(__a, std::__to_address(__p)); } + + static constexpr _Alloc _S_select_on_copy(const _Alloc& __a) + { return _Base_type::select_on_container_copy_construction(__a); } + + static _GLIBCXX14_CONSTEXPR void _S_on_swap(_Alloc& __a, _Alloc& __b) + { std::__alloc_on_swap(__a, __b); } + + static constexpr bool _S_propagate_on_copy_assign() + { return _Base_type::propagate_on_container_copy_assignment::value; } + + static constexpr bool _S_propagate_on_move_assign() + { return _Base_type::propagate_on_container_move_assignment::value; } + + static constexpr bool _S_propagate_on_swap() + { return _Base_type::propagate_on_container_swap::value; } + + static constexpr bool _S_always_equal() + { return _Base_type::is_always_equal::value; } + + static constexpr bool _S_nothrow_move() + { return _S_propagate_on_move_assign() || _S_always_equal(); } + + template + struct rebind + { typedef typename _Base_type::template rebind_alloc<_Tp> other; }; +#else // ! C++11 + + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef typename _Alloc::value_type value_type; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + typedef typename _Alloc::size_type size_type; + typedef typename _Alloc::difference_type difference_type; + + _GLIBCXX_NODISCARD static pointer + allocate(_Alloc& __a, size_type __n) + { return __a.allocate(__n); } + + template + _GLIBCXX_NODISCARD static pointer + allocate(_Alloc& __a, size_type __n, _Hint __hint) + { return __a.allocate(__n, __hint); } + + static void deallocate(_Alloc& __a, pointer __p, size_type __n) + { __a.deallocate(__p, __n); } + + template + static void construct(_Alloc& __a, pointer __p, const _Tp& __arg) + { __a.construct(__p, __arg); } + + static void destroy(_Alloc& __a, pointer __p) + { __a.destroy(__p); } + + static size_type max_size(const _Alloc& __a) + { return __a.max_size(); } + + static const _Alloc& _S_select_on_copy(const _Alloc& __a) { return __a; } + + static void _S_on_swap(_Alloc& __a, _Alloc& __b) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 431. Swapping containers with unequal allocators. + std::__alloc_swap<_Alloc>::_S_do_it(__a, __b); + } + + template + struct rebind + { typedef typename _Alloc::template rebind<_Tp>::other other; }; +#endif // C++11 + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace __gnu_cxx + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/atomicity.h b/resources/sources/avr-libstdcpp/include/ext/atomicity.h new file mode 100644 index 000000000..581e0c92a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/atomicity.h @@ -0,0 +1,116 @@ +// Support for atomic operations -*- C++ -*- + +// Copyright (C) 2004-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/atomicity.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _GLIBCXX_ATOMICITY_H +#define _GLIBCXX_ATOMICITY_H 1 + +#pragma GCC system_header + +#include + +typedef int _Atomic_word; + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Functions for portable atomic access. + // To abstract locking primitives across all thread policies, use: + // __exchange_and_add_dispatch + // __atomic_add_dispatch +#ifdef _GLIBCXX_ATOMIC_BUILTINS + inline _Atomic_word + __attribute__((__always_inline__)) + __exchange_and_add(volatile _Atomic_word* __mem, int __val) + { return __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } + + inline void + __attribute__((__always_inline__)) + __atomic_add(volatile _Atomic_word* __mem, int __val) + { __atomic_fetch_add(__mem, __val, __ATOMIC_ACQ_REL); } +#else + _Atomic_word + __exchange_and_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; + + void + __atomic_add(volatile _Atomic_word*, int) _GLIBCXX_NOTHROW; +#endif + + inline _Atomic_word + __attribute__((__always_inline__)) + __exchange_and_add_single(_Atomic_word* __mem, int __val) + { + _Atomic_word __result = *__mem; + *__mem += __val; + return __result; + } + + inline void + __attribute__((__always_inline__)) + __atomic_add_single(_Atomic_word* __mem, int __val) + { *__mem += __val; } + + inline _Atomic_word + __attribute__ ((__always_inline__)) + __exchange_and_add_dispatch(_Atomic_word* __mem, int __val) + { +#ifdef __GTHREADS + if (__gthread_active_p()) + return __exchange_and_add(__mem, __val); +#endif + return __exchange_and_add_single(__mem, __val); + } + + inline void + __attribute__ ((__always_inline__)) + __atomic_add_dispatch(_Atomic_word* __mem, int __val) + { +#ifdef __GTHREADS + if (__gthread_active_p()) + { + __atomic_add(__mem, __val); + return; + } +#endif + __atomic_add_single(__mem, __val); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +// Even if the CPU doesn't need a memory barrier, we need to ensure +// that the compiler doesn't reorder memory accesses across the +// barriers. +#ifndef _GLIBCXX_READ_MEM_BARRIER +#define _GLIBCXX_READ_MEM_BARRIER __atomic_thread_fence (__ATOMIC_ACQUIRE) +#endif +#ifndef _GLIBCXX_WRITE_MEM_BARRIER +#define _GLIBCXX_WRITE_MEM_BARRIER __atomic_thread_fence (__ATOMIC_RELEASE) +#endif + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/cmath b/resources/sources/avr-libstdcpp/include/ext/cmath new file mode 100644 index 000000000..09c6e44b8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/cmath @@ -0,0 +1,152 @@ +// Math extensions -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/cmath + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_CMATH +#define _EXT_CMATH 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // A class for math constants. + template + struct __math_constants + { + static_assert(std::is_floating_point<_RealType>::value, + "template argument not a floating point type"); + + // Constant @f$ \pi @f$. + static constexpr _RealType __pi = 3.1415926535897932384626433832795029L; + // Constant @f$ \pi / 2 @f$. + static constexpr _RealType __pi_half = 1.5707963267948966192313216916397514L; + // Constant @f$ \pi / 3 @f$. + static constexpr _RealType __pi_third = 1.0471975511965977461542144610931676L; + // Constant @f$ \pi / 4 @f$. + static constexpr _RealType __pi_quarter = 0.7853981633974483096156608458198757L; + // Constant @f$ \sqrt(\pi / 2) @f$. + static constexpr _RealType __root_pi_div_2 = 1.2533141373155002512078826424055226L; + // Constant @f$ 1 / \pi @f$. + static constexpr _RealType __one_div_pi = 0.3183098861837906715377675267450287L; + // Constant @f$ 2 / \pi @f$. + static constexpr _RealType __two_div_pi = 0.6366197723675813430755350534900574L; + // Constant @f$ 2 / \sqrt(\pi) @f$. + static constexpr _RealType __two_div_root_pi = 1.1283791670955125738961589031215452L; + + // Constant Euler's number @f$ e @f$. + static constexpr _RealType __e = 2.7182818284590452353602874713526625L; + // Constant @f$ 1 / e @f$. + static constexpr _RealType __one_div_e = 0.36787944117144232159552377016146087L; + // Constant @f$ \log_2(e) @f$. + static constexpr _RealType __log2_e = 1.4426950408889634073599246810018921L; + // Constant @f$ \log_10(e) @f$. + static constexpr _RealType __log10_e = 0.4342944819032518276511289189166051L; + // Constant @f$ \ln(2) @f$. + static constexpr _RealType __ln_2 = 0.6931471805599453094172321214581766L; + // Constant @f$ \ln(3) @f$. + static constexpr _RealType __ln_3 = 1.0986122886681096913952452369225257L; + // Constant @f$ \ln(10) @f$. + static constexpr _RealType __ln_10 = 2.3025850929940456840179914546843642L; + + // Constant Euler-Mascheroni @f$ \gamma_E @f$. + static constexpr _RealType __gamma_e = 0.5772156649015328606065120900824024L; + // Constant Golden Ratio @f$ \phi @f$. + static constexpr _RealType __phi = 1.6180339887498948482045868343656381L; + + // Constant @f$ \sqrt(2) @f$. + static constexpr _RealType __root_2 = 1.4142135623730950488016887242096981L; + // Constant @f$ \sqrt(3) @f$. + static constexpr _RealType __root_3 = 1.7320508075688772935274463415058724L; + // Constant @f$ \sqrt(5) @f$. + static constexpr _RealType __root_5 = 2.2360679774997896964091736687312762L; + // Constant @f$ \sqrt(7) @f$. + static constexpr _RealType __root_7 = 2.6457513110645905905016157536392604L; + // Constant @f$ 1 / \sqrt(2) @f$. + static constexpr _RealType __one_div_root_2 = 0.7071067811865475244008443621048490L; + }; + + // And the template definitions for the constants. + template + constexpr _RealType __math_constants<_RealType>::__pi; + template + constexpr _RealType __math_constants<_RealType>::__pi_half; + template + constexpr _RealType __math_constants<_RealType>::__pi_third; + template + constexpr _RealType __math_constants<_RealType>::__pi_quarter; + template + constexpr _RealType __math_constants<_RealType>::__root_pi_div_2; + template + constexpr _RealType __math_constants<_RealType>::__one_div_pi; + template + constexpr _RealType __math_constants<_RealType>::__two_div_pi; + template + constexpr _RealType __math_constants<_RealType>::__two_div_root_pi; + template + constexpr _RealType __math_constants<_RealType>::__e; + template + constexpr _RealType __math_constants<_RealType>::__one_div_e; + template + constexpr _RealType __math_constants<_RealType>::__log2_e; + template + constexpr _RealType __math_constants<_RealType>::__log10_e; + template + constexpr _RealType __math_constants<_RealType>::__ln_2; + template + constexpr _RealType __math_constants<_RealType>::__ln_3; + template + constexpr _RealType __math_constants<_RealType>::__ln_10; + template + constexpr _RealType __math_constants<_RealType>::__gamma_e; + template + constexpr _RealType __math_constants<_RealType>::__phi; + template + constexpr _RealType __math_constants<_RealType>::__root_2; + template + constexpr _RealType __math_constants<_RealType>::__root_3; + template + constexpr _RealType __math_constants<_RealType>::__root_5; + template + constexpr _RealType __math_constants<_RealType>::__root_7; + template + constexpr _RealType __math_constants<_RealType>::__one_div_root_2; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace __gnu_cxx + +#endif // C++11 + +#endif // _EXT_CMATH diff --git a/resources/sources/avr-libstdcpp/include/ext/functional b/resources/sources/avr-libstdcpp/include/ext/functional new file mode 100644 index 000000000..4f50a6003 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/functional @@ -0,0 +1,422 @@ +// Functional extensions -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/functional + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_FUNCTIONAL +#define _EXT_FUNCTIONAL 1 + +#pragma GCC system_header + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** The @c identity_element functions are not part of the C++ + * standard; SGI provided them as an extension. Its argument is an + * operation, and its return value is the identity element for that + * operation. It is overloaded for addition and multiplication, + * and you can overload it for your own nefarious operations. + * + * @addtogroup SGIextensions + * @{ + */ + /// An \link SGIextensions SGI extension \endlink. + template + inline _Tp + identity_element(std::plus<_Tp>) + { return _Tp(0); } + + /// An \link SGIextensions SGI extension \endlink. + template + inline _Tp + identity_element(std::multiplies<_Tp>) + { return _Tp(1); } + /** @} */ + + /** As an extension to the binders, SGI provided composition functors and + * wrapper functions to aid in their creation. The @c unary_compose + * functor is constructed from two functions/functors, @c f and @c g. + * Calling @c operator() with a single argument @c x returns @c f(g(x)). + * The function @c compose1 takes the two functions and constructs a + * @c unary_compose variable for you. + * + * @c binary_compose is constructed from three functors, @c f, @c g1, + * and @c g2. Its @c operator() returns @c f(g1(x),g2(x)). The function + * compose2 takes f, g1, and g2, and constructs the @c binary_compose + * instance for you. For example, if @c f returns an int, then + * \code + * int answer = (compose2(f,g1,g2))(x); + * \endcode + * is equivalent to + * \code + * int temp1 = g1(x); + * int temp2 = g2(x); + * int answer = f(temp1,temp2); + * \endcode + * But the first form is more compact, and can be passed around as a + * functor to other algorithms. + * + * @addtogroup SGIextensions + * @{ + */ + /// An \link SGIextensions SGI extension \endlink. + template + class unary_compose + : public std::unary_function + { + protected: + _Operation1 _M_fn1; + _Operation2 _M_fn2; + + public: + unary_compose(const _Operation1& __x, const _Operation2& __y) + : _M_fn1(__x), _M_fn2(__y) {} + + typename _Operation1::result_type + operator()(const typename _Operation2::argument_type& __x) const + { return _M_fn1(_M_fn2(__x)); } + }; + + /// An \link SGIextensions SGI extension \endlink. + template + inline unary_compose<_Operation1, _Operation2> + compose1(const _Operation1& __fn1, const _Operation2& __fn2) + { return unary_compose<_Operation1,_Operation2>(__fn1, __fn2); } + + /// An \link SGIextensions SGI extension \endlink. + template + class binary_compose + : public std::unary_function + { + protected: + _Operation1 _M_fn1; + _Operation2 _M_fn2; + _Operation3 _M_fn3; + + public: + binary_compose(const _Operation1& __x, const _Operation2& __y, + const _Operation3& __z) + : _M_fn1(__x), _M_fn2(__y), _M_fn3(__z) { } + + typename _Operation1::result_type + operator()(const typename _Operation2::argument_type& __x) const + { return _M_fn1(_M_fn2(__x), _M_fn3(__x)); } + }; + + /// An \link SGIextensions SGI extension \endlink. + template + inline binary_compose<_Operation1, _Operation2, _Operation3> + compose2(const _Operation1& __fn1, const _Operation2& __fn2, + const _Operation3& __fn3) + { return binary_compose<_Operation1, _Operation2, _Operation3> + (__fn1, __fn2, __fn3); } + /** @} */ + + /** As an extension, SGI provided a functor called @c identity. When a + * functor is required but no operations are desired, this can be used as a + * pass-through. Its @c operator() returns its argument unchanged. + * + * @addtogroup SGIextensions + */ + template + struct identity + : public std::_Identity<_Tp> {}; + + /** @c select1st and @c select2nd are extensions provided by SGI. Their + * @c operator()s + * take a @c std::pair as an argument, and return either the first member + * or the second member, respectively. They can be used (especially with + * the composition functors) to @a strip data from a sequence before + * performing the remainder of an algorithm. + * + * @addtogroup SGIextensions + * @{ + */ + /// An \link SGIextensions SGI extension \endlink. + template + struct select1st + : public std::_Select1st<_Pair> {}; + + /// An \link SGIextensions SGI extension \endlink. + template + struct select2nd + : public std::_Select2nd<_Pair> {}; + + /** @} */ + + // extension documented next + template + struct _Project1st : public std::binary_function<_Arg1, _Arg2, _Arg1> + { + _Arg1 + operator()(const _Arg1& __x, const _Arg2&) const + { return __x; } + }; + + template + struct _Project2nd : public std::binary_function<_Arg1, _Arg2, _Arg2> + { + _Arg2 + operator()(const _Arg1&, const _Arg2& __y) const + { return __y; } + }; + + /** The @c operator() of the @c project1st functor takes two arbitrary + * arguments and returns the first one, while @c project2nd returns the + * second one. They are extensions provided by SGI. + * + * @addtogroup SGIextensions + * @{ + */ + + /// An \link SGIextensions SGI extension \endlink. + template + struct project1st : public _Project1st<_Arg1, _Arg2> {}; + + /// An \link SGIextensions SGI extension \endlink. + template + struct project2nd : public _Project2nd<_Arg1, _Arg2> {}; + /** @} */ + + // extension documented next + template + struct _Constant_void_fun + { + typedef _Result result_type; + result_type _M_val; + + _Constant_void_fun(const result_type& __v) : _M_val(__v) {} + + const result_type& + operator()() const + { return _M_val; } + }; + + template + struct _Constant_unary_fun + { + typedef _Argument argument_type; + typedef _Result result_type; + result_type _M_val; + + _Constant_unary_fun(const result_type& __v) : _M_val(__v) {} + + const result_type& + operator()(const _Argument&) const + { return _M_val; } + }; + + template + struct _Constant_binary_fun + { + typedef _Arg1 first_argument_type; + typedef _Arg2 second_argument_type; + typedef _Result result_type; + _Result _M_val; + + _Constant_binary_fun(const _Result& __v) : _M_val(__v) {} + + const result_type& + operator()(const _Arg1&, const _Arg2&) const + { return _M_val; } + }; + + /** These three functors are each constructed from a single arbitrary + * variable/value. Later, their @c operator()s completely ignore any + * arguments passed, and return the stored value. + * - @c constant_void_fun's @c operator() takes no arguments + * - @c constant_unary_fun's @c operator() takes one argument (ignored) + * - @c constant_binary_fun's @c operator() takes two arguments (ignored) + * + * The helper creator functions @c constant0, @c constant1, and + * @c constant2 each take a @a result argument and construct variables of + * the appropriate functor type. + * + * @addtogroup SGIextensions + * @{ + */ + /// An \link SGIextensions SGI extension \endlink. + template + struct constant_void_fun + : public _Constant_void_fun<_Result> + { + constant_void_fun(const _Result& __v) + : _Constant_void_fun<_Result>(__v) {} + }; + + /// An \link SGIextensions SGI extension \endlink. + template + struct constant_unary_fun : public _Constant_unary_fun<_Result, _Argument> + { + constant_unary_fun(const _Result& __v) + : _Constant_unary_fun<_Result, _Argument>(__v) {} + }; + + /// An \link SGIextensions SGI extension \endlink. + template + struct constant_binary_fun + : public _Constant_binary_fun<_Result, _Arg1, _Arg2> + { + constant_binary_fun(const _Result& __v) + : _Constant_binary_fun<_Result, _Arg1, _Arg2>(__v) {} + }; + + /// An \link SGIextensions SGI extension \endlink. + template + inline constant_void_fun<_Result> + constant0(const _Result& __val) + { return constant_void_fun<_Result>(__val); } + + /// An \link SGIextensions SGI extension \endlink. + template + inline constant_unary_fun<_Result, _Result> + constant1(const _Result& __val) + { return constant_unary_fun<_Result, _Result>(__val); } + + /// An \link SGIextensions SGI extension \endlink. + template + inline constant_binary_fun<_Result,_Result,_Result> + constant2(const _Result& __val) + { return constant_binary_fun<_Result, _Result, _Result>(__val); } + /** @} */ + + /** The @c subtractive_rng class is documented on + * SGI's site. + * Note that this code assumes that @c int is 32 bits. + * + * @ingroup SGIextensions + */ + class subtractive_rng + : public std::unary_function + { + private: + unsigned int _M_table[55]; + std::size_t _M_index1; + std::size_t _M_index2; + + public: + /// Returns a number less than the argument. + unsigned int + operator()(unsigned int __limit) + { + _M_index1 = (_M_index1 + 1) % 55; + _M_index2 = (_M_index2 + 1) % 55; + _M_table[_M_index1] = _M_table[_M_index1] - _M_table[_M_index2]; + return _M_table[_M_index1] % __limit; + } + + void + _M_initialize(unsigned int __seed) + { + unsigned int __k = 1; + _M_table[54] = __seed; + std::size_t __i; + for (__i = 0; __i < 54; __i++) + { + std::size_t __ii = (21 * (__i + 1) % 55) - 1; + _M_table[__ii] = __k; + __k = __seed - __k; + __seed = _M_table[__ii]; + } + for (int __loop = 0; __loop < 4; __loop++) + { + for (__i = 0; __i < 55; __i++) + _M_table[__i] = _M_table[__i] - _M_table[(1 + __i + 30) % 55]; + } + _M_index1 = 0; + _M_index2 = 31; + } + + /// Ctor allowing you to initialize the seed. + subtractive_rng(unsigned int __seed) + { _M_initialize(__seed); } + + /// Default ctor; initializes its state with some number you don't see. + subtractive_rng() + { _M_initialize(161803398u); } + }; + + // Mem_fun adaptor helper functions mem_fun1 and mem_fun1_ref, + // provided for backward compatibility, they are no longer part of + // the C++ standard. + + template + inline std::mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun1(_Ret (_Tp::*__f)(_Arg)) + { return std::mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + inline std::const_mem_fun1_t<_Ret, _Tp, _Arg> + mem_fun1(_Ret (_Tp::*__f)(_Arg) const) + { return std::const_mem_fun1_t<_Ret, _Tp, _Arg>(__f); } + + template + inline std::mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun1_ref(_Ret (_Tp::*__f)(_Arg)) + { return std::mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + + template + inline std::const_mem_fun1_ref_t<_Ret, _Tp, _Arg> + mem_fun1_ref(_Ret (_Tp::*__f)(_Arg) const) + { return std::const_mem_fun1_ref_t<_Ret, _Tp, _Arg>(__f); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/ext/hash_map b/resources/sources/avr-libstdcpp/include/ext/hash_map new file mode 100644 index 000000000..93db70d56 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/hash_map @@ -0,0 +1,599 @@ +// Hashing map implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_map + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_MAP +#define _BACKWARD_HASH_MAP 1 + +#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH +#include +#endif + +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::equal_to; + using std::allocator; + using std::pair; + using std::_Select1st; + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Key>, class _Alloc = allocator<_Tp> > + class hash_map + { + private: + typedef hashtable,_Key, _HashFn, + _Select1st >, + _EqualKey, _Alloc> _Ht; + + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_map() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_map(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_map(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_map(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_map(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_map(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_map& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator== (const hash_map<_K1, _T1, _HF, _EqK, _Al>&, + const hash_map<_K1, _T1, _HF, _EqK, _Al>&); + + iterator + begin() + { return _M_ht.begin(); } + + iterator + end() + { return _M_ht.end(); } + + const_iterator + begin() const + { return _M_ht.begin(); } + + const_iterator + end() const + { return _M_ht.end(); } + + pair + insert(const value_type& __obj) + { return _M_ht.insert_unique(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f, __l); } + + pair + insert_noresize(const value_type& __obj) + { return _M_ht.insert_unique_noresize(__obj); } + + iterator + find(const key_type& __key) + { return _M_ht.find(__key); } + + const_iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + _Tp& + operator[](const key_type& __key) + { return _M_ht.find_or_insert(value_type(__key, _Tp())).second; } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + {return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { return __hm1._M_ht == __hm2._M_ht; } + + template + inline bool + operator!=(const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + const hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { return !(__hm1 == __hm2); } + + template + inline void + swap(hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + hash_map<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { __hm1.swap(__hm2); } + + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Key>, + class _Alloc = allocator<_Tp> > + class hash_multimap + { + // concept requirements + __glibcxx_class_requires(_Key, _SGIAssignableConcept) + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFn, size_t, _Key, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Key, _Key, _BinaryPredicateConcept) + + private: + typedef hashtable, _Key, _HashFn, + _Select1st >, _EqualKey, _Alloc> + _Ht; + + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef _Tp data_type; + typedef _Tp mapped_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Ht::pointer pointer; + typedef typename _Ht::const_pointer const_pointer; + typedef typename _Ht::reference reference; + typedef typename _Ht::const_reference const_reference; + + typedef typename _Ht::iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_multimap() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_multimap(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_multimap(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_multimap(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_multimap(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multimap(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_multimap& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator==(const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&, + const hash_multimap<_K1, _T1, _HF, _EqK, _Al>&); + + iterator + begin() + { return _M_ht.begin(); } + + iterator + end() + { return _M_ht.end(); } + + const_iterator + begin() const + { return _M_ht.begin(); } + + const_iterator + end() const + { return _M_ht.end(); } + + iterator + insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } + + iterator + insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator + find(const key_type& __key) + { return _M_ht.find(__key); } + + const_iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) + { return _M_ht.equal_range(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + { return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, + const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) + { return __hm1._M_ht == __hm2._M_ht; } + + template + inline bool + operator!=(const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm1, + const hash_multimap<_Key, _Tp, _HF, _EqKey, _Alloc>& __hm2) + { return !(__hm1 == __hm2); } + + template + inline void + swap(hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm1, + hash_multimap<_Key, _Tp, _HashFn, _EqlKey, _Alloc>& __hm2) + { __hm1.swap(__hm2); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that it will work for hash_map + // and hash_multimap. + template + class insert_iterator<__gnu_cxx::hash_map<_Key, _Tp, _HashFn, + _EqKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_map<_Key, _Tp, _HashFn, _EqKey, _Alloc> + _Container; + _Container* container; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + + template + class insert_iterator<__gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, + _EqKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_multimap<_Key, _Tp, _HashFn, _EqKey, _Alloc> + _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/hash_set b/resources/sources/avr-libstdcpp/include/ext/hash_set new file mode 100644 index 000000000..0b99302af --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/hash_set @@ -0,0 +1,569 @@ +// Hashing set implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file backward/hash_set + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _BACKWARD_HASH_SET +#define _BACKWARD_HASH_SET 1 + +#ifndef _GLIBCXX_PERMIT_BACKWARD_HASH +#include +#endif + +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::equal_to; + using std::allocator; + using std::pair; + using std::_Identity; + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Value>, + class _Alloc = allocator<_Value> > + class hash_set + { + // concept requirements + __glibcxx_class_requires(_Value, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) + + typedef __alloc_traits<_Alloc> _Alloc_traits; + + private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Alloc_traits::pointer pointer; + typedef typename _Alloc_traits::const_pointer const_pointer; + typedef typename _Alloc_traits::reference reference; + typedef typename _Alloc_traits::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_set() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_set(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_set(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_set(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_set(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_unique(__f, __l); } + + template + hash_set(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_unique(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_set& __hs) + { _M_ht.swap(__hs._M_ht); } + + template + friend bool + operator==(const hash_set<_Val, _HF, _EqK, _Al>&, + const hash_set<_Val, _HF, _EqK, _Al>&); + + iterator + begin() const + { return _M_ht.begin(); } + + iterator + end() const + { return _M_ht.end(); } + + pair + insert(const value_type& __obj) + { + pair __p = _M_ht.insert_unique(__obj); + return pair(__p.first, __p.second); + } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_unique(__f, __l); } + + pair + insert_noresize(const value_type& __obj) + { + pair __p + = _M_ht.insert_unique_noresize(__obj); + return pair(__p.first, __p.second); + } + + iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + {return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return __hs1._M_ht == __hs2._M_ht; } + + template + inline bool + operator!=(const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_set<_Value, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return !(__hs1 == __hs2); } + + template + inline void + swap(hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + hash_set<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { __hs1.swap(__hs2); } + + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template, + class _EqualKey = equal_to<_Value>, + class _Alloc = allocator<_Value> > + class hash_multiset + { + // concept requirements + __glibcxx_class_requires(_Value, _SGIAssignableConcept) + __glibcxx_class_requires3(_HashFcn, size_t, _Value, _UnaryFunctionConcept) + __glibcxx_class_requires3(_EqualKey, _Value, _Value, _BinaryPredicateConcept) + + private: + typedef hashtable<_Value, _Value, _HashFcn, _Identity<_Value>, + _EqualKey, _Alloc> _Ht; + _Ht _M_ht; + + public: + typedef typename _Ht::key_type key_type; + typedef typename _Ht::value_type value_type; + typedef typename _Ht::hasher hasher; + typedef typename _Ht::key_equal key_equal; + + typedef typename _Ht::size_type size_type; + typedef typename _Ht::difference_type difference_type; + typedef typename _Alloc::pointer pointer; + typedef typename _Alloc::const_pointer const_pointer; + typedef typename _Alloc::reference reference; + typedef typename _Alloc::const_reference const_reference; + + typedef typename _Ht::const_iterator iterator; + typedef typename _Ht::const_iterator const_iterator; + + typedef typename _Ht::allocator_type allocator_type; + + hasher + hash_funct() const + { return _M_ht.hash_funct(); } + + key_equal + key_eq() const + { return _M_ht.key_eq(); } + + allocator_type + get_allocator() const + { return _M_ht.get_allocator(); } + + hash_multiset() + : _M_ht(100, hasher(), key_equal(), allocator_type()) {} + + explicit + hash_multiset(size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) {} + + hash_multiset(size_type __n, const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) {} + + hash_multiset(size_type __n, const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) {} + + template + hash_multiset(_InputIterator __f, _InputIterator __l) + : _M_ht(100, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n) + : _M_ht(__n, hasher(), key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf) + : _M_ht(__n, __hf, key_equal(), allocator_type()) + { _M_ht.insert_equal(__f, __l); } + + template + hash_multiset(_InputIterator __f, _InputIterator __l, size_type __n, + const hasher& __hf, const key_equal& __eql, + const allocator_type& __a = allocator_type()) + : _M_ht(__n, __hf, __eql, __a) + { _M_ht.insert_equal(__f, __l); } + + size_type + size() const + { return _M_ht.size(); } + + size_type + max_size() const + { return _M_ht.max_size(); } + + _GLIBCXX_NODISCARD bool + empty() const + { return _M_ht.empty(); } + + void + swap(hash_multiset& hs) + { _M_ht.swap(hs._M_ht); } + + template + friend bool + operator==(const hash_multiset<_Val, _HF, _EqK, _Al>&, + const hash_multiset<_Val, _HF, _EqK, _Al>&); + + iterator + begin() const + { return _M_ht.begin(); } + + iterator + end() const + { return _M_ht.end(); } + + iterator + insert(const value_type& __obj) + { return _M_ht.insert_equal(__obj); } + + template + void + insert(_InputIterator __f, _InputIterator __l) + { _M_ht.insert_equal(__f,__l); } + + iterator + insert_noresize(const value_type& __obj) + { return _M_ht.insert_equal_noresize(__obj); } + + iterator + find(const key_type& __key) const + { return _M_ht.find(__key); } + + size_type + count(const key_type& __key) const + { return _M_ht.count(__key); } + + pair + equal_range(const key_type& __key) const + { return _M_ht.equal_range(__key); } + + size_type + erase(const key_type& __key) + { return _M_ht.erase(__key); } + + void + erase(iterator __it) + { _M_ht.erase(__it); } + + void + erase(iterator __f, iterator __l) + { _M_ht.erase(__f, __l); } + + void + clear() + { _M_ht.clear(); } + + void + resize(size_type __hint) + { _M_ht.resize(__hint); } + + size_type + bucket_count() const + { return _M_ht.bucket_count(); } + + size_type + max_bucket_count() const + { return _M_ht.max_bucket_count(); } + + size_type + elems_in_bucket(size_type __n) const + { return _M_ht.elems_in_bucket(__n); } + }; + + template + inline bool + operator==(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return __hs1._M_ht == __hs2._M_ht; } + + template + inline bool + operator!=(const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + const hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { return !(__hs1 == __hs2); } + + template + inline void + swap(hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs1, + hash_multiset<_Val, _HashFcn, _EqualKey, _Alloc>& __hs2) + { __hs1.swap(__hs2); } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that it will work for hash_set + // and hash_multiset. + template + class insert_iterator<__gnu_cxx::hash_set<_Value, _HashFcn, + _EqualKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_set<_Value, _HashFcn, _EqualKey, _Alloc> + _Container; + _Container* container; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + + template + class insert_iterator<__gnu_cxx::hash_multiset<_Value, _HashFcn, + _EqualKey, _Alloc> > + { + protected: + typedef __gnu_cxx::hash_multiset<_Value, _HashFcn, _EqualKey, _Alloc> + _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x) + : container(&__x) {} + + insert_iterator(_Container& __x, typename _Container::iterator) + : container(&__x) {} + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + container->insert(__value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/iterator b/resources/sources/avr-libstdcpp/include/ext/iterator new file mode 100644 index 000000000..acfb353a9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/iterator @@ -0,0 +1,116 @@ +// HP/SGI iterator extensions -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996-1998 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/iterator + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_ITERATOR +#define _EXT_ITERATOR 1 + +#pragma GCC system_header + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // There are two signatures for distance. In addition to the one + // taking two iterators and returning a result, there is another + // taking two iterators and a reference-to-result variable, and + // returning nothing. The latter seems to be an SGI extension. + // -- pedwards + template + inline void + __distance(_InputIterator __first, _InputIterator __last, + _Distance& __n, std::input_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_InputIteratorConcept<_InputIterator>) + while (__first != __last) + { + ++__first; + ++__n; + } + } + + template + inline void + __distance(_RandomAccessIterator __first, _RandomAccessIterator __last, + _Distance& __n, std::random_access_iterator_tag) + { + // concept requirements + __glibcxx_function_requires(_RandomAccessIteratorConcept< + _RandomAccessIterator>) + __n += __last - __first; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline void + distance(_InputIterator __first, _InputIterator __last, + _Distance& __n) + { + // concept requirements -- taken care of in __distance + __distance(__first, __last, __n, std::__iterator_category(__first)); + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h b/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h new file mode 100644 index 000000000..366c766f2 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/malloc_allocator.h @@ -0,0 +1,199 @@ +// Allocator that wraps "C" malloc -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/malloc_allocator.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _MALLOC_ALLOCATOR_H +#define _MALLOC_ALLOCATOR_H 1 + +#include +#include +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief An allocator that uses malloc. + * @ingroup allocators + * + * This is precisely the allocator defined in the C++ Standard. + * - all allocation calls malloc + * - all deallocation calls free + */ + template + class malloc_allocator + { + public: + typedef _Tp value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; +#if __cplusplus <= 201703L + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + + template + struct rebind + { typedef malloc_allocator<_Tp1> other; }; +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. propagate_on_container_move_assignment + typedef std::true_type propagate_on_container_move_assignment; +#endif + + _GLIBCXX20_CONSTEXPR + malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } + + _GLIBCXX20_CONSTEXPR + malloc_allocator(const malloc_allocator&) _GLIBCXX_USE_NOEXCEPT { } + + template + _GLIBCXX20_CONSTEXPR + malloc_allocator(const malloc_allocator<_Tp1>&) + _GLIBCXX_USE_NOEXCEPT { } + +#if __cplusplus <= 201703L + ~malloc_allocator() _GLIBCXX_USE_NOEXCEPT { } + + pointer + address(reference __x) const _GLIBCXX_NOEXCEPT + { return std::__addressof(__x); } + + const_pointer + address(const_reference __x) const _GLIBCXX_NOEXCEPT + { return std::__addressof(__x); } +#endif + + // NB: __n is permitted to be 0. The C++ standard says nothing + // about what the return value is when __n == 0. + _Tp* + allocate(size_type __n, const void* = 0) + { + if (__n > this->_M_max_size()) + std::__throw_bad_alloc(); + + _Tp* __ret = 0; +#if __cpp_aligned_new +#if __cplusplus > 201402L && _GLIBCXX_HAVE_ALIGNED_ALLOC + if (alignof(_Tp) > alignof(std::max_align_t)) + { + __ret = static_cast<_Tp*>(::aligned_alloc(alignof(_Tp), + __n * sizeof(_Tp))); + } +#else +# define _GLIBCXX_CHECK_MALLOC_RESULT +#endif +#endif + if (!__ret) + __ret = static_cast<_Tp*>(std::malloc(__n * sizeof(_Tp))); + if (!__ret) + std::__throw_bad_alloc(); +#ifdef _GLIBCXX_CHECK_MALLOC_RESULT +#undef _GLIBCXX_CHECK_MALLOC_RESULT + if (reinterpret_cast(__ret) % alignof(_Tp)) + { + // Memory returned by malloc is not suitably aligned for _Tp. + deallocate(__ret, __n); + std::__throw_bad_alloc(); + } +#endif + return __ret; + } + + // __p is not permitted to be a null pointer. + void + deallocate(_Tp* __p, size_type) + { std::free(static_cast(__p)); } + +#if __cplusplus <= 201703L + size_type + max_size() const _GLIBCXX_USE_NOEXCEPT + { return _M_max_size(); } + +#if __cplusplus >= 201103L + template + void + construct(_Up* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } + + template + void + destroy(_Up* __p) + noexcept(std::is_nothrow_destructible<_Up>::value) + { __p->~_Up(); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_] allocator::construct + void + construct(pointer __p, const _Tp& __val) + { ::new((void *)__p) value_type(__val); } + + void + destroy(pointer __p) { __p->~_Tp(); } +#endif +#endif // ! C++20 + + template + friend _GLIBCXX20_CONSTEXPR bool + operator==(const malloc_allocator&, const malloc_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + template + friend _GLIBCXX20_CONSTEXPR bool + operator!=(const malloc_allocator&, const malloc_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return false; } +#endif + + private: + _GLIBCXX_CONSTEXPR size_type + _M_max_size() const _GLIBCXX_USE_NOEXCEPT + { +#if __PTRDIFF_MAX__ < __SIZE_MAX__ + return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); +#else + return std::size_t(-1) / sizeof(_Tp); +#endif + } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/memory b/resources/sources/avr-libstdcpp/include/ext/memory new file mode 100644 index 000000000..f590fd98c --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/memory @@ -0,0 +1,200 @@ +// Memory extensions -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/memory + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_MEMORY +#define _EXT_MEMORY 1 + +#pragma GCC system_header + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + using std::_Temporary_buffer; + + template + std::pair<_InputIter, _ForwardIter> + __uninitialized_copy_n(_InputIter __first, _Size __count, + _ForwardIter __result, std::input_iterator_tag) + { + _ForwardIter __cur = __result; + __try + { + for (; __count > 0 ; --__count, ++__first, ++__cur) + std::_Construct(&*__cur, *__first); + return std::pair<_InputIter, _ForwardIter>(__first, __cur); + } + __catch(...) + { + std::_Destroy(__result, __cur); + __throw_exception_again; + } + } + + template + inline std::pair<_RandomAccessIter, _ForwardIter> + __uninitialized_copy_n(_RandomAccessIter __first, _Size __count, + _ForwardIter __result, + std::random_access_iterator_tag) + { + _RandomAccessIter __last = __first + __count; + return (std::pair<_RandomAccessIter, _ForwardIter> + (__last, std::uninitialized_copy(__first, __last, __result))); + } + + template + inline std::pair<_InputIter, _ForwardIter> + __uninitialized_copy_n(_InputIter __first, _Size __count, + _ForwardIter __result) + { + return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result, + std::__iterator_category(__first)); + } + + /** + * @brief Copies the range [first,last) into result. + * @param __first An input iterator. + * @param __count Length + * @param __result An output iterator. + * @return __result + (__first + __count) + * @ingroup SGIextensions + * + * Like copy(), but does not require an initialized output range. + */ + template + inline std::pair<_InputIter, _ForwardIter> + uninitialized_copy_n(_InputIter __first, _Size __count, + _ForwardIter __result) + { + return __gnu_cxx::__uninitialized_copy_n(__first, __count, __result, + std::__iterator_category(__first)); + } + + + // An alternative version of uninitialized_copy_n that constructs + // and destroys objects with a user-provided allocator. + template + std::pair<_InputIter, _ForwardIter> + __uninitialized_copy_n_a(_InputIter __first, _Size __count, + _ForwardIter __result, + _Allocator __alloc) + { + _ForwardIter __cur = __result; + __try + { + for (; __count > 0 ; --__count, ++__first, ++__cur) + __alloc.construct(&*__cur, *__first); + return std::pair<_InputIter, _ForwardIter>(__first, __cur); + } + __catch(...) + { + std::_Destroy(__result, __cur, __alloc); + __throw_exception_again; + } + } + + template + inline std::pair<_InputIter, _ForwardIter> + __uninitialized_copy_n_a(_InputIter __first, _Size __count, + _ForwardIter __result, + std::allocator<_Tp>) + { + return __gnu_cxx::uninitialized_copy_n(__first, __count, __result); + } + + /** + * This class provides similar behavior and semantics of the standard + * functions get_temporary_buffer() and return_temporary_buffer(), but + * encapsulated in a type vaguely resembling a standard container. + * + * By default, a temporary_buffer stores space for objects of + * whatever type the Iter iterator points to. It is constructed from a + * typical [first,last) range, and provides the begin(), end(), size() + * functions, as well as requested_size(). For non-trivial types, copies + * of *first will be used to initialize the storage. + * + * @c malloc is used to obtain underlying storage. + * + * Like get_temporary_buffer(), not all the requested memory may be + * available. Ideally, the created buffer will be large enough to hold a + * copy of [first,last), but if size() is less than requested_size(), + * then this didn't happen. + * + * @ingroup SGIextensions + */ + template ::value_type > + struct temporary_buffer : public _Temporary_buffer<_ForwardIterator, _Tp> + { + /// Requests storage large enough to hold a copy of [first,last). + temporary_buffer(_ForwardIterator __first, _ForwardIterator __last) + : _Temporary_buffer<_ForwardIterator, _Tp>(__first, + std::distance(__first, __last)) + { } + + /// Destroys objects and frees storage. + ~temporary_buffer() { } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + diff --git a/resources/sources/avr-libstdcpp/include/ext/new_allocator.h b/resources/sources/avr-libstdcpp/include/ext/new_allocator.h new file mode 100644 index 000000000..131718b8b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/new_allocator.h @@ -0,0 +1,198 @@ +// Allocator that wraps operator new -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/new_allocator.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _NEW_ALLOCATOR_H +#define _NEW_ALLOCATOR_H 1 + +#include +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief An allocator that uses global new, as per [20.4]. + * @ingroup allocators + * + * This is precisely the allocator defined in the C++ Standard. + * - all allocation calls operator new + * - all deallocation calls operator delete + * + * @tparam _Tp Type of allocated object. + */ + template + class new_allocator + { + public: + typedef _Tp value_type; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; +#if __cplusplus <= 201703L + typedef _Tp* pointer; + typedef const _Tp* const_pointer; + typedef _Tp& reference; + typedef const _Tp& const_reference; + + template + struct rebind + { typedef new_allocator<_Tp1> other; }; +#endif + +#if __cplusplus >= 201103L + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2103. propagate_on_container_move_assignment + typedef std::true_type propagate_on_container_move_assignment; +#endif + + _GLIBCXX20_CONSTEXPR + new_allocator() _GLIBCXX_USE_NOEXCEPT { } + + _GLIBCXX20_CONSTEXPR + new_allocator(const new_allocator&) _GLIBCXX_USE_NOEXCEPT { } + + template + _GLIBCXX20_CONSTEXPR + new_allocator(const new_allocator<_Tp1>&) _GLIBCXX_USE_NOEXCEPT { } + +#if __cplusplus <= 201703L + ~new_allocator() _GLIBCXX_USE_NOEXCEPT { } + + pointer + address(reference __x) const _GLIBCXX_NOEXCEPT + { return std::__addressof(__x); } + + const_pointer + address(const_reference __x) const _GLIBCXX_NOEXCEPT + { return std::__addressof(__x); } +#endif + + // NB: __n is permitted to be 0. The C++ standard says nothing + // about what the return value is when __n == 0. + _GLIBCXX_NODISCARD _Tp* + allocate(size_type __n, const void* = static_cast(0)) + { + if (__n > this->_M_max_size()) + std::__throw_bad_alloc(); + +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + std::align_val_t __al = std::align_val_t(alignof(_Tp)); + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp), __al)); + } +#endif + return static_cast<_Tp*>(::operator new(__n * sizeof(_Tp))); + } + + // __p is not permitted to be a null pointer. + void + deallocate(_Tp* __p, size_type __t) + { +#if __cpp_aligned_new + if (alignof(_Tp) > __STDCPP_DEFAULT_NEW_ALIGNMENT__) + { + ::operator delete(__p, +# if __cpp_sized_deallocation + __t * sizeof(_Tp), +# endif + std::align_val_t(alignof(_Tp))); + return; + } +#endif + ::operator delete(__p +#if __cpp_sized_deallocation + , __t * sizeof(_Tp) +#endif + ); + } + +#if __cplusplus <= 201703L + size_type + max_size() const _GLIBCXX_USE_NOEXCEPT + { return _M_max_size(); } + +#if __cplusplus >= 201103L + template + void + construct(_Up* __p, _Args&&... __args) + noexcept(std::is_nothrow_constructible<_Up, _Args...>::value) + { ::new((void *)__p) _Up(std::forward<_Args>(__args)...); } + + template + void + destroy(_Up* __p) + noexcept(std::is_nothrow_destructible<_Up>::value) + { __p->~_Up(); } +#else + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 402. wrong new expression in [some_] allocator::construct + void + construct(pointer __p, const _Tp& __val) + { ::new((void *)__p) _Tp(__val); } + + void + destroy(pointer __p) { __p->~_Tp(); } +#endif +#endif // ! C++20 + + template + friend _GLIBCXX20_CONSTEXPR bool + operator==(const new_allocator&, const new_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return true; } + +#if __cpp_impl_three_way_comparison < 201907L + template + friend _GLIBCXX20_CONSTEXPR bool + operator!=(const new_allocator&, const new_allocator<_Up>&) + _GLIBCXX_NOTHROW + { return false; } +#endif + + private: + _GLIBCXX_CONSTEXPR size_type + _M_max_size() const _GLIBCXX_USE_NOEXCEPT + { +#if __PTRDIFF_MAX__ < __SIZE_MAX__ + return std::size_t(__PTRDIFF_MAX__) / sizeof(_Tp); +#else + return std::size_t(-1) / sizeof(_Tp); +#endif + } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/numeric b/resources/sources/avr-libstdcpp/include/ext/numeric new file mode 100644 index 000000000..f437ecafd --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/numeric @@ -0,0 +1,152 @@ +// Numeric extensions -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/numeric + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _EXT_NUMERIC +#define _EXT_NUMERIC 1 + +#pragma GCC system_header + +#include +#include + +#include // For identity_element + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Returns __x ** __n, where __n >= 0. _Note that "multiplication" + // is required to be associative, but not necessarily commutative. + template + _Tp + __power(_Tp __x, _Integer __n, _MonoidOperation __monoid_op) + { + if (__n == 0) + return identity_element(__monoid_op); + else + { + while ((__n & 1) == 0) + { + __n >>= 1; + __x = __monoid_op(__x, __x); + } + + _Tp __result = __x; + __n >>= 1; + while (__n != 0) + { + __x = __monoid_op(__x, __x); + if ((__n & 1) != 0) + __result = __monoid_op(__result, __x); + __n >>= 1; + } + return __result; + } + } + + template + inline _Tp + __power(_Tp __x, _Integer __n) + { return __power(__x, __n, std::multiplies<_Tp>()); } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + // Alias for the internal name __power. Note that power is an extension, + // not part of the C++ standard. + template + inline _Tp + power(_Tp __x, _Integer __n, _MonoidOperation __monoid_op) + { return __power(__x, __n, __monoid_op); } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template + inline _Tp + power(_Tp __x, _Integer __n) + { return __power(__x, __n); } + +#if __cplusplus >= 201103L + using std::iota; +#else + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + // iota is not part of the standard until C++11. It is an extension. + template + void + iota(_ForwardIter __first, _ForwardIter __last, _Tp __value) + { + // concept requirements + __glibcxx_function_requires(_Mutable_ForwardIteratorConcept<_ForwardIter>) + __glibcxx_function_requires(_ConvertibleConcept<_Tp, + typename std::iterator_traits<_ForwardIter>::value_type>) + + while (__first != __last) + *__first++ = __value++; + } +#endif // C++11 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h b/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h new file mode 100644 index 000000000..69f286d7b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/numeric_traits.h @@ -0,0 +1,148 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software +// Foundation; either version 3, or (at your option) any later +// version. + +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/numeric_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_NUMERIC_TRAITS +#define _EXT_NUMERIC_TRAITS 1 + +#pragma GCC system_header + +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Compile time constants for builtin types. + // In C++98 std::numeric_limits member functions cannot be used for this. +#define __glibcxx_signed(_Tp) ((_Tp)(-1) < 0) +#define __glibcxx_digits(_Tp) \ + (sizeof(_Tp) * __CHAR_BIT__ - __glibcxx_signed(_Tp)) + +#define __glibcxx_min(_Tp) \ + (__glibcxx_signed(_Tp) ? -__glibcxx_max(_Tp) - 1 : (_Tp)0) + +#define __glibcxx_max(_Tp) \ + (__glibcxx_signed(_Tp) ? \ + (((((_Tp)1 << (__glibcxx_digits(_Tp) - 1)) - 1) << 1) + 1) : ~(_Tp)0) + + template + struct __numeric_traits_integer + { +#if __cplusplus >= 201103L + static_assert(std::__is_integer<_Value>::__value, + "invalid specialization"); +#endif + + // Only integers for initialization of member constant. + static const _Value __min = __glibcxx_min(_Value); + static const _Value __max = __glibcxx_max(_Value); + + // NB: these two also available in std::numeric_limits as compile + // time constants, but is big and we avoid including it. + static const bool __is_signed = __glibcxx_signed(_Value); + static const int __digits = __glibcxx_digits(_Value); + }; + + template + const _Value __numeric_traits_integer<_Value>::__min; + + template + const _Value __numeric_traits_integer<_Value>::__max; + + template + const bool __numeric_traits_integer<_Value>::__is_signed; + + template + const int __numeric_traits_integer<_Value>::__digits; + +#if __cplusplus >= 201103L + template + using __int_traits = __numeric_traits_integer<_Tp>; +#endif + +#undef __glibcxx_signed +#undef __glibcxx_digits +#undef __glibcxx_min +#undef __glibcxx_max + +#define __glibcxx_floating(_Tp, _Fval, _Dval, _LDval) \ + (std::__are_same<_Tp, float>::__value ? _Fval \ + : std::__are_same<_Tp, double>::__value ? _Dval : _LDval) + +#define __glibcxx_max_digits10(_Tp) \ + (2 + __glibcxx_floating(_Tp, __FLT_MANT_DIG__, __DBL_MANT_DIG__, \ + __LDBL_MANT_DIG__) * 643L / 2136) + +#define __glibcxx_digits10(_Tp) \ + __glibcxx_floating(_Tp, __FLT_DIG__, __DBL_DIG__, __LDBL_DIG__) + +#define __glibcxx_max_exponent10(_Tp) \ + __glibcxx_floating(_Tp, __FLT_MAX_10_EXP__, __DBL_MAX_10_EXP__, \ + __LDBL_MAX_10_EXP__) + + template + struct __numeric_traits_floating + { + // Only floating point types. See N1822. + static const int __max_digits10 = __glibcxx_max_digits10(_Value); + + // See above comment... + static const bool __is_signed = true; + static const int __digits10 = __glibcxx_digits10(_Value); + static const int __max_exponent10 = __glibcxx_max_exponent10(_Value); + }; + + template + const int __numeric_traits_floating<_Value>::__max_digits10; + + template + const bool __numeric_traits_floating<_Value>::__is_signed; + + template + const int __numeric_traits_floating<_Value>::__digits10; + + template + const int __numeric_traits_floating<_Value>::__max_exponent10; + + template + struct __numeric_traits + : public __conditional_type::__value, + __numeric_traits_integer<_Value>, + __numeric_traits_floating<_Value> >::__type + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#undef __glibcxx_floating +#undef __glibcxx_max_digits10 +#undef __glibcxx_digits10 +#undef __glibcxx_max_exponent10 + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h b/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h new file mode 100644 index 000000000..fc68a7290 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/pod_char_traits.h @@ -0,0 +1,198 @@ +// POD character, std::char_traits specialization -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/pod_char_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +// Gabriel Dos Reis +// Benjamin Kosnik + +#ifndef _POD_CHAR_TRAITS_H +#define _POD_CHAR_TRAITS_H 1 + +#pragma GCC system_header + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // POD character abstraction. + // NB: The char_type parameter is a subset of int_type, as to allow + // int_type to properly hold the full range of char_type values as + // well as EOF. + /// @brief A POD class that serves as a character abstraction class. + template + struct character + { + typedef _Value value_type; + typedef _Int int_type; + typedef _St state_type; + typedef character<_Value, _Int, _St> char_type; + + value_type value; + + template + static char_type + from(const V2& v) + { + char_type ret = { static_cast(v) }; + return ret; + } + + template + static V2 + to(const char_type& c) + { + V2 ret = { static_cast(c.value) }; + return ret; + } + + }; + + template + inline bool + operator==(const character<_Value, _Int, _St>& lhs, + const character<_Value, _Int, _St>& rhs) + { return lhs.value == rhs.value; } + + template + inline bool + operator<(const character<_Value, _Int, _St>& lhs, + const character<_Value, _Int, _St>& rhs) + { return lhs.value < rhs.value; } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// char_traits<__gnu_cxx::character> specialization. + template + struct char_traits<__gnu_cxx::character<_Value, _Int, _St> > + { + typedef __gnu_cxx::character<_Value, _Int, _St> char_type; + typedef typename char_type::int_type int_type; + typedef typename char_type::state_type state_type; + typedef fpos pos_type; + typedef streamoff off_type; + + static void + assign(char_type& __c1, const char_type& __c2) + { __c1 = __c2; } + + static bool + eq(const char_type& __c1, const char_type& __c2) + { return __c1 == __c2; } + + static bool + lt(const char_type& __c1, const char_type& __c2) + { return __c1 < __c2; } + + static int + compare(const char_type* __s1, const char_type* __s2, size_t __n) + { + for (size_t __i = 0; __i < __n; ++__i) + if (!eq(__s1[__i], __s2[__i])) + return lt(__s1[__i], __s2[__i]) ? -1 : 1; + return 0; + } + + static size_t + length(const char_type* __s) + { + const char_type* __p = __s; + while (__p->value) + ++__p; + return (__p - __s); + } + + static const char_type* + find(const char_type* __s, size_t __n, const char_type& __a) + { + for (const char_type* __p = __s; size_t(__p - __s) < __n; ++__p) + if (*__p == __a) + return __p; + return 0; + } + + static char_type* + move(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; + return static_cast + (__builtin_memmove(__s1, __s2, __n * sizeof(char_type))); + } + + static char_type* + copy(char_type* __s1, const char_type* __s2, size_t __n) + { + if (__n == 0) + return __s1; + std::copy(__s2, __s2 + __n, __s1); + return __s1; + } + + static char_type* + assign(char_type* __s, size_t __n, char_type __a) + { + std::fill_n(__s, __n, __a); + return __s; + } + + static char_type + to_char_type(const int_type& __i) + { return char_type::template from(__i); } + + static int_type + to_int_type(const char_type& __c) + { return char_type::template to(__c); } + + static bool + eq_int_type(const int_type& __c1, const int_type& __c2) + { return __c1 == __c2; } + + static int_type + eof() + { + int_type __r = { static_cast::__value, + int_type, int>::__type>(-1) }; + return __r; + } + + static int_type + not_eof(const int_type& __c) + { return eq_int_type(__c, eof()) ? int_type() : __c; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/rb_tree b/resources/sources/avr-libstdcpp/include/ext/rb_tree new file mode 100644 index 000000000..036e959b1 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/rb_tree @@ -0,0 +1,93 @@ +// rb_tree extension -*- C++ -*- + +// Copyright (C) 2002-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file ext/rb_tree + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _RB_TREE +#define _RB_TREE 1 + +#pragma GCC system_header + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Class rb_tree is not part of the C++ standard. It is provided for + // compatibility with the HP STL. + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template > + struct rb_tree + : public std::_Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc> + { + typedef std::_Rb_tree<_Key, _Value, _KeyOfValue, _Compare, _Alloc> _Base; + typedef typename _Base::allocator_type allocator_type; + + rb_tree(const _Compare& __comp = _Compare(), + const allocator_type& __a = allocator_type()) + : _Base(__comp, __a) { } + + ~rb_tree() { } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/slist b/resources/sources/avr-libstdcpp/include/ext/slist new file mode 100644 index 000000000..03c550127 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/slist @@ -0,0 +1,1082 @@ +// Singly-linked list implementation -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file ext/slist + * This file is a GNU extension to the Standard C++ Library (possibly + * containing extensions from the HP/SGI STL subset). + */ + +#ifndef _SLIST +#define _SLIST 1 + +#include +#include +#include +#include +#include +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + struct _Slist_node_base + { + _Slist_node_base* _M_next; + }; + + inline _Slist_node_base* + __slist_make_link(_Slist_node_base* __prev_node, + _Slist_node_base* __new_node) + { + __new_node->_M_next = __prev_node->_M_next; + __prev_node->_M_next = __new_node; + return __new_node; + } + + inline _Slist_node_base* + __slist_previous(_Slist_node_base* __head, + const _Slist_node_base* __node) + { + while (__head && __head->_M_next != __node) + __head = __head->_M_next; + return __head; + } + + inline const _Slist_node_base* + __slist_previous(const _Slist_node_base* __head, + const _Slist_node_base* __node) + { + while (__head && __head->_M_next != __node) + __head = __head->_M_next; + return __head; + } + + inline void + __slist_splice_after(_Slist_node_base* __pos, + _Slist_node_base* __before_first, + _Slist_node_base* __before_last) + { + if (__pos != __before_first && __pos != __before_last) + { + _Slist_node_base* __first = __before_first->_M_next; + _Slist_node_base* __after = __pos->_M_next; + __before_first->_M_next = __before_last->_M_next; + __pos->_M_next = __first; + __before_last->_M_next = __after; + } + } + + inline void + __slist_splice_after(_Slist_node_base* __pos, _Slist_node_base* __head) + { + _Slist_node_base* __before_last = __slist_previous(__head, 0); + if (__before_last != __head) + { + _Slist_node_base* __after = __pos->_M_next; + __pos->_M_next = __head->_M_next; + __head->_M_next = 0; + __before_last->_M_next = __after; + } + } + + inline _Slist_node_base* + __slist_reverse(_Slist_node_base* __node) + { + _Slist_node_base* __result = __node; + __node = __node->_M_next; + __result->_M_next = 0; + while(__node) + { + _Slist_node_base* __next = __node->_M_next; + __node->_M_next = __result; + __result = __node; + __node = __next; + } + return __result; + } + + inline std::size_t + __slist_size(_Slist_node_base* __node) + { + std::size_t __result = 0; + for (; __node != 0; __node = __node->_M_next) + ++__result; + return __result; + } + + template + struct _Slist_node : public _Slist_node_base + { + _Tp _M_data; + }; + + struct _Slist_iterator_base + { + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + typedef std::forward_iterator_tag iterator_category; + + _Slist_node_base* _M_node; + + _Slist_iterator_base(_Slist_node_base* __x) + : _M_node(__x) {} + + void + _M_incr() + { _M_node = _M_node->_M_next; } + + bool + operator==(const _Slist_iterator_base& __x) const + { return _M_node == __x._M_node; } + + bool + operator!=(const _Slist_iterator_base& __x) const + { return _M_node != __x._M_node; } + }; + + template + struct _Slist_iterator : public _Slist_iterator_base + { + typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; + typedef _Slist_iterator<_Tp, _Ref, _Ptr> _Self; + + typedef _Tp value_type; + typedef _Ptr pointer; + typedef _Ref reference; + typedef _Slist_node<_Tp> _Node; + + explicit + _Slist_iterator(_Node* __x) + : _Slist_iterator_base(__x) {} + + _Slist_iterator() + : _Slist_iterator_base(0) {} + + _Slist_iterator(const iterator& __x) + : _Slist_iterator_base(__x._M_node) {} + + reference + operator*() const + { return ((_Node*) _M_node)->_M_data; } + + pointer + operator->() const + { return &(operator*()); } + + _Self& + operator++() + { + _M_incr(); + return *this; + } + + _Self + operator++(int) + { + _Self __tmp = *this; + _M_incr(); + return __tmp; + } + }; + + template + struct _Slist_base + : public __alloc_traits<_Alloc>::template rebind<_Slist_node<_Tp> >::other + { + typedef typename __alloc_traits<_Alloc>::template + rebind<_Slist_node<_Tp> >::other _Node_alloc; + typedef _Alloc allocator_type; + + allocator_type + get_allocator() const + { return *static_cast(this); } + + _Slist_base(const allocator_type& __a) + : _Node_alloc(__a) + { this->_M_head._M_next = 0; } + + ~_Slist_base() + { _M_erase_after(&this->_M_head, 0); } + + protected: + _Slist_node_base _M_head; + + _Slist_node<_Tp>* + _M_get_node() + { return _Node_alloc::allocate(1); } + + void + _M_put_node(_Slist_node<_Tp>* __p) + { _Node_alloc::deallocate(__p, 1); } + + protected: + _Slist_node_base* _M_erase_after(_Slist_node_base* __pos) + { + _Slist_node<_Tp>* __next = (_Slist_node<_Tp>*) (__pos->_M_next); + _Slist_node_base* __next_next = __next->_M_next; + __pos->_M_next = __next_next; + allocator_type __a = get_allocator(); + __alloc_traits::destroy(__a, &__next->_M_data); + _M_put_node(__next); + return __next_next; + } + _Slist_node_base* _M_erase_after(_Slist_node_base*, _Slist_node_base*); + }; + + template + _Slist_node_base* + _Slist_base<_Tp,_Alloc>::_M_erase_after(_Slist_node_base* __before_first, + _Slist_node_base* __last_node) + { + _Slist_node<_Tp>* __cur = (_Slist_node<_Tp>*) (__before_first->_M_next); + while (__cur != __last_node) + { + _Slist_node<_Tp>* __tmp = __cur; + __cur = (_Slist_node<_Tp>*) __cur->_M_next; + allocator_type __a = get_allocator(); + __alloc_traits::destroy(__a, &__tmp->_M_data); + _M_put_node(__tmp); + } + __before_first->_M_next = __last_node; + return __last_node; + } + + /** + * This is an SGI extension. + * @ingroup SGIextensions + * @doctodo + */ + template > + class slist : private _Slist_base<_Tp,_Alloc> + { + // concept requirements + __glibcxx_class_requires(_Tp, _SGIAssignableConcept) + + private: + typedef _Slist_base<_Tp,_Alloc> _Base; + + public: + typedef _Tp value_type; + typedef value_type* pointer; + typedef const value_type* const_pointer; + typedef value_type& reference; + typedef const value_type& const_reference; + typedef std::size_t size_type; + typedef std::ptrdiff_t difference_type; + + typedef _Slist_iterator<_Tp, _Tp&, _Tp*> iterator; + typedef _Slist_iterator<_Tp, const _Tp&, const _Tp*> const_iterator; + + typedef typename _Base::allocator_type allocator_type; + + allocator_type + get_allocator() const + { return _Base::get_allocator(); } + + private: + typedef _Slist_node<_Tp> _Node; + typedef _Slist_node_base _Node_base; + typedef _Slist_iterator_base _Iterator_base; + + _Node* + _M_create_node(const value_type& __x) + { + _Node* __node = this->_M_get_node(); + __try + { + allocator_type __a = get_allocator(); + __alloc_traits::construct(__a, &__node->_M_data, + __x); + __node->_M_next = 0; + } + __catch(...) + { + this->_M_put_node(__node); + __throw_exception_again; + } + return __node; + } + + _Node* + _M_create_node() + { + _Node* __node = this->_M_get_node(); + __try + { + allocator_type __a = get_allocator(); + __alloc_traits::construct(__a, &__node->_M_data, + value_type()); + __node->_M_next = 0; + } + __catch(...) + { + this->_M_put_node(__node); + __throw_exception_again; + } + return __node; + } + + public: + explicit + slist(const allocator_type& __a = allocator_type()) + : _Base(__a) {} + + slist(size_type __n, const value_type& __x, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { _M_insert_after_fill(&this->_M_head, __n, __x); } + + explicit + slist(size_type __n) + : _Base(allocator_type()) + { _M_insert_after_fill(&this->_M_head, __n, value_type()); } + + // We don't need any dispatching tricks here, because + // _M_insert_after_range already does them. + template + slist(_InputIterator __first, _InputIterator __last, + const allocator_type& __a = allocator_type()) + : _Base(__a) + { _M_insert_after_range(&this->_M_head, __first, __last); } + + slist(const slist& __x) + : _Base(__x.get_allocator()) + { _M_insert_after_range(&this->_M_head, __x.begin(), __x.end()); } + + slist& + operator= (const slist& __x); + + ~slist() {} + + public: + // assign(), a generalized assignment member function. Two + // versions: one that takes a count, and one that takes a range. + // The range version is a member template, so we dispatch on whether + // or not the type is an integer. + + void + assign(size_type __n, const _Tp& __val) + { _M_fill_assign(__n, __val); } + + void + _M_fill_assign(size_type __n, const _Tp& __val); + + template + void + assign(_InputIterator __first, _InputIterator __last) + { + typedef typename std::__is_integer<_InputIterator>::__type _Integral; + _M_assign_dispatch(__first, __last, _Integral()); + } + + template + void + _M_assign_dispatch(_Integer __n, _Integer __val, std::__true_type) + { _M_fill_assign((size_type) __n, (_Tp) __val); } + + template + void + _M_assign_dispatch(_InputIterator __first, _InputIterator __last, + std::__false_type); + + public: + + iterator + begin() + { return iterator((_Node*)this->_M_head._M_next); } + + const_iterator + begin() const + { return const_iterator((_Node*)this->_M_head._M_next);} + + iterator + end() + { return iterator(0); } + + const_iterator + end() const + { return const_iterator(0); } + + // Experimental new feature: before_begin() returns a + // non-dereferenceable iterator that, when incremented, yields + // begin(). This iterator may be used as the argument to + // insert_after, erase_after, etc. Note that even for an empty + // slist, before_begin() is not the same iterator as end(). It + // is always necessary to increment before_begin() at least once to + // obtain end(). + iterator + before_begin() + { return iterator((_Node*) &this->_M_head); } + + const_iterator + before_begin() const + { return const_iterator((_Node*) &this->_M_head); } + + size_type + size() const + { return __slist_size(this->_M_head._M_next); } + + size_type + max_size() const + { return size_type(-1); } + + _GLIBCXX_NODISCARD bool + empty() const + { return this->_M_head._M_next == 0; } + + void + swap(slist& __x) + { std::swap(this->_M_head._M_next, __x._M_head._M_next); } + + public: + + reference + front() + { return ((_Node*) this->_M_head._M_next)->_M_data; } + + const_reference + front() const + { return ((_Node*) this->_M_head._M_next)->_M_data; } + + void + push_front(const value_type& __x) + { __slist_make_link(&this->_M_head, _M_create_node(__x)); } + + void + push_front() + { __slist_make_link(&this->_M_head, _M_create_node()); } + + void + pop_front() + { + _Node* __node = (_Node*) this->_M_head._M_next; + this->_M_head._M_next = __node->_M_next; + allocator_type __a = get_allocator(); + __alloc_traits::destroy(__a, &__node->_M_data); + this->_M_put_node(__node); + } + + iterator + previous(const_iterator __pos) + { return iterator((_Node*) __slist_previous(&this->_M_head, + __pos._M_node)); } + + const_iterator + previous(const_iterator __pos) const + { return const_iterator((_Node*) __slist_previous(&this->_M_head, + __pos._M_node)); } + + private: + _Node* + _M_insert_after(_Node_base* __pos, const value_type& __x) + { return (_Node*) (__slist_make_link(__pos, _M_create_node(__x))); } + + _Node* + _M_insert_after(_Node_base* __pos) + { return (_Node*) (__slist_make_link(__pos, _M_create_node())); } + + void + _M_insert_after_fill(_Node_base* __pos, + size_type __n, const value_type& __x) + { + for (size_type __i = 0; __i < __n; ++__i) + __pos = __slist_make_link(__pos, _M_create_node(__x)); + } + + // Check whether it's an integral type. If so, it's not an iterator. + template + void + _M_insert_after_range(_Node_base* __pos, + _InIterator __first, _InIterator __last) + { + typedef typename std::__is_integer<_InIterator>::__type _Integral; + _M_insert_after_range(__pos, __first, __last, _Integral()); + } + + template + void + _M_insert_after_range(_Node_base* __pos, _Integer __n, _Integer __x, + std::__true_type) + { _M_insert_after_fill(__pos, __n, __x); } + + template + void + _M_insert_after_range(_Node_base* __pos, + _InIterator __first, _InIterator __last, + std::__false_type) + { + while (__first != __last) + { + __pos = __slist_make_link(__pos, _M_create_node(*__first)); + ++__first; + } + } + + public: + iterator + insert_after(iterator __pos, const value_type& __x) + { return iterator(_M_insert_after(__pos._M_node, __x)); } + + iterator + insert_after(iterator __pos) + { return insert_after(__pos, value_type()); } + + void + insert_after(iterator __pos, size_type __n, const value_type& __x) + { _M_insert_after_fill(__pos._M_node, __n, __x); } + + // We don't need any dispatching tricks here, because + // _M_insert_after_range already does them. + template + void + insert_after(iterator __pos, _InIterator __first, _InIterator __last) + { _M_insert_after_range(__pos._M_node, __first, __last); } + + iterator + insert(iterator __pos, const value_type& __x) + { return iterator(_M_insert_after(__slist_previous(&this->_M_head, + __pos._M_node), + __x)); } + + iterator + insert(iterator __pos) + { return iterator(_M_insert_after(__slist_previous(&this->_M_head, + __pos._M_node), + value_type())); } + + void + insert(iterator __pos, size_type __n, const value_type& __x) + { _M_insert_after_fill(__slist_previous(&this->_M_head, __pos._M_node), + __n, __x); } + + // We don't need any dispatching tricks here, because + // _M_insert_after_range already does them. + template + void + insert(iterator __pos, _InIterator __first, _InIterator __last) + { _M_insert_after_range(__slist_previous(&this->_M_head, __pos._M_node), + __first, __last); } + + public: + iterator + erase_after(iterator __pos) + { return iterator((_Node*) this->_M_erase_after(__pos._M_node)); } + + iterator + erase_after(iterator __before_first, iterator __last) + { + return iterator((_Node*) this->_M_erase_after(__before_first._M_node, + __last._M_node)); + } + + iterator + erase(iterator __pos) + { + return iterator((_Node*) this->_M_erase_after + (__slist_previous(&this->_M_head, __pos._M_node))); + } + + iterator + erase(iterator __first, iterator __last) + { + return iterator((_Node*) this->_M_erase_after + (__slist_previous(&this->_M_head, __first._M_node), + __last._M_node)); + } + + void + resize(size_type new_size, const _Tp& __x); + + void + resize(size_type new_size) + { resize(new_size, _Tp()); } + + void + clear() + { this->_M_erase_after(&this->_M_head, 0); } + + public: + // Moves the range [__before_first + 1, __before_last + 1) to *this, + // inserting it immediately after __pos. This is constant time. + void + splice_after(iterator __pos, + iterator __before_first, iterator __before_last) + { + if (__before_first != __before_last) + __slist_splice_after(__pos._M_node, __before_first._M_node, + __before_last._M_node); + } + + // Moves the element that follows __prev to *this, inserting it + // immediately after __pos. This is constant time. + void + splice_after(iterator __pos, iterator __prev) + { __slist_splice_after(__pos._M_node, + __prev._M_node, __prev._M_node->_M_next); } + + // Removes all of the elements from the list __x to *this, inserting + // them immediately after __pos. __x must not be *this. Complexity: + // linear in __x.size(). + void + splice_after(iterator __pos, slist& __x) + { __slist_splice_after(__pos._M_node, &__x._M_head); } + + // Linear in distance(begin(), __pos), and linear in __x.size(). + void + splice(iterator __pos, slist& __x) + { + if (__x._M_head._M_next) + __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), + &__x._M_head, + __slist_previous(&__x._M_head, 0)); } + + // Linear in distance(begin(), __pos), and in distance(__x.begin(), __i). + void + splice(iterator __pos, slist& __x, iterator __i) + { __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), + __slist_previous(&__x._M_head, __i._M_node), + __i._M_node); } + + // Linear in distance(begin(), __pos), in distance(__x.begin(), __first), + // and in distance(__first, __last). + void + splice(iterator __pos, slist& __x, iterator __first, iterator __last) + { + if (__first != __last) + __slist_splice_after(__slist_previous(&this->_M_head, __pos._M_node), + __slist_previous(&__x._M_head, __first._M_node), + __slist_previous(__first._M_node, + __last._M_node)); + } + + public: + void + reverse() + { + if (this->_M_head._M_next) + this->_M_head._M_next = __slist_reverse(this->_M_head._M_next); + } + + void + remove(const _Tp& __val); + + void + unique(); + + void + merge(slist& __x); + + void + sort(); + + template + void + remove_if(_Predicate __pred); + + template + void + unique(_BinaryPredicate __pred); + + template + void + merge(slist&, _StrictWeakOrdering); + + template + void + sort(_StrictWeakOrdering __comp); + }; + + template + slist<_Tp, _Alloc>& + slist<_Tp, _Alloc>::operator=(const slist<_Tp, _Alloc>& __x) + { + if (&__x != this) + { + _Node_base* __p1 = &this->_M_head; + _Node* __n1 = (_Node*) this->_M_head._M_next; + const _Node* __n2 = (const _Node*) __x._M_head._M_next; + while (__n1 && __n2) + { + __n1->_M_data = __n2->_M_data; + __p1 = __n1; + __n1 = (_Node*) __n1->_M_next; + __n2 = (const _Node*) __n2->_M_next; + } + if (__n2 == 0) + this->_M_erase_after(__p1, 0); + else + _M_insert_after_range(__p1, const_iterator((_Node*)__n2), + const_iterator(0)); + } + return *this; + } + + template + void + slist<_Tp, _Alloc>::_M_fill_assign(size_type __n, const _Tp& __val) + { + _Node_base* __prev = &this->_M_head; + _Node* __node = (_Node*) this->_M_head._M_next; + for (; __node != 0 && __n > 0; --__n) + { + __node->_M_data = __val; + __prev = __node; + __node = (_Node*) __node->_M_next; + } + if (__n > 0) + _M_insert_after_fill(__prev, __n, __val); + else + this->_M_erase_after(__prev, 0); + } + + template + template + void + slist<_Tp, _Alloc>::_M_assign_dispatch(_InputIterator __first, + _InputIterator __last, + std::__false_type) + { + _Node_base* __prev = &this->_M_head; + _Node* __node = (_Node*) this->_M_head._M_next; + while (__node != 0 && __first != __last) + { + __node->_M_data = *__first; + __prev = __node; + __node = (_Node*) __node->_M_next; + ++__first; + } + if (__first != __last) + _M_insert_after_range(__prev, __first, __last); + else + this->_M_erase_after(__prev, 0); + } + + template + inline bool + operator==(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { + typedef typename slist<_Tp,_Alloc>::const_iterator const_iterator; + const_iterator __end1 = _SL1.end(); + const_iterator __end2 = _SL2.end(); + + const_iterator __i1 = _SL1.begin(); + const_iterator __i2 = _SL2.begin(); + while (__i1 != __end1 && __i2 != __end2 && *__i1 == *__i2) + { + ++__i1; + ++__i2; + } + return __i1 == __end1 && __i2 == __end2; + } + + + template + inline bool + operator<(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return std::lexicographical_compare(_SL1.begin(), _SL1.end(), + _SL2.begin(), _SL2.end()); } + + template + inline bool + operator!=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return !(_SL1 == _SL2); } + + template + inline bool + operator>(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return _SL2 < _SL1; } + + template + inline bool + operator<=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return !(_SL2 < _SL1); } + + template + inline bool + operator>=(const slist<_Tp, _Alloc>& _SL1, const slist<_Tp, _Alloc>& _SL2) + { return !(_SL1 < _SL2); } + + template + inline void + swap(slist<_Tp, _Alloc>& __x, slist<_Tp, _Alloc>& __y) + { __x.swap(__y); } + + template + void + slist<_Tp, _Alloc>::resize(size_type __len, const _Tp& __x) + { + _Node_base* __cur = &this->_M_head; + while (__cur->_M_next != 0 && __len > 0) + { + --__len; + __cur = __cur->_M_next; + } + if (__cur->_M_next) + this->_M_erase_after(__cur, 0); + else + _M_insert_after_fill(__cur, __len, __x); + } + + template + void + slist<_Tp, _Alloc>::remove(const _Tp& __val) + { + _Node_base* __cur = &this->_M_head; + while (__cur && __cur->_M_next) + { + if (((_Node*) __cur->_M_next)->_M_data == __val) + this->_M_erase_after(__cur); + else + __cur = __cur->_M_next; + } + } + + template + void + slist<_Tp, _Alloc>::unique() + { + _Node_base* __cur = this->_M_head._M_next; + if (__cur) + { + while (__cur->_M_next) + { + if (((_Node*)__cur)->_M_data + == ((_Node*)(__cur->_M_next))->_M_data) + this->_M_erase_after(__cur); + else + __cur = __cur->_M_next; + } + } + } + + template + void + slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x) + { + _Node_base* __n1 = &this->_M_head; + while (__n1->_M_next && __x._M_head._M_next) + { + if (((_Node*) __x._M_head._M_next)->_M_data + < ((_Node*) __n1->_M_next)->_M_data) + __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); + __n1 = __n1->_M_next; + } + if (__x._M_head._M_next) + { + __n1->_M_next = __x._M_head._M_next; + __x._M_head._M_next = 0; + } + } + + template + void + slist<_Tp, _Alloc>::sort() + { + if (this->_M_head._M_next && this->_M_head._M_next->_M_next) + { + slist __carry; + slist __counter[64]; + int __fill = 0; + while (!empty()) + { + __slist_splice_after(&__carry._M_head, + &this->_M_head, this->_M_head._M_next); + int __i = 0; + while (__i < __fill && !__counter[__i].empty()) + { + __counter[__i].merge(__carry); + __carry.swap(__counter[__i]); + ++__i; + } + __carry.swap(__counter[__i]); + if (__i == __fill) + ++__fill; + } + + for (int __i = 1; __i < __fill; ++__i) + __counter[__i].merge(__counter[__i-1]); + this->swap(__counter[__fill-1]); + } + } + + template + template + void slist<_Tp, _Alloc>::remove_if(_Predicate __pred) + { + _Node_base* __cur = &this->_M_head; + while (__cur->_M_next) + { + if (__pred(((_Node*) __cur->_M_next)->_M_data)) + this->_M_erase_after(__cur); + else + __cur = __cur->_M_next; + } + } + + template + template + void + slist<_Tp, _Alloc>::unique(_BinaryPredicate __pred) + { + _Node* __cur = (_Node*) this->_M_head._M_next; + if (__cur) + { + while (__cur->_M_next) + { + if (__pred(((_Node*)__cur)->_M_data, + ((_Node*)(__cur->_M_next))->_M_data)) + this->_M_erase_after(__cur); + else + __cur = (_Node*) __cur->_M_next; + } + } + } + + template + template + void + slist<_Tp, _Alloc>::merge(slist<_Tp, _Alloc>& __x, + _StrictWeakOrdering __comp) + { + _Node_base* __n1 = &this->_M_head; + while (__n1->_M_next && __x._M_head._M_next) + { + if (__comp(((_Node*) __x._M_head._M_next)->_M_data, + ((_Node*) __n1->_M_next)->_M_data)) + __slist_splice_after(__n1, &__x._M_head, __x._M_head._M_next); + __n1 = __n1->_M_next; + } + if (__x._M_head._M_next) + { + __n1->_M_next = __x._M_head._M_next; + __x._M_head._M_next = 0; + } + } + + template + template + void + slist<_Tp, _Alloc>::sort(_StrictWeakOrdering __comp) + { + if (this->_M_head._M_next && this->_M_head._M_next->_M_next) + { + slist __carry; + slist __counter[64]; + int __fill = 0; + while (!empty()) + { + __slist_splice_after(&__carry._M_head, + &this->_M_head, this->_M_head._M_next); + int __i = 0; + while (__i < __fill && !__counter[__i].empty()) + { + __counter[__i].merge(__carry, __comp); + __carry.swap(__counter[__i]); + ++__i; + } + __carry.swap(__counter[__i]); + if (__i == __fill) + ++__fill; + } + + for (int __i = 1; __i < __fill; ++__i) + __counter[__i].merge(__counter[__i-1], __comp); + this->swap(__counter[__fill-1]); + } + } + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Specialization of insert_iterator so that insertions will be constant + // time rather than linear time. + template + class insert_iterator<__gnu_cxx::slist<_Tp, _Alloc> > + { + protected: + typedef __gnu_cxx::slist<_Tp, _Alloc> _Container; + _Container* container; + typename _Container::iterator iter; + + public: + typedef _Container container_type; + typedef output_iterator_tag iterator_category; + typedef void value_type; + typedef void difference_type; + typedef void pointer; + typedef void reference; + + insert_iterator(_Container& __x, typename _Container::iterator __i) + : container(&__x) + { + if (__i == __x.begin()) + iter = __x.before_begin(); + else + iter = __x.previous(__i); + } + + insert_iterator<_Container>& + operator=(const typename _Container::value_type& __value) + { + iter = container->insert_after(iter, __value); + return *this; + } + + insert_iterator<_Container>& + operator*() + { return *this; } + + insert_iterator<_Container>& + operator++() + { return *this; } + + insert_iterator<_Container>& + operator++(int) + { return *this; } + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/type_traits.h b/resources/sources/avr-libstdcpp/include/ext/type_traits.h new file mode 100644 index 000000000..cf773cf2d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/type_traits.h @@ -0,0 +1,221 @@ +// -*- C++ -*- + +// Copyright (C) 2005-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the terms +// of the GNU General Public License as published by the Free Software +// Foundation; either version 3, or (at your option) any later +// version. + +// This library is distributed in the hope that it will be useful, but +// WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +// General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file ext/type_traits.h + * This file is a GNU extension to the Standard C++ Library. + */ + +#ifndef _EXT_TYPE_TRAITS +#define _EXT_TYPE_TRAITS 1 + +#pragma GCC system_header + +#include +#include + +extern "C++" { + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + // Define a nested type if some predicate holds. + template + struct __enable_if + { }; + + template + struct __enable_if + { typedef _Tp __type; }; + + + // Conditional expression for types. If true, first, if false, second. + template + struct __conditional_type + { typedef _Iftrue __type; }; + + template + struct __conditional_type + { typedef _Iffalse __type; }; + + + // Given an integral builtin type, return the corresponding unsigned type. + template + struct __add_unsigned + { + private: + typedef __enable_if::__value, _Tp> __if_type; + + public: + typedef typename __if_type::__type __type; + }; + + template<> + struct __add_unsigned + { typedef unsigned char __type; }; + + template<> + struct __add_unsigned + { typedef unsigned char __type; }; + + template<> + struct __add_unsigned + { typedef unsigned short __type; }; + + template<> + struct __add_unsigned + { typedef unsigned int __type; }; + + template<> + struct __add_unsigned + { typedef unsigned long __type; }; + + template<> + struct __add_unsigned + { typedef unsigned long long __type; }; + + // Declare but don't define. + template<> + struct __add_unsigned; + + template<> + struct __add_unsigned; + + + // Given an integral builtin type, return the corresponding signed type. + template + struct __remove_unsigned + { + private: + typedef __enable_if::__value, _Tp> __if_type; + + public: + typedef typename __if_type::__type __type; + }; + + template<> + struct __remove_unsigned + { typedef signed char __type; }; + + template<> + struct __remove_unsigned + { typedef signed char __type; }; + + template<> + struct __remove_unsigned + { typedef short __type; }; + + template<> + struct __remove_unsigned + { typedef int __type; }; + + template<> + struct __remove_unsigned + { typedef long __type; }; + + template<> + struct __remove_unsigned + { typedef long long __type; }; + + // Declare but don't define. + template<> + struct __remove_unsigned; + + template<> + struct __remove_unsigned; + + + // For use in string and vstring. + template + inline bool + __is_null_pointer(_Type* __ptr) + { return __ptr == 0; } + + template + inline bool + __is_null_pointer(_Type) + { return false; } + +#if __cplusplus >= 201103L + inline bool + __is_null_pointer(std::nullptr_t) + { return true; } +#endif + + // For complex and cmath + template::__value> + struct __promote + { typedef double __type; }; + + // No nested __type member for non-integer non-floating point types, + // allows this type to be used for SFINAE to constrain overloads in + // and to only the intended types. + template + struct __promote<_Tp, false> + { }; + + template<> + struct __promote + { typedef long double __type; }; + + template<> + struct __promote + { typedef double __type; }; + + template<> + struct __promote + { typedef float __type; }; + + template::__type, + typename _Up2 = typename __promote<_Up>::__type> + struct __promote_2 + { + typedef __typeof__(_Tp2() + _Up2()) __type; + }; + + template::__type, + typename _Up2 = typename __promote<_Up>::__type, + typename _Vp2 = typename __promote<_Vp>::__type> + struct __promote_3 + { + typedef __typeof__(_Tp2() + _Up2() + _Vp2()) __type; + }; + + template::__type, + typename _Up2 = typename __promote<_Up>::__type, + typename _Vp2 = typename __promote<_Vp>::__type, + typename _Wp2 = typename __promote<_Wp>::__type> + struct __promote_4 + { + typedef __typeof__(_Tp2() + _Up2() + _Vp2() + _Wp2()) __type; + }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +} // extern "C++" + +#endif diff --git a/resources/sources/avr-libstdcpp/include/ext/typelist.h b/resources/sources/avr-libstdcpp/include/ext/typelist.h new file mode 100644 index 000000000..1835c141f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ext/typelist.h @@ -0,0 +1,538 @@ +// -*- C++ -*- + +// Copyright (C) 2005-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +// Copyright (C) 2004 Ami Tavory and Vladimir Dreizin, IBM-HRL. + +// Permission to use, copy, modify, sell, and distribute this software +// is hereby granted without fee, provided that the above copyright +// notice appears in all copies, and that both that copyright notice and +// this permission notice appear in supporting documentation. None of +// the above authors, nor IBM Haifa Research Laboratories, make any +// representation about the suitability of this software for any +// purpose. It is provided "as is" without express or implied warranty. + +/** + * @file ext/typelist.h + * This file is a GNU extension to the Standard C++ Library. + * + * Contains typelist_chain definitions. + * Typelists are an idea by Andrei Alexandrescu. + */ + +#ifndef _TYPELIST_H +#define _TYPELIST_H 1 + +#include + +namespace __gnu_cxx _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** @namespace __gnu_cxx::typelist + * @brief GNU typelist extensions for public compile-time use. +*/ +namespace typelist +{ + struct null_type { }; + + template + struct node + { + typedef Root root; + }; + + // Forward declarations of functors. + template + struct chain + { + typedef Hd head; + typedef Typelist tail; + }; + + // Apply all typelist types to unary functor. + template + void + apply(Fn&, Typelist); + + /// Apply all typelist types to generator functor. + template + void + apply_generator(Gn&, Typelist); + + // Apply all typelist types and values to generator functor. + template + void + apply_generator(Gn&, TypelistT, TypelistV); + + template + struct append; + + template + struct append_typelist; + + template + struct contains; + + template class Pred> + struct filter; + + template + struct at_index; + + template class Transform> + struct transform; + + template + struct flatten; + + template + struct from_first; + + template + struct create1; + + template + struct create2; + + template + struct create3; + + template + struct create4; + + template + struct create5; + + template + struct create6; + +namespace detail +{ + template + struct apply_; + + template + struct apply_ > + { + void + operator()(Fn& f) + { + f.operator()(Hd()); + apply_ next; + next(f); + } + }; + + template + struct apply_ + { + void + operator()(Fn&) { } + }; + + template + struct apply_generator1_; + + template + struct apply_generator1_ > + { + void + operator()(Gn& g) + { + g.template operator()(); + apply_generator1_ next; + next(g); + } + }; + + template + struct apply_generator1_ + { + void + operator()(Gn&) { } + }; + + template + struct apply_generator2_; + + template + struct apply_generator2_, chain > + { + void + operator()(Gn& g) + { + g.template operator()(); + apply_generator2_ next; + next(g); + } + }; + + template + struct apply_generator2_ + { + void + operator()(Gn&) { } + }; + + template + struct append_; + + template + struct append_, Typelist_Chain> + { + private: + typedef append_ append_type; + + public: + typedef chain type; + }; + + template + struct append_ + { + typedef Typelist_Chain type; + }; + + template + struct append_, null_type> + { + typedef chain type; + }; + + template<> + struct append_ + { + typedef null_type type; + }; + + template + struct append_typelist_; + + template + struct append_typelist_ > + { + typedef chain type; + }; + + template + struct append_typelist_ > + { + private: + typedef typename append_typelist_::type rest_type; + + public: + typedef typename append >::type::root type; + }; + + template + struct contains_; + + template + struct contains_ + { + enum + { + value = false + }; + }; + + template + struct contains_, T> + { + enum + { + value = contains_::value + }; + }; + + template + struct contains_, T> + { + enum + { + value = true + }; + }; + + template class Pred> + struct chain_filter_; + + template class Pred> + struct chain_filter_ + { + typedef null_type type; + }; + + template class Pred> + struct chain_filter_, Pred> + { + private: + enum + { + include_hd = Pred::value + }; + + typedef typename chain_filter_::type rest_type; + typedef chain chain_type; + + public: + typedef typename __conditional_type::__type type; + }; + + template + struct chain_at_index_; + + template + struct chain_at_index_, 0> + { + typedef Hd type; + }; + + template + struct chain_at_index_, i> + { + typedef typename chain_at_index_::type type; + }; + + template class Transform> + struct chain_transform_; + + template class Transform> + struct chain_transform_ + { + typedef null_type type; + }; + + template class Transform> + struct chain_transform_, Transform> + { + private: + typedef typename chain_transform_::type rest_type; + typedef typename Transform::type transform_type; + + public: + typedef chain type; + }; + + template + struct chain_flatten_; + + template + struct chain_flatten_ > + { + typedef typename Hd_Tl::root type; + }; + + template + struct chain_flatten_ > + { + private: + typedef typename chain_flatten_::type rest_type; + typedef append > append_type; + public: + typedef typename append_type::type::root type; + }; +} // namespace detail + +#define _GLIBCXX_TYPELIST_CHAIN1(X0) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN2(X0, X1) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN3(X0, X1, X2) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN4(X0, X1, X2, X3) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN5(X0, X1, X2, X3, X4) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN6(X0, X1, X2, X3, X4, X5) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN7(X0, X1, X2, X3, X4, X5, X6) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN8(X0, X1, X2, X3, X4, X5, X6, X7) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN9(X0, X1, X2, X3, X4, X5, X6, X7, X8) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN10(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN11(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN12(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN13(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN14(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN15(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN16(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN17(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN18(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN19(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18) __gnu_cxx::typelist::chain +#define _GLIBCXX_TYPELIST_CHAIN20(X0, X1, X2, X3, X4, X5, X6, X7, X8, X9, X10, X11, X12, X13, X14, X15, X16, X17, X18, X19) __gnu_cxx::typelist::chain + + template + void + apply(Fn& fn, Typelist) + { + detail::apply_ a; + a(fn); + } + + template + void + apply_generator(Fn& fn, Typelist) + { + detail::apply_generator1_ a; + a(fn); + } + + template + void + apply_generator(Fn& fn, TypelistT, TypelistV) + { + typedef typename TypelistT::root rootT; + typedef typename TypelistV::root rootV; + detail::apply_generator2_ a; + a(fn); + } + + template + struct append + { + private: + typedef typename Typelist0::root root0_type; + typedef typename Typelist1::root root1_type; + typedef detail::append_ append_type; + + public: + typedef node type; + }; + + template + struct append_typelist + { + private: + typedef typename Typelist_Typelist::root root_type; + typedef detail::append_typelist_ append_type; + + public: + typedef node type; + }; + + template + struct contains + { + private: + typedef typename Typelist::root root_type; + + public: + enum + { + value = detail::contains_::value + }; + }; + + template class Pred> + struct filter + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_filter_ filter_type; + + public: + typedef node type; + }; + + template + struct at_index + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_at_index_ index_type; + + public: + typedef typename index_type::type type; + }; + + template class Transform> + struct transform + { + private: + typedef typename Typelist::root root_type; + typedef detail::chain_transform_ transform_type; + + public: + typedef node type; + }; + + template + struct flatten + { + private: + typedef typename Typelist_Typelist::root root_type; + typedef typename detail::chain_flatten_::type flatten_type; + + public: + typedef node type; + }; + + template + struct from_first + { + private: + typedef typename at_index::type first_type; + + public: + typedef node > type; + }; + + template + struct create1 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN1(T1)> type; + }; + + template + struct create2 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN2(T1,T2)> type; + }; + + template + struct create3 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN3(T1,T2,T3)> type; + }; + + template + struct create4 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN4(T1,T2,T3,T4)> type; + }; + + template + struct create5 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN5(T1,T2,T3,T4,T5)> type; + }; + + template + struct create6 + { + typedef node<_GLIBCXX_TYPELIST_CHAIN6(T1,T2,T3,T4,T5,T6)> type; + }; +} // namespace typelist +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + + +#endif diff --git a/resources/sources/avr-libstdcpp/include/forward_list b/resources/sources/avr-libstdcpp/include/forward_list new file mode 100644 index 000000000..439ef6b38 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/forward_list @@ -0,0 +1,87 @@ +// -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/forward_list + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_FORWARD_LIST +#define _GLIBCXX_FORWARD_LIST 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template + using forward_list = std::forward_list<_Tp, polymorphic_allocator<_Tp>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_erase_if 202002L + + template + inline typename forward_list<_Tp, _Alloc>::size_type + erase_if(forward_list<_Tp, _Alloc>& __cont, _Predicate __pred) + { return __cont.remove_if(__pred); } + + template + inline typename forward_list<_Tp, _Alloc>::size_type + erase(forward_list<_Tp, _Alloc>& __cont, const _Up& __value) + { + using __elem_type = typename forward_list<_Tp, _Alloc>::value_type; + return std::erase_if(__cont, [&](__elem_type& __elem) { + return __elem == __value; + }); + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif // C++11 + +#endif // _GLIBCXX_FORWARD_LIST diff --git a/resources/sources/avr-libstdcpp/include/functional b/resources/sources/avr-libstdcpp/include/functional new file mode 100644 index 000000000..dc21c10b7 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/functional @@ -0,0 +1,1280 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file include/functional + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_FUNCTIONAL +#define _GLIBCXX_FUNCTIONAL 1 + +#pragma GCC system_header + +#include +#include + +#if __cplusplus >= 201103L + +#include +#include +#include +#include +#include +#include // std::reference_wrapper and _Mem_fn_traits +#include // std::function +#if __cplusplus > 201402L +# include +# include +# include +# include +# include +#endif +#if __cplusplus > 201703L +# include +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus >= 201703L +# define __cpp_lib_invoke 201411L +# if __cplusplus > 201703L +# define __cpp_lib_constexpr_functional 201907L +# endif + + /// Invoke a callable object. + template + inline _GLIBCXX20_CONSTEXPR invoke_result_t<_Callable, _Args...> + invoke(_Callable&& __fn, _Args&&... __args) + noexcept(is_nothrow_invocable_v<_Callable, _Args...>) + { + return std::__invoke(std::forward<_Callable>(__fn), + std::forward<_Args>(__args)...); + } +#endif // C++17 + + template::value> + class _Mem_fn_base + : public _Mem_fn_traits<_MemFunPtr>::__maybe_type + { + using _Traits = _Mem_fn_traits<_MemFunPtr>; + + using _Arity = typename _Traits::__arity; + using _Varargs = typename _Traits::__vararg; + + template + friend struct _Bind_check_arity; + + _MemFunPtr _M_pmf; + + public: + + using result_type = typename _Traits::__result_type; + + explicit constexpr + _Mem_fn_base(_MemFunPtr __pmf) noexcept : _M_pmf(__pmf) { } + + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_Args&&... __args) const + noexcept(noexcept( + std::__invoke(_M_pmf, std::forward<_Args>(__args)...))) + -> decltype(std::__invoke(_M_pmf, std::forward<_Args>(__args)...)) + { return std::__invoke(_M_pmf, std::forward<_Args>(__args)...); } + }; + + // Partial specialization for member object pointers. + template + class _Mem_fn_base<_MemObjPtr, false> + { + using _Arity = integral_constant; + using _Varargs = false_type; + + template + friend struct _Bind_check_arity; + + _MemObjPtr _M_pm; + + public: + explicit constexpr + _Mem_fn_base(_MemObjPtr __pm) noexcept : _M_pm(__pm) { } + + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_Tp&& __obj) const + noexcept(noexcept(std::__invoke(_M_pm, std::forward<_Tp>(__obj)))) + -> decltype(std::__invoke(_M_pm, std::forward<_Tp>(__obj))) + { return std::__invoke(_M_pm, std::forward<_Tp>(__obj)); } + }; + + template + struct _Mem_fn; // undefined + + template + struct _Mem_fn<_Res _Class::*> + : _Mem_fn_base<_Res _Class::*> + { + using _Mem_fn_base<_Res _Class::*>::_Mem_fn_base; + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2048. Unnecessary mem_fn overloads + /** + * @brief Returns a function object that forwards to the member + * pointer @a pm. + * @ingroup functors + */ + template + _GLIBCXX20_CONSTEXPR + inline _Mem_fn<_Tp _Class::*> + mem_fn(_Tp _Class::* __pm) noexcept + { + return _Mem_fn<_Tp _Class::*>(__pm); + } + + /** + * @brief Determines if the given type _Tp is a function object that + * should be treated as a subexpression when evaluating calls to + * function objects returned by bind(). + * + * C++11 [func.bind.isbind]. + * @ingroup binders + */ + template + struct is_bind_expression + : public false_type { }; + + /** + * @brief Determines if the given type _Tp is a placeholder in a + * bind() expression and, if so, which placeholder it is. + * + * C++11 [func.bind.isplace]. + * @ingroup binders + */ + template + struct is_placeholder + : public integral_constant + { }; + +#if __cplusplus > 201402L + template inline constexpr bool is_bind_expression_v + = is_bind_expression<_Tp>::value; + template inline constexpr int is_placeholder_v + = is_placeholder<_Tp>::value; +#endif // C++17 + + /** @brief The type of placeholder objects defined by libstdc++. + * @ingroup binders + */ + template struct _Placeholder { }; + + /** @namespace std::placeholders + * @brief ISO C++ 2011 namespace for std::bind placeholders. + * @ingroup binders + */ + namespace placeholders + { + /* Define a large number of placeholders. There is no way to + * simplify this with variadic templates, because we're introducing + * unique names for each. + */ + extern const _Placeholder<1> _1; + extern const _Placeholder<2> _2; + extern const _Placeholder<3> _3; + extern const _Placeholder<4> _4; + extern const _Placeholder<5> _5; + extern const _Placeholder<6> _6; + extern const _Placeholder<7> _7; + extern const _Placeholder<8> _8; + extern const _Placeholder<9> _9; + extern const _Placeholder<10> _10; + extern const _Placeholder<11> _11; + extern const _Placeholder<12> _12; + extern const _Placeholder<13> _13; + extern const _Placeholder<14> _14; + extern const _Placeholder<15> _15; + extern const _Placeholder<16> _16; + extern const _Placeholder<17> _17; + extern const _Placeholder<18> _18; + extern const _Placeholder<19> _19; + extern const _Placeholder<20> _20; + extern const _Placeholder<21> _21; + extern const _Placeholder<22> _22; + extern const _Placeholder<23> _23; + extern const _Placeholder<24> _24; + extern const _Placeholder<25> _25; + extern const _Placeholder<26> _26; + extern const _Placeholder<27> _27; + extern const _Placeholder<28> _28; + extern const _Placeholder<29> _29; + } + + /** + * Partial specialization of is_placeholder that provides the placeholder + * number for the placeholder objects defined by libstdc++. + * @ingroup binders + */ + template + struct is_placeholder<_Placeholder<_Num> > + : public integral_constant + { }; + + template + struct is_placeholder > + : public integral_constant + { }; + + + // Like tuple_element_t but SFINAE-friendly. + template + using _Safe_tuple_element_t + = typename enable_if<(__i < tuple_size<_Tuple>::value), + tuple_element<__i, _Tuple>>::type::type; + + /** + * Maps an argument to bind() into an actual argument to the bound + * function object [func.bind.bind]/10. Only the first parameter should + * be specified: the rest are used to determine among the various + * implementations. Note that, although this class is a function + * object, it isn't entirely normal because it takes only two + * parameters regardless of the number of parameters passed to the + * bind expression. The first parameter is the bound argument and + * the second parameter is a tuple containing references to the + * rest of the arguments. + */ + template::value, + bool _IsPlaceholder = (is_placeholder<_Arg>::value > 0)> + class _Mu; + + /** + * If the argument is reference_wrapper<_Tp>, returns the + * underlying reference. + * C++11 [func.bind.bind] p10 bullet 1. + */ + template + class _Mu, false, false> + { + public: + /* Note: This won't actually work for const volatile + * reference_wrappers, because reference_wrapper::get() is const + * but not volatile-qualified. This might be a defect in the TR. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp& + operator()(_CVRef& __arg, _Tuple&) const volatile + { return __arg.get(); } + }; + + /** + * If the argument is a bind expression, we invoke the underlying + * function object with the same cv-qualifiers as we are given and + * pass along all of our arguments (unwrapped). + * C++11 [func.bind.bind] p10 bullet 2. + */ + template + class _Mu<_Arg, true, false> + { + public: + template + _GLIBCXX20_CONSTEXPR + auto + operator()(_CVArg& __arg, + tuple<_Args...>& __tuple) const volatile + -> decltype(__arg(declval<_Args>()...)) + { + // Construct an index tuple and forward to __call + typedef typename _Build_index_tuple::__type + _Indexes; + return this->__call(__arg, __tuple, _Indexes()); + } + + private: + // Invokes the underlying function object __arg by unpacking all + // of the arguments in the tuple. + template + _GLIBCXX20_CONSTEXPR + auto + __call(_CVArg& __arg, tuple<_Args...>& __tuple, + const _Index_tuple<_Indexes...>&) const volatile + -> decltype(__arg(declval<_Args>()...)) + { + return __arg(std::get<_Indexes>(std::move(__tuple))...); + } + }; + + /** + * If the argument is a placeholder for the Nth argument, returns + * a reference to the Nth argument to the bind function object. + * C++11 [func.bind.bind] p10 bullet 3. + */ + template + class _Mu<_Arg, false, true> + { + public: + template + _GLIBCXX20_CONSTEXPR + _Safe_tuple_element_t<(is_placeholder<_Arg>::value - 1), _Tuple>&& + operator()(const volatile _Arg&, _Tuple& __tuple) const volatile + { + return + ::std::get<(is_placeholder<_Arg>::value - 1)>(std::move(__tuple)); + } + }; + + /** + * If the argument is just a value, returns a reference to that + * value. The cv-qualifiers on the reference are determined by the caller. + * C++11 [func.bind.bind] p10 bullet 4. + */ + template + class _Mu<_Arg, false, false> + { + public: + template + _GLIBCXX20_CONSTEXPR + _CVArg&& + operator()(_CVArg&& __arg, _Tuple&) const volatile + { return std::forward<_CVArg>(__arg); } + }; + + // std::get for volatile-qualified tuples + template + inline auto + __volget(volatile tuple<_Tp...>& __tuple) + -> __tuple_element_t<_Ind, tuple<_Tp...>> volatile& + { return std::get<_Ind>(const_cast&>(__tuple)); } + + // std::get for const-volatile-qualified tuples + template + inline auto + __volget(const volatile tuple<_Tp...>& __tuple) + -> __tuple_element_t<_Ind, tuple<_Tp...>> const volatile& + { return std::get<_Ind>(const_cast&>(__tuple)); } + + /// Type of the function object returned from bind(). + template + struct _Bind; + + template + class _Bind<_Functor(_Bound_args...)> + : public _Weak_result_type<_Functor> + { + typedef typename _Build_index_tuple::__type + _Bound_indexes; + + _Functor _M_f; + tuple<_Bound_args...> _M_bound_args; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + _Result + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... + ); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + _Result + __call_c(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(std::get<_Indexes>(_M_bound_args), __args)... + ); + } + + // Call as volatile + template + _Result + __call_v(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) volatile + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... + ); + } + + // Call as const volatile + template + _Result + __call_c_v(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) const volatile + { + return std::__invoke(_M_f, + _Mu<_Bound_args>()(__volget<_Indexes>(_M_bound_args), __args)... + ); + } + + template + using _Mu_type = decltype( + _Mu::type>()( + std::declval<_BoundArg&>(), std::declval<_CallArgs&>()) ); + + template + using _Res_type_impl + = typename result_of< _Fn&(_Mu_type<_BArgs, _CallArgs>&&...) >::type; + + template + using _Res_type = _Res_type_impl<_Functor, _CallArgs, _Bound_args...>; + + template + using __dependent = typename + enable_if::value+1), _Functor>::type; + + template class __cv_quals> + using _Res_type_cv = _Res_type_impl< + typename __cv_quals<__dependent<_CallArgs>>::type, + _CallArgs, + typename __cv_quals<_Bound_args>::type...>; + + public: + template + explicit _GLIBCXX20_CONSTEXPR + _Bind(const _Functor& __f, _Args&&... __args) + : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) + { } + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind(_Functor&& __f, _Args&&... __args) + : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) + { } + + _Bind(const _Bind&) = default; + _Bind(_Bind&&) = default; + + // Call unqualified + template>> + _GLIBCXX20_CONSTEXPR + _Result + operator()(_Args&&... __args) + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const + template, add_const>> + _GLIBCXX20_CONSTEXPR + _Result + operator()(_Args&&... __args) const + { + return this->__call_c<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + +#if __cplusplus > 201402L +# define _GLIBCXX_DEPR_BIND \ + [[deprecated("std::bind does not support volatile in C++17")]] +#else +# define _GLIBCXX_DEPR_BIND +#endif + // Call as volatile + template, add_volatile>> + _GLIBCXX_DEPR_BIND + _Result + operator()(_Args&&... __args) volatile + { + return this->__call_v<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const volatile + template, add_cv>> + _GLIBCXX_DEPR_BIND + _Result + operator()(_Args&&... __args) const volatile + { + return this->__call_c_v<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + }; + + /// Type of the function object returned from bind(). + template + struct _Bind_result; + + template + class _Bind_result<_Result, _Functor(_Bound_args...)> + { + typedef typename _Build_index_tuple::__type + _Bound_indexes; + + _Functor _M_f; + tuple<_Bound_args...> _M_bound_args; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (std::get<_Indexes>(_M_bound_args), __args)...); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) const + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (std::get<_Indexes>(_M_bound_args), __args)...); + } + + // Call as volatile + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, _Index_tuple<_Indexes...>) volatile + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (__volget<_Indexes>(_M_bound_args), __args)...); + } + + // Call as const volatile + template + _GLIBCXX20_CONSTEXPR + _Res + __call(tuple<_Args...>&& __args, + _Index_tuple<_Indexes...>) const volatile + { + return std::__invoke_r<_Res>(_M_f, _Mu<_Bound_args>() + (__volget<_Indexes>(_M_bound_args), __args)...); + } + + public: + typedef _Result result_type; + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind_result(const _Functor& __f, _Args&&... __args) + : _M_f(__f), _M_bound_args(std::forward<_Args>(__args)...) + { } + + template + explicit _GLIBCXX20_CONSTEXPR + _Bind_result(_Functor&& __f, _Args&&... __args) + : _M_f(std::move(__f)), _M_bound_args(std::forward<_Args>(__args)...) + { } + + _Bind_result(const _Bind_result&) = default; + _Bind_result(_Bind_result&&) = default; + + // Call unqualified + template + _GLIBCXX20_CONSTEXPR + result_type + operator()(_Args&&... __args) + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const + template + _GLIBCXX20_CONSTEXPR + result_type + operator()(_Args&&... __args) const + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as volatile + template + _GLIBCXX_DEPR_BIND + result_type + operator()(_Args&&... __args) volatile + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + + // Call as const volatile + template + _GLIBCXX_DEPR_BIND + result_type + operator()(_Args&&... __args) const volatile + { + return this->__call<_Result>( + std::forward_as_tuple(std::forward<_Args>(__args)...), + _Bound_indexes()); + } + }; +#undef _GLIBCXX_DEPR_BIND + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression<_Bind<_Signature> > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression > + : public true_type { }; + + /** + * @brief Class template _Bind is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression<_Bind_result<_Result, _Signature>> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + /** + * @brief Class template _Bind_result is always a bind expression. + * @ingroup binders + */ + template + struct is_bind_expression> + : public true_type { }; + + template + struct _Bind_check_arity { }; + + template + struct _Bind_check_arity<_Ret (*)(_Args...), _BoundArgs...> + { + static_assert(sizeof...(_BoundArgs) == sizeof...(_Args), + "Wrong number of arguments for function"); + }; + + template + struct _Bind_check_arity<_Ret (*)(_Args......), _BoundArgs...> + { + static_assert(sizeof...(_BoundArgs) >= sizeof...(_Args), + "Wrong number of arguments for function"); + }; + + template + struct _Bind_check_arity<_Tp _Class::*, _BoundArgs...> + { + using _Arity = typename _Mem_fn<_Tp _Class::*>::_Arity; + using _Varargs = typename _Mem_fn<_Tp _Class::*>::_Varargs; + static_assert(_Varargs::value + ? sizeof...(_BoundArgs) >= _Arity::value + 1 + : sizeof...(_BoundArgs) == _Arity::value + 1, + "Wrong number of arguments for pointer-to-member"); + }; + + // Trait type used to remove std::bind() from overload set via SFINAE + // when first argument has integer type, so that std::bind() will + // not be a better match than ::bind() from the BSD Sockets API. + template::type> + using __is_socketlike = __or_, is_enum<_Tp2>>; + + template + struct _Bind_helper + : _Bind_check_arity::type, _BoundArgs...> + { + typedef typename decay<_Func>::type __func_type; + typedef _Bind<__func_type(typename decay<_BoundArgs>::type...)> type; + }; + + // Partial specialization for is_socketlike == true, does not define + // nested type so std::bind() will not participate in overload resolution + // when the first argument might be a socket file descriptor. + template + struct _Bind_helper + { }; + + /** + * @brief Function template for std::bind. + * @ingroup binders + */ + template + inline _GLIBCXX20_CONSTEXPR typename + _Bind_helper<__is_socketlike<_Func>::value, _Func, _BoundArgs...>::type + bind(_Func&& __f, _BoundArgs&&... __args) + { + typedef _Bind_helper __helper_type; + return typename __helper_type::type(std::forward<_Func>(__f), + std::forward<_BoundArgs>(__args)...); + } + + template + struct _Bindres_helper + : _Bind_check_arity::type, _BoundArgs...> + { + typedef typename decay<_Func>::type __functor_type; + typedef _Bind_result<_Result, + __functor_type(typename decay<_BoundArgs>::type...)> + type; + }; + + /** + * @brief Function template for std::bind. + * @ingroup binders + */ + template + inline _GLIBCXX20_CONSTEXPR + typename _Bindres_helper<_Result, _Func, _BoundArgs...>::type + bind(_Func&& __f, _BoundArgs&&... __args) + { + typedef _Bindres_helper<_Result, _Func, _BoundArgs...> __helper_type; + return typename __helper_type::type(std::forward<_Func>(__f), + std::forward<_BoundArgs>(__args)...); + } + +#if __cplusplus > 201703L +#define __cpp_lib_bind_front 201907L + + template + struct _Bind_front + { + static_assert(is_move_constructible_v<_Fd>); + static_assert((is_move_constructible_v<_BoundArgs> && ...)); + + // First parameter is to ensure this constructor is never used + // instead of the copy/move constructor. + template + explicit constexpr + _Bind_front(int, _Fn&& __fn, _Args&&... __args) + noexcept(__and_, + is_nothrow_constructible<_BoundArgs, _Args>...>::value) + : _M_fd(std::forward<_Fn>(__fn)), + _M_bound_args(std::forward<_Args>(__args)...) + { static_assert(sizeof...(_Args) == sizeof...(_BoundArgs)); } + + _Bind_front(const _Bind_front&) = default; + _Bind_front(_Bind_front&&) = default; + _Bind_front& operator=(const _Bind_front&) = default; + _Bind_front& operator=(_Bind_front&&) = default; + ~_Bind_front() = default; + + template + constexpr + invoke_result_t<_Fd&, _BoundArgs&..., _CallArgs...> + operator()(_CallArgs&&... __call_args) & + noexcept(is_nothrow_invocable_v<_Fd&, _BoundArgs&..., _CallArgs...>) + { + return _S_call(*this, _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + constexpr + invoke_result_t + operator()(_CallArgs&&... __call_args) const & + noexcept(is_nothrow_invocable_v) + { + return _S_call(*this, _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + constexpr + invoke_result_t<_Fd, _BoundArgs..., _CallArgs...> + operator()(_CallArgs&&... __call_args) && + noexcept(is_nothrow_invocable_v<_Fd, _BoundArgs..., _CallArgs...>) + { + return _S_call(std::move(*this), _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + template + constexpr + invoke_result_t + operator()(_CallArgs&&... __call_args) const && + noexcept(is_nothrow_invocable_v) + { + return _S_call(std::move(*this), _BoundIndices(), + std::forward<_CallArgs>(__call_args)...); + } + + private: + using _BoundIndices = index_sequence_for<_BoundArgs...>; + + template + static constexpr + decltype(auto) + _S_call(_Tp&& __g, index_sequence<_Ind...>, _CallArgs&&... __call_args) + { + return std::invoke(std::forward<_Tp>(__g)._M_fd, + std::get<_Ind>(std::forward<_Tp>(__g)._M_bound_args)..., + std::forward<_CallArgs>(__call_args)...); + } + + _Fd _M_fd; + std::tuple<_BoundArgs...> _M_bound_args; + }; + + template + using _Bind_front_t + = _Bind_front, decay_t<_Args>...>; + + template + constexpr _Bind_front_t<_Fn, _Args...> + bind_front(_Fn&& __fn, _Args&&... __args) + noexcept(is_nothrow_constructible_v<_Bind_front_t<_Fn, _Args...>, + int, _Fn, _Args...>) + { + return _Bind_front_t<_Fn, _Args...>(0, std::forward<_Fn>(__fn), + std::forward<_Args>(__args)...); + } +#endif + +#if __cplusplus >= 201402L + /// Generalized negator. + template + class _Not_fn + { + template + using __inv_res_t = typename __invoke_result<_Fn2, _Args...>::type; + + template + static decltype(!std::declval<_Tp>()) + _S_not() noexcept(noexcept(!std::declval<_Tp>())); + + public: + template + constexpr + _Not_fn(_Fn2&& __fn, int) + : _M_fn(std::forward<_Fn2>(__fn)) { } + + _Not_fn(const _Not_fn& __fn) = default; + _Not_fn(_Not_fn&& __fn) = default; + ~_Not_fn() = default; + + // Macro to define operator() with given cv-qualifiers ref-qualifiers, + // forwarding _M_fn and the function arguments with the same qualifiers, + // and deducing the return type and exception-specification. +#define _GLIBCXX_NOT_FN_CALL_OP( _QUALS ) \ + template \ + _GLIBCXX20_CONSTEXPR \ + decltype(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>()) \ + operator()(_Args&&... __args) _QUALS \ + noexcept(__is_nothrow_invocable<_Fn _QUALS, _Args...>::value \ + && noexcept(_S_not<__inv_res_t<_Fn _QUALS, _Args...>>())) \ + { \ + return !std::__invoke(std::forward< _Fn _QUALS >(_M_fn), \ + std::forward<_Args>(__args)...); \ + } + _GLIBCXX_NOT_FN_CALL_OP( & ) + _GLIBCXX_NOT_FN_CALL_OP( const & ) + _GLIBCXX_NOT_FN_CALL_OP( && ) + _GLIBCXX_NOT_FN_CALL_OP( const && ) +#undef _GLIBCXX_NOT_FN_CALL_OP + + private: + _Fn _M_fn; + }; + + template + struct __is_byte_like : false_type { }; + + template + struct __is_byte_like<_Tp, equal_to<_Tp>> + : __bool_constant::value> { }; + + template + struct __is_byte_like<_Tp, equal_to> + : __bool_constant::value> { }; + +#if __cplusplus >= 201703L + // Declare std::byte (full definition is in ). + enum class byte : unsigned char; + + template<> + struct __is_byte_like> + : true_type { }; + + template<> + struct __is_byte_like> + : true_type { }; + +#define __cpp_lib_not_fn 201603 + /// [func.not_fn] Function template not_fn + template + _GLIBCXX20_CONSTEXPR + inline auto + not_fn(_Fn&& __fn) + noexcept(std::is_nothrow_constructible, _Fn&&>::value) + { + return _Not_fn>{std::forward<_Fn>(__fn), 0}; + } + + // Searchers +#define __cpp_lib_boyer_moore_searcher 201603 + + template> + class default_searcher + { + public: + _GLIBCXX20_CONSTEXPR + default_searcher(_ForwardIterator1 __pat_first, + _ForwardIterator1 __pat_last, + _BinaryPredicate __pred = _BinaryPredicate()) + : _M_m(__pat_first, __pat_last, std::move(__pred)) + { } + + template + _GLIBCXX20_CONSTEXPR + pair<_ForwardIterator2, _ForwardIterator2> + operator()(_ForwardIterator2 __first, _ForwardIterator2 __last) const + { + _ForwardIterator2 __first_ret = + std::search(__first, __last, std::get<0>(_M_m), std::get<1>(_M_m), + std::get<2>(_M_m)); + auto __ret = std::make_pair(__first_ret, __first_ret); + if (__ret.first != __last) + std::advance(__ret.second, std::distance(std::get<0>(_M_m), + std::get<1>(_M_m))); + return __ret; + } + + private: + tuple<_ForwardIterator1, _ForwardIterator1, _BinaryPredicate> _M_m; + }; + + template + struct __boyer_moore_map_base + { + template + __boyer_moore_map_base(_RAIter __pat, size_t __patlen, + _Hash&& __hf, _Pred&& __pred) + : _M_bad_char{ __patlen, std::move(__hf), std::move(__pred) } + { + if (__patlen > 0) + for (__diff_type __i = 0; __i < __patlen - 1; ++__i) + _M_bad_char[__pat[__i]] = __patlen - 1 - __i; + } + + using __diff_type = _Tp; + + __diff_type + _M_lookup(_Key __key, __diff_type __not_found) const + { + auto __iter = _M_bad_char.find(__key); + if (__iter == _M_bad_char.end()) + return __not_found; + return __iter->second; + } + + _Pred + _M_pred() const { return _M_bad_char.key_eq(); } + + _GLIBCXX_STD_C::unordered_map<_Key, _Tp, _Hash, _Pred> _M_bad_char; + }; + + template + struct __boyer_moore_array_base + { + template + __boyer_moore_array_base(_RAIter __pat, size_t __patlen, + _Unused&&, _Pred&& __pred) + : _M_bad_char{ _GLIBCXX_STD_C::array<_Tp, _Len>{}, std::move(__pred) } + { + std::get<0>(_M_bad_char).fill(__patlen); + if (__patlen > 0) + for (__diff_type __i = 0; __i < __patlen - 1; ++__i) + { + auto __ch = __pat[__i]; + using _UCh = make_unsigned_t; + auto __uch = static_cast<_UCh>(__ch); + std::get<0>(_M_bad_char)[__uch] = __patlen - 1 - __i; + } + } + + using __diff_type = _Tp; + + template + __diff_type + _M_lookup(_Key __key, __diff_type __not_found) const + { + auto __ukey = static_cast>(__key); + if (__ukey >= _Len) + return __not_found; + return std::get<0>(_M_bad_char)[__ukey]; + } + + const _Pred& + _M_pred() const { return std::get<1>(_M_bad_char); } + + tuple<_GLIBCXX_STD_C::array<_Tp, _Len>, _Pred> _M_bad_char; + }; + + // Use __boyer_moore_array_base when pattern consists of narrow characters + // (or std::byte) and uses std::equal_to as the predicate. + template::value_type, + typename _Diff = typename iterator_traits<_RAIter>::difference_type> + using __boyer_moore_base_t + = conditional_t<__is_byte_like<_Val, _Pred>::value, + __boyer_moore_array_base<_Diff, 256, _Pred>, + __boyer_moore_map_base<_Val, _Diff, _Hash, _Pred>>; + + template::value_type>, + typename _BinaryPredicate = equal_to<>> + class boyer_moore_searcher + : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate> + { + using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>; + using typename _Base::__diff_type; + + public: + boyer_moore_searcher(_RAIter __pat_first, _RAIter __pat_last, + _Hash __hf = _Hash(), + _BinaryPredicate __pred = _BinaryPredicate()); + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const; + + private: + bool + _M_is_prefix(_RAIter __word, __diff_type __len, + __diff_type __pos) + { + const auto& __pred = this->_M_pred(); + __diff_type __suffixlen = __len - __pos; + for (__diff_type __i = 0; __i < __suffixlen; ++__i) + if (!__pred(__word[__i], __word[__pos + __i])) + return false; + return true; + } + + __diff_type + _M_suffix_length(_RAIter __word, __diff_type __len, + __diff_type __pos) + { + const auto& __pred = this->_M_pred(); + __diff_type __i = 0; + while (__pred(__word[__pos - __i], __word[__len - 1 - __i]) + && __i < __pos) + { + ++__i; + } + return __i; + } + + template + __diff_type + _M_bad_char_shift(_Tp __c) const + { return this->_M_lookup(__c, _M_pat_end - _M_pat); } + + _RAIter _M_pat; + _RAIter _M_pat_end; + _GLIBCXX_STD_C::vector<__diff_type> _M_good_suffix; + }; + + template::value_type>, + typename _BinaryPredicate = equal_to<>> + class boyer_moore_horspool_searcher + : __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate> + { + using _Base = __boyer_moore_base_t<_RAIter, _Hash, _BinaryPredicate>; + using typename _Base::__diff_type; + + public: + boyer_moore_horspool_searcher(_RAIter __pat, + _RAIter __pat_end, + _Hash __hf = _Hash(), + _BinaryPredicate __pred + = _BinaryPredicate()) + : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)), + _M_pat(__pat), _M_pat_end(__pat_end) + { } + + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const + { + const auto& __pred = this->_M_pred(); + auto __patlen = _M_pat_end - _M_pat; + if (__patlen == 0) + return std::make_pair(__first, __first); + auto __len = __last - __first; + while (__len >= __patlen) + { + for (auto __scan = __patlen - 1; + __pred(__first[__scan], _M_pat[__scan]); --__scan) + if (__scan == 0) + return std::make_pair(__first, __first + __patlen); + auto __shift = _M_bad_char_shift(__first[__patlen - 1]); + __len -= __shift; + __first += __shift; + } + return std::make_pair(__last, __last); + } + + private: + template + __diff_type + _M_bad_char_shift(_Tp __c) const + { return this->_M_lookup(__c, _M_pat_end - _M_pat); } + + _RAIter _M_pat; + _RAIter _M_pat_end; + }; + + template + boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>:: + boyer_moore_searcher(_RAIter __pat, _RAIter __pat_end, + _Hash __hf, _BinaryPredicate __pred) + : _Base(__pat, __pat_end - __pat, std::move(__hf), std::move(__pred)), + _M_pat(__pat), _M_pat_end(__pat_end), _M_good_suffix(__pat_end - __pat) + { + auto __patlen = __pat_end - __pat; + if (__patlen == 0) + return; + __diff_type __last_prefix = __patlen - 1; + for (__diff_type __p = __patlen - 1; __p >= 0; --__p) + { + if (_M_is_prefix(__pat, __patlen, __p + 1)) + __last_prefix = __p + 1; + _M_good_suffix[__p] = __last_prefix + (__patlen - 1 - __p); + } + for (__diff_type __p = 0; __p < __patlen - 1; ++__p) + { + auto __slen = _M_suffix_length(__pat, __patlen, __p); + auto __pos = __patlen - 1 - __slen; + if (!__pred(__pat[__p - __slen], __pat[__pos])) + _M_good_suffix[__pos] = __patlen - 1 - __p + __slen; + } + } + + template + template + pair<_RandomAccessIterator2, _RandomAccessIterator2> + boyer_moore_searcher<_RAIter, _Hash, _BinaryPredicate>:: + operator()(_RandomAccessIterator2 __first, + _RandomAccessIterator2 __last) const + { + auto __patlen = _M_pat_end - _M_pat; + if (__patlen == 0) + return std::make_pair(__first, __first); + const auto& __pred = this->_M_pred(); + __diff_type __i = __patlen - 1; + auto __stringlen = __last - __first; + while (__i < __stringlen) + { + __diff_type __j = __patlen - 1; + while (__j >= 0 && __pred(__first[__i], _M_pat[__j])) + { + --__i; + --__j; + } + if (__j < 0) + { + const auto __match = __first + __i + 1; + return std::make_pair(__match, __match + __patlen); + } + __i += std::max(_M_bad_char_shift(__first[__i]), + _M_good_suffix[__j]); + } + return std::make_pair(__last, __last); + } + +#endif // C++17 +#endif // C++14 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_FUNCTIONAL diff --git a/resources/sources/avr-libstdcpp/include/initializer_list b/resources/sources/avr-libstdcpp/include/initializer_list index 031640ecb..9f4859514 100644 --- a/resources/sources/avr-libstdcpp/include/initializer_list +++ b/resources/sources/avr-libstdcpp/include/initializer_list @@ -1,25 +1,109 @@ -// Minimal for AVR -// GCC has built-in support for initializer_list, this just provides the type. -#ifndef _AVR_INITIALIZER_LIST -#define _AVR_INITIALIZER_LIST - -namespace std { - template - class initializer_list { - const T* _begin; - size_t _size; - constexpr initializer_list(const T* b, size_t s) noexcept : _begin(b), _size(s) {} - public: - using value_type = T; - using reference = const T&; - using const_reference = const T&; - using size_type = size_t; - using iterator = const T*; - using const_iterator = const T*; - constexpr initializer_list() noexcept : _begin(nullptr), _size(0) {} - constexpr size_type size() const noexcept { return _size; } - constexpr const_iterator begin() const noexcept { return _begin; } - constexpr const_iterator end() const noexcept { return _begin + _size; } - }; +// std::initializer_list support -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file initializer_list + * This is a Standard C++ Library header. + */ + +#ifndef _INITIALIZER_LIST +#define _INITIALIZER_LIST + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else // C++0x + +#pragma GCC visibility push(default) + +#include + +namespace std +{ + /// initializer_list + template + class initializer_list + { + public: + typedef _E value_type; + typedef const _E& reference; + typedef const _E& const_reference; + typedef size_t size_type; + typedef const _E* iterator; + typedef const _E* const_iterator; + + private: + iterator _M_array; + size_type _M_len; + + // The compiler can call a private constructor. + constexpr initializer_list(const_iterator __a, size_type __l) + : _M_array(__a), _M_len(__l) { } + + public: + constexpr initializer_list() noexcept + : _M_array(0), _M_len(0) { } + + // Number of elements. + constexpr size_type + size() const noexcept { return _M_len; } + + // First element. + constexpr const_iterator + begin() const noexcept { return _M_array; } + + // One past the last element. + constexpr const_iterator + end() const noexcept { return begin() + size(); } + }; + + /** + * @brief Return an iterator pointing to the first element of + * the initializer_list. + * @param __ils Initializer list. + * @relates initializer_list + */ + template + constexpr const _Tp* + begin(initializer_list<_Tp> __ils) noexcept + { return __ils.begin(); } + + /** + * @brief Return an iterator pointing to one past the last element + * of the initializer_list. + * @param __ils Initializer list. + * @relates initializer_list + */ + template + constexpr const _Tp* + end(initializer_list<_Tp> __ils) noexcept + { return __ils.end(); } } -#endif + +#pragma GCC visibility pop + +#endif // C++11 + +#endif // _INITIALIZER_LIST diff --git a/resources/sources/avr-libstdcpp/include/iterator b/resources/sources/avr-libstdcpp/include/iterator new file mode 100644 index 000000000..fbc47e01e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/iterator @@ -0,0 +1,70 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/iterator + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_ITERATOR +#define _GLIBCXX_ITERATOR 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#if __cplusplus >= 201402L && ! defined _GLIBCXX_DEBUG // PR libstdc++/70303 +# define __cpp_lib_null_iterators 201304L +#endif + +#endif /* _GLIBCXX_ITERATOR */ diff --git a/resources/sources/avr-libstdcpp/include/limits b/resources/sources/avr-libstdcpp/include/limits new file mode 100644 index 000000000..898406f91 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/limits @@ -0,0 +1,1893 @@ +// The template and inlines for the numeric_limits classes. -*- C++ -*- + +// Copyright (C) 1999-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/limits + * This is a Standard C++ Library header. + */ + +// Note: this is not a conforming implementation. +// Written by Gabriel Dos Reis + +// +// ISO 14882:1998 +// 18.2.1 +// + +#ifndef _GLIBCXX_NUMERIC_LIMITS +#define _GLIBCXX_NUMERIC_LIMITS 1 + +#pragma GCC system_header + +#include + +// +// The numeric_limits<> traits document implementation-defined aspects +// of fundamental arithmetic data types (integers and floating points). +// From Standard C++ point of view, there are 14 such types: +// * integers +// bool (1) +// char, signed char, unsigned char, wchar_t (4) +// short, unsigned short (2) +// int, unsigned (2) +// long, unsigned long (2) +// +// * floating points +// float (1) +// double (1) +// long double (1) +// +// GNU C++ understands (where supported by the host C-library) +// * integer +// long long, unsigned long long (2) +// +// which brings us to 16 fundamental arithmetic data types in GNU C++. +// +// +// Since a numeric_limits<> is a bit tricky to get right, we rely on +// an interface composed of macros which should be defined in config/os +// or config/cpu when they differ from the generic (read arbitrary) +// definitions given here. +// + +// These values can be overridden in the target configuration file. +// The default values are appropriate for many 32-bit targets. + +// GCC only intrinsically supports modulo integral types. The only remaining +// integral exceptional values is division by zero. Only targets that do not +// signal division by zero in some "hard to ignore" way should use false. +#ifndef __glibcxx_integral_traps +# define __glibcxx_integral_traps true +#endif + +// float +// + +// Default values. Should be overridden in configuration files if necessary. + +#ifndef __glibcxx_float_has_denorm_loss +# define __glibcxx_float_has_denorm_loss false +#endif +#ifndef __glibcxx_float_traps +# define __glibcxx_float_traps false +#endif +#ifndef __glibcxx_float_tinyness_before +# define __glibcxx_float_tinyness_before false +#endif + +// double + +// Default values. Should be overridden in configuration files if necessary. + +#ifndef __glibcxx_double_has_denorm_loss +# define __glibcxx_double_has_denorm_loss false +#endif +#ifndef __glibcxx_double_traps +# define __glibcxx_double_traps false +#endif +#ifndef __glibcxx_double_tinyness_before +# define __glibcxx_double_tinyness_before false +#endif + +// long double + +// Default values. Should be overridden in configuration files if necessary. + +#ifndef __glibcxx_long_double_has_denorm_loss +# define __glibcxx_long_double_has_denorm_loss false +#endif +#ifndef __glibcxx_long_double_traps +# define __glibcxx_long_double_traps false +#endif +#ifndef __glibcxx_long_double_tinyness_before +# define __glibcxx_long_double_tinyness_before false +#endif + +// You should not need to define any macros below this point. + +#define __glibcxx_signed_b(T,B) ((T)(-1) < 0) + +#define __glibcxx_min_b(T,B) \ + (__glibcxx_signed_b (T,B) ? -__glibcxx_max_b (T,B) - 1 : (T)0) + +#define __glibcxx_max_b(T,B) \ + (__glibcxx_signed_b (T,B) ? \ + (((((T)1 << (__glibcxx_digits_b (T,B) - 1)) - 1) << 1) + 1) : ~(T)0) + +#define __glibcxx_digits_b(T,B) \ + (B - __glibcxx_signed_b (T,B)) + +// The fraction 643/2136 approximates log10(2) to 7 significant digits. +#define __glibcxx_digits10_b(T,B) \ + (__glibcxx_digits_b (T,B) * 643L / 2136) + +#define __glibcxx_signed(T) \ + __glibcxx_signed_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_min(T) \ + __glibcxx_min_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_max(T) \ + __glibcxx_max_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_digits(T) \ + __glibcxx_digits_b (T, sizeof(T) * __CHAR_BIT__) +#define __glibcxx_digits10(T) \ + __glibcxx_digits10_b (T, sizeof(T) * __CHAR_BIT__) + +#define __glibcxx_max_digits10(T) \ + (2 + (T) * 643L / 2136) + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @brief Describes the rounding style for floating-point types. + * + * This is used in the std::numeric_limits class. + */ + enum float_round_style + { + round_indeterminate = -1, /// Intermediate. + round_toward_zero = 0, /// To zero. + round_to_nearest = 1, /// To the nearest representable value. + round_toward_infinity = 2, /// To infinity. + round_toward_neg_infinity = 3 /// To negative infinity. + }; + + /** + * @brief Describes the denormalization for floating-point types. + * + * These values represent the presence or absence of a variable number + * of exponent bits. This type is used in the std::numeric_limits class. + */ + enum float_denorm_style + { + /// Indeterminate at compile time whether denormalized values are allowed. + denorm_indeterminate = -1, + /// The type does not allow denormalized values. + denorm_absent = 0, + /// The type allows denormalized values. + denorm_present = 1 + }; + + /** + * @brief Part of std::numeric_limits. + * + * The @c static @c const members are usable as integral constant + * expressions. + * + * @note This is a separate class for purposes of efficiency; you + * should only access these members as part of an instantiation + * of the std::numeric_limits class. + */ + struct __numeric_limits_base + { + /** This will be true for all fundamental types (which have + specializations), and false for everything else. */ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = false; + + /** The number of @c radix digits that be represented without change: for + integer types, the number of non-sign bits in the mantissa; for + floating types, the number of @c radix digits in the mantissa. */ + static _GLIBCXX_USE_CONSTEXPR int digits = 0; + + /** The number of base 10 digits that can be represented without change. */ + static _GLIBCXX_USE_CONSTEXPR int digits10 = 0; + +#if __cplusplus >= 201103L + /** The number of base 10 digits required to ensure that values which + differ are always differentiated. */ + static constexpr int max_digits10 = 0; +#endif + + /** True if the type is signed. */ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + + /** True if the type is integer. */ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + + /** True if the type uses an exact representation. All integer types are + exact, but not all exact types are integer. For example, rational and + fixed-exponent representations are exact but not integer. */ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + + /** For integer types, specifies the base of the representation. For + floating types, specifies the base of the exponent representation. */ + static _GLIBCXX_USE_CONSTEXPR int radix = 0; + + /** The minimum negative integer such that @c radix raised to the power of + (one less than that integer) is a normalized floating point number. */ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + + /** The minimum negative integer such that 10 raised to that power is in + the range of normalized floating point numbers. */ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + + /** The maximum positive integer such that @c radix raised to the power of + (one less than that integer) is a representable finite floating point + number. */ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + + /** The maximum positive integer such that 10 raised to that power is in + the range of representable finite floating point numbers. */ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + /** True if the type has a representation for positive infinity. */ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + + /** True if the type has a representation for a quiet (non-signaling) + Not a Number. */ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + + /** True if the type has a representation for a signaling + Not a Number. */ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + + /** See std::float_denorm_style for more information. */ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm = denorm_absent; + + /** True if loss of accuracy is detected as a denormalization loss, + rather than as an inexact result. */ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + /** True if-and-only-if the type adheres to the IEC 559 standard, also + known as IEEE 754. (Only makes sense for floating point types.) */ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + + /** True if the set of values representable by the type is + finite. All built-in types are bounded, this member would be + false for arbitrary precision types. */ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = false; + + /** True if the type is @e modulo. A type is modulo if, for any + operation involving +, -, or * on values of that type whose + result would fall outside the range [min(),max()], the value + returned differs from the true value by an integer multiple of + max() - min() + 1. On most machines, this is false for floating + types, true for unsigned integers, and true for signed integers. + See PR22200 about signed integers. */ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + /** True if trapping is implemented for this type. */ + static _GLIBCXX_USE_CONSTEXPR bool traps = false; + + /** True if tininess is detected before rounding. (see IEC 559) */ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + + /** See std::float_round_style for more information. This is only + meaningful for floating types; integer types will all be + round_toward_zero. */ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = + round_toward_zero; + }; + + /** + * @brief Properties of fundamental types. + * + * This class allows a program to obtain information about the + * representation of a fundamental type on a given platform. For + * non-fundamental types, the functions will return 0 and the data + * members will all be @c false. + */ + template + struct numeric_limits : public __numeric_limits_base + { + /** The minimum finite value, or for floating types with + denormalization, the minimum positive normalized value. */ + static _GLIBCXX_CONSTEXPR _Tp + min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The maximum finite value. */ + static _GLIBCXX_CONSTEXPR _Tp + max() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + +#if __cplusplus >= 201103L + /** A finite value x such that there is no other finite value y + * where y < x. */ + static constexpr _Tp + lowest() noexcept { return _Tp(); } +#endif + + /** The @e machine @e epsilon: the difference between 1 and the least + value greater than 1 that is representable. */ + static _GLIBCXX_CONSTEXPR _Tp + epsilon() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The maximum rounding error measurement (see LIA-1). */ + static _GLIBCXX_CONSTEXPR _Tp + round_error() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of positive infinity, if @c has_infinity. */ + static _GLIBCXX_CONSTEXPR _Tp + infinity() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of a quiet Not a Number, + if @c has_quiet_NaN. */ + static _GLIBCXX_CONSTEXPR _Tp + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The representation of a signaling Not a Number, if + @c has_signaling_NaN. */ + static _GLIBCXX_CONSTEXPR _Tp + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + + /** The minimum positive denormalized value. For types where + @c has_denorm is false, this is the minimum positive normalized + value. */ + static _GLIBCXX_CONSTEXPR _Tp + denorm_min() _GLIBCXX_USE_NOEXCEPT { return _Tp(); } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 559. numeric_limits + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + template + struct numeric_limits + : public numeric_limits<_Tp> { }; + + // Now there follow 16 explicit specializations. Yes, 16. Make sure + // you get the count right. (18 in C++11 mode, with char16_t and char32_t.) + // (+1 if char8_t is enabled.) + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 184. numeric_limits wording problems + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR bool + min() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + max() _GLIBCXX_USE_NOEXCEPT { return true; } + +#if __cplusplus >= 201103L + static constexpr bool + lowest() noexcept { return min(); } +#endif + static _GLIBCXX_USE_CONSTEXPR int digits = 1; + static _GLIBCXX_USE_CONSTEXPR int digits10 = 0; +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR bool + epsilon() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + round_error() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR bool + infinity() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_CONSTEXPR bool + denorm_min() _GLIBCXX_USE_NOEXCEPT { return false; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + // It is not clear what it means for a boolean type to trap. + // This is a DR on the LWG issue list. Here, I use integer + // promotion semantics. + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR char + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min(char); } + + static _GLIBCXX_CONSTEXPR char + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max(char); } + +#if __cplusplus >= 201103L + static constexpr char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR + char infinity() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char(); } + + static _GLIBCXX_CONSTEXPR char + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR signed char + min() _GLIBCXX_USE_NOEXCEPT { return -__SCHAR_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR signed char + max() _GLIBCXX_USE_NOEXCEPT { return __SCHAR_MAX__; } + +#if __cplusplus >= 201103L + static constexpr signed char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (signed char); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (signed char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR signed char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR signed char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR signed char + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR signed char + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned char + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned char + max() _GLIBCXX_USE_NOEXCEPT { return __SCHAR_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned char + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned char); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned char); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned char + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned char + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned char + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned char + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR wchar_t + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (wchar_t); } + + static _GLIBCXX_CONSTEXPR wchar_t + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (wchar_t); } + +#if __cplusplus >= 201103L + static constexpr wchar_t + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (wchar_t); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (wchar_t); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (wchar_t); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR wchar_t + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR wchar_t + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR wchar_t + infinity() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_CONSTEXPR wchar_t + denorm_min() _GLIBCXX_USE_NOEXCEPT { return wchar_t(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + +#if _GLIBCXX_USE_CHAR8_T + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR char8_t + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min (char8_t); } + + static _GLIBCXX_CONSTEXPR char8_t + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max (char8_t); } + + static _GLIBCXX_CONSTEXPR char8_t + lowest() _GLIBCXX_USE_NOEXCEPT { return min(); } + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (char8_t); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (char8_t); + static _GLIBCXX_USE_CONSTEXPR int max_digits10 = 0; + static _GLIBCXX_USE_CONSTEXPR bool is_signed = __glibcxx_signed (char8_t); + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR char8_t + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR char8_t + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR char8_t + infinity() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_CONSTEXPR char8_t + denorm_min() _GLIBCXX_USE_NOEXCEPT { return char8_t(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = !is_signed; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; +#endif + +#if __cplusplus >= 201103L + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static constexpr bool is_specialized = true; + + static constexpr char16_t + min() noexcept { return __glibcxx_min (char16_t); } + + static constexpr char16_t + max() noexcept { return __glibcxx_max (char16_t); } + + static constexpr char16_t + lowest() noexcept { return min(); } + + static constexpr int digits = __glibcxx_digits (char16_t); + static constexpr int digits10 = __glibcxx_digits10 (char16_t); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = __glibcxx_signed (char16_t); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr char16_t + epsilon() noexcept { return 0; } + + static constexpr char16_t + round_error() noexcept { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr char16_t + infinity() noexcept { return char16_t(); } + + static constexpr char16_t + quiet_NaN() noexcept { return char16_t(); } + + static constexpr char16_t + signaling_NaN() noexcept { return char16_t(); } + + static constexpr char16_t + denorm_min() noexcept { return char16_t(); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = !is_signed; + + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static constexpr bool is_specialized = true; + + static constexpr char32_t + min() noexcept { return __glibcxx_min (char32_t); } + + static constexpr char32_t + max() noexcept { return __glibcxx_max (char32_t); } + + static constexpr char32_t + lowest() noexcept { return min(); } + + static constexpr int digits = __glibcxx_digits (char32_t); + static constexpr int digits10 = __glibcxx_digits10 (char32_t); + static constexpr int max_digits10 = 0; + static constexpr bool is_signed = __glibcxx_signed (char32_t); + static constexpr bool is_integer = true; + static constexpr bool is_exact = true; + static constexpr int radix = 2; + + static constexpr char32_t + epsilon() noexcept { return 0; } + + static constexpr char32_t + round_error() noexcept { return 0; } + + static constexpr int min_exponent = 0; + static constexpr int min_exponent10 = 0; + static constexpr int max_exponent = 0; + static constexpr int max_exponent10 = 0; + + static constexpr bool has_infinity = false; + static constexpr bool has_quiet_NaN = false; + static constexpr bool has_signaling_NaN = false; + static constexpr float_denorm_style has_denorm = denorm_absent; + static constexpr bool has_denorm_loss = false; + + static constexpr char32_t + infinity() noexcept { return char32_t(); } + + static constexpr char32_t + quiet_NaN() noexcept { return char32_t(); } + + static constexpr char32_t + signaling_NaN() noexcept { return char32_t(); } + + static constexpr char32_t + denorm_min() noexcept { return char32_t(); } + + static constexpr bool is_iec559 = false; + static constexpr bool is_bounded = true; + static constexpr bool is_modulo = !is_signed; + + static constexpr bool traps = __glibcxx_integral_traps; + static constexpr bool tinyness_before = false; + static constexpr float_round_style round_style = round_toward_zero; + }; +#endif + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR short + min() _GLIBCXX_USE_NOEXCEPT { return -__SHRT_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR short + max() _GLIBCXX_USE_NOEXCEPT { return __SHRT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr short + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (short); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (short); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR short + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR short + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR short + infinity() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_CONSTEXPR short + denorm_min() _GLIBCXX_USE_NOEXCEPT { return short(); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned short + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned short + max() _GLIBCXX_USE_NOEXCEPT { return __SHRT_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned short + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned short); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned short); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned short + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned short + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned short + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned short + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR int + min() _GLIBCXX_USE_NOEXCEPT { return -__INT_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR int + max() _GLIBCXX_USE_NOEXCEPT { return __INT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr int + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (int); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (int); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR int + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR int + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR int + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR int + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned int + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned int + max() _GLIBCXX_USE_NOEXCEPT { return __INT_MAX__ * 2U + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned int + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned int); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned int); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned int + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned int + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned int + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned int + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long + min() _GLIBCXX_USE_NOEXCEPT { return -__LONG_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __glibcxx_digits (long); + static _GLIBCXX_USE_CONSTEXPR int digits10 = __glibcxx_digits10 (long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR long + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned long + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_MAX__ * 2UL + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned long + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long long + min() _GLIBCXX_USE_NOEXCEPT { return -__LONG_LONG_MAX__ - 1; } + + static _GLIBCXX_CONSTEXPR long long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_LONG_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (long long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (long long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR long long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR long long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR long long + infinity() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR long long + denorm_min() _GLIBCXX_USE_NOEXCEPT { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR unsigned long long + min() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long long + max() _GLIBCXX_USE_NOEXCEPT { return __LONG_LONG_MAX__ * 2ULL + 1; } + +#if __cplusplus >= 201103L + static constexpr unsigned long long + lowest() noexcept { return min(); } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits + = __glibcxx_digits (unsigned long long); + static _GLIBCXX_USE_CONSTEXPR int digits10 + = __glibcxx_digits10 (unsigned long long); +#if __cplusplus >= 201103L + static constexpr int max_digits10 = 0; +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; + static _GLIBCXX_USE_CONSTEXPR int radix = 2; + + static _GLIBCXX_CONSTEXPR unsigned long long + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_CONSTEXPR unsigned long long + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; + + static _GLIBCXX_CONSTEXPR unsigned long long + infinity() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + quiet_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + signaling_NaN() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_CONSTEXPR unsigned long long + denorm_min() _GLIBCXX_USE_NOEXCEPT + { return static_cast(0); } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_toward_zero; + }; + +#if !defined(__STRICT_ANSI__) + +#define __INT_N(TYPE, BITSIZE, EXT, UEXT) \ + template<> \ + struct numeric_limits \ + { \ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + min() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_min_b (TYPE, BITSIZE); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + max() _GLIBCXX_USE_NOEXCEPT { return __glibcxx_max_b (TYPE, BITSIZE); } \ + \ + static _GLIBCXX_USE_CONSTEXPR int digits \ + = BITSIZE - 1; \ + static _GLIBCXX_USE_CONSTEXPR int digits10 \ + = (BITSIZE - 1) * 643L / 2136; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; \ + static _GLIBCXX_USE_CONSTEXPR int radix = 2; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + EXT \ + \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ + = denorm_absent; \ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + infinity() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR TYPE \ + denorm_min() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool traps \ + = __glibcxx_integral_traps; \ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ + = round_toward_zero; \ + }; \ + \ + template<> \ + struct numeric_limits \ + { \ + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + min() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + max() _GLIBCXX_USE_NOEXCEPT \ + { return __glibcxx_max_b (unsigned TYPE, BITSIZE); } \ + \ + UEXT \ + \ + static _GLIBCXX_USE_CONSTEXPR int digits \ + = BITSIZE; \ + static _GLIBCXX_USE_CONSTEXPR int digits10 \ + = BITSIZE * 643L / 2136; \ + static _GLIBCXX_USE_CONSTEXPR bool is_signed = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_integer = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_exact = true; \ + static _GLIBCXX_USE_CONSTEXPR int radix = 2; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + epsilon() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + round_error() _GLIBCXX_USE_NOEXCEPT { return 0; } \ + \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent = 0; \ + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = 0; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = false; \ + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm \ + = denorm_absent; \ + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss = false; \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + infinity() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + quiet_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + signaling_NaN() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_CONSTEXPR unsigned TYPE \ + denorm_min() _GLIBCXX_USE_NOEXCEPT \ + { return static_cast(0); } \ + \ + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 = false; \ + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; \ + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = true; \ + \ + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_integral_traps; \ + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = false; \ + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style \ + = round_toward_zero; \ + }; + +#if __cplusplus >= 201103L + +#define __INT_N_201103(TYPE) \ + static constexpr TYPE \ + lowest() noexcept { return min(); } \ + static constexpr int max_digits10 = 0; + +#define __INT_N_U201103(TYPE) \ + static constexpr unsigned TYPE \ + lowest() noexcept { return min(); } \ + static constexpr int max_digits10 = 0; + +#else +#define __INT_N_201103(TYPE) +#define __INT_N_U201103(TYPE) +#endif + +#ifdef __GLIBCXX_TYPE_INT_N_0 + __INT_N(__GLIBCXX_TYPE_INT_N_0, __GLIBCXX_BITSIZE_INT_N_0, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_0), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_0)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_1 + __INT_N (__GLIBCXX_TYPE_INT_N_1, __GLIBCXX_BITSIZE_INT_N_1, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_1), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_1)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_2 + __INT_N (__GLIBCXX_TYPE_INT_N_2, __GLIBCXX_BITSIZE_INT_N_2, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_2), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_2)) +#endif +#ifdef __GLIBCXX_TYPE_INT_N_3 + __INT_N (__GLIBCXX_TYPE_INT_N_3, __GLIBCXX_BITSIZE_INT_N_3, + __INT_N_201103 (__GLIBCXX_TYPE_INT_N_3), __INT_N_U201103 (__GLIBCXX_TYPE_INT_N_3)) +#endif + +#undef __INT_N +#undef __INT_N_201103 +#undef __INT_N_U201103 + +#endif + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR float + min() _GLIBCXX_USE_NOEXCEPT { return __FLT_MIN__; } + + static _GLIBCXX_CONSTEXPR float + max() _GLIBCXX_USE_NOEXCEPT { return __FLT_MAX__; } + +#if __cplusplus >= 201103L + static constexpr float + lowest() noexcept { return -__FLT_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __FLT_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __FLT_DIG__; +#if __cplusplus >= 201103L + static constexpr int max_digits10 + = __glibcxx_max_digits10 (__FLT_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR float + epsilon() _GLIBCXX_USE_NOEXCEPT { return __FLT_EPSILON__; } + + static _GLIBCXX_CONSTEXPR float + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5F; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __FLT_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __FLT_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __FLT_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __FLT_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __FLT_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __FLT_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__FLT_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_float_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR float + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_valf(); } + + static _GLIBCXX_CONSTEXPR float + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nanf(""); } + + static _GLIBCXX_CONSTEXPR float + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nansf(""); } + + static _GLIBCXX_CONSTEXPR float + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __FLT_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_float_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before + = __glibcxx_float_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_to_nearest; + }; + +#undef __glibcxx_float_has_denorm_loss +#undef __glibcxx_float_traps +#undef __glibcxx_float_tinyness_before + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR double + min() _GLIBCXX_USE_NOEXCEPT { return __DBL_MIN__; } + + static _GLIBCXX_CONSTEXPR double + max() _GLIBCXX_USE_NOEXCEPT { return __DBL_MAX__; } + +#if __cplusplus >= 201103L + static constexpr double + lowest() noexcept { return -__DBL_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __DBL_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __DBL_DIG__; +#if __cplusplus >= 201103L + static constexpr int max_digits10 + = __glibcxx_max_digits10 (__DBL_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR double + epsilon() _GLIBCXX_USE_NOEXCEPT { return __DBL_EPSILON__; } + + static _GLIBCXX_CONSTEXPR double + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __DBL_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __DBL_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __DBL_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __DBL_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __DBL_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __DBL_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__DBL_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_double_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR double + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_val(); } + + static _GLIBCXX_CONSTEXPR double + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nan(""); } + + static _GLIBCXX_CONSTEXPR double + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nans(""); } + + static _GLIBCXX_CONSTEXPR double + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __DBL_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_double_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before + = __glibcxx_double_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style + = round_to_nearest; + }; + +#undef __glibcxx_double_has_denorm_loss +#undef __glibcxx_double_traps +#undef __glibcxx_double_tinyness_before + + /// numeric_limits specialization. + template<> + struct numeric_limits + { + static _GLIBCXX_USE_CONSTEXPR bool is_specialized = true; + + static _GLIBCXX_CONSTEXPR long double + min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_MIN__; } + + static _GLIBCXX_CONSTEXPR long double + max() _GLIBCXX_USE_NOEXCEPT { return __LDBL_MAX__; } + +#if __cplusplus >= 201103L + static constexpr long double + lowest() noexcept { return -__LDBL_MAX__; } +#endif + + static _GLIBCXX_USE_CONSTEXPR int digits = __LDBL_MANT_DIG__; + static _GLIBCXX_USE_CONSTEXPR int digits10 = __LDBL_DIG__; +#if __cplusplus >= 201103L + static _GLIBCXX_USE_CONSTEXPR int max_digits10 + = __glibcxx_max_digits10 (__LDBL_MANT_DIG__); +#endif + static _GLIBCXX_USE_CONSTEXPR bool is_signed = true; + static _GLIBCXX_USE_CONSTEXPR bool is_integer = false; + static _GLIBCXX_USE_CONSTEXPR bool is_exact = false; + static _GLIBCXX_USE_CONSTEXPR int radix = __FLT_RADIX__; + + static _GLIBCXX_CONSTEXPR long double + epsilon() _GLIBCXX_USE_NOEXCEPT { return __LDBL_EPSILON__; } + + static _GLIBCXX_CONSTEXPR long double + round_error() _GLIBCXX_USE_NOEXCEPT { return 0.5L; } + + static _GLIBCXX_USE_CONSTEXPR int min_exponent = __LDBL_MIN_EXP__; + static _GLIBCXX_USE_CONSTEXPR int min_exponent10 = __LDBL_MIN_10_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent = __LDBL_MAX_EXP__; + static _GLIBCXX_USE_CONSTEXPR int max_exponent10 = __LDBL_MAX_10_EXP__; + + static _GLIBCXX_USE_CONSTEXPR bool has_infinity = __LDBL_HAS_INFINITY__; + static _GLIBCXX_USE_CONSTEXPR bool has_quiet_NaN = __LDBL_HAS_QUIET_NAN__; + static _GLIBCXX_USE_CONSTEXPR bool has_signaling_NaN = has_quiet_NaN; + static _GLIBCXX_USE_CONSTEXPR float_denorm_style has_denorm + = bool(__LDBL_HAS_DENORM__) ? denorm_present : denorm_absent; + static _GLIBCXX_USE_CONSTEXPR bool has_denorm_loss + = __glibcxx_long_double_has_denorm_loss; + + static _GLIBCXX_CONSTEXPR long double + infinity() _GLIBCXX_USE_NOEXCEPT { return __builtin_huge_vall(); } + + static _GLIBCXX_CONSTEXPR long double + quiet_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nanl(""); } + + static _GLIBCXX_CONSTEXPR long double + signaling_NaN() _GLIBCXX_USE_NOEXCEPT { return __builtin_nansl(""); } + + static _GLIBCXX_CONSTEXPR long double + denorm_min() _GLIBCXX_USE_NOEXCEPT { return __LDBL_DENORM_MIN__; } + + static _GLIBCXX_USE_CONSTEXPR bool is_iec559 + = has_infinity && has_quiet_NaN && has_denorm == denorm_present; + static _GLIBCXX_USE_CONSTEXPR bool is_bounded = true; + static _GLIBCXX_USE_CONSTEXPR bool is_modulo = false; + + static _GLIBCXX_USE_CONSTEXPR bool traps = __glibcxx_long_double_traps; + static _GLIBCXX_USE_CONSTEXPR bool tinyness_before = + __glibcxx_long_double_tinyness_before; + static _GLIBCXX_USE_CONSTEXPR float_round_style round_style = + round_to_nearest; + }; + +#undef __glibcxx_long_double_has_denorm_loss +#undef __glibcxx_long_double_traps +#undef __glibcxx_long_double_tinyness_before + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#undef __glibcxx_signed +#undef __glibcxx_min +#undef __glibcxx_max +#undef __glibcxx_digits +#undef __glibcxx_digits10 +#undef __glibcxx_max_digits10 + +#endif // _GLIBCXX_NUMERIC_LIMITS diff --git a/resources/sources/avr-libstdcpp/include/list b/resources/sources/avr-libstdcpp/include/list new file mode 100644 index 000000000..7b3d3c2e8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/list @@ -0,0 +1,109 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/list + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_LIST +#define _GLIBCXX_LIST 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template + using list = std::list<_Tp, polymorphic_allocator<_Tp>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_erase_if 202002L + + template + inline typename list<_Tp, _Alloc>::size_type + erase_if(list<_Tp, _Alloc>& __cont, _Predicate __pred) + { return __cont.remove_if(__pred); } + + template + inline typename list<_Tp, _Alloc>::size_type + erase(list<_Tp, _Alloc>& __cont, const _Up& __value) + { + using __elem_type = typename list<_Tp, _Alloc>::value_type; + return std::erase_if(__cont, [&](__elem_type& __elem) { + return __elem == __value; + }); + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_LIST */ diff --git a/resources/sources/avr-libstdcpp/include/map b/resources/sources/avr-libstdcpp/include/map new file mode 100644 index 000000000..9e8f76b48 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/map @@ -0,0 +1,109 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/map + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_MAP +#define _GLIBCXX_MAP 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template> + using map + = std::map<_Key, _Tp, _Cmp, + polymorphic_allocator>>; + template> + using multimap + = std::multimap<_Key, _Tp, _Cmp, + polymorphic_allocator>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template + inline typename map<_Key, _Tp, _Compare, _Alloc>::size_type + erase_if(map<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } + + template + inline typename multimap<_Key, _Tp, _Compare, _Alloc>::size_type + erase_if(multimap<_Key, _Tp, _Compare, _Alloc>& __cont, _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_MAP */ diff --git a/resources/sources/avr-libstdcpp/include/memory b/resources/sources/avr-libstdcpp/include/memory new file mode 100644 index 000000000..0ed1a86b5 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/memory @@ -0,0 +1,404 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * Copyright (c) 1997-1999 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + */ + +/** @file include/memory + * This is a Standard C++ Library header. + * @ingroup memory + */ + +#ifndef _GLIBCXX_MEMORY +#define _GLIBCXX_MEMORY 1 + +#pragma GCC system_header + +/** + * @defgroup memory Memory + * @ingroup utilities + * + * Components for memory allocation, deallocation, and management. + */ + +/** + * @defgroup pointer_abstractions Pointer Abstractions + * @ingroup memory + * + * Smart pointers, etc. + */ + +#include +#include +#include +#include +#include +#include +#include + +#if __cplusplus >= 201103L +# include +# include +# include // std::less +# include +# include +# include +# include +# include +#endif + +#if __cplusplus >= 201103L +#include +#if __cplusplus > 201703L +# include // for has_single_bit +# include // for placement operator new +# include // for tuple, make_tuple, make_from_tuple +#endif +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** + * @brief Fit aligned storage in buffer. + * @ingroup memory + * + * This function tries to fit @a __size bytes of storage with alignment + * @a __align into the buffer @a __ptr of size @a __space bytes. If such + * a buffer fits then @a __ptr is changed to point to the first byte of the + * aligned storage and @a __space is reduced by the bytes used for alignment. + * + * C++11 20.6.5 [ptr.align] + * + * @param __align A fundamental or extended alignment value. + * @param __size Size of the aligned storage required. + * @param __ptr Pointer to a buffer of @a __space bytes. + * @param __space Size of the buffer pointed to by @a __ptr. + * @return the updated pointer if the aligned storage fits, otherwise nullptr. + * + */ +inline void* +align(size_t __align, size_t __size, void*& __ptr, size_t& __space) noexcept +{ +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + const auto __intptr = reinterpret_cast(__ptr); +#else + // Cannot use std::uintptr_t so assume that std::size_t can be used instead. + static_assert(sizeof(size_t) >= sizeof(void*), + "std::size_t must be a suitable substitute for std::uintptr_t"); + const auto __intptr = reinterpret_cast(__ptr); +#endif + const auto __aligned = (__intptr - 1u + __align) & -__align; + const auto __diff = __aligned - __intptr; + if ((__size + __diff) > __space) + return nullptr; + else + { + __space -= __diff; + return __ptr = reinterpret_cast(__aligned); + } +} + +/** @defgroup ptr_safety Pointer Safety and Garbage Collection + * @ingroup memory + * + * Utilities to assist with garbage collection in an implementation + * that supports strict pointer safety. + * This implementation only supports relaxed pointer safety + * and so these functions have no effect. + * + * C++11 20.6.4 [util.dynamic.safety], Pointer safety + * + * @{ + */ + +/// Constants representing the different types of pointer safety. +enum class pointer_safety { relaxed, preferred, strict }; + +/// Inform a garbage collector that an object is still in use. +inline void +declare_reachable(void*) { } + +/// Unregister an object previously registered with declare_reachable. +template + inline _Tp* + undeclare_reachable(_Tp* __p) { return __p; } + +/// Inform a garbage collector that a region of memory need not be traced. +inline void +declare_no_pointers(char*, size_t) { } + +/// Unregister a range previously registered with declare_no_pointers. +inline void +undeclare_no_pointers(char*, size_t) { } + +/// The type of pointer safety supported by the implementation. +inline pointer_safety +get_pointer_safety() noexcept { return pointer_safety::relaxed; } +// @} + +#if __cplusplus > 201703L +#define __cpp_lib_assume_aligned 201811L + /** @brief Inform the compiler that a pointer is aligned. + * + * @tparam _Align An alignment value (i.e. a power of two) + * @tparam _Tp An object type + * @param __ptr A pointer that is aligned to _Align + * + * C++20 20.10.6 [ptr.align] + * + * @ingroup memory + */ + template + [[nodiscard,__gnu__::__always_inline__]] + constexpr _Tp* + assume_aligned(_Tp* __ptr) noexcept + { + static_assert(std::has_single_bit(_Align)); + if (std::is_constant_evaluated()) + return __ptr; + else + { + // This function is expected to be used in hot code, where + // __glibcxx_assert would add unwanted overhead. + _GLIBCXX_DEBUG_ASSERT((std::uintptr_t)__ptr % _Align == 0); + return static_cast<_Tp*>(__builtin_assume_aligned(__ptr, _Align)); + } + } +#endif // C++2a + +#if __cplusplus > 201703L + template + struct __is_pair : false_type { }; + template + struct __is_pair> : true_type { }; + template + struct __is_pair> : true_type { }; + +/** @addtogroup allocators + * @{ + */ + template>>, + typename _Alloc, typename... _Args> + constexpr auto + __uses_alloc_args(const _Alloc& __a, _Args&&... __args) noexcept + { + if constexpr (uses_allocator_v, _Alloc>) + { + if constexpr (is_constructible_v<_Tp, allocator_arg_t, + const _Alloc&, _Args...>) + { + return tuple( + allocator_arg, __a, std::forward<_Args>(__args)...); + } + else + { + static_assert(is_constructible_v<_Tp, _Args..., const _Alloc&>, + "construction with an allocator must be possible" + " if uses_allocator is true"); + + return tuple<_Args&&..., const _Alloc&>( + std::forward<_Args>(__args)..., __a); + } + } + else + { + static_assert(is_constructible_v<_Tp, _Args...>); + + return tuple<_Args&&...>(std::forward<_Args>(__args)...); + } + } + +#if __cpp_concepts + template + concept _Std_pair = __is_pair<_Tp>::value; +#endif + +// This is a temporary workaround until -fconcepts is implied by -std=gnu++2a +#if __cpp_concepts +# define _GLIBCXX_STD_PAIR_CONSTRAINT(T) _Std_pair T +# define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) _Std_pair T +#else +# define _GLIBCXX_STD_PAIR_CONSTRAINT(T) \ + typename T, typename __ = _Require<__is_pair> +# define _GLIBCXX_STD_PAIR_CONSTRAINT_(T) typename T, typename +#endif + + template>>, +#endif + typename _Alloc, typename... _Args> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + _Args&&... __args) noexcept +#if __cpp_concepts + requires (! _Std_pair<_Tp>) +#endif + { + return std::__uses_alloc_args<_Tp>(__a, std::forward<_Args>(__args)...); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, + typename _Tuple1, typename _Tuple2> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, + _Tuple1&& __x, _Tuple2&& __y) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc> + constexpr auto + uses_allocator_construction_args(const _Alloc&) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, _Up&&, _Vp&&) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, + const pair<_Up, _Vp>&) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc&, pair<_Up, _Vp>&&) noexcept; + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, + typename _Tuple1, typename _Tuple2> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, piecewise_construct_t, + _Tuple1&& __x, _Tuple2&& __y) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::apply([&__a](auto&&... __args1) { + return std::uses_allocator_construction_args<_Tp1>( + __a, std::forward(__args1)...); + }, std::forward<_Tuple1>(__x)), + std::apply([&__a](auto&&... __args2) { + return std::uses_allocator_construction_args<_Tp2>( + __a, std::forward(__args2)...); + }, std::forward<_Tuple2>(__y))); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a), + std::uses_allocator_construction_args<_Tp2>(__a)); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, _Up&& __u, _Vp&& __v) + noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, + std::forward<_Up>(__u)), + std::uses_allocator_construction_args<_Tp2>(__a, + std::forward<_Vp>(__v))); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + const pair<_Up, _Vp>& __pr) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, __pr.first), + std::uses_allocator_construction_args<_Tp2>(__a, __pr.second)); + } + + template<_GLIBCXX_STD_PAIR_CONSTRAINT_(_Tp), typename _Alloc, + typename _Up, typename _Vp> + constexpr auto + uses_allocator_construction_args(const _Alloc& __a, + pair<_Up, _Vp>&& __pr) noexcept + { + using _Tp1 = typename _Tp::first_type; + using _Tp2 = typename _Tp::second_type; + + return std::make_tuple(piecewise_construct, + std::uses_allocator_construction_args<_Tp1>(__a, + std::move(__pr).first), + std::uses_allocator_construction_args<_Tp2>(__a, + std::move(__pr).second)); + } + + template + inline _Tp + make_obj_using_allocator(const _Alloc& __a, _Args&&... __args) + { + return std::make_from_tuple<_Tp>( + std::uses_allocator_construction_args<_Tp>(__a, + std::forward<_Args>(__args)...)); + } + + template + inline _Tp* + uninitialized_construct_using_allocator(_Tp* __p, const _Alloc& __a, + _Args&&... __args) + { + return std::apply([&](auto&&... __xs) { + return std::construct_at(__p, std::forward(__xs)...); + }, std::uses_allocator_construction_args<_Tp>(__a, + std::forward<_Args>(__args)...)); + } +// @} + +#endif // C++2a + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // C++11 + +#endif /* _GLIBCXX_MEMORY */ diff --git a/resources/sources/avr-libstdcpp/include/mutex b/resources/sources/avr-libstdcpp/include/mutex new file mode 100644 index 000000000..389504d7d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/mutex @@ -0,0 +1,746 @@ +// -*- C++ -*- + +// Copyright (C) 2003-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/mutex + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_MUTEX +#define _GLIBCXX_MUTEX 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#ifndef _GLIBCXX_HAVE_TLS +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup mutexes + * @{ + */ + +#ifdef _GLIBCXX_HAS_GTHREADS + + // Common base class for std::recursive_mutex and std::recursive_timed_mutex + class __recursive_mutex_base + { + protected: + typedef __gthread_recursive_mutex_t __native_type; + + __recursive_mutex_base(const __recursive_mutex_base&) = delete; + __recursive_mutex_base& operator=(const __recursive_mutex_base&) = delete; + +#ifdef __GTHREAD_RECURSIVE_MUTEX_INIT + __native_type _M_mutex = __GTHREAD_RECURSIVE_MUTEX_INIT; + + __recursive_mutex_base() = default; +#else + __native_type _M_mutex; + + __recursive_mutex_base() + { + // XXX EAGAIN, ENOMEM, EPERM, EBUSY(may), EINVAL(may) + __GTHREAD_RECURSIVE_MUTEX_INIT_FUNCTION(&_M_mutex); + } + + ~__recursive_mutex_base() + { __gthread_recursive_mutex_destroy(&_M_mutex); } +#endif + }; + + /// The standard recursive mutex type. + class recursive_mutex : private __recursive_mutex_base + { + public: + typedef __native_type* native_handle_type; + + recursive_mutex() = default; + ~recursive_mutex() = default; + + recursive_mutex(const recursive_mutex&) = delete; + recursive_mutex& operator=(const recursive_mutex&) = delete; + + void + lock() + { + int __e = __gthread_recursive_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() noexcept + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_recursive_mutex_trylock(&_M_mutex); + } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EBUSY + __gthread_recursive_mutex_unlock(&_M_mutex); + } + + native_handle_type + native_handle() noexcept + { return &_M_mutex; } + }; + +#if _GTHREAD_USE_MUTEX_TIMEDLOCK + template + class __timed_mutex_impl + { + protected: + template + bool + _M_try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { +#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK + using __clock = chrono::steady_clock; +#else + using __clock = chrono::system_clock; +#endif + + auto __rt = chrono::duration_cast<__clock::duration>(__rtime); + if (ratio_greater<__clock::period, _Period>()) + ++__rt; + return _M_try_lock_until(__clock::now() + __rt); + } + + template + bool + _M_try_lock_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + return static_cast<_Derived*>(this)->_M_timedlock(__ts); + } + +#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK + template + bool + _M_try_lock_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + return static_cast<_Derived*>(this)->_M_clocklock(CLOCK_MONOTONIC, + __ts); + } +#endif + + template + bool + _M_try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { +#if __cplusplus > 201703L + static_assert(chrono::is_clock_v<_Clock>); +#endif + // The user-supplied clock may not tick at the same rate as + // steady_clock, so we must loop in order to guarantee that + // the timeout has expired before returning false. + auto __now = _Clock::now(); + do { + auto __rtime = __atime - __now; + if (_M_try_lock_for(__rtime)) + return true; + __now = _Clock::now(); + } while (__atime > __now); + return false; + } + }; + + /// The standard timed mutex type. + class timed_mutex + : private __mutex_base, public __timed_mutex_impl + { + public: + typedef __native_type* native_handle_type; + + timed_mutex() = default; + ~timed_mutex() = default; + + timed_mutex(const timed_mutex&) = delete; + timed_mutex& operator=(const timed_mutex&) = delete; + + void + lock() + { + int __e = __gthread_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() noexcept + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_mutex_trylock(&_M_mutex); + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { return _M_try_lock_for(__rtime); } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { return _M_try_lock_until(__atime); } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EBUSY + __gthread_mutex_unlock(&_M_mutex); + } + + native_handle_type + native_handle() noexcept + { return &_M_mutex; } + + private: + friend class __timed_mutex_impl; + + bool + _M_timedlock(const __gthread_time_t& __ts) + { return !__gthread_mutex_timedlock(&_M_mutex, &__ts); } + +#if _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK + bool + _M_clocklock(clockid_t clockid, const __gthread_time_t& __ts) + { return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); } +#endif + }; + + /// recursive_timed_mutex + class recursive_timed_mutex + : private __recursive_mutex_base, + public __timed_mutex_impl + { + public: + typedef __native_type* native_handle_type; + + recursive_timed_mutex() = default; + ~recursive_timed_mutex() = default; + + recursive_timed_mutex(const recursive_timed_mutex&) = delete; + recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; + + void + lock() + { + int __e = __gthread_recursive_mutex_lock(&_M_mutex); + + // EINVAL, EAGAIN, EBUSY, EINVAL, EDEADLK(may) + if (__e) + __throw_system_error(__e); + } + + bool + try_lock() noexcept + { + // XXX EINVAL, EAGAIN, EBUSY + return !__gthread_recursive_mutex_trylock(&_M_mutex); + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { return _M_try_lock_for(__rtime); } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { return _M_try_lock_until(__atime); } + + void + unlock() + { + // XXX EINVAL, EAGAIN, EBUSY + __gthread_recursive_mutex_unlock(&_M_mutex); + } + + native_handle_type + native_handle() noexcept + { return &_M_mutex; } + + private: + friend class __timed_mutex_impl; + + bool + _M_timedlock(const __gthread_time_t& __ts) + { return !__gthread_recursive_mutex_timedlock(&_M_mutex, &__ts); } + +#ifdef _GLIBCXX_USE_PTHREAD_MUTEX_CLOCKLOCK + bool + _M_clocklock(clockid_t clockid, const __gthread_time_t& __ts) + { return !pthread_mutex_clocklock(&_M_mutex, clockid, &__ts); } +#endif + }; + +#else // !_GTHREAD_USE_MUTEX_TIMEDLOCK + + /// timed_mutex + class timed_mutex + { + mutex _M_mut; + condition_variable _M_cv; + bool _M_locked = false; + + public: + + timed_mutex() = default; + ~timed_mutex() { __glibcxx_assert( !_M_locked ); } + + timed_mutex(const timed_mutex&) = delete; + timed_mutex& operator=(const timed_mutex&) = delete; + + void + lock() + { + unique_lock __lk(_M_mut); + _M_cv.wait(__lk, [&]{ return !_M_locked; }); + _M_locked = true; + } + + bool + try_lock() + { + lock_guard __lk(_M_mut); + if (_M_locked) + return false; + _M_locked = true; + return true; + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + unique_lock __lk(_M_mut); + if (!_M_cv.wait_for(__lk, __rtime, [&]{ return !_M_locked; })) + return false; + _M_locked = true; + return true; + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + unique_lock __lk(_M_mut); + if (!_M_cv.wait_until(__lk, __atime, [&]{ return !_M_locked; })) + return false; + _M_locked = true; + return true; + } + + void + unlock() + { + lock_guard __lk(_M_mut); + __glibcxx_assert( _M_locked ); + _M_locked = false; + _M_cv.notify_one(); + } + }; + + /// recursive_timed_mutex + class recursive_timed_mutex + { + mutex _M_mut; + condition_variable _M_cv; + thread::id _M_owner; + unsigned _M_count = 0; + + // Predicate type that tests whether the current thread can lock a mutex. + struct _Can_lock + { + // Returns true if the mutex is unlocked or is locked by _M_caller. + bool + operator()() const noexcept + { return _M_mx->_M_count == 0 || _M_mx->_M_owner == _M_caller; } + + const recursive_timed_mutex* _M_mx; + thread::id _M_caller; + }; + + public: + + recursive_timed_mutex() = default; + ~recursive_timed_mutex() { __glibcxx_assert( _M_count == 0 ); } + + recursive_timed_mutex(const recursive_timed_mutex&) = delete; + recursive_timed_mutex& operator=(const recursive_timed_mutex&) = delete; + + void + lock() + { + auto __id = this_thread::get_id(); + _Can_lock __can_lock{this, __id}; + unique_lock __lk(_M_mut); + _M_cv.wait(__lk, __can_lock); + if (_M_count == -1u) + __throw_system_error(EAGAIN); // [thread.timedmutex.recursive]/3 + _M_owner = __id; + ++_M_count; + } + + bool + try_lock() + { + auto __id = this_thread::get_id(); + _Can_lock __can_lock{this, __id}; + lock_guard __lk(_M_mut); + if (!__can_lock()) + return false; + if (_M_count == -1u) + return false; + _M_owner = __id; + ++_M_count; + return true; + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + auto __id = this_thread::get_id(); + _Can_lock __can_lock{this, __id}; + unique_lock __lk(_M_mut); + if (!_M_cv.wait_for(__lk, __rtime, __can_lock)) + return false; + if (_M_count == -1u) + return false; + _M_owner = __id; + ++_M_count; + return true; + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { + auto __id = this_thread::get_id(); + _Can_lock __can_lock{this, __id}; + unique_lock __lk(_M_mut); + if (!_M_cv.wait_until(__lk, __atime, __can_lock)) + return false; + if (_M_count == -1u) + return false; + _M_owner = __id; + ++_M_count; + return true; + } + + void + unlock() + { + lock_guard __lk(_M_mut); + __glibcxx_assert( _M_owner == this_thread::get_id() ); + __glibcxx_assert( _M_count > 0 ); + if (--_M_count == 0) + { + _M_owner = {}; + _M_cv.notify_one(); + } + } + }; + +#endif +#endif // _GLIBCXX_HAS_GTHREADS + + /// @cond undocumented + template + inline unique_lock<_Lock> + __try_to_lock(_Lock& __l) + { return unique_lock<_Lock>{__l, try_to_lock}; } + + template + struct __try_lock_impl + { + template + static void + __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) + { + __idx = _Idx; + auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); + if (__lock.owns_lock()) + { + constexpr bool __cont = _Idx + 2 < sizeof...(_Lock); + using __try_locker = __try_lock_impl<_Idx + 1, __cont>; + __try_locker::__do_try_lock(__locks, __idx); + if (__idx == -1) + __lock.release(); + } + } + }; + + template + struct __try_lock_impl<_Idx, false> + { + template + static void + __do_try_lock(tuple<_Lock&...>& __locks, int& __idx) + { + __idx = _Idx; + auto __lock = std::__try_to_lock(std::get<_Idx>(__locks)); + if (__lock.owns_lock()) + { + __idx = -1; + __lock.release(); + } + } + }; + /// @endcond + + /** @brief Generic try_lock. + * @param __l1 Meets Lockable requirements (try_lock() may throw). + * @param __l2 Meets Lockable requirements (try_lock() may throw). + * @param __l3 Meets Lockable requirements (try_lock() may throw). + * @return Returns -1 if all try_lock() calls return true. Otherwise returns + * a 0-based index corresponding to the argument that returned false. + * @post Either all arguments are locked, or none will be. + * + * Sequentially calls try_lock() on each argument. + */ + template + int + try_lock(_Lock1& __l1, _Lock2& __l2, _Lock3&... __l3) + { + int __idx; + auto __locks = std::tie(__l1, __l2, __l3...); + __try_lock_impl<0>::__do_try_lock(__locks, __idx); + return __idx; + } + + /** @brief Generic lock. + * @param __l1 Meets Lockable requirements (try_lock() may throw). + * @param __l2 Meets Lockable requirements (try_lock() may throw). + * @param __l3 Meets Lockable requirements (try_lock() may throw). + * @throw An exception thrown by an argument's lock() or try_lock() member. + * @post All arguments are locked. + * + * All arguments are locked via a sequence of calls to lock(), try_lock() + * and unlock(). If the call exits via an exception any locks that were + * obtained will be released. + */ + template + void + lock(_L1& __l1, _L2& __l2, _L3&... __l3) + { + while (true) + { + using __try_locker = __try_lock_impl<0, sizeof...(_L3) != 0>; + unique_lock<_L1> __first(__l1); + int __idx; + auto __locks = std::tie(__l2, __l3...); + __try_locker::__do_try_lock(__locks, __idx); + if (__idx == -1) + { + __first.release(); + return; + } + } + } + +#if __cplusplus >= 201703L +#define __cpp_lib_scoped_lock 201703 + /** @brief A scoped lock type for multiple lockable objects. + * + * A scoped_lock controls mutex ownership within a scope, releasing + * ownership in the destructor. + */ + template + class scoped_lock + { + public: + explicit scoped_lock(_MutexTypes&... __m) : _M_devices(std::tie(__m...)) + { std::lock(__m...); } + + explicit scoped_lock(adopt_lock_t, _MutexTypes&... __m) noexcept + : _M_devices(std::tie(__m...)) + { } // calling thread owns mutex + + ~scoped_lock() + { std::apply([](auto&... __m) { (__m.unlock(), ...); }, _M_devices); } + + scoped_lock(const scoped_lock&) = delete; + scoped_lock& operator=(const scoped_lock&) = delete; + + private: + tuple<_MutexTypes&...> _M_devices; + }; + + template<> + class scoped_lock<> + { + public: + explicit scoped_lock() = default; + explicit scoped_lock(adopt_lock_t) noexcept { } + ~scoped_lock() = default; + + scoped_lock(const scoped_lock&) = delete; + scoped_lock& operator=(const scoped_lock&) = delete; + }; + + template + class scoped_lock<_Mutex> + { + public: + using mutex_type = _Mutex; + + explicit scoped_lock(mutex_type& __m) : _M_device(__m) + { _M_device.lock(); } + + explicit scoped_lock(adopt_lock_t, mutex_type& __m) noexcept + : _M_device(__m) + { } // calling thread owns mutex + + ~scoped_lock() + { _M_device.unlock(); } + + scoped_lock(const scoped_lock&) = delete; + scoped_lock& operator=(const scoped_lock&) = delete; + + private: + mutex_type& _M_device; + }; +#endif // C++17 + +#ifdef _GLIBCXX_HAS_GTHREADS + /// Flag type used by std::call_once + struct once_flag + { + private: + typedef __gthread_once_t __native_type; + __native_type _M_once = __GTHREAD_ONCE_INIT; + + public: + /// Constructor + constexpr once_flag() noexcept = default; + + /// Deleted copy constructor + once_flag(const once_flag&) = delete; + /// Deleted assignment operator + once_flag& operator=(const once_flag&) = delete; + + template + friend void + call_once(once_flag& __once, _Callable&& __f, _Args&&... __args); + }; + + /// @cond undocumented +#ifdef _GLIBCXX_HAVE_TLS + extern __thread void* __once_callable; + extern __thread void (*__once_call)(); +#else + extern function __once_functor; + + extern void + __set_once_functor_lock_ptr(unique_lock*); + + extern mutex& + __get_once_mutex(); +#endif + + extern "C" void __once_proxy(void); + /// @endcond + + /// Invoke a callable and synchronize with other calls using the same flag + template + void + call_once(once_flag& __once, _Callable&& __f, _Args&&... __args) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2442. call_once() shouldn't DECAY_COPY() + auto __callable = [&] { + std::__invoke(std::forward<_Callable>(__f), + std::forward<_Args>(__args)...); + }; +#ifdef _GLIBCXX_HAVE_TLS + __once_callable = std::__addressof(__callable); + __once_call = []{ (*(decltype(__callable)*)__once_callable)(); }; +#else + unique_lock __functor_lock(__get_once_mutex()); + __once_functor = __callable; + __set_once_functor_lock_ptr(&__functor_lock); +#endif + + int __e = __gthread_once(&__once._M_once, &__once_proxy); + +#ifndef _GLIBCXX_HAVE_TLS + if (__functor_lock) + __set_once_functor_lock_ptr(0); +#endif + +#ifdef __clang_analyzer__ + // PR libstdc++/82481 + __once_callable = nullptr; + __once_call = nullptr; +#endif + + if (__e) + __throw_system_error(__e); + } +#endif // _GLIBCXX_HAS_GTHREADS + + // @} group mutexes +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _GLIBCXX_MUTEX diff --git a/resources/sources/avr-libstdcpp/include/new b/resources/sources/avr-libstdcpp/include/new index aa5574829..06e43dc6f 100644 --- a/resources/sources/avr-libstdcpp/include/new +++ b/resources/sources/avr-libstdcpp/include/new @@ -1,7 +1,193 @@ -// Minimal for AVR -- placement new -#ifndef _AVR_NEW -#define _AVR_NEW +// The -*- C++ -*- dynamic memory management header. + +// Copyright (C) 1994-2020 Free Software Foundation, Inc. + +// This file is part of GCC. +// +// GCC is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 3, or (at your option) +// any later version. +// +// GCC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file new + * This is a Standard C++ Library header. + * + * The header @c new defines several functions to manage dynamic memory and + * handling memory allocation errors; see + * https://gcc.gnu.org/onlinedocs/libstdc++/manual/dynamic_memory.html + * for more. + */ + +#ifndef _NEW +#define _NEW + +#pragma GCC system_header + +#include #include -inline void* operator new(size_t, void* p) noexcept { return p; } -inline void* operator new[](size_t, void* p) noexcept { return p; } + +#pragma GCC visibility push(default) + +extern "C++" { + +namespace std +{ +#if __cpp_aligned_new + enum class align_val_t: size_t {}; +#endif + + struct nothrow_t + { +#if __cplusplus >= 201103L + explicit nothrow_t() = default; +#endif + }; + + extern const nothrow_t nothrow; + + /** If you write your own error handler to be called by @c new, it must + * be of this type. */ + typedef void (*new_handler)(); + + /// Takes a replacement handler as the argument, returns the + /// previous handler. + new_handler set_new_handler(new_handler) throw(); + +#if __cplusplus >= 201103L + /// Return the current new handler. + new_handler get_new_handler() noexcept; +#endif +} // namespace std + +//@{ +/** These are replaceable signatures: + * - normal single new and delete (no arguments, throw @c bad_alloc on error) + * - normal array new and delete (same) + * - @c nothrow single new and delete (take a @c nothrow argument, return + * @c NULL on error) + * - @c nothrow array new and delete (same) + * + * Placement new and delete signatures (take a memory address argument, + * does nothing) may not be replaced by a user's program. +*/ +_GLIBCXX_NODISCARD void* operator new(std::size_t) _GLIBCXX_THROW (std::bad_alloc) + __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t) _GLIBCXX_THROW (std::bad_alloc) + __attribute__((__externally_visible__)); +void operator delete(void*) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#if __cpp_sized_deallocation +void operator delete(void*, std::size_t) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*, std::size_t) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#endif +_GLIBCXX_NODISCARD void* operator new(std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__, __malloc__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__, __malloc__)); +void operator delete(void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +void operator delete[](void*, const std::nothrow_t&) _GLIBCXX_USE_NOEXCEPT + __attribute__((__externally_visible__)); +#if 0 // __cpp_aligned_new +_GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t) + __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new(std::size_t, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __malloc__)); +void operator delete(void*, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete(void*, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t) + __attribute__((__externally_visible__)); +_GLIBCXX_NODISCARD void* operator new[](std::size_t, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__, __malloc__)); +void operator delete[](void*, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete[](void*, std::align_val_t, const std::nothrow_t&) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +#if __cpp_sized_deallocation +void operator delete(void*, std::size_t, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +void operator delete[](void*, std::size_t, std::align_val_t) + _GLIBCXX_USE_NOEXCEPT __attribute__((__externally_visible__)); +#endif // __cpp_sized_deallocation +#endif // __cpp_aligned_new + +// Default placement versions of operator new. +_GLIBCXX_NODISCARD inline void* operator new(std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT +{ return __p; } +_GLIBCXX_NODISCARD inline void* operator new[](std::size_t, void* __p) _GLIBCXX_USE_NOEXCEPT +{ return __p; } + +// Default placement versions of operator delete. +inline void operator delete (void*, void*) _GLIBCXX_USE_NOEXCEPT { } +inline void operator delete[](void*, void*) _GLIBCXX_USE_NOEXCEPT { } +//@} +} // extern "C++" + +#if __cplusplus >= 201703L +#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER +namespace std +{ +#define __cpp_lib_launder 201606 + /// Pointer optimization barrier [ptr.launder] + template + [[nodiscard]] constexpr _Tp* + launder(_Tp* __p) noexcept + { return __builtin_launder(__p); } + + // The program is ill-formed if T is a function type or + // (possibly cv-qualified) void. + + template + void launder(_Ret (*)(_Args...) _GLIBCXX_NOEXCEPT_QUAL) = delete; + template + void launder(_Ret (*)(_Args......) _GLIBCXX_NOEXCEPT_QUAL) = delete; + + void launder(void*) = delete; + void launder(const void*) = delete; + void launder(volatile void*) = delete; + void launder(const volatile void*) = delete; +} +#endif // _GLIBCXX_HAVE_BUILTIN_LAUNDER +#endif // C++17 + +#if __cplusplus > 201703L +namespace std +{ + /// Tag type used to declare a class-specific operator delete that can + /// invoke the destructor before deallocating the memory. + struct destroying_delete_t + { + explicit destroying_delete_t() = default; + }; + /// Tag variable of type destroying_delete_t. + inline constexpr destroying_delete_t destroying_delete{}; +} +// Only define the feature test macro if the compiler supports the feature: +#if __cpp_impl_destroying_delete +# define __cpp_lib_destroying_delete 201806L +#endif +#endif // C++20 + +#pragma GCC visibility pop + #endif diff --git a/resources/sources/avr-libstdcpp/include/numbers b/resources/sources/avr-libstdcpp/include/numbers new file mode 100644 index 000000000..7e51851bd --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/numbers @@ -0,0 +1,208 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/numbers + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_NUMBERS +#define _GLIBCXX_NUMBERS 1 + +#pragma GCC system_header + +#if __cplusplus > 201703L + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +/** @defgroup math_constants Mathematical constants + * @ingroup numerics + * @{ + */ + +/// Namespace for mathematical constants +namespace numbers +{ +#define __cpp_lib_math_constants 201907L + + /// @cond undoc + template + using _Enable_if_floating = enable_if_t, _Tp>; + /// @endcond + + /// e + template + inline constexpr _Tp e_v + = _Enable_if_floating<_Tp>(2.718281828459045235360287471352662498L); + + /// log_2 e + template + inline constexpr _Tp log2e_v + = _Enable_if_floating<_Tp>(1.442695040888963407359924681001892137L); + + /// log_10 e + template + inline constexpr _Tp log10e_v + = _Enable_if_floating<_Tp>(0.434294481903251827651128918916605082L); + + /// pi + template + inline constexpr _Tp pi_v + = _Enable_if_floating<_Tp>(3.141592653589793238462643383279502884L); + + /// 1/pi + template + inline constexpr _Tp inv_pi_v + = _Enable_if_floating<_Tp>(0.318309886183790671537767526745028724L); + + /// 1/sqrt(pi) + template + inline constexpr _Tp inv_sqrtpi_v + = _Enable_if_floating<_Tp>(0.564189583547756286948079451560772586L); + + /// log_e 2 + template + inline constexpr _Tp ln2_v + = _Enable_if_floating<_Tp>(0.693147180559945309417232121458176568L); + + /// log_e 10 + template + inline constexpr _Tp ln10_v + = _Enable_if_floating<_Tp>(2.302585092994045684017991454684364208L); + + /// sqrt(2) + template + inline constexpr _Tp sqrt2_v + = _Enable_if_floating<_Tp>(1.414213562373095048801688724209698079L); + + /// sqrt(3) + template + inline constexpr _Tp sqrt3_v + = _Enable_if_floating<_Tp>(1.732050807568877293527446341505872367L); + + /// 1/sqrt(3) + template + inline constexpr _Tp inv_sqrt3_v + = _Enable_if_floating<_Tp>(0.577350269189625764509148780501957456L); + + /// The Euler-Mascheroni constant + template + inline constexpr _Tp egamma_v + = _Enable_if_floating<_Tp>(0.577215664901532860606512090082402431L); + + /// The golden ratio, (1+sqrt(5))/2 + template + inline constexpr _Tp phi_v + = _Enable_if_floating<_Tp>(1.618033988749894848204586834365638118L); + + inline constexpr double e = e_v; + inline constexpr double log2e = log2e_v; + inline constexpr double log10e = log10e_v; + inline constexpr double pi = pi_v; + inline constexpr double inv_pi = inv_pi_v; + inline constexpr double inv_sqrtpi = inv_sqrtpi_v; + inline constexpr double ln2 = ln2_v; + inline constexpr double ln10 = ln10_v; + inline constexpr double sqrt2 = sqrt2_v; + inline constexpr double sqrt3 = sqrt3_v; + inline constexpr double inv_sqrt3 = inv_sqrt3_v; + inline constexpr double egamma = egamma_v; + inline constexpr double phi = phi_v; + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + template<> + inline constexpr __float128 e_v<__float128> + = 2.718281828459045235360287471352662498Q; + + /// log_2 e + template<> + inline constexpr __float128 log2e_v<__float128> + = 1.442695040888963407359924681001892137Q; + + /// log_10 e + template<> + inline constexpr __float128 log10e_v<__float128> + = 0.434294481903251827651128918916605082Q; + + /// pi + template<> + inline constexpr __float128 pi_v<__float128> + = 3.141592653589793238462643383279502884Q; + + /// 1/pi + template<> + inline constexpr __float128 inv_pi_v<__float128> + = 0.318309886183790671537767526745028724Q; + + /// 1/sqrt(pi) + template<> + inline constexpr __float128 inv_sqrtpi_v<__float128> + = 0.564189583547756286948079451560772586Q; + + /// log_e 2 + template<> + inline constexpr __float128 ln2_v<__float128> + = 0.693147180559945309417232121458176568Q; + + /// log_e 10 + template<> + inline constexpr __float128 ln10_v<__float128> + = 2.302585092994045684017991454684364208Q; + + /// sqrt(2) + template<> + inline constexpr __float128 sqrt2_v<__float128> + = 1.414213562373095048801688724209698079Q; + + /// sqrt(3) + template<> + inline constexpr __float128 sqrt3_v<__float128> + = 1.732050807568877293527446341505872367Q; + + /// 1/sqrt(3) + template<> + inline constexpr __float128 inv_sqrt3_v<__float128> + = 0.577350269189625764509148780501957456Q; + + /// The Euler-Mascheroni constant + template<> + inline constexpr __float128 egamma_v<__float128> + = 0.577215664901532860606512090082402431Q; + + /// The golden ratio, (1+sqrt(5))/2 + template<> + inline constexpr __float128 phi_v<__float128> + = 1.618033988749894848204586834365638118Q; +#endif // USE_FLOAT128 + +} // namespace numbers +/// @} +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++20 +#endif // _GLIBCXX_NUMBERS diff --git a/resources/sources/avr-libstdcpp/include/numeric b/resources/sources/avr-libstdcpp/include/numeric new file mode 100644 index 000000000..7793c9db3 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/numeric @@ -0,0 +1,699 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/numeric + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_NUMERIC +#define _GLIBCXX_NUMERIC 1 + +#pragma GCC system_header + +#include +#include +#include +#include + +/** + * @defgroup numerics Numerics + * + * Components for performing numeric operations. Includes support for + * complex number types, random number generation, numeric (n-at-a-time) + * arrays, generalized numeric algorithms, and mathematical special functions. + */ + +#if __cplusplus >= 201402L +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __detail +{ + // std::abs is not constexpr, doesn't support unsigned integers, + // and std::abs(std::numeric_limits::min()) is undefined. + template + constexpr _Up + __absu(_Tp __val) + { + static_assert(is_unsigned<_Up>::value, "result type must be unsigned"); + static_assert(sizeof(_Up) >= sizeof(_Tp), + "result type must be at least as wide as the input type"); + return __val < 0 ? -(_Up)__val : (_Up)__val; + } + + template void __absu(bool) = delete; + + // GCD implementation + template + constexpr _Tp + __gcd(_Tp __m, _Tp __n) + { + static_assert(is_unsigned<_Tp>::value, "type must be unsigned"); + return __m == 0 ? __n + : __n == 0 ? __m + : __detail::__gcd(__n, _Tp(__m % __n)); + } + + // LCM implementation + template + constexpr _Tp + __lcm(_Tp __m, _Tp __n) + { + return (__m != 0 && __n != 0) + ? (__m / __detail::__gcd(__m, __n)) * __n + : 0; + } +} // namespace __detail + +#if __cplusplus >= 201703L + +#define __cpp_lib_gcd_lcm 201606 +// These were used in drafts of SD-6: +#define __cpp_lib_gcd 201606 +#define __cpp_lib_lcm 201606 + + /// Greatest common divisor + template + constexpr common_type_t<_Mn, _Nn> + gcd(_Mn __m, _Nn __n) noexcept + { + static_assert(is_integral_v<_Mn>, "std::gcd arguments must be integers"); + static_assert(is_integral_v<_Nn>, "std::gcd arguments must be integers"); + static_assert(_Mn(2) != _Mn(1), "std::gcd arguments must not be bool"); + static_assert(_Nn(2) != _Nn(1), "std::gcd arguments must not be bool"); + using _Up = make_unsigned_t>; + return __detail::__gcd(__detail::__absu<_Up>(__m), + __detail::__absu<_Up>(__n)); + } + + /// Least common multiple + template + constexpr common_type_t<_Mn, _Nn> + lcm(_Mn __m, _Nn __n) noexcept + { + static_assert(is_integral_v<_Mn>, "std::lcm arguments must be integers"); + static_assert(is_integral_v<_Nn>, "std::lcm arguments must be integers"); + static_assert(_Mn(2) == 2, "std::lcm arguments must not be bool"); + static_assert(_Nn(2) == 2, "std::lcm arguments must not be bool"); + using _Up = make_unsigned_t>; + return __detail::__lcm(__detail::__absu<_Up>(__m), + __detail::__absu<_Up>(__n)); + } + +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++14 + +#if __cplusplus > 201703L +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + // midpoint +# define __cpp_lib_interpolate 201902L + + template + constexpr + enable_if_t<__and_v, is_same, _Tp>, + __not_>>, + _Tp> + midpoint(_Tp __a, _Tp __b) noexcept + { + if constexpr (is_integral_v<_Tp>) + { + using _Up = make_unsigned_t<_Tp>; + + int __k = 1; + _Up __m = __a; + _Up __M = __b; + if (__a > __b) + { + __k = -1; + __m = __b; + __M = __a; + } + return __a + __k * _Tp(_Up(__M - __m) / 2); + } + else // is_floating + { + constexpr _Tp __lo = numeric_limits<_Tp>::min() * 2; + constexpr _Tp __hi = numeric_limits<_Tp>::max() / 2; + const _Tp __abs_a = __a < 0 ? -__a : __a; + const _Tp __abs_b = __b < 0 ? -__b : __b; + if (__abs_a <= __hi && __abs_b <= __hi) [[likely]] + return (__a + __b) / 2; // always correctly rounded + if (__abs_a < __lo) // not safe to halve __a + return __a + __b/2; + if (__abs_b < __lo) // not safe to halve __b + return __a/2 + __b; + return __a/2 + __b/2; // otherwise correctly rounded + } + } + + template + constexpr enable_if_t, _Tp*> + midpoint(_Tp* __a, _Tp* __b) noexcept + { + static_assert( sizeof(_Tp) != 0, "type must be complete" ); + return __a + (__b - __a) / 2; + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++20 + +#if __cplusplus > 201402L +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#if __cplusplus > 201703L +#define __cpp_lib_constexpr_numeric 201911L +#endif + + /// @addtogroup numeric_ops + /// @{ + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op A binary function object. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using a binary operation. + * The initial value is `init`. The values are not necessarily processed + * in order. + * + * This algorithm is similar to `std::accumulate` but is not required to + * perform the operations in order from first to last. For operations + * that are commutative and associative the result will be the same as + * for `std::accumulate`, but for other operations (such as floating point + * arithmetic) the result can be different. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + reduce(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op) + { + using value_type = typename iterator_traits<_InputIterator>::value_type; + static_assert(is_invocable_r_v<_Tp, _BinaryOperation&, _Tp&, _Tp&>); + static_assert(is_convertible_v); + if constexpr (__is_random_access_iter<_InputIterator>::value) + { + while ((__last - __first) >= 4) + { + _Tp __v1 = __binary_op(__first[0], __first[1]); + _Tp __v2 = __binary_op(__first[2], __first[3]); + _Tp __v3 = __binary_op(__v1, __v2); + __init = __binary_op(__init, __v3); + __first += 4; + } + } + for (; __first != __last; ++__first) + __init = __binary_op(__init, *__first); + return __init; + } + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using addition. + * Equivalent to calling `std::reduce(first, last, init, std::plus<>())`. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + reduce(_InputIterator __first, _InputIterator __last, _Tp __init) + { return std::reduce(__first, __last, std::move(__init), plus<>()); } + + /** + * @brief Calculate reduction of values in a range. + * + * @param __first Start of range. + * @param __last End of range. + * @return The final sum. + * + * Reduce the values in the range `[first,last)` using addition, with + * an initial value of `T{}`, where `T` is the iterator's value type. + * Equivalent to calling `std::reduce(first, last, T{}, std::plus<>())`. + */ + template + _GLIBCXX20_CONSTEXPR + inline typename iterator_traits<_InputIterator>::value_type + reduce(_InputIterator __first, _InputIterator __last) + { + using value_type = typename iterator_traits<_InputIterator>::value_type; + return std::reduce(__first, __last, value_type{}, plus<>()); + } + + /** + * @brief Combine elements from two ranges and reduce + * + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __init Starting value to add other values to. + * @param __binary_op1 The function used to perform reduction. + * @param __binary_op2 The function used to combine values from the ranges. + * @return The final sum. + * + * Call `binary_op2(first1[n],first2[n])` for each `n` in `[0,last1-first1)` + * and then use `binary_op1` to reduce the values returned by `binary_op2` + * to a single value of type `T`. + * + * The range beginning at `first2` must contain at least `last1-first1` + * elements. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init, + _BinaryOperation1 __binary_op1, + _BinaryOperation2 __binary_op2) + { + if constexpr (__and_v<__is_random_access_iter<_InputIterator1>, + __is_random_access_iter<_InputIterator2>>) + { + while ((__last1 - __first1) >= 4) + { + _Tp __v1 = __binary_op1(__binary_op2(__first1[0], __first2[0]), + __binary_op2(__first1[1], __first2[1])); + _Tp __v2 = __binary_op1(__binary_op2(__first1[2], __first2[2]), + __binary_op2(__first1[3], __first2[3])); + _Tp __v3 = __binary_op1(__v1, __v2); + __init = __binary_op1(__init, __v3); + __first1 += 4; + __first2 += 4; + } + } + for (; __first1 != __last1; ++__first1, (void) ++__first2) + __init = __binary_op1(__init, __binary_op2(*__first1, *__first2)); + return __init; + } + + /** + * @brief Combine elements from two ranges and reduce + * + * @param __first1 Start of first range. + * @param __last1 End of first range. + * @param __first2 Start of second range. + * @param __init Starting value to add other values to. + * @return The final sum. + * + * Call `first1[n]*first2[n]` for each `n` in `[0,last1-first1)` and then + * use addition to sum those products to a single value of type `T`. + * + * The range beginning at `first2` must contain at least `last1-first1` + * elements. + */ + template + _GLIBCXX20_CONSTEXPR + inline _Tp + transform_reduce(_InputIterator1 __first1, _InputIterator1 __last1, + _InputIterator2 __first2, _Tp __init) + { + return std::transform_reduce(__first1, __last1, __first2, + std::move(__init), + plus<>(), multiplies<>()); + } + + /** + * @brief Transform the elements of a range and reduce + * + * @param __first Start of range. + * @param __last End of range. + * @param __init Starting value to add other values to. + * @param __binary_op The function used to perform reduction. + * @param __unary_op The function used to transform values from the range. + * @return The final sum. + * + * Call `unary_op(first[n])` for each `n` in `[0,last-first)` and then + * use `binary_op` to reduce the values returned by `unary_op` + * to a single value of type `T`. + */ + template + _GLIBCXX20_CONSTEXPR + _Tp + transform_reduce(_InputIterator __first, _InputIterator __last, _Tp __init, + _BinaryOperation __binary_op, _UnaryOperation __unary_op) + { + if constexpr (__is_random_access_iter<_InputIterator>::value) + { + while ((__last - __first) >= 4) + { + _Tp __v1 = __binary_op(__unary_op(__first[0]), + __unary_op(__first[1])); + _Tp __v2 = __binary_op(__unary_op(__first[2]), + __unary_op(__first[3])); + _Tp __v3 = __binary_op(__v1, __v2); + __init = __binary_op(__init, __v3); + __first += 4; + } + } + for (; __first != __last; ++__first) + __init = __binary_op(__init, __unary_op(*__first)); + return __init; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @param __binary_op Function to perform summation. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `binary_op` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init, + _BinaryOperation __binary_op) + { + while (__first != __last) + { + auto __v = __init; + __init = __binary_op(__init, *__first); + ++__first; + *__result++ = std::move(__v); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `std::plus<>` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init) + { + return std::exclusive_scan(__first, __last, __result, std::move(__init), + plus<>()); + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op, + _Tp __init) + { + for (; __first != __last; ++__first) + *__result++ = __init = __binary_op(__init, *__first); + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, using `binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _BinaryOperation __binary_op) + { + if (__first != __last) + { + auto __init = *__first; + *__result++ = __init; + ++__first; + if (__first != __last) + __result = std::inclusive_scan(__first, __last, __result, + __binary_op, std::move(__init)); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, using `std::plus<>` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + inline _OutputIterator + inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result) + { return std::inclusive_scan(__first, __last, __result, plus<>()); } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __init Initial value. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "exclusive" scan, meaning the Nth element + * of the output range is the sum of the first N-1 input elements, + * so the Nth input element is not included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_exclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, _Tp __init, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) + { + while (__first != __last) + { + auto __v = __init; + __init = __binary_op(__init, __unary_op(*__first)); + ++__first; + *__result++ = std::move(__v); + } + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @param __init Initial value. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements (and the initial value), + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op, + _Tp __init) + { + for (; __first != __last; ++__first) + *__result++ = __init = __binary_op(__init, __unary_op(*__first)); + return __result; + } + + /** @brief Output the cumulative sum of one range to a second range + * + * @param __first Start of input range. + * @param __last End of input range. + * @param __result Start of output range. + * @param __binary_op Function to perform summation. + * @param __unary_op Function to transform elements of the input range. + * @return The end of the output range. + * + * Write the cumulative sum (aka prefix sum, aka scan) of the input range + * to the output range. Each element of the output range contains the + * running total of all earlier elements, + * using `__unary_op` to transform the input elements + * and using `__binary_op` for summation. + * + * This function generates an "inclusive" scan, meaning the Nth element + * of the output range is the sum of the first N input elements, + * so the Nth input element is included. + */ + template + _GLIBCXX20_CONSTEXPR + _OutputIterator + transform_inclusive_scan(_InputIterator __first, _InputIterator __last, + _OutputIterator __result, + _BinaryOperation __binary_op, + _UnaryOperation __unary_op) + { + if (__first != __last) + { + auto __init = __unary_op(*__first); + *__result++ = __init; + ++__first; + if (__first != __last) + __result = std::transform_inclusive_scan(__first, __last, __result, + __binary_op, __unary_op, + std::move(__init)); + } + return __result; + } + + // @} group numeric_ops + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif /* _GLIBCXX_NUMERIC */ diff --git a/resources/sources/avr-libstdcpp/include/optional b/resources/sources/avr-libstdcpp/include/optional new file mode 100644 index 000000000..6c7701e21 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/optional @@ -0,0 +1,1238 @@ +// -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/optional + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_OPTIONAL +#define _GLIBCXX_OPTIONAL 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#include +#include +#include +#include +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + +#define __cpp_lib_optional 201606L + + template + class optional; + + /// Tag type to disengage optional objects. + struct nullopt_t + { + // Do not user-declare default constructor at all for + // optional_value = {} syntax to work. + // nullopt_t() = delete; + + // Used for constructing nullopt. + enum class _Construct { _Token }; + + // Must be constexpr for nullopt_t to be literal. + explicit constexpr nullopt_t(_Construct) { } + }; + + /// Tag to disengage optional objects. + inline constexpr nullopt_t nullopt { nullopt_t::_Construct::_Token }; + + // This class template manages construction/destruction of + // the contained value for a std::optional. + template + struct _Optional_payload_base + { + using _Stored_type = remove_const_t<_Tp>; + + _Optional_payload_base() = default; + ~_Optional_payload_base() = default; + + template + constexpr + _Optional_payload_base(in_place_t __tag, _Args&&... __args) + : _M_payload(__tag, std::forward<_Args>(__args)...), + _M_engaged(true) + { } + + template + constexpr + _Optional_payload_base(std::initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(__il, std::forward<_Args>(__args)...), + _M_engaged(true) + { } + + // Constructor used by _Optional_base copy constructor when the + // contained value is not trivially copy constructible. + constexpr + _Optional_payload_base(bool __engaged, + const _Optional_payload_base& __other) + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + } + + // Constructor used by _Optional_base move constructor when the + // contained value is not trivially move constructible. + constexpr + _Optional_payload_base(bool __engaged, + _Optional_payload_base&& __other) + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + } + + // Copy constructor is only used to when the contained value is + // trivially copy constructible. + _Optional_payload_base(const _Optional_payload_base&) = default; + + // Move constructor is only used to when the contained value is + // trivially copy constructible. + _Optional_payload_base(_Optional_payload_base&&) = default; + + _Optional_payload_base& + operator=(const _Optional_payload_base&) = default; + + _Optional_payload_base& + operator=(_Optional_payload_base&&) = default; + + // used to perform non-trivial copy assignment. + constexpr void + _M_copy_assign(const _Optional_payload_base& __other) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = __other._M_get(); + else + { + if (__other._M_engaged) + this->_M_construct(__other._M_get()); + else + this->_M_reset(); + } + } + + // used to perform non-trivial move assignment. + constexpr void + _M_move_assign(_Optional_payload_base&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + if (this->_M_engaged && __other._M_engaged) + this->_M_get() = std::move(__other._M_get()); + else + { + if (__other._M_engaged) + this->_M_construct(std::move(__other._M_get())); + else + this->_M_reset(); + } + } + + struct _Empty_byte { }; + + template> + union _Storage + { + constexpr _Storage() noexcept : _M_empty() { } + + template + constexpr + _Storage(in_place_t, _Args&&... __args) + : _M_value(std::forward<_Args>(__args)...) + { } + + template + constexpr + _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) + : _M_value(__il, std::forward<_Args>(__args)...) + { } + + _Empty_byte _M_empty; + _Up _M_value; + }; + + template + union _Storage<_Up, false> + { + constexpr _Storage() noexcept : _M_empty() { } + + template + constexpr + _Storage(in_place_t, _Args&&... __args) + : _M_value(std::forward<_Args>(__args)...) + { } + + template + constexpr + _Storage(std::initializer_list<_Vp> __il, _Args&&... __args) + : _M_value(__il, std::forward<_Args>(__args)...) + { } + + // User-provided destructor is needed when _Up has non-trivial dtor. + ~_Storage() { } + + _Empty_byte _M_empty; + _Up _M_value; + }; + + _Storage<_Stored_type> _M_payload; + + bool _M_engaged = false; + + template + void + _M_construct(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) + { + ::new ((void *) std::__addressof(this->_M_payload)) + _Stored_type(std::forward<_Args>(__args)...); + this->_M_engaged = true; + } + + constexpr void + _M_destroy() noexcept + { + _M_engaged = false; + _M_payload._M_value.~_Stored_type(); + } + + // The _M_get() operations have _M_engaged as a precondition. + // They exist to access the contained value with the appropriate + // const-qualification, because _M_payload has had the const removed. + + constexpr _Tp& + _M_get() noexcept + { return this->_M_payload._M_value; } + + constexpr const _Tp& + _M_get() const noexcept + { return this->_M_payload._M_value; } + + // _M_reset is a 'safe' operation with no precondition. + constexpr void + _M_reset() noexcept + { + if (this->_M_engaged) + _M_destroy(); + } + }; + + // Class template that manages the payload for optionals. + template , + bool /*_HasTrivialCopy */ = + is_trivially_copy_assignable_v<_Tp> + && is_trivially_copy_constructible_v<_Tp>, + bool /*_HasTrivialMove */ = + is_trivially_move_assignable_v<_Tp> + && is_trivially_move_constructible_v<_Tp>> + struct _Optional_payload; + + // Payload for potentially-constexpr optionals (trivial copy/move/destroy). + template + struct _Optional_payload<_Tp, true, true, true> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + }; + + // Payload for optionals with non-trivial copy construction/assignment. + template + struct _Optional_payload<_Tp, true, false, true> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(_Optional_payload&&) = default; + + // Non-trivial copy assignment. + constexpr + _Optional_payload& + operator=(const _Optional_payload& __other) + { + this->_M_copy_assign(__other); + return *this; + } + }; + + // Payload for optionals with non-trivial move construction/assignment. + template + struct _Optional_payload<_Tp, true, true, false> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(const _Optional_payload&) = default; + + // Non-trivial move assignment. + constexpr + _Optional_payload& + operator=(_Optional_payload&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + this->_M_move_assign(std::move(__other)); + return *this; + } + }; + + // Payload for optionals with non-trivial copy and move assignment. + template + struct _Optional_payload<_Tp, true, false, false> + : _Optional_payload_base<_Tp> + { + using _Optional_payload_base<_Tp>::_Optional_payload_base; + + _Optional_payload() = default; + ~_Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + + // Non-trivial copy assignment. + constexpr + _Optional_payload& + operator=(const _Optional_payload& __other) + { + this->_M_copy_assign(__other); + return *this; + } + + // Non-trivial move assignment. + constexpr + _Optional_payload& + operator=(_Optional_payload&& __other) + noexcept(__and_v, + is_nothrow_move_assignable<_Tp>>) + { + this->_M_move_assign(std::move(__other)); + return *this; + } + }; + + // Payload for optionals with non-trivial destructors. + template + struct _Optional_payload<_Tp, false, _Copy, _Move> + : _Optional_payload<_Tp, true, false, false> + { + // Base class implements all the constructors and assignment operators: + using _Optional_payload<_Tp, true, false, false>::_Optional_payload; + _Optional_payload() = default; + _Optional_payload(const _Optional_payload&) = default; + _Optional_payload(_Optional_payload&&) = default; + _Optional_payload& operator=(const _Optional_payload&) = default; + _Optional_payload& operator=(_Optional_payload&&) = default; + + // Destructor needs to destroy the contained value: + ~_Optional_payload() { this->_M_reset(); } + }; + + // Common base class for _Optional_base to avoid repeating these + // member functions in each specialization. + template + class _Optional_base_impl + { + protected: + using _Stored_type = remove_const_t<_Tp>; + + // The _M_construct operation has !_M_engaged as a precondition + // while _M_destruct has _M_engaged as a precondition. + template + void + _M_construct(_Args&&... __args) + noexcept(is_nothrow_constructible_v<_Stored_type, _Args...>) + { + ::new + (std::__addressof(static_cast<_Dp*>(this)->_M_payload._M_payload)) + _Stored_type(std::forward<_Args>(__args)...); + static_cast<_Dp*>(this)->_M_payload._M_engaged = true; + } + + void + _M_destruct() noexcept + { static_cast<_Dp*>(this)->_M_payload._M_destroy(); } + + // _M_reset is a 'safe' operation with no precondition. + constexpr void + _M_reset() noexcept + { static_cast<_Dp*>(this)->_M_payload._M_reset(); } + + constexpr bool _M_is_engaged() const noexcept + { return static_cast(this)->_M_payload._M_engaged; } + + // The _M_get operations have _M_engaged as a precondition. + constexpr _Tp& + _M_get() noexcept + { + __glibcxx_assert(this->_M_is_engaged()); + return static_cast<_Dp*>(this)->_M_payload._M_get(); + } + + constexpr const _Tp& + _M_get() const noexcept + { + __glibcxx_assert(this->_M_is_engaged()); + return static_cast(this)->_M_payload._M_get(); + } + }; + + /** + * @brief Class template that provides copy/move constructors of optional. + * + * Such a separate base class template is necessary in order to + * conditionally make copy/move constructors trivial. + * + * When the contained value is trivially copy/move constructible, + * the copy/move constructors of _Optional_base will invoke the + * trivial copy/move constructor of _Optional_payload. Otherwise, + * they will invoke _Optional_payload(bool, const _Optional_payload&) + * or _Optional_payload(bool, _Optional_payload&&) to initialize + * the contained value, if copying/moving an engaged optional. + * + * Whether the other special members are trivial is determined by the + * _Optional_payload<_Tp> specialization used for the _M_payload member. + * + * @see optional, _Enable_special_members + */ + template, + bool = is_trivially_move_constructible_v<_Tp>> + struct _Optional_base + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, + std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>, bool> = false> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, + __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) + : _M_payload(__other._M_payload._M_engaged, + __other._M_payload) + { } + + constexpr _Optional_base(_Optional_base&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp>) + : _M_payload(__other._M_payload._M_engaged, + std::move(__other._M_payload)) + { } + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, false, true> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, + std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>, bool> = false> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, + __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) + : _M_payload(__other._M_payload._M_engaged, + __other._M_payload) + { } + + constexpr _Optional_base(_Optional_base&& __other) = default; + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, true, false> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, + std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>, bool> = false> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, + __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) = default; + + constexpr _Optional_base(_Optional_base&& __other) + noexcept(is_nothrow_move_constructible_v<_Tp>) + : _M_payload(__other._M_payload._M_engaged, + std::move(__other._M_payload)) + { } + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + struct _Optional_base<_Tp, true, true> + : _Optional_base_impl<_Tp, _Optional_base<_Tp>> + { + // Constructors for disengaged optionals. + constexpr _Optional_base() = default; + + // Constructors for engaged optionals. + template, bool> = false> + constexpr explicit _Optional_base(in_place_t, _Args&&... __args) + : _M_payload(in_place, + std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>, bool> = false> + constexpr explicit _Optional_base(in_place_t, + initializer_list<_Up> __il, + _Args&&... __args) + : _M_payload(in_place, + __il, std::forward<_Args>(__args)...) + { } + + // Copy and move constructors. + constexpr _Optional_base(const _Optional_base& __other) = default; + constexpr _Optional_base(_Optional_base&& __other) = default; + + // Assignment operators. + _Optional_base& operator=(const _Optional_base&) = default; + _Optional_base& operator=(_Optional_base&&) = default; + + _Optional_payload<_Tp> _M_payload; + }; + + template + class optional; + + template + using __converts_from_optional = + __or_&>, + is_constructible<_Tp, optional<_Up>&>, + is_constructible<_Tp, const optional<_Up>&&>, + is_constructible<_Tp, optional<_Up>&&>, + is_convertible&, _Tp>, + is_convertible&, _Tp>, + is_convertible&&, _Tp>, + is_convertible&&, _Tp>>; + + template + using __assigns_from_optional = + __or_&>, + is_assignable<_Tp&, optional<_Up>&>, + is_assignable<_Tp&, const optional<_Up>&&>, + is_assignable<_Tp&, optional<_Up>&&>>; + + /** + * @brief Class template for optional values. + */ + template + class optional + : private _Optional_base<_Tp>, + private _Enable_copy_move< + // Copy constructor. + is_copy_constructible_v<_Tp>, + // Copy assignment. + __and_v, is_copy_assignable<_Tp>>, + // Move constructor. + is_move_constructible_v<_Tp>, + // Move assignment. + __and_v, is_move_assignable<_Tp>>, + // Unique tag type. + optional<_Tp>> + { + static_assert(!is_same_v, nullopt_t>); + static_assert(!is_same_v, in_place_t>); + static_assert(!is_reference_v<_Tp>); + + private: + using _Base = _Optional_base<_Tp>; + + // SFINAE helpers + template + using __not_self = __not_>>; + template + using __not_tag = __not_>>; + template + using _Requires = enable_if_t<__and_v<_Cond...>, bool>; + + public: + using value_type = _Tp; + + constexpr optional() = default; + + constexpr optional(nullopt_t) noexcept { } + + // Converting constructors for engaged optionals. + template, __not_tag<_Up>, + is_constructible<_Tp, _Up&&>, + is_convertible<_Up&&, _Tp>> = true> + constexpr + optional(_Up&& __t) + : _Base(std::in_place, std::forward<_Up>(__t)) { } + + template, __not_tag<_Up>, + is_constructible<_Tp, _Up&&>, + __not_>> = false> + explicit constexpr + optional(_Up&& __t) + : _Base(std::in_place, std::forward<_Up>(__t)) { } + + template>, + is_constructible<_Tp, const _Up&>, + is_convertible, + __not_<__converts_from_optional<_Tp, _Up>>> = true> + constexpr + optional(const optional<_Up>& __t) + { + if (__t) + emplace(*__t); + } + + template>, + is_constructible<_Tp, const _Up&>, + __not_>, + __not_<__converts_from_optional<_Tp, _Up>>> = false> + explicit constexpr + optional(const optional<_Up>& __t) + { + if (__t) + emplace(*__t); + } + + template >, + is_constructible<_Tp, _Up&&>, + is_convertible<_Up&&, _Tp>, + __not_<__converts_from_optional<_Tp, _Up>>> = true> + constexpr + optional(optional<_Up>&& __t) + { + if (__t) + emplace(std::move(*__t)); + } + + template >, + is_constructible<_Tp, _Up&&>, + __not_>, + __not_<__converts_from_optional<_Tp, _Up>>> = false> + explicit constexpr + optional(optional<_Up>&& __t) + { + if (__t) + emplace(std::move(*__t)); + } + + template> = false> + explicit constexpr + optional(in_place_t, _Args&&... __args) + : _Base(std::in_place, std::forward<_Args>(__args)...) { } + + template&, + _Args&&...>> = false> + explicit constexpr + optional(in_place_t, initializer_list<_Up> __il, _Args&&... __args) + : _Base(std::in_place, __il, std::forward<_Args>(__args)...) { } + + // Assignment operators. + optional& + operator=(nullopt_t) noexcept + { + this->_M_reset(); + return *this; + } + + template + enable_if_t<__and_v<__not_self<_Up>, + __not_<__and_, + is_same<_Tp, decay_t<_Up>>>>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>>, + optional&> + operator=(_Up&& __u) + { + if (this->_M_is_engaged()) + this->_M_get() = std::forward<_Up>(__u); + else + this->_M_construct(std::forward<_Up>(__u)); + + return *this; + } + + template + enable_if_t<__and_v<__not_>, + is_constructible<_Tp, const _Up&>, + is_assignable<_Tp&, _Up>, + __not_<__converts_from_optional<_Tp, _Up>>, + __not_<__assigns_from_optional<_Tp, _Up>>>, + optional&> + operator=(const optional<_Up>& __u) + { + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = *__u; + else + this->_M_construct(*__u); + } + else + { + this->_M_reset(); + } + return *this; + } + + template + enable_if_t<__and_v<__not_>, + is_constructible<_Tp, _Up>, + is_assignable<_Tp&, _Up>, + __not_<__converts_from_optional<_Tp, _Up>>, + __not_<__assigns_from_optional<_Tp, _Up>>>, + optional&> + operator=(optional<_Up>&& __u) + { + if (__u) + { + if (this->_M_is_engaged()) + this->_M_get() = std::move(*__u); + else + this->_M_construct(std::move(*__u)); + } + else + { + this->_M_reset(); + } + + return *this; + } + + template + enable_if_t, _Tp&> + emplace(_Args&&... __args) + { + this->_M_reset(); + this->_M_construct(std::forward<_Args>(__args)...); + return this->_M_get(); + } + + template + enable_if_t&, + _Args&&...>, _Tp&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + this->_M_reset(); + this->_M_construct(__il, std::forward<_Args>(__args)...); + return this->_M_get(); + } + + // Destructor is implicit, implemented in _Optional_base. + + // Swap. + void + swap(optional& __other) + noexcept(is_nothrow_move_constructible_v<_Tp> + && is_nothrow_swappable_v<_Tp>) + { + using std::swap; + + if (this->_M_is_engaged() && __other._M_is_engaged()) + swap(this->_M_get(), __other._M_get()); + else if (this->_M_is_engaged()) + { + __other._M_construct(std::move(this->_M_get())); + this->_M_destruct(); + } + else if (__other._M_is_engaged()) + { + this->_M_construct(std::move(__other._M_get())); + __other._M_destruct(); + } + } + + // Observers. + constexpr const _Tp* + operator->() const + { return std::__addressof(this->_M_get()); } + + constexpr _Tp* + operator->() + { return std::__addressof(this->_M_get()); } + + constexpr const _Tp& + operator*() const& + { return this->_M_get(); } + + constexpr _Tp& + operator*()& + { return this->_M_get(); } + + constexpr _Tp&& + operator*()&& + { return std::move(this->_M_get()); } + + constexpr const _Tp&& + operator*() const&& + { return std::move(this->_M_get()); } + + constexpr explicit operator bool() const noexcept + { return this->_M_is_engaged(); } + + constexpr bool has_value() const noexcept + { return this->_M_is_engaged(); } + + constexpr const _Tp& + value() const& + { + return this->_M_is_engaged() + ? this->_M_get() + : (__throw_bad_optional_access(), this->_M_get()); + } + + constexpr _Tp& + value()& + { + return this->_M_is_engaged() + ? this->_M_get() + : (__throw_bad_optional_access(), this->_M_get()); + } + + constexpr _Tp&& + value()&& + { + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : (__throw_bad_optional_access(), std::move(this->_M_get())); + } + + constexpr const _Tp&& + value() const&& + { + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : (__throw_bad_optional_access(), std::move(this->_M_get())); + } + + template + constexpr _Tp + value_or(_Up&& __u) const& + { + static_assert(is_copy_constructible_v<_Tp>); + static_assert(is_convertible_v<_Up&&, _Tp>); + + return this->_M_is_engaged() + ? this->_M_get() : static_cast<_Tp>(std::forward<_Up>(__u)); + } + + template + constexpr _Tp + value_or(_Up&& __u) && + { + static_assert(is_move_constructible_v<_Tp>); + static_assert(is_convertible_v<_Up&&, _Tp>); + + return this->_M_is_engaged() + ? std::move(this->_M_get()) + : static_cast<_Tp>(std::forward<_Up>(__u)); + } + + void reset() noexcept { this->_M_reset(); } + }; + + template + using __optional_relop_t = + enable_if_t::value, bool>; + + // Comparisons between optional values. + template + constexpr auto + operator==(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() == declval<_Up>())> + { + return static_cast(__lhs) == static_cast(__rhs) + && (!__lhs || *__lhs == *__rhs); + } + + template + constexpr auto + operator!=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() != declval<_Up>())> + { + return static_cast(__lhs) != static_cast(__rhs) + || (static_cast(__lhs) && *__lhs != *__rhs); + } + + template + constexpr auto + operator<(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() < declval<_Up>())> + { + return static_cast(__rhs) && (!__lhs || *__lhs < *__rhs); + } + + template + constexpr auto + operator>(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() > declval<_Up>())> + { + return static_cast(__lhs) && (!__rhs || *__lhs > *__rhs); + } + + template + constexpr auto + operator<=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() <= declval<_Up>())> + { + return !__lhs || (static_cast(__rhs) && *__lhs <= *__rhs); + } + + template + constexpr auto + operator>=(const optional<_Tp>& __lhs, const optional<_Up>& __rhs) + -> __optional_relop_t() >= declval<_Up>())> + { + return !__rhs || (static_cast(__lhs) && *__lhs >= *__rhs); + } + +#ifdef __cpp_lib_three_way_comparison + template _Up> + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(const optional<_Tp>& __x, const optional<_Up>& __y) + { + return __x && __y ? *__x <=> *__y : bool(__x) <=> bool(__y); + } +#endif + + // Comparisons with nullopt. + template + constexpr bool + operator==(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + +#ifdef __cpp_lib_three_way_comparison + template + constexpr strong_ordering + operator<=>(const optional<_Tp>& __x, nullopt_t) noexcept + { return bool(__x) <=> false; } +#else + template + constexpr bool + operator==(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } + + template + constexpr bool + operator!=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast(__lhs); } + + template + constexpr bool + operator!=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast(__rhs); } + + template + constexpr bool + operator<(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return false; } + + template + constexpr bool + operator<(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return static_cast(__rhs); } + + template + constexpr bool + operator>(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return static_cast(__lhs); } + + template + constexpr bool + operator>(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return false; } + + template + constexpr bool + operator<=(const optional<_Tp>& __lhs, nullopt_t) noexcept + { return !__lhs; } + + template + constexpr bool + operator<=(nullopt_t, const optional<_Tp>& /* __rhs */) noexcept + { return true; } + + template + constexpr bool + operator>=(const optional<_Tp>& /* __lhs */, nullopt_t) noexcept + { return true; } + + template + constexpr bool + operator>=(nullopt_t, const optional<_Tp>& __rhs) noexcept + { return !__rhs; } +#endif // three-way-comparison + + // Comparisons with value type. + template + constexpr auto + operator==(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() == declval<_Up>())> + { return __lhs && *__lhs == __rhs; } + + template + constexpr auto + operator==(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() == declval<_Tp>())> + { return __rhs && __lhs == *__rhs; } + + template + constexpr auto + operator!=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() != declval<_Up>())> + { return !__lhs || *__lhs != __rhs; } + + template + constexpr auto + operator!=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() != declval<_Tp>())> + { return !__rhs || __lhs != *__rhs; } + + template + constexpr auto + operator<(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() < declval<_Up>())> + { return !__lhs || *__lhs < __rhs; } + + template + constexpr auto + operator<(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() < declval<_Tp>())> + { return __rhs && __lhs < *__rhs; } + + template + constexpr auto + operator>(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() > declval<_Up>())> + { return __lhs && *__lhs > __rhs; } + + template + constexpr auto + operator>(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() > declval<_Tp>())> + { return !__rhs || __lhs > *__rhs; } + + template + constexpr auto + operator<=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() <= declval<_Up>())> + { return !__lhs || *__lhs <= __rhs; } + + template + constexpr auto + operator<=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() <= declval<_Tp>())> + { return __rhs && __lhs <= *__rhs; } + + template + constexpr auto + operator>=(const optional<_Tp>& __lhs, const _Up& __rhs) + -> __optional_relop_t() >= declval<_Up>())> + { return __lhs && *__lhs >= __rhs; } + + template + constexpr auto + operator>=(const _Up& __lhs, const optional<_Tp>& __rhs) + -> __optional_relop_t() >= declval<_Tp>())> + { return !__rhs || __lhs >= *__rhs; } + +#ifdef __cpp_lib_three_way_comparison + template + constexpr compare_three_way_result_t<_Tp, _Up> + operator<=>(const optional<_Tp>& __x, const _Up& __v) + { return bool(__x) ? *__x <=> __v : strong_ordering::less; } +#endif + + // Swap and creation functions. + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2748. swappable traits for optionals + template + inline enable_if_t && is_swappable_v<_Tp>> + swap(optional<_Tp>& __lhs, optional<_Tp>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template + enable_if_t && is_swappable_v<_Tp>)> + swap(optional<_Tp>&, optional<_Tp>&) = delete; + + template + constexpr optional> + make_optional(_Tp&& __t) + { return optional> { std::forward<_Tp>(__t) }; } + + template + constexpr optional<_Tp> + make_optional(_Args&&... __args) + { return optional<_Tp> { in_place, std::forward<_Args>(__args)... }; } + + template + constexpr optional<_Tp> + make_optional(initializer_list<_Up> __il, _Args&&... __args) + { return optional<_Tp> { in_place, __il, std::forward<_Args>(__args)... }; } + + // Hash. + + template, + bool = __poison_hash<_Up>::__enable_hash_call> + struct __optional_hash_call_base + { + size_t + operator()(const optional<_Tp>& __t) const + noexcept(noexcept(hash<_Up>{}(*__t))) + { + // We pick an arbitrary hash for disengaged optionals which hopefully + // usual values of _Tp won't typically hash to. + constexpr size_t __magic_disengaged_hash = static_cast(-3333); + return __t ? hash<_Up>{}(*__t) : __magic_disengaged_hash; + } + }; + + template + struct __optional_hash_call_base<_Tp, _Up, false> {}; + + template + struct hash> + : private __poison_hash>, + public __optional_hash_call_base<_Tp> + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = optional<_Tp>; + }; + + template + struct __is_fast_hash>> : __is_fast_hash> + { }; + + /// @} + +#if __cpp_deduction_guides >= 201606 + template optional(_Tp) -> optional<_Tp>; +#endif + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_OPTIONAL diff --git a/resources/sources/avr-libstdcpp/include/ostream b/resources/sources/avr-libstdcpp/include/ostream deleted file mode 100644 index 841859075..000000000 --- a/resources/sources/avr-libstdcpp/include/ostream +++ /dev/null @@ -1,4 +0,0 @@ -// Stub: I/O streams not available on AVR -#ifndef _AVR_OSTREAM_STUB -#define _AVR_OSTREAM_STUB -#endif diff --git a/resources/sources/avr-libstdcpp/include/queue b/resources/sources/avr-libstdcpp/include/queue new file mode 100644 index 000000000..ef6b6fd60 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/queue @@ -0,0 +1,66 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/queue + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_QUEUE +#define _GLIBCXX_QUEUE 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#endif /* _GLIBCXX_QUEUE */ diff --git a/resources/sources/avr-libstdcpp/include/random b/resources/sources/avr-libstdcpp/include/random new file mode 100644 index 000000000..7a68ba37f --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/random @@ -0,0 +1,54 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/random + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_RANDOM +#define _GLIBCXX_RANDOM 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_USE_C99_STDINT_TR1 + +#include // For uint_fast32_t, uint_fast64_t, uint_least32_t +#include +#include + +#endif // _GLIBCXX_USE_C99_STDINT_TR1 + +#endif // C++11 + +#endif // _GLIBCXX_RANDOM diff --git a/resources/sources/avr-libstdcpp/include/ranges b/resources/sources/avr-libstdcpp/include/ranges new file mode 100644 index 000000000..56800095b --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ranges @@ -0,0 +1,3561 @@ +// -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ranges + * This is a Standard C++ Library header. + * @ingroup concepts + */ + +#ifndef _GLIBCXX_RANGES +#define _GLIBCXX_RANGES 1 + +#if __cplusplus > 201703L + +#pragma GCC system_header + +#include + +#if __cpp_lib_concepts + +#include +#include +#include +#include +#include +#include + +/** + * @defgroup ranges Ranges + * + * Components for dealing with ranges of elements. + */ + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION +namespace ranges +{ + // [range.range] The range concept. + // [range.sized] The sized_range concept. + // Defined in + + // [range.refinements] + // Defined in + + struct view_base { }; + + template + inline constexpr bool enable_view = derived_from<_Tp, view_base>; + + template + concept view + = range<_Tp> && movable<_Tp> && default_initializable<_Tp> + && enable_view<_Tp>; + + /// A range which can be safely converted to a view. + template + concept viewable_range = range<_Tp> + && (borrowed_range<_Tp> || view>); + + namespace __detail + { + template + concept __simple_view = view<_Range> && range + && same_as, iterator_t> + && same_as, sentinel_t>; + + template + concept __has_arrow = input_iterator<_It> + && (is_pointer_v<_It> || requires(_It __it) { __it.operator->(); }); + + template + concept __not_same_as + = !same_as, remove_cvref_t<_Up>>; + } // namespace __detail + + template + requires is_class_v<_Derived> && same_as<_Derived, remove_cv_t<_Derived>> + class view_interface : public view_base + { + private: + constexpr _Derived& _M_derived() noexcept + { + static_assert(derived_from<_Derived, view_interface<_Derived>>); + static_assert(view<_Derived>); + return static_cast<_Derived&>(*this); + } + + constexpr const _Derived& _M_derived() const noexcept + { + static_assert(derived_from<_Derived, view_interface<_Derived>>); + static_assert(view<_Derived>); + return static_cast(*this); + } + + public: + constexpr bool + empty() requires forward_range<_Derived> + { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); } + + constexpr bool + empty() const requires forward_range + { return ranges::begin(_M_derived()) == ranges::end(_M_derived()); } + + constexpr explicit + operator bool() requires requires { ranges::empty(_M_derived()); } + { return !ranges::empty(_M_derived()); } + + constexpr explicit + operator bool() const requires requires { ranges::empty(_M_derived()); } + { return !ranges::empty(_M_derived()); } + + constexpr auto + data() requires contiguous_iterator> + { return to_address(ranges::begin(_M_derived())); } + + constexpr auto + data() const + requires range + && contiguous_iterator> + { return to_address(ranges::begin(_M_derived())); } + + constexpr auto + size() + requires forward_range<_Derived> + && sized_sentinel_for, iterator_t<_Derived>> + { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); } + + constexpr auto + size() const + requires forward_range + && sized_sentinel_for, + iterator_t> + { return ranges::end(_M_derived()) - ranges::begin(_M_derived()); } + + constexpr decltype(auto) + front() requires forward_range<_Derived> + { + __glibcxx_assert(!empty()); + return *ranges::begin(_M_derived()); + } + + constexpr decltype(auto) + front() const requires forward_range + { + __glibcxx_assert(!empty()); + return *ranges::begin(_M_derived()); + } + + constexpr decltype(auto) + back() + requires bidirectional_range<_Derived> && common_range<_Derived> + { + __glibcxx_assert(!empty()); + return *ranges::prev(ranges::end(_M_derived())); + } + + constexpr decltype(auto) + back() const + requires bidirectional_range + && common_range + { + __glibcxx_assert(!empty()); + return *ranges::prev(ranges::end(_M_derived())); + } + + template + constexpr decltype(auto) + operator[](range_difference_t<_Range> __n) + { return ranges::begin(_M_derived())[__n]; } + + template + constexpr decltype(auto) + operator[](range_difference_t<_Range> __n) const + { return ranges::begin(_M_derived())[__n]; } + }; + + namespace __detail + { + template + concept __convertible_to_non_slicing = convertible_to<_From, _To> + && !(is_pointer_v> && is_pointer_v> + && __not_same_as>, + remove_pointer_t>>); + + template + concept __pair_like + = !is_reference_v<_Tp> && requires(_Tp __t) + { + typename tuple_size<_Tp>::type; + requires derived_from, integral_constant>; + typename tuple_element_t<0, remove_const_t<_Tp>>; + typename tuple_element_t<1, remove_const_t<_Tp>>; + { get<0>(__t) } -> convertible_to&>; + { get<1>(__t) } -> convertible_to&>; + }; + + template + concept __pair_like_convertible_from + = !range<_Tp> && __pair_like<_Tp> + && constructible_from<_Tp, _Up, _Vp> + && __convertible_to_non_slicing<_Up, tuple_element_t<0, _Tp>> + && convertible_to<_Vp, tuple_element_t<1, _Tp>>; + + template + concept __iterator_sentinel_pair + = !range<_Tp> && __pair_like<_Tp> + && sentinel_for, tuple_element_t<0, _Tp>>; + + } // namespace __detail + + enum class subrange_kind : bool { unsized, sized }; + + template _Sent = _It, + subrange_kind _Kind = sized_sentinel_for<_Sent, _It> + ? subrange_kind::sized : subrange_kind::unsized> + requires (_Kind == subrange_kind::sized || !sized_sentinel_for<_Sent, _It>) + class subrange : public view_interface> + { + private: + // XXX: gcc complains when using constexpr here + static const bool _S_store_size + = _Kind == subrange_kind::sized && !sized_sentinel_for<_Sent, _It>; + + _It _M_begin = _It(); + _Sent _M_end = _Sent(); + + template + struct _Size + { }; + + template + struct _Size<_Tp, true> + { __detail::__make_unsigned_like_t<_Tp> _M_size; }; + + [[no_unique_address]] _Size> _M_size = {}; + + public: + subrange() = default; + + constexpr + subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s) + requires (!_S_store_size) + : _M_begin(std::move(__i)), _M_end(__s) + { } + + constexpr + subrange(__detail::__convertible_to_non_slicing<_It> auto __i, _Sent __s, + __detail::__make_unsigned_like_t> __n) + requires (_Kind == subrange_kind::sized) + : _M_begin(std::move(__i)), _M_end(__s) + { + using __detail::__to_unsigned_like; + __glibcxx_assert(__n == __to_unsigned_like(ranges::distance(__i, __s))); + if constexpr (_S_store_size) + _M_size._M_size = __n; + } + + template<__detail::__not_same_as _Rng> + requires borrowed_range<_Rng> + && __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r) requires _S_store_size && sized_range<_Rng> + : subrange{__r, ranges::size(__r)} + { } + + template<__detail::__not_same_as _Rng> + requires borrowed_range<_Rng> + && __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r) requires (!_S_store_size) + : subrange{ranges::begin(__r), ranges::end(__r)} + { } + + template + requires __detail::__convertible_to_non_slicing, _It> + && convertible_to, _Sent> + constexpr + subrange(_Rng&& __r, + __detail::__make_unsigned_like_t> __n) + requires (_Kind == subrange_kind::sized) + : subrange{ranges::begin(__r), ranges::end(__r), __n} + { } + + template<__detail::__not_same_as _PairLike> + requires __detail::__pair_like_convertible_from<_PairLike, const _It&, + const _Sent&> + constexpr + operator _PairLike() const + { return _PairLike(_M_begin, _M_end); } + + constexpr _It + begin() const requires copyable<_It> + { return _M_begin; } + + [[nodiscard]] constexpr _It + begin() requires (!copyable<_It>) + { return std::move(_M_begin); } + + constexpr _Sent end() const { return _M_end; } + + constexpr bool empty() const { return _M_begin == _M_end; } + + constexpr __detail::__make_unsigned_like_t> + size() const requires (_Kind == subrange_kind::sized) + { + if constexpr (_S_store_size) + return _M_size._M_size; + else + return __detail::__to_unsigned_like(_M_end - _M_begin); + } + + [[nodiscard]] constexpr subrange + next(iter_difference_t<_It> __n = 1) const & + requires forward_iterator<_It> + { + auto __tmp = *this; + __tmp.advance(__n); + return __tmp; + } + + [[nodiscard]] constexpr subrange + next(iter_difference_t<_It> __n = 1) && + { + advance(__n); + return std::move(*this); + } + + [[nodiscard]] constexpr subrange + prev(iter_difference_t<_It> __n = 1) const + requires bidirectional_iterator<_It> + { + auto __tmp = *this; + __tmp.advance(-__n); + return __tmp; + } + + constexpr subrange& + advance(iter_difference_t<_It> __n) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3433. subrange::advance(n) has UB when n < 0 + if constexpr (bidirectional_iterator<_It>) + if (__n < 0) + { + ranges::advance(_M_begin, __n); + if constexpr (_S_store_size) + _M_size._M_size += __detail::__to_unsigned_like(-__n); + return *this; + } + + __glibcxx_assert(__n >= 0); + auto __d = __n - ranges::advance(_M_begin, __n, _M_end); + if constexpr (_S_store_size) + _M_size._M_size -= __detail::__to_unsigned_like(__d); + return *this; + } + }; + + template _Sent> + subrange(_It, _Sent) -> subrange<_It, _Sent>; + + template _Sent> + subrange(_It, _Sent, + __detail::__make_unsigned_like_t>) + -> subrange<_It, _Sent, subrange_kind::sized>; + + template<__detail::__iterator_sentinel_pair _Pr> + subrange(_Pr) + -> subrange, tuple_element_t<1, _Pr>>; + + template<__detail::__iterator_sentinel_pair _Pr> + subrange(_Pr, __detail::__make_unsigned_like_t>>) + -> subrange, tuple_element_t<1, _Pr>, + subrange_kind::sized>; + + template + subrange(_Rng&&) + -> subrange, sentinel_t<_Rng>, + (sized_range<_Rng> + || sized_sentinel_for, iterator_t<_Rng>>) + ? subrange_kind::sized : subrange_kind::unsized>; + + template + subrange(_Rng&&, + __detail::__make_unsigned_like_t>) + -> subrange, sentinel_t<_Rng>, subrange_kind::sized>; + + template + requires (_Num < 2) + constexpr auto + get(const subrange<_It, _Sent, _Kind>& __r) + { + if constexpr (_Num == 0) + return __r.begin(); + else + return __r.end(); + } + + template + requires (_Num < 2) + constexpr auto + get(subrange<_It, _Sent, _Kind>&& __r) + { + if constexpr (_Num == 0) + return __r.begin(); + else + return __r.end(); + } + + template _Sent, + subrange_kind _Kind> + inline constexpr bool + enable_borrowed_range> = true; + +} // namespace ranges + + using ranges::get; + +namespace ranges +{ + /// Type returned by algorithms instead of a dangling iterator or subrange. + struct dangling + { + constexpr dangling() noexcept = default; + template + constexpr dangling(_Args&&...) noexcept { } + }; + + template + using borrowed_iterator_t = conditional_t, + iterator_t<_Range>, + dangling>; + + template + using borrowed_subrange_t = conditional_t, + subrange>, + dangling>; + + template requires is_object_v<_Tp> + class empty_view + : public view_interface> + { + public: + static constexpr _Tp* begin() noexcept { return nullptr; } + static constexpr _Tp* end() noexcept { return nullptr; } + static constexpr _Tp* data() noexcept { return nullptr; } + static constexpr size_t size() noexcept { return 0; } + static constexpr bool empty() noexcept { return true; } + }; + + template + inline constexpr bool enable_borrowed_range> = true; + + namespace __detail + { + template requires is_object_v<_Tp> + struct __box : std::optional<_Tp> + { + using std::optional<_Tp>::optional; + + constexpr + __box() + noexcept(is_nothrow_default_constructible_v<_Tp>) + requires default_initializable<_Tp> + : std::optional<_Tp>{std::in_place} + { } + + __box(const __box&) = default; + __box(__box&&) = default; + + using std::optional<_Tp>::operator=; + + __box& + operator=(const __box& __that) + noexcept(is_nothrow_copy_constructible_v<_Tp>) + requires (!assignable_from<_Tp&, const _Tp&>) + { + if ((bool)__that) + this->emplace(*__that); + else + this->reset(); + return *this; + } + + __box& + operator=(__box&& __that) + noexcept(is_nothrow_move_constructible_v<_Tp>) + requires (!assignable_from<_Tp&, _Tp>) + { + if ((bool)__that) + this->emplace(std::move(*__that)); + else + this->reset(); + return *this; + } + }; + + } // namespace __detail + + /// A view that contains exactly one element. + template requires is_object_v<_Tp> + class single_view : public view_interface> + { + public: + single_view() = default; + + constexpr explicit + single_view(const _Tp& __t) + : _M_value(__t) + { } + + constexpr explicit + single_view(_Tp&& __t) + : _M_value(std::move(__t)) + { } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3428. single_view's in place constructor should be explicit + template + requires constructible_from<_Tp, _Args...> + constexpr explicit + single_view(in_place_t, _Args&&... __args) + : _M_value{in_place, std::forward<_Args>(__args)...} + { } + + constexpr _Tp* + begin() noexcept + { return data(); } + + constexpr const _Tp* + begin() const noexcept + { return data(); } + + constexpr _Tp* + end() noexcept + { return data() + 1; } + + constexpr const _Tp* + end() const noexcept + { return data() + 1; } + + static constexpr size_t + size() noexcept + { return 1; } + + constexpr _Tp* + data() noexcept + { return _M_value.operator->(); } + + constexpr const _Tp* + data() const noexcept + { return _M_value.operator->(); } + + private: + __detail::__box<_Tp> _M_value; + }; + + namespace __detail + { + template + constexpr auto __to_signed_like(_Wp __w) noexcept + { + if constexpr (!integral<_Wp>) + return iter_difference_t<_Wp>(); + else if constexpr (sizeof(iter_difference_t<_Wp>) > sizeof(_Wp)) + return iter_difference_t<_Wp>(__w); + else if constexpr (sizeof(ptrdiff_t) > sizeof(_Wp)) + return ptrdiff_t(__w); + else if constexpr (sizeof(long long) > sizeof(_Wp)) + return (long long)(__w); +#ifdef __SIZEOF_INT128__ + else if constexpr (__SIZEOF_INT128__ > sizeof(_Wp)) + return __int128(__w); +#endif + else + return __max_diff_type(__w); + } + + template + using __iota_diff_t = decltype(__to_signed_like(std::declval<_Wp>())); + + template + concept __decrementable = incrementable<_It> + && requires(_It __i) + { + { --__i } -> same_as<_It&>; + { __i-- } -> same_as<_It>; + }; + + template + concept __advanceable = __decrementable<_It> && totally_ordered<_It> + && requires( _It __i, const _It __j, const __iota_diff_t<_It> __n) + { + { __i += __n } -> same_as<_It&>; + { __i -= __n } -> same_as<_It&>; + _It(__j + __n); + _It(__n + __j); + _It(__j - __n); + { __j - __j } -> convertible_to<__iota_diff_t<_It>>; + }; + + } // namespace __detail + + template + requires std::__detail::__weakly_eq_cmp_with<_Winc, _Bound> + && semiregular<_Winc> + class iota_view : public view_interface> + { + private: + struct _Sentinel; + + struct _Iterator + { + private: + static auto + _S_iter_cat() + { + using namespace __detail; + if constexpr (__advanceable<_Winc>) + return random_access_iterator_tag{}; + else if constexpr (__decrementable<_Winc>) + return bidirectional_iterator_tag{}; + else if constexpr (incrementable<_Winc>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + public: + using iterator_category = decltype(_S_iter_cat()); + using value_type = _Winc; + using difference_type = __detail::__iota_diff_t<_Winc>; + + _Iterator() = default; + + constexpr explicit + _Iterator(_Winc __value) + : _M_value(__value) { } + + constexpr _Winc + operator*() const noexcept(is_nothrow_copy_constructible_v<_Winc>) + { return _M_value; } + + constexpr _Iterator& + operator++() + { + ++_M_value; + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires incrementable<_Winc> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires __detail::__decrementable<_Winc> + { + --_M_value; + return *this; + } + + constexpr _Iterator + operator--(int) requires __detail::__decrementable<_Winc> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + if constexpr (__is_integer_like<_Winc> + && !__is_signed_integer_like<_Winc>) + { + if (__n >= difference_type(0)) + _M_value += static_cast<_Winc>(__n); + else + _M_value -= static_cast<_Winc>(-__n); + } + else + _M_value += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + if constexpr (__is_integer_like<_Winc> + && !__is_signed_integer_like<_Winc>) + { + if (__n >= difference_type(0)) + _M_value -= static_cast<_Winc>(__n); + else + _M_value += static_cast<_Winc>(-__n); + } + else + _M_value -= __n; + return *this; + } + + constexpr _Winc + operator[](difference_type __n) const + requires __detail::__advanceable<_Winc> + { return _Winc(_M_value + __n); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Winc> + { return __x._M_value == __y._M_value; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return __x._M_value < __y._M_value; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> + { return !(__x < __y); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires totally_ordered<_Winc> && three_way_comparable<_Winc> + { return __x._M_value <=> __y._M_value; } +#endif + + friend constexpr _Iterator + operator+(_Iterator __i, difference_type __n) + requires __detail::__advanceable<_Winc> + { return __i += __n; } + + friend constexpr _Iterator + operator+(difference_type __n, _Iterator __i) + requires __detail::__advanceable<_Winc> + { return __i += __n; } + + friend constexpr _Iterator + operator-(_Iterator __i, difference_type __n) + requires __detail::__advanceable<_Winc> + { return __i -= __n; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires __detail::__advanceable<_Winc> + { + using __detail::__is_integer_like; + using __detail::__is_signed_integer_like; + using _Dt = difference_type; + if constexpr (__is_integer_like<_Winc>) + { + if constexpr (__is_signed_integer_like<_Winc>) + return _Dt(_Dt(__x._M_value) - _Dt(__y._M_value)); + else + return (__y._M_value > __x._M_value) + ? _Dt(-_Dt(__y._M_value - __x._M_value)) + : _Dt(__x._M_value - __y._M_value); + } + else + return __x._M_value - __y._M_value; + } + + private: + _Winc _M_value = _Winc(); + + friend _Sentinel; + }; + + struct _Sentinel + { + private: + constexpr bool + _M_equal(const _Iterator& __x) const + { return __x._M_value == _M_bound; } + + _Bound _M_bound = _Bound(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(_Bound __bound) + : _M_bound(__bound) { } + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __y._M_equal(__x); } + + friend constexpr iter_difference_t<_Winc> + operator-(const _Iterator& __x, const _Sentinel& __y) + requires sized_sentinel_for<_Bound, _Winc> + { return __x._M_value - __y._M_bound; } + + friend constexpr iter_difference_t<_Winc> + operator-(const _Sentinel& __x, const _Iterator& __y) + requires sized_sentinel_for<_Bound, _Winc> + { return -(__y - __x); } + }; + + _Winc _M_value = _Winc(); + _Bound _M_bound = _Bound(); + + public: + iota_view() = default; + + constexpr explicit + iota_view(_Winc __value) + : _M_value(__value) + { } + + constexpr + iota_view(type_identity_t<_Winc> __value, + type_identity_t<_Bound> __bound) + : _M_value(__value), _M_bound(__bound) + { + if constexpr (totally_ordered_with<_Winc, _Bound>) + { + __glibcxx_assert( bool(__value <= __bound) ); + } + } + + constexpr _Iterator + begin() const { return _Iterator{_M_value}; } + + constexpr auto + end() const + { + if constexpr (same_as<_Bound, unreachable_sentinel_t>) + return unreachable_sentinel; + else + return _Sentinel{_M_bound}; + } + + constexpr _Iterator + end() const requires same_as<_Winc, _Bound> + { return _Iterator{_M_bound}; } + + constexpr auto + size() const + requires (same_as<_Winc, _Bound> && __detail::__advanceable<_Winc>) + || (integral<_Winc> && integral<_Bound>) + || sized_sentinel_for<_Bound, _Winc> + { + using __detail::__is_integer_like; + using __detail::__to_unsigned_like; + if constexpr (__is_integer_like<_Winc> && __is_integer_like<_Bound>) + return (_M_value < 0) + ? ((_M_bound < 0) + ? __to_unsigned_like(-_M_value) - __to_unsigned_like(-_M_bound) + : __to_unsigned_like(_M_bound) + __to_unsigned_like(-_M_value)) + : __to_unsigned_like(_M_bound) - __to_unsigned_like(_M_value); + else + return __to_unsigned_like(_M_bound - _M_value); + } + }; + + template + requires (!__detail::__is_integer_like<_Winc> + || !__detail::__is_integer_like<_Bound> + || (__detail::__is_signed_integer_like<_Winc> + == __detail::__is_signed_integer_like<_Bound>)) + iota_view(_Winc, _Bound) -> iota_view<_Winc, _Bound>; + + template + inline constexpr bool + enable_borrowed_range> = true; + +namespace views +{ + template + inline constexpr empty_view<_Tp> empty{}; + + struct _Single + { + template + constexpr auto + operator()(_Tp&& __e) const + { return single_view{std::forward<_Tp>(__e)}; } + }; + + inline constexpr _Single single{}; + + struct _Iota + { + template + constexpr auto + operator()(_Tp&& __e) const + { return iota_view{std::forward<_Tp>(__e)}; } + + template + constexpr auto + operator()(_Tp&& __e, _Up&& __f) const + { return iota_view{std::forward<_Tp>(__e), std::forward<_Up>(__f)}; } + }; + + inline constexpr _Iota iota{}; +} // namespace views + +namespace __detail +{ + struct _Empty { }; + + // Alias for a type that is conditionally present + // (and is an empty type otherwise). + // Data members using this alias should use [[no_unique_address]] so that + // they take no space when not needed. + template + using __maybe_present_t = conditional_t<_Present, _Tp, _Empty>; + + // Alias for a type that is conditionally const. + template + using __maybe_const_t = conditional_t<_Const, const _Tp, _Tp>; + +} // namespace __detail + +namespace views +{ + namespace __adaptor + { + template + inline constexpr auto + __maybe_refwrap(_Tp& __arg) + { return reference_wrapper<_Tp>{__arg}; } + + template + inline constexpr auto + __maybe_refwrap(const _Tp& __arg) + { return reference_wrapper{__arg}; } + + template + inline constexpr decltype(auto) + __maybe_refwrap(_Tp&& __arg) + { return std::forward<_Tp>(__arg); } + + template + struct _RangeAdaptorClosure; + + template + struct _RangeAdaptor + { + protected: + [[no_unique_address]] + __detail::__maybe_present_t, + _Callable> _M_callable; + + public: + constexpr + _RangeAdaptor(const _Callable& = {}) + requires is_default_constructible_v<_Callable> + { } + + constexpr + _RangeAdaptor(_Callable __callable) + requires (!is_default_constructible_v<_Callable>) + : _M_callable(std::move(__callable)) + { } + + template + requires (sizeof...(_Args) >= 1) + constexpr auto + operator()(_Args&&... __args) const + { + // [range.adaptor.object]: If a range adaptor object accepts more + // than one argument, then the following expressions are equivalent: + // + // (1) adaptor(range, args...) + // (2) adaptor(args...)(range) + // (3) range | adaptor(args...) + // + // In this case, adaptor(args...) is a range adaptor closure object. + // + // We handle (1) and (2) here, and (3) is just a special case of a + // more general case already handled by _RangeAdaptorClosure. + if constexpr (is_invocable_v<_Callable, _Args...>) + { + static_assert(sizeof...(_Args) != 1, + "a _RangeAdaptor that accepts only one argument " + "should be defined as a _RangeAdaptorClosure"); + // Here we handle adaptor(range, args...) -- just forward all + // arguments to the underlying adaptor routine. + return _Callable{}(std::forward<_Args>(__args)...); + } + else + { + // Here we handle adaptor(args...)(range). + // Given args..., we return a _RangeAdaptorClosure that takes a + // range argument, such that (2) is equivalent to (1). + // + // We need to be careful about how we capture args... in this + // closure. By using __maybe_refwrap, we capture lvalue + // references by reference (through a reference_wrapper) and + // otherwise capture by value. + auto __closure + = [...__args(__maybe_refwrap(std::forward<_Args>(__args)))] + (_Range&& __r) { + // This static_cast has two purposes: it forwards a + // reference_wrapper capture as a T&, and otherwise + // forwards the captured argument as an rvalue. + return _Callable{}(std::forward<_Range>(__r), + (static_cast>> + (__args))...); + }; + using _ClosureType = decltype(__closure); + return _RangeAdaptorClosure<_ClosureType>(std::move(__closure)); + } + } + }; + + template + _RangeAdaptor(_Callable) -> _RangeAdaptor<_Callable>; + + template + struct _RangeAdaptorClosure : public _RangeAdaptor<_Callable> + { + using _RangeAdaptor<_Callable>::_RangeAdaptor; + + template + requires requires { declval<_Callable>()(declval<_Range>()); } + constexpr auto + operator()(_Range&& __r) const + { + if constexpr (is_default_constructible_v<_Callable>) + return _Callable{}(std::forward<_Range>(__r)); + else + return this->_M_callable(std::forward<_Range>(__r)); + } + + template + requires requires { declval<_Callable>()(declval<_Range>()); } + friend constexpr auto + operator|(_Range&& __r, const _RangeAdaptorClosure& __o) + { return __o(std::forward<_Range>(__r)); } + + template + friend constexpr auto + operator|(const _RangeAdaptorClosure<_Tp>& __x, + const _RangeAdaptorClosure& __y) + { + if constexpr (is_default_constructible_v<_Tp> + && is_default_constructible_v<_Callable>) + { + auto __closure = [] (_Up&& __e) { + return std::forward<_Up>(__e) | decltype(__x){} | decltype(__y){}; + }; + return _RangeAdaptorClosure(__closure); + } + else if constexpr (is_default_constructible_v<_Tp> + && !is_default_constructible_v<_Callable>) + { + auto __closure = [__y] (_Up&& __e) { + return std::forward<_Up>(__e) | decltype(__x){} | __y; + }; + return _RangeAdaptorClosure(__closure); + } + else if constexpr (!is_default_constructible_v<_Tp> + && is_default_constructible_v<_Callable>) + { + auto __closure = [__x] (_Up&& __e) { + return std::forward<_Up>(__e) | __x | decltype(__y){}; + }; + return _RangeAdaptorClosure(__closure); + } + else + { + auto __closure = [__x, __y] (_Up&& __e) { + return std::forward<_Up>(__e) | __x | __y; + }; + return _RangeAdaptorClosure(__closure); + } + } + }; + + template + _RangeAdaptorClosure(_Callable) -> _RangeAdaptorClosure<_Callable>; + } // namespace __adaptor +} // namespace views + + template requires is_object_v<_Range> + class ref_view : public view_interface> + { + private: + _Range* _M_r = nullptr; + + static void _S_fun(_Range&); // not defined + static void _S_fun(_Range&&) = delete; + + public: + constexpr + ref_view() noexcept = default; + + template<__detail::__not_same_as _Tp> + requires convertible_to<_Tp, _Range&> + && requires { _S_fun(declval<_Tp>()); } + constexpr + ref_view(_Tp&& __t) + : _M_r(std::__addressof(static_cast<_Range&>(std::forward<_Tp>(__t)))) + { } + + constexpr _Range& + base() const + { return *_M_r; } + + constexpr iterator_t<_Range> + begin() const + { return ranges::begin(*_M_r); } + + constexpr sentinel_t<_Range> + end() const + { return ranges::end(*_M_r); } + + constexpr bool + empty() const requires requires { ranges::empty(*_M_r); } + { return ranges::empty(*_M_r); } + + constexpr auto + size() const requires sized_range<_Range> + { return ranges::size(*_M_r); } + + constexpr auto + data() const requires contiguous_range<_Range> + { return ranges::data(*_M_r); } + }; + + template + ref_view(_Range&) -> ref_view<_Range>; + + template + inline constexpr bool enable_borrowed_range> = true; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptorClosure all + = [] (_Range&& __r) + { + if constexpr (view>) + return std::forward<_Range>(__r); + else if constexpr (requires { ref_view{std::forward<_Range>(__r)}; }) + return ref_view{std::forward<_Range>(__r)}; + else + return subrange{std::forward<_Range>(__r)}; + }; + + template + using all_t = decltype(all(std::declval<_Range>())); + + } // namespace views + + // XXX: the following algos are copied from ranges_algo.h to avoid a circular + // dependency with that header. + namespace __detail + { + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + find_if(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + while (__first != __last + && !(bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template _Sent, + typename _Proj = identity, + indirect_unary_predicate> _Pred> + constexpr _Iter + find_if_not(_Iter __first, _Sent __last, _Pred __pred, _Proj __proj = {}) + { + while (__first != __last + && (bool)std::__invoke(__pred, std::__invoke(__proj, *__first))) + ++__first; + return __first; + } + + template> + _Comp = ranges::less> + constexpr const _Tp& + min(const _Tp& __a, const _Tp& __b, _Comp __comp = {}, _Proj __proj = {}) + { + if (std::__invoke(std::move(__comp), + std::__invoke(__proj, __b), + std::__invoke(__proj, __a))) + return __b; + else + return __a; + } + + template _Sent1, + input_iterator _Iter2, sentinel_for<_Iter2> _Sent2, + typename _Pred = ranges::equal_to, + typename _Proj1 = identity, typename _Proj2 = identity> + requires indirectly_comparable<_Iter1, _Iter2, _Pred, _Proj1, _Proj2> + constexpr pair<_Iter1, _Iter2> + mismatch(_Iter1 __first1, _Sent1 __last1, _Iter2 __first2, _Sent2 __last2, + _Pred __pred = {}, _Proj1 __proj1 = {}, _Proj2 __proj2 = {}) + { + while (__first1 != __last1 && __first2 != __last2 + && (bool)std::__invoke(__pred, + std::__invoke(__proj1, *__first1), + std::__invoke(__proj2, *__first2))) + { + ++__first1; + ++__first2; + } + return { std::move(__first1), std::move(__first2) }; + } + } // namespace __detail + + namespace __detail + { + template + struct _CachedPosition + { + constexpr bool + _M_has_value() const + { return false; } + + constexpr iterator_t<_Range> + _M_get(const _Range&) const + { + __glibcxx_assert(false); + return {}; + } + + constexpr void + _M_set(const _Range&, const iterator_t<_Range>&) const + { } + }; + + template + struct _CachedPosition<_Range> + { + private: + iterator_t<_Range> _M_iter{}; + + public: + constexpr bool + _M_has_value() const + { return _M_iter != iterator_t<_Range>{}; } + + constexpr iterator_t<_Range> + _M_get(const _Range&) const + { + __glibcxx_assert(_M_has_value()); + return _M_iter; + } + + constexpr void + _M_set(const _Range&, const iterator_t<_Range>& __it) + { + __glibcxx_assert(!_M_has_value()); + _M_iter = __it; + } + }; + + template + requires (sizeof(range_difference_t<_Range>) + <= sizeof(iterator_t<_Range>)) + struct _CachedPosition<_Range> + { + private: + range_difference_t<_Range> _M_offset = -1; + + public: + constexpr bool + _M_has_value() const + { return _M_offset >= 0; } + + constexpr iterator_t<_Range> + _M_get(_Range& __r) const + { + __glibcxx_assert(_M_has_value()); + return ranges::begin(__r) + _M_offset; + } + + constexpr void + _M_set(_Range& __r, const iterator_t<_Range>& __it) + { + __glibcxx_assert(!_M_has_value()); + _M_offset = __it - ranges::begin(__r); + } + }; + + } // namespace __detail + + template> _Pred> + requires view<_Vp> && is_object_v<_Pred> + class filter_view : public view_interface> + { + private: + struct _Sentinel; + + struct _Iterator + { + private: + static constexpr auto + _S_iter_concept() + { + if constexpr (bidirectional_range<_Vp>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Vp>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + static constexpr auto + _S_iter_cat() + { + using _Cat = typename iterator_traits<_Vp_iter>::iterator_category; + if constexpr (derived_from<_Cat, bidirectional_iterator_tag>) + return bidirectional_iterator_tag{}; + else if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return _Cat{}; + } + + friend filter_view; + + using _Vp_iter = iterator_t<_Vp>; + + _Vp_iter _M_current = _Vp_iter(); + filter_view* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + using iterator_category = decltype(_S_iter_cat()); + using value_type = range_value_t<_Vp>; + using difference_type = range_difference_t<_Vp>; + + _Iterator() = default; + + constexpr + _Iterator(filter_view& __parent, _Vp_iter __current) + : _M_current(std::move(__current)), + _M_parent(std::__addressof(__parent)) + { } + + constexpr _Vp_iter + base() const & + requires copyable<_Vp_iter> + { return _M_current; } + + constexpr _Vp_iter + base() && + { return std::move(_M_current); } + + constexpr range_reference_t<_Vp> + operator*() const + { return *_M_current; } + + constexpr _Vp_iter + operator->() const + requires __detail::__has_arrow<_Vp_iter> + && copyable<_Vp_iter> + { return _M_current; } + + constexpr _Iterator& + operator++() + { + _M_current = __detail::find_if(std::move(++_M_current), + ranges::end(_M_parent->_M_base), + std::ref(*_M_parent->_M_pred)); + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) requires forward_range<_Vp> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Vp> + { + do + --_M_current; + while (!std::__invoke(*_M_parent->_M_pred, *_M_current)); + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Vp> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Vp_iter> + { return __x._M_current == __y._M_current; } + + friend constexpr range_rvalue_reference_t<_Vp> + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_current))) + { return ranges::iter_move(__i._M_current); } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + requires indirectly_swappable<_Vp_iter> + { ranges::iter_swap(__x._M_current, __y._M_current); } + }; + + struct _Sentinel + { + private: + sentinel_t<_Vp> _M_end = sentinel_t<_Vp>(); + + constexpr bool + __equal(const _Iterator& __i) const + { return __i._M_current == _M_end; } + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(filter_view& __parent) + : _M_end(ranges::end(__parent._M_base)) + { } + + constexpr sentinel_t<_Vp> + base() const + { return _M_end; } + + friend constexpr bool + operator==(const _Iterator& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + }; + + _Vp _M_base = _Vp(); + __detail::__box<_Pred> _M_pred; + [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; + + public: + filter_view() = default; + + constexpr + filter_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr _Iterator + begin() + { + if (_M_cached_begin._M_has_value()) + return {*this, _M_cached_begin._M_get(_M_base)}; + + __glibcxx_assert(_M_pred.has_value()); + auto __it = __detail::find_if(ranges::begin(_M_base), + ranges::end(_M_base), + std::ref(*_M_pred)); + _M_cached_begin._M_set(_M_base, __it); + return {*this, std::move(__it)}; + } + + constexpr auto + end() + { + if constexpr (common_range<_Vp>) + return _Iterator{*this, ranges::end(_M_base)}; + else + return _Sentinel{*this}; + } + }; + + template + filter_view(_Range&&, _Pred) -> filter_view, _Pred>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor filter + = [] (_Range&& __r, _Pred&& __p) + { + return filter_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)}; + }; + } // namespace views + + template + requires view<_Vp> && is_object_v<_Fp> + && regular_invocable<_Fp&, range_reference_t<_Vp>> + && std::__detail::__can_reference>> + class transform_view : public view_interface> + { + private: + template + struct _Sentinel; + + template + struct _Iterator + { + private: + using _Parent = __detail::__maybe_const_t<_Const, transform_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + static constexpr auto + _S_iter_concept() + { + if constexpr (random_access_range<_Vp>) + return random_access_iterator_tag{}; + else if constexpr (bidirectional_range<_Vp>) + return bidirectional_iterator_tag{}; + else if constexpr (forward_range<_Vp>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + static constexpr auto + _S_iter_cat() + { + using _Res = invoke_result_t<_Fp&, range_reference_t<_Base>>; + if constexpr (is_lvalue_reference_v<_Res>) + { + using _Cat + = typename iterator_traits<_Base_iter>::iterator_category; + if constexpr (derived_from<_Cat, contiguous_iterator_tag>) + return random_access_iterator_tag{}; + else + return _Cat{}; + } + else + return input_iterator_tag{}; + } + + using _Base_iter = iterator_t<_Base>; + + _Base_iter _M_current = _Base_iter(); + _Parent* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + using iterator_category = decltype(_S_iter_cat()); + using value_type + = remove_cvref_t>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr + _Iterator(_Parent& __parent, _Base_iter __current) + : _M_current(std::move(__current)), + _M_parent(std::__addressof(__parent)) + { } + + constexpr + _Iterator(_Iterator __i) + requires _Const + && convertible_to, _Base_iter> + : _M_current(std::move(__i._M_current)), _M_parent(__i._M_parent) + { } + + constexpr _Base_iter + base() const & + requires copyable<_Base_iter> + { return _M_current; } + + constexpr _Base_iter + base() && + { return std::move(_M_current); } + + constexpr decltype(auto) + operator*() const + noexcept(noexcept(std::__invoke(*_M_parent->_M_fun, *_M_current))) + { return std::__invoke(*_M_parent->_M_fun, *_M_current); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + return *this; + } + + constexpr void + operator++(int) + { ++_M_current; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) requires random_access_range<_Base> + { + _M_current += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) requires random_access_range<_Base> + { + _M_current -= __n; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const + requires random_access_range<_Base> + { return std::__invoke(*_M_parent->_M_fun, _M_current[__n]); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable<_Base_iter> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y < __x; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y < __x); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x < __y); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable<_Base_iter> + { return __x._M_current <=> __y._M_current; } +#endif + + friend constexpr _Iterator + operator+(_Iterator __i, difference_type __n) + requires random_access_range<_Base> + { return {*__i._M_parent, __i._M_current + __n}; } + + friend constexpr _Iterator + operator+(difference_type __n, _Iterator __i) + requires random_access_range<_Base> + { return {*__i._M_parent, __i._M_current + __n}; } + + friend constexpr _Iterator + operator-(_Iterator __i, difference_type __n) + requires random_access_range<_Base> + { return {*__i._M_parent, __i._M_current - __n}; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current - __y._M_current; } + + friend constexpr decltype(auto) + iter_move(const _Iterator& __i) noexcept(noexcept(*__i)) + { + if constexpr (is_lvalue_reference_v) + return std::move(*__i); + else + return *__i; + } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_current, __y._M_current))) + requires indirectly_swappable<_Base_iter> + { return ranges::iter_swap(__x._M_current, __y._M_current); } + + friend _Iterator; + template friend struct _Sentinel; + }; + + template + struct _Sentinel + { + private: + using _Parent = __detail::__maybe_const_t<_Const, transform_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + constexpr auto + __distance_from(const _Iterator<_Const2>& __i) const + { return _M_end - __i._M_current; } + + template + constexpr bool + __equal(const _Iterator<_Const2>& __i) const + { return __i._M_current == _M_end; } + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + constexpr + _Sentinel(_Sentinel __i) + requires _Const + && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__i._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return -__y.__distance_from(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Sentinel& __y, const _Iterator<_Const2>& __x) + { return __y.__distance_from(__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + __detail::__box<_Fp> _M_fun; + + public: + transform_view() = default; + + constexpr + transform_view(_Vp __base, _Fp __fun) + : _M_base(std::move(__base)), _M_fun(std::move(__fun)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base ; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr _Iterator + begin() + { return _Iterator{*this, ranges::begin(_M_base)}; } + + constexpr _Iterator + begin() const + requires range + && regular_invocable> + { return _Iterator{*this, ranges::begin(_M_base)}; } + + constexpr _Sentinel + end() + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr _Iterator + end() requires common_range<_Vp> + { return _Iterator{*this, ranges::end(_M_base)}; } + + constexpr _Sentinel + end() const + requires range + && regular_invocable> + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr _Iterator + end() const + requires common_range + && regular_invocable> + { return _Iterator{*this, ranges::end(_M_base)}; } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + transform_view(_Range&&, _Fp) -> transform_view, _Fp>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor transform + = [] (_Range&& __r, _Fp&& __f) + { + return transform_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)}; + }; + } // namespace views + + template + class take_view : public view_interface> + { + private: + template + struct _Sentinel + { + private: + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + using _CI = counted_iterator>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(__end) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__s._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + friend constexpr bool operator==(const _CI& __y, const _Sentinel& __x) + { return __y.count() == 0 || __y.base() == __x._M_end; } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; + + public: + take_view() = default; + + constexpr + take_view(_Vp base, range_difference_t<_Vp> __count) + : _M_base(std::move(base)), _M_count(std::move(__count)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (sized_range<_Vp>) + { + if constexpr (random_access_range<_Vp>) + return ranges::begin(_M_base); + else + { + auto __sz = size(); + return counted_iterator{ranges::begin(_M_base), __sz}; + } + } + else + return counted_iterator{ranges::begin(_M_base), _M_count}; + } + + constexpr auto + begin() const requires range + { + if constexpr (sized_range) + { + if constexpr (random_access_range) + return ranges::begin(_M_base); + else + { + auto __sz = size(); + return counted_iterator{ranges::begin(_M_base), __sz}; + } + } + else + return counted_iterator{ranges::begin(_M_base), _M_count}; + } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { + if constexpr (sized_range<_Vp>) + { + if constexpr (random_access_range<_Vp>) + return ranges::begin(_M_base) + size(); + else + return default_sentinel; + } + else + return _Sentinel{ranges::end(_M_base)}; + } + + constexpr auto + end() const requires range + { + if constexpr (sized_range) + { + if constexpr (random_access_range) + return ranges::begin(_M_base) + size(); + else + return default_sentinel; + } + else + return _Sentinel{ranges::end(_M_base)}; + } + + constexpr auto + size() requires sized_range<_Vp> + { + auto __n = ranges::size(_M_base); + return __detail::min(__n, static_cast(_M_count)); + } + + constexpr auto + size() const requires sized_range + { + auto __n = ranges::size(_M_base); + return __detail::min(__n, static_cast(_M_count)); + } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3447. Deduction guides for take_view and drop_view have different + // constraints + template + take_view(_Range&&, range_difference_t<_Range>) + -> take_view>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor take + = [] (_Range&& __r, _Tp&& __n) + { + return take_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)}; + }; + } // namespace views + + template + requires input_range<_Vp> && is_object_v<_Pred> + && indirect_unary_predicate> + class take_while_view : public view_interface> + { + template + struct _Sentinel + { + private: + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + const _Pred* _M_pred = nullptr; + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end, const _Pred* __pred) + : _M_end(__end), _M_pred(__pred) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(__s._M_end), _M_pred(__s._M_pred) + { } + + constexpr sentinel_t<_Base> + base() const { return _M_end; } + + friend constexpr bool + operator==(const iterator_t<_Base>& __x, const _Sentinel& __y) + { return __y._M_end == __x || !std::__invoke(*__y._M_pred, *__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + __detail::__box<_Pred> _M_pred; + + public: + take_while_view() = default; + + constexpr + take_while_view(_Vp base, _Pred __pred) + : _M_base(std::move(base)), _M_pred(std::move(__pred)) + { + } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return ranges::begin(_M_base); } + + constexpr auto + begin() const requires range + && indirect_unary_predicate> + { return ranges::begin(_M_base); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return _Sentinel(ranges::end(_M_base), + std::__addressof(*_M_pred)); } + + constexpr auto + end() const requires range + && indirect_unary_predicate> + { return _Sentinel(ranges::end(_M_base), + std::__addressof(*_M_pred)); } + }; + + template + take_while_view(_Range&&, _Pred) + -> take_while_view, _Pred>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor take_while + = [] (_Range&& __r, _Pred&& __p) + { + return take_while_view{std::forward<_Range>(__r), std::forward<_Pred>(__p)}; + }; + } // namespace views + + template + class drop_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + range_difference_t<_Vp> _M_count = 0; + + static constexpr bool _S_needs_cached_begin = !random_access_range<_Vp>; + [[no_unique_address]] + __detail::__maybe_present_t<_S_needs_cached_begin, + __detail::_CachedPosition<_Vp>> + _M_cached_begin; + + public: + drop_view() = default; + + constexpr + drop_view(_Vp __base, range_difference_t<_Vp> __count) + : _M_base(std::move(__base)), _M_count(__count) + { __glibcxx_assert(__count >= 0); } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!(__detail::__simple_view<_Vp> + && random_access_range<_Vp>)) + { + if constexpr (_S_needs_cached_begin) + if (_M_cached_begin._M_has_value()) + return _M_cached_begin._M_get(_M_base); + + auto __it = ranges::next(ranges::begin(_M_base), + _M_count, ranges::end(_M_base)); + if constexpr (_S_needs_cached_begin) + _M_cached_begin._M_set(_M_base, __it); + return __it; + } + + constexpr auto + begin() const requires random_access_range + { + return ranges::next(ranges::begin(_M_base), _M_count, + ranges::end(_M_base)); + } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp>) + { return ranges::end(_M_base); } + + constexpr auto + end() const requires range + { return ranges::end(_M_base); } + + constexpr auto + size() requires sized_range<_Vp> + { + const auto __s = ranges::size(_M_base); + const auto __c = static_cast(_M_count); + return __s < __c ? 0 : __s - __c; + } + + constexpr auto + size() const requires sized_range + { + const auto __s = ranges::size(_M_base); + const auto __c = static_cast(_M_count); + return __s < __c ? 0 : __s - __c; + } + }; + + template + drop_view(_Range&&, range_difference_t<_Range>) + -> drop_view>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor drop + = [] (_Range&& __r, _Tp&& __n) + { + return drop_view{std::forward<_Range>(__r), std::forward<_Tp>(__n)}; + }; + } // namespace views + + template + requires input_range<_Vp> && is_object_v<_Pred> + && indirect_unary_predicate> + class drop_while_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + __detail::__box<_Pred> _M_pred; + [[no_unique_address]] __detail::_CachedPosition<_Vp> _M_cached_begin; + + public: + drop_while_view() = default; + + constexpr + drop_while_view(_Vp __base, _Pred __pred) + : _M_base(std::move(__base)), _M_pred(std::move(__pred)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr const _Pred& + pred() const + { return *_M_pred; } + + constexpr auto + begin() + { + if (_M_cached_begin._M_has_value()) + return _M_cached_begin._M_get(_M_base); + + auto __it = __detail::find_if_not(ranges::begin(_M_base), + ranges::end(_M_base), + std::cref(*_M_pred)); + _M_cached_begin._M_set(_M_base, __it); + return __it; + } + + constexpr auto + end() + { return ranges::end(_M_base); } + }; + + template + drop_while_view(_Range&&, _Pred) + -> drop_while_view, _Pred>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor drop_while + = [] (_Range&& __r, _Pred&& __p) + { + return drop_while_view{std::forward<_Range>(__r), + std::forward<_Pred>(__p)}; + }; + } // namespace views + + template + requires view<_Vp> && input_range> + && (is_reference_v> + || view>) + class join_view : public view_interface> + { + private: + using _InnerRange = range_reference_t<_Vp>; + + template + struct _Sentinel; + + template + struct _Iterator + { + private: + using _Parent = __detail::__maybe_const_t<_Const, join_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + static constexpr bool _S_ref_is_glvalue + = is_reference_v>; + + constexpr void + _M_satisfy() + { + auto __update_inner = [this] (range_reference_t<_Base> __x) -> auto& + { + if constexpr (_S_ref_is_glvalue) + return __x; + else + return (_M_parent->_M_inner = views::all(std::move(__x))); + }; + + for (; _M_outer != ranges::end(_M_parent->_M_base); ++_M_outer) + { + auto& inner = __update_inner(*_M_outer); + _M_inner = ranges::begin(inner); + if (_M_inner != ranges::end(inner)) + return; + } + + if constexpr (_S_ref_is_glvalue) + _M_inner = _Inner_iter(); + } + + static constexpr auto + _S_iter_concept() + { + if constexpr (_S_ref_is_glvalue + && bidirectional_range<_Base> + && bidirectional_range>) + return bidirectional_iterator_tag{}; + else if constexpr (_S_ref_is_glvalue + && forward_range<_Base> + && forward_range>) + return forward_iterator_tag{}; + else + return input_iterator_tag{}; + } + + static constexpr auto + _S_iter_cat() + { + using _OuterCat + = typename iterator_traits<_Outer_iter>::iterator_category; + using _InnerCat + = typename iterator_traits<_Inner_iter>::iterator_category; + if constexpr (_S_ref_is_glvalue + && derived_from<_OuterCat, bidirectional_iterator_tag> + && derived_from<_InnerCat, bidirectional_iterator_tag>) + return bidirectional_iterator_tag{}; + else if constexpr (_S_ref_is_glvalue + && derived_from<_OuterCat, forward_iterator_tag> + && derived_from<_InnerCat, forward_iterator_tag>) + return forward_iterator_tag{}; + else if constexpr (derived_from<_OuterCat, input_iterator_tag> + && derived_from<_InnerCat, input_iterator_tag>) + return input_iterator_tag{}; + else + return output_iterator_tag{}; + } + + using _Outer_iter = iterator_t<_Base>; + using _Inner_iter = iterator_t>; + + _Outer_iter _M_outer = _Outer_iter(); + _Inner_iter _M_inner = _Inner_iter(); + _Parent* _M_parent = nullptr; + + public: + using iterator_concept = decltype(_S_iter_concept()); + using iterator_category = decltype(_S_iter_cat()); + using value_type = range_value_t>; + using difference_type + = common_type_t, + range_difference_t>>; + + _Iterator() = default; + + constexpr + _Iterator(_Parent& __parent, _Outer_iter __outer) + : _M_outer(std::move(__outer)), + _M_parent(std::__addressof(__parent)) + { _M_satisfy(); } + + constexpr + _Iterator(_Iterator __i) + requires _Const + && convertible_to, _Outer_iter> + && convertible_to, _Inner_iter> + : _M_outer(std::move(__i._M_outer)), _M_inner(__i._M_inner), + _M_parent(__i._M_parent) + { } + + constexpr decltype(auto) + operator*() const + { return *_M_inner; } + + constexpr _Outer_iter + operator->() const + requires __detail::__has_arrow<_Outer_iter> + && copyable<_Outer_iter> + { return _M_inner; } + + constexpr _Iterator& + operator++() + { + auto&& __inner_range = [this] () -> decltype(auto) { + if constexpr (_S_ref_is_glvalue) + return *_M_outer; + else + return _M_parent->_M_inner; + }(); + if (++_M_inner == ranges::end(__inner_range)) + { + ++_M_outer; + _M_satisfy(); + } + return *this; + } + + constexpr void + operator++(int) + { ++*this; } + + constexpr _Iterator + operator++(int) + requires _S_ref_is_glvalue && forward_range<_Base> + && forward_range> + { + auto __tmp = *this; + ++*this; + return __tmp; + } + + constexpr _Iterator& + operator--() + requires _S_ref_is_glvalue && bidirectional_range<_Base> + && bidirectional_range> + && common_range> + { + if (_M_outer == ranges::end(_M_parent->_M_base)) + _M_inner = ranges::end(*--_M_outer); + while (_M_inner == ranges::begin(*_M_outer)) + _M_inner = ranges::end(*--_M_outer); + --_M_inner; + return *this; + } + + constexpr _Iterator + operator--(int) + requires _S_ref_is_glvalue && bidirectional_range<_Base> + && bidirectional_range> + && common_range> + { + auto __tmp = *this; + --*this; + return __tmp; + } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires _S_ref_is_glvalue + && equality_comparable<_Outer_iter> + && equality_comparable<_Inner_iter> + { + return (__x._M_outer == __y._M_outer + && __x._M_inner == __y._M_inner); + } + + friend constexpr decltype(auto) + iter_move(const _Iterator& __i) + noexcept(noexcept(ranges::iter_move(__i._M_inner))) + { return ranges::iter_move(__i._M_inner); } + + friend constexpr void + iter_swap(const _Iterator& __x, const _Iterator& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_inner, __y._M_inner))) + { return ranges::iter_swap(__x._M_inner, __y._M_inner); } + + friend _Iterator; + template friend struct _Sentinel; + }; + + template + struct _Sentinel + { + private: + using _Parent = __detail::__maybe_const_t<_Const, join_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + template + constexpr bool + __equal(const _Iterator<_Const2>& __i) const + { return __i._M_outer == _M_end; } + + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(_Parent& __parent) + : _M_end(ranges::end(__parent._M_base)) + { } + + constexpr + _Sentinel(_Sentinel __s) + requires _Const && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__s._M_end)) + { } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y.__equal(__x); } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + + // XXX: _M_inner is "present only when !is_reference_v<_InnerRange>" + [[no_unique_address]] + __detail::__maybe_present_t, + views::all_t<_InnerRange>> _M_inner; + + public: + join_view() = default; + + constexpr explicit + join_view(_Vp __base) + : _M_base(std::move(__base)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + constexpr bool __use_const + = (__detail::__simple_view<_Vp> + && is_reference_v>); + return _Iterator<__use_const>{*this, ranges::begin(_M_base)}; + } + + constexpr auto + begin() const + requires input_range + && is_reference_v> + { + return _Iterator{*this, ranges::begin(_M_base)}; + } + + constexpr auto + end() + { + if constexpr (forward_range<_Vp> && is_reference_v<_InnerRange> + && forward_range<_InnerRange> + && common_range<_Vp> && common_range<_InnerRange>) + return _Iterator<__detail::__simple_view<_Vp>>{*this, + ranges::end(_M_base)}; + else + return _Sentinel<__detail::__simple_view<_Vp>>{*this}; + } + + constexpr auto + end() const + requires input_range + && is_reference_v> + { + if constexpr (forward_range + && is_reference_v> + && forward_range> + && common_range + && common_range>) + return _Iterator{*this, ranges::end(_M_base)}; + else + return _Sentinel{*this}; + } + }; + + template + explicit join_view(_Range&&) -> join_view>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptorClosure join + = [] (_Range&& __r) + { + return join_view{std::forward<_Range>(__r)}; + }; + } // namespace views + + namespace __detail + { + template + struct __require_constant; + + template + concept __tiny_range = sized_range<_Range> + && requires + { typename __require_constant::size()>; } + && (remove_reference_t<_Range>::size() <= 1); + } + + template + requires view<_Vp> && view<_Pattern> + && indirectly_comparable, iterator_t<_Pattern>, + ranges::equal_to> + && (forward_range<_Vp> || __detail::__tiny_range<_Pattern>) + class split_view : public view_interface> + { + private: + template + struct _InnerIter; + + template + struct _OuterIter + { + private: + using _Parent = __detail::__maybe_const_t<_Const, split_view>; + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + constexpr bool + __at_end() const + { return __current() == ranges::end(_M_parent->_M_base); } + + // [range.split.outer] p1 + // Many of the following specifications refer to the notional member + // current of outer-iterator. current is equivalent to current_ if + // V models forward_range, and parent_->current_ otherwise. + constexpr auto& + __current() noexcept + { + if constexpr (forward_range<_Vp>) + return _M_current; + else + return _M_parent->_M_current; + } + + constexpr auto& + __current() const noexcept + { + if constexpr (forward_range<_Vp>) + return _M_current; + else + return _M_parent->_M_current; + } + + _Parent* _M_parent = nullptr; + + // XXX: _M_current is present only if "V models forward_range" + [[no_unique_address]] + __detail::__maybe_present_t, + iterator_t<_Base>> _M_current; + + public: + using iterator_concept = conditional_t, + forward_iterator_tag, + input_iterator_tag>; + using iterator_category = input_iterator_tag; + using difference_type = range_difference_t<_Base>; + + struct value_type : view_interface + { + private: + _OuterIter _M_i = _OuterIter(); + + public: + value_type() = default; + + constexpr explicit + value_type(_OuterIter __i) + : _M_i(std::move(__i)) + { } + + constexpr _InnerIter<_Const> + begin() const + requires copyable<_OuterIter> + { return _InnerIter<_Const>{_M_i}; } + + constexpr _InnerIter<_Const> + begin() + requires (!copyable<_OuterIter>) + { return _InnerIter<_Const>{std::move(_M_i)}; } + + constexpr default_sentinel_t + end() const + { return default_sentinel; } + }; + + _OuterIter() = default; + + constexpr explicit + _OuterIter(_Parent& __parent) requires (!forward_range<_Base>) + : _M_parent(std::__addressof(__parent)) + { } + + constexpr + _OuterIter(_Parent& __parent, iterator_t<_Base> __current) + requires forward_range<_Base> + : _M_parent(std::__addressof(__parent)), + _M_current(std::move(__current)) + { } + + constexpr + _OuterIter(_OuterIter __i) + requires _Const + && convertible_to, iterator_t<_Base>> + : _M_parent(__i._M_parent), _M_current(std::move(__i._M_current)) + { } + + constexpr value_type + operator*() const + { return value_type{*this}; } + + constexpr _OuterIter& + operator++() + { + const auto __end = ranges::end(_M_parent->_M_base); + if (__current() == __end) + return *this; + const auto [__pbegin, __pend] = subrange{_M_parent->_M_pattern}; + if (__pbegin == __pend) + ++__current(); + else + do + { + auto [__b, __p] + = __detail::mismatch(std::move(__current()), __end, + __pbegin, __pend); + __current() = std::move(__b); + if (__p == __pend) + break; + } while (++__current() != __end); + return *this; + } + + constexpr decltype(auto) + operator++(int) + { + if constexpr (forward_range<_Base>) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + else + ++*this; + } + + friend constexpr bool + operator==(const _OuterIter& __x, const _OuterIter& __y) + requires forward_range<_Base> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator==(const _OuterIter& __x, default_sentinel_t) + { return __x.__at_end(); }; + + friend _OuterIter; + friend _InnerIter<_Const>; + }; + + template + struct _InnerIter + { + private: + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + constexpr bool + __at_end() const + { + auto [__pcur, __pend] = subrange{_M_i._M_parent->_M_pattern}; + auto __end = ranges::end(_M_i._M_parent->_M_base); + if constexpr (__detail::__tiny_range<_Pattern>) + { + const auto& __cur = _M_i_current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return _M_incremented; + return *__cur == *__pcur; + } + else + { + auto __cur = _M_i_current(); + if (__cur == __end) + return true; + if (__pcur == __pend) + return _M_incremented; + do + { + if (*__cur != *__pcur) + return false; + if (++__pcur == __pend) + return true; + } while (++__cur != __end); + return false; + } + } + + static constexpr auto + _S_iter_cat() + { + using _Cat + = typename iterator_traits>::iterator_category; + if constexpr (derived_from<_Cat, forward_iterator_tag>) + return forward_iterator_tag{}; + else + return _Cat{}; + } + + constexpr auto& + _M_i_current() noexcept + { return _M_i.__current(); } + + constexpr auto& + _M_i_current() const noexcept + { return _M_i.__current(); } + + _OuterIter<_Const> _M_i = _OuterIter<_Const>(); + bool _M_incremented = false; + + public: + using iterator_concept + = typename _OuterIter<_Const>::iterator_concept; + using iterator_category = decltype(_S_iter_cat()); + using value_type = range_value_t<_Base>; + using difference_type = range_difference_t<_Base>; + + _InnerIter() = default; + + constexpr explicit + _InnerIter(_OuterIter<_Const> __i) + : _M_i(std::move(__i)) + { } + + constexpr decltype(auto) + operator*() const + { return *_M_i_current(); } + + constexpr _InnerIter& + operator++() + { + _M_incremented = true; + if constexpr (!forward_range<_Base>) + if constexpr (_Pattern::size() == 0) + return *this; + ++_M_i_current(); + return *this; + } + + constexpr decltype(auto) + operator++(int) + { + if constexpr (forward_range<_Vp>) + { + auto __tmp = *this; + ++*this; + return __tmp; + } + else + ++*this; + } + + friend constexpr bool + operator==(const _InnerIter& __x, const _InnerIter& __y) + requires forward_range<_Base> + { return __x._M_i == __y._M_i; } + + friend constexpr bool + operator==(const _InnerIter& __x, default_sentinel_t) + { return __x.__at_end(); } + + friend constexpr decltype(auto) + iter_move(const _InnerIter& __i) + noexcept(noexcept(ranges::iter_move(__i._M_i_current()))) + { return ranges::iter_move(__i._M_i_current()); } + + friend constexpr void + iter_swap(const _InnerIter& __x, const _InnerIter& __y) + noexcept(noexcept(ranges::iter_swap(__x._M_i_current(), + __y._M_i_current()))) + requires indirectly_swappable> + { ranges::iter_swap(__x._M_i_current(), __y._M_i_current()); } + }; + + _Vp _M_base = _Vp(); + _Pattern _M_pattern = _Pattern(); + + // XXX: _M_current is "present only if !forward_range" + [[no_unique_address]] + __detail::__maybe_present_t, iterator_t<_Vp>> + _M_current; + + + public: + split_view() = default; + + constexpr + split_view(_Vp __base, _Pattern __pattern) + : _M_base(std::move(__base)), _M_pattern(std::move(__pattern)) + { } + + template + requires constructible_from<_Vp, views::all_t<_Range>> + && constructible_from<_Pattern, single_view>> + constexpr + split_view(_Range&& __r, range_value_t<_Range> __e) + : _M_base(views::all(std::forward<_Range>(__r))), + _M_pattern(std::move(__e)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + if constexpr (forward_range<_Vp>) + return _OuterIter<__detail::__simple_view<_Vp>>{ + *this, ranges::begin(_M_base)}; + else + { + _M_current = ranges::begin(_M_base); + return _OuterIter{*this}; + } + } + + constexpr auto + begin() const requires forward_range<_Vp> && forward_range + { + return _OuterIter{*this, ranges::begin(_M_base)}; + } + + constexpr auto + end() requires forward_range<_Vp> && common_range<_Vp> + { + return _OuterIter<__detail::__simple_view<_Vp>>{ + *this, ranges::end(_M_base)}; + } + + constexpr auto + end() const + { + if constexpr (forward_range<_Vp> + && forward_range + && common_range) + return _OuterIter{*this, ranges::end(_M_base)}; + else + return default_sentinel; + } + }; + + template + split_view(_Range&&, _Pred&&) + -> split_view, views::all_t<_Pred>>; + + template + split_view(_Range&&, range_value_t<_Range>) + -> split_view, single_view>>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptor split + = [] (_Range&& __r, _Fp&& __f) + { + return split_view{std::forward<_Range>(__r), std::forward<_Fp>(__f)}; + }; + } // namespace views + + namespace views + { + struct _Counted + { + template + constexpr auto + operator()(_Iter __i, iter_difference_t<_Iter> __n) const + { + if constexpr (random_access_iterator<_Iter>) + return subrange{__i, __i + __n}; + else + return subrange{counted_iterator{std::move(__i), __n}, + default_sentinel}; + } + }; + + inline constexpr _Counted counted{}; + } // namespace views + + template + requires (!common_range<_Vp>) && copyable> + class common_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + + public: + common_view() = default; + + constexpr explicit + common_view(_Vp __r) + : _M_base(std::move(__r)) + { } + + /* XXX: LWG 3280 didn't remove this constructor, but I think it should? + template + requires (!common_range<_Range>) + && constructible_from<_Vp, views::all_t<_Range>> + constexpr explicit + common_view(_Range&& __r) + : _M_base(views::all(std::forward<_Range>(__r))) + { } + */ + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() + { + if constexpr (random_access_range<_Vp> && sized_range<_Vp>) + return ranges::begin(_M_base); + else + return common_iterator, sentinel_t<_Vp>> + (ranges::begin(_M_base)); + } + + constexpr auto + begin() const requires range + { + if constexpr (random_access_range && sized_range) + return ranges::begin(_M_base); + else + return common_iterator, sentinel_t> + (ranges::begin(_M_base)); + } + + constexpr auto + end() + { + if constexpr (random_access_range<_Vp> && sized_range<_Vp>) + return ranges::begin(_M_base) + ranges::size(_M_base); + else + return common_iterator, sentinel_t<_Vp>> + (ranges::end(_M_base)); + } + + constexpr auto + end() const requires range + { + if constexpr (random_access_range && sized_range) + return ranges::begin(_M_base) + ranges::size(_M_base); + else + return common_iterator, sentinel_t> + (ranges::end(_M_base)); + } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + common_view(_Range&&) -> common_view>; + + namespace views + { + inline constexpr __adaptor::_RangeAdaptorClosure common + = [] (_Range&& __r) + { + if constexpr (common_range<_Range> + && requires { views::all(std::forward<_Range>(__r)); }) + return views::all(std::forward<_Range>(__r)); + else + return common_view{std::forward<_Range>(__r)}; + }; + + } // namespace views + + template + requires bidirectional_range<_Vp> + class reverse_view : public view_interface> + { + private: + _Vp _M_base = _Vp(); + + static constexpr bool _S_needs_cached_begin + = !common_range<_Vp> && !random_access_range<_Vp>; + [[no_unique_address]] + __detail::__maybe_present_t<_S_needs_cached_begin, + __detail::_CachedPosition<_Vp>> + _M_cached_begin; + + public: + reverse_view() = default; + + constexpr explicit + reverse_view(_Vp __r) + : _M_base(std::move(__r)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr reverse_iterator> + begin() + { + if constexpr (_S_needs_cached_begin) + if (_M_cached_begin._M_has_value()) + return make_reverse_iterator(_M_cached_begin._M_get(_M_base)); + + auto __it = ranges::next(ranges::begin(_M_base), ranges::end(_M_base)); + if constexpr (_S_needs_cached_begin) + _M_cached_begin._M_set(_M_base, __it); + return make_reverse_iterator(std::move(__it)); + } + + constexpr auto + begin() requires common_range<_Vp> + { return make_reverse_iterator(ranges::end(_M_base)); } + + constexpr auto + begin() const requires common_range + { return make_reverse_iterator(ranges::end(_M_base)); } + + constexpr reverse_iterator> + end() + { return make_reverse_iterator(ranges::begin(_M_base)); } + + constexpr auto + end() const requires common_range + { return make_reverse_iterator(ranges::begin(_M_base)); } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + }; + + template + reverse_view(_Range&&) -> reverse_view>; + + namespace views + { + namespace __detail + { + template + inline constexpr bool __is_reversible_subrange = false; + + template + inline constexpr bool + __is_reversible_subrange, + reverse_iterator<_Iter>, + _Kind>> = true; + + template + inline constexpr bool __is_reverse_view = false; + + template + inline constexpr bool __is_reverse_view> = true; + } + + inline constexpr __adaptor::_RangeAdaptorClosure reverse + = [] (_Range&& __r) + { + using _Tp = remove_cvref_t<_Range>; + if constexpr (__detail::__is_reverse_view<_Tp>) + return std::forward<_Range>(__r).base(); + else if constexpr (__detail::__is_reversible_subrange<_Tp>) + { + using _Iter = decltype(ranges::begin(__r).base()); + if constexpr (sized_range<_Tp>) + return subrange<_Iter, _Iter, subrange_kind::sized> + (__r.end().base(), __r.begin().base(), __r.size()); + else + return subrange<_Iter, _Iter, subrange_kind::unsized> + (__r.end().base(), __r.begin().base()); + } + else + return reverse_view{std::forward<_Range>(__r)}; + }; + } // namespace views + + namespace __detail + { + template + concept __has_tuple_element = requires(_Tp __t) + { + typename tuple_size<_Tp>::type; + requires _Nm < tuple_size_v<_Tp>; + typename tuple_element_t<_Nm, _Tp>; + { std::get<_Nm>(__t) } + -> convertible_to&>; + }; + } + + template + requires view<_Vp> + && __detail::__has_tuple_element, _Nm> + && __detail::__has_tuple_element>, + _Nm> + class elements_view : public view_interface> + { + public: + elements_view() = default; + + constexpr explicit + elements_view(_Vp base) + : _M_base(std::move(base)) + { } + + constexpr _Vp + base() const& requires copy_constructible<_Vp> + { return _M_base; } + + constexpr _Vp + base() && + { return std::move(_M_base); } + + constexpr auto + begin() requires (!__detail::__simple_view<_Vp>) + { return _Iterator(ranges::begin(_M_base)); } + + constexpr auto + begin() const requires range + { return _Iterator(ranges::begin(_M_base)); } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp> && !common_range<_Vp>) + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr auto + end() requires (!__detail::__simple_view<_Vp> && common_range<_Vp>) + { return _Iterator{ranges::end(_M_base)}; } + + constexpr auto + end() const requires range + { return _Sentinel{ranges::end(_M_base)}; } + + constexpr auto + end() const requires common_range + { return _Iterator{ranges::end(_M_base)}; } + + constexpr auto + size() requires sized_range<_Vp> + { return ranges::size(_M_base); } + + constexpr auto + size() const requires sized_range + { return ranges::size(_M_base); } + + private: + template + struct _Sentinel; + + template + struct _Iterator + { + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + + iterator_t<_Base> _M_current = iterator_t<_Base>(); + + friend _Iterator; + + public: + using iterator_category + = typename iterator_traits>::iterator_category; + using value_type + = remove_cvref_t>>; + using difference_type = range_difference_t<_Base>; + + _Iterator() = default; + + constexpr explicit + _Iterator(iterator_t<_Base> current) + : _M_current(std::move(current)) + { } + + constexpr + _Iterator(_Iterator i) + requires _Const && convertible_to, iterator_t<_Base>> + : _M_current(std::move(i._M_current)) + { } + + constexpr iterator_t<_Base> + base() const& + requires copyable> + { return _M_current; } + + constexpr iterator_t<_Base> + base() && + { return std::move(_M_current); } + + constexpr decltype(auto) + operator*() const + { return std::get<_Nm>(*_M_current); } + + constexpr _Iterator& + operator++() + { + ++_M_current; + return *this; + } + + constexpr void + operator++(int) requires (!forward_range<_Base>) + { ++_M_current; } + + constexpr _Iterator + operator++(int) requires forward_range<_Base> + { + auto __tmp = *this; + ++_M_current; + return __tmp; + } + + constexpr _Iterator& + operator--() requires bidirectional_range<_Base> + { + --_M_current; + return *this; + } + + constexpr _Iterator + operator--(int) requires bidirectional_range<_Base> + { + auto __tmp = *this; + --_M_current; + return __tmp; + } + + constexpr _Iterator& + operator+=(difference_type __n) + requires random_access_range<_Base> + { + _M_current += __n; + return *this; + } + + constexpr _Iterator& + operator-=(difference_type __n) + requires random_access_range<_Base> + { + _M_current -= __n; + return *this; + } + + constexpr decltype(auto) + operator[](difference_type __n) const + requires random_access_range<_Base> + { return std::get<_Nm>(*(_M_current + __n)); } + + friend constexpr bool + operator==(const _Iterator& __x, const _Iterator& __y) + requires equality_comparable> + { return __x._M_current == __y._M_current; } + + friend constexpr bool + operator<(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current < __y._M_current; } + + friend constexpr bool + operator>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y._M_current < __x._M_current; } + + friend constexpr bool + operator<=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__y._M_current > __x._M_current); } + + friend constexpr bool + operator>=(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return !(__x._M_current > __y._M_current); } + +#ifdef __cpp_lib_three_way_comparison + friend constexpr auto + operator<=>(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + && three_way_comparable> + { return __x._M_current <=> __y._M_current; } +#endif + + friend constexpr _Iterator + operator+(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return _Iterator{__x} += __y; } + + friend constexpr _Iterator + operator+(difference_type __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __y + __x; } + + friend constexpr _Iterator + operator-(const _Iterator& __x, difference_type __y) + requires random_access_range<_Base> + { return _Iterator{__x} -= __y; } + + friend constexpr difference_type + operator-(const _Iterator& __x, const _Iterator& __y) + requires random_access_range<_Base> + { return __x._M_current - __y._M_current; } + + friend _Sentinel<_Const>; + }; + + template + struct _Sentinel + { + private: + constexpr bool + _M_equal(const _Iterator<_Const>& __x) const + { return __x._M_current == _M_end; } + + using _Base = __detail::__maybe_const_t<_Const, _Vp>; + sentinel_t<_Base> _M_end = sentinel_t<_Base>(); + + public: + _Sentinel() = default; + + constexpr explicit + _Sentinel(sentinel_t<_Base> __end) + : _M_end(std::move(__end)) + { } + + constexpr + _Sentinel(_Sentinel __other) + requires _Const + && convertible_to, sentinel_t<_Base>> + : _M_end(std::move(__other._M_end)) + { } + + constexpr sentinel_t<_Base> + base() const + { return _M_end; } + + template + requires sentinel_for, + iterator_t<__detail::__maybe_const_t<_Const2, _Vp>>> + friend constexpr bool + operator==(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __y._M_equal(__x); } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base2> + operator-(const _Iterator<_Const2>& __x, const _Sentinel& __y) + { return __x._M_current - __y._M_end; } + + template> + requires sized_sentinel_for, iterator_t<_Base2>> + friend constexpr range_difference_t<_Base> + operator-(const _Sentinel& __x, const _Iterator<_Const2>& __y) + { return __x._M_end - __y._M_current; } + + friend _Sentinel; + }; + + _Vp _M_base = _Vp(); + }; + + template + using keys_view = elements_view, 0>; + + template + using values_view = elements_view, 1>; + + namespace views + { + template + inline constexpr __adaptor::_RangeAdaptorClosure elements + = [] (_Range&& __r) + { + using _El = elements_view, _Nm>; + return _El{std::forward<_Range>(__r)}; + }; + + inline constexpr __adaptor::_RangeAdaptorClosure keys = elements<0>; + inline constexpr __adaptor::_RangeAdaptorClosure values = elements<1>; + } // namespace views + +} // namespace ranges + + namespace views = ranges::views; + + template + struct tuple_size> + : integral_constant + { }; + + template + struct tuple_element<0, ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Iter; }; + + template + struct tuple_element<1, ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Sent; }; + + template + struct tuple_element<0, const ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Iter; }; + + template + struct tuple_element<1, const ranges::subrange<_Iter, _Sent, _Kind>> + { using type = _Sent; }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace +#endif // library concepts +#endif // C++2a +#endif /* _GLIBCXX_RANGES */ diff --git a/resources/sources/avr-libstdcpp/include/ratio b/resources/sources/avr-libstdcpp/include/ratio new file mode 100644 index 000000000..83c8c7927 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/ratio @@ -0,0 +1,576 @@ +// ratio -*- C++ -*- + +// Copyright (C) 2008-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/ratio + * This is a Standard C++ Library header. + * @ingroup ratio + */ + +#ifndef _GLIBCXX_RATIO +#define _GLIBCXX_RATIO 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include // intmax_t, uintmax_t + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup ratio Rational Arithmetic + * @ingroup utilities + * + * Compile time representation of finite rational numbers. + * @{ + */ + + /// @cond undocumented + + template + struct __static_sign + : integral_constant + { }; + + template + struct __static_abs + : integral_constant::value> + { }; + + template + struct __static_gcd + : __static_gcd<_Qn, (_Pn % _Qn)> + { }; + + template + struct __static_gcd<_Pn, 0> + : integral_constant::value> + { }; + + template + struct __static_gcd<0, _Qn> + : integral_constant::value> + { }; + + // Let c = 2^(half # of bits in an intmax_t) + // then we find a1, a0, b1, b0 s.t. N = a1*c + a0, M = b1*c + b0 + // The multiplication of N and M becomes, + // N * M = (a1 * b1)c^2 + (a0 * b1 + b0 * a1)c + a0 * b0 + // Multiplication is safe if each term and the sum of the terms + // is representable by intmax_t. + template + struct __safe_multiply + { + private: + static const uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + + static const uintmax_t __a0 = __static_abs<_Pn>::value % __c; + static const uintmax_t __a1 = __static_abs<_Pn>::value / __c; + static const uintmax_t __b0 = __static_abs<_Qn>::value % __c; + static const uintmax_t __b1 = __static_abs<_Qn>::value / __c; + + static_assert(__a1 == 0 || __b1 == 0, + "overflow in multiplication"); + static_assert(__a0 * __b1 + __b0 * __a1 < (__c >> 1), + "overflow in multiplication"); + static_assert(__b0 * __a0 <= __INTMAX_MAX__, + "overflow in multiplication"); + static_assert((__a0 * __b1 + __b0 * __a1) * __c + <= __INTMAX_MAX__ - __b0 * __a0, + "overflow in multiplication"); + + public: + static const intmax_t value = _Pn * _Qn; + }; + + // Some double-precision utilities, where numbers are represented as + // __hi*2^(8*sizeof(uintmax_t)) + __lo. + template + struct __big_less + : integral_constant + { }; + + template + struct __big_add + { + static constexpr uintmax_t __lo = __lo1 + __lo2; + static constexpr uintmax_t __hi = (__hi1 + __hi2 + + (__lo1 + __lo2 < __lo1)); // carry + }; + + // Subtract a number from a bigger one. + template + struct __big_sub + { + static_assert(!__big_less<__hi1, __lo1, __hi2, __lo2>::value, + "Internal library error"); + static constexpr uintmax_t __lo = __lo1 - __lo2; + static constexpr uintmax_t __hi = (__hi1 - __hi2 - + (__lo1 < __lo2)); // carry + }; + + // Same principle as __safe_multiply. + template + struct __big_mul + { + private: + static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + static constexpr uintmax_t __x0 = __x % __c; + static constexpr uintmax_t __x1 = __x / __c; + static constexpr uintmax_t __y0 = __y % __c; + static constexpr uintmax_t __y1 = __y / __c; + static constexpr uintmax_t __x0y0 = __x0 * __y0; + static constexpr uintmax_t __x0y1 = __x0 * __y1; + static constexpr uintmax_t __x1y0 = __x1 * __y0; + static constexpr uintmax_t __x1y1 = __x1 * __y1; + static constexpr uintmax_t __mix = __x0y1 + __x1y0; // possible carry... + static constexpr uintmax_t __mix_lo = __mix * __c; + static constexpr uintmax_t __mix_hi + = __mix / __c + ((__mix < __x0y1) ? __c : 0); // ... added here + typedef __big_add<__mix_hi, __mix_lo, __x1y1, __x0y0> _Res; + public: + static constexpr uintmax_t __hi = _Res::__hi; + static constexpr uintmax_t __lo = _Res::__lo; + }; + + // Adapted from __udiv_qrnnd_c in longlong.h + // This version assumes that the high bit of __d is 1. + template + struct __big_div_impl + { + private: + static_assert(__d >= (uintmax_t(1) << (sizeof(intmax_t) * 8 - 1)), + "Internal library error"); + static_assert(__n1 < __d, "Internal library error"); + static constexpr uintmax_t __c = uintmax_t(1) << (sizeof(intmax_t) * 4); + static constexpr uintmax_t __d1 = __d / __c; + static constexpr uintmax_t __d0 = __d % __c; + + static constexpr uintmax_t __q1x = __n1 / __d1; + static constexpr uintmax_t __r1x = __n1 % __d1; + static constexpr uintmax_t __m = __q1x * __d0; + static constexpr uintmax_t __r1y = __r1x * __c + __n0 / __c; + static constexpr uintmax_t __r1z = __r1y + __d; + static constexpr uintmax_t __r1 + = ((__r1y < __m) ? ((__r1z >= __d) && (__r1z < __m)) + ? (__r1z + __d) : __r1z : __r1y) - __m; + static constexpr uintmax_t __q1 + = __q1x - ((__r1y < __m) + ? ((__r1z >= __d) && (__r1z < __m)) ? 2 : 1 : 0); + static constexpr uintmax_t __q0x = __r1 / __d1; + static constexpr uintmax_t __r0x = __r1 % __d1; + static constexpr uintmax_t __n = __q0x * __d0; + static constexpr uintmax_t __r0y = __r0x * __c + __n0 % __c; + static constexpr uintmax_t __r0z = __r0y + __d; + static constexpr uintmax_t __r0 + = ((__r0y < __n) ? ((__r0z >= __d) && (__r0z < __n)) + ? (__r0z + __d) : __r0z : __r0y) - __n; + static constexpr uintmax_t __q0 + = __q0x - ((__r0y < __n) ? ((__r0z >= __d) + && (__r0z < __n)) ? 2 : 1 : 0); + + public: + static constexpr uintmax_t __quot = __q1 * __c + __q0; + static constexpr uintmax_t __rem = __r0; + + private: + typedef __big_mul<__quot, __d> _Prod; + typedef __big_add<_Prod::__hi, _Prod::__lo, 0, __rem> _Sum; + static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, + "Internal library error"); + }; + + template + struct __big_div + { + private: + static_assert(__d != 0, "Internal library error"); + static_assert(sizeof (uintmax_t) == sizeof (unsigned long long), + "This library calls __builtin_clzll on uintmax_t, which " + "is unsafe on your platform. Please complain to " + "http://gcc.gnu.org/bugzilla/"); + static constexpr int __shift = __builtin_clzll(__d); + static constexpr int __coshift_ = sizeof(uintmax_t) * 8 - __shift; + static constexpr int __coshift = (__shift != 0) ? __coshift_ : 0; + static constexpr uintmax_t __c1 = uintmax_t(1) << __shift; + static constexpr uintmax_t __c2 = uintmax_t(1) << __coshift; + static constexpr uintmax_t __new_d = __d * __c1; + static constexpr uintmax_t __new_n0 = __n0 * __c1; + static constexpr uintmax_t __n1_shifted = (__n1 % __d) * __c1; + static constexpr uintmax_t __n0_top = (__shift != 0) ? (__n0 / __c2) : 0; + static constexpr uintmax_t __new_n1 = __n1_shifted + __n0_top; + typedef __big_div_impl<__new_n1, __new_n0, __new_d> _Res; + + public: + static constexpr uintmax_t __quot_hi = __n1 / __d; + static constexpr uintmax_t __quot_lo = _Res::__quot; + static constexpr uintmax_t __rem = _Res::__rem / __c1; + + private: + typedef __big_mul<__quot_lo, __d> _P0; + typedef __big_mul<__quot_hi, __d> _P1; + typedef __big_add<_P0::__hi, _P0::__lo, _P1::__lo, __rem> _Sum; + // No overflow. + static_assert(_P1::__hi == 0, "Internal library error"); + static_assert(_Sum::__hi >= _P0::__hi, "Internal library error"); + // Matches the input data. + static_assert(_Sum::__hi == __n1 && _Sum::__lo == __n0, + "Internal library error"); + static_assert(__rem < __d, "Internal library error"); + }; + + /// @endcond + + /** + * @brief Provides compile-time rational arithmetic. + * + * This class template represents any finite rational number with a + * numerator and denominator representable by compile-time constants of + * type intmax_t. The ratio is simplified when instantiated. + * + * For example: + * @code + * std::ratio<7,-21>::num == -1; + * std::ratio<7,-21>::den == 3; + * @endcode + * + */ + template + struct ratio + { + static_assert(_Den != 0, "denominator cannot be zero"); + static_assert(_Num >= -__INTMAX_MAX__ && _Den >= -__INTMAX_MAX__, + "out of range"); + + // Note: sign(N) * abs(N) == N + static constexpr intmax_t num = + _Num * __static_sign<_Den>::value / __static_gcd<_Num, _Den>::value; + + static constexpr intmax_t den = + __static_abs<_Den>::value / __static_gcd<_Num, _Den>::value; + + typedef ratio type; + }; + + template + constexpr intmax_t ratio<_Num, _Den>::num; + + template + constexpr intmax_t ratio<_Num, _Den>::den; + + /// @cond undocumented + + template + struct __ratio_multiply + { + private: + static const intmax_t __gcd1 = + __static_gcd<_R1::num, _R2::den>::value; + static const intmax_t __gcd2 = + __static_gcd<_R2::num, _R1::den>::value; + + public: + typedef ratio< + __safe_multiply<(_R1::num / __gcd1), + (_R2::num / __gcd2)>::value, + __safe_multiply<(_R1::den / __gcd2), + (_R2::den / __gcd1)>::value> type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + + template + constexpr intmax_t __ratio_multiply<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_multiply<_R1, _R2>::den; + + /// @endcond + + /// ratio_multiply + template + using ratio_multiply = typename __ratio_multiply<_R1, _R2>::type; + + /// @cond undocumented + + template + struct __ratio_divide + { + static_assert(_R2::num != 0, "division by 0"); + + typedef typename __ratio_multiply< + _R1, + ratio<_R2::den, _R2::num>>::type type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + + template + constexpr intmax_t __ratio_divide<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_divide<_R1, _R2>::den; + + /// @endcond + + /// ratio_divide + template + using ratio_divide = typename __ratio_divide<_R1, _R2>::type; + + /// ratio_equal + template + struct ratio_equal + : integral_constant + { }; + + /// ratio_not_equal + template + struct ratio_not_equal + : integral_constant::value> + { }; + + /// @cond undocumented + + // Both numbers are positive. + template, + typename _Right = __big_mul<_R2::num,_R1::den> > + struct __ratio_less_impl_1 + : integral_constant::value> + { }; + + template::value + != __static_sign<_R2::num>::value)), + bool = (__static_sign<_R1::num>::value == -1 + && __static_sign<_R2::num>::value == -1)> + struct __ratio_less_impl + : __ratio_less_impl_1<_R1, _R2>::type + { }; + + template + struct __ratio_less_impl<_R1, _R2, true, false> + : integral_constant + { }; + + template + struct __ratio_less_impl<_R1, _R2, false, true> + : __ratio_less_impl_1, + ratio<-_R1::num, _R1::den> >::type + { }; + + /// @endcond + + /// ratio_less + template + struct ratio_less + : __ratio_less_impl<_R1, _R2>::type + { }; + + /// ratio_less_equal + template + struct ratio_less_equal + : integral_constant::value> + { }; + + /// ratio_greater + template + struct ratio_greater + : integral_constant::value> + { }; + + /// ratio_greater_equal + template + struct ratio_greater_equal + : integral_constant::value> + { }; + +#if __cplusplus > 201402L + template + inline constexpr bool ratio_equal_v = ratio_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_not_equal_v = ratio_not_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_less_v = ratio_less<_R1, _R2>::value; + template + inline constexpr bool ratio_less_equal_v = + ratio_less_equal<_R1, _R2>::value; + template + inline constexpr bool ratio_greater_v = ratio_greater<_R1, _R2>::value; + template + inline constexpr bool ratio_greater_equal_v + = ratio_greater_equal<_R1, _R2>::value; +#endif // C++17 + + /// @cond undocumented + + template= 0), + bool = (_R2::num >= 0), + bool = ratio_less::value, _R1::den>, + ratio<__static_abs<_R2::num>::value, _R2::den> >::value> + struct __ratio_add_impl + { + private: + typedef typename __ratio_add_impl< + ratio<-_R1::num, _R1::den>, + ratio<-_R2::num, _R2::den> >::type __t; + public: + typedef ratio<-__t::num, __t::den> type; + }; + + // True addition of nonnegative numbers. + template + struct __ratio_add_impl<_R1, _R2, true, true, __b> + { + private: + static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; + static constexpr uintmax_t __d2 = _R2::den / __g; + typedef __big_mul<_R1::den, __d2> __d; + typedef __big_mul<_R1::num, _R2::den / __g> __x; + typedef __big_mul<_R2::num, _R1::den / __g> __y; + typedef __big_add<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; + static_assert(__n::__hi >= __x::__hi, "Internal library error"); + typedef __big_div<__n::__hi, __n::__lo, __g> __ng; + static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; + typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; + static_assert(__n_final::__rem == 0, "Internal library error"); + static_assert(__n_final::__quot_hi == 0 && + __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); + typedef __big_mul<_R1::den / __g2, __d2> __d_final; + static_assert(__d_final::__hi == 0 && + __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); + public: + typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; + }; + + template + struct __ratio_add_impl<_R1, _R2, false, true, true> + : __ratio_add_impl<_R2, _R1> + { }; + + // True subtraction of nonnegative numbers yielding a nonnegative result. + template + struct __ratio_add_impl<_R1, _R2, true, false, false> + { + private: + static constexpr uintmax_t __g = __static_gcd<_R1::den, _R2::den>::value; + static constexpr uintmax_t __d2 = _R2::den / __g; + typedef __big_mul<_R1::den, __d2> __d; + typedef __big_mul<_R1::num, _R2::den / __g> __x; + typedef __big_mul<-_R2::num, _R1::den / __g> __y; + typedef __big_sub<__x::__hi, __x::__lo, __y::__hi, __y::__lo> __n; + typedef __big_div<__n::__hi, __n::__lo, __g> __ng; + static constexpr uintmax_t __g2 = __static_gcd<__ng::__rem, __g>::value; + typedef __big_div<__n::__hi, __n::__lo, __g2> __n_final; + static_assert(__n_final::__rem == 0, "Internal library error"); + static_assert(__n_final::__quot_hi == 0 && + __n_final::__quot_lo <= __INTMAX_MAX__, "overflow in addition"); + typedef __big_mul<_R1::den / __g2, __d2> __d_final; + static_assert(__d_final::__hi == 0 && + __d_final::__lo <= __INTMAX_MAX__, "overflow in addition"); + public: + typedef ratio<__n_final::__quot_lo, __d_final::__lo> type; + }; + + template + struct __ratio_add + { + typedef typename __ratio_add_impl<_R1, _R2>::type type; + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + + template + constexpr intmax_t __ratio_add<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_add<_R1, _R2>::den; + + /// @endcond + + /// ratio_add + template + using ratio_add = typename __ratio_add<_R1, _R2>::type; + + /// @cond undocumented + + template + struct __ratio_subtract + { + typedef typename __ratio_add< + _R1, + ratio<-_R2::num, _R2::den>>::type type; + + static constexpr intmax_t num = type::num; + static constexpr intmax_t den = type::den; + }; + + template + constexpr intmax_t __ratio_subtract<_R1, _R2>::num; + + template + constexpr intmax_t __ratio_subtract<_R1, _R2>::den; + + /// @endcond + + /// ratio_subtract + template + using ratio_subtract = typename __ratio_subtract<_R1, _R2>::type; + + + typedef ratio<1, 1000000000000000000> atto; + typedef ratio<1, 1000000000000000> femto; + typedef ratio<1, 1000000000000> pico; + typedef ratio<1, 1000000000> nano; + typedef ratio<1, 1000000> micro; + typedef ratio<1, 1000> milli; + typedef ratio<1, 100> centi; + typedef ratio<1, 10> deci; + typedef ratio< 10, 1> deca; + typedef ratio< 100, 1> hecto; + typedef ratio< 1000, 1> kilo; + typedef ratio< 1000000, 1> mega; + typedef ratio< 1000000000, 1> giga; + typedef ratio< 1000000000000, 1> tera; + typedef ratio< 1000000000000000, 1> peta; + typedef ratio< 1000000000000000000, 1> exa; + + // @} group ratio +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif //_GLIBCXX_RATIO diff --git a/resources/sources/avr-libstdcpp/include/scoped_allocator b/resources/sources/avr-libstdcpp/include/scoped_allocator new file mode 100644 index 000000000..969b6d8e8 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/scoped_allocator @@ -0,0 +1,519 @@ +// -*- C++ -*- + +// Copyright (C) 2011-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/scoped_allocator + * This is a Standard C++ Library header. + * @ingroup allocators + */ + +#ifndef _SCOPED_ALLOCATOR +#define _SCOPED_ALLOCATOR 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup allocators + * @{ + */ + + /// @cond undocumented + + template + using __outer_allocator_t + = decltype(std::declval<_Alloc>().outer_allocator()); + + template + struct __outermost_type + { + using type = _Alloc; + static type& _S_outermost(_Alloc& __a) { return __a; } + }; + + template + struct __outermost_type<_Alloc, __void_t<__outer_allocator_t<_Alloc>>> + : __outermost_type< + typename remove_reference<__outer_allocator_t<_Alloc>>::type + > + { + using __base = __outermost_type< + typename remove_reference<__outer_allocator_t<_Alloc>>::type + >; + + static typename __base::type& + _S_outermost(_Alloc& __a) + { return __base::_S_outermost(__a.outer_allocator()); } + }; + + /// Implementation of the OUTERMOST pseudofunction + template + inline typename __outermost_type<_Alloc>::type& + __outermost(_Alloc& __a) + { return __outermost_type<_Alloc>::_S_outermost(__a); } + + template + class scoped_allocator_adaptor; + + template + struct __inner_type_impl; + + template + struct __inner_type_impl<_Outer> + { + typedef scoped_allocator_adaptor<_Outer> __type; + + __inner_type_impl() = default; + __inner_type_impl(const __inner_type_impl&) = default; + __inner_type_impl(__inner_type_impl&&) = default; + __inner_type_impl& operator=(const __inner_type_impl&) = default; + __inner_type_impl& operator=(__inner_type_impl&&) = default; + + template + __inner_type_impl(const __inner_type_impl<_Alloc>& __other) + { } + + template + __inner_type_impl(__inner_type_impl<_Alloc>&& __other) + { } + + __type& + _M_get(__type* __p) noexcept { return *__p; } + + const __type& + _M_get(const __type* __p) const noexcept { return *__p; } + + tuple<> + _M_tie() const noexcept { return tuple<>(); } + + bool + operator==(const __inner_type_impl&) const noexcept + { return true; } + }; + + template + struct __inner_type_impl<_Outer, _InnerHead, _InnerTail...> + { + typedef scoped_allocator_adaptor<_InnerHead, _InnerTail...> __type; + + __inner_type_impl() = default; + __inner_type_impl(const __inner_type_impl&) = default; + __inner_type_impl(__inner_type_impl&&) = default; + __inner_type_impl& operator=(const __inner_type_impl&) = default; + __inner_type_impl& operator=(__inner_type_impl&&) = default; + + template + __inner_type_impl(const __inner_type_impl<_Allocs...>& __other) + : _M_inner(__other._M_inner) { } + + template + __inner_type_impl(__inner_type_impl<_Allocs...>&& __other) + : _M_inner(std::move(__other._M_inner)) { } + + template + explicit + __inner_type_impl(_Args&&... __args) + : _M_inner(std::forward<_Args>(__args)...) { } + + __type& + _M_get(void*) noexcept { return _M_inner; } + + const __type& + _M_get(const void*) const noexcept { return _M_inner; } + + tuple + _M_tie() const noexcept + { return _M_inner._M_tie(); } + + bool + operator==(const __inner_type_impl& __other) const noexcept + { return _M_inner == __other._M_inner; } + + private: + template friend class __inner_type_impl; + template friend class scoped_allocator_adaptor; + + __type _M_inner; + }; + + /// @endcond + + /// An adaptor to recursively pass an allocator to the objects it constructs + template + class scoped_allocator_adaptor + : public _OuterAlloc + { + typedef allocator_traits<_OuterAlloc> __traits; + + typedef __inner_type_impl<_OuterAlloc, _InnerAllocs...> __inner_type; + __inner_type _M_inner; + + template + friend class scoped_allocator_adaptor; + + template + friend class __inner_type_impl; + + tuple + _M_tie() const noexcept + { return std::tuple_cat(std::tie(outer_allocator()), _M_inner._M_tie()); } + + template + using __outermost_alloc_traits + = allocator_traits::type>; + +#if __cplusplus <= 201703 + template + void + _M_construct(__uses_alloc0, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + std::forward<_Args>(__args)...); + } + + typedef __uses_alloc1 __uses_alloc1_; + typedef __uses_alloc2 __uses_alloc2_; + + template + void + _M_construct(__uses_alloc1_, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + allocator_arg, inner_allocator(), + std::forward<_Args>(__args)...); + } + + template + void + _M_construct(__uses_alloc2_, _Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, + std::forward<_Args>(__args)..., + inner_allocator()); + } +#endif // C++17 + + template + static _Alloc + _S_select_on_copy(const _Alloc& __a) + { + typedef allocator_traits<_Alloc> __a_traits; + return __a_traits::select_on_container_copy_construction(__a); + } + + template + scoped_allocator_adaptor(tuple __refs, + _Index_tuple<_Indices...>) + : _OuterAlloc(_S_select_on_copy(std::get<0>(__refs))), + _M_inner(_S_select_on_copy(std::get<_Indices+1>(__refs))...) + { } + + // Used to constrain constructors to disallow invalid conversions. + template + using _Constructible = typename enable_if< + is_constructible<_OuterAlloc, _Alloc>::value + >::type; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2975. Missing case for pair construction in scoped [...] allocators + template + struct __not_pair { using type = void; }; + + template + struct __not_pair> { }; + + public: + typedef _OuterAlloc outer_allocator_type; + typedef typename __inner_type::__type inner_allocator_type; + + typedef typename __traits::value_type value_type; + typedef typename __traits::size_type size_type; + typedef typename __traits::difference_type difference_type; + typedef typename __traits::pointer pointer; + typedef typename __traits::const_pointer const_pointer; + typedef typename __traits::void_pointer void_pointer; + typedef typename __traits::const_void_pointer const_void_pointer; + + typedef typename __or_< + typename __traits::propagate_on_container_copy_assignment, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_copy_assignment...>::type + propagate_on_container_copy_assignment; + + typedef typename __or_< + typename __traits::propagate_on_container_move_assignment, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_move_assignment...>::type + propagate_on_container_move_assignment; + + typedef typename __or_< + typename __traits::propagate_on_container_swap, + typename allocator_traits<_InnerAllocs>:: + propagate_on_container_swap...>::type + propagate_on_container_swap; + + typedef typename __and_< + typename __traits::is_always_equal, + typename allocator_traits<_InnerAllocs>::is_always_equal...>::type + is_always_equal; + + template + struct rebind + { + typedef scoped_allocator_adaptor< + typename __traits::template rebind_alloc<_Tp>, + _InnerAllocs...> other; + }; + + scoped_allocator_adaptor() : _OuterAlloc(), _M_inner() { } + + template> + scoped_allocator_adaptor(_Outer2&& __outer, + const _InnerAllocs&... __inner) + : _OuterAlloc(std::forward<_Outer2>(__outer)), + _M_inner(__inner...) + { } + + scoped_allocator_adaptor(const scoped_allocator_adaptor& __other) + : _OuterAlloc(__other.outer_allocator()), + _M_inner(__other._M_inner) + { } + + scoped_allocator_adaptor(scoped_allocator_adaptor&& __other) + : _OuterAlloc(std::move(__other.outer_allocator())), + _M_inner(std::move(__other._M_inner)) + { } + + template> + scoped_allocator_adaptor( + const scoped_allocator_adaptor<_Outer2, _InnerAllocs...>& __other) + : _OuterAlloc(__other.outer_allocator()), + _M_inner(__other._M_inner) + { } + + template> + scoped_allocator_adaptor( + scoped_allocator_adaptor<_Outer2, _InnerAllocs...>&& __other) + : _OuterAlloc(std::move(__other.outer_allocator())), + _M_inner(std::move(__other._M_inner)) + { } + + scoped_allocator_adaptor& + operator=(const scoped_allocator_adaptor&) = default; + + scoped_allocator_adaptor& + operator=(scoped_allocator_adaptor&&) = default; + + inner_allocator_type& inner_allocator() noexcept + { return _M_inner._M_get(this); } + + const inner_allocator_type& inner_allocator() const noexcept + { return _M_inner._M_get(this); } + + outer_allocator_type& outer_allocator() noexcept + { return static_cast<_OuterAlloc&>(*this); } + + const outer_allocator_type& outer_allocator() const noexcept + { return static_cast(*this); } + + _GLIBCXX_NODISCARD pointer allocate(size_type __n) + { return __traits::allocate(outer_allocator(), __n); } + + _GLIBCXX_NODISCARD pointer allocate(size_type __n, const_void_pointer __hint) + { return __traits::allocate(outer_allocator(), __n, __hint); } + + void deallocate(pointer __p, size_type __n) + { return __traits::deallocate(outer_allocator(), __p, __n); } + + size_type max_size() const + { return __traits::max_size(outer_allocator()); } + +#if __cplusplus <= 201703 + template + typename __not_pair<_Tp>::type + construct(_Tp* __p, _Args&&... __args) + { + auto& __inner = inner_allocator(); + auto __use_tag + = std::__use_alloc<_Tp, inner_allocator_type, _Args...>(__inner); + _M_construct(__use_tag, __p, std::forward<_Args>(__args)...); + } + + template + void + construct(pair<_T1, _T2>* __p, piecewise_construct_t, + tuple<_Args1...> __x, tuple<_Args2...> __y) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2203. wrong argument types for piecewise construction + auto& __inner = inner_allocator(); + auto __x_use_tag + = std::__use_alloc<_T1, inner_allocator_type, _Args1...>(__inner); + auto __y_use_tag + = std::__use_alloc<_T2, inner_allocator_type, _Args2...>(__inner); + typename _Build_index_tuple::__type __x_indices; + typename _Build_index_tuple::__type __y_indices; + typedef __outermost_alloc_traits _O_traits; + _O_traits::construct(__outermost(*this), __p, piecewise_construct, + _M_construct_p(__x_use_tag, __x_indices, __x), + _M_construct_p(__y_use_tag, __y_indices, __y)); + } + + template + void + construct(pair<_T1, _T2>* __p) + { construct(__p, piecewise_construct, tuple<>(), tuple<>()); } + + template + void + construct(pair<_T1, _T2>* __p, _Up&& __u, _Vp&& __v) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(std::forward<_Up>(__u)), + std::forward_as_tuple(std::forward<_Vp>(__v))); + } + + template + void + construct(pair<_T1, _T2>* __p, const pair<_Up, _Vp>& __x) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(__x.first), + std::forward_as_tuple(__x.second)); + } + + template + void + construct(pair<_T1, _T2>* __p, pair<_Up, _Vp>&& __x) + { + construct(__p, piecewise_construct, + std::forward_as_tuple(std::forward<_Up>(__x.first)), + std::forward_as_tuple(std::forward<_Vp>(__x.second))); + } +#else // C++2a + template + __attribute__((__nonnull__)) + void + construct(_Tp* __p, _Args&&... __args) + { + typedef __outermost_alloc_traits _O_traits; + std::apply([__p, this](auto&&... __newargs) { + _O_traits::construct(__outermost(*this), __p, + std::forward(__newargs)...); + }, + uses_allocator_construction_args<_Tp>(inner_allocator(), + std::forward<_Args>(__args)...)); + } +#endif // C++2a + + template + void destroy(_Tp* __p) + { + typedef __outermost_alloc_traits _O_traits; + _O_traits::destroy(__outermost(*this), __p); + } + + scoped_allocator_adaptor + select_on_container_copy_construction() const + { + typedef typename _Build_index_tuple::__type + _Indices; + return scoped_allocator_adaptor(_M_tie(), _Indices()); + } + + template + friend bool + operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept; + + private: +#if __cplusplus <= 201703L + template + tuple<_Args&&...> + _M_construct_p(__uses_alloc0, _Ind, tuple<_Args...>& __t) + { return std::move(__t); } + + template + tuple + _M_construct_p(__uses_alloc1_, _Index_tuple<_Ind...>, + tuple<_Args...>& __t) + { + return { allocator_arg, inner_allocator(), + std::get<_Ind>(std::move(__t))... + }; + } + + template + tuple<_Args&&..., inner_allocator_type&> + _M_construct_p(__uses_alloc2_, _Index_tuple<_Ind...>, + tuple<_Args...>& __t) + { + return { std::get<_Ind>(std::move(__t))..., inner_allocator() }; + } +#endif // C++17 + }; + + /// @related std::scoped_allocator_adaptor + template + inline bool + operator==(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept + { + return __a.outer_allocator() == __b.outer_allocator() + && __a._M_inner == __b._M_inner; + } + +#if __cpp_impl_three_way_comparison < 201907L + /// @related std::scoped_allocator_adaptor + template + inline bool + operator!=(const scoped_allocator_adaptor<_OutA1, _InA...>& __a, + const scoped_allocator_adaptor<_OutA2, _InA...>& __b) noexcept + { return !(__a == __b); } +#endif + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++11 + +#endif // _SCOPED_ALLOCATOR diff --git a/resources/sources/avr-libstdcpp/include/set b/resources/sources/avr-libstdcpp/include/set new file mode 100644 index 000000000..168918346 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/set @@ -0,0 +1,105 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/set + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_SET +#define _GLIBCXX_SET 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template> + using set = std::set<_Key, _Cmp, polymorphic_allocator<_Key>>; + template> + using multiset = std::multiset<_Key, _Cmp, polymorphic_allocator<_Key>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template + inline typename set<_Key, _Compare, _Alloc>::size_type + erase_if(set<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } + + template + inline typename multiset<_Key, _Compare, _Alloc>::size_type + erase_if(multiset<_Key, _Compare, _Alloc>& __cont, _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_SET */ diff --git a/resources/sources/avr-libstdcpp/include/shared_mutex b/resources/sources/avr-libstdcpp/include/shared_mutex new file mode 100644 index 000000000..343886107 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/shared_mutex @@ -0,0 +1,855 @@ +// -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/shared_mutex + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_SHARED_MUTEX +#define _GLIBCXX_SHARED_MUTEX 1 + +#pragma GCC system_header + +#if __cplusplus >= 201402L + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup mutexes + * @{ + */ + +#ifdef _GLIBCXX_HAS_GTHREADS + +#if __cplusplus >= 201703L +#define __cpp_lib_shared_mutex 201505 + class shared_mutex; +#endif + +#define __cpp_lib_shared_timed_mutex 201402 + class shared_timed_mutex; + + /// @cond undocumented + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T +#ifdef __gthrw +#define _GLIBCXX_GTHRW(name) \ + __gthrw(pthread_ ## name); \ + static inline int \ + __glibcxx_ ## name (pthread_rwlock_t *__rwlock) \ + { \ + if (__gthread_active_p ()) \ + return __gthrw_(pthread_ ## name) (__rwlock); \ + else \ + return 0; \ + } + _GLIBCXX_GTHRW(rwlock_rdlock) + _GLIBCXX_GTHRW(rwlock_tryrdlock) + _GLIBCXX_GTHRW(rwlock_wrlock) + _GLIBCXX_GTHRW(rwlock_trywrlock) + _GLIBCXX_GTHRW(rwlock_unlock) +# ifndef PTHREAD_RWLOCK_INITIALIZER + _GLIBCXX_GTHRW(rwlock_destroy) + __gthrw(pthread_rwlock_init); + static inline int + __glibcxx_rwlock_init (pthread_rwlock_t *__rwlock) + { + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_init) (__rwlock, NULL); + else + return 0; + } +# endif +# if _GTHREAD_USE_MUTEX_TIMEDLOCK + __gthrw(pthread_rwlock_timedrdlock); + static inline int + __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock, + const timespec *__ts) + { + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_timedrdlock) (__rwlock, __ts); + else + return 0; + } + __gthrw(pthread_rwlock_timedwrlock); + static inline int + __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock, + const timespec *__ts) + { + if (__gthread_active_p ()) + return __gthrw_(pthread_rwlock_timedwrlock) (__rwlock, __ts); + else + return 0; + } +# endif +#else + static inline int + __glibcxx_rwlock_rdlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_rdlock (__rwlock); } + static inline int + __glibcxx_rwlock_tryrdlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_tryrdlock (__rwlock); } + static inline int + __glibcxx_rwlock_wrlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_wrlock (__rwlock); } + static inline int + __glibcxx_rwlock_trywrlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_trywrlock (__rwlock); } + static inline int + __glibcxx_rwlock_unlock (pthread_rwlock_t *__rwlock) + { return pthread_rwlock_unlock (__rwlock); } + static inline int + __glibcxx_rwlock_destroy(pthread_rwlock_t *__rwlock) + { return pthread_rwlock_destroy (__rwlock); } + static inline int + __glibcxx_rwlock_init(pthread_rwlock_t *__rwlock) + { return pthread_rwlock_init (__rwlock, NULL); } +# if _GTHREAD_USE_MUTEX_TIMEDLOCK + static inline int + __glibcxx_rwlock_timedrdlock (pthread_rwlock_t *__rwlock, + const timespec *__ts) + { return pthread_rwlock_timedrdlock (__rwlock, __ts); } + static inline int + __glibcxx_rwlock_timedwrlock (pthread_rwlock_t *__rwlock, + const timespec *__ts) + { return pthread_rwlock_timedwrlock (__rwlock, __ts); } +# endif +#endif + + /// A shared mutex type implemented using pthread_rwlock_t. + class __shared_mutex_pthread + { + friend class shared_timed_mutex; + +#ifdef PTHREAD_RWLOCK_INITIALIZER + pthread_rwlock_t _M_rwlock = PTHREAD_RWLOCK_INITIALIZER; + + public: + __shared_mutex_pthread() = default; + ~__shared_mutex_pthread() = default; +#else + pthread_rwlock_t _M_rwlock; + + public: + __shared_mutex_pthread() + { + int __ret = __glibcxx_rwlock_init(&_M_rwlock); + if (__ret == ENOMEM) + __throw_bad_alloc(); + else if (__ret == EAGAIN) + __throw_system_error(int(errc::resource_unavailable_try_again)); + else if (__ret == EPERM) + __throw_system_error(int(errc::operation_not_permitted)); + // Errors not handled: EBUSY, EINVAL + __glibcxx_assert(__ret == 0); + } + + ~__shared_mutex_pthread() + { + int __ret __attribute((__unused__)) = __glibcxx_rwlock_destroy(&_M_rwlock); + // Errors not handled: EBUSY, EINVAL + __glibcxx_assert(__ret == 0); + } +#endif + + __shared_mutex_pthread(const __shared_mutex_pthread&) = delete; + __shared_mutex_pthread& operator=(const __shared_mutex_pthread&) = delete; + + void + lock() + { + int __ret = __glibcxx_rwlock_wrlock(&_M_rwlock); + if (__ret == EDEADLK) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + } + + bool + try_lock() + { + int __ret = __glibcxx_rwlock_trywrlock(&_M_rwlock); + if (__ret == EBUSY) return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } + + void + unlock() + { + int __ret __attribute((__unused__)) = __glibcxx_rwlock_unlock(&_M_rwlock); + // Errors not handled: EPERM, EBUSY, EINVAL + __glibcxx_assert(__ret == 0); + } + + // Shared ownership + + void + lock_shared() + { + int __ret; + // We retry if we exceeded the maximum number of read locks supported by + // the POSIX implementation; this can result in busy-waiting, but this + // is okay based on the current specification of forward progress + // guarantees by the standard. + do + __ret = __glibcxx_rwlock_rdlock(&_M_rwlock); + while (__ret == EAGAIN); + if (__ret == EDEADLK) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + } + + bool + try_lock_shared() + { + int __ret = __glibcxx_rwlock_tryrdlock(&_M_rwlock); + // If the maximum number of read locks has been exceeded, we just fail + // to acquire the lock. Unlike for lock(), we are not allowed to throw + // an exception. + if (__ret == EBUSY || __ret == EAGAIN) return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } + + void + unlock_shared() + { + unlock(); + } + + void* native_handle() { return &_M_rwlock; } + }; +#endif + +#if ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) + /// A shared mutex type implemented using std::condition_variable. + class __shared_mutex_cv + { + friend class shared_timed_mutex; + + // Based on Howard Hinnant's reference implementation from N2406. + + // The high bit of _M_state is the write-entered flag which is set to + // indicate a writer has taken the lock or is queuing to take the lock. + // The remaining bits are the count of reader locks. + // + // To take a reader lock, block on gate1 while the write-entered flag is + // set or the maximum number of reader locks is held, then increment the + // reader lock count. + // To release, decrement the count, then if the write-entered flag is set + // and the count is zero then signal gate2 to wake a queued writer, + // otherwise if the maximum number of reader locks was held signal gate1 + // to wake a reader. + // + // To take a writer lock, block on gate1 while the write-entered flag is + // set, then set the write-entered flag to start queueing, then block on + // gate2 while the number of reader locks is non-zero. + // To release, unset the write-entered flag and signal gate1 to wake all + // blocked readers and writers. + // + // This means that when no reader locks are held readers and writers get + // equal priority. When one or more reader locks is held a writer gets + // priority and no more reader locks can be taken while the writer is + // queued. + + // Only locked when accessing _M_state or waiting on condition variables. + mutex _M_mut; + // Used to block while write-entered is set or reader count at maximum. + condition_variable _M_gate1; + // Used to block queued writers while reader count is non-zero. + condition_variable _M_gate2; + // The write-entered flag and reader count. + unsigned _M_state; + + static constexpr unsigned _S_write_entered + = 1U << (sizeof(unsigned)*__CHAR_BIT__ - 1); + static constexpr unsigned _S_max_readers = ~_S_write_entered; + + // Test whether the write-entered flag is set. _M_mut must be locked. + bool _M_write_entered() const { return _M_state & _S_write_entered; } + + // The number of reader locks currently held. _M_mut must be locked. + unsigned _M_readers() const { return _M_state & _S_max_readers; } + + public: + __shared_mutex_cv() : _M_state(0) {} + + ~__shared_mutex_cv() + { + __glibcxx_assert( _M_state == 0 ); + } + + __shared_mutex_cv(const __shared_mutex_cv&) = delete; + __shared_mutex_cv& operator=(const __shared_mutex_cv&) = delete; + + // Exclusive ownership + + void + lock() + { + unique_lock __lk(_M_mut); + // Wait until we can set the write-entered flag. + _M_gate1.wait(__lk, [=]{ return !_M_write_entered(); }); + _M_state |= _S_write_entered; + // Then wait until there are no more readers. + _M_gate2.wait(__lk, [=]{ return _M_readers() == 0; }); + } + + bool + try_lock() + { + unique_lock __lk(_M_mut, try_to_lock); + if (__lk.owns_lock() && _M_state == 0) + { + _M_state = _S_write_entered; + return true; + } + return false; + } + + void + unlock() + { + lock_guard __lk(_M_mut); + __glibcxx_assert( _M_write_entered() ); + _M_state = 0; + // call notify_all() while mutex is held so that another thread can't + // lock and unlock the mutex then destroy *this before we make the call. + _M_gate1.notify_all(); + } + + // Shared ownership + + void + lock_shared() + { + unique_lock __lk(_M_mut); + _M_gate1.wait(__lk, [=]{ return _M_state < _S_max_readers; }); + ++_M_state; + } + + bool + try_lock_shared() + { + unique_lock __lk(_M_mut, try_to_lock); + if (!__lk.owns_lock()) + return false; + if (_M_state < _S_max_readers) + { + ++_M_state; + return true; + } + return false; + } + + void + unlock_shared() + { + lock_guard __lk(_M_mut); + __glibcxx_assert( _M_readers() > 0 ); + auto __prev = _M_state--; + if (_M_write_entered()) + { + // Wake the queued writer if there are no more readers. + if (_M_readers() == 0) + _M_gate2.notify_one(); + // No need to notify gate1 because we give priority to the queued + // writer, and that writer will eventually notify gate1 after it + // clears the write-entered flag. + } + else + { + // Wake any thread that was blocked on reader overflow. + if (__prev == _S_max_readers) + _M_gate1.notify_one(); + } + } + }; +#endif + /// @endcond + +#if __cplusplus > 201402L + /// The standard shared mutex type. + class shared_mutex + { + public: + shared_mutex() = default; + ~shared_mutex() = default; + + shared_mutex(const shared_mutex&) = delete; + shared_mutex& operator=(const shared_mutex&) = delete; + + // Exclusive ownership + + void lock() { _M_impl.lock(); } + bool try_lock() { return _M_impl.try_lock(); } + void unlock() { _M_impl.unlock(); } + + // Shared ownership + + void lock_shared() { _M_impl.lock_shared(); } + bool try_lock_shared() { return _M_impl.try_lock_shared(); } + void unlock_shared() { _M_impl.unlock_shared(); } + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T + typedef void* native_handle_type; + native_handle_type native_handle() { return _M_impl.native_handle(); } + + private: + __shared_mutex_pthread _M_impl; +#else + private: + __shared_mutex_cv _M_impl; +#endif + }; +#endif // C++17 + + /// @cond undocumented +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK + using __shared_timed_mutex_base = __shared_mutex_pthread; +#else + using __shared_timed_mutex_base = __shared_mutex_cv; +#endif + /// @endcond + + /// The standard shared timed mutex type. + class shared_timed_mutex + : private __shared_timed_mutex_base + { + using _Base = __shared_timed_mutex_base; + + // Must use the same clock as condition_variable for __shared_mutex_cv. +#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK + using __clock_t = chrono::steady_clock; +#else + using __clock_t = chrono::system_clock; +#endif + + public: + shared_timed_mutex() = default; + ~shared_timed_mutex() = default; + + shared_timed_mutex(const shared_timed_mutex&) = delete; + shared_timed_mutex& operator=(const shared_timed_mutex&) = delete; + + // Exclusive ownership + + void lock() { _Base::lock(); } + bool try_lock() { return _Base::try_lock(); } + void unlock() { _Base::unlock(); } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rtime) + { + auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime); + if (ratio_greater<__clock_t::period, _Period>()) + ++__rt; + return try_lock_until(__clock_t::now() + __rt); + } + + // Shared ownership + + void lock_shared() { _Base::lock_shared(); } + bool try_lock_shared() { return _Base::try_lock_shared(); } + void unlock_shared() { _Base::unlock_shared(); } + + template + bool + try_lock_shared_for(const chrono::duration<_Rep, _Period>& __rtime) + { + auto __rt = chrono::duration_cast<__clock_t::duration>(__rtime); + if (ratio_greater<__clock_t::period, _Period>()) + ++__rt; + return try_lock_shared_until(__clock_t::now() + __rt); + } + +#if _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK + + // Exclusive ownership + + template + bool + try_lock_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret = __glibcxx_rwlock_timedwrlock(&_M_rwlock, &__ts); + // On self-deadlock, we just fail to acquire the lock. Technically, + // the program violated the precondition. + if (__ret == ETIMEDOUT || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } + +#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK + template + bool + try_lock_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret = pthread_rwlock_clockwrlock(&_M_rwlock, CLOCK_MONOTONIC, + &__ts); + // On self-deadlock, we just fail to acquire the lock. Technically, + // the program violated the precondition. + if (__ret == ETIMEDOUT || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } +#endif + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __atime) + { +#if __cplusplus > 201703L + static_assert(chrono::is_clock_v<_Clock>); +#endif + // The user-supplied clock may not tick at the same rate as + // steady_clock, so we must loop in order to guarantee that + // the timeout has expired before returning false. + typename _Clock::time_point __now = _Clock::now(); + do { + auto __rtime = __atime - __now; + if (try_lock_for(__rtime)) + return true; + __now = _Clock::now(); + } while (__atime > __now); + return false; + } + + // Shared ownership + + template + bool + try_lock_shared_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret; + // Unlike for lock(), we are not allowed to throw an exception so if + // the maximum number of read locks has been exceeded, or we would + // deadlock, we just try to acquire the lock again (and will time out + // eventually). + // In cases where we would exceed the maximum number of read locks + // throughout the whole time until the timeout, we will fail to + // acquire the lock even if it would be logically free; however, this + // is allowed by the standard, and we made a "strong effort" + // (see C++14 30.4.1.4p26). + // For cases where the implementation detects a deadlock we + // intentionally block and timeout so that an early return isn't + // mistaken for a spurious failure, which might help users realise + // there is a deadlock. + do + __ret = __glibcxx_rwlock_timedrdlock(&_M_rwlock, &__ts); + while (__ret == EAGAIN || __ret == EDEADLK); + if (__ret == ETIMEDOUT) + return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } + +#ifdef _GLIBCXX_USE_PTHREAD_RWLOCK_CLOCKLOCK + template + bool + try_lock_shared_until(const chrono::time_point& __atime) + { + auto __s = chrono::time_point_cast(__atime); + auto __ns = chrono::duration_cast(__atime - __s); + + __gthread_time_t __ts = + { + static_cast(__s.time_since_epoch().count()), + static_cast(__ns.count()) + }; + + int __ret = pthread_rwlock_clockrdlock(&_M_rwlock, CLOCK_MONOTONIC, + &__ts); + // On self-deadlock, we just fail to acquire the lock. Technically, + // the program violated the precondition. + if (__ret == ETIMEDOUT || __ret == EDEADLK) + return false; + // Errors not handled: EINVAL + __glibcxx_assert(__ret == 0); + return true; + } +#endif + + template + bool + try_lock_shared_until(const chrono::time_point<_Clock, + _Duration>& __atime) + { +#if __cplusplus > 201703L + static_assert(chrono::is_clock_v<_Clock>); +#endif + // The user-supplied clock may not tick at the same rate as + // steady_clock, so we must loop in order to guarantee that + // the timeout has expired before returning false. + typename _Clock::time_point __now = _Clock::now(); + do { + auto __rtime = __atime - __now; + if (try_lock_shared_for(__rtime)) + return true; + __now = _Clock::now(); + } while (__atime > __now); + return false; + } + +#else // ! (_GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK) + + // Exclusive ownership + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + { + unique_lock __lk(_M_mut); + if (!_M_gate1.wait_until(__lk, __abs_time, + [=]{ return !_M_write_entered(); })) + { + return false; + } + _M_state |= _S_write_entered; + if (!_M_gate2.wait_until(__lk, __abs_time, + [=]{ return _M_readers() == 0; })) + { + _M_state ^= _S_write_entered; + // Wake all threads blocked while the write-entered flag was set. + _M_gate1.notify_all(); + return false; + } + return true; + } + + // Shared ownership + + template + bool + try_lock_shared_until(const chrono::time_point<_Clock, + _Duration>& __abs_time) + { + unique_lock __lk(_M_mut); + if (!_M_gate1.wait_until(__lk, __abs_time, + [=]{ return _M_state < _S_max_readers; })) + { + return false; + } + ++_M_state; + return true; + } + +#endif // _GLIBCXX_USE_PTHREAD_RWLOCK_T && _GTHREAD_USE_MUTEX_TIMEDLOCK + }; +#endif // _GLIBCXX_HAS_GTHREADS + + /// shared_lock + template + class shared_lock + { + public: + typedef _Mutex mutex_type; + + // Shared locking + + shared_lock() noexcept : _M_pm(nullptr), _M_owns(false) { } + + explicit + shared_lock(mutex_type& __m) + : _M_pm(std::__addressof(__m)), _M_owns(true) + { __m.lock_shared(); } + + shared_lock(mutex_type& __m, defer_lock_t) noexcept + : _M_pm(std::__addressof(__m)), _M_owns(false) { } + + shared_lock(mutex_type& __m, try_to_lock_t) + : _M_pm(std::__addressof(__m)), _M_owns(__m.try_lock_shared()) { } + + shared_lock(mutex_type& __m, adopt_lock_t) + : _M_pm(std::__addressof(__m)), _M_owns(true) { } + + template + shared_lock(mutex_type& __m, + const chrono::time_point<_Clock, _Duration>& __abs_time) + : _M_pm(std::__addressof(__m)), + _M_owns(__m.try_lock_shared_until(__abs_time)) { } + + template + shared_lock(mutex_type& __m, + const chrono::duration<_Rep, _Period>& __rel_time) + : _M_pm(std::__addressof(__m)), + _M_owns(__m.try_lock_shared_for(__rel_time)) { } + + ~shared_lock() + { + if (_M_owns) + _M_pm->unlock_shared(); + } + + shared_lock(shared_lock const&) = delete; + shared_lock& operator=(shared_lock const&) = delete; + + shared_lock(shared_lock&& __sl) noexcept : shared_lock() + { swap(__sl); } + + shared_lock& + operator=(shared_lock&& __sl) noexcept + { + shared_lock(std::move(__sl)).swap(*this); + return *this; + } + + void + lock() + { + _M_lockable(); + _M_pm->lock_shared(); + _M_owns = true; + } + + bool + try_lock() + { + _M_lockable(); + return _M_owns = _M_pm->try_lock_shared(); + } + + template + bool + try_lock_for(const chrono::duration<_Rep, _Period>& __rel_time) + { + _M_lockable(); + return _M_owns = _M_pm->try_lock_shared_for(__rel_time); + } + + template + bool + try_lock_until(const chrono::time_point<_Clock, _Duration>& __abs_time) + { + _M_lockable(); + return _M_owns = _M_pm->try_lock_shared_until(__abs_time); + } + + void + unlock() + { + if (!_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + _M_pm->unlock_shared(); + _M_owns = false; + } + + // Setters + + void + swap(shared_lock& __u) noexcept + { + std::swap(_M_pm, __u._M_pm); + std::swap(_M_owns, __u._M_owns); + } + + mutex_type* + release() noexcept + { + _M_owns = false; + return std::exchange(_M_pm, nullptr); + } + + // Getters + + bool owns_lock() const noexcept { return _M_owns; } + + explicit operator bool() const noexcept { return _M_owns; } + + mutex_type* mutex() const noexcept { return _M_pm; } + + private: + void + _M_lockable() const + { + if (_M_pm == nullptr) + __throw_system_error(int(errc::operation_not_permitted)); + if (_M_owns) + __throw_system_error(int(errc::resource_deadlock_would_occur)); + + } + + mutex_type* _M_pm; + bool _M_owns; + }; + + /// Swap specialization for shared_lock + /// @relates shared_mutex + template + void + swap(shared_lock<_Mutex>& __x, shared_lock<_Mutex>& __y) noexcept + { __x.swap(__y); } + + // @} group mutexes +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif // C++14 + +#endif // _GLIBCXX_SHARED_MUTEX diff --git a/resources/sources/avr-libstdcpp/include/span b/resources/sources/avr-libstdcpp/include/span new file mode 100644 index 000000000..1cdc0589d --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/span @@ -0,0 +1,462 @@ +// Components for manipulating non-owning sequences of objects -*- C++ -*- + +// Copyright (C) 2019-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file span + * This is a Standard C++ Library header. + */ + +// +// P0122 span library +// Contributed by ThePhD +// + +#ifndef _GLIBCXX_SPAN +#define _GLIBCXX_SPAN 1 + +#pragma GCC system_header + +#if __cplusplus > 201703L + +#include +#include +#include +#include + +#if __cpp_lib_concepts +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_span 202002L + + inline constexpr size_t dynamic_extent = static_cast(-1); + + template + class span; + + namespace __detail + { + template + struct __is_std_span : false_type { }; + + template + struct __is_std_span> : true_type { }; + + template + struct __is_std_array : false_type { }; + + template + struct __is_std_array<_GLIBCXX_STD_C::array<_Tp, _Num>> : true_type { }; + +#ifdef _GLIBCXX_DEBUG + template + struct __is_std_array<__debug::array<_Tp, _Num>> : true_type { }; +#endif + + template + class __extent_storage + { + public: + constexpr + __extent_storage(size_t) noexcept + { } + + static constexpr size_t + _M_extent() noexcept + { return _Extent; } + }; + + template<> + class __extent_storage + { + public: + constexpr + __extent_storage(size_t __extent) noexcept + : _M_extent_value(__extent) + { } + + constexpr size_t + _M_extent() const noexcept + { return this->_M_extent_value; } + + private: + size_t _M_extent_value; + }; + } // namespace __detail + + template + class span + { + template + static constexpr size_t + _S_subspan_extent() + { + if constexpr (_Count != dynamic_extent) + return _Count; + else if constexpr (extent != dynamic_extent) + return _Extent - _Offset; + else + return dynamic_extent; + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 3255. span's array constructor is too strict + template + requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) + using __is_compatible_array = __is_array_convertible<_Type, _Tp>; + + template + using __is_compatible_ref + = __is_array_convertible<_Type, remove_reference_t<_Ref>>; + + public: + // member types + using element_type = _Type; + using value_type = remove_cv_t<_Type>; + using size_type = size_t; + using difference_type = ptrdiff_t; + using pointer = _Type*; + using const_pointer = const _Type*; + using reference = element_type&; + using const_reference = const element_type&; + using iterator = __gnu_cxx::__normal_iterator; + using reverse_iterator = std::reverse_iterator; + + // member constants + static constexpr size_t extent = _Extent; + + // constructors, copy and assignment + + constexpr + span() noexcept + requires ((_Extent + 1u) <= 1u) + : _M_extent(0), _M_ptr(nullptr) + { } + + template + requires __is_compatible_ref>::value + constexpr explicit(extent != dynamic_extent) + span(_It __first, size_type __count) + noexcept + : _M_extent(__count), _M_ptr(std::to_address(__first)) + { + if constexpr (_Extent != dynamic_extent) + { + __glibcxx_assert(__count == _Extent); + } + } + + template _End> + requires __is_compatible_ref>::value + && (!is_convertible_v<_End, size_type>) + constexpr explicit(extent != dynamic_extent) + span(_It __first, _End __last) + noexcept(noexcept(__last - __first)) + : _M_extent(static_cast(__last - __first)), + _M_ptr(std::to_address(__first)) + { + if constexpr (_Extent != dynamic_extent) + { + __glibcxx_assert((__last - __first) == _Extent); + } + } + + template + requires (_Extent == dynamic_extent || _ArrayExtent == _Extent) + constexpr + span(type_identity_t (&__arr)[_ArrayExtent]) noexcept + : span(static_cast(__arr), _ArrayExtent) + { } + + template + requires __is_compatible_array<_Tp, _ArrayExtent>::value + constexpr + span(array<_Tp, _ArrayExtent>& __arr) noexcept + : span(static_cast(__arr.data()), _ArrayExtent) + { } + + template + requires __is_compatible_array::value + constexpr + span(const array<_Tp, _ArrayExtent>& __arr) noexcept + : span(static_cast(__arr.data()), _ArrayExtent) + { } + + template + requires ranges::contiguous_range<_Range> && ranges::sized_range<_Range> + && (ranges::borrowed_range<_Range> || is_const_v) + && (!__detail::__is_std_span>::value) + && (!__detail::__is_std_array>::value) + && (!is_array_v>) + && __is_compatible_ref>::value + constexpr explicit(extent != dynamic_extent) + span(_Range&& __range) + noexcept(noexcept(ranges::data(__range)) + && noexcept(ranges::size(__range))) + : span(ranges::data(__range), ranges::size(__range)) + { + if constexpr (extent != dynamic_extent) + { + __glibcxx_assert(ranges::size(__range) == extent); + } + } + + constexpr + span(const span&) noexcept = default; + + template + requires (_Extent == dynamic_extent || _OExtent == dynamic_extent + || _Extent == _OExtent) + && (__is_array_convertible<_Type, _OType>::value) + constexpr + explicit(extent != dynamic_extent && _OExtent == dynamic_extent) + span(const span<_OType, _OExtent>& __s) noexcept + : _M_extent(__s.size()), _M_ptr(__s.data()) + { + if constexpr (extent != dynamic_extent) + { + __glibcxx_assert(__s.size() == extent); + } + } + + ~span() noexcept = default; + + constexpr span& + operator=(const span&) noexcept = default; + + // observers + + constexpr size_type + size() const noexcept + { return this->_M_extent._M_extent(); } + + constexpr size_type + size_bytes() const noexcept + { return this->_M_extent._M_extent() * sizeof(element_type); } + + [[nodiscard]] constexpr bool + empty() const noexcept + { return size() == 0; } + + // element access + + constexpr reference + front() const noexcept + { + __glibcxx_assert(!empty()); + return *this->_M_ptr; + } + + constexpr reference + back() const noexcept + { + __glibcxx_assert(!empty()); + return *(this->_M_ptr + (size() - 1)); + } + + constexpr reference + operator[](size_type __idx) const noexcept + { + __glibcxx_assert(__idx < size()); + return *(this->_M_ptr + __idx); + } + + constexpr pointer + data() const noexcept + { return this->_M_ptr; } + + // iterator support + + constexpr iterator + begin() const noexcept + { return iterator(this->_M_ptr); } + + constexpr iterator + end() const noexcept + { return iterator(this->_M_ptr + this->size()); } + + constexpr reverse_iterator + rbegin() const noexcept + { return reverse_iterator(this->end()); } + + constexpr reverse_iterator + rend() const noexcept + { return reverse_iterator(this->begin()); } + + // subviews + + template + constexpr span + first() const noexcept + { + if constexpr (_Extent == dynamic_extent) + __glibcxx_assert(_Count <= size()); + else + static_assert(_Count <= extent); + using _Sp = span; + return _Sp{ this->data(), _Count }; + } + + constexpr span + first(size_type __count) const noexcept + { + __glibcxx_assert(__count <= size()); + return { this->data(), __count }; + } + + template + constexpr span + last() const noexcept + { + if constexpr (_Extent == dynamic_extent) + __glibcxx_assert(_Count <= size()); + else + static_assert(_Count <= extent); + using _Sp = span; + return _Sp{ this->data() + (this->size() - _Count), _Count }; + } + + constexpr span + last(size_type __count) const noexcept + { + __glibcxx_assert(__count <= size()); + return { this->data() + (this->size() - __count), __count }; + } + + template + constexpr auto + subspan() const noexcept + -> span()> + { + if constexpr (_Extent == dynamic_extent) + { + __glibcxx_assert(_Offset <= size()); + } + else + static_assert(_Offset <= extent); + + using _Sp = span()>; + + if constexpr (_Count == dynamic_extent) + return _Sp{ this->data() + _Offset, this->size() - _Offset }; + else + { + if constexpr (_Extent == dynamic_extent) + { + __glibcxx_assert(_Count <= size()); + __glibcxx_assert(_Count <= (size() - _Offset)); + } + else + { + static_assert(_Count <= extent); + static_assert(_Count <= (extent - _Offset)); + } + return _Sp{ this->data() + _Offset, _Count }; + } + } + + constexpr span + subspan(size_type __offset, size_type __count = dynamic_extent) const + noexcept + { + __glibcxx_assert(__offset <= size()); + if (__count == dynamic_extent) + __count = this->size() - __offset; + else + { + __glibcxx_assert(__count <= size()); + __glibcxx_assert(__offset + __count <= size()); + } + return {this->data() + __offset, __count}; + } + + private: + [[no_unique_address]] __detail::__extent_storage _M_extent; + pointer _M_ptr; + }; + + // deduction guides + + template + span(_Type(&)[_ArrayExtent]) -> span<_Type, _ArrayExtent>; + + template + span(array<_Type, _ArrayExtent>&) -> span<_Type, _ArrayExtent>; + + template + span(const array<_Type, _ArrayExtent>&) + -> span; + + template + span(_Iter, _End) + -> span>>; + + template + span(_Range &&) + -> span>>; + + template + inline + span + as_bytes(span<_Type, _Extent> __sp) noexcept + { + auto data = reinterpret_cast(__sp.data()); + auto size = __sp.size_bytes(); + constexpr auto extent = _Extent == dynamic_extent + ? dynamic_extent : _Extent * sizeof(_Type); + return span{data, size}; + } + + template + inline + span + as_writable_bytes(span<_Type, _Extent> __sp) noexcept + { + auto data = reinterpret_cast(__sp.data()); + auto size = __sp.size_bytes(); + constexpr auto extent = _Extent == dynamic_extent + ? dynamic_extent : _Extent * sizeof(_Type); + return span{data, size}; + } + + namespace ranges + { + // Opt-in to borrowed_range concept + template + inline constexpr bool + enable_borrowed_range> = true; + + // Opt-in to view concept + template + inline constexpr bool + enable_view> + = _Extent == 0 || _Extent == dynamic_extent; + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // concepts +#endif // C++20 +#endif // _GLIBCXX_SPAN diff --git a/resources/sources/avr-libstdcpp/include/stack b/resources/sources/avr-libstdcpp/include/stack new file mode 100644 index 000000000..064b3583a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/stack @@ -0,0 +1,63 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/stack + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_STACK +#define _GLIBCXX_STACK 1 + +#pragma GCC system_header + +#include +#include + +#endif /* _GLIBCXX_STACK */ diff --git a/resources/sources/avr-libstdcpp/include/stdexcept b/resources/sources/avr-libstdcpp/include/stdexcept deleted file mode 100644 index efeeb30a6..000000000 --- a/resources/sources/avr-libstdcpp/include/stdexcept +++ /dev/null @@ -1,4 +0,0 @@ -// Stub: exceptions not available on AVR -#ifndef _AVR_STDEXCEPT_STUB -#define _AVR_STDEXCEPT_STUB -#endif diff --git a/resources/sources/avr-libstdcpp/include/string b/resources/sources/avr-libstdcpp/include/string index cb862b18d..03acb5d6b 100644 --- a/resources/sources/avr-libstdcpp/include/string +++ b/resources/sources/avr-libstdcpp/include/string @@ -1,4 +1,18 @@ -// Stub: std::string not available on AVR (requires heap + exceptions) -#ifndef _AVR_STRING_STUB -#define _AVR_STRING_STUB +// -*- C++ -*- +// OpenPLC Editor stub for on AVR. +// +// modm-io/avr-libstdcpp intentionally excludes because std::string +// requires heap allocation, exceptions, and a hosted environment, none of +// which are appropriate for AVR targets. +// +// STruC++ generated code emits `#include ` unconditionally in its +// header preamble, but never actually uses std::string — it uses its own +// IECString template (stack-allocated, fixed-size) for IEC STRING +// variables. This stub satisfies the include without providing the type. +// +// If you do try to use std::string on AVR with this stub, you'll get a +// clear compile error rather than a silent misbehavior. + +#ifndef _OPENPLC_AVR_STRING_STUB +#define _OPENPLC_AVR_STRING_STUB #endif diff --git a/resources/sources/avr-libstdcpp/include/string_view b/resources/sources/avr-libstdcpp/include/string_view new file mode 100644 index 000000000..487088c7e --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/string_view @@ -0,0 +1,758 @@ +// Components for manipulating non-owning sequences of characters -*- C++ -*- + +// Copyright (C) 2013-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file string_view + * This is a Standard C++ Library header. + */ + +// +// N3762 basic_string_view library +// + +#ifndef _GLIBCXX_STRING_VIEW +#define _GLIBCXX_STRING_VIEW 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +# define __cpp_lib_string_view 201803L +#if __cplusplus > 201703L +# define __cpp_lib_constexpr_string_view 201811L +#endif + + // Helper for basic_string and basic_string_view members. + constexpr size_t + __sv_check(size_t __size, size_t __pos, const char* __s) + { + if (__pos > __size) + __throw_out_of_range_fmt(__N("%s: __pos (which is %zu) > __size " + "(which is %zu)"), __s, __pos, __size); + return __pos; + } + + // Helper for basic_string members. + // NB: __sv_limit doesn't check for a bad __pos value. + constexpr size_t + __sv_limit(size_t __size, size_t __pos, size_t __off) noexcept + { + const bool __testoff = __off < __size - __pos; + return __testoff ? __off : __size - __pos; + } + + /** + * @class basic_string_view + * @brief A non-owning reference to a string. + * + * @ingroup strings + * @ingroup sequences + * + * @tparam _CharT Type of character + * @tparam _Traits Traits for character type, defaults to + * char_traits<_CharT>. + * + * A basic_string_view looks like this: + * + * @code + * _CharT* _M_str + * size_t _M_len + * @endcode + */ + template> + class basic_string_view + { + static_assert(!is_array_v<_CharT>); + static_assert(is_trivial_v<_CharT> && is_standard_layout_v<_CharT>); + static_assert(is_same_v<_CharT, typename _Traits::char_type>); + + public: + + // types + using traits_type = _Traits; + using value_type = _CharT; + using pointer = value_type*; + using const_pointer = const value_type*; + using reference = value_type&; + using const_reference = const value_type&; + using const_iterator = const value_type*; + using iterator = const_iterator; + using const_reverse_iterator = std::reverse_iterator; + using reverse_iterator = const_reverse_iterator; + using size_type = size_t; + using difference_type = ptrdiff_t; + static constexpr size_type npos = size_type(-1); + + // [string.view.cons], construction and assignment + + constexpr + basic_string_view() noexcept + : _M_len{0}, _M_str{nullptr} + { } + + constexpr basic_string_view(const basic_string_view&) noexcept = default; + + __attribute__((__nonnull__)) constexpr + basic_string_view(const _CharT* __str) noexcept + : _M_len{traits_type::length(__str)}, + _M_str{__str} + { } + + constexpr + basic_string_view(const _CharT* __str, size_type __len) noexcept + : _M_len{__len}, _M_str{__str} + { } + +#if __cplusplus > 201703L && __cpp_lib_concepts + template _End> + requires same_as, _CharT> + && (!convertible_to<_End, size_type>) + constexpr + basic_string_view(_It __first, _End __last) + : _M_len(__last - __first), _M_str(std::to_address(__first)) + { } +#endif + + constexpr basic_string_view& + operator=(const basic_string_view&) noexcept = default; + + // [string.view.iterators], iterator support + + constexpr const_iterator + begin() const noexcept + { return this->_M_str; } + + constexpr const_iterator + end() const noexcept + { return this->_M_str + this->_M_len; } + + constexpr const_iterator + cbegin() const noexcept + { return this->_M_str; } + + constexpr const_iterator + cend() const noexcept + { return this->_M_str + this->_M_len; } + + constexpr const_reverse_iterator + rbegin() const noexcept + { return const_reverse_iterator(this->end()); } + + constexpr const_reverse_iterator + rend() const noexcept + { return const_reverse_iterator(this->begin()); } + + constexpr const_reverse_iterator + crbegin() const noexcept + { return const_reverse_iterator(this->end()); } + + constexpr const_reverse_iterator + crend() const noexcept + { return const_reverse_iterator(this->begin()); } + + // [string.view.capacity], capacity + + constexpr size_type + size() const noexcept + { return this->_M_len; } + + constexpr size_type + length() const noexcept + { return _M_len; } + + constexpr size_type + max_size() const noexcept + { + return (npos - sizeof(size_type) - sizeof(void*)) + / sizeof(value_type) / 4; + } + + [[nodiscard]] constexpr bool + empty() const noexcept + { return this->_M_len == 0; } + + // [string.view.access], element access + + constexpr const_reference + operator[](size_type __pos) const noexcept + { + __glibcxx_assert(__pos < this->_M_len); + return *(this->_M_str + __pos); + } + + constexpr const_reference + at(size_type __pos) const + { + if (__pos >= _M_len) + __throw_out_of_range_fmt(__N("basic_string_view::at: __pos " + "(which is %zu) >= this->size() " + "(which is %zu)"), __pos, this->size()); + return *(this->_M_str + __pos); + } + + constexpr const_reference + front() const noexcept + { + __glibcxx_assert(this->_M_len > 0); + return *this->_M_str; + } + + constexpr const_reference + back() const noexcept + { + __glibcxx_assert(this->_M_len > 0); + return *(this->_M_str + this->_M_len - 1); + } + + constexpr const_pointer + data() const noexcept + { return this->_M_str; } + + // [string.view.modifiers], modifiers: + + constexpr void + remove_prefix(size_type __n) noexcept + { + __glibcxx_assert(this->_M_len >= __n); + this->_M_str += __n; + this->_M_len -= __n; + } + + constexpr void + remove_suffix(size_type __n) noexcept + { this->_M_len -= __n; } + + constexpr void + swap(basic_string_view& __sv) noexcept + { + auto __tmp = *this; + *this = __sv; + __sv = __tmp; + } + + // [string.view.ops], string operations: + + _GLIBCXX20_CONSTEXPR + size_type + copy(_CharT* __str, size_type __n, size_type __pos = 0) const + { + __glibcxx_requires_string_len(__str, __n); + __pos = std::__sv_check(size(), __pos, "basic_string_view::copy"); + const size_type __rlen = std::min(__n, _M_len - __pos); + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2777. basic_string_view::copy should use char_traits::copy + traits_type::copy(__str, data() + __pos, __rlen); + return __rlen; + } + + constexpr basic_string_view + substr(size_type __pos = 0, size_type __n = npos) const noexcept(false) + { + __pos = std::__sv_check(size(), __pos, "basic_string_view::substr"); + const size_type __rlen = std::min(__n, _M_len - __pos); + return basic_string_view{_M_str + __pos, __rlen}; + } + + constexpr int + compare(basic_string_view __str) const noexcept + { + const size_type __rlen = std::min(this->_M_len, __str._M_len); + int __ret = traits_type::compare(this->_M_str, __str._M_str, __rlen); + if (__ret == 0) + __ret = _S_compare(this->_M_len, __str._M_len); + return __ret; + } + + constexpr int + compare(size_type __pos1, size_type __n1, basic_string_view __str) const + { return this->substr(__pos1, __n1).compare(__str); } + + constexpr int + compare(size_type __pos1, size_type __n1, + basic_string_view __str, size_type __pos2, size_type __n2) const + { + return this->substr(__pos1, __n1).compare(__str.substr(__pos2, __n2)); + } + + __attribute__((__nonnull__)) constexpr int + compare(const _CharT* __str) const noexcept + { return this->compare(basic_string_view{__str}); } + + __attribute__((__nonnull__)) constexpr int + compare(size_type __pos1, size_type __n1, const _CharT* __str) const + { return this->substr(__pos1, __n1).compare(basic_string_view{__str}); } + + constexpr int + compare(size_type __pos1, size_type __n1, + const _CharT* __str, size_type __n2) const noexcept(false) + { + return this->substr(__pos1, __n1) + .compare(basic_string_view(__str, __n2)); + } + +#if __cplusplus > 201703L +#define __cpp_lib_starts_ends_with 201711L + constexpr bool + starts_with(basic_string_view __x) const noexcept + { return this->substr(0, __x.size()) == __x; } + + constexpr bool + starts_with(_CharT __x) const noexcept + { return !this->empty() && traits_type::eq(this->front(), __x); } + + constexpr bool + starts_with(const _CharT* __x) const noexcept + { return this->starts_with(basic_string_view(__x)); } + + constexpr bool + ends_with(basic_string_view __x) const noexcept + { + return this->size() >= __x.size() + && this->compare(this->size() - __x.size(), npos, __x) == 0; + } + + constexpr bool + ends_with(_CharT __x) const noexcept + { return !this->empty() && traits_type::eq(this->back(), __x); } + + constexpr bool + ends_with(const _CharT* __x) const noexcept + { return this->ends_with(basic_string_view(__x)); } +#endif // C++20 + + // [string.view.find], searching + + constexpr size_type + find(basic_string_view __str, size_type __pos = 0) const noexcept + { return this->find(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find(_CharT __c, size_type __pos = 0) const noexcept; + + constexpr size_type + find(const _CharT* __str, size_type __pos, size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find(const _CharT* __str, size_type __pos = 0) const noexcept + { return this->find(__str, __pos, traits_type::length(__str)); } + + constexpr size_type + rfind(basic_string_view __str, size_type __pos = npos) const noexcept + { return this->rfind(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + rfind(_CharT __c, size_type __pos = npos) const noexcept; + + constexpr size_type + rfind(const _CharT* __str, size_type __pos, size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + rfind(const _CharT* __str, size_type __pos = npos) const noexcept + { return this->rfind(__str, __pos, traits_type::length(__str)); } + + constexpr size_type + find_first_of(basic_string_view __str, size_type __pos = 0) const noexcept + { return this->find_first_of(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find_first_of(_CharT __c, size_type __pos = 0) const noexcept + { return this->find(__c, __pos); } + + constexpr size_type + find_first_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find_first_of(const _CharT* __str, size_type __pos = 0) const noexcept + { return this->find_first_of(__str, __pos, traits_type::length(__str)); } + + constexpr size_type + find_last_of(basic_string_view __str, + size_type __pos = npos) const noexcept + { return this->find_last_of(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find_last_of(_CharT __c, size_type __pos=npos) const noexcept + { return this->rfind(__c, __pos); } + + constexpr size_type + find_last_of(const _CharT* __str, size_type __pos, + size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find_last_of(const _CharT* __str, size_type __pos = npos) const noexcept + { return this->find_last_of(__str, __pos, traits_type::length(__str)); } + + constexpr size_type + find_first_not_of(basic_string_view __str, + size_type __pos = 0) const noexcept + { return this->find_first_not_of(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find_first_not_of(_CharT __c, size_type __pos = 0) const noexcept; + + constexpr size_type + find_first_not_of(const _CharT* __str, + size_type __pos, size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find_first_not_of(const _CharT* __str, size_type __pos = 0) const noexcept + { + return this->find_first_not_of(__str, __pos, + traits_type::length(__str)); + } + + constexpr size_type + find_last_not_of(basic_string_view __str, + size_type __pos = npos) const noexcept + { return this->find_last_not_of(__str._M_str, __pos, __str._M_len); } + + constexpr size_type + find_last_not_of(_CharT __c, size_type __pos = npos) const noexcept; + + constexpr size_type + find_last_not_of(const _CharT* __str, + size_type __pos, size_type __n) const noexcept; + + __attribute__((__nonnull__)) constexpr size_type + find_last_not_of(const _CharT* __str, + size_type __pos = npos) const noexcept + { + return this->find_last_not_of(__str, __pos, + traits_type::length(__str)); + } + + private: + + static constexpr int + _S_compare(size_type __n1, size_type __n2) noexcept + { + const difference_type __diff = __n1 - __n2; + if (__diff > __gnu_cxx::__int_traits::__max) + return __gnu_cxx::__int_traits::__max; + if (__diff < __gnu_cxx::__int_traits::__min) + return __gnu_cxx::__int_traits::__min; + return static_cast(__diff); + } + + size_t _M_len; + const _CharT* _M_str; + }; + +#if __cplusplus > 201703L && __cpp_lib_concepts && __cpp_deduction_guides + template _End> + basic_string_view(_It, _End) -> basic_string_view>; +#endif + + // [string.view.comparison], non-member basic_string_view comparison function + + // Several of these functions use type_identity_t to create a non-deduced + // context, so that only one argument participates in template argument + // deduction and the other argument gets implicitly converted to the deduced + // type (see N3766). + + template + constexpr bool + operator==(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + + template + constexpr bool + operator==(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + +#if __cpp_lib_three_way_comparison + template + constexpr auto + operator<=>(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) + { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } + + template + constexpr auto + operator<=>(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + -> decltype(__detail::__char_traits_cmp_cat<_Traits>(0)) + { return __detail::__char_traits_cmp_cat<_Traits>(__x.compare(__y)); } +#else + template + constexpr bool + operator==(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.size() == __y.size() && __x.compare(__y) == 0; } + + template + constexpr bool + operator!=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return !(__x == __y); } + + template + constexpr bool + operator!=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return !(__x == __y); } + + template + constexpr bool + operator!=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return !(__x == __y); } + + template + constexpr bool + operator< (basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) < 0; } + + template + constexpr bool + operator< (basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) < 0; } + + template + constexpr bool + operator< (__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) < 0; } + + template + constexpr bool + operator> (basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) > 0; } + + template + constexpr bool + operator> (basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) > 0; } + + template + constexpr bool + operator> (__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) > 0; } + + template + constexpr bool + operator<=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) <= 0; } + + template + constexpr bool + operator<=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) <= 0; } + + template + constexpr bool + operator<=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) <= 0; } + + template + constexpr bool + operator>=(basic_string_view<_CharT, _Traits> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) >= 0; } + + template + constexpr bool + operator>=(basic_string_view<_CharT, _Traits> __x, + __type_identity_t> __y) + noexcept + { return __x.compare(__y) >= 0; } + + template + constexpr bool + operator>=(__type_identity_t> __x, + basic_string_view<_CharT, _Traits> __y) noexcept + { return __x.compare(__y) >= 0; } +#endif // three-way comparison + + // basic_string_view typedef names + + using string_view = basic_string_view; +#ifdef _GLIBCXX_USE_WCHAR_T + using wstring_view = basic_string_view; +#endif +#ifdef _GLIBCXX_USE_CHAR8_T + using u8string_view = basic_string_view; +#endif + using u16string_view = basic_string_view; + using u32string_view = basic_string_view; + + // [string.view.hash], hash support: + + template + struct hash; + + template<> + struct hash + : public __hash_base + { + size_t + operator()(const string_view& __str) const noexcept + { return std::_Hash_impl::hash(__str.data(), __str.length()); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct hash + : public __hash_base + { + size_t + operator()(const wstring_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(wchar_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; +#endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct hash + : public __hash_base + { + size_t + operator()(const u8string_view& __str) const noexcept + { return std::_Hash_impl::hash(__str.data(), __str.length()); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; +#endif + + template<> + struct hash + : public __hash_base + { + size_t + operator()(const u16string_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(char16_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + + template<> + struct hash + : public __hash_base + { + size_t + operator()(const u32string_view& __s) const noexcept + { return std::_Hash_impl::hash(__s.data(), + __s.length() * sizeof(char32_t)); } + }; + + template<> + struct __is_fast_hash> : std::false_type + { }; + + inline namespace literals + { + inline namespace string_view_literals + { +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wliteral-suffix" + inline constexpr basic_string_view + operator""sv(const char* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + +#ifdef _GLIBCXX_USE_WCHAR_T + inline constexpr basic_string_view + operator""sv(const wchar_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } +#endif + +#ifdef _GLIBCXX_USE_CHAR8_T + inline constexpr basic_string_view + operator""sv(const char8_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } +#endif + + inline constexpr basic_string_view + operator""sv(const char16_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + + inline constexpr basic_string_view + operator""sv(const char32_t* __str, size_t __len) noexcept + { return basic_string_view{__str, __len}; } + +#pragma GCC diagnostic pop + } // namespace string_literals + } // namespace literals + +#if __cpp_lib_concepts + namespace ranges + { + // Opt-in to borrowed_range concept + template + inline constexpr bool + enable_borrowed_range> = true; + + // Opt-in to view concept + template + inline constexpr bool + enable_view> = true; + } +#endif +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#include + +#endif // __cplusplus <= 201402L + +#endif // _GLIBCXX_EXPERIMENTAL_STRING_VIEW diff --git a/resources/sources/avr-libstdcpp/include/tuple b/resources/sources/avr-libstdcpp/include/tuple new file mode 100644 index 000000000..94b9e0335 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/tuple @@ -0,0 +1,1764 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/tuple + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TUPLE +#define _GLIBCXX_TUPLE 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +# define __cpp_lib_constexpr_tuple 201811L +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup utilities + * @{ + */ + + template + class tuple; + + template + struct __is_empty_non_tuple : is_empty<_Tp> { }; + + // Using EBO for elements that are tuples causes ambiguous base errors. + template + struct __is_empty_non_tuple> : false_type { }; + + // Use the Empty Base-class Optimization for empty, non-final types. + template + using __empty_not_final + = typename conditional<__is_final(_Tp), false_type, + __is_empty_non_tuple<_Tp>>::type; + + template::value> + struct _Head_base; + + template + struct _Head_base<_Idx, _Head, true> + : public _Head + { + constexpr _Head_base() + : _Head() { } + + constexpr _Head_base(const _Head& __h) + : _Head(__h) { } + + constexpr _Head_base(const _Head_base&) = default; + constexpr _Head_base(_Head_base&&) = default; + + template + constexpr _Head_base(_UHead&& __h) + : _Head(std::forward<_UHead>(__h)) { } + + _Head_base(allocator_arg_t, __uses_alloc0) + : _Head() { } + + template + _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) + : _Head(allocator_arg, *__a._M_a) { } + + template + _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) + : _Head(*__a._M_a) { } + + template + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _Head(std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _Head(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _Head(std::forward<_UHead>(__uhead), *__a._M_a) { } + + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b; } + }; + + template + struct _Head_base<_Idx, _Head, false> + { + constexpr _Head_base() + : _M_head_impl() { } + + constexpr _Head_base(const _Head& __h) + : _M_head_impl(__h) { } + + constexpr _Head_base(const _Head_base&) = default; + constexpr _Head_base(_Head_base&&) = default; + + template + constexpr _Head_base(_UHead&& __h) + : _M_head_impl(std::forward<_UHead>(__h)) { } + + _GLIBCXX20_CONSTEXPR + _Head_base(allocator_arg_t, __uses_alloc0) + : _M_head_impl() { } + + template + _Head_base(allocator_arg_t, __uses_alloc1<_Alloc> __a) + : _M_head_impl(allocator_arg, *__a._M_a) { } + + template + _Head_base(allocator_arg_t, __uses_alloc2<_Alloc> __a) + : _M_head_impl(*__a._M_a) { } + + template + _GLIBCXX20_CONSTEXPR + _Head_base(__uses_alloc0, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead)) { } + + template + _Head_base(__uses_alloc1<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(allocator_arg, *__a._M_a, std::forward<_UHead>(__uhead)) + { } + + template + _Head_base(__uses_alloc2<_Alloc> __a, _UHead&& __uhead) + : _M_head_impl(std::forward<_UHead>(__uhead), *__a._M_a) { } + + static constexpr _Head& + _M_head(_Head_base& __b) noexcept { return __b._M_head_impl; } + + static constexpr const _Head& + _M_head(const _Head_base& __b) noexcept { return __b._M_head_impl; } + + _Head _M_head_impl; + }; + + /** + * Contains the actual implementation of the @c tuple template, stored + * as a recursive inheritance hierarchy from the first element (most + * derived class) to the last (least derived class). The @c Idx + * parameter gives the 0-based index of the element stored at this + * point in the hierarchy; we use it to implement a constant-time + * get() operation. + */ + template + struct _Tuple_impl; + + /** + * Recursive tuple implementation. Here we store the @c Head element + * and derive from a @c Tuple_impl containing the remaining elements + * (which contains the @c Tail). + */ + template + struct _Tuple_impl<_Idx, _Head, _Tail...> + : public _Tuple_impl<_Idx + 1, _Tail...>, + private _Head_base<_Idx, _Head> + { + template friend class _Tuple_impl; + + typedef _Tuple_impl<_Idx + 1, _Tail...> _Inherited; + typedef _Head_base<_Idx, _Head> _Base; + + static constexpr _Head& + _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr const _Head& + _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr _Inherited& + _M_tail(_Tuple_impl& __t) noexcept { return __t; } + + static constexpr const _Inherited& + _M_tail(const _Tuple_impl& __t) noexcept { return __t; } + + constexpr _Tuple_impl() + : _Inherited(), _Base() { } + + explicit + constexpr _Tuple_impl(const _Head& __head, const _Tail&... __tail) + : _Inherited(__tail...), _Base(__head) { } + + template::type> + explicit + constexpr _Tuple_impl(_UHead&& __head, _UTail&&... __tail) + : _Inherited(std::forward<_UTail>(__tail)...), + _Base(std::forward<_UHead>(__head)) { } + + constexpr _Tuple_impl(const _Tuple_impl&) = default; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2729. Missing SFINAE on std::pair::operator= + _Tuple_impl& operator=(const _Tuple_impl&) = delete; + + constexpr + _Tuple_impl(_Tuple_impl&& __in) + noexcept(__and_, + is_nothrow_move_constructible<_Inherited>>::value) + : _Inherited(std::move(_M_tail(__in))), + _Base(std::forward<_Head>(_M_head(__in))) { } + + template + constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UElements...>& __in) + : _Inherited(_Tuple_impl<_Idx, _UElements...>::_M_tail(__in)), + _Base(_Tuple_impl<_Idx, _UElements...>::_M_head(__in)) { } + + template + constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a), + _Base(__tag, __use_alloc<_Head>(__a)) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Head& __head, const _Tail&... __tail) + : _Inherited(__tag, __a, __tail...), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } + + template::type> + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _UHead&& __head, _UTail&&... __tail) + : _Inherited(__tag, __a, std::forward<_UTail>(__tail)...), + _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(__head)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl& __in) + : _Inherited(__tag, __a, _M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl&& __in) + : _Inherited(__tag, __a, std::move(_M_tail(__in))), + _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + std::forward<_Head>(_M_head(__in))) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead, _UTails...>& __in) + : _Inherited(__tag, __a, + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in)), + _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), + _Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + : _Inherited(__tag, __a, std::move + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))), + _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in))) { } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(const _Tuple_impl<_Idx, _UElements...>& __in) + { + _M_head(*this) = _Tuple_impl<_Idx, _UElements...>::_M_head(__in); + _M_tail(*this)._M_assign( + _Tuple_impl<_Idx, _UElements...>::_M_tail(__in)); + } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(_Tuple_impl<_Idx, _UHead, _UTails...>&& __in) + { + _M_head(*this) = std::forward<_UHead> + (_Tuple_impl<_Idx, _UHead, _UTails...>::_M_head(__in)); + _M_tail(*this)._M_assign( + std::move(_Tuple_impl<_Idx, _UHead, _UTails...>::_M_tail(__in))); + } + + protected: + _GLIBCXX20_CONSTEXPR + void + _M_swap(_Tuple_impl& __in) + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + _Inherited::_M_swap(_M_tail(__in)); + } + }; + + // Basis case of inheritance recursion. + template + struct _Tuple_impl<_Idx, _Head> + : private _Head_base<_Idx, _Head> + { + template friend class _Tuple_impl; + + typedef _Head_base<_Idx, _Head> _Base; + + static constexpr _Head& + _M_head(_Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + static constexpr const _Head& + _M_head(const _Tuple_impl& __t) noexcept { return _Base::_M_head(__t); } + + constexpr _Tuple_impl() + : _Base() { } + + explicit + constexpr _Tuple_impl(const _Head& __head) + : _Base(__head) { } + + template + explicit + constexpr _Tuple_impl(_UHead&& __head) + : _Base(std::forward<_UHead>(__head)) { } + + constexpr _Tuple_impl(const _Tuple_impl&) = default; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2729. Missing SFINAE on std::pair::operator= + _Tuple_impl& operator=(const _Tuple_impl&) = delete; + + constexpr + _Tuple_impl(_Tuple_impl&& __in) + noexcept(is_nothrow_move_constructible<_Head>::value) + : _Base(std::forward<_Head>(_M_head(__in))) { } + + template + constexpr _Tuple_impl(const _Tuple_impl<_Idx, _UHead>& __in) + : _Base(_Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } + + template + constexpr _Tuple_impl(_Tuple_impl<_Idx, _UHead>&& __in) + : _Base(std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a) + : _Base(__tag, __use_alloc<_Head>(__a)) { } + + template + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Head& __head) + : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), __head) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _UHead&& __head) + : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(__head)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl& __in) + : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), _M_head(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl&& __in) + : _Base(__use_alloc<_Head, _Alloc, _Head>(__a), + std::forward<_Head>(_M_head(__in))) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + const _Tuple_impl<_Idx, _UHead>& __in) + : _Base(__use_alloc<_Head, _Alloc, const _UHead&>(__a), + _Tuple_impl<_Idx, _UHead>::_M_head(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + _Tuple_impl(allocator_arg_t __tag, const _Alloc& __a, + _Tuple_impl<_Idx, _UHead>&& __in) + : _Base(__use_alloc<_Head, _Alloc, _UHead>(__a), + std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in))) + { } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(const _Tuple_impl<_Idx, _UHead>& __in) + { + _M_head(*this) = _Tuple_impl<_Idx, _UHead>::_M_head(__in); + } + + template + _GLIBCXX20_CONSTEXPR + void + _M_assign(_Tuple_impl<_Idx, _UHead>&& __in) + { + _M_head(*this) + = std::forward<_UHead>(_Tuple_impl<_Idx, _UHead>::_M_head(__in)); + } + + protected: + _GLIBCXX20_CONSTEXPR + void + _M_swap(_Tuple_impl& __in) + { + using std::swap; + swap(_M_head(*this), _M_head(__in)); + } + }; + + // Concept utility functions, reused in conditionally-explicit + // constructors. + template + struct _TupleConstraints + { + // Constraint for a non-explicit constructor. + // True iff each Ti in _Types... can be constructed from Ui in _UTypes... + // and every Ui is implicitly convertible to Ti. + template + static constexpr bool __is_implicitly_constructible() + { + return __and_..., + is_convertible<_UTypes, _Types>... + >::value; + } + + // Constraint for a non-explicit constructor. + // True iff each Ti in _Types... can be constructed from Ui in _UTypes... + // but not every Ui is implicitly convertible to Ti. + template + static constexpr bool __is_explicitly_constructible() + { + return __and_..., + __not_<__and_...>> + >::value; + } + + static constexpr bool __is_implicitly_default_constructible() + { + return __and_... + >::value; + } + + static constexpr bool __is_explicitly_default_constructible() + { + return __and_..., + __not_<__and_< + std::__is_implicitly_default_constructible<_Types>...> + >>::value; + } + }; + + // Partial specialization used when a required precondition isn't met, + // e.g. when sizeof...(_Types) != sizeof...(_UTypes). + template + struct _TupleConstraints + { + template + static constexpr bool __is_implicitly_constructible() + { return false; } + + template + static constexpr bool __is_explicitly_constructible() + { return false; } + }; + + /// Primary class template, tuple + template + class tuple : public _Tuple_impl<0, _Elements...> + { + typedef _Tuple_impl<0, _Elements...> _Inherited; + + template + using _TCC = _TupleConstraints<_Cond, _Elements...>; + + // Constraint for non-explicit default constructor + template + using _ImplicitDefaultCtor = __enable_if_t< + _TCC<_Dummy>::__is_implicitly_default_constructible(), + bool>; + + // Constraint for explicit default constructor + template + using _ExplicitDefaultCtor = __enable_if_t< + _TCC<_Dummy>::__is_explicitly_default_constructible(), + bool>; + + // Constraint for non-explicit constructors + template + using _ImplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_implicitly_constructible<_Args...>(), + bool>; + + // Constraint for non-explicit constructors + template + using _ExplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_explicitly_constructible<_Args...>(), + bool>; + + template + static constexpr + __enable_if_t + __assignable() + { return __and_...>::value; } + + // Condition for noexcept-specifier of an assignment operator. + template + static constexpr bool __nothrow_assignable() + { + return + __and_...>::value; + } + + // Condition for noexcept-specifier of a constructor. + template + static constexpr bool __nothrow_constructible() + { + return + __and_...>::value; + } + + // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) == 1. + template + static constexpr bool __valid_args() + { + return sizeof...(_Elements) == 1 + && !is_same>::value; + } + + // Constraint for tuple(_UTypes&&...) where sizeof...(_UTypes) > 1. + template + static constexpr bool __valid_args() + { return (sizeof...(_Tail) + 2) == sizeof...(_Elements); } + + /* Constraint for constructors with a tuple parameter ensures + * that the constructor is only viable when it would not interfere with + * tuple(UTypes&&...) or tuple(const tuple&) or tuple(tuple&&). + * Such constructors are only viable if: + * either sizeof...(Types) != 1, + * or (when Types... expands to T and UTypes... expands to U) + * is_convertible_v, is_constructible_v, + * and is_same_v are all false. + */ + template> + struct _UseOtherCtor + : false_type + { }; + // If TUPLE is convertible to the single element in *this, + // then TUPLE should match tuple(UTypes&&...) instead. + template + struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Up>> + : __or_, is_constructible<_Tp, _Tuple>> + { }; + // If TUPLE and *this each have a single element of the same type, + // then TUPLE should match a copy/move constructor instead. + template + struct _UseOtherCtor<_Tuple, tuple<_Tp>, tuple<_Tp>> + : true_type + { }; + + // Return true iff sizeof...(Types) == 1 && tuple_size_v == 1 + // and the single element in Types can be initialized from TUPLE, + // or is the same type as tuple_element_t<0, TUPLE>. + template + static constexpr bool __use_other_ctor() + { return _UseOtherCtor<_Tuple>::value; } + + public: + template::value> = true> + constexpr + tuple() + noexcept(__and_...>::value) + : _Inherited() { } + + template::value> = false> + explicit constexpr + tuple() + noexcept(__and_...>::value) + : _Inherited() { } + + template= 1), + _ImplicitCtor<_NotEmpty, const _Elements&...> = true> + constexpr + tuple(const _Elements&... __elements) + noexcept(__nothrow_constructible()) + : _Inherited(__elements...) { } + + template= 1), + _ExplicitCtor<_NotEmpty, const _Elements&...> = false> + explicit constexpr + tuple(const _Elements&... __elements) + noexcept(__nothrow_constructible()) + : _Inherited(__elements...) { } + + template(), + _ImplicitCtor<_Valid, _UElements...> = true> + constexpr + tuple(_UElements&&... __elements) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(std::forward<_UElements>(__elements)...) { } + + template(), + _ExplicitCtor<_Valid, _UElements...> = false> + explicit constexpr + tuple(_UElements&&... __elements) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(std::forward<_UElements>(__elements)...) { } + + constexpr tuple(const tuple&) = default; + + constexpr tuple(tuple&&) = default; + + template&>(), + _ImplicitCtor<_Valid, const _UElements&...> = true> + constexpr + tuple(const tuple<_UElements...>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) + { } + + template&>(), + _ExplicitCtor<_Valid, const _UElements&...> = false> + explicit constexpr + tuple(const tuple<_UElements...>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) + { } + + template&&>(), + _ImplicitCtor<_Valid, _UElements...> = true> + constexpr + tuple(tuple<_UElements...>&& __in) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } + + template&&>(), + _ExplicitCtor<_Valid, _UElements...> = false> + explicit constexpr + tuple(tuple<_UElements...>&& __in) + noexcept(__nothrow_constructible<_UElements...>()) + : _Inherited(static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) { } + + // Allocator-extended constructors. + + template::value> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template= 1), + _ImplicitCtor<_NotEmpty, const _Elements&...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _Elements&... __elements) + : _Inherited(__tag, __a, __elements...) { } + + template= 1), + _ExplicitCtor<_NotEmpty, const _Elements&...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _Elements&... __elements) + : _Inherited(__tag, __a, __elements...) { } + + template(), + _ImplicitCtor<_Valid, _UElements...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + _UElements&&... __elements) + : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) + { } + + template(), + _ExplicitCtor<_Valid, _UElements...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + _UElements&&... __elements) + : _Inherited(__tag, __a, std::forward<_UElements>(__elements)...) + { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template&>(), + _ImplicitCtor<_Valid, const _UElements&...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UElements...>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template&>(), + _ExplicitCtor<_Valid, const _UElements&...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_UElements...>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template&&>(), + _ImplicitCtor<_Valid, _UElements...> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_UElements...>&& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { } + + template&&>(), + _ExplicitCtor<_Valid, _UElements...> = false> + _GLIBCXX20_CONSTEXPR + explicit + tuple(allocator_arg_t __tag, const _Alloc& __a, + tuple<_UElements...>&& __in) + : _Inherited(__tag, __a, + static_cast<_Tuple_impl<0, _UElements...>&&>(__in)) + { } + + // tuple assignment + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(typename conditional<__assignable(), + const tuple&, + const __nonesuch&>::type __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(typename conditional<__assignable<_Elements...>(), + tuple&&, + __nonesuch&&>::type __in) + noexcept(__nothrow_assignable<_Elements...>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const tuple<_UElements...>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_UElements...>(), tuple&> + operator=(tuple<_UElements...>&& __in) + noexcept(__nothrow_assignable<_UElements...>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + // tuple swap + _GLIBCXX20_CONSTEXPR + void + swap(tuple& __in) + noexcept(__and_<__is_nothrow_swappable<_Elements>...>::value) + { _Inherited::_M_swap(__in); } + }; + +#if __cpp_deduction_guides >= 201606 + template + tuple(_UTypes...) -> tuple<_UTypes...>; + template + tuple(pair<_T1, _T2>) -> tuple<_T1, _T2>; + template + tuple(allocator_arg_t, _Alloc, _UTypes...) -> tuple<_UTypes...>; + template + tuple(allocator_arg_t, _Alloc, pair<_T1, _T2>) -> tuple<_T1, _T2>; + template + tuple(allocator_arg_t, _Alloc, tuple<_UTypes...>) -> tuple<_UTypes...>; +#endif + + // Explicit specialization, zero-element tuple. + template<> + class tuple<> + { + public: + void swap(tuple&) noexcept { /* no-op */ } + // We need the default since we're going to define no-op + // allocator constructors. + tuple() = default; + // No-op allocator constructors. + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t, const _Alloc&) noexcept { } + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t, const _Alloc&, const tuple&) noexcept { } + }; + + /// Partial specialization, 2-element tuple. + /// Includes construction and assignment from a pair. + template + class tuple<_T1, _T2> : public _Tuple_impl<0, _T1, _T2> + { + typedef _Tuple_impl<0, _T1, _T2> _Inherited; + + // Constraint for non-explicit default constructor + template + using _ImplicitDefaultCtor = __enable_if_t< + _TupleConstraints<_Dummy, _U1, _U2>:: + __is_implicitly_default_constructible(), + bool>; + + // Constraint for explicit default constructor + template + using _ExplicitDefaultCtor = __enable_if_t< + _TupleConstraints<_Dummy, _U1, _U2>:: + __is_explicitly_default_constructible(), + bool>; + + template + using _TCC = _TupleConstraints<_Dummy, _T1, _T2>; + + // Constraint for non-explicit constructors + template + using _ImplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_implicitly_constructible<_U1, _U2>(), + bool>; + + // Constraint for non-explicit constructors + template + using _ExplicitCtor = __enable_if_t< + _TCC<_Cond>::template __is_explicitly_constructible<_U1, _U2>(), + bool>; + + template + static constexpr bool __assignable() + { + return __and_, + is_assignable<_T2&, _U2>>::value; + } + + template + static constexpr bool __nothrow_assignable() + { + return __and_, + is_nothrow_assignable<_T2&, _U2>>::value; + } + + template + static constexpr bool __nothrow_constructible() + { + return __and_, + is_nothrow_constructible<_T2, _U2>>::value; + } + + static constexpr bool __nothrow_default_constructible() + { + return __and_, + is_nothrow_default_constructible<_T2>>::value; + } + + template + static constexpr bool __is_alloc_arg() + { return is_same<__remove_cvref_t<_U1>, allocator_arg_t>::value; } + + public: + template = true> + constexpr + tuple() + noexcept(__nothrow_default_constructible()) + : _Inherited() { } + + template = false> + explicit constexpr + tuple() + noexcept(__nothrow_default_constructible()) + : _Inherited() { } + + template = true> + constexpr + tuple(const _T1& __a1, const _T2& __a2) + noexcept(__nothrow_constructible()) + : _Inherited(__a1, __a2) { } + + template = false> + explicit constexpr + tuple(const _T1& __a1, const _T2& __a2) + noexcept(__nothrow_constructible()) + : _Inherited(__a1, __a2) { } + + template(), _U1, _U2> = true> + constexpr + tuple(_U1&& __a1, _U2&& __a2) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } + + template(), _U1, _U2> = false> + explicit constexpr + tuple(_U1&& __a1, _U2&& __a2) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__a1), std::forward<_U2>(__a2)) { } + + constexpr tuple(const tuple&) = default; + + constexpr tuple(tuple&&) = default; + + template = true> + constexpr + tuple(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) { } + + template = false> + explicit constexpr + tuple(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(static_cast&>(__in)) { } + + template = true> + constexpr + tuple(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } + + template = false> + explicit constexpr + tuple(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) { } + + template = true> + constexpr + tuple(const pair<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(__in.first, __in.second) { } + + template = false> + explicit constexpr + tuple(const pair<_U1, _U2>& __in) + noexcept(__nothrow_constructible()) + : _Inherited(__in.first, __in.second) { } + + template = true> + constexpr + tuple(pair<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + + template = false> + explicit constexpr + tuple(pair<_U1, _U2>&& __in) + noexcept(__nothrow_constructible<_U1, _U2>()) + : _Inherited(std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + + // Allocator-extended constructors. + + template::value, _T1, _T2> = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a) + : _Inherited(__tag, __a) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _T1& __a1, const _T2& __a2) + : _Inherited(__tag, __a, __a1, __a2) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const _T1& __a1, const _T2& __a2) + : _Inherited(__tag, __a, __a1, __a2) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, _U1&& __a1, _U2&& __a2) + : _Inherited(__tag, __a, std::forward<_U1>(__a1), + std::forward<_U2>(__a2)) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + _U1&& __a1, _U2&& __a2) + : _Inherited(__tag, __a, std::forward<_U1>(__a1), + std::forward<_U2>(__a2)) { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, const tuple& __in) + : _Inherited(__tag, __a, static_cast(__in)) { } + + template + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple&& __in) + : _Inherited(__tag, __a, static_cast<_Inherited&&>(__in)) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_U1, _U2>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const tuple<_U1, _U2>& __in) + : _Inherited(__tag, __a, + static_cast&>(__in)) + { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, tuple<_U1, _U2>&& __in) + : _Inherited(__tag, __a, static_cast<_Tuple_impl<0, _U1, _U2>&&>(__in)) + { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>& __in) + : _Inherited(__tag, __a, __in.first, __in.second) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, + const pair<_U1, _U2>& __in) + : _Inherited(__tag, __a, __in.first, __in.second) { } + + template = true> + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) + : _Inherited(__tag, __a, std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + + template = false> + explicit + _GLIBCXX20_CONSTEXPR + tuple(allocator_arg_t __tag, const _Alloc& __a, pair<_U1, _U2>&& __in) + : _Inherited(__tag, __a, std::forward<_U1>(__in.first), + std::forward<_U2>(__in.second)) { } + + // Tuple assignment. + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(typename conditional<__assignable(), + const tuple&, + const __nonesuch&>::type __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + _GLIBCXX20_CONSTEXPR + tuple& + operator=(typename conditional<__assignable<_T1, _T2>(), + tuple&&, + __nonesuch&&>::type __in) + noexcept(__nothrow_assignable<_T1, _T2>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const tuple<_U1, _U2>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_assign(__in); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_U1, _U2>(), tuple&> + operator=(tuple<_U1, _U2>&& __in) + noexcept(__nothrow_assignable<_U1, _U2>()) + { + this->_M_assign(std::move(__in)); + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable(), tuple&> + operator=(const pair<_U1, _U2>& __in) + noexcept(__nothrow_assignable()) + { + this->_M_head(*this) = __in.first; + this->_M_tail(*this)._M_head(*this) = __in.second; + return *this; + } + + template + _GLIBCXX20_CONSTEXPR + __enable_if_t<__assignable<_U1, _U2>(), tuple&> + operator=(pair<_U1, _U2>&& __in) + noexcept(__nothrow_assignable<_U1, _U2>()) + { + this->_M_head(*this) = std::forward<_U1>(__in.first); + this->_M_tail(*this)._M_head(*this) = std::forward<_U2>(__in.second); + return *this; + } + + _GLIBCXX20_CONSTEXPR + void + swap(tuple& __in) + noexcept(__and_<__is_nothrow_swappable<_T1>, + __is_nothrow_swappable<_T2>>::value) + { _Inherited::_M_swap(__in); } + }; + + + /// class tuple_size + template + struct tuple_size> + : public integral_constant { }; + +#if __cplusplus > 201402L + template + inline constexpr size_t tuple_size_v = tuple_size<_Tp>::value; +#endif + + /** + * Recursive case for tuple_element: strip off the first element in + * the tuple and retrieve the (i-1)th element of the remaining tuple. + */ + template + struct tuple_element<__i, tuple<_Head, _Tail...> > + : tuple_element<__i - 1, tuple<_Tail...> > { }; + + /** + * Basis case for tuple_element: The first element is the one we're seeking. + */ + template + struct tuple_element<0, tuple<_Head, _Tail...> > + { + typedef _Head type; + }; + + /** + * Error case for tuple_element: invalid index. + */ + template + struct tuple_element<__i, tuple<>> + { + static_assert(__i < tuple_size>::value, + "tuple index is in range"); + }; + + template + constexpr _Head& + __get_helper(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + template + constexpr const _Head& + __get_helper(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + /// Return a reference to the ith element of a tuple. + template + constexpr __tuple_element_t<__i, tuple<_Elements...>>& + get(tuple<_Elements...>& __t) noexcept + { return std::__get_helper<__i>(__t); } + + /// Return a const reference to the ith element of a const tuple. + template + constexpr const __tuple_element_t<__i, tuple<_Elements...>>& + get(const tuple<_Elements...>& __t) noexcept + { return std::__get_helper<__i>(__t); } + + /// Return an rvalue reference to the ith element of a tuple rvalue. + template + constexpr __tuple_element_t<__i, tuple<_Elements...>>&& + get(tuple<_Elements...>&& __t) noexcept + { + typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; + return std::forward<__element_type&&>(std::get<__i>(__t)); + } + + /// Return a const rvalue reference to the ith element of a const tuple rvalue. + template + constexpr const __tuple_element_t<__i, tuple<_Elements...>>&& + get(const tuple<_Elements...>&& __t) noexcept + { + typedef __tuple_element_t<__i, tuple<_Elements...>> __element_type; + return std::forward(std::get<__i>(__t)); + } + +#if __cplusplus >= 201402L + +#define __cpp_lib_tuples_by_type 201304 + + template + constexpr _Head& + __get_helper2(_Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + template + constexpr const _Head& + __get_helper2(const _Tuple_impl<__i, _Head, _Tail...>& __t) noexcept + { return _Tuple_impl<__i, _Head, _Tail...>::_M_head(__t); } + + /// Return a reference to the unique element of type _Tp of a tuple. + template + constexpr _Tp& + get(tuple<_Types...>& __t) noexcept + { return std::__get_helper2<_Tp>(__t); } + + /// Return a reference to the unique element of type _Tp of a tuple rvalue. + template + constexpr _Tp&& + get(tuple<_Types...>&& __t) noexcept + { return std::forward<_Tp&&>(std::__get_helper2<_Tp>(__t)); } + + /// Return a const reference to the unique element of type _Tp of a tuple. + template + constexpr const _Tp& + get(const tuple<_Types...>& __t) noexcept + { return std::__get_helper2<_Tp>(__t); } + + /// Return a const reference to the unique element of type _Tp of + /// a const tuple rvalue. + template + constexpr const _Tp&& + get(const tuple<_Types...>&& __t) noexcept + { return std::forward(std::__get_helper2<_Tp>(__t)); } +#endif + + // This class performs the comparison operations on tuples + template + struct __tuple_compare + { + static constexpr bool + __eq(const _Tp& __t, const _Up& __u) + { + return bool(std::get<__i>(__t) == std::get<__i>(__u)) + && __tuple_compare<_Tp, _Up, __i + 1, __size>::__eq(__t, __u); + } + + static constexpr bool + __less(const _Tp& __t, const _Up& __u) + { + return bool(std::get<__i>(__t) < std::get<__i>(__u)) + || (!bool(std::get<__i>(__u) < std::get<__i>(__t)) + && __tuple_compare<_Tp, _Up, __i + 1, __size>::__less(__t, __u)); + } + }; + + template + struct __tuple_compare<_Tp, _Up, __size, __size> + { + static constexpr bool + __eq(const _Tp&, const _Up&) { return true; } + + static constexpr bool + __less(const _Tp&, const _Up&) { return false; } + }; + + template + constexpr bool + operator==(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { + static_assert(sizeof...(_TElements) == sizeof...(_UElements), + "tuple objects can only be compared if they have equal sizes."); + using __compare = __tuple_compare, + tuple<_UElements...>, + 0, sizeof...(_TElements)>; + return __compare::__eq(__t, __u); + } + +#if __cpp_lib_three_way_comparison + template + constexpr _Cat + __tuple_cmp(const _Tp&, const _Up&, index_sequence<>) + { return _Cat::equivalent; } + + template + constexpr _Cat + __tuple_cmp(const _Tp& __t, const _Up& __u, + index_sequence<_Idx0, _Idxs...>) + { + auto __c + = __detail::__synth3way(std::get<_Idx0>(__t), std::get<_Idx0>(__u)); + if (__c != 0) + return __c; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence<_Idxs...>()); + } + + template + constexpr + common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...> + operator<=>(const tuple<_Tps...>& __t, const tuple<_Ups...>& __u) + { + using _Cat + = common_comparison_category_t<__detail::__synth3way_t<_Tps, _Ups>...>; + return std::__tuple_cmp<_Cat>(__t, __u, index_sequence_for<_Tps...>()); + } +#else + template + constexpr bool + operator<(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { + static_assert(sizeof...(_TElements) == sizeof...(_UElements), + "tuple objects can only be compared if they have equal sizes."); + using __compare = __tuple_compare, + tuple<_UElements...>, + 0, sizeof...(_TElements)>; + return __compare::__less(__t, __u); + } + + template + constexpr bool + operator!=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__t == __u); } + + template + constexpr bool + operator>(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return __u < __t; } + + template + constexpr bool + operator<=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__u < __t); } + + template + constexpr bool + operator>=(const tuple<_TElements...>& __t, + const tuple<_UElements...>& __u) + { return !(__t < __u); } +#endif // three_way_comparison + + // NB: DR 705. + template + constexpr tuple::__type...> + make_tuple(_Elements&&... __args) + { + typedef tuple::__type...> + __result_type; + return __result_type(std::forward<_Elements>(__args)...); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2275. Why is forward_as_tuple not constexpr? + /// std::forward_as_tuple + template + constexpr tuple<_Elements&&...> + forward_as_tuple(_Elements&&... __args) noexcept + { return tuple<_Elements&&...>(std::forward<_Elements>(__args)...); } + + template + struct __make_tuple_impl; + + template + struct __make_tuple_impl<_Idx, tuple<_Tp...>, _Tuple, _Nm> + : __make_tuple_impl<_Idx + 1, + tuple<_Tp..., __tuple_element_t<_Idx, _Tuple>>, + _Tuple, _Nm> + { }; + + template + struct __make_tuple_impl<_Nm, tuple<_Tp...>, _Tuple, _Nm> + { + typedef tuple<_Tp...> __type; + }; + + template + struct __do_make_tuple + : __make_tuple_impl<0, tuple<>, _Tuple, std::tuple_size<_Tuple>::value> + { }; + + // Returns the std::tuple equivalent of a tuple-like type. + template + struct __make_tuple + : public __do_make_tuple<__remove_cvref_t<_Tuple>> + { }; + + // Combines several std::tuple's into a single one. + template + struct __combine_tuples; + + template<> + struct __combine_tuples<> + { + typedef tuple<> __type; + }; + + template + struct __combine_tuples> + { + typedef tuple<_Ts...> __type; + }; + + template + struct __combine_tuples, tuple<_T2s...>, _Rem...> + { + typedef typename __combine_tuples, + _Rem...>::__type __type; + }; + + // Computes the result type of tuple_cat given a set of tuple-like types. + template + struct __tuple_cat_result + { + typedef typename __combine_tuples + ::__type...>::__type __type; + }; + + // Helper to determine the index set for the first tuple-like + // type of a given set. + template + struct __make_1st_indices; + + template<> + struct __make_1st_indices<> + { + typedef std::_Index_tuple<> __type; + }; + + template + struct __make_1st_indices<_Tp, _Tpls...> + { + typedef typename std::_Build_index_tuple::type>::value>::__type __type; + }; + + // Performs the actual concatenation by step-wise expanding tuple-like + // objects into the elements, which are finally forwarded into the + // result tuple. + template + struct __tuple_concater; + + template + struct __tuple_concater<_Ret, std::_Index_tuple<_Is...>, _Tp, _Tpls...> + { + template + static constexpr _Ret + _S_do(_Tp&& __tp, _Tpls&&... __tps, _Us&&... __us) + { + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<_Ret, __idx, _Tpls...> __next; + return __next::_S_do(std::forward<_Tpls>(__tps)..., + std::forward<_Us>(__us)..., + std::get<_Is>(std::forward<_Tp>(__tp))...); + } + }; + + template + struct __tuple_concater<_Ret, std::_Index_tuple<>> + { + template + static constexpr _Ret + _S_do(_Us&&... __us) + { + return _Ret(std::forward<_Us>(__us)...); + } + }; + + /// tuple_cat + template...>::value>::type> + constexpr auto + tuple_cat(_Tpls&&... __tpls) + -> typename __tuple_cat_result<_Tpls...>::__type + { + typedef typename __tuple_cat_result<_Tpls...>::__type __ret; + typedef typename __make_1st_indices<_Tpls...>::__type __idx; + typedef __tuple_concater<__ret, __idx, _Tpls...> __concater; + return __concater::_S_do(std::forward<_Tpls>(__tpls)...); + } + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2301. Why is tie not constexpr? + /// tie + template + constexpr tuple<_Elements&...> + tie(_Elements&... __args) noexcept + { return tuple<_Elements&...>(__args...); } + + /// swap + template + _GLIBCXX20_CONSTEXPR + inline +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + // Constrained free swap overload, see p0185r1 + typename enable_if<__and_<__is_swappable<_Elements>...>::value + >::type +#else + void +#endif + swap(tuple<_Elements...>& __x, tuple<_Elements...>& __y) + noexcept(noexcept(__x.swap(__y))) + { __x.swap(__y); } + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 + template + _GLIBCXX20_CONSTEXPR + typename enable_if...>::value>::type + swap(tuple<_Elements...>&, tuple<_Elements...>&) = delete; +#endif + + // A class (and instance) which can be used in 'tie' when an element + // of a tuple is not required. + // _GLIBCXX14_CONSTEXPR + // 2933. PR for LWG 2773 could be clearer + struct _Swallow_assign + { + template + _GLIBCXX14_CONSTEXPR const _Swallow_assign& + operator=(const _Tp&) const + { return *this; } + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2773. Making std::ignore constexpr + _GLIBCXX17_INLINE constexpr _Swallow_assign ignore{}; + + /// Partial specialization for tuples + template + struct uses_allocator, _Alloc> : true_type { }; + + // See stl_pair.h... + /** "piecewise construction" using a tuple of arguments for each member. + * + * @param __first Arguments for the first member of the pair. + * @param __second Arguments for the second member of the pair. + * + * The elements of each tuple will be used as the constructor arguments + * for the data members of the pair. + */ + template + template + _GLIBCXX20_CONSTEXPR + inline + pair<_T1, _T2>:: + pair(piecewise_construct_t, + tuple<_Args1...> __first, tuple<_Args2...> __second) + : pair(__first, __second, + typename _Build_index_tuple::__type(), + typename _Build_index_tuple::__type()) + { } + + template + template + _GLIBCXX20_CONSTEXPR inline + pair<_T1, _T2>:: + pair(tuple<_Args1...>& __tuple1, tuple<_Args2...>& __tuple2, + _Index_tuple<_Indexes1...>, _Index_tuple<_Indexes2...>) + : first(std::forward<_Args1>(std::get<_Indexes1>(__tuple1))...), + second(std::forward<_Args2>(std::get<_Indexes2>(__tuple2))...) + { } + +#if __cplusplus >= 201703L + + // Unpack a std::tuple into a type trait and use its value. + // For cv std::tuple<_Up> the result is _Trait<_Tp, cv _Up...>::value. + // For cv std::tuple<_Up>& the result is _Trait<_Tp, cv _Up&...>::value. + // Otherwise the result is false (because we don't know if std::get throws). + template class _Trait, typename _Tp, typename _Tuple> + inline constexpr bool __unpack_std_tuple = false; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>> + = _Trait<_Tp, _Up...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, tuple<_Up...>&> + = _Trait<_Tp, _Up&...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>> + = _Trait<_Tp, const _Up...>::value; + + template class _Trait, typename _Tp, typename... _Up> + inline constexpr bool __unpack_std_tuple<_Trait, _Tp, const tuple<_Up...>&> + = _Trait<_Tp, const _Up&...>::value; + +# define __cpp_lib_apply 201603 + + template + constexpr decltype(auto) + __apply_impl(_Fn&& __f, _Tuple&& __t, index_sequence<_Idx...>) + { + return std::__invoke(std::forward<_Fn>(__f), + std::get<_Idx>(std::forward<_Tuple>(__t))...); + } + + template + constexpr decltype(auto) + apply(_Fn&& __f, _Tuple&& __t) + noexcept(__unpack_std_tuple) + { + using _Indices + = make_index_sequence>>; + return std::__apply_impl(std::forward<_Fn>(__f), + std::forward<_Tuple>(__t), + _Indices{}); + } + +#define __cpp_lib_make_from_tuple 201606 + + template + constexpr _Tp + __make_from_tuple_impl(_Tuple&& __t, index_sequence<_Idx...>) + { return _Tp(std::get<_Idx>(std::forward<_Tuple>(__t))...); } + + template + constexpr _Tp + make_from_tuple(_Tuple&& __t) + noexcept(__unpack_std_tuple) + { + return __make_from_tuple_impl<_Tp>( + std::forward<_Tuple>(__t), + make_index_sequence>>{}); + } +#endif // C++17 + + /// @} + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++11 + +#endif // _GLIBCXX_TUPLE diff --git a/resources/sources/avr-libstdcpp/include/type_traits b/resources/sources/avr-libstdcpp/include/type_traits index 1f6a99e24..37ef4238d 100644 --- a/resources/sources/avr-libstdcpp/include/type_traits +++ b/resources/sources/avr-libstdcpp/include/type_traits @@ -1,184 +1,3774 @@ -// Minimal for AVR GCC 7.3 (Arduino) -// Provides the subset needed by STruC++ runtime headers. -#ifndef _AVR_TYPE_TRAITS -#define _AVR_TYPE_TRAITS - -namespace std { - -// integral_constant -template struct integral_constant { - static constexpr T value = v; - using value_type = T; - using type = integral_constant; - constexpr operator value_type() const noexcept { return value; } - constexpr value_type operator()() const noexcept { return value; } -}; -using true_type = integral_constant; -using false_type = integral_constant; -template using bool_constant = integral_constant; - -// enable_if -template struct enable_if {}; -template struct enable_if { using type = T; }; -template using enable_if_t = typename enable_if::type; - -// conditional -template struct conditional { using type = T; }; -template struct conditional { using type = F; }; -template using conditional_t = typename conditional::type; - -// is_same -template struct is_same : false_type {}; -template struct is_same : true_type {}; -template inline constexpr bool is_same_v = is_same::value; - -// remove_const / remove_volatile / remove_cv -template struct remove_const { using type = T; }; -template struct remove_const { using type = T; }; -template using remove_const_t = typename remove_const::type; - -template struct remove_volatile { using type = T; }; -template struct remove_volatile { using type = T; }; -template using remove_volatile_t = typename remove_volatile::type; - -template struct remove_cv { - using type = typename remove_volatile::type>::type; -}; -template using remove_cv_t = typename remove_cv::type; - -// remove_reference -template struct remove_reference { using type = T; }; -template struct remove_reference { using type = T; }; -template struct remove_reference { using type = T; }; -template using remove_reference_t = typename remove_reference::type; - -// decay (simplified) -template struct decay { using type = remove_cv_t>; }; -template using decay_t = typename decay::type; - -// is_integral (via explicit specializations -- no __is_integral on GCC 7.3) -template struct _is_integral_impl : false_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template<> struct _is_integral_impl : true_type {}; -template struct is_integral : _is_integral_impl> {}; -template inline constexpr bool is_integral_v = is_integral::value; - -// is_floating_point -template struct _is_fp_impl : false_type {}; -template<> struct _is_fp_impl : true_type {}; -template<> struct _is_fp_impl : true_type {}; -template<> struct _is_fp_impl : true_type {}; -template struct is_floating_point : _is_fp_impl> {}; -template inline constexpr bool is_floating_point_v = is_floating_point::value; - -// is_arithmetic -template struct is_arithmetic : bool_constant || is_floating_point_v> {}; -template inline constexpr bool is_arithmetic_v = is_arithmetic::value; - -// is_signed / is_unsigned -template> struct _is_signed_impl : false_type {}; -template struct _is_signed_impl : bool_constant {}; -template struct is_signed : _is_signed_impl {}; -template inline constexpr bool is_signed_v = is_signed::value; - -template> struct _is_unsigned_impl : false_type {}; -template struct _is_unsigned_impl : bool_constant {}; -template struct is_unsigned : _is_unsigned_impl {}; -template inline constexpr bool is_unsigned_v = is_unsigned::value; - -// is_enum / is_class / is_base_of (GCC builtins available since GCC 4.3) -template struct is_enum : bool_constant<__is_enum(T)> {}; -template inline constexpr bool is_enum_v = is_enum::value; - -template struct is_class : bool_constant<__is_class(T)> {}; -template inline constexpr bool is_class_v = is_class::value; - -template struct is_base_of : bool_constant<__is_base_of(B, D)> {}; -template inline constexpr bool is_base_of_v = is_base_of::value; - -// is_convertible (SFINAE-based) -namespace _detail { - template void _conv_test(T); - template - struct _is_conv : false_type {}; - template - struct _is_conv(static_cast(*(From*)0)), void())> - : true_type {}; -} -template struct is_convertible : _detail::_is_conv {}; -template inline constexpr bool is_convertible_v = is_convertible::value; - -// underlying_type (GCC builtin) -template struct underlying_type { using type = __underlying_type(T); }; -template using underlying_type_t = typename underlying_type::type; - -// is_void -template struct is_void : is_same> {}; -template inline constexpr bool is_void_v = is_void::value; - -// is_pointer (simplified) -template struct is_pointer : false_type {}; -template struct is_pointer : true_type {}; -template struct is_pointer : true_type {}; -template struct is_pointer : true_type {}; -template struct is_pointer : true_type {}; -template inline constexpr bool is_pointer_v = is_pointer::value; - -// make_unsigned / make_signed -template struct make_unsigned; -template<> struct make_unsigned { using type = unsigned char; }; -template<> struct make_unsigned { using type = unsigned char; }; -template<> struct make_unsigned { using type = unsigned char; }; -template<> struct make_unsigned { using type = unsigned short; }; -template<> struct make_unsigned { using type = unsigned short; }; -template<> struct make_unsigned { using type = unsigned int; }; -template<> struct make_unsigned { using type = unsigned int; }; -template<> struct make_unsigned { using type = unsigned long; }; -template<> struct make_unsigned { using type = unsigned long; }; -template<> struct make_unsigned { using type = unsigned long long; }; -template<> struct make_unsigned { using type = unsigned long long; }; -template using make_unsigned_t = typename make_unsigned::type; - -template struct make_signed; -template<> struct make_signed { using type = signed char; }; -template<> struct make_signed { using type = signed char; }; -template<> struct make_signed { using type = signed char; }; -template<> struct make_signed { using type = short; }; -template<> struct make_signed { using type = short; }; -template<> struct make_signed { using type = int; }; -template<> struct make_signed { using type = int; }; -template<> struct make_signed { using type = long; }; -template<> struct make_signed { using type = long; }; -template<> struct make_signed { using type = long long; }; -template<> struct make_signed { using type = long long; }; -template using make_signed_t = typename make_signed::type; - -// declval -template T&& declval() noexcept; - -// common_type (simplified: binary case using ternary operator type deduction) -template struct common_type; -template struct common_type { using type = decay_t; }; -template -struct common_type { - using type = decay_t() : declval())>; -}; -template -struct common_type { - using type = typename common_type::type, Rest...>::type; -}; -template using common_type_t = typename common_type::type; +// C++11 -*- C++ -*- +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/type_traits + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_TYPE_TRAITS +#define _GLIBCXX_TYPE_TRAITS 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup metaprogramming Metaprogramming + * @ingroup utilities + * + * Template utilities for compile-time introspection and modification, + * including type classification traits, type property inspection traits + * and type transformation traits. + * + * @{ + */ + + /// integral_constant + template + struct integral_constant + { + static constexpr _Tp value = __v; + typedef _Tp value_type; + typedef integral_constant<_Tp, __v> type; + constexpr operator value_type() const noexcept { return value; } +#if __cplusplus > 201103L + +#define __cpp_lib_integral_constant_callable 201304 + + constexpr value_type operator()() const noexcept { return value; } +#endif + }; + + template + constexpr _Tp integral_constant<_Tp, __v>::value; + + /// The type used as a compile-time boolean with true value. + typedef integral_constant true_type; + + /// The type used as a compile-time boolean with false value. + typedef integral_constant false_type; + + template + using __bool_constant = integral_constant; + +#if __cplusplus > 201402L +# define __cpp_lib_bool_constant 201505 + template + using bool_constant = integral_constant; +#endif + + // Meta programming helper types. + + template + struct conditional; + + template + struct __type_identity + { using type = _Type; }; + + template + using __type_identity_t = typename __type_identity<_Tp>::type; + + template + struct __or_; + + template<> + struct __or_<> + : public false_type + { }; + + template + struct __or_<_B1> + : public _B1 + { }; + + template + struct __or_<_B1, _B2> + : public conditional<_B1::value, _B1, _B2>::type + { }; + + template + struct __or_<_B1, _B2, _B3, _Bn...> + : public conditional<_B1::value, _B1, __or_<_B2, _B3, _Bn...>>::type + { }; + + template + struct __and_; + + template<> + struct __and_<> + : public true_type + { }; + + template + struct __and_<_B1> + : public _B1 + { }; + + template + struct __and_<_B1, _B2> + : public conditional<_B1::value, _B2, _B1>::type + { }; + + template + struct __and_<_B1, _B2, _B3, _Bn...> + : public conditional<_B1::value, __and_<_B2, _B3, _Bn...>, _B1>::type + { }; + + template + struct __not_ + : public __bool_constant + { }; + +#if __cplusplus >= 201703L + + template + inline constexpr bool __or_v = __or_<_Bn...>::value; + template + inline constexpr bool __and_v = __and_<_Bn...>::value; + +#define __cpp_lib_logical_traits 201510 + + template + struct conjunction + : __and_<_Bn...> + { }; + + template + struct disjunction + : __or_<_Bn...> + { }; + + template + struct negation + : __not_<_Pp> + { }; + + template + inline constexpr bool conjunction_v = conjunction<_Bn...>::value; + + template + inline constexpr bool disjunction_v = disjunction<_Bn...>::value; + + template + inline constexpr bool negation_v = negation<_Pp>::value; + +#endif // C++17 + + // Forward declarations + template + struct is_reference; + template + struct is_function; + template + struct is_void; + template + struct __is_array_unknown_bounds; + + // Helper functions that return false_type for incomplete classes, + // incomplete unions and arrays of known bound from those. + + template + constexpr true_type __is_complete_or_unbounded(__type_identity<_Tp>) + { return {}; } + + template + constexpr typename __or_< + is_reference<_NestedType>, + is_function<_NestedType>, + is_void<_NestedType>, + __is_array_unknown_bounds<_NestedType> + >::type __is_complete_or_unbounded(_TypeIdentity) + { return {}; } + + // For several sfinae-friendly trait implementations we transport both the + // result information (as the member type) and the failure information (no + // member type). This is very similar to std::enable_if, but we cannot use + // them, because we need to derive from them as an implementation detail. + + template + struct __success_type + { typedef _Tp type; }; + + struct __failure_type + { }; + + template + struct remove_cv; + + // __remove_cv_t (std::remove_cv_t for C++11). + template + using __remove_cv_t = typename remove_cv<_Tp>::type; + + template + struct is_const; + + // Primary type categories. + + template + struct __is_void_helper + : public false_type { }; + + template<> + struct __is_void_helper + : public true_type { }; + + /// is_void + template + struct is_void + : public __is_void_helper<__remove_cv_t<_Tp>>::type + { }; + + template + struct __is_integral_helper + : public false_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + +#ifdef _GLIBCXX_USE_WCHAR_T + template<> + struct __is_integral_helper + : public true_type { }; +#endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __is_integral_helper + : public true_type { }; +#endif + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; + + // Conditionalizing on __STRICT_ANSI__ here will break any port that + // uses one of these types for size_t. +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_0> + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_1> + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_2> + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + template<> + struct __is_integral_helper<__GLIBCXX_TYPE_INT_N_3> + : public true_type { }; + + template<> + struct __is_integral_helper + : public true_type { }; +#endif + + /// is_integral + template + struct is_integral + : public __is_integral_helper<__remove_cv_t<_Tp>>::type + { }; + + template + struct __is_floating_point_helper + : public false_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + + template<> + struct __is_floating_point_helper + : public true_type { }; + +#if !defined(__STRICT_ANSI__) && defined(_GLIBCXX_USE_FLOAT128) + template<> + struct __is_floating_point_helper<__float128> + : public true_type { }; +#endif + + /// is_floating_point + template + struct is_floating_point + : public __is_floating_point_helper<__remove_cv_t<_Tp>>::type + { }; + + /// is_array + template + struct is_array + : public false_type { }; + + template + struct is_array<_Tp[_Size]> + : public true_type { }; + + template + struct is_array<_Tp[]> + : public true_type { }; + + template + struct __is_pointer_helper + : public false_type { }; + + template + struct __is_pointer_helper<_Tp*> + : public true_type { }; + + /// is_pointer + template + struct is_pointer + : public __is_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + /// is_lvalue_reference + template + struct is_lvalue_reference + : public false_type { }; + + template + struct is_lvalue_reference<_Tp&> + : public true_type { }; + + /// is_rvalue_reference + template + struct is_rvalue_reference + : public false_type { }; + + template + struct is_rvalue_reference<_Tp&&> + : public true_type { }; + + template + struct __is_member_object_pointer_helper + : public false_type { }; + + template + struct __is_member_object_pointer_helper<_Tp _Cp::*> + : public __not_>::type { }; + + /// is_member_object_pointer + template + struct is_member_object_pointer + : public __is_member_object_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + template + struct __is_member_function_pointer_helper + : public false_type { }; + + template + struct __is_member_function_pointer_helper<_Tp _Cp::*> + : public is_function<_Tp>::type { }; + + /// is_member_function_pointer + template + struct is_member_function_pointer + : public __is_member_function_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + /// is_enum + template + struct is_enum + : public integral_constant + { }; + + /// is_union + template + struct is_union + : public integral_constant + { }; + + /// is_class + template + struct is_class + : public integral_constant + { }; + + /// is_function + template + struct is_function + : public __bool_constant::value> { }; + + template + struct is_function<_Tp&> + : public false_type { }; + + template + struct is_function<_Tp&&> + : public false_type { }; + +#define __cpp_lib_is_null_pointer 201309 + + template + struct __is_null_pointer_helper + : public false_type { }; + + template<> + struct __is_null_pointer_helper + : public true_type { }; + + /// is_null_pointer (LWG 2247). + template + struct is_null_pointer + : public __is_null_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + /// __is_nullptr_t (deprecated extension). + template + struct __is_nullptr_t + : public is_null_pointer<_Tp> + { } _GLIBCXX_DEPRECATED_SUGGEST("std::is_null_pointer"); + + // Composite type categories. + + /// is_reference + template + struct is_reference + : public __or_, + is_rvalue_reference<_Tp>>::type + { }; + + /// is_arithmetic + template + struct is_arithmetic + : public __or_, is_floating_point<_Tp>>::type + { }; + + /// is_fundamental + template + struct is_fundamental + : public __or_, is_void<_Tp>, + is_null_pointer<_Tp>>::type + { }; + + /// is_object + template + struct is_object + : public __not_<__or_, is_reference<_Tp>, + is_void<_Tp>>>::type + { }; + + template + struct is_member_pointer; + + /// is_scalar + template + struct is_scalar + : public __or_, is_enum<_Tp>, is_pointer<_Tp>, + is_member_pointer<_Tp>, is_null_pointer<_Tp>>::type + { }; + + /// is_compound + template + struct is_compound + : public __not_>::type { }; + + template + struct __is_member_pointer_helper + : public false_type { }; + + template + struct __is_member_pointer_helper<_Tp _Cp::*> + : public true_type { }; + + /// is_member_pointer + template + struct is_member_pointer + : public __is_member_pointer_helper<__remove_cv_t<_Tp>>::type + { }; + + template + struct is_same; + + template + using __is_one_of = __or_...>; + + // Check if a type is one of the signed integer types. + template + using __is_signed_integer = __is_one_of<__remove_cv_t<_Tp>, + signed char, signed short, signed int, signed long, + signed long long +#if defined(__GLIBCXX_TYPE_INT_N_0) + , signed __GLIBCXX_TYPE_INT_N_0 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + , signed __GLIBCXX_TYPE_INT_N_1 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + , signed __GLIBCXX_TYPE_INT_N_2 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + , signed __GLIBCXX_TYPE_INT_N_3 +#endif + >; + + // Check if a type is one of the unsigned integer types. + template + using __is_unsigned_integer = __is_one_of<__remove_cv_t<_Tp>, + unsigned char, unsigned short, unsigned int, unsigned long, + unsigned long long +#if defined(__GLIBCXX_TYPE_INT_N_0) + , unsigned __GLIBCXX_TYPE_INT_N_0 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + , unsigned __GLIBCXX_TYPE_INT_N_1 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + , unsigned __GLIBCXX_TYPE_INT_N_2 +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + , unsigned __GLIBCXX_TYPE_INT_N_3 +#endif + >; + + // Check if a type is one of the signed or unsigned integer types. + template + using __is_standard_integer + = __or_<__is_signed_integer<_Tp>, __is_unsigned_integer<_Tp>>; + + // __void_t (std::void_t for C++11) + template using __void_t = void; + + // Utility to detect referenceable types ([defns.referenceable]). + + template + struct __is_referenceable + : public false_type + { }; + + template + struct __is_referenceable<_Tp, __void_t<_Tp&>> + : public true_type + { }; + + // Type properties. + + /// is_const + template + struct is_const + : public false_type { }; + + template + struct is_const<_Tp const> + : public true_type { }; + + /// is_volatile + template + struct is_volatile + : public false_type { }; + + template + struct is_volatile<_Tp volatile> + : public true_type { }; + + /// is_trivial + template + struct is_trivial + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + // is_trivially_copyable + template + struct is_trivially_copyable + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_standard_layout + template + struct is_standard_layout + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_pod (deprecated in C++20) + // Could use is_standard_layout && is_trivial instead of the builtin. + template + struct + _GLIBCXX20_DEPRECATED("use is_standard_layout && is_trivial instead") + is_pod + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_literal_type + template + struct is_literal_type + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_empty + template + struct is_empty + : public integral_constant + { }; + + /// is_polymorphic + template + struct is_polymorphic + : public integral_constant + { }; + +#if __cplusplus >= 201402L +#define __cpp_lib_is_final 201402L + /// is_final + template + struct is_final + : public integral_constant + { }; +#endif + + /// is_abstract + template + struct is_abstract + : public integral_constant + { }; + + template::value> + struct __is_signed_helper + : public false_type { }; + + template + struct __is_signed_helper<_Tp, true> + : public integral_constant + { }; + + /// is_signed + template + struct is_signed + : public __is_signed_helper<_Tp>::type + { }; + + /// is_unsigned + template + struct is_unsigned + : public __and_, __not_>> + { }; + + + // Destructible and constructible type properties. + + /** + * @brief Utility to simplify expressions used in unevaluated operands + * @ingroup utilities + */ + + template + _Up + __declval(int); + + template + _Tp + __declval(long); + + template + auto declval() noexcept -> decltype(__declval<_Tp>(0)); + + template + struct extent; + + template + struct remove_all_extents; + + template + struct __is_array_known_bounds + : public integral_constant::value > 0)> + { }; + + template + struct __is_array_unknown_bounds + : public __and_, __not_>> + { }; + + // In N3290 is_destructible does not say anything about function + // types and abstract types, see LWG 2049. This implementation + // describes function types as non-destructible and all complete + // object types as destructible, iff the explicit destructor + // call expression is wellformed. + struct __do_is_destructible_impl + { + template().~_Tp())> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_destructible_impl + : public __do_is_destructible_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template, + __is_array_unknown_bounds<_Tp>, + is_function<_Tp>>::value, + bool = __or_, is_scalar<_Tp>>::value> + struct __is_destructible_safe; + + template + struct __is_destructible_safe<_Tp, false, false> + : public __is_destructible_impl::type>::type + { }; + + template + struct __is_destructible_safe<_Tp, true, false> + : public false_type { }; + + template + struct __is_destructible_safe<_Tp, false, true> + : public true_type { }; + + /// is_destructible + template + struct is_destructible + : public __is_destructible_safe<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + // is_nothrow_destructible requires that is_destructible is + // satisfied as well. We realize that by mimicing the + // implementation of is_destructible but refer to noexcept(expr) + // instead of decltype(expr). + struct __do_is_nt_destructible_impl + { + template + static __bool_constant().~_Tp())> + __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_nt_destructible_impl + : public __do_is_nt_destructible_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template, + __is_array_unknown_bounds<_Tp>, + is_function<_Tp>>::value, + bool = __or_, is_scalar<_Tp>>::value> + struct __is_nt_destructible_safe; + + template + struct __is_nt_destructible_safe<_Tp, false, false> + : public __is_nt_destructible_impl::type>::type + { }; + + template + struct __is_nt_destructible_safe<_Tp, true, false> + : public false_type { }; + + template + struct __is_nt_destructible_safe<_Tp, false, true> + : public true_type { }; + + /// is_nothrow_destructible + template + struct is_nothrow_destructible + : public __is_nt_destructible_safe<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +#if __GNUC__ >= 8 + template + struct __is_constructible_impl + : public __bool_constant<__is_constructible(_Tp, _Args...)> + { }; +#else + // Implementation of __is_constructible_impl. + + struct __do_is_default_constructible_impl + { + template + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_default_constructible_impl + : public __do_is_default_constructible_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template + struct __is_default_constructible_atom + : public __and_<__not_>, + __is_default_constructible_impl<_Tp>>::type + { }; + + template::value> + struct __is_default_constructible_safe; + + // The following technique is a workaround for a current core language + // restriction, which does not allow for array types to occur in + // functional casts of the form T(). Complete arrays can be default- + // constructed, if the element type is default-constructible, but + // arrays with unknown bounds are not. + template + struct __is_default_constructible_safe<_Tp, true> + : public __and_<__is_array_known_bounds<_Tp>, + __is_default_constructible_atom::type>>::type + { }; + + template + struct __is_default_constructible_safe<_Tp, false> + : public __is_default_constructible_atom<_Tp>::type + { }; + + // The hardest part of this trait is the binary direct-initialization + // case, because we hit into a functional cast of the form T(arg). + // This implementation uses different strategies depending on the + // target type to reduce the test overhead as much as possible: + // + // a) For a reference target type, we use a static_cast expression + // modulo its extra cases. + // + // b) For a non-reference target type we use a ::new expression. + struct __do_is_static_castable_impl + { + template(declval<_From>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_static_castable_impl + : public __do_is_static_castable_impl + { + typedef decltype(__test<_From, _To>(0)) type; + }; + + template + struct __is_static_castable_safe + : public __is_static_castable_impl<_From, _To>::type + { }; + + // __is_static_castable + template + struct __is_static_castable + : public integral_constant::value)> + { }; + + // Implementation for non-reference types. To meet the proper + // variable definition semantics, we also need to test for + // is_destructible in this case. + // This form should be simplified by a single expression: + // ::delete ::new _Tp(declval<_Arg>()), see c++/51222. + struct __do_is_direct_constructible_impl + { + template()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_direct_constructible_impl + : public __do_is_direct_constructible_impl + { + typedef decltype(__test<_Tp, _Arg>(0)) type; + }; + + template + struct __is_direct_constructible_new_safe + : public __and_, + __is_direct_constructible_impl<_Tp, _Arg>> + { }; + + template + struct is_same; + + template + struct is_base_of; + + template + struct remove_reference; + + template, + is_function<_From>>>::value> + struct __is_base_to_derived_ref; + + template + struct is_constructible; + + // Detect whether we have a downcast situation during + // reference binding. + template + struct __is_base_to_derived_ref<_From, _To, true> + { + typedef typename remove_cv::type>::type __src_t; + typedef typename remove_cv::type>::type __dst_t; + typedef __and_<__not_>, + is_base_of<__src_t, __dst_t>, + __not_>> type; + static constexpr bool value = type::value; + }; + + template + struct __is_base_to_derived_ref<_From, _To, false> + : public false_type + { }; + + template, + is_rvalue_reference<_To>>::value> + struct __is_lvalue_to_rvalue_ref; + + // Detect whether we have an lvalue of non-function type + // bound to a reference-compatible rvalue-reference. + template + struct __is_lvalue_to_rvalue_ref<_From, _To, true> + { + typedef typename remove_cv::type>::type __src_t; + typedef typename remove_cv::type>::type __dst_t; + typedef __and_<__not_>, + __or_, + is_base_of<__dst_t, __src_t>>> type; + static constexpr bool value = type::value; + }; + + template + struct __is_lvalue_to_rvalue_ref<_From, _To, false> + : public false_type + { }; + + // Here we handle direct-initialization to a reference type as + // equivalent to a static_cast modulo overshooting conversions. + // These are restricted to the following conversions: + // a) A base class value to a derived class reference + // b) An lvalue to an rvalue-reference of reference-compatible + // types that are not functions + template + struct __is_direct_constructible_ref_cast + : public __and_<__is_static_castable<_Arg, _Tp>, + __not_<__or_<__is_base_to_derived_ref<_Arg, _Tp>, + __is_lvalue_to_rvalue_ref<_Arg, _Tp> + >>> + { }; + + template + struct __is_direct_constructible_new + : public conditional::value, + __is_direct_constructible_ref_cast<_Tp, _Arg>, + __is_direct_constructible_new_safe<_Tp, _Arg> + >::type + { }; + + template + struct __is_direct_constructible + : public __is_direct_constructible_new<_Tp, _Arg>::type + { }; + + // Since default-construction and binary direct-initialization have + // been handled separately, the implementation of the remaining + // n-ary construction cases is rather straightforward. We can use + // here a functional cast, because array types are excluded anyway + // and this form is never interpreted as a C cast. + struct __do_is_nary_constructible_impl + { + template()...))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + template + struct __is_nary_constructible_impl + : public __do_is_nary_constructible_impl + { + typedef decltype(__test<_Tp, _Args...>(0)) type; + }; + + template + struct __is_nary_constructible + : public __is_nary_constructible_impl<_Tp, _Args...>::type + { + static_assert(sizeof...(_Args) > 1, + "Only useful for > 1 arguments"); + }; + + template + struct __is_constructible_impl + : public __is_nary_constructible<_Tp, _Args...> + { }; + + template + struct __is_constructible_impl<_Tp, _Arg> + : public __is_direct_constructible<_Tp, _Arg> + { }; + + template + struct __is_constructible_impl<_Tp> + : public __is_default_constructible_safe<_Tp>::type + { }; +#endif + + /// is_constructible + template + struct is_constructible + : public __is_constructible_impl<_Tp, _Args...> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_default_constructible + template + struct is_default_constructible + : public __is_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_copy_constructible_impl; + + template + struct __is_copy_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_copy_constructible_impl<_Tp, true> + : public __is_constructible_impl<_Tp, const _Tp&> + { }; + + /// is_copy_constructible + template + struct is_copy_constructible + : public __is_copy_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_move_constructible_impl; + + template + struct __is_move_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_move_constructible_impl<_Tp, true> + : public __is_constructible_impl<_Tp, _Tp&&> + { }; + + /// is_move_constructible + template + struct is_move_constructible + : public __is_move_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template + struct __is_nt_constructible_impl + : public false_type + { }; + + template + struct __is_nt_constructible_impl + : public __bool_constant()...))> + { }; + + template + struct __is_nt_constructible_impl + : public __bool_constant(std::declval<_Arg>()))> + { }; + + template + struct __is_nt_constructible_impl + : public __bool_constant + { }; + + template + struct __is_nt_constructible_impl + : public __bool_constant::type())> + { }; + +#if __cpp_aggregate_paren_init + template + struct __is_nt_constructible_impl + : public __is_nt_constructible_impl + { }; + + template + struct __is_nt_constructible_impl + : public __and_<__is_nt_constructible_impl...> + { }; +#endif + +#if __GNUC__ >= 8 + template + using __is_nothrow_constructible_impl + = __is_nt_constructible_impl<__is_constructible(_Tp, _Args...), + _Tp, _Args...>; +#else + template + using __is_nothrow_constructible_impl + = __is_nt_constructible_impl<__is_constructible_impl<_Tp, _Args...>::value, + _Tp, _Args...>; +#endif + + /// is_nothrow_constructible + template + struct is_nothrow_constructible + : public __is_nothrow_constructible_impl<_Tp, _Args...>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_default_constructible + template + struct is_nothrow_default_constructible + : public __is_nothrow_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + + template::value> + struct __is_nothrow_copy_constructible_impl; + + template + struct __is_nothrow_copy_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_nothrow_copy_constructible_impl<_Tp, true> + : public __is_nothrow_constructible_impl<_Tp, const _Tp&> + { }; + + /// is_nothrow_copy_constructible + template + struct is_nothrow_copy_constructible + : public __is_nothrow_copy_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_nothrow_move_constructible_impl; + + template + struct __is_nothrow_move_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_nothrow_move_constructible_impl<_Tp, true> + : public __is_nothrow_constructible_impl<_Tp, _Tp&&> + { }; + + /// is_nothrow_move_constructible + template + struct is_nothrow_move_constructible + : public __is_nothrow_move_constructible_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +#if __GNUC__ >= 8 + /// is_assignable + template + struct is_assignable + : public __bool_constant<__is_assignable(_Tp, _Up)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; +#else + template + class __is_assignable_helper + { + template() = declval<_Up1>())> + static true_type + __test(int); + + template + static false_type + __test(...); + + public: + typedef decltype(__test<_Tp, _Up>(0)) type; + }; + + /// is_assignable + template + struct is_assignable + : public __is_assignable_helper<_Tp, _Up>::type + { }; +#endif + + template::value> + struct __is_copy_assignable_impl; + + template + struct __is_copy_assignable_impl<_Tp, false> + : public false_type { }; + +#if __GNUC__ >= 8 + template + struct __is_copy_assignable_impl<_Tp, true> + : public __bool_constant<__is_assignable(_Tp&, const _Tp&)> + { }; +#else + template + struct __is_copy_assignable_impl<_Tp, true> + : public is_assignable<_Tp&, const _Tp&> + { }; +#endif + + /// is_copy_assignable + template + struct is_copy_assignable + : public __is_copy_assignable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_move_assignable_impl; + + template + struct __is_move_assignable_impl<_Tp, false> + : public false_type { }; + +#if __GNUC__ >= 8 + template + struct __is_move_assignable_impl<_Tp, true> + : public __bool_constant<__is_assignable(_Tp&, _Tp&&)> + { }; +#else + template + struct __is_move_assignable_impl<_Tp, true> + : public is_assignable<_Tp&, _Tp&&> + { }; +#endif + + /// is_move_assignable + template + struct is_move_assignable + : public __is_move_assignable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template + struct __is_nt_assignable_impl + : public integral_constant() = declval<_Up>())> + { }; + +#if __GNUC__ >= 8 + template + struct __is_nothrow_assignable_impl + : public __and_<__bool_constant<__is_assignable(_Tp, _Up)>, + __is_nt_assignable_impl<_Tp, _Up>> + { }; +#else + template + struct __is_nothrow_assignable_impl + : public __and_, + __is_nt_assignable_impl<_Tp, _Up>> + { }; +#endif + + /// is_nothrow_assignable + template + struct is_nothrow_assignable + : public __is_nothrow_assignable_impl<_Tp, _Up> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_nt_copy_assignable_impl; + + template + struct __is_nt_copy_assignable_impl<_Tp, false> + : public false_type { }; + + template + struct __is_nt_copy_assignable_impl<_Tp, true> + : public __is_nothrow_assignable_impl<_Tp&, const _Tp&> + { }; + + /// is_nothrow_copy_assignable + template + struct is_nothrow_copy_assignable + : public __is_nt_copy_assignable_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_nt_move_assignable_impl; + + template + struct __is_nt_move_assignable_impl<_Tp, false> + : public false_type { }; + + template + struct __is_nt_move_assignable_impl<_Tp, true> + : public __is_nothrow_assignable_impl<_Tp&, _Tp&&> + { }; + + /// is_nothrow_move_assignable + template + struct is_nothrow_move_assignable + : public __is_nt_move_assignable_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_constructible + template + struct is_trivially_constructible + : public __bool_constant<__is_trivially_constructible(_Tp, _Args...)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_default_constructible + template + struct is_trivially_default_constructible + : public __bool_constant<__is_trivially_constructible(_Tp)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + struct __do_is_implicitly_default_constructible_impl + { + template + static void __helper(const _Tp&); + + template + static true_type __test(const _Tp&, + decltype(__helper({}))* = 0); + + static false_type __test(...); + }; + + template + struct __is_implicitly_default_constructible_impl + : public __do_is_implicitly_default_constructible_impl + { + typedef decltype(__test(declval<_Tp>())) type; + }; + + template + struct __is_implicitly_default_constructible_safe + : public __is_implicitly_default_constructible_impl<_Tp>::type + { }; + + template + struct __is_implicitly_default_constructible + : public __and_<__is_constructible_impl<_Tp>, + __is_implicitly_default_constructible_safe<_Tp>> + { }; + + template::value> + struct __is_trivially_copy_constructible_impl; + + template + struct __is_trivially_copy_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_trivially_copy_constructible_impl<_Tp, true> + : public __and_<__is_copy_constructible_impl<_Tp>, + integral_constant> + { }; + + /// is_trivially_copy_constructible + template + struct is_trivially_copy_constructible + : public __is_trivially_copy_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_trivially_move_constructible_impl; + + template + struct __is_trivially_move_constructible_impl<_Tp, false> + : public false_type { }; + + template + struct __is_trivially_move_constructible_impl<_Tp, true> + : public __and_<__is_move_constructible_impl<_Tp>, + integral_constant> + { }; + + /// is_trivially_move_constructible + template + struct is_trivially_move_constructible + : public __is_trivially_move_constructible_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_assignable + template + struct is_trivially_assignable + : public __bool_constant<__is_trivially_assignable(_Tp, _Up)> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_trivially_copy_assignable_impl; + + template + struct __is_trivially_copy_assignable_impl<_Tp, false> + : public false_type { }; + + template + struct __is_trivially_copy_assignable_impl<_Tp, true> + : public __bool_constant<__is_trivially_assignable(_Tp&, const _Tp&)> + { }; + + /// is_trivially_copy_assignable + template + struct is_trivially_copy_assignable + : public __is_trivially_copy_assignable_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template::value> + struct __is_trivially_move_assignable_impl; + + template + struct __is_trivially_move_assignable_impl<_Tp, false> + : public false_type { }; + + template + struct __is_trivially_move_assignable_impl<_Tp, true> + : public __bool_constant<__is_trivially_assignable(_Tp&, _Tp&&)> + { }; + + /// is_trivially_move_assignable + template + struct is_trivially_move_assignable + : public __is_trivially_move_assignable_impl<_Tp> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_trivially_destructible + template + struct is_trivially_destructible + : public __and_<__is_destructible_safe<_Tp>, + __bool_constant<__has_trivial_destructor(_Tp)>> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + + /// has_virtual_destructor + template + struct has_virtual_destructor + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + + // type property queries. + + /// alignment_of + template + struct alignment_of + : public integral_constant + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// rank + template + struct rank + : public integral_constant { }; + + template + struct rank<_Tp[_Size]> + : public integral_constant::value> { }; + + template + struct rank<_Tp[]> + : public integral_constant::value> { }; + + /// extent + template + struct extent + : public integral_constant { }; + + template + struct extent<_Tp[_Size], _Uint> + : public integral_constant::value> + { }; + + template + struct extent<_Tp[], _Uint> + : public integral_constant::value> + { }; + + + // Type relations. + + /// is_same + template + struct is_same +#ifdef _GLIBCXX_BUILTIN_IS_SAME_AS + : public integral_constant +#else + : public false_type +#endif + { }; + +#ifndef _GLIBCXX_BUILTIN_IS_SAME_AS + template + struct is_same<_Tp, _Tp> + : public true_type + { }; +#endif + + /// is_base_of + template + struct is_base_of + : public integral_constant + { }; + + template, is_function<_To>, + is_array<_To>>::value> + struct __is_convertible_helper + { + typedef typename is_void<_To>::type type; + }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + template + class __is_convertible_helper<_From, _To, false> + { + template + static void __test_aux(_To1) noexcept; + + template(std::declval<_From1>()))> + static true_type + __test(int); + + template + static false_type + __test(...); + + public: + typedef decltype(__test<_From, _To>(0)) type; + }; +#pragma GCC diagnostic pop + + /// is_convertible + template + struct is_convertible + : public __is_convertible_helper<_From, _To>::type + { }; + + // helper trait for unique_ptr, shared_ptr, and span + template + using __is_array_convertible + = is_convertible<_FromElementType(*)[], _ToElementType(*)[]>; + +#if __cplusplus >= 202002L +#define __cpp_lib_is_nothrow_convertible 201806L + +#if __has_builtin(__is_nothrow_convertible) + /// is_nothrow_convertible_v + template + inline constexpr bool is_nothrow_convertible_v + = __is_nothrow_convertible(_From, _To); + + /// is_nothrow_convertible + template + struct is_nothrow_convertible + : public bool_constant> + { }; +#else + template, is_function<_To>, + is_array<_To>>::value> + struct __is_nt_convertible_helper + : is_void<_To> + { }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + template + class __is_nt_convertible_helper<_From, _To, false> + { + template + static void __test_aux(_To1) noexcept; + + template + static + __bool_constant(std::declval<_From1>()))> + __test(int); + + template + static false_type + __test(...); + + public: + using type = decltype(__test<_From, _To>(0)); + }; +#pragma GCC diagnostic pop + + /// is_nothrow_convertible + template + struct is_nothrow_convertible + : public __is_nt_convertible_helper<_From, _To>::type + { }; + + /// is_nothrow_convertible_v + template + inline constexpr bool is_nothrow_convertible_v + = is_nothrow_convertible<_From, _To>::value; +#endif +#endif // C++2a + + // Const-volatile modifications. + + /// remove_const + template + struct remove_const + { typedef _Tp type; }; + + template + struct remove_const<_Tp const> + { typedef _Tp type; }; + + /// remove_volatile + template + struct remove_volatile + { typedef _Tp type; }; + + template + struct remove_volatile<_Tp volatile> + { typedef _Tp type; }; + + /// remove_cv + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; + + template + struct remove_cv + { using type = _Tp; }; + + /// add_const + template + struct add_const + { typedef _Tp const type; }; + + /// add_volatile + template + struct add_volatile + { typedef _Tp volatile type; }; + + /// add_cv + template + struct add_cv + { + typedef typename + add_const::type>::type type; + }; + +#if __cplusplus > 201103L + +#define __cpp_lib_transformation_trait_aliases 201304 + + /// Alias template for remove_const + template + using remove_const_t = typename remove_const<_Tp>::type; + + /// Alias template for remove_volatile + template + using remove_volatile_t = typename remove_volatile<_Tp>::type; + + /// Alias template for remove_cv + template + using remove_cv_t = typename remove_cv<_Tp>::type; + + /// Alias template for add_const + template + using add_const_t = typename add_const<_Tp>::type; + + /// Alias template for add_volatile + template + using add_volatile_t = typename add_volatile<_Tp>::type; + + /// Alias template for add_cv + template + using add_cv_t = typename add_cv<_Tp>::type; +#endif + + // Reference transformations. + + /// remove_reference + template + struct remove_reference + { typedef _Tp type; }; + + template + struct remove_reference<_Tp&> + { typedef _Tp type; }; + + template + struct remove_reference<_Tp&&> + { typedef _Tp type; }; + + template::value> + struct __add_lvalue_reference_helper + { typedef _Tp type; }; + + template + struct __add_lvalue_reference_helper<_Tp, true> + { typedef _Tp& type; }; + + /// add_lvalue_reference + template + struct add_lvalue_reference + : public __add_lvalue_reference_helper<_Tp> + { }; + + template::value> + struct __add_rvalue_reference_helper + { typedef _Tp type; }; + + template + struct __add_rvalue_reference_helper<_Tp, true> + { typedef _Tp&& type; }; + + /// add_rvalue_reference + template + struct add_rvalue_reference + : public __add_rvalue_reference_helper<_Tp> + { }; + +#if __cplusplus > 201103L + /// Alias template for remove_reference + template + using remove_reference_t = typename remove_reference<_Tp>::type; + + /// Alias template for add_lvalue_reference + template + using add_lvalue_reference_t = typename add_lvalue_reference<_Tp>::type; + + /// Alias template for add_rvalue_reference + template + using add_rvalue_reference_t = typename add_rvalue_reference<_Tp>::type; +#endif + + // Sign modifications. + + // Utility for constructing identically cv-qualified types. + template + struct __cv_selector; + + template + struct __cv_selector<_Unqualified, false, false> + { typedef _Unqualified __type; }; + + template + struct __cv_selector<_Unqualified, false, true> + { typedef volatile _Unqualified __type; }; + + template + struct __cv_selector<_Unqualified, true, false> + { typedef const _Unqualified __type; }; + + template + struct __cv_selector<_Unqualified, true, true> + { typedef const volatile _Unqualified __type; }; + + template::value, + bool _IsVol = is_volatile<_Qualified>::value> + class __match_cv_qualifiers + { + typedef __cv_selector<_Unqualified, _IsConst, _IsVol> __match; + + public: + typedef typename __match::__type __type; + }; + + // Utility for finding the unsigned versions of signed integral types. + template + struct __make_unsigned + { typedef _Tp __type; }; + + template<> + struct __make_unsigned + { typedef unsigned char __type; }; + + template<> + struct __make_unsigned + { typedef unsigned char __type; }; + + template<> + struct __make_unsigned + { typedef unsigned short __type; }; + + template<> + struct __make_unsigned + { typedef unsigned int __type; }; + + template<> + struct __make_unsigned + { typedef unsigned long __type; }; + + template<> + struct __make_unsigned + { typedef unsigned long long __type; }; + +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_0> + { typedef unsigned __GLIBCXX_TYPE_INT_N_0 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_1> + { typedef unsigned __GLIBCXX_TYPE_INT_N_1 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_2> + { typedef unsigned __GLIBCXX_TYPE_INT_N_2 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + template<> + struct __make_unsigned<__GLIBCXX_TYPE_INT_N_3> + { typedef unsigned __GLIBCXX_TYPE_INT_N_3 __type; }; +#endif + + // Select between integral and enum: not possible to be both. + template::value, + bool _IsEnum = is_enum<_Tp>::value> + class __make_unsigned_selector; + + template + class __make_unsigned_selector<_Tp, true, false> + { + using __unsigned_type + = typename __make_unsigned<__remove_cv_t<_Tp>>::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; + }; + + class __make_unsigned_selector_base + { + protected: + template struct _List { }; + + template + struct _List<_Tp, _Up...> : _List<_Up...> + { static constexpr size_t __size = sizeof(_Tp); }; + + template + struct __select; + + template + struct __select<_Sz, _List<_Uint, _UInts...>, true> + { using __type = _Uint; }; + + template + struct __select<_Sz, _List<_Uint, _UInts...>, false> + : __select<_Sz, _List<_UInts...>> + { }; + }; + + // Choose unsigned integer type with the smallest rank and same size as _Tp + template + class __make_unsigned_selector<_Tp, false, true> + : __make_unsigned_selector_base + { + // With -fshort-enums, an enum may be as small as a char. + using _UInts = _List; + + using __unsigned_type = typename __select::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __unsigned_type>::__type; + }; + + // wchar_t, char8_t, char16_t and char32_t are integral types but are + // neither signed integer types nor unsigned integer types, so must be + // transformed to the unsigned integer type with the smallest rank. + // Use the partial specialization for enumeration types to do that. +#if defined(_GLIBCXX_USE_WCHAR_T) + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; +#endif + +#ifdef _GLIBCXX_USE_CHAR8_T + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; +#endif + + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; + + template<> + struct __make_unsigned + { + using __type + = typename __make_unsigned_selector::__type; + }; + + // Given an integral/enum type, return the corresponding unsigned + // integer type. + // Primary template. + /// make_unsigned + template + struct make_unsigned + { typedef typename __make_unsigned_selector<_Tp>::__type type; }; + + // Integral, but don't define. + template<> + struct make_unsigned; + + + // Utility for finding the signed versions of unsigned integral types. + template + struct __make_signed + { typedef _Tp __type; }; + + template<> + struct __make_signed + { typedef signed char __type; }; + + template<> + struct __make_signed + { typedef signed char __type; }; + + template<> + struct __make_signed + { typedef signed short __type; }; + + template<> + struct __make_signed + { typedef signed int __type; }; + + template<> + struct __make_signed + { typedef signed long __type; }; + + template<> + struct __make_signed + { typedef signed long long __type; }; + +#if defined(__GLIBCXX_TYPE_INT_N_0) + template<> + struct __make_signed + { typedef __GLIBCXX_TYPE_INT_N_0 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_1) + template<> + struct __make_signed + { typedef __GLIBCXX_TYPE_INT_N_1 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_2) + template<> + struct __make_signed + { typedef __GLIBCXX_TYPE_INT_N_2 __type; }; +#endif +#if defined(__GLIBCXX_TYPE_INT_N_3) + template<> + struct __make_signed + { typedef __GLIBCXX_TYPE_INT_N_3 __type; }; +#endif + + // Select between integral and enum: not possible to be both. + template::value, + bool _IsEnum = is_enum<_Tp>::value> + class __make_signed_selector; + + template + class __make_signed_selector<_Tp, true, false> + { + using __signed_type + = typename __make_signed<__remove_cv_t<_Tp>>::__type; + + public: + using __type + = typename __match_cv_qualifiers<_Tp, __signed_type>::__type; + }; + + // Choose signed integer type with the smallest rank and same size as _Tp + template + class __make_signed_selector<_Tp, false, true> + { + typedef typename __make_unsigned_selector<_Tp>::__type __unsigned_type; + + public: + typedef typename __make_signed_selector<__unsigned_type>::__type __type; + }; + + // wchar_t, char16_t and char32_t are integral types but are neither + // signed integer types nor unsigned integer types, so must be + // transformed to the signed integer type with the smallest rank. + // Use the partial specialization for enumeration types to do that. +#if defined(_GLIBCXX_USE_WCHAR_T) + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; +#endif + +#if defined(_GLIBCXX_USE_CHAR8_T) + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; +#endif + + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + + template<> + struct __make_signed + { + using __type + = typename __make_signed_selector::__type; + }; + + // Given an integral/enum type, return the corresponding signed + // integer type. + // Primary template. + /// make_signed + template + struct make_signed + { typedef typename __make_signed_selector<_Tp>::__type type; }; + + // Integral, but don't define. + template<> + struct make_signed; + +#if __cplusplus > 201103L + /// Alias template for make_signed + template + using make_signed_t = typename make_signed<_Tp>::type; + + /// Alias template for make_unsigned + template + using make_unsigned_t = typename make_unsigned<_Tp>::type; +#endif + + // Array modifications. + + /// remove_extent + template + struct remove_extent + { typedef _Tp type; }; + + template + struct remove_extent<_Tp[_Size]> + { typedef _Tp type; }; + + template + struct remove_extent<_Tp[]> + { typedef _Tp type; }; + + /// remove_all_extents + template + struct remove_all_extents + { typedef _Tp type; }; + + template + struct remove_all_extents<_Tp[_Size]> + { typedef typename remove_all_extents<_Tp>::type type; }; + + template + struct remove_all_extents<_Tp[]> + { typedef typename remove_all_extents<_Tp>::type type; }; + +#if __cplusplus > 201103L + /// Alias template for remove_extent + template + using remove_extent_t = typename remove_extent<_Tp>::type; + + /// Alias template for remove_all_extents + template + using remove_all_extents_t = typename remove_all_extents<_Tp>::type; +#endif + + // Pointer modifications. + + template + struct __remove_pointer_helper + { typedef _Tp type; }; + + template + struct __remove_pointer_helper<_Tp, _Up*> + { typedef _Up type; }; + + /// remove_pointer + template + struct remove_pointer + : public __remove_pointer_helper<_Tp, __remove_cv_t<_Tp>> + { }; + + /// add_pointer + template, + is_void<_Tp>>::value> + struct __add_pointer_helper + { typedef _Tp type; }; + + template + struct __add_pointer_helper<_Tp, true> + { typedef typename remove_reference<_Tp>::type* type; }; + + template + struct add_pointer + : public __add_pointer_helper<_Tp> + { }; + +#if __cplusplus > 201103L + /// Alias template for remove_pointer + template + using remove_pointer_t = typename remove_pointer<_Tp>::type; + + /// Alias template for add_pointer + template + using add_pointer_t = typename add_pointer<_Tp>::type; +#endif + + template + struct __aligned_storage_msa + { + union __type + { + unsigned char __data[_Len]; + struct __attribute__((__aligned__)) { } __align; + }; + }; + + /** + * @brief Alignment type. + * + * The value of _Align is a default-alignment which shall be the + * most stringent alignment requirement for any C++ object type + * whose size is no greater than _Len (3.9). The member typedef + * type shall be a POD type suitable for use as uninitialized + * storage for any object whose size is at most _Len and whose + * alignment is a divisor of _Align. + */ + template::__type)> + struct aligned_storage + { + union type + { + unsigned char __data[_Len]; + struct __attribute__((__aligned__((_Align)))) { } __align; + }; + }; + + template + struct __strictest_alignment + { + static const size_t _S_alignment = 0; + static const size_t _S_size = 0; + }; + + template + struct __strictest_alignment<_Tp, _Types...> + { + static const size_t _S_alignment = + alignof(_Tp) > __strictest_alignment<_Types...>::_S_alignment + ? alignof(_Tp) : __strictest_alignment<_Types...>::_S_alignment; + static const size_t _S_size = + sizeof(_Tp) > __strictest_alignment<_Types...>::_S_size + ? sizeof(_Tp) : __strictest_alignment<_Types...>::_S_size; + }; + + /** + * @brief Provide aligned storage for types. + * + * [meta.trans.other] + * + * Provides aligned storage for any of the provided types of at + * least size _Len. + * + * @see aligned_storage + */ + template + struct aligned_union + { + private: + static_assert(sizeof...(_Types) != 0, "At least one type is required"); + + using __strictest = __strictest_alignment<_Types...>; + static const size_t _S_len = _Len > __strictest::_S_size + ? _Len : __strictest::_S_size; + public: + /// The value of the strictest alignment of _Types. + static const size_t alignment_value = __strictest::_S_alignment; + /// The storage. + typedef typename aligned_storage<_S_len, alignment_value>::type type; + }; + + template + const size_t aligned_union<_Len, _Types...>::alignment_value; + + // Decay trait for arrays and functions, used for perfect forwarding + // in make_pair, make_tuple, etc. + template::value, + bool _IsFunction = is_function<_Up>::value> + struct __decay_selector; + + // NB: DR 705. + template + struct __decay_selector<_Up, false, false> + { typedef __remove_cv_t<_Up> __type; }; + + template + struct __decay_selector<_Up, true, false> + { typedef typename remove_extent<_Up>::type* __type; }; + + template + struct __decay_selector<_Up, false, true> + { typedef typename add_pointer<_Up>::type __type; }; + + /// decay + template + class decay + { + typedef typename remove_reference<_Tp>::type __remove_type; + + public: + typedef typename __decay_selector<__remove_type>::__type type; + }; + + // __decay_t (std::decay_t for C++11). + template + using __decay_t = typename decay<_Tp>::type; + + template + class reference_wrapper; + + // Helper which adds a reference to a type when given a reference_wrapper + template + struct __strip_reference_wrapper + { + typedef _Tp __type; + }; + + template + struct __strip_reference_wrapper > + { + typedef _Tp& __type; + }; + + template + using __decay_and_strip = __strip_reference_wrapper<__decay_t<_Tp>>; + + + // Primary template. + /// Define a member typedef @c type only if a boolean constant is true. + template + struct enable_if + { }; + + // Partial specialization for true. + template + struct enable_if + { typedef _Tp type; }; + + // __enable_if_t (std::enable_if_t for C++11) + template + using __enable_if_t = typename enable_if<_Cond, _Tp>::type; + + template + using _Require = __enable_if_t<__and_<_Cond...>::value>; + + // Primary template. + /// Define a member typedef @c type to one of two argument types. + template + struct conditional + { typedef _Iftrue type; }; + + // Partial specialization for false. + template + struct conditional + { typedef _Iffalse type; }; + + // __remove_cvref_t (std::remove_cvref_t for C++11). + template + using __remove_cvref_t + = typename remove_cv::type>::type; + + /// common_type + template + struct common_type; + + // Sfinae-friendly common_type implementation: + + struct __do_common_type_impl + { + template + using __cond_t + = decltype(true ? std::declval<_Tp>() : std::declval<_Up>()); + + // if decay_t() : declval())> + // denotes a valid type, let C denote that type. + template + static __success_type<__decay_t<__cond_t<_Tp, _Up>>> + _S_test(int); + +#if __cplusplus > 201703L + // Otherwise, if COND-RES(CREF(D1), CREF(D2)) denotes a type, + // let C denote the type decay_t. + template + static __success_type<__remove_cvref_t<__cond_t>> + _S_test_2(int); +#endif + + template + static __failure_type + _S_test_2(...); + + template + static decltype(_S_test_2<_Tp, _Up>(0)) + _S_test(...); + }; + + // If sizeof...(T) is zero, there shall be no member type. + template<> + struct common_type<> + { }; + + // If sizeof...(T) is one, the same type, if any, as common_type_t. + template + struct common_type<_Tp0> + : public common_type<_Tp0, _Tp0> + { }; + + // If sizeof...(T) is two, ... + template, typename _Dp2 = __decay_t<_Tp2>> + struct __common_type_impl + { + // If is_same_v is false or is_same_v is false, + // let C denote the same type, if any, as common_type_t. + using type = common_type<_Dp1, _Dp2>; + }; + + template + struct __common_type_impl<_Tp1, _Tp2, _Tp1, _Tp2> + : private __do_common_type_impl + { + // Otherwise, if decay_t() : declval())> + // denotes a valid type, let C denote that type. + using type = decltype(_S_test<_Tp1, _Tp2>(0)); + }; + + // If sizeof...(T) is two, ... + template + struct common_type<_Tp1, _Tp2> + : public __common_type_impl<_Tp1, _Tp2>::type + { }; + + template + struct __common_type_pack + { }; + + template + struct __common_type_fold; + + // If sizeof...(T) is greater than two, ... + template + struct common_type<_Tp1, _Tp2, _Rp...> + : public __common_type_fold, + __common_type_pack<_Rp...>> + { }; + + // Let C denote the same type, if any, as common_type_t. + // If there is such a type C, type shall denote the same type, if any, + // as common_type_t. + template + struct __common_type_fold<_CTp, __common_type_pack<_Rp...>, + __void_t> + : public common_type + { }; + + // Otherwise, there shall be no member type. + template + struct __common_type_fold<_CTp, _Rp, void> + { }; + + template::value> + struct __underlying_type_impl + { + using type = __underlying_type(_Tp); + }; + + template + struct __underlying_type_impl<_Tp, false> + { }; + + /// The underlying type of an enum. + template + struct underlying_type + : public __underlying_type_impl<_Tp> + { }; + + template + struct __declval_protector + { + static const bool __stop = false; + }; + + template + auto declval() noexcept -> decltype(__declval<_Tp>(0)) + { + static_assert(__declval_protector<_Tp>::__stop, + "declval() must not be used!"); + return __declval<_Tp>(0); + } + + /// result_of + template + class result_of; + + // Sfinae-friendly result_of implementation: + +#define __cpp_lib_result_of_sfinae 201210 + + struct __invoke_memfun_ref { }; + struct __invoke_memfun_deref { }; + struct __invoke_memobj_ref { }; + struct __invoke_memobj_deref { }; + struct __invoke_other { }; + + // Associate a tag type with a specialization of __success_type. + template + struct __result_of_success : __success_type<_Tp> + { using __invoke_type = _Tag; }; + + // [func.require] paragraph 1 bullet 1: + struct __result_of_memfun_ref_impl + { + template + static __result_of_success().*std::declval<_Fp>())(std::declval<_Args>()...) + ), __invoke_memfun_ref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memfun_ref + : private __result_of_memfun_ref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg, _Args...>(0)) type; + }; + + // [func.require] paragraph 1 bullet 2: + struct __result_of_memfun_deref_impl + { + template + static __result_of_success()).*std::declval<_Fp>())(std::declval<_Args>()...) + ), __invoke_memfun_deref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memfun_deref + : private __result_of_memfun_deref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg, _Args...>(0)) type; + }; + + // [func.require] paragraph 1 bullet 3: + struct __result_of_memobj_ref_impl + { + template + static __result_of_success().*std::declval<_Fp>() + ), __invoke_memobj_ref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memobj_ref + : private __result_of_memobj_ref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg>(0)) type; + }; + + // [func.require] paragraph 1 bullet 4: + struct __result_of_memobj_deref_impl + { + template + static __result_of_success()).*std::declval<_Fp>() + ), __invoke_memobj_deref> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_memobj_deref + : private __result_of_memobj_deref_impl + { + typedef decltype(_S_test<_MemPtr, _Arg>(0)) type; + }; + + template + struct __result_of_memobj; + + template + struct __result_of_memobj<_Res _Class::*, _Arg> + { + typedef __remove_cvref_t<_Arg> _Argval; + typedef _Res _Class::* _MemPtr; + typedef typename conditional<__or_, + is_base_of<_Class, _Argval>>::value, + __result_of_memobj_ref<_MemPtr, _Arg>, + __result_of_memobj_deref<_MemPtr, _Arg> + >::type::type type; + }; + + template + struct __result_of_memfun; + + template + struct __result_of_memfun<_Res _Class::*, _Arg, _Args...> + { + typedef typename remove_reference<_Arg>::type _Argval; + typedef _Res _Class::* _MemPtr; + typedef typename conditional::value, + __result_of_memfun_ref<_MemPtr, _Arg, _Args...>, + __result_of_memfun_deref<_MemPtr, _Arg, _Args...> + >::type::type type; + }; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2219. INVOKE-ing a pointer to member with a reference_wrapper + // as the object expression + + // Used by result_of, invoke etc. to unwrap a reference_wrapper. + template> + struct __inv_unwrap + { + using type = _Tp; + }; + + template + struct __inv_unwrap<_Tp, reference_wrapper<_Up>> + { + using type = _Up&; + }; + + template + struct __result_of_impl + { + typedef __failure_type type; + }; + + template + struct __result_of_impl + : public __result_of_memobj<__decay_t<_MemPtr>, + typename __inv_unwrap<_Arg>::type> + { }; + + template + struct __result_of_impl + : public __result_of_memfun<__decay_t<_MemPtr>, + typename __inv_unwrap<_Arg>::type, _Args...> + { }; + + // [func.require] paragraph 1 bullet 5: + struct __result_of_other_impl + { + template + static __result_of_success()(std::declval<_Args>()...) + ), __invoke_other> _S_test(int); + + template + static __failure_type _S_test(...); + }; + + template + struct __result_of_impl + : private __result_of_other_impl + { + typedef decltype(_S_test<_Functor, _ArgTypes...>(0)) type; + }; + + // __invoke_result (std::invoke_result for C++11) + template + struct __invoke_result + : public __result_of_impl< + is_member_object_pointer< + typename remove_reference<_Functor>::type + >::value, + is_member_function_pointer< + typename remove_reference<_Functor>::type + >::value, + _Functor, _ArgTypes... + >::type + { }; + + template + struct result_of<_Functor(_ArgTypes...)> + : public __invoke_result<_Functor, _ArgTypes...> + { }; + +#if __cplusplus >= 201402L + /// Alias template for aligned_storage + template::__type)> + using aligned_storage_t = typename aligned_storage<_Len, _Align>::type; + + template + using aligned_union_t = typename aligned_union<_Len, _Types...>::type; + + /// Alias template for decay + template + using decay_t = typename decay<_Tp>::type; + + /// Alias template for enable_if + template + using enable_if_t = typename enable_if<_Cond, _Tp>::type; + + /// Alias template for conditional + template + using conditional_t = typename conditional<_Cond, _Iftrue, _Iffalse>::type; + + /// Alias template for common_type + template + using common_type_t = typename common_type<_Tp...>::type; + + /// Alias template for underlying_type + template + using underlying_type_t = typename underlying_type<_Tp>::type; + + /// Alias template for result_of + template + using result_of_t = typename result_of<_Tp>::type; +#endif // C++14 + +#if __cplusplus >= 201703L || !defined(__STRICT_ANSI__) // c++17 or gnu++11 +#define __cpp_lib_void_t 201411 + /// A metafunction that always yields void, used for detecting valid types. + template using void_t = void; +#endif + + /// Implementation of the detection idiom (negative case). + template class _Op, typename... _Args> + struct __detector + { + using value_t = false_type; + using type = _Default; + }; + + /// Implementation of the detection idiom (positive case). + template class _Op, + typename... _Args> + struct __detector<_Default, __void_t<_Op<_Args...>>, _Op, _Args...> + { + using value_t = true_type; + using type = _Op<_Args...>; + }; + + // Detect whether _Op<_Args...> is a valid type, use _Default if not. + template class _Op, + typename... _Args> + using __detected_or = __detector<_Default, void, _Op, _Args...>; + + // _Op<_Args...> if that is a valid type, otherwise _Default. + template class _Op, + typename... _Args> + using __detected_or_t + = typename __detected_or<_Default, _Op, _Args...>::type; + + /// @} group metaprogramming + + /** + * Use SFINAE to determine if the type _Tp has a publicly-accessible + * member type _NTYPE. + */ +#define _GLIBCXX_HAS_NESTED_TYPE(_NTYPE) \ + template> \ + struct __has_##_NTYPE \ + : false_type \ + { }; \ + template \ + struct __has_##_NTYPE<_Tp, __void_t> \ + : true_type \ + { }; + + template + struct __is_swappable; + + template + struct __is_nothrow_swappable; + + template + class tuple; + + template + struct __is_tuple_like_impl : false_type + { }; + + template + struct __is_tuple_like_impl> : true_type + { }; + + // Internal type trait that allows us to sfinae-protect tuple_cat. + template + struct __is_tuple_like + : public __is_tuple_like_impl<__remove_cvref_t<_Tp>>::type + { }; + + template + _GLIBCXX20_CONSTEXPR + inline + _Require<__not_<__is_tuple_like<_Tp>>, + is_move_constructible<_Tp>, + is_move_assignable<_Tp>> + swap(_Tp&, _Tp&) + noexcept(__and_, + is_nothrow_move_assignable<_Tp>>::value); + + template + _GLIBCXX20_CONSTEXPR + inline + __enable_if_t<__is_swappable<_Tp>::value> + swap(_Tp (&__a)[_Nm], _Tp (&__b)[_Nm]) + noexcept(__is_nothrow_swappable<_Tp>::value); + + namespace __swappable_details { + using std::swap; + + struct __do_is_swappable_impl + { + template(), std::declval<_Tp&>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + struct __do_is_nothrow_swappable_impl + { + template + static __bool_constant< + noexcept(swap(std::declval<_Tp&>(), std::declval<_Tp&>())) + > __test(int); + + template + static false_type __test(...); + }; + + } // namespace __swappable_details + + template + struct __is_swappable_impl + : public __swappable_details::__do_is_swappable_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template + struct __is_nothrow_swappable_impl + : public __swappable_details::__do_is_nothrow_swappable_impl + { + typedef decltype(__test<_Tp>(0)) type; + }; + + template + struct __is_swappable + : public __is_swappable_impl<_Tp>::type + { }; + + template + struct __is_nothrow_swappable + : public __is_nothrow_swappable_impl<_Tp>::type + { }; + +#if __cplusplus > 201402L || !defined(__STRICT_ANSI__) // c++1z or gnu++11 +#define __cpp_lib_is_swappable 201603 + /// Metafunctions used for detecting swappable types: p0185r1 + + /// is_swappable + template + struct is_swappable + : public __is_swappable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + /// is_nothrow_swappable + template + struct is_nothrow_swappable + : public __is_nothrow_swappable_impl<_Tp>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + +#if __cplusplus >= 201402L + /// is_swappable_v + template + _GLIBCXX17_INLINE constexpr bool is_swappable_v = + is_swappable<_Tp>::value; + + /// is_nothrow_swappable_v + template + _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_v = + is_nothrow_swappable<_Tp>::value; +#endif // __cplusplus >= 201402L + + namespace __swappable_with_details { + using std::swap; + + struct __do_is_swappable_with_impl + { + template(), std::declval<_Up>())), + typename + = decltype(swap(std::declval<_Up>(), std::declval<_Tp>()))> + static true_type __test(int); + + template + static false_type __test(...); + }; + + struct __do_is_nothrow_swappable_with_impl + { + template + static __bool_constant< + noexcept(swap(std::declval<_Tp>(), std::declval<_Up>())) + && + noexcept(swap(std::declval<_Up>(), std::declval<_Tp>())) + > __test(int); + + template + static false_type __test(...); + }; + + } // namespace __swappable_with_details + + template + struct __is_swappable_with_impl + : public __swappable_with_details::__do_is_swappable_with_impl + { + typedef decltype(__test<_Tp, _Up>(0)) type; + }; + + // Optimization for the homogenous lvalue case, not required: + template + struct __is_swappable_with_impl<_Tp&, _Tp&> + : public __swappable_details::__do_is_swappable_impl + { + typedef decltype(__test<_Tp&>(0)) type; + }; + + template + struct __is_nothrow_swappable_with_impl + : public __swappable_with_details::__do_is_nothrow_swappable_with_impl + { + typedef decltype(__test<_Tp, _Up>(0)) type; + }; + + // Optimization for the homogenous lvalue case, not required: + template + struct __is_nothrow_swappable_with_impl<_Tp&, _Tp&> + : public __swappable_details::__do_is_nothrow_swappable_impl + { + typedef decltype(__test<_Tp&>(0)) type; + }; + + /// is_swappable_with + template + struct is_swappable_with + : public __is_swappable_with_impl<_Tp, _Up>::type + { }; + + /// is_nothrow_swappable_with + template + struct is_nothrow_swappable_with + : public __is_nothrow_swappable_with_impl<_Tp, _Up>::type + { }; + +#if __cplusplus >= 201402L + /// is_swappable_with_v + template + _GLIBCXX17_INLINE constexpr bool is_swappable_with_v = + is_swappable_with<_Tp, _Up>::value; + + /// is_nothrow_swappable_with_v + template + _GLIBCXX17_INLINE constexpr bool is_nothrow_swappable_with_v = + is_nothrow_swappable_with<_Tp, _Up>::value; +#endif // __cplusplus >= 201402L + +#endif// c++1z or gnu++11 + + // __is_invocable (std::is_invocable for C++11) + + // The primary template is used for invalid INVOKE expressions. + template::value, typename = void> + struct __is_invocable_impl : false_type { }; + + // Used for valid INVOKE and INVOKE expressions. + template + struct __is_invocable_impl<_Result, _Ret, + /* is_void<_Ret> = */ true, + __void_t> + : true_type + { }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + // Used for INVOKE expressions to check the implicit conversion to R. + template + struct __is_invocable_impl<_Result, _Ret, + /* is_void<_Ret> = */ false, + __void_t> + { + private: + // The type of the INVOKE expression. + // Unlike declval, this doesn't add_rvalue_reference. + static typename _Result::type _S_get(); + + template + static void _S_conv(_Tp); + + // This overload is viable if INVOKE(f, args...) can convert to _Tp. + template(_S_get()))> + static true_type + _S_test(int); + + template + static false_type + _S_test(...); + + public: + using type = decltype(_S_test<_Ret>(1)); + }; +#pragma GCC diagnostic pop + + template + struct __is_invocable + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type + { }; + + template + constexpr bool __call_is_nt(__invoke_memfun_ref) + { + using _Up = typename __inv_unwrap<_Tp>::type; + return noexcept((std::declval<_Up>().*std::declval<_Fn>())( + std::declval<_Args>()...)); + } + + template + constexpr bool __call_is_nt(__invoke_memfun_deref) + { + return noexcept(((*std::declval<_Tp>()).*std::declval<_Fn>())( + std::declval<_Args>()...)); + } + + template + constexpr bool __call_is_nt(__invoke_memobj_ref) + { + using _Up = typename __inv_unwrap<_Tp>::type; + return noexcept(std::declval<_Up>().*std::declval<_Fn>()); + } + + template + constexpr bool __call_is_nt(__invoke_memobj_deref) + { + return noexcept((*std::declval<_Tp>()).*std::declval<_Fn>()); + } + + template + constexpr bool __call_is_nt(__invoke_other) + { + return noexcept(std::declval<_Fn>()(std::declval<_Args>()...)); + } + + template + struct __call_is_nothrow + : __bool_constant< + std::__call_is_nt<_Fn, _Args...>(typename _Result::__invoke_type{}) + > + { }; + + template + using __call_is_nothrow_ + = __call_is_nothrow<__invoke_result<_Fn, _Args...>, _Fn, _Args...>; + + // __is_nothrow_invocable (std::is_nothrow_invocable for C++11) + template + struct __is_nothrow_invocable + : __and_<__is_invocable<_Fn, _Args...>, + __call_is_nothrow_<_Fn, _Args...>>::type + { }; + +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wctor-dtor-privacy" + struct __nonesuchbase {}; + struct __nonesuch : private __nonesuchbase { + ~__nonesuch() = delete; + __nonesuch(__nonesuch const&) = delete; + void operator=(__nonesuch const&) = delete; + }; +#pragma GCC diagnostic pop + +#if __cplusplus >= 201703L +# define __cpp_lib_is_invocable 201703 + + /// std::invoke_result + template + struct invoke_result + : public __invoke_result<_Functor, _ArgTypes...> + { }; + + /// std::invoke_result_t + template + using invoke_result_t = typename invoke_result<_Fn, _Args...>::type; + + /// std::is_invocable + template + struct is_invocable + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; + + /// std::is_invocable_r + template + struct is_invocable_r + : __is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; + + /// std::is_nothrow_invocable + template + struct is_nothrow_invocable + : __and_<__is_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, void>, + __call_is_nothrow_<_Fn, _ArgTypes...>>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + }; + + /// @cond undocumented + // This checks that the INVOKE expression is well-formed and that the + // conversion to R does not throw. It does *not* check whether the INVOKE + // expression itself can throw. That is done by __call_is_nothrow_ instead. + template + using __is_nt_invocable_impl + = typename __is_invocable_impl<_Result, _Ret>::__nothrow_conv; + /// @endcond + + /// std::is_nothrow_invocable_r + template + struct is_nothrow_invocable_r + : __and_<__is_nt_invocable_impl<__invoke_result<_Fn, _ArgTypes...>, _Ret>, + __call_is_nothrow_<_Fn, _ArgTypes...>>::type + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Fn>{}), + "_Fn must be a complete class or an unbounded array"); + static_assert((std::__is_complete_or_unbounded( + __type_identity<_ArgTypes>{}) && ...), + "each argument type must be a complete class or an unbounded array"); + static_assert(std::__is_complete_or_unbounded(__type_identity<_Ret>{}), + "_Ret must be a complete class or an unbounded array"); + }; + + /// std::is_invocable_v + template + inline constexpr bool is_invocable_v = is_invocable<_Fn, _Args...>::value; + + /// std::is_nothrow_invocable_v + template + inline constexpr bool is_nothrow_invocable_v + = is_nothrow_invocable<_Fn, _Args...>::value; + + /// std::is_invocable_r_v + template + inline constexpr bool is_invocable_r_v + = is_invocable_r<_Ret, _Fn, _Args...>::value; + + /// std::is_nothrow_invocable_r_v + template + inline constexpr bool is_nothrow_invocable_r_v + = is_nothrow_invocable_r<_Ret, _Fn, _Args...>::value; +#endif // C++17 + +#if __cplusplus >= 201703L +# define __cpp_lib_type_trait_variable_templates 201510L +template + inline constexpr bool is_void_v = is_void<_Tp>::value; +template + inline constexpr bool is_null_pointer_v = is_null_pointer<_Tp>::value; +template + inline constexpr bool is_integral_v = is_integral<_Tp>::value; +template + inline constexpr bool is_floating_point_v = is_floating_point<_Tp>::value; +template + inline constexpr bool is_array_v = is_array<_Tp>::value; +template + inline constexpr bool is_pointer_v = is_pointer<_Tp>::value; +template + inline constexpr bool is_lvalue_reference_v = + is_lvalue_reference<_Tp>::value; +template + inline constexpr bool is_rvalue_reference_v = + is_rvalue_reference<_Tp>::value; +template + inline constexpr bool is_member_object_pointer_v = + is_member_object_pointer<_Tp>::value; +template + inline constexpr bool is_member_function_pointer_v = + is_member_function_pointer<_Tp>::value; +template + inline constexpr bool is_enum_v = is_enum<_Tp>::value; +template + inline constexpr bool is_union_v = is_union<_Tp>::value; +template + inline constexpr bool is_class_v = is_class<_Tp>::value; +template + inline constexpr bool is_function_v = is_function<_Tp>::value; +template + inline constexpr bool is_reference_v = is_reference<_Tp>::value; +template + inline constexpr bool is_arithmetic_v = is_arithmetic<_Tp>::value; +template + inline constexpr bool is_fundamental_v = is_fundamental<_Tp>::value; +template + inline constexpr bool is_object_v = is_object<_Tp>::value; +template + inline constexpr bool is_scalar_v = is_scalar<_Tp>::value; +template + inline constexpr bool is_compound_v = is_compound<_Tp>::value; +template + inline constexpr bool is_member_pointer_v = is_member_pointer<_Tp>::value; +template + inline constexpr bool is_const_v = is_const<_Tp>::value; +template + inline constexpr bool is_volatile_v = is_volatile<_Tp>::value; +template + inline constexpr bool is_trivial_v = is_trivial<_Tp>::value; +template + inline constexpr bool is_trivially_copyable_v = + is_trivially_copyable<_Tp>::value; +template + inline constexpr bool is_standard_layout_v = is_standard_layout<_Tp>::value; +#pragma GCC diagnostic push +#pragma GCC diagnostic ignored "-Wdeprecated-declarations" +template + _GLIBCXX20_DEPRECATED("use is_standard_layout_v && is_trivial_v instead") + inline constexpr bool is_pod_v = is_pod<_Tp>::value; +#pragma GCC diagnostic pop +template + inline constexpr bool is_literal_type_v = is_literal_type<_Tp>::value; +template + inline constexpr bool is_empty_v = is_empty<_Tp>::value; +template + inline constexpr bool is_polymorphic_v = is_polymorphic<_Tp>::value; +template + inline constexpr bool is_abstract_v = is_abstract<_Tp>::value; +template + inline constexpr bool is_final_v = is_final<_Tp>::value; +template + inline constexpr bool is_signed_v = is_signed<_Tp>::value; +template + inline constexpr bool is_unsigned_v = is_unsigned<_Tp>::value; +template + inline constexpr bool is_constructible_v = + is_constructible<_Tp, _Args...>::value; +template + inline constexpr bool is_default_constructible_v = + is_default_constructible<_Tp>::value; +template + inline constexpr bool is_copy_constructible_v = + is_copy_constructible<_Tp>::value; +template + inline constexpr bool is_move_constructible_v = + is_move_constructible<_Tp>::value; +template + inline constexpr bool is_assignable_v = is_assignable<_Tp, _Up>::value; +template + inline constexpr bool is_copy_assignable_v = is_copy_assignable<_Tp>::value; +template + inline constexpr bool is_move_assignable_v = is_move_assignable<_Tp>::value; +template + inline constexpr bool is_destructible_v = is_destructible<_Tp>::value; +template + inline constexpr bool is_trivially_constructible_v = + is_trivially_constructible<_Tp, _Args...>::value; +template + inline constexpr bool is_trivially_default_constructible_v = + is_trivially_default_constructible<_Tp>::value; +template + inline constexpr bool is_trivially_copy_constructible_v = + is_trivially_copy_constructible<_Tp>::value; +template + inline constexpr bool is_trivially_move_constructible_v = + is_trivially_move_constructible<_Tp>::value; +template + inline constexpr bool is_trivially_assignable_v = + is_trivially_assignable<_Tp, _Up>::value; +template + inline constexpr bool is_trivially_copy_assignable_v = + is_trivially_copy_assignable<_Tp>::value; +template + inline constexpr bool is_trivially_move_assignable_v = + is_trivially_move_assignable<_Tp>::value; +template + inline constexpr bool is_trivially_destructible_v = + is_trivially_destructible<_Tp>::value; +template + inline constexpr bool is_nothrow_constructible_v = + is_nothrow_constructible<_Tp, _Args...>::value; +template + inline constexpr bool is_nothrow_default_constructible_v = + is_nothrow_default_constructible<_Tp>::value; +template + inline constexpr bool is_nothrow_copy_constructible_v = + is_nothrow_copy_constructible<_Tp>::value; +template + inline constexpr bool is_nothrow_move_constructible_v = + is_nothrow_move_constructible<_Tp>::value; +template + inline constexpr bool is_nothrow_assignable_v = + is_nothrow_assignable<_Tp, _Up>::value; +template + inline constexpr bool is_nothrow_copy_assignable_v = + is_nothrow_copy_assignable<_Tp>::value; +template + inline constexpr bool is_nothrow_move_assignable_v = + is_nothrow_move_assignable<_Tp>::value; +template + inline constexpr bool is_nothrow_destructible_v = + is_nothrow_destructible<_Tp>::value; +template + inline constexpr bool has_virtual_destructor_v = + has_virtual_destructor<_Tp>::value; +template + inline constexpr size_t alignment_of_v = alignment_of<_Tp>::value; +template + inline constexpr size_t rank_v = rank<_Tp>::value; +template + inline constexpr size_t extent_v = extent<_Tp, _Idx>::value; +#ifdef _GLIBCXX_BUILTIN_IS_SAME_AS +template + inline constexpr bool is_same_v = _GLIBCXX_BUILTIN_IS_SAME_AS(_Tp, _Up); +#else +template + inline constexpr bool is_same_v = std::is_same<_Tp, _Up>::value; +#endif +template + inline constexpr bool is_base_of_v = is_base_of<_Base, _Derived>::value; +template + inline constexpr bool is_convertible_v = is_convertible<_From, _To>::value; + +#ifdef _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP +# define __cpp_lib_has_unique_object_representations 201606 + /// has_unique_object_representations + template + struct has_unique_object_representations + : bool_constant<__has_unique_object_representations( + remove_cv_t> + )> + { + static_assert(std::__is_complete_or_unbounded(__type_identity<_Tp>{}), + "template argument must be a complete class or an unbounded array"); + }; + + template + inline constexpr bool has_unique_object_representations_v + = has_unique_object_representations<_Tp>::value; +#endif + +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE +# define __cpp_lib_is_aggregate 201703 + /// is_aggregate + template + struct is_aggregate + : bool_constant<__is_aggregate(remove_cv_t<_Tp>)> + { }; + + /// is_aggregate_v + template + inline constexpr bool is_aggregate_v = is_aggregate<_Tp>::value; +#endif +#endif // C++17 + +#if __cplusplus > 201703L +#define __cpp_lib_remove_cvref 201711L + + /// Remove references and cv-qualifiers. + template + struct remove_cvref + { + using type = __remove_cvref_t<_Tp>; + }; + + template + using remove_cvref_t = __remove_cvref_t<_Tp>; + +#define __cpp_lib_type_identity 201806L + /// Identity metafunction. + template + struct type_identity { using type = _Tp; }; + + template + using type_identity_t = typename type_identity<_Tp>::type; + +#define __cpp_lib_unwrap_ref 201811L + + /// Unwrap a reference_wrapper + template + struct unwrap_reference { using type = _Tp; }; + + template + struct unwrap_reference> { using type = _Tp&; }; + + template + using unwrap_reference_t = typename unwrap_reference<_Tp>::type; + + /// Decay type and if it's a reference_wrapper, unwrap it + template + struct unwrap_ref_decay { using type = unwrap_reference_t>; }; + + template + using unwrap_ref_decay_t = typename unwrap_ref_decay<_Tp>::type; + +#define __cpp_lib_bounded_array_traits 201902L + + /// True for a type that is an array of known bound. + template + struct is_bounded_array + : public __is_array_known_bounds<_Tp> + { }; + + /// True for a type that is an array of unknown bound. + template + struct is_unbounded_array + : public __is_array_unknown_bounds<_Tp> + { }; + + template + inline constexpr bool is_bounded_array_v + = is_bounded_array<_Tp>::value; + + template + inline constexpr bool is_unbounded_array_v + = is_unbounded_array<_Tp>::value; + +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED + +#define __cpp_lib_is_constant_evaluated 201811L + + constexpr inline bool + is_constant_evaluated() noexcept + { return __builtin_is_constant_evaluated(); } +#endif + + template + using __copy_cv = typename __match_cv_qualifiers<_From, _To>::__type; + + template + using __cond_res + = decltype(false ? declval<_Xp(&)()>()() : declval<_Yp(&)()>()()); + + template + struct __common_ref_impl + { }; + + // [meta.trans.other], COMMON-REF(A, B) + template + using __common_ref = typename __common_ref_impl<_Ap, _Bp>::type; + + // If A and B are both lvalue reference types, ... + template + struct __common_ref_impl<_Xp&, _Yp&, + __void_t<__cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>>> + { using type = __cond_res<__copy_cv<_Xp, _Yp>&, __copy_cv<_Yp, _Xp>&>; }; + + // let C be remove_reference_t&& + template + using __common_ref_C = remove_reference_t<__common_ref<_Xp&, _Yp&>>&&; + + // If A and B are both rvalue reference types, ... + template + struct __common_ref_impl<_Xp&&, _Yp&&, + _Require>, + is_convertible<_Yp&&, __common_ref_C<_Xp, _Yp>>>> + { using type = __common_ref_C<_Xp, _Yp>; }; + + // let D be COMMON-REF(const X&, Y&) + template + using __common_ref_D = __common_ref; + + // If A is an rvalue reference and B is an lvalue reference, ... + template + struct __common_ref_impl<_Xp&&, _Yp&, + _Require>>> + { using type = __common_ref_D<_Xp, _Yp>; }; + + // If A is an lvalue reference and B is an rvalue reference, ... + template + struct __common_ref_impl<_Xp&, _Yp&&> + : __common_ref_impl<_Yp&&, _Xp&> + { }; + + template class _TQual, template class _UQual> + struct basic_common_reference + { }; + + template + struct __xref + { template using __type = __copy_cv<_Tp, _Up>; }; + + template + struct __xref<_Tp&> + { template using __type = __copy_cv<_Tp, _Up>&; }; + + template + struct __xref<_Tp&&> + { template using __type = __copy_cv<_Tp, _Up>&&; }; + + template + using __basic_common_ref + = typename basic_common_reference, + remove_cvref_t<_Tp2>, + __xref<_Tp1>::template __type, + __xref<_Tp2>::template __type>::type; + + template + struct common_reference; + + template + using common_reference_t = typename common_reference<_Tp...>::type; + + // If sizeof...(T) is zero, there shall be no member type. + template<> + struct common_reference<> + { }; + + // If sizeof...(T) is one ... + template + struct common_reference<_Tp0> + { using type = _Tp0; }; + + template + struct __common_reference_impl + : __common_reference_impl<_Tp1, _Tp2, _Bullet + 1> + { }; + + // If sizeof...(T) is two ... + template + struct common_reference<_Tp1, _Tp2> + : __common_reference_impl<_Tp1, _Tp2> + { }; + + // If T1 and T2 are reference types and COMMON-REF(T1, T2) is well-formed, ... + template + struct __common_reference_impl<_Tp1&, _Tp2&, 1, + void_t<__common_ref<_Tp1&, _Tp2&>>> + { using type = __common_ref<_Tp1&, _Tp2&>; }; + + template + struct __common_reference_impl<_Tp1&&, _Tp2&&, 1, + void_t<__common_ref<_Tp1&&, _Tp2&&>>> + { using type = __common_ref<_Tp1&&, _Tp2&&>; }; + + template + struct __common_reference_impl<_Tp1&, _Tp2&&, 1, + void_t<__common_ref<_Tp1&, _Tp2&&>>> + { using type = __common_ref<_Tp1&, _Tp2&&>; }; + + template + struct __common_reference_impl<_Tp1&&, _Tp2&, 1, + void_t<__common_ref<_Tp1&&, _Tp2&>>> + { using type = __common_ref<_Tp1&&, _Tp2&>; }; + + // Otherwise, if basic_common_reference<...>::type is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 2, + void_t<__basic_common_ref<_Tp1, _Tp2>>> + { using type = __basic_common_ref<_Tp1, _Tp2>; }; + + // Otherwise, if COND-RES(T1, T2) is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 3, + void_t<__cond_res<_Tp1, _Tp2>>> + { using type = __cond_res<_Tp1, _Tp2>; }; + + // Otherwise, if common_type_t is well-formed, ... + template + struct __common_reference_impl<_Tp1, _Tp2, 4, + void_t>> + { using type = common_type_t<_Tp1, _Tp2>; }; + + // Otherwise, there shall be no member type. + template + struct __common_reference_impl<_Tp1, _Tp2, 5, void> + { }; + + // Otherwise, if sizeof...(T) is greater than two, ... + template + struct common_reference<_Tp1, _Tp2, _Rest...> + : __common_type_fold, + __common_type_pack<_Rest...>> + { }; + + // Reuse __common_type_fold for common_reference + template + struct __common_type_fold, + __common_type_pack<_Rest...>, + void_t>> + : public common_reference, _Rest...> + { }; + +#endif // C++2a + +_GLIBCXX_END_NAMESPACE_VERSION } // namespace std -#endif // _AVR_TYPE_TRAITS +#endif // C++11 + +#endif // _GLIBCXX_TYPE_TRAITS diff --git a/resources/sources/avr-libstdcpp/include/unordered_map b/resources/sources/avr-libstdcpp/include/unordered_map new file mode 100644 index 000000000..e05238fe9 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/unordered_map @@ -0,0 +1,101 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/unordered_map + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_UNORDERED_MAP +#define _GLIBCXX_UNORDERED_MAP 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include +#include +#include // equal_to, _Identity, _Select1st +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template, + typename _Pred = std::equal_to<_Key>> + using unordered_map + = std::unordered_map<_Key, _Tp, _Hash, _Pred, + polymorphic_allocator>>; + template, + typename _Pred = std::equal_to<_Key>> + using unordered_multimap + = std::unordered_multimap<_Key, _Tp, _Hash, _Pred, + polymorphic_allocator>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template + inline typename unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>::size_type + erase_if(unordered_map<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, + _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } + + template + inline typename unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>:: + size_type + erase_if(unordered_multimap<_Key, _Tp, _Hash, _CPred, _Alloc>& __cont, + _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif // C++11 + +#endif // _GLIBCXX_UNORDERED_MAP diff --git a/resources/sources/avr-libstdcpp/include/unordered_set b/resources/sources/avr-libstdcpp/include/unordered_set new file mode 100644 index 000000000..6cbd242ff --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/unordered_set @@ -0,0 +1,100 @@ +// -*- C++ -*- + +// Copyright (C) 2007-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/unordered_set + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_UNORDERED_SET +#define _GLIBCXX_UNORDERED_SET 1 + +#pragma GCC system_header + +#if __cplusplus < 201103L +# include +#else + +#include +#include +#include +#include +#include +#include +#include // equal_to, _Identity, _Select1st +#include +#include +#include +#include +#include + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr + { + template class polymorphic_allocator; + template, + typename _Pred = std::equal_to<_Key>> + using unordered_set + = std::unordered_set<_Key, _Hash, _Pred, + polymorphic_allocator<_Key>>; + template, + typename _Pred = std::equal_to<_Key>> + using unordered_multiset + = std::unordered_multiset<_Key, _Hash, _Pred, + polymorphic_allocator<_Key>>; + } // namespace pmr +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + template + inline typename unordered_set<_Key, _Hash, _CPred, _Alloc>::size_type + erase_if(unordered_set<_Key, _Hash, _CPred, _Alloc>& __cont, + _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } + + template + inline typename unordered_multiset<_Key, _Hash, _CPred, _Alloc>::size_type + erase_if(unordered_multiset<_Key, _Hash, _CPred, _Alloc>& __cont, + _Predicate __pred) + { return __detail::__erase_nodes_if(__cont, __pred); } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif // C++11 + +#endif // _GLIBCXX_UNORDERED_SET diff --git a/resources/sources/avr-libstdcpp/include/utility b/resources/sources/avr-libstdcpp/include/utility index daa16ae36..f7533d5a5 100644 --- a/resources/sources/avr-libstdcpp/include/utility +++ b/resources/sources/avr-libstdcpp/include/utility @@ -1,20 +1,538 @@ -// Minimal for AVR -#ifndef _AVR_UTILITY -#define _AVR_UTILITY +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996,1997 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/utility + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_UTILITY +#define _GLIBCXX_UTILITY 1 + +#pragma GCC system_header + +/** + * @defgroup utilities Utilities + * + * Components deemed generally useful. Includes pair, tuple, + * forward/move helpers, ratio, function object, metaprogramming and + * type traits, time, date, and memory functions. + */ + +#include +#include +#include + +#if __cplusplus >= 201103L + #include +#include +#include + +#if __cplusplus > 201703L +#include +#endif -namespace std { - template constexpr remove_reference_t&& move(T&& t) noexcept { - return static_cast&&>(t); - } - template constexpr T&& forward(remove_reference_t& t) noexcept { - return static_cast(t); - } - template constexpr T&& forward(remove_reference_t&& t) noexcept { - return static_cast(t); - } - template void swap(T& a, T& b) noexcept { - T tmp = move(a); a = move(b); b = move(tmp); - } -} +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /// Finds the size of a given tuple type. + template + struct tuple_size; + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 2313. tuple_size should always derive from integral_constant + // 2770. tuple_size specialization is not SFINAE compatible + + template::type, + typename = typename enable_if::value>::type, + size_t = tuple_size<_Tp>::value> + using __enable_if_has_tuple_size = _Tp; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + + template + struct tuple_size> + : public tuple_size<_Tp> { }; + + /// Gives the type of the ith element of a given tuple type. + template + struct tuple_element; + + // Duplicate of C++14's tuple_element_t for internal use in C++11 mode + template + using __tuple_element_t = typename tuple_element<__i, _Tp>::type; + + template + struct tuple_element<__i, const _Tp> + { + typedef typename add_const<__tuple_element_t<__i, _Tp>>::type type; + }; + + template + struct tuple_element<__i, volatile _Tp> + { + typedef typename add_volatile<__tuple_element_t<__i, _Tp>>::type type; + }; + + template + struct tuple_element<__i, const volatile _Tp> + { + typedef typename add_cv<__tuple_element_t<__i, _Tp>>::type type; + }; + +#if __cplusplus >= 201402L +// The standard says this macro and alias template should be in +// but we define them here, to be available when the partial specializations +// of tuple_element> and tuple_element> are defined. +#define __cpp_lib_tuple_element_t 201402L + + template + using tuple_element_t = typename tuple_element<__i, _Tp>::type; #endif + + // Various functions which give std::pair a tuple-like interface. + + /// Partial specialization for std::pair + template + struct __is_tuple_like_impl> : true_type + { }; + + /// Partial specialization for std::pair + template + struct tuple_size> + : public integral_constant { }; + + /// Partial specialization for std::pair + template + struct tuple_element<0, std::pair<_Tp1, _Tp2>> + { typedef _Tp1 type; }; + + /// Partial specialization for std::pair + template + struct tuple_element<1, std::pair<_Tp1, _Tp2>> + { typedef _Tp2 type; }; + + template + struct __pair_get; + + template<> + struct __pair_get<0> + { + template + static constexpr _Tp1& + __get(std::pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.first; } + + template + static constexpr _Tp1&& + __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<_Tp1>(__pair.first); } + + template + static constexpr const _Tp1& + __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.first; } + + template + static constexpr const _Tp1&& + __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward(__pair.first); } + }; + + template<> + struct __pair_get<1> + { + template + static constexpr _Tp2& + __get(std::pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.second; } + + template + static constexpr _Tp2&& + __move_get(std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward<_Tp2>(__pair.second); } + + template + static constexpr const _Tp2& + __const_get(const std::pair<_Tp1, _Tp2>& __pair) noexcept + { return __pair.second; } + + template + static constexpr const _Tp2&& + __const_move_get(const std::pair<_Tp1, _Tp2>&& __pair) noexcept + { return std::forward(__pair.second); } + }; + + template + constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& + get(std::pair<_Tp1, _Tp2>& __in) noexcept + { return __pair_get<_Int>::__get(__in); } + + template + constexpr typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& + get(std::pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__move_get(std::move(__in)); } + + template + constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type& + get(const std::pair<_Tp1, _Tp2>& __in) noexcept + { return __pair_get<_Int>::__const_get(__in); } + + template + constexpr const typename tuple_element<_Int, std::pair<_Tp1, _Tp2>>::type&& + get(const std::pair<_Tp1, _Tp2>&& __in) noexcept + { return __pair_get<_Int>::__const_move_get(std::move(__in)); } + +#if __cplusplus >= 201402L + +#define __cpp_lib_tuples_by_type 201304 + + template + constexpr _Tp& + get(pair<_Tp, _Up>& __p) noexcept + { return __p.first; } + + template + constexpr const _Tp& + get(const pair<_Tp, _Up>& __p) noexcept + { return __p.first; } + + template + constexpr _Tp&& + get(pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template + constexpr const _Tp&& + get(const pair<_Tp, _Up>&& __p) noexcept + { return std::move(__p.first); } + + template + constexpr _Tp& + get(pair<_Up, _Tp>& __p) noexcept + { return __p.second; } + + template + constexpr const _Tp& + get(const pair<_Up, _Tp>& __p) noexcept + { return __p.second; } + + template + constexpr _Tp&& + get(pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } + + template + constexpr const _Tp&& + get(const pair<_Up, _Tp>&& __p) noexcept + { return std::move(__p.second); } + +#define __cpp_lib_exchange_function 201304 + + /// Assign @p __new_val to @p __obj and return its previous value. + template + _GLIBCXX20_CONSTEXPR + inline _Tp + exchange(_Tp& __obj, _Up&& __new_val) + { return std::__exchange(__obj, std::forward<_Up>(__new_val)); } + +#endif // C++14 + + // Stores a tuple of indices. Used by tuple and pair, and by bind() to + // extract the elements in a tuple. + template struct _Index_tuple { }; + +#if __GNUC__ >= 8 + +#ifdef __has_builtin +# if __has_builtin(__make_integer_seq) +# define _GLIBCXX_USE_MAKE_INTEGER_SEQ 1 +# endif +#endif + + // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. + template + struct _Build_index_tuple + { +#if _GLIBCXX_USE_MAKE_INTEGER_SEQ + template + using _IdxTuple = _Index_tuple<_Indices...>; + + using __type = __make_integer_seq<_IdxTuple, size_t, _Num>; +#else + using __type = _Index_tuple<__integer_pack(_Num)...>; +#endif + }; +#else // __GNUC__ < 8 + // Concatenates two _Index_tuples. + template struct _Itup_cat; + + template + struct _Itup_cat<_Index_tuple<_Ind1...>, _Index_tuple<_Ind2...>> + { + using __type = _Index_tuple<_Ind1..., (_Ind2 + sizeof...(_Ind1))...>; + }; + + // Builds an _Index_tuple<0, 1, 2, ..., _Num-1>. + template + struct _Build_index_tuple + : _Itup_cat::__type, + typename _Build_index_tuple<_Num - _Num / 2>::__type> + { }; + + template<> + struct _Build_index_tuple<1> + { + typedef _Index_tuple<0> __type; + }; + + template<> + struct _Build_index_tuple<0> + { + typedef _Index_tuple<> __type; + }; +#endif // __GNUC__ < 8 + +#if __cplusplus > 201103L + +#define __cpp_lib_integer_sequence 201304 + +#if __GNUC__ >= 8 + /// Class template integer_sequence + template + struct integer_sequence + { + typedef _Tp value_type; + static constexpr size_t size() noexcept { return sizeof...(_Idx); } + }; + + /// Alias template make_integer_sequence + template + using make_integer_sequence +#if _GLIBCXX_USE_MAKE_INTEGER_SEQ + = __make_integer_seq; +#else + = integer_sequence<_Tp, __integer_pack(_Num)...>; +#endif + +#undef _GLIBCXX_USE_MAKE_INTEGER_SEQ + +#else // __GNUC__ < 8 + /// Class template integer_sequence + template + struct integer_sequence + { + typedef _Tp value_type; + static constexpr size_t size() { return sizeof...(_Idx); } + }; + + template::__type> + struct _Make_integer_sequence; + + template + struct _Make_integer_sequence<_Tp, _Num, _Index_tuple<_Idx...>> + { + static_assert( _Num >= 0, + "Cannot make integer sequence of negative length" ); + + typedef integer_sequence<_Tp, static_cast<_Tp>(_Idx)...> __type; + }; + + /// Alias template make_integer_sequence + template + using make_integer_sequence + = typename _Make_integer_sequence<_Tp, _Num>::__type; +#endif // __GNUC__ < 8 + + /// Alias template index_sequence + template + using index_sequence = integer_sequence; + + /// Alias template make_index_sequence + template + using make_index_sequence = make_integer_sequence; + + /// Alias template index_sequence_for + template + using index_sequence_for = make_index_sequence; +#endif + +#if __cplusplus > 201402L + + struct in_place_t { + explicit in_place_t() = default; + }; + + inline constexpr in_place_t in_place{}; + + template struct in_place_type_t + { + explicit in_place_type_t() = default; + }; + + template + inline constexpr in_place_type_t<_Tp> in_place_type{}; + + template struct in_place_index_t + { + explicit in_place_index_t() = default; + }; + + template + inline constexpr in_place_index_t<_Idx> in_place_index{}; + + template + struct __is_in_place_type_impl : false_type + { }; + + template + struct __is_in_place_type_impl> : true_type + { }; + + template + struct __is_in_place_type + : public __is_in_place_type_impl<_Tp> + { }; + +#define __cpp_lib_as_const 201510 + template + constexpr add_const_t<_Tp>& as_const(_Tp& __t) noexcept { return __t; } + + template + void as_const(const _Tp&&) = delete; + +#if __cplusplus > 201703L +#define __cpp_lib_integer_comparison_functions 202002L + + template + constexpr bool + cmp_equal(_Tp __t, _Up __u) noexcept + { + static_assert(__is_standard_integer<_Tp>::value); + static_assert(__is_standard_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t == __u; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 && make_unsigned_t<_Tp>(__t) == __u; + else + return __u >= 0 && __t == make_unsigned_t<_Up>(__u); + } + + template + constexpr bool + cmp_not_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_equal(__t, __u); } + + template + constexpr bool + cmp_less(_Tp __t, _Up __u) noexcept + { + static_assert(__is_standard_integer<_Tp>::value); + static_assert(__is_standard_integer<_Up>::value); + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __t < __u; + else if constexpr (is_signed_v<_Tp>) + return __t < 0 || make_unsigned_t<_Tp>(__t) < __u; + else + return __u >= 0 && __t < make_unsigned_t<_Up>(__u); + } + + template + constexpr bool + cmp_greater(_Tp __t, _Up __u) noexcept + { return std::cmp_less(__u, __t); } + + template + constexpr bool + cmp_less_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__u, __t); } + + template + constexpr bool + cmp_greater_equal(_Tp __t, _Up __u) noexcept + { return !std::cmp_less(__t, __u); } + + template + constexpr bool + in_range(_Tp __t) noexcept + { + static_assert(__is_standard_integer<_Up>::value); + static_assert(__is_standard_integer<_Tp>::value); + using __gnu_cxx::__int_traits; + + if constexpr (is_signed_v<_Tp> == is_signed_v<_Up>) + return __int_traits<_Up>::__min <= __t + && __t <= __int_traits<_Up>::__max; + else if constexpr (is_signed_v<_Tp>) + return __t >= 0 + && make_unsigned_t<_Tp>(__t) <= __int_traits<_Up>::__max; + else + return __t <= make_unsigned_t<_Up>(__int_traits<_Up>::__max); + } +#endif // C++20 +#endif // C++17 + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif + +#endif /* _GLIBCXX_UTILITY */ diff --git a/resources/sources/avr-libstdcpp/include/valarray b/resources/sources/avr-libstdcpp/include/valarray new file mode 100644 index 000000000..be2e70dc0 --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/valarray @@ -0,0 +1,1253 @@ +// The template and inlines for the -*- C++ -*- valarray class. + +// Copyright (C) 1997-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file include/valarray + * This is a Standard C++ Library header. + */ + +// Written by Gabriel Dos Reis + +#ifndef _GLIBCXX_VALARRAY +#define _GLIBCXX_VALARRAY 1 + +#pragma GCC system_header + +#include +#include +#include +#include +#if __cplusplus >= 201103L +#include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + template + class _Expr; + + template + class _ValArray; + +namespace __detail +{ + template class _Meta, class _Dom> + struct _UnClos; + + template class _Meta1, + template class _Meta2, + class _Dom1, class _Dom2> + class _BinClos; + + template class _Meta, class _Dom> + class _SClos; + + template class _Meta, class _Dom> + class _GClos; + + template class _Meta, class _Dom> + class _IClos; + + template class _Meta, class _Dom> + class _ValFunClos; + + template class _Meta, class _Dom> + class _RefFunClos; +} // namespace __detail + + using __detail::_UnClos; + using __detail::_BinClos; + using __detail::_SClos; + using __detail::_GClos; + using __detail::_IClos; + using __detail::_ValFunClos; + using __detail::_RefFunClos; + + template class valarray; // An array of type _Tp + class slice; // BLAS-like slice out of an array + template class slice_array; + class gslice; // generalized slice out of an array + template class gslice_array; + template class mask_array; // masked array + template class indirect_array; // indirected array + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @defgroup numeric_arrays Numeric Arrays + * @ingroup numerics + * + * Classes and functions for representing and manipulating arrays of elements. + * @{ + */ + + /** + * @brief Smart array designed to support numeric processing. + * + * A valarray is an array that provides constraints intended to allow for + * effective optimization of numeric array processing by reducing the + * aliasing that can result from pointer representations. It represents a + * one-dimensional array from which different multidimensional subsets can + * be accessed and modified. + * + * @tparam _Tp Type of object in the array. + */ + template + class valarray + { + template + struct _UnaryOp + { + typedef typename __fun<_Op, _Tp>::result_type __rt; + typedef _Expr<_UnClos<_Op, _ValArray, _Tp>, __rt> _Rt; + }; + public: + typedef _Tp value_type; + + // _lib.valarray.cons_ construct/destroy: + /// Construct an empty array. + valarray(); + + /// Construct an array with @a n elements. + explicit valarray(size_t); + + /// Construct an array with @a n elements initialized to @a t. + valarray(const _Tp&, size_t); + + /// Construct an array initialized to the first @a n elements of @a t. + valarray(const _Tp* __restrict__, size_t); + + /// Copy constructor. + valarray(const valarray&); + +#if __cplusplus >= 201103L + /// Move constructor. + valarray(valarray&&) noexcept; +#endif + + /// Construct an array with the same size and values in @a sa. + valarray(const slice_array<_Tp>&); + + /// Construct an array with the same size and values in @a ga. + valarray(const gslice_array<_Tp>&); + + /// Construct an array with the same size and values in @a ma. + valarray(const mask_array<_Tp>&); + + /// Construct an array with the same size and values in @a ia. + valarray(const indirect_array<_Tp>&); + +#if __cplusplus >= 201103L + /// Construct an array with an initializer_list of values. + valarray(initializer_list<_Tp>); +#endif + + template + valarray(const _Expr<_Dom, _Tp>& __e); + + ~valarray() _GLIBCXX_NOEXCEPT; + + // _lib.valarray.assign_ assignment: + /** + * @brief Assign elements to an array. + * + * Assign elements of array to values in @a v. + * + * @param __v Valarray to get values from. + */ + valarray<_Tp>& operator=(const valarray<_Tp>& __v); + +#if __cplusplus >= 201103L + /** + * @brief Move assign elements to an array. + * + * Move assign elements of array to values in @a v. + * + * @param __v Valarray to get values from. + */ + valarray<_Tp>& operator=(valarray<_Tp>&& __v) noexcept; +#endif + + /** + * @brief Assign elements to a value. + * + * Assign all elements of array to @a t. + * + * @param __t Value for elements. + */ + valarray<_Tp>& operator=(const _Tp& __t); + + /** + * @brief Assign elements to an array subset. + * + * Assign elements of array to values in @a sa. Results are undefined + * if @a sa does not have the same size as this array. + * + * @param __sa Array slice to get values from. + */ + valarray<_Tp>& operator=(const slice_array<_Tp>& __sa); + + /** + * @brief Assign elements to an array subset. + * + * Assign elements of array to values in @a ga. Results are undefined + * if @a ga does not have the same size as this array. + * + * @param __ga Array slice to get values from. + */ + valarray<_Tp>& operator=(const gslice_array<_Tp>& __ga); + + /** + * @brief Assign elements to an array subset. + * + * Assign elements of array to values in @a ma. Results are undefined + * if @a ma does not have the same size as this array. + * + * @param __ma Array slice to get values from. + */ + valarray<_Tp>& operator=(const mask_array<_Tp>& __ma); + + /** + * @brief Assign elements to an array subset. + * + * Assign elements of array to values in @a ia. Results are undefined + * if @a ia does not have the same size as this array. + * + * @param __ia Array slice to get values from. + */ + valarray<_Tp>& operator=(const indirect_array<_Tp>& __ia); + +#if __cplusplus >= 201103L + /** + * @brief Assign elements to an initializer_list. + * + * Assign elements of array to values in @a __l. Results are undefined + * if @a __l does not have the same size as this array. + * + * @param __l initializer_list to get values from. + */ + valarray& operator=(initializer_list<_Tp> __l); +#endif + + template valarray<_Tp>& + operator= (const _Expr<_Dom, _Tp>&); + + // _lib.valarray.access_ element access: + /** + * Return a reference to the i'th array element. + * + * @param __i Index of element to return. + * @return Reference to the i'th element. + */ + _Tp& operator[](size_t __i); + + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 389. Const overload of valarray::operator[] returns by value. + const _Tp& operator[](size_t) const; + + // _lib.valarray.sub_ subset operations: + /** + * @brief Return an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the slice argument. The new valarray has the same size + * as the input slice. @see slice. + * + * @param __s The source slice. + * @return New valarray containing elements in @a __s. + */ + _Expr<_SClos<_ValArray, _Tp>, _Tp> operator[](slice __s) const; + + /** + * @brief Return a reference to an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the slice argument. The new valarray has the same size + * as the input slice. @see slice. + * + * @param __s The source slice. + * @return New valarray containing elements in @a __s. + */ + slice_array<_Tp> operator[](slice __s); + + /** + * @brief Return an array subset. + * + * Returns a slice_array referencing the elements of the array + * indicated by the slice argument. @see gslice. + * + * @param __s The source slice. + * @return Slice_array referencing elements indicated by @a __s. + */ + _Expr<_GClos<_ValArray, _Tp>, _Tp> operator[](const gslice& __s) const; + + /** + * @brief Return a reference to an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the gslice argument. The new valarray has + * the same size as the input gslice. @see gslice. + * + * @param __s The source gslice. + * @return New valarray containing elements in @a __s. + */ + gslice_array<_Tp> operator[](const gslice& __s); + + /** + * @brief Return an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the argument. The input is a valarray of bool which + * represents a bitmask indicating which elements should be copied into + * the new valarray. Each element of the array is added to the return + * valarray if the corresponding element of the argument is true. + * + * @param __m The valarray bitmask. + * @return New valarray containing elements indicated by @a __m. + */ + valarray<_Tp> operator[](const valarray& __m) const; + + /** + * @brief Return a reference to an array subset. + * + * Returns a new mask_array referencing the elements of the array + * indicated by the argument. The input is a valarray of bool which + * represents a bitmask indicating which elements are part of the + * subset. Elements of the array are part of the subset if the + * corresponding element of the argument is true. + * + * @param __m The valarray bitmask. + * @return New valarray containing elements indicated by @a __m. + */ + mask_array<_Tp> operator[](const valarray& __m); + + /** + * @brief Return an array subset. + * + * Returns a new valarray containing the elements of the array + * indicated by the argument. The elements in the argument are + * interpreted as the indices of elements of this valarray to copy to + * the return valarray. + * + * @param __i The valarray element index list. + * @return New valarray containing elements in @a __s. + */ + _Expr<_IClos<_ValArray, _Tp>, _Tp> + operator[](const valarray& __i) const; + + /** + * @brief Return a reference to an array subset. + * + * Returns an indirect_array referencing the elements of the array + * indicated by the argument. The elements in the argument are + * interpreted as the indices of elements of this valarray to include + * in the subset. The returned indirect_array refers to these + * elements. + * + * @param __i The valarray element index list. + * @return Indirect_array referencing elements in @a __i. + */ + indirect_array<_Tp> operator[](const valarray& __i); + + // _lib.valarray.unary_ unary operators: + /// Return a new valarray by applying unary + to each element. + typename _UnaryOp<__unary_plus>::_Rt operator+() const; + + /// Return a new valarray by applying unary - to each element. + typename _UnaryOp<__negate>::_Rt operator-() const; + + /// Return a new valarray by applying unary ~ to each element. + typename _UnaryOp<__bitwise_not>::_Rt operator~() const; + + /// Return a new valarray by applying unary ! to each element. + typename _UnaryOp<__logical_not>::_Rt operator!() const; + + // _lib.valarray.cassign_ computed assignment: + /// Multiply each element of array by @a t. + valarray<_Tp>& operator*=(const _Tp&); + + /// Divide each element of array by @a t. + valarray<_Tp>& operator/=(const _Tp&); + + /// Set each element e of array to e % @a t. + valarray<_Tp>& operator%=(const _Tp&); + + /// Add @a t to each element of array. + valarray<_Tp>& operator+=(const _Tp&); + + /// Subtract @a t to each element of array. + valarray<_Tp>& operator-=(const _Tp&); + + /// Set each element e of array to e ^ @a t. + valarray<_Tp>& operator^=(const _Tp&); + + /// Set each element e of array to e & @a t. + valarray<_Tp>& operator&=(const _Tp&); + + /// Set each element e of array to e | @a t. + valarray<_Tp>& operator|=(const _Tp&); + + /// Left shift each element e of array by @a t bits. + valarray<_Tp>& operator<<=(const _Tp&); + + /// Right shift each element e of array by @a t bits. + valarray<_Tp>& operator>>=(const _Tp&); + + /// Multiply elements of array by corresponding elements of @a v. + valarray<_Tp>& operator*=(const valarray<_Tp>&); + + /// Divide elements of array by corresponding elements of @a v. + valarray<_Tp>& operator/=(const valarray<_Tp>&); + + /// Modulo elements of array by corresponding elements of @a v. + valarray<_Tp>& operator%=(const valarray<_Tp>&); + + /// Add corresponding elements of @a v to elements of array. + valarray<_Tp>& operator+=(const valarray<_Tp>&); + + /// Subtract corresponding elements of @a v from elements of array. + valarray<_Tp>& operator-=(const valarray<_Tp>&); + + /// Logical xor corresponding elements of @a v with elements of array. + valarray<_Tp>& operator^=(const valarray<_Tp>&); + + /// Logical or corresponding elements of @a v with elements of array. + valarray<_Tp>& operator|=(const valarray<_Tp>&); + + /// Logical and corresponding elements of @a v with elements of array. + valarray<_Tp>& operator&=(const valarray<_Tp>&); + + /// Left shift elements of array by corresponding elements of @a v. + valarray<_Tp>& operator<<=(const valarray<_Tp>&); + + /// Right shift elements of array by corresponding elements of @a v. + valarray<_Tp>& operator>>=(const valarray<_Tp>&); + + template + valarray<_Tp>& operator*=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator/=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator%=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator+=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator-=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator^=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator|=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator&=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator<<=(const _Expr<_Dom, _Tp>&); + template + valarray<_Tp>& operator>>=(const _Expr<_Dom, _Tp>&); + + // _lib.valarray.members_ member functions: +#if __cplusplus >= 201103L + /// Swap. + void swap(valarray<_Tp>& __v) noexcept; +#endif + + /// Return the number of elements in array. + size_t size() const; + + /** + * @brief Return the sum of all elements in the array. + * + * Accumulates the sum of all elements into a Tp using +=. The order + * of adding the elements is unspecified. + */ + _Tp sum() const; + + /// Return the minimum element using operator<(). + _Tp min() const; + + /// Return the maximum element using operator<(). + _Tp max() const; + + /** + * @brief Return a shifted array. + * + * A new valarray is constructed as a copy of this array with elements + * in shifted positions. For an element with index i, the new position + * is i - n. The new valarray has the same size as the current one. + * New elements without a value are set to 0. Elements whose new + * position is outside the bounds of the array are discarded. + * + * Positive arguments shift toward index 0, discarding elements [0, n). + * Negative arguments discard elements from the top of the array. + * + * @param __n Number of element positions to shift. + * @return New valarray with elements in shifted positions. + */ + valarray<_Tp> shift (int __n) const; + + /** + * @brief Return a rotated array. + * + * A new valarray is constructed as a copy of this array with elements + * in shifted positions. For an element with index i, the new position + * is (i - n) % size(). The new valarray has the same size as the + * current one. Elements that are shifted beyond the array bounds are + * shifted into the other end of the array. No elements are lost. + * + * Positive arguments shift toward index 0, wrapping around the top. + * Negative arguments shift towards the top, wrapping around to 0. + * + * @param __n Number of element positions to rotate. + * @return New valarray with elements in shifted positions. + */ + valarray<_Tp> cshift(int __n) const; + + /** + * @brief Apply a function to the array. + * + * Returns a new valarray with elements assigned to the result of + * applying func to the corresponding element of this array. The new + * array has the same size as this one. + * + * @param func Function of Tp returning Tp to apply. + * @return New valarray with transformed elements. + */ + _Expr<_ValFunClos<_ValArray, _Tp>, _Tp> apply(_Tp func(_Tp)) const; + + /** + * @brief Apply a function to the array. + * + * Returns a new valarray with elements assigned to the result of + * applying func to the corresponding element of this array. The new + * array has the same size as this one. + * + * @param func Function of const Tp& returning Tp to apply. + * @return New valarray with transformed elements. + */ + _Expr<_RefFunClos<_ValArray, _Tp>, _Tp> apply(_Tp func(const _Tp&)) const; + + /** + * @brief Resize array. + * + * Resize this array to @a size and set all elements to @a c. All + * references and iterators are invalidated. + * + * @param __size New array size. + * @param __c New value for all elements. + */ + void resize(size_t __size, _Tp __c = _Tp()); + + private: + size_t _M_size; + _Tp* __restrict__ _M_data; + + friend class _Array<_Tp>; + }; + +#if __cpp_deduction_guides >= 201606 + template + valarray(const _Tp(&)[_Nm], size_t) -> valarray<_Tp>; +#endif + + template + inline const _Tp& + valarray<_Tp>::operator[](size_t __i) const + { + __glibcxx_requires_subscript(__i); + return _M_data[__i]; + } + + template + inline _Tp& + valarray<_Tp>::operator[](size_t __i) + { + __glibcxx_requires_subscript(__i); + return _M_data[__i]; + } + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#include +#include +#include +#include +#include +#include + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + + /** + * @addtogroup numeric_arrays + * @{ + */ + + template + inline + valarray<_Tp>::valarray() : _M_size(0), _M_data(0) {} + + template + inline + valarray<_Tp>::valarray(size_t __n) + : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) + { std::__valarray_default_construct(_M_data, _M_data + __n); } + + template + inline + valarray<_Tp>::valarray(const _Tp& __t, size_t __n) + : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) + { std::__valarray_fill_construct(_M_data, _M_data + __n, __t); } + + template + inline + valarray<_Tp>::valarray(const _Tp* __restrict__ __p, size_t __n) + : _M_size(__n), _M_data(__valarray_get_storage<_Tp>(__n)) + { + __glibcxx_assert(__p != 0 || __n == 0); + std::__valarray_copy_construct(__p, __p + __n, _M_data); + } + + template + inline + valarray<_Tp>::valarray(const valarray<_Tp>& __v) + : _M_size(__v._M_size), _M_data(__valarray_get_storage<_Tp>(__v._M_size)) + { std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size, + _M_data); } + +#if __cplusplus >= 201103L + template + inline + valarray<_Tp>::valarray(valarray<_Tp>&& __v) noexcept + : _M_size(__v._M_size), _M_data(__v._M_data) + { + __v._M_size = 0; + __v._M_data = 0; + } +#endif + + template + inline + valarray<_Tp>::valarray(const slice_array<_Tp>& __sa) + : _M_size(__sa._M_sz), _M_data(__valarray_get_storage<_Tp>(__sa._M_sz)) + { + std::__valarray_copy_construct + (__sa._M_array, __sa._M_sz, __sa._M_stride, _Array<_Tp>(_M_data)); + } + + template + inline + valarray<_Tp>::valarray(const gslice_array<_Tp>& __ga) + : _M_size(__ga._M_index.size()), + _M_data(__valarray_get_storage<_Tp>(_M_size)) + { + std::__valarray_copy_construct + (__ga._M_array, _Array(__ga._M_index), + _Array<_Tp>(_M_data), _M_size); + } + + template + inline + valarray<_Tp>::valarray(const mask_array<_Tp>& __ma) + : _M_size(__ma._M_sz), _M_data(__valarray_get_storage<_Tp>(__ma._M_sz)) + { + std::__valarray_copy_construct + (__ma._M_array, __ma._M_mask, _Array<_Tp>(_M_data), _M_size); + } + + template + inline + valarray<_Tp>::valarray(const indirect_array<_Tp>& __ia) + : _M_size(__ia._M_sz), _M_data(__valarray_get_storage<_Tp>(__ia._M_sz)) + { + std::__valarray_copy_construct + (__ia._M_array, __ia._M_index, _Array<_Tp>(_M_data), _M_size); + } + +#if __cplusplus >= 201103L + template + inline + valarray<_Tp>::valarray(initializer_list<_Tp> __l) + : _M_size(__l.size()), _M_data(__valarray_get_storage<_Tp>(__l.size())) + { std::__valarray_copy_construct(__l.begin(), __l.end(), _M_data); } +#endif + + template template + inline + valarray<_Tp>::valarray(const _Expr<_Dom, _Tp>& __e) + : _M_size(__e.size()), _M_data(__valarray_get_storage<_Tp>(_M_size)) + { std::__valarray_copy_construct(__e, _M_size, _Array<_Tp>(_M_data)); } + + template + inline + valarray<_Tp>::~valarray() _GLIBCXX_NOEXCEPT + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const valarray<_Tp>& __v) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 630. arrays of valarray. + if (_M_size == __v._M_size) + std::__valarray_copy(__v._M_data, _M_size, _M_data); + else + { + if (_M_data) + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + _M_size = __v._M_size; + _M_data = __valarray_get_storage<_Tp>(_M_size); + std::__valarray_copy_construct(__v._M_data, __v._M_data + _M_size, + _M_data); + } + return *this; + } + +#if __cplusplus >= 201103L + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(valarray<_Tp>&& __v) noexcept + { + if (_M_data) + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + _M_size = __v._M_size; + _M_data = __v._M_data; + __v._M_size = 0; + __v._M_data = 0; + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(initializer_list<_Tp> __l) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 630. arrays of valarray. + if (_M_size == __l.size()) + std::__valarray_copy(__l.begin(), __l.size(), _M_data); + else + { + if (_M_data) + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + _M_size = __l.size(); + _M_data = __valarray_get_storage<_Tp>(_M_size); + std::__valarray_copy_construct(__l.begin(), __l.begin() + _M_size, + _M_data); + } + return *this; + } +#endif + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const _Tp& __t) + { + std::__valarray_fill(_M_data, _M_size, __t); + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const slice_array<_Tp>& __sa) + { + __glibcxx_assert(_M_size == __sa._M_sz); + std::__valarray_copy(__sa._M_array, __sa._M_sz, + __sa._M_stride, _Array<_Tp>(_M_data)); + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const gslice_array<_Tp>& __ga) + { + __glibcxx_assert(_M_size == __ga._M_index.size()); + std::__valarray_copy(__ga._M_array, _Array(__ga._M_index), + _Array<_Tp>(_M_data), _M_size); + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const mask_array<_Tp>& __ma) + { + __glibcxx_assert(_M_size == __ma._M_sz); + std::__valarray_copy(__ma._M_array, __ma._M_mask, + _Array<_Tp>(_M_data), _M_size); + return *this; + } + + template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const indirect_array<_Tp>& __ia) + { + __glibcxx_assert(_M_size == __ia._M_sz); + std::__valarray_copy(__ia._M_array, __ia._M_index, + _Array<_Tp>(_M_data), _M_size); + return *this; + } + + template template + inline valarray<_Tp>& + valarray<_Tp>::operator=(const _Expr<_Dom, _Tp>& __e) + { + // _GLIBCXX_RESOLVE_LIB_DEFECTS + // 630. arrays of valarray. + if (_M_size == __e.size()) + std::__valarray_copy(__e, _M_size, _Array<_Tp>(_M_data)); + else + { + if (_M_data) + { + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + std::__valarray_release_memory(_M_data); + } + _M_size = __e.size(); + _M_data = __valarray_get_storage<_Tp>(_M_size); + std::__valarray_copy_construct(__e, _M_size, _Array<_Tp>(_M_data)); + } + return *this; + } + + template + inline _Expr<_SClos<_ValArray,_Tp>, _Tp> + valarray<_Tp>::operator[](slice __s) const + { + typedef _SClos<_ValArray,_Tp> _Closure; + return _Expr<_Closure, _Tp>(_Closure (_Array<_Tp>(_M_data), __s)); + } + + template + inline slice_array<_Tp> + valarray<_Tp>::operator[](slice __s) + { return slice_array<_Tp>(_Array<_Tp>(_M_data), __s); } + + template + inline _Expr<_GClos<_ValArray,_Tp>, _Tp> + valarray<_Tp>::operator[](const gslice& __gs) const + { + typedef _GClos<_ValArray,_Tp> _Closure; + return _Expr<_Closure, _Tp> + (_Closure(_Array<_Tp>(_M_data), __gs._M_index->_M_index)); + } + + template + inline gslice_array<_Tp> + valarray<_Tp>::operator[](const gslice& __gs) + { + return gslice_array<_Tp> + (_Array<_Tp>(_M_data), __gs._M_index->_M_index); + } + + template + inline valarray<_Tp> + valarray<_Tp>::operator[](const valarray& __m) const + { + size_t __s = 0; + size_t __e = __m.size(); + for (size_t __i=0; __i<__e; ++__i) + if (__m[__i]) ++__s; + return valarray<_Tp>(mask_array<_Tp>(_Array<_Tp>(_M_data), __s, + _Array (__m))); + } + + template + inline mask_array<_Tp> + valarray<_Tp>::operator[](const valarray& __m) + { + size_t __s = 0; + size_t __e = __m.size(); + for (size_t __i=0; __i<__e; ++__i) + if (__m[__i]) ++__s; + return mask_array<_Tp>(_Array<_Tp>(_M_data), __s, _Array(__m)); + } + + template + inline _Expr<_IClos<_ValArray,_Tp>, _Tp> + valarray<_Tp>::operator[](const valarray& __i) const + { + typedef _IClos<_ValArray,_Tp> _Closure; + return _Expr<_Closure, _Tp>(_Closure(*this, __i)); + } + + template + inline indirect_array<_Tp> + valarray<_Tp>::operator[](const valarray& __i) + { + return indirect_array<_Tp>(_Array<_Tp>(_M_data), __i.size(), + _Array(__i)); + } + +#if __cplusplus >= 201103L + template + inline void + valarray<_Tp>::swap(valarray<_Tp>& __v) noexcept + { + std::swap(_M_size, __v._M_size); + std::swap(_M_data, __v._M_data); + } +#endif + + template + inline size_t + valarray<_Tp>::size() const + { return _M_size; } + + template + inline _Tp + valarray<_Tp>::sum() const + { + __glibcxx_assert(_M_size > 0); + return std::__valarray_sum(_M_data, _M_data + _M_size); + } + + template + inline valarray<_Tp> + valarray<_Tp>::shift(int __n) const + { + valarray<_Tp> __ret; + + if (_M_size == 0) + return __ret; + + _Tp* __restrict__ __tmp_M_data = + std::__valarray_get_storage<_Tp>(_M_size); + + if (__n == 0) + std::__valarray_copy_construct(_M_data, + _M_data + _M_size, __tmp_M_data); + else if (__n > 0) // shift left + { + if (size_t(__n) > _M_size) + __n = int(_M_size); + + std::__valarray_copy_construct(_M_data + __n, + _M_data + _M_size, __tmp_M_data); + std::__valarray_default_construct(__tmp_M_data + _M_size - __n, + __tmp_M_data + _M_size); + } + else // shift right + { + if (-size_t(__n) > _M_size) + __n = -int(_M_size); + + std::__valarray_copy_construct(_M_data, _M_data + _M_size + __n, + __tmp_M_data - __n); + std::__valarray_default_construct(__tmp_M_data, + __tmp_M_data - __n); + } + + __ret._M_size = _M_size; + __ret._M_data = __tmp_M_data; + return __ret; + } + + template + inline valarray<_Tp> + valarray<_Tp>::cshift(int __n) const + { + valarray<_Tp> __ret; + + if (_M_size == 0) + return __ret; + + _Tp* __restrict__ __tmp_M_data = + std::__valarray_get_storage<_Tp>(_M_size); + + if (__n == 0) + std::__valarray_copy_construct(_M_data, + _M_data + _M_size, __tmp_M_data); + else if (__n > 0) // cshift left + { + if (size_t(__n) > _M_size) + __n = int(__n % _M_size); + + std::__valarray_copy_construct(_M_data, _M_data + __n, + __tmp_M_data + _M_size - __n); + std::__valarray_copy_construct(_M_data + __n, _M_data + _M_size, + __tmp_M_data); + } + else // cshift right + { + if (-size_t(__n) > _M_size) + __n = -int(-size_t(__n) % _M_size); + + std::__valarray_copy_construct(_M_data + _M_size + __n, + _M_data + _M_size, __tmp_M_data); + std::__valarray_copy_construct(_M_data, _M_data + _M_size + __n, + __tmp_M_data - __n); + } + + __ret._M_size = _M_size; + __ret._M_data = __tmp_M_data; + return __ret; + } + + template + inline void + valarray<_Tp>::resize(size_t __n, _Tp __c) + { + // This complication is so to make valarray > work + // even though it is not required by the standard. Nobody should + // be saying valarray > anyway. See the specs. + std::__valarray_destroy_elements(_M_data, _M_data + _M_size); + if (_M_size != __n) + { + std::__valarray_release_memory(_M_data); + _M_size = __n; + _M_data = __valarray_get_storage<_Tp>(__n); + } + std::__valarray_fill_construct(_M_data, _M_data + __n, __c); + } + + template + inline _Tp + valarray<_Tp>::min() const + { + __glibcxx_assert(_M_size > 0); + return *std::min_element(_M_data, _M_data + _M_size); + } + + template + inline _Tp + valarray<_Tp>::max() const + { + __glibcxx_assert(_M_size > 0); + return *std::max_element(_M_data, _M_data + _M_size); + } + + template + inline _Expr<_ValFunClos<_ValArray, _Tp>, _Tp> + valarray<_Tp>::apply(_Tp func(_Tp)) const + { + typedef _ValFunClos<_ValArray, _Tp> _Closure; + return _Expr<_Closure, _Tp>(_Closure(*this, func)); + } + + template + inline _Expr<_RefFunClos<_ValArray, _Tp>, _Tp> + valarray<_Tp>::apply(_Tp func(const _Tp &)) const + { + typedef _RefFunClos<_ValArray, _Tp> _Closure; + return _Expr<_Closure, _Tp>(_Closure(*this, func)); + } + +#define _DEFINE_VALARRAY_UNARY_OPERATOR(_Op, _Name) \ + template \ + inline typename valarray<_Tp>::template _UnaryOp<_Name>::_Rt \ + valarray<_Tp>::operator _Op() const \ + { \ + typedef _UnClos<_Name, _ValArray, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(*this)); \ + } + + _DEFINE_VALARRAY_UNARY_OPERATOR(+, __unary_plus) + _DEFINE_VALARRAY_UNARY_OPERATOR(-, __negate) + _DEFINE_VALARRAY_UNARY_OPERATOR(~, __bitwise_not) + _DEFINE_VALARRAY_UNARY_OPERATOR (!, __logical_not) + +#undef _DEFINE_VALARRAY_UNARY_OPERATOR + +#define _DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(_Op, _Name) \ + template \ + inline valarray<_Tp>& \ + valarray<_Tp>::operator _Op##=(const _Tp &__t) \ + { \ + _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, __t); \ + return *this; \ + } \ + \ + template \ + inline valarray<_Tp>& \ + valarray<_Tp>::operator _Op##=(const valarray<_Tp> &__v) \ + { \ + __glibcxx_assert(_M_size == __v._M_size); \ + _Array_augmented_##_Name(_Array<_Tp>(_M_data), _M_size, \ + _Array<_Tp>(__v._M_data)); \ + return *this; \ + } + +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(+, __plus) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(-, __minus) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(*, __multiplies) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(/, __divides) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(%, __modulus) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(^, __bitwise_xor) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(&, __bitwise_and) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(|, __bitwise_or) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(<<, __shift_left) +_DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT(>>, __shift_right) + +#undef _DEFINE_VALARRAY_AUGMENTED_ASSIGNMENT + +#define _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(_Op, _Name) \ + template template \ + inline valarray<_Tp>& \ + valarray<_Tp>::operator _Op##=(const _Expr<_Dom, _Tp>& __e) \ + { \ + _Array_augmented_##_Name(_Array<_Tp>(_M_data), __e, _M_size); \ + return *this; \ + } + +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(+, __plus) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(-, __minus) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(*, __multiplies) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(/, __divides) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(%, __modulus) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(^, __bitwise_xor) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(&, __bitwise_and) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(|, __bitwise_or) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(<<, __shift_left) +_DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT(>>, __shift_right) + +#undef _DEFINE_VALARRAY_EXPR_AUGMENTED_ASSIGNMENT + + +#define _DEFINE_BINARY_OPERATOR(_Op, _Name) \ + template \ + inline _Expr<_BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ + operator _Op(const valarray<_Tp>& __v, const valarray<_Tp>& __w) \ + { \ + __glibcxx_assert(__v.size() == __w.size()); \ + typedef _BinClos<_Name, _ValArray, _ValArray, _Tp, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__v, __w)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _ValArray,_Constant, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ + operator _Op(const valarray<_Tp>& __v, \ + const typename valarray<_Tp>::value_type& __t) \ + { \ + typedef _BinClos<_Name, _ValArray, _Constant, _Tp, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__v, __t)); \ + } \ + \ + template \ + inline _Expr<_BinClos<_Name, _Constant, _ValArray, _Tp, _Tp>, \ + typename __fun<_Name, _Tp>::result_type> \ + operator _Op(const typename valarray<_Tp>::value_type& __t, \ + const valarray<_Tp>& __v) \ + { \ + typedef _BinClos<_Name, _Constant, _ValArray, _Tp, _Tp> _Closure; \ + typedef typename __fun<_Name, _Tp>::result_type _Rt; \ + return _Expr<_Closure, _Rt>(_Closure(__t, __v)); \ + } + +_DEFINE_BINARY_OPERATOR(+, __plus) +_DEFINE_BINARY_OPERATOR(-, __minus) +_DEFINE_BINARY_OPERATOR(*, __multiplies) +_DEFINE_BINARY_OPERATOR(/, __divides) +_DEFINE_BINARY_OPERATOR(%, __modulus) +_DEFINE_BINARY_OPERATOR(^, __bitwise_xor) +_DEFINE_BINARY_OPERATOR(&, __bitwise_and) +_DEFINE_BINARY_OPERATOR(|, __bitwise_or) +_DEFINE_BINARY_OPERATOR(<<, __shift_left) +_DEFINE_BINARY_OPERATOR(>>, __shift_right) +_DEFINE_BINARY_OPERATOR(&&, __logical_and) +_DEFINE_BINARY_OPERATOR(||, __logical_or) +_DEFINE_BINARY_OPERATOR(==, __equal_to) +_DEFINE_BINARY_OPERATOR(!=, __not_equal_to) +_DEFINE_BINARY_OPERATOR(<, __less) +_DEFINE_BINARY_OPERATOR(>, __greater) +_DEFINE_BINARY_OPERATOR(<=, __less_equal) +_DEFINE_BINARY_OPERATOR(>=, __greater_equal) + +#undef _DEFINE_BINARY_OPERATOR + +#if __cplusplus >= 201103L + /** + * @brief Return an iterator pointing to the first element of + * the valarray. + * @param __va valarray. + */ + template + inline _Tp* + begin(valarray<_Tp>& __va) + { return std::__addressof(__va[0]); } + + /** + * @brief Return an iterator pointing to the first element of + * the const valarray. + * @param __va valarray. + */ + template + inline const _Tp* + begin(const valarray<_Tp>& __va) + { return std::__addressof(__va[0]); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the valarray. + * @param __va valarray. + */ + template + inline _Tp* + end(valarray<_Tp>& __va) + { return std::__addressof(__va[0]) + __va.size(); } + + /** + * @brief Return an iterator pointing to one past the last element of + * the const valarray. + * @param __va valarray. + */ + template + inline const _Tp* + end(const valarray<_Tp>& __va) + { return std::__addressof(__va[0]) + __va.size(); } +#endif // C++11 + + // @} group numeric_arrays + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace + +#endif /* _GLIBCXX_VALARRAY */ diff --git a/resources/sources/avr-libstdcpp/include/variant b/resources/sources/avr-libstdcpp/include/variant new file mode 100644 index 000000000..3a0d1c1ce --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/variant @@ -0,0 +1,1775 @@ +// -*- C++ -*- + +// Copyright (C) 2016-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file variant + * This is the C++ Library header. + */ + +#ifndef _GLIBCXX_VARIANT +#define _GLIBCXX_VARIANT 1 + +#pragma GCC system_header + +#if __cplusplus >= 201703L + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#if __cplusplus > 201703L +# include +#endif + +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +namespace __detail +{ +namespace __variant +{ + template + struct _Nth_type; + + template + struct _Nth_type<_Np, _First, _Rest...> + : _Nth_type<_Np-1, _Rest...> { }; + + template + struct _Nth_type<0, _First, _Rest...> + { using type = _First; }; + +} // namespace __variant +} // namespace __detail + +#define __cpp_lib_variant 201606L + + template class tuple; + template class variant; + template struct hash; + + template + struct variant_size; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size : variant_size<_Variant> {}; + + template + struct variant_size> + : std::integral_constant {}; + + template + inline constexpr size_t variant_size_v = variant_size<_Variant>::value; + + template + struct variant_alternative; + + template + struct variant_alternative<_Np, variant<_First, _Rest...>> + : variant_alternative<_Np-1, variant<_Rest...>> {}; + + template + struct variant_alternative<0, variant<_First, _Rest...>> + { using type = _First; }; + + template + using variant_alternative_t = + typename variant_alternative<_Np, _Variant>::type; + + template + struct variant_alternative<_Np, const _Variant> + { using type = add_const_t>; }; + + template + struct variant_alternative<_Np, volatile _Variant> + { using type = add_volatile_t>; }; + + template + struct variant_alternative<_Np, const volatile _Variant> + { using type = add_cv_t>; }; + + inline constexpr size_t variant_npos = -1; + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>& + get(variant<_Types...>&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>&& + get(variant<_Types...>&&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>> const& + get(const variant<_Types...>&); + + template + constexpr variant_alternative_t<_Np, variant<_Types...>> const&& + get(const variant<_Types...>&&); + + template + constexpr decltype(auto) + __do_visit(_Visitor&& __visitor, _Variants&&... __variants); + + template + decltype(auto) + __variant_cast(_Tp&& __rhs) + { + if constexpr (is_lvalue_reference_v<_Tp>) + { + if constexpr (is_const_v>) + return static_cast&>(__rhs); + else + return static_cast&>(__rhs); + } + else + return static_cast&&>(__rhs); + } + +namespace __detail +{ +namespace __variant +{ + // Returns the first appearence of _Tp in _Types. + // Returns sizeof...(_Types) if _Tp is not in _Types. + template + struct __index_of : std::integral_constant {}; + + template + inline constexpr size_t __index_of_v = __index_of<_Tp, _Types...>::value; + + template + struct __index_of<_Tp, _First, _Rest...> : + std::integral_constant + ? 0 : __index_of_v<_Tp, _Rest...> + 1> {}; + + // used for raw visitation + struct __variant_cookie {}; + // used for raw visitation with indices passed in + struct __variant_idx_cookie { using type = __variant_idx_cookie; }; + // Used to enable deduction (and same-type checking) for std::visit: + template struct __deduce_visit_result { }; + + // Visit variants that might be valueless. + template + constexpr void + __raw_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + std::__do_visit<__variant_cookie>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + + // Visit variants that might be valueless, passing indices to the visitor. + template + constexpr void + __raw_idx_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + std::__do_visit<__variant_idx_cookie>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + + // _Uninitialized is guaranteed to be a trivially destructible type, + // even if T is not. + template> + struct _Uninitialized; + + template + struct _Uninitialized<_Type, true> + { + template + constexpr + _Uninitialized(in_place_index_t<0>, _Args&&... __args) + : _M_storage(std::forward<_Args>(__args)...) + { } + + constexpr const _Type& _M_get() const & noexcept + { return _M_storage; } + + constexpr _Type& _M_get() & noexcept + { return _M_storage; } + + constexpr const _Type&& _M_get() const && noexcept + { return std::move(_M_storage); } + + constexpr _Type&& _M_get() && noexcept + { return std::move(_M_storage); } + + _Type _M_storage; + }; + + template + struct _Uninitialized<_Type, false> + { + template + constexpr + _Uninitialized(in_place_index_t<0>, _Args&&... __args) + { + ::new ((void*)std::addressof(_M_storage)) + _Type(std::forward<_Args>(__args)...); + } + + const _Type& _M_get() const & noexcept + { return *_M_storage._M_ptr(); } + + _Type& _M_get() & noexcept + { return *_M_storage._M_ptr(); } + + const _Type&& _M_get() const && noexcept + { return std::move(*_M_storage._M_ptr()); } + + _Type&& _M_get() && noexcept + { return std::move(*_M_storage._M_ptr()); } + + __gnu_cxx::__aligned_membuf<_Type> _M_storage; + }; + + template + constexpr decltype(auto) + __get(in_place_index_t<0>, _Union&& __u) noexcept + { return std::forward<_Union>(__u)._M_first._M_get(); } + + template + constexpr decltype(auto) + __get(in_place_index_t<_Np>, _Union&& __u) noexcept + { + return __variant::__get(in_place_index<_Np-1>, + std::forward<_Union>(__u)._M_rest); + } + + // Returns the typed storage for __v. + template + constexpr decltype(auto) + __get(_Variant&& __v) noexcept + { + return __variant::__get(std::in_place_index<_Np>, + std::forward<_Variant>(__v)._M_u); + } + + template + struct _Traits + { + static constexpr bool _S_default_ctor = + is_default_constructible_v::type>; + static constexpr bool _S_copy_ctor = + (is_copy_constructible_v<_Types> && ...); + static constexpr bool _S_move_ctor = + (is_move_constructible_v<_Types> && ...); + static constexpr bool _S_copy_assign = + _S_copy_ctor + && (is_copy_assignable_v<_Types> && ...); + static constexpr bool _S_move_assign = + _S_move_ctor + && (is_move_assignable_v<_Types> && ...); + + static constexpr bool _S_trivial_dtor = + (is_trivially_destructible_v<_Types> && ...); + static constexpr bool _S_trivial_copy_ctor = + (is_trivially_copy_constructible_v<_Types> && ...); + static constexpr bool _S_trivial_move_ctor = + (is_trivially_move_constructible_v<_Types> && ...); + static constexpr bool _S_trivial_copy_assign = + _S_trivial_dtor && _S_trivial_copy_ctor + && (is_trivially_copy_assignable_v<_Types> && ...); + static constexpr bool _S_trivial_move_assign = + _S_trivial_dtor && _S_trivial_move_ctor + && (is_trivially_move_assignable_v<_Types> && ...); + + // The following nothrow traits are for non-trivial SMFs. Trivial SMFs + // are always nothrow. + static constexpr bool _S_nothrow_default_ctor = + is_nothrow_default_constructible_v< + typename _Nth_type<0, _Types...>::type>; + static constexpr bool _S_nothrow_copy_ctor = false; + static constexpr bool _S_nothrow_move_ctor = + (is_nothrow_move_constructible_v<_Types> && ...); + static constexpr bool _S_nothrow_copy_assign = false; + static constexpr bool _S_nothrow_move_assign = + _S_nothrow_move_ctor + && (is_nothrow_move_assignable_v<_Types> && ...); + }; + + // Defines members and ctors. + template + union _Variadic_union { }; + + template + union _Variadic_union<_First, _Rest...> + { + constexpr _Variadic_union() : _M_rest() { } + + template + constexpr _Variadic_union(in_place_index_t<0>, _Args&&... __args) + : _M_first(in_place_index<0>, std::forward<_Args>(__args)...) + { } + + template + constexpr _Variadic_union(in_place_index_t<_Np>, _Args&&... __args) + : _M_rest(in_place_index<_Np-1>, std::forward<_Args>(__args)...) + { } + + _Uninitialized<_First> _M_first; + _Variadic_union<_Rest...> _M_rest; + }; + + // _Never_valueless_alt is true for variant alternatives that can + // always be placed in a variant without it becoming valueless. + + // For suitably-small, trivially copyable types we can create temporaries + // on the stack and then memcpy them into place. + template + struct _Never_valueless_alt + : __and_, is_trivially_copyable<_Tp>> + { }; + + // Specialize _Never_valueless_alt for other types which have a + // non-throwing and cheap move construction and move assignment operator, + // so that emplacing the type will provide the strong exception-safety + // guarantee, by creating and moving a temporary. + // Whether _Never_valueless_alt is true or not affects the ABI of a + // variant using that alternative, so we can't change the value later! + + // True if every alternative in _Types... can be emplaced in a variant + // without it becoming valueless. If this is true, variant<_Types...> + // can never be valueless, which enables some minor optimizations. + template + constexpr bool __never_valueless() + { + return _Traits<_Types...>::_S_move_assign + && (_Never_valueless_alt<_Types>::value && ...); + } + + // Defines index and the dtor, possibly trivial. + template + struct _Variant_storage; + + template + using __select_index = + typename __select_int::_Select_int_base::type::value_type; + + template + struct _Variant_storage + { + constexpr + _Variant_storage() + : _M_index(static_cast<__index_type>(variant_npos)) + { } + + template + constexpr + _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) + : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), + _M_index{_Np} + { } + + void _M_reset() + { + if (!_M_valid()) [[unlikely]] + return; + + std::__do_visit([](auto&& __this_mem) mutable + { + std::_Destroy(std::__addressof(__this_mem)); + }, __variant_cast<_Types...>(*this)); + + _M_index = static_cast<__index_type>(variant_npos); + } + + ~_Variant_storage() + { _M_reset(); } + + void* + _M_storage() const noexcept + { + return const_cast(static_cast( + std::addressof(_M_u))); + } + + constexpr bool + _M_valid() const noexcept + { + if constexpr (__variant::__never_valueless<_Types...>()) + return true; + return this->_M_index != __index_type(variant_npos); + } + + _Variadic_union<_Types...> _M_u; + using __index_type = __select_index<_Types...>; + __index_type _M_index; + }; + + template + struct _Variant_storage + { + constexpr + _Variant_storage() + : _M_index(static_cast<__index_type>(variant_npos)) + { } + + template + constexpr + _Variant_storage(in_place_index_t<_Np>, _Args&&... __args) + : _M_u(in_place_index<_Np>, std::forward<_Args>(__args)...), + _M_index{_Np} + { } + + void _M_reset() noexcept + { _M_index = static_cast<__index_type>(variant_npos); } + + void* + _M_storage() const noexcept + { + return const_cast(static_cast( + std::addressof(_M_u))); + } + + constexpr bool + _M_valid() const noexcept + { + if constexpr (__variant::__never_valueless<_Types...>()) + return true; + return this->_M_index != static_cast<__index_type>(variant_npos); + } + + _Variadic_union<_Types...> _M_u; + using __index_type = __select_index<_Types...>; + __index_type _M_index; + }; + + template + using _Variant_storage_alias = + _Variant_storage<_Traits<_Types...>::_S_trivial_dtor, _Types...>; + + template + void __variant_construct_single(_Tp&& __lhs, _Up&& __rhs_mem) + { + void* __storage = std::addressof(__lhs._M_u); + using _Type = remove_reference_t; + if constexpr (!is_same_v<_Type, __variant_cookie>) + ::new (__storage) + _Type(std::forward(__rhs_mem)); + } + + template + void __variant_construct(_Tp&& __lhs, _Up&& __rhs) + { + __lhs._M_index = __rhs._M_index; + __variant::__raw_visit([&__lhs](auto&& __rhs_mem) mutable + { + __variant_construct_single(std::forward<_Tp>(__lhs), + std::forward(__rhs_mem)); + }, __variant_cast<_Types...>(std::forward<_Up>(__rhs))); + } + + // The following are (Copy|Move) (ctor|assign) layers for forwarding + // triviality and handling non-trivial SMF behaviors. + + template + struct _Copy_ctor_base : _Variant_storage_alias<_Types...> + { + using _Base = _Variant_storage_alias<_Types...>; + using _Base::_Base; + + _Copy_ctor_base(const _Copy_ctor_base& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_copy_ctor) + { + __variant_construct<_Types...>(*this, __rhs); + } + + _Copy_ctor_base(_Copy_ctor_base&&) = default; + _Copy_ctor_base& operator=(const _Copy_ctor_base&) = default; + _Copy_ctor_base& operator=(_Copy_ctor_base&&) = default; + }; + + template + struct _Copy_ctor_base : _Variant_storage_alias<_Types...> + { + using _Base = _Variant_storage_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Copy_ctor_alias = + _Copy_ctor_base<_Traits<_Types...>::_S_trivial_copy_ctor, _Types...>; + + template + struct _Move_ctor_base : _Copy_ctor_alias<_Types...> + { + using _Base = _Copy_ctor_alias<_Types...>; + using _Base::_Base; + + _Move_ctor_base(_Move_ctor_base&& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_move_ctor) + { + __variant_construct<_Types...>(*this, std::move(__rhs)); + } + + template + void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs) + { + this->_M_reset(); + __variant_construct_single(*this, std::forward<_Up>(__rhs)); + this->_M_index = __rhs_index; + } + + template + void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs) + { + this->_M_reset(); + __variant_construct_single(*this, __rhs); + this->_M_index = __rhs_index; + } + + _Move_ctor_base(const _Move_ctor_base&) = default; + _Move_ctor_base& operator=(const _Move_ctor_base&) = default; + _Move_ctor_base& operator=(_Move_ctor_base&&) = default; + }; + + template + struct _Move_ctor_base : _Copy_ctor_alias<_Types...> + { + using _Base = _Copy_ctor_alias<_Types...>; + using _Base::_Base; + + template + void _M_destructive_move(unsigned short __rhs_index, _Up&& __rhs) + { + this->_M_reset(); + __variant_construct_single(*this, std::forward<_Up>(__rhs)); + this->_M_index = __rhs_index; + } + + template + void _M_destructive_copy(unsigned short __rhs_index, const _Up& __rhs) + { + this->_M_reset(); + __variant_construct_single(*this, __rhs); + this->_M_index = __rhs_index; + } + }; + + template + using _Move_ctor_alias = + _Move_ctor_base<_Traits<_Types...>::_S_trivial_move_ctor, _Types...>; + + template + struct _Copy_assign_base : _Move_ctor_alias<_Types...> + { + using _Base = _Move_ctor_alias<_Types...>; + using _Base::_Base; + + _Copy_assign_base& + operator=(const _Copy_assign_base& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_copy_assign) + { + __variant::__raw_idx_visit( + [this](auto&& __rhs_mem, auto __rhs_index) mutable + { + if constexpr (__rhs_index != variant_npos) + { + if (this->_M_index == __rhs_index) + __variant::__get<__rhs_index>(*this) = __rhs_mem; + else + { + using __rhs_type = __remove_cvref_t; + if constexpr (is_nothrow_copy_constructible_v<__rhs_type> + || !is_nothrow_move_constructible_v<__rhs_type>) + // The standard says this->emplace<__rhs_type>(__rhs_mem) + // should be used here, but _M_destructive_copy is + // equivalent in this case. Either copy construction + // doesn't throw, so _M_destructive_copy gives strong + // exception safety guarantee, or both copy construction + // and move construction can throw, so emplace only gives + // basic exception safety anyway. + this->_M_destructive_copy(__rhs_index, __rhs_mem); + else + __variant_cast<_Types...>(*this) + = variant<_Types...>(std::in_place_index<__rhs_index>, + __rhs_mem); + } + } + else + this->_M_reset(); + }, __variant_cast<_Types...>(__rhs)); + return *this; + } + + _Copy_assign_base(const _Copy_assign_base&) = default; + _Copy_assign_base(_Copy_assign_base&&) = default; + _Copy_assign_base& operator=(_Copy_assign_base&&) = default; + }; + + template + struct _Copy_assign_base : _Move_ctor_alias<_Types...> + { + using _Base = _Move_ctor_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Copy_assign_alias = + _Copy_assign_base<_Traits<_Types...>::_S_trivial_copy_assign, _Types...>; + + template + struct _Move_assign_base : _Copy_assign_alias<_Types...> + { + using _Base = _Copy_assign_alias<_Types...>; + using _Base::_Base; + + _Move_assign_base& + operator=(_Move_assign_base&& __rhs) + noexcept(_Traits<_Types...>::_S_nothrow_move_assign) + { + __variant::__raw_idx_visit( + [this](auto&& __rhs_mem, auto __rhs_index) mutable + { + if constexpr (__rhs_index != variant_npos) + { + if (this->_M_index == __rhs_index) + __variant::__get<__rhs_index>(*this) = std::move(__rhs_mem); + else + __variant_cast<_Types...>(*this) + .template emplace<__rhs_index>(std::move(__rhs_mem)); + } + else + this->_M_reset(); + }, __variant_cast<_Types...>(__rhs)); + return *this; + } + + _Move_assign_base(const _Move_assign_base&) = default; + _Move_assign_base(_Move_assign_base&&) = default; + _Move_assign_base& operator=(const _Move_assign_base&) = default; + }; + + template + struct _Move_assign_base : _Copy_assign_alias<_Types...> + { + using _Base = _Copy_assign_alias<_Types...>; + using _Base::_Base; + }; + + template + using _Move_assign_alias = + _Move_assign_base<_Traits<_Types...>::_S_trivial_move_assign, _Types...>; + + template + struct _Variant_base : _Move_assign_alias<_Types...> + { + using _Base = _Move_assign_alias<_Types...>; + + constexpr + _Variant_base() + noexcept(_Traits<_Types...>::_S_nothrow_default_ctor) + : _Variant_base(in_place_index<0>) { } + + template + constexpr explicit + _Variant_base(in_place_index_t<_Np> __i, _Args&&... __args) + : _Base(__i, std::forward<_Args>(__args)...) + { } + + _Variant_base(const _Variant_base&) = default; + _Variant_base(_Variant_base&&) = default; + _Variant_base& operator=(const _Variant_base&) = default; + _Variant_base& operator=(_Variant_base&&) = default; + }; + + // For how many times does _Tp appear in _Tuple? + template + struct __tuple_count; + + template + inline constexpr size_t __tuple_count_v = + __tuple_count<_Tp, _Tuple>::value; + + template + struct __tuple_count<_Tp, tuple<_Types...>> + : integral_constant { }; + + template + struct __tuple_count<_Tp, tuple<_First, _Rest...>> + : integral_constant< + size_t, + __tuple_count_v<_Tp, tuple<_Rest...>> + is_same_v<_Tp, _First>> { }; + + // TODO: Reuse this in ? + template + inline constexpr bool __exactly_once = + __tuple_count_v<_Tp, tuple<_Types...>> == 1; + + // Helper used to check for valid conversions that don't involve narrowing. + template struct _Arr { _Ti _M_x[1]; }; + + // Build an imaginary function FUN(Ti) for each alternative type Ti + template, bool>, + typename = void> + struct _Build_FUN + { + // This function means 'using _Build_FUN::_S_fun;' is valid, + // but only static functions will be considered in the call below. + void _S_fun(); + }; + + // ... for which Ti x[] = {std::forward(t)}; is well-formed, + template + struct _Build_FUN<_Ind, _Tp, _Ti, false, + void_t{{std::declval<_Tp>()}})>> + { + // This is the FUN function for type _Ti, with index _Ind + static integral_constant _S_fun(_Ti); + }; + + // ... and if Ti is cv bool, remove_cvref_t is bool. + template + struct _Build_FUN<_Ind, _Tp, _Ti, true, + enable_if_t, bool>>> + { + // This is the FUN function for when _Ti is cv bool, with index _Ind + static integral_constant _S_fun(_Ti); + }; + + template>> + struct _Build_FUNs; + + template + struct _Build_FUNs<_Tp, variant<_Ti...>, index_sequence<_Ind...>> + : _Build_FUN<_Ind, _Tp, _Ti>... + { + using _Build_FUN<_Ind, _Tp, _Ti>::_S_fun...; + }; + + // The index j of the overload FUN(Tj) selected by overload resolution + // for FUN(std::forward<_Tp>(t)) + template + using _FUN_type + = decltype(_Build_FUNs<_Tp, _Variant>::_S_fun(std::declval<_Tp>())); + + // The index selected for FUN(std::forward(t)), or variant_npos if none. + template + struct __accepted_index + : integral_constant + { }; + + template + struct __accepted_index<_Tp, _Variant, void_t<_FUN_type<_Tp, _Variant>>> + : _FUN_type<_Tp, _Variant> + { }; + + // Returns the raw storage for __v. + template + void* __get_storage(_Variant&& __v) noexcept + { return __v._M_storage(); } + + template + struct _Extra_visit_slot_needed + { + template struct _Variant_never_valueless; + + template + struct _Variant_never_valueless> + : bool_constant<__variant::__never_valueless<_Types...>()> {}; + + static constexpr bool value = + (is_same_v<_Maybe_variant_cookie, __variant_cookie> + || is_same_v<_Maybe_variant_cookie, __variant_idx_cookie>) + && !_Variant_never_valueless<__remove_cvref_t<_Variant>>::value; + }; + + // Used for storing a multi-dimensional vtable. + template + struct _Multi_array; + + // Partial specialization with rank zero, stores a single _Tp element. + template + struct _Multi_array<_Tp> + { + template + struct __untag_result + : false_type + { using element_type = _Tp; }; + + template + struct __untag_result + : false_type + { using element_type = void(*)(_Args...); }; + + template + struct __untag_result<__variant_cookie(*)(_Args...)> + : false_type + { using element_type = void(*)(_Args...); }; + + template + struct __untag_result<__variant_idx_cookie(*)(_Args...)> + : false_type + { using element_type = void(*)(_Args...); }; + + template + struct __untag_result<__deduce_visit_result<_Res>(*)(_Args...)> + : true_type + { using element_type = _Res(*)(_Args...); }; + + using __result_is_deduced = __untag_result<_Tp>; + + constexpr const typename __untag_result<_Tp>::element_type& + _M_access() const + { return _M_data; } + + typename __untag_result<_Tp>::element_type _M_data; + }; + + // Partial specialization with rank >= 1. + template + struct _Multi_array<_Ret(*)(_Visitor, _Variants...), __first, __rest...> + { + static constexpr size_t __index = + sizeof...(_Variants) - sizeof...(__rest) - 1; + + using _Variant = typename _Nth_type<__index, _Variants...>::type; + + static constexpr int __do_cookie = + _Extra_visit_slot_needed<_Ret, _Variant>::value ? 1 : 0; + + using _Tp = _Ret(*)(_Visitor, _Variants...); + + template + constexpr decltype(auto) + _M_access(size_t __first_index, _Args... __rest_indices) const + { + return _M_arr[__first_index + __do_cookie] + ._M_access(__rest_indices...); + } + + _Multi_array<_Tp, __rest...> _M_arr[__first + __do_cookie]; + }; + + // Creates a multi-dimensional vtable recursively. + // + // For example, + // visit([](auto, auto){}, + // variant(), // typedef'ed as V1 + // variant()) // typedef'ed as V2 + // will trigger instantiations of: + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<0, 2>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 0>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 1>> + // __gen_vtable_impl<_Multi_array, + // tuple, std::index_sequence<1, 2>> + // The returned multi-dimensional vtable can be fast accessed by the visitor + // using index calculation. + template + struct __gen_vtable_impl; + + // Defines the _S_apply() member that returns a _Multi_array populated + // with function pointers that perform the visitation expressions e(m) + // for each valid pack of indexes into the variant types _Variants. + // + // This partial specialization builds up the index sequences by recursively + // calling _S_apply() on the next specialization of __gen_vtable_impl. + // The base case of the recursion defines the actual function pointers. + template + struct __gen_vtable_impl< + _Multi_array<_Result_type (*)(_Visitor, _Variants...), __dimensions...>, + std::index_sequence<__indices...>> + { + using _Next = + remove_reference_t::type>; + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...), + __dimensions...>; + + static constexpr _Array_type + _S_apply() + { + _Array_type __vtable{}; + _S_apply_all_alts( + __vtable, make_index_sequence>()); + return __vtable; + } + + template + static constexpr void + _S_apply_all_alts(_Array_type& __vtable, + std::index_sequence<__var_indices...>) + { + if constexpr (_Extra_visit_slot_needed<_Result_type, _Next>::value) + (_S_apply_single_alt( + __vtable._M_arr[__var_indices + 1], + &(__vtable._M_arr[0])), ...); + else + (_S_apply_single_alt( + __vtable._M_arr[__var_indices]), ...); + } + + template + static constexpr void + _S_apply_single_alt(_Tp& __element, _Tp* __cookie_element = nullptr) + { + if constexpr (__do_cookie) + { + __element = __gen_vtable_impl< + _Tp, + std::index_sequence<__indices..., __index>>::_S_apply(); + *__cookie_element = __gen_vtable_impl< + _Tp, + std::index_sequence<__indices..., variant_npos>>::_S_apply(); + } + else + { + __element = __gen_vtable_impl< + remove_reference_t, + std::index_sequence<__indices..., __index>>::_S_apply(); + } + } + }; + + // This partial specialization is the base case for the recursion. + // It populates a _Multi_array element with the address of a function + // that invokes the visitor with the alternatives specified by __indices. + template + struct __gen_vtable_impl< + _Multi_array<_Result_type (*)(_Visitor, _Variants...)>, + std::index_sequence<__indices...>> + { + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...)>; + + template + static constexpr decltype(auto) + __element_by_index_or_cookie(_Variant&& __var) noexcept + { + if constexpr (__index != variant_npos) + return __variant::__get<__index>(std::forward<_Variant>(__var)); + else + return __variant_cookie{}; + } + + static constexpr decltype(auto) + __visit_invoke(_Visitor&& __visitor, _Variants... __vars) + { + if constexpr (is_same_v<_Result_type, __variant_idx_cookie>) + // For raw visitation using indices, pass the indices to the visitor + // and discard the return value: + std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))..., + integral_constant()...); + else if constexpr (is_same_v<_Result_type, __variant_cookie>) + // For raw visitation without indices, and discard the return value: + std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))...); + else if constexpr (_Array_type::__result_is_deduced::value) + // For the usual std::visit case deduce the return value: + return std::__invoke(std::forward<_Visitor>(__visitor), + __element_by_index_or_cookie<__indices>( + std::forward<_Variants>(__vars))...); + else // for std::visit use INVOKE + return std::__invoke_r<_Result_type>( + std::forward<_Visitor>(__visitor), + __variant::__get<__indices>(std::forward<_Variants>(__vars))...); + } + + static constexpr auto + _S_apply() + { return _Array_type{&__visit_invoke}; } + }; + + template + struct __gen_vtable + { + using _Array_type = + _Multi_array<_Result_type (*)(_Visitor, _Variants...), + variant_size_v>...>; + + static constexpr _Array_type _S_vtable + = __gen_vtable_impl<_Array_type, std::index_sequence<>>::_S_apply(); + }; + + template + struct _Base_dedup : public _Tp { }; + + template + struct _Variant_hash_base; + + template + struct _Variant_hash_base, + std::index_sequence<__indices...>> + : _Base_dedup<__indices, __poison_hash>>... { }; + +} // namespace __variant +} // namespace __detail + + template + void __variant_construct_by_index(_Variant& __v, _Args&&... __args) + { + __v._M_index = _Np; + auto&& __storage = __detail::__variant::__get<_Np>(__v); + ::new ((void*)std::addressof(__storage)) + remove_reference_t + (std::forward<_Args>(__args)...); + } + + template + constexpr bool + holds_alternative(const variant<_Types...>& __v) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + return __v.index() == __detail::__variant::__index_of_v<_Tp, _Types...>; + } + + template + constexpr _Tp& get(variant<_Types...>& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); + } + + template + constexpr _Tp&& get(variant<_Types...>&& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( + std::move(__v)); + } + + template + constexpr const _Tp& get(const variant<_Types...>& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>(__v); + } + + template + constexpr const _Tp&& get(const variant<_Types...>&& __v) + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get<__detail::__variant::__index_of_v<_Tp, _Types...>>( + std::move(__v)); + } + + template + constexpr add_pointer_t>> + get_if(variant<_Types...>* __ptr) noexcept + { + using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void"); + if (__ptr && __ptr->index() == _Np) + return std::addressof(__detail::__variant::__get<_Np>(*__ptr)); + return nullptr; + } + + template + constexpr + add_pointer_t>> + get_if(const variant<_Types...>* __ptr) noexcept + { + using _Alternative_type = variant_alternative_t<_Np, variant<_Types...>>; + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + static_assert(!is_void_v<_Alternative_type>, "_Tp must not be void"); + if (__ptr && __ptr->index() == _Np) + return std::addressof(__detail::__variant::__get<_Np>(*__ptr)); + return nullptr; + } + + template + constexpr add_pointer_t<_Tp> + get_if(variant<_Types...>* __ptr) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( + __ptr); + } + + template + constexpr add_pointer_t + get_if(const variant<_Types...>* __ptr) noexcept + { + static_assert(__detail::__variant::__exactly_once<_Tp, _Types...>, + "T must occur exactly once in alternatives"); + static_assert(!is_void_v<_Tp>, "_Tp must not be void"); + return std::get_if<__detail::__variant::__index_of_v<_Tp, _Types...>>( + __ptr); + } + + struct monostate { }; + +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP, __NAME) \ + template \ + constexpr bool operator __OP(const variant<_Types...>& __lhs, \ + const variant<_Types...>& __rhs) \ + { \ + bool __ret = true; \ + __detail::__variant::__raw_idx_visit( \ + [&__ret, &__lhs] (auto&& __rhs_mem, auto __rhs_index) mutable \ + { \ + if constexpr (__rhs_index != variant_npos) \ + { \ + if (__lhs.index() == __rhs_index) \ + { \ + auto& __this_mem = std::get<__rhs_index>(__lhs); \ + __ret = __this_mem __OP __rhs_mem; \ + } \ + else \ + __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ + } \ + else \ + __ret = (__lhs.index() + 1) __OP (__rhs_index + 1); \ + }, __rhs); \ + return __ret; \ + } + + _VARIANT_RELATION_FUNCTION_TEMPLATE(<, less) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=, less_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==, equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=, not_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=, greater_equal) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>, greater) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE + + constexpr bool operator==(monostate, monostate) noexcept { return true; } + +#ifdef __cpp_lib_three_way_comparison + template + requires (three_way_comparable<_Types> && ...) + constexpr + common_comparison_category_t...> + operator<=>(const variant<_Types...>& __v, const variant<_Types...>& __w) + { + common_comparison_category_t...> __ret + = strong_ordering::equal; + + __detail::__variant::__raw_idx_visit( + [&__ret, &__v] (auto&& __w_mem, auto __w_index) mutable + { + if constexpr (__w_index != variant_npos) + { + if (__v.index() == __w_index) + { + auto& __this_mem = std::get<__w_index>(__v); + __ret = __this_mem <=> __w_mem; + return; + } + } + __ret = (__v.index() + 1) <=> (__w_index + 1); + }, __w); + return __ret; + } + + constexpr strong_ordering + operator<=>(monostate, monostate) noexcept { return strong_ordering::equal; } +#else + constexpr bool operator!=(monostate, monostate) noexcept { return false; } + constexpr bool operator<(monostate, monostate) noexcept { return false; } + constexpr bool operator>(monostate, monostate) noexcept { return false; } + constexpr bool operator<=(monostate, monostate) noexcept { return true; } + constexpr bool operator>=(monostate, monostate) noexcept { return true; } +#endif + + template + constexpr decltype(auto) visit(_Visitor&&, _Variants&&...); + + template + inline enable_if_t<(is_move_constructible_v<_Types> && ...) + && (is_swappable_v<_Types> && ...)> + swap(variant<_Types...>& __lhs, variant<_Types...>& __rhs) + noexcept(noexcept(__lhs.swap(__rhs))) + { __lhs.swap(__rhs); } + + template + enable_if_t && ...) + && (is_swappable_v<_Types> && ...))> + swap(variant<_Types...>&, variant<_Types...>&) = delete; + + inline void + __throw_bad_variant_access(bool __valueless __attribute__((unused))) + { + __throw_bad_variant_access(""); + } + + template + class variant + : private __detail::__variant::_Variant_base<_Types...>, + private _Enable_default_constructor< + __detail::__variant::_Traits<_Types...>::_S_default_ctor, + variant<_Types...>>, + private _Enable_copy_move< + __detail::__variant::_Traits<_Types...>::_S_copy_ctor, + __detail::__variant::_Traits<_Types...>::_S_copy_assign, + __detail::__variant::_Traits<_Types...>::_S_move_ctor, + __detail::__variant::_Traits<_Types...>::_S_move_assign, + variant<_Types...>> + { + private: + template + friend decltype(auto) __variant_cast(_Tp&&); + template + friend void __variant_construct_by_index(_Variant& __v, + _Args&&... __args); + + static_assert(sizeof...(_Types) > 0, + "variant must have at least one alternative"); + static_assert(!(std::is_reference_v<_Types> || ...), + "variant must have no reference alternative"); + static_assert(!(std::is_void_v<_Types> || ...), + "variant must have no void alternative"); + + using _Base = __detail::__variant::_Variant_base<_Types...>; + using _Default_ctor_enabler = + _Enable_default_constructor< + __detail::__variant::_Traits<_Types...>::_S_default_ctor, + variant<_Types...>>; + + template + static constexpr bool __not_self + = !is_same_v<__remove_cvref_t<_Tp>, variant>; + + template + static constexpr bool + __exactly_once = __detail::__variant::__exactly_once<_Tp, _Types...>; + + template + static constexpr size_t __accepted_index + = __detail::__variant::__accepted_index<_Tp, variant>::value; + + template> + using __to_type = variant_alternative_t<_Np, variant>; + + template>> + using __accepted_type = __to_type<__accepted_index<_Tp>>; + + template + static constexpr size_t __index_of = + __detail::__variant::__index_of_v<_Tp, _Types...>; + + using _Traits = __detail::__variant::_Traits<_Types...>; + + template + struct __is_in_place_tag : false_type { }; + template + struct __is_in_place_tag> : true_type { }; + template + struct __is_in_place_tag> : true_type { }; + + template + static constexpr bool __not_in_place_tag + = !__is_in_place_tag<__remove_cvref_t<_Tp>>::value; + + public: + variant() = default; + variant(const variant& __rhs) = default; + variant(variant&&) = default; + variant& operator=(const variant&) = default; + variant& operator=(variant&&) = default; + ~variant() = default; + + template, + typename = enable_if_t<__not_in_place_tag<_Tp>>, + typename _Tj = __accepted_type<_Tp&&>, + typename = enable_if_t<__exactly_once<_Tj> + && is_constructible_v<_Tj, _Tp>>> + constexpr + variant(_Tp&& __t) + noexcept(is_nothrow_constructible_v<_Tj, _Tp>) + : variant(in_place_index<__accepted_index<_Tp>>, + std::forward<_Tp>(__t)) + { } + + template + && is_constructible_v<_Tp, _Args...>>> + constexpr explicit + variant(in_place_type_t<_Tp>, _Args&&... __args) + : variant(in_place_index<__index_of<_Tp>>, + std::forward<_Args>(__args)...) + { } + + template + && is_constructible_v<_Tp, + initializer_list<_Up>&, _Args...>>> + constexpr explicit + variant(in_place_type_t<_Tp>, initializer_list<_Up> __il, + _Args&&... __args) + : variant(in_place_index<__index_of<_Tp>>, __il, + std::forward<_Args>(__args)...) + { } + + template, + typename = enable_if_t>> + constexpr explicit + variant(in_place_index_t<_Np>, _Args&&... __args) + : _Base(in_place_index<_Np>, std::forward<_Args>(__args)...), + _Default_ctor_enabler(_Enable_default_constructor_tag{}) + { } + + template, + typename = enable_if_t&, + _Args...>>> + constexpr explicit + variant(in_place_index_t<_Np>, initializer_list<_Up> __il, + _Args&&... __args) + : _Base(in_place_index<_Np>, __il, std::forward<_Args>(__args)...), + _Default_ctor_enabler(_Enable_default_constructor_tag{}) + { } + + template + enable_if_t<__exactly_once<__accepted_type<_Tp&&>> + && is_constructible_v<__accepted_type<_Tp&&>, _Tp> + && is_assignable_v<__accepted_type<_Tp&&>&, _Tp>, + variant&> + operator=(_Tp&& __rhs) + noexcept(is_nothrow_assignable_v<__accepted_type<_Tp&&>&, _Tp> + && is_nothrow_constructible_v<__accepted_type<_Tp&&>, _Tp>) + { + constexpr auto __index = __accepted_index<_Tp>; + if (index() == __index) + std::get<__index>(*this) = std::forward<_Tp>(__rhs); + else + { + using _Tj = __accepted_type<_Tp&&>; + if constexpr (is_nothrow_constructible_v<_Tj, _Tp> + || !is_nothrow_move_constructible_v<_Tj>) + this->emplace<__index>(std::forward<_Tp>(__rhs)); + else + operator=(variant(std::forward<_Tp>(__rhs))); + } + return *this; + } + + template + enable_if_t && __exactly_once<_Tp>, + _Tp&> + emplace(_Args&&... __args) + { + constexpr size_t __index = __index_of<_Tp>; + return this->emplace<__index>(std::forward<_Args>(__args)...); + } + + template + enable_if_t&, _Args...> + && __exactly_once<_Tp>, + _Tp&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + constexpr size_t __index = __index_of<_Tp>; + return this->emplace<__index>(__il, std::forward<_Args>(__args)...); + } + + template + enable_if_t, + _Args...>, + variant_alternative_t<_Np, variant>&> + emplace(_Args&&... __args) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + using type = variant_alternative_t<_Np, variant>; + // Provide the strong exception-safety guarantee when possible, + // to avoid becoming valueless. + if constexpr (is_nothrow_constructible_v) + { + this->_M_reset(); + __variant_construct_by_index<_Np>(*this, + std::forward<_Args>(__args)...); + } + else if constexpr (is_scalar_v) + { + // This might invoke a potentially-throwing conversion operator: + const type __tmp(std::forward<_Args>(__args)...); + // But these steps won't throw: + this->_M_reset(); + __variant_construct_by_index<_Np>(*this, __tmp); + } + else if constexpr (__detail::__variant::_Never_valueless_alt() + && _Traits::_S_move_assign) + { + // This construction might throw: + variant __tmp(in_place_index<_Np>, + std::forward<_Args>(__args)...); + // But _Never_valueless_alt means this won't: + *this = std::move(__tmp); + } + else + { + // This case only provides the basic exception-safety guarantee, + // i.e. the variant can become valueless. + this->_M_reset(); + __try + { + __variant_construct_by_index<_Np>(*this, + std::forward<_Args>(__args)...); + } + __catch (...) + { + this->_M_index = variant_npos; + __throw_exception_again; + } + } + return std::get<_Np>(*this); + } + + template + enable_if_t, + initializer_list<_Up>&, _Args...>, + variant_alternative_t<_Np, variant>&> + emplace(initializer_list<_Up> __il, _Args&&... __args) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + using type = variant_alternative_t<_Np, variant>; + // Provide the strong exception-safety guarantee when possible, + // to avoid becoming valueless. + if constexpr (is_nothrow_constructible_v&, + _Args...>) + { + this->_M_reset(); + __variant_construct_by_index<_Np>(*this, __il, + std::forward<_Args>(__args)...); + } + else if constexpr (__detail::__variant::_Never_valueless_alt() + && _Traits::_S_move_assign) + { + // This construction might throw: + variant __tmp(in_place_index<_Np>, __il, + std::forward<_Args>(__args)...); + // But _Never_valueless_alt means this won't: + *this = std::move(__tmp); + } + else + { + // This case only provides the basic exception-safety guarantee, + // i.e. the variant can become valueless. + this->_M_reset(); + __try + { + __variant_construct_by_index<_Np>(*this, __il, + std::forward<_Args>(__args)...); + } + __catch (...) + { + this->_M_index = variant_npos; + __throw_exception_again; + } + } + return std::get<_Np>(*this); + } + + constexpr bool valueless_by_exception() const noexcept + { return !this->_M_valid(); } + + constexpr size_t index() const noexcept + { + using __index_type = typename _Base::__index_type; + if constexpr (__detail::__variant::__never_valueless<_Types...>()) + return this->_M_index; + else if constexpr (sizeof...(_Types) <= __index_type(-1) / 2) + return make_signed_t<__index_type>(this->_M_index); + else + return size_t(__index_type(this->_M_index + 1)) - 1; + } + + void + swap(variant& __rhs) + noexcept((__is_nothrow_swappable<_Types>::value && ...) + && is_nothrow_move_constructible_v) + { + __detail::__variant::__raw_idx_visit( + [this, &__rhs](auto&& __rhs_mem, auto __rhs_index) mutable + { + if constexpr (__rhs_index != variant_npos) + { + if (this->index() == __rhs_index) + { + auto& __this_mem = + std::get<__rhs_index>(*this); + using std::swap; + swap(__this_mem, __rhs_mem); + } + else + { + if (!this->valueless_by_exception()) [[__likely__]] + { + auto __tmp(std::move(__rhs_mem)); + __rhs = std::move(*this); + this->_M_destructive_move(__rhs_index, + std::move(__tmp)); + } + else + { + this->_M_destructive_move(__rhs_index, + std::move(__rhs_mem)); + __rhs._M_reset(); + } + } + } + else + { + if (!this->valueless_by_exception()) [[__likely__]] + { + __rhs = std::move(*this); + this->_M_reset(); + } + } + }, __rhs); + } + + private: + +#if defined(__clang__) && __clang_major__ <= 7 + public: + using _Base::_M_u; // See https://bugs.llvm.org/show_bug.cgi?id=31852 + private: +#endif + + template + friend constexpr decltype(auto) + __detail::__variant::__get(_Vp&& __v) noexcept; + + template + friend void* + __detail::__variant::__get_storage(_Vp&& __v) noexcept; + +#define _VARIANT_RELATION_FUNCTION_TEMPLATE(__OP) \ + template \ + friend constexpr bool \ + operator __OP(const variant<_Tp...>& __lhs, \ + const variant<_Tp...>& __rhs); + + _VARIANT_RELATION_FUNCTION_TEMPLATE(<) + _VARIANT_RELATION_FUNCTION_TEMPLATE(<=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(==) + _VARIANT_RELATION_FUNCTION_TEMPLATE(!=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>=) + _VARIANT_RELATION_FUNCTION_TEMPLATE(>) + +#undef _VARIANT_RELATION_FUNCTION_TEMPLATE + }; + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>& + get(variant<_Types...>& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(__v); + } + + template + constexpr variant_alternative_t<_Np, variant<_Types...>>&& + get(variant<_Types...>&& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(std::move(__v)); + } + + template + constexpr const variant_alternative_t<_Np, variant<_Types...>>& + get(const variant<_Types...>& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(__v); + } + + template + constexpr const variant_alternative_t<_Np, variant<_Types...>>&& + get(const variant<_Types...>&& __v) + { + static_assert(_Np < sizeof...(_Types), + "The index must be in [0, number of alternatives)"); + if (__v.index() != _Np) + __throw_bad_variant_access(__v.valueless_by_exception()); + return __detail::__variant::__get<_Np>(std::move(__v)); + } + + template + constexpr decltype(auto) + __do_visit(_Visitor&& __visitor, _Variants&&... __variants) + { + constexpr auto& __vtable = __detail::__variant::__gen_vtable< + _Result_type, _Visitor&&, _Variants&&...>::_S_vtable; + + auto __func_ptr = __vtable._M_access(__variants.index()...); + return (*__func_ptr)(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + + template + constexpr decltype(auto) + visit(_Visitor&& __visitor, _Variants&&... __variants) + { + if ((__variants.valueless_by_exception() || ...)) + __throw_bad_variant_access("std::visit: variant is valueless"); + + using _Result_type = std::invoke_result_t<_Visitor, + decltype(std::get<0>(std::declval<_Variants>()))...>; + + using _Tag = __detail::__variant::__deduce_visit_result<_Result_type>; + + return std::__do_visit<_Tag>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } + +#if __cplusplus > 201703L + template + constexpr _Res + visit(_Visitor&& __visitor, _Variants&&... __variants) + { + if ((__variants.valueless_by_exception() || ...)) + __throw_bad_variant_access("std::visit: variant is valueless"); + + return std::__do_visit<_Res>(std::forward<_Visitor>(__visitor), + std::forward<_Variants>(__variants)...); + } +#endif + + template + struct __variant_hash_call_base_impl + { + size_t + operator()(const variant<_Types...>& __t) const + noexcept((is_nothrow_invocable_v>, _Types> && ...)) + { + size_t __ret; + __detail::__variant::__raw_visit( + [&__t, &__ret](auto&& __t_mem) mutable + { + using _Type = __remove_cvref_t; + if constexpr (!is_same_v<_Type, + __detail::__variant::__variant_cookie>) + __ret = std::hash{}(__t.index()) + + std::hash<_Type>{}(__t_mem); + else + __ret = std::hash{}(__t.index()); + }, __t); + return __ret; + } + }; + + template + struct __variant_hash_call_base_impl {}; + + template + using __variant_hash_call_base = + __variant_hash_call_base_impl<(__poison_hash>:: + __enable_hash_call &&...), _Types...>; + + template + struct hash> + : private __detail::__variant::_Variant_hash_base< + variant<_Types...>, std::index_sequence_for<_Types...>>, + public __variant_hash_call_base<_Types...> + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = variant<_Types...>; + }; + + template<> + struct hash + { + using result_type [[__deprecated__]] = size_t; + using argument_type [[__deprecated__]] = monostate; + + size_t + operator()(const monostate&) const noexcept + { + constexpr size_t __magic_monostate_hash = -7777; + return __magic_monostate_hash; + } + }; + + template + struct __is_fast_hash>> + : bool_constant<(__is_fast_hash<_Types>::value && ...)> + { }; + +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std + +#endif // C++17 + +#endif // _GLIBCXX_VARIANT diff --git a/resources/sources/avr-libstdcpp/include/vector b/resources/sources/avr-libstdcpp/include/vector new file mode 100644 index 000000000..6f587a82a --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/vector @@ -0,0 +1,129 @@ +// -*- C++ -*- + +// Copyright (C) 2001-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +/** @file include/vector + * This is a Standard C++ Library header. + */ + +#ifndef _GLIBCXX_VECTOR +#define _GLIBCXX_VECTOR 1 + +#pragma GCC system_header + +#include +#if __cplusplus > 201703L +# include // For remove and remove_if +#endif // C++20 +#include +#include +#include +#include +#include +#include + +#ifndef _GLIBCXX_EXPORT_TEMPLATE +# include +#endif + +#ifdef _GLIBCXX_DEBUG +# include +#endif + +#if __cplusplus >= 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + namespace pmr { + template class polymorphic_allocator; + template + using vector = std::vector<_Tp, polymorphic_allocator<_Tp>>; + } // namespace pmr +# ifdef _GLIBCXX_DEBUG + namespace _GLIBCXX_STD_C::pmr { + template + using vector + = _GLIBCXX_STD_C::vector<_Tp, std::pmr::polymorphic_allocator<_Tp>>; + } // namespace _GLIBCXX_STD_C::pmr +# endif +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++17 + +#if __cplusplus > 201703L +namespace std _GLIBCXX_VISIBILITY(default) +{ +_GLIBCXX_BEGIN_NAMESPACE_VERSION + +#define __cpp_lib_erase_if 202002L + + template + inline typename vector<_Tp, _Alloc>::size_type + erase_if(vector<_Tp, _Alloc>& __cont, _Predicate __pred) + { + const auto __osz = __cont.size(); + __cont.erase(std::remove_if(__cont.begin(), __cont.end(), __pred), + __cont.end()); + return __osz - __cont.size(); + } + + template + inline typename vector<_Tp, _Alloc>::size_type + erase(vector<_Tp, _Alloc>& __cont, const _Up& __value) + { + const auto __osz = __cont.size(); + __cont.erase(std::remove(__cont.begin(), __cont.end(), __value), + __cont.end()); + return __osz - __cont.size(); + } +_GLIBCXX_END_NAMESPACE_VERSION +} // namespace std +#endif // C++20 + +#endif /* _GLIBCXX_VECTOR */ diff --git a/resources/sources/avr-libstdcpp/include/version b/resources/sources/avr-libstdcpp/include/version new file mode 100644 index 000000000..1e98be3ce --- /dev/null +++ b/resources/sources/avr-libstdcpp/include/version @@ -0,0 +1,231 @@ +// -*- C++ -*- Libstdc++ version details header. + +// Copyright (C) 2018-2020 Free Software Foundation, Inc. +// +// This file is part of the GNU ISO C++ Library. This library is free +// software; you can redistribute it and/or modify it under the +// terms of the GNU General Public License as published by the +// Free Software Foundation; either version 3, or (at your option) +// any later version. + +// This library is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. + +// Under Section 7 of GPL version 3, you are granted additional +// permissions described in the GCC Runtime Library Exception, version +// 3.1, as published by the Free Software Foundation. + +// You should have received a copy of the GNU General Public License and +// a copy of the GCC Runtime Library Exception along with this program; +// see the files COPYING3 and COPYING.RUNTIME respectively. If not, see +// . + +/** @file version + * This is a Standard C++ Library file. You should @c \#include this file + * in your programs, rather than any of the @a *.h implementation files. + */ + +#ifndef _GLIBCXX_VERSION_INCLUDED +#define _GLIBCXX_VERSION_INCLUDED + +#pragma GCC system_header + +#include + +// c++03 +#if _GLIBCXX_HOSTED +# define __cpp_lib_incomplete_container_elements 201505 +#endif + +#if !defined(__STRICT_ANSI__) +// gnu++03 +# define __cpp_lib_uncaught_exceptions 201411L +#endif + +#if __cplusplus >= 201103L +// c++11 +#define __cpp_lib_is_null_pointer 201309 +#define __cpp_lib_result_of_sfinae 201210 + +#if _GLIBCXX_HOSTED +# define __cpp_lib_allocator_traits_is_always_equal 201411 +# define __cpp_lib_shared_ptr_arrays 201611L +#endif + +#if !defined(__STRICT_ANSI__) +// gnu++11 +# define __cpp_lib_is_swappable 201603 +# define __cpp_lib_void_t 201411 +# if _GLIBCXX_HOSTED +# define __cpp_lib_enable_shared_from_this 201603 +# endif +#endif + +// For C++11 and later we support ISO/IEC 29124 Mathematical Special Functions +#define __STDCPP_MATH_SPEC_FUNCS__ 201003L + +#if __cplusplus >= 201402L +// c++14 +#if __cpp_impl_coroutine +# define __cpp_lib_coroutine 201902L +#endif +#define __cpp_lib_integral_constant_callable 201304 +#define __cpp_lib_is_final 201402L +#define __cpp_lib_transformation_trait_aliases 201304 + +#if _GLIBCXX_HOSTED +# define __cpp_lib_chrono_udls 201304 +# define __cpp_lib_complex_udls 201309 +# define __cpp_lib_exchange_function 201304 +# define __cpp_lib_generic_associative_lookup 201304 +# define __cpp_lib_integer_sequence 201304 +# define __cpp_lib_make_reverse_iterator 201402 +# define __cpp_lib_make_unique 201304 +# ifndef _GLIBCXX_DEBUG // PR libstdc++/70303 +# define __cpp_lib_null_iterators 201304L +# endif +# define __cpp_lib_quoted_string_io 201304 +# define __cpp_lib_robust_nonmodifying_seq_ops 201304 +# ifdef _GLIBCXX_HAS_GTHREADS +# define __cpp_lib_shared_timed_mutex 201402 +# endif +# define __cpp_lib_string_udls 201304 +# define __cpp_lib_transparent_operators 201510 +# define __cpp_lib_tuple_element_t 201402L +# define __cpp_lib_tuples_by_type 201304 +#endif + +#if __cplusplus >= 201703L +// c++17 +#define __cpp_lib_addressof_constexpr 201603 +#define __cpp_lib_atomic_is_always_lock_free 201603 +#define __cpp_lib_bool_constant 201505 +#define __cpp_lib_byte 201603 +#ifdef _GLIBCXX_HAVE_BUILTIN_HAS_UNIQ_OBJ_REP +# define __cpp_lib_has_unique_object_representations 201606 +#endif +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_AGGREGATE +# define __cpp_lib_is_aggregate 201703 +#endif +#define __cpp_lib_is_invocable 201703 +#define __cpp_lib_is_swappable 201603 +#ifdef _GLIBCXX_HAVE_BUILTIN_LAUNDER +# define __cpp_lib_launder 201606 +#endif +#define __cpp_lib_logical_traits 201510 +#define __cpp_lib_type_trait_variable_templates 201510L +#define __cpp_lib_uncaught_exceptions 201411L +#define __cpp_lib_void_t 201411 + +#if _GLIBCXX_HOSTED +#define __cpp_lib_any 201606L +#define __cpp_lib_apply 201603 +#define __cpp_lib_array_constexpr 201803L +#define __cpp_lib_as_const 201510 +#define __cpp_lib_boyer_moore_searcher 201603 +#define __cpp_lib_chrono 201611 +#define __cpp_lib_clamp 201603 +#define __cpp_lib_constexpr_char_traits 201611 +#define __cpp_lib_enable_shared_from_this 201603 +#define __cpp_lib_execution 201902L // FIXME: should be 201603L +#define __cpp_lib_filesystem 201703 +#define __cpp_lib_gcd 201606 +#define __cpp_lib_gcd_lcm 201606 +#define __cpp_lib_hypot 201603 +#define __cpp_lib_invoke 201411L +#define __cpp_lib_lcm 201606 +#define __cpp_lib_make_from_tuple 201606 +#define __cpp_lib_map_try_emplace 201411 +#define __cpp_lib_math_special_functions 201603L +#ifdef _GLIBCXX_HAS_GTHREADS +# define __cpp_lib_memory_resource 201603 +#else +# define __cpp_lib_memory_resource 1 +#endif +#define __cpp_lib_node_extract 201606 +#define __cpp_lib_nonmember_container_access 201411 +#define __cpp_lib_not_fn 201603 +#define __cpp_lib_optional 201606L +#define __cpp_lib_raw_memory_algorithms 201606L +#define __cpp_lib_sample 201603 +#ifdef _GLIBCXX_HAS_GTHREADS +# define __cpp_lib_scoped_lock 201703 +# define __cpp_lib_shared_mutex 201505 +#endif +#define __cpp_lib_shared_ptr_weak_type 201606 +#define __cpp_lib_string_view 201803L +// #define __cpp_lib_to_chars 201611L +#define __cpp_lib_unordered_map_try_emplace 201411 +#define __cpp_lib_variant 201606L +#endif + +#if __cplusplus > 201703L +// c++2a +#define __cpp_lib_atomic_float 201711L +#define __cpp_lib_atomic_ref 201806L +#define __cpp_lib_atomic_value_initialization 201911L +#define __cpp_lib_bitops 201907L +#define __cpp_lib_bounded_array_traits 201902L +// __cpp_lib_char8_t is defined in +#if __cpp_concepts >= 201907L +# define __cpp_lib_concepts 202002L +#endif +#if __cpp_impl_destroying_delete +# define __cpp_lib_destroying_delete 201806L +#endif +#define __cpp_lib_endian 201907L +#define __cpp_lib_int_pow2 202002L +#ifdef _GLIBCXX_HAVE_BUILTIN_IS_CONSTANT_EVALUATED +# define __cpp_lib_is_constant_evaluated 201811L +#endif +#define __cpp_lib_is_nothrow_convertible 201806L +#define __cpp_lib_remove_cvref 201711L +#if __cpp_impl_three_way_comparison >= 201907L && __cpp_lib_concepts +# define __cpp_lib_three_way_comparison 201907L +#endif +#define __cpp_lib_type_identity 201806L +#define __cpp_lib_unwrap_ref 201811L + +#if _GLIBCXX_HOSTED +#undef __cpp_lib_array_constexpr +#define __cpp_lib_array_constexpr 201811L +#define __cpp_lib_assume_aligned 201811L +#define __cpp_lib_bind_front 201907L +// FIXME: #define __cpp_lib_execution 201902L +#define __cpp_lib_integer_comparison_functions 202002L +#define __cpp_lib_constexpr_algorithms 201806L +#define __cpp_lib_constexpr_complex 201711L +#define __cpp_lib_constexpr_dynamic_alloc 201907L +#define __cpp_lib_constexpr_functional 201907L +# define __cpp_lib_constexpr_iterator 201811L +#define __cpp_lib_constexpr_memory 201811L +#define __cpp_lib_constexpr_numeric 201911L +#define __cpp_lib_constexpr_string_view 201811L +#define __cpp_lib_constexpr_tuple 201811L +#define __cpp_lib_constexpr_utility 201811L +#define __cpp_lib_erase_if 202002L +#define __cpp_lib_interpolate 201902L +#ifdef _GLIBCXX_HAS_GTHREADS +# define __cpp_lib_jthread 201911L +#endif +#define __cpp_lib_list_remove_return_type 201806L +#define __cpp_lib_math_constants 201907L +#define __cpp_lib_polymorphic_allocator 201902L +#if __cpp_lib_concepts +# define __cpp_lib_ranges 201911L +#endif +#define __cpp_lib_shift 201806L +#define __cpp_lib_span 202002L +#define __cpp_lib_ssize 201902L +#define __cpp_lib_starts_ends_with 201711L +#define __cpp_lib_to_address 201711L +#define __cpp_lib_to_array 201907L +#endif +#endif // C++2a +#endif // C++17 +#endif // C++14 +#endif // C++11 + +#endif // _GLIBCXX_VERSION_INCLUDED From 0c9215e9910523f27521643d60fe7503b27a6731 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 11:54:22 -0400 Subject: [PATCH 031/296] fix: update strucpp::__CURRENT_TIME_NS so IEC timers elapse The sketch was defining a separate global ::__CURRENT_TIME_NS and updateTime() was incrementing it, while TIME() inside TON/TOF reads strucpp::__CURRENT_TIME_NS (the inline variable in iec_std_lib.hpp). The strucpp one stayed 0, so timers never fired and located outputs never toggled. Co-Authored-By: Claude Opus 4.7 (1M context) --- resources/sources/StrucppBaremetal/Baremetal.ino | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/resources/sources/StrucppBaremetal/Baremetal.ino b/resources/sources/StrucppBaremetal/Baremetal.ino index 117c67981..4b4c37e6b 100644 --- a/resources/sources/StrucppBaremetal/Baremetal.ino +++ b/resources/sources/StrucppBaremetal/Baremetal.ino @@ -59,11 +59,6 @@ // --------------------------------------------------------------------------- void operator delete(void* ptr, unsigned int) { free(ptr); } -// --------------------------------------------------------------------------- -// STruC++ time variable (used by generated code for TIME operations) -// --------------------------------------------------------------------------- -int64_t __CURRENT_TIME_NS = 0; - // --------------------------------------------------------------------------- // I/O Buffer definitions (declared extern in openplc.h, must be defined here) // --------------------------------------------------------------------------- @@ -235,8 +230,7 @@ void discoverTasks() { // Time update // --------------------------------------------------------------------------- void updateTime() { - extern int64_t __CURRENT_TIME_NS; - __CURRENT_TIME_NS += (int64_t)common_ticktime__; + strucpp::__CURRENT_TIME_NS += (int64_t)common_ticktime__; } // --------------------------------------------------------------------------- From 1b37afecb2dd3408fd9821c46c93488e2cdda6bf Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 12:00:31 -0400 Subject: [PATCH 032/296] fix: keep Arduino TIMER* macros visible in sketch for user function blocks User C/C++ function blocks may reference TIMER0A/TIMER1A/etc directly, so we shouldn't strip them from the sketch TU. Collisions with user variables of the same name are better resolved by treating TIMER* as reserved words in STruC++. min/max/abs/round undefs are kept because those break C++ stdlib templates. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../sources/StrucppBaremetal/Baremetal.ino | 25 +++---------------- 1 file changed, 4 insertions(+), 21 deletions(-) diff --git a/resources/sources/StrucppBaremetal/Baremetal.ino b/resources/sources/StrucppBaremetal/Baremetal.ino index 4b4c37e6b..c1aecace5 100644 --- a/resources/sources/StrucppBaremetal/Baremetal.ino +++ b/resources/sources/StrucppBaremetal/Baremetal.ino @@ -7,31 +7,14 @@ // - Computes GCD of task intervals for the scan cycle base tick // - Schedules programs round-robin with per-task divisors -// Arduino.h defines several macros that conflict with C++ standard library -// and STruC++ runtime headers. Undefine them before including anything. +// Arduino.h defines min/max/abs/round as function-like macros that break +// C++ standard library templates (, , etc). Undefine them +// before including anything. TIMER* macros are left intact so user C/C++ +// function blocks can reference them directly. #undef min #undef max #undef abs #undef round -// Arduino timer macros conflict with user variable names (STruC++ uppercases identifiers) -#undef TIMER0A -#undef TIMER0B -#undef TIMER1A -#undef TIMER1B -#undef TIMER1C -#undef TIMER2 -#undef TIMER2A -#undef TIMER2B -#undef TIMER3A -#undef TIMER3B -#undef TIMER3C -#undef TIMER4A -#undef TIMER4B -#undef TIMER4C -#undef TIMER4D -#undef TIMER5A -#undef TIMER5B -#undef TIMER5C // Include openplc.h FIRST (defines IEC_BOOL etc. as plain typedefs) #include "openplc.h" From f8e6a9dd9bab71274e0345fbfa5304af1ac37167 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 12:04:39 -0400 Subject: [PATCH 033/296] style: reformat StrucppBaremetal sketch to Allman brace style Match the brace placement used by the existing Baremetal.ino and the rest of the Arduino runtime sources (opening brace on its own line). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../sources/StrucppBaremetal/Baremetal.ino | 216 ++++++++++++------ 1 file changed, 146 insertions(+), 70 deletions(-) diff --git a/resources/sources/StrucppBaremetal/Baremetal.ino b/resources/sources/StrucppBaremetal/Baremetal.ino index c1aecace5..c9afd8c56 100644 --- a/resources/sources/StrucppBaremetal/Baremetal.ino +++ b/resources/sources/StrucppBaremetal/Baremetal.ino @@ -40,7 +40,10 @@ // --------------------------------------------------------------------------- // AVR: provide sized operator delete (virtual destructors generate this) // --------------------------------------------------------------------------- -void operator delete(void* ptr, unsigned int) { free(ptr); } +void operator delete(void* ptr, unsigned int) +{ + free(ptr); +} // --------------------------------------------------------------------------- // I/O Buffer definitions (declared extern in openplc.h, must be defined here) @@ -93,23 +96,33 @@ extern uint8_t pinMask_AOUT[]; // --------------------------------------------------------------------------- // GCD utility // --------------------------------------------------------------------------- -static uint64_t gcd(uint64_t a, uint64_t b) { - while (b) { uint64_t t = b; b = a % b; a = t; } +static uint64_t gcd(uint64_t a, uint64_t b) +{ + while (b) + { + uint64_t t = b; + b = a % b; + a = t; + } return a; } // --------------------------------------------------------------------------- // I/O Binding: walk locatedVars[] and bind to openplc.h buffer pointers // --------------------------------------------------------------------------- -void bindLocatedVars() { +void bindLocatedVars() +{ using namespace strucpp; - for (uint32_t i = 0; i < locatedVarsCount; ++i) { + for (uint32_t i = 0; i < locatedVarsCount; ++i) + { LocatedVar& lv = locatedVars[i]; if (!lv.pointer) continue; - switch (lv.area) { + switch (lv.area) + { case LocatedArea::Input: - switch (lv.size) { + switch (lv.size) + { case LocatedSize::Bit: bool_input[lv.byte_index][lv.bit_index] = (::IEC_BOOL*)lv.pointer; break; @@ -129,7 +142,8 @@ void bindLocatedVars() { break; case LocatedArea::Output: - switch (lv.size) { + switch (lv.size) + { case LocatedSize::Bit: bool_output[lv.byte_index][lv.bit_index] = (::IEC_BOOL*)lv.pointer; break; @@ -150,7 +164,8 @@ void bindLocatedVars() { case LocatedArea::Memory: #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) - switch (lv.size) { + switch (lv.size) + { case LocatedSize::Word: int_memory[lv.byte_index] = (::IEC_UINT*)lv.pointer; break; @@ -171,14 +186,17 @@ void bindLocatedVars() { // --------------------------------------------------------------------------- // Task Discovery: walk Configuration → Resource → Task to find programs // --------------------------------------------------------------------------- -void discoverTasks() { +void discoverTasks() +{ // First pass: count programs and compute GCD of intervals uint64_t gcd_ns = 0; size_t prog_count = 0; auto* resources = g_config.get_resources(); - for (size_t r = 0; r < g_config.get_resource_count(); ++r) { - for (size_t t = 0; t < resources[r].task_count; ++t) { + for (size_t r = 0; r < g_config.get_resource_count(); ++r) + { + for (size_t t = 0; t < resources[r].task_count; ++t) + { auto& task = resources[r].tasks[t]; prog_count += task.program_count; uint64_t interval = task.interval_ns > 0 ? task.interval_ns : 20000000ULL; @@ -195,12 +213,15 @@ void discoverTasks() { total_programs = prog_count; size_t idx = 0; - for (size_t r = 0; r < g_config.get_resource_count(); ++r) { - for (size_t t = 0; t < resources[r].task_count; ++t) { + for (size_t r = 0; r < g_config.get_resource_count(); ++r) + { + for (size_t t = 0; t < resources[r].task_count; ++t) + { auto& task = resources[r].tasks[t]; uint64_t interval = task.interval_ns > 0 ? task.interval_ns : gcd_ns; uint32_t divisor = (uint32_t)(interval / gcd_ns); - for (size_t p = 0; p < task.program_count; ++p) { + for (size_t p = 0; p < task.program_count; ++p) + { all_programs[idx] = task.programs[p]; task_divisors[idx] = divisor; idx++; @@ -212,14 +233,16 @@ void discoverTasks() { // --------------------------------------------------------------------------- // Time update // --------------------------------------------------------------------------- -void updateTime() { +void updateTime() +{ strucpp::__CURRENT_TIME_NS += (int64_t)common_ticktime__; } // --------------------------------------------------------------------------- // Scan cycle delay setup // --------------------------------------------------------------------------- -void setupCycleDelay(unsigned long long cycle_time) { +void setupCycleDelay(unsigned long long cycle_time) +{ scan_cycle = (uint32_t)(cycle_time / 1000); last_run = micros(); } @@ -227,7 +250,8 @@ void setupCycleDelay(unsigned long long cycle_time) { // ============================================================================= // SETUP // ============================================================================= -void setup() { +void setup() +{ // Turn off WiFi radio on ESP32/ESP8266 if not using WiFi #ifndef MBTCP #if defined(BOARD_ESP8266) || defined(BOARD_ESP32) @@ -248,16 +272,20 @@ void setup() { #ifdef MBSERIAL #ifdef MBSERIAL_TXPIN // Disable TX pin from OpenPLC hardware layer - for (int i = 0; i < NUM_DISCRETE_INPUT; i++) { + for (int i = 0; i < NUM_DISCRETE_INPUT; i++) + { if (pinMask_DIN[i] == MBSERIAL_TXPIN) pinMask_DIN[i] = 255; } - for (int i = 0; i < NUM_ANALOG_INPUT; i++) { + for (int i = 0; i < NUM_ANALOG_INPUT; i++) + { if (pinMask_AIN[i] == MBSERIAL_TXPIN) pinMask_AIN[i] = 255; } - for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++) { + for (int i = 0; i < NUM_DISCRETE_OUTPUT; i++) + { if (pinMask_DOUT[i] == MBSERIAL_TXPIN) pinMask_DOUT[i] = 255; } - for (int i = 0; i < NUM_ANALOG_OUTPUT; i++) { + for (int i = 0; i < NUM_ANALOG_OUTPUT; i++) + { if (pinMask_AOUT[i] == MBSERIAL_TXPIN) pinMask_AOUT[i] = 255; } MBSERIAL_IFACE.begin(MBSERIAL_BAUD); @@ -303,42 +331,57 @@ void setup() { // MAP EMPTY BUFFERS (for Modbus -- identical to current Baremetal.ino) // ============================================================================= #ifdef MODBUS_ENABLED -void mapEmptyBuffers() { - for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) { - if (bool_output[i/8][i%8] == NULL) { +void mapEmptyBuffers() +{ + for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) + { + if (bool_output[i/8][i%8] == NULL) + { bool_output[i/8][i%8] = (IEC_BOOL *)malloc(sizeof(IEC_BOOL)); *bool_output[i/8][i%8] = 0; } } - for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) { - if (int_output[i] == NULL) { + for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) + { + if (int_output[i] == NULL) + { int_output[i] = (IEC_UINT *)(modbus.holding + i); } } - for (int i = 0; i < MAX_DIGITAL_INPUT; i++) { - if (bool_input[i/8][i%8] == NULL) { + for (int i = 0; i < MAX_DIGITAL_INPUT; i++) + { + if (bool_input[i/8][i%8] == NULL) + { bool_input[i/8][i%8] = (IEC_BOOL *)malloc(sizeof(IEC_BOOL)); *bool_input[i/8][i%8] = 0; } } - for (int i = 0; i < MAX_ANALOG_INPUT; i++) { - if (int_input[i] == NULL) { + for (int i = 0; i < MAX_ANALOG_INPUT; i++) + { + if (int_input[i] == NULL) + { int_input[i] = (IEC_UINT *)(modbus.input_regs + i); } } #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) - for (int i = 0; i < MAX_MEMORY_WORD; i++) { - if (int_memory[i] == NULL) { + for (int i = 0; i < MAX_MEMORY_WORD; i++) + { + if (int_memory[i] == NULL) + { int_memory[i] = (IEC_UINT *)(modbus.holding + MAX_ANALOG_OUTPUT + i); } } - for (int i = 0; i < MAX_MEMORY_DWORD; i++) { - if (dint_memory[i] == NULL) { + for (int i = 0; i < MAX_MEMORY_DWORD; i++) + { + if (dint_memory[i] == NULL) + { dint_memory[i] = (IEC_UDINT *)(modbus.dint_memory + i); } } - for (int i = 0; i < MAX_MEMORY_LWORD; i++) { - if (lint_memory[i] == NULL) { + for (int i = 0; i < MAX_MEMORY_LWORD; i++) + { + if (lint_memory[i] == NULL) + { lint_memory[i] = (IEC_ULINT *)(modbus.lint_memory + i); } } @@ -348,41 +391,56 @@ void mapEmptyBuffers() { // ============================================================================= // MODBUS TASK (identical to current Baremetal.ino) // ============================================================================= -void modbusTask() { +void modbusTask() +{ // Sync OpenPLC Buffers with Modbus Buffers - for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) { - if (bool_output[i/8][i%8] != NULL) { + for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) + { + if (bool_output[i/8][i%8] != NULL) + { write_discrete(i, COILS, (bool)*bool_output[i/8][i%8]); } } - for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) { - if (int_output[i] != NULL) { + for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) + { + if (int_output[i] != NULL) + { modbus.holding[i] = *int_output[i]; } } - for (int i = 0; i < MAX_DIGITAL_INPUT; i++) { - if (bool_input[i/8][i%8] != NULL) { + for (int i = 0; i < MAX_DIGITAL_INPUT; i++) + { + if (bool_input[i/8][i%8] != NULL) + { write_discrete(i, INPUTSTATUS, (bool)*bool_input[i/8][i%8]); } } - for (int i = 0; i < MAX_ANALOG_INPUT; i++) { - if (int_input[i] != NULL) { + for (int i = 0; i < MAX_ANALOG_INPUT; i++) + { + if (int_input[i] != NULL) + { modbus.input_regs[i] = *int_input[i]; } } #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) - for (int i = 0; i < MAX_MEMORY_WORD; i++) { - if (int_memory[i] != NULL) { + for (int i = 0; i < MAX_MEMORY_WORD; i++) + { + if (int_memory[i] != NULL) + { modbus.holding[i + MAX_ANALOG_OUTPUT] = *int_memory[i]; } } - for (int i = 0; i < MAX_MEMORY_DWORD; i++) { - if (dint_memory[i] != NULL) { + for (int i = 0; i < MAX_MEMORY_DWORD; i++) + { + if (dint_memory[i] != NULL) + { modbus.dint_memory[i] = *dint_memory[i]; } } - for (int i = 0; i < MAX_MEMORY_LWORD; i++) { - if (lint_memory[i] != NULL) { + for (int i = 0; i < MAX_MEMORY_LWORD; i++) + { + if (lint_memory[i] != NULL) + { modbus.lint_memory[i] = *lint_memory[i]; } } @@ -392,29 +450,39 @@ void modbusTask() { mbtask(); // Write changes back to OpenPLC Buffers - for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) { - if (bool_output[i/8][i%8] != NULL) { + for (int i = 0; i < MAX_DIGITAL_OUTPUT; i++) + { + if (bool_output[i/8][i%8] != NULL) + { *bool_output[i/8][i%8] = get_discrete(i, COILS); } } - for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) { - if (int_output[i] != NULL) { + for (int i = 0; i < MAX_ANALOG_OUTPUT; i++) + { + if (int_output[i] != NULL) + { *int_output[i] = modbus.holding[i]; } } #if !defined(__AVR_ATmega328P__) && !defined(__AVR_ATmega168__) && !defined(__AVR_ATmega32U4__) && !defined(__AVR_ATmega16U4__) - for (int i = 0; i < MAX_MEMORY_WORD; i++) { - if (int_memory[i] != NULL) { + for (int i = 0; i < MAX_MEMORY_WORD; i++) + { + if (int_memory[i] != NULL) + { *int_memory[i] = modbus.holding[i + MAX_ANALOG_OUTPUT]; } } - for (int i = 0; i < MAX_MEMORY_DWORD; i++) { - if (dint_memory[i] != NULL) { + for (int i = 0; i < MAX_MEMORY_DWORD; i++) + { + if (dint_memory[i] != NULL) + { *dint_memory[i] = modbus.dint_memory[i]; } } - for (int i = 0; i < MAX_MEMORY_LWORD; i++) { - if (lint_memory[i] != NULL) { + for (int i = 0; i < MAX_MEMORY_LWORD; i++) + { + if (lint_memory[i] != NULL) + { *lint_memory[i] = modbus.lint_memory[i]; } } @@ -425,12 +493,15 @@ void modbusTask() { // ============================================================================= // PLC CYCLE TASK // ============================================================================= -void plcCycleTask() { +void plcCycleTask() +{ updateInputBuffers(); // Run each program according to its task divisor - for (size_t i = 0; i < total_programs; ++i) { - if (task_divisors[i] == 0 || (__tick % task_divisors[i]) == 0) { + for (size_t i = 0; i < total_programs; ++i) + { + if (task_divisors[i] == 0 || (__tick % task_divisors[i]) == 0) + { all_programs[i]->run(); } } @@ -443,7 +514,8 @@ void plcCycleTask() { // ============================================================================= // SCHEDULER // ============================================================================= -void scheduler() { +void scheduler() +{ plcCycleTask(); #ifdef USE_ARDUINO_SKETCH @@ -454,7 +526,8 @@ void scheduler() { modbusTask(); #endif - if (!first_cycle) { + if (!first_cycle) + { first_cycle = true; // Recalculate last_run to avoid time drift on the first cycle last_run = micros() - scan_cycle; @@ -464,15 +537,18 @@ void scheduler() { // ============================================================================= // MAIN LOOP // ============================================================================= -void loop() { - if ((micros() - last_run) >= scan_cycle) { +void loop() +{ + if ((micros() - last_run) >= scan_cycle) + { scheduler(); last_run += scan_cycle; } #ifdef MODBUS_ENABLED // Only run Modbus task again if we have at least 10ms gap until the next cycle - if ((micros() - last_run) >= 10000) { + if ((micros() - last_run) >= 10000) + { modbusTask(); } #endif From 6f267112716700355c1ab108f5fd161e5dbe35ce Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 16:43:13 -0400 Subject: [PATCH 034/296] docs: add Phase 4 debugger plan (scalable per-leaf addressing) New debugger design based on discussion: - Full leaf-level expansion, stored as {void* ptr, type_tag} entries in PROGMEM (Flash). Zero SRAM cost. - Multiple debug arrays (8000 entries each) to work around AVR's 32767-byte single-object limit that causes the current failure at ~33K leaves. - Protocol addressing: (array_idx: u8, elem_idx: u16). Wire format keeps FCs 0x41-0x45 with updated PDU layout. - Agnostic dispatch: type-tag indexed TypeOps table in the STruC++ runtime header, with templated force_impl / unforce_impl / read_impl per IEC elementary type. No per-project debug logic -- only the compiler-emitted pointer tables are project-specific. - debug-map.json replaces debug.c on the editor side. Upper-layer changes are minimal: composite-key tree, polling cadence, forcing UI, and Zustand shapes stay the same; only the address type changes from number to {arrayIdx, elemIdx}. - Two-stage rollout: Phase 4a polling only, Phase 4b adds subscribe (0x46) + unsolicited stream (0x48) for low-latency embedded. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/strucpp-migration/04-debugger.md | 494 +++++++++++++++++++++++--- 1 file changed, 439 insertions(+), 55 deletions(-) diff --git a/docs/strucpp-migration/04-debugger.md b/docs/strucpp-migration/04-debugger.md index c011ae188..40035b44a 100644 --- a/docs/strucpp-migration/04-debugger.md +++ b/docs/strucpp-migration/04-debugger.md @@ -1,57 +1,441 @@ # Phase 4: Debugger -## Status: Deferred - -This phase is intentionally deferred until after Phase 3 (Arduino runtime) is working and -stable. The debugger is complex and benefits from being designed with concrete knowledge of -how the runtime actually operates with STruC++ generated code. - -## Why Deferred - -1. **Better design context**: After Phases 2-3, we'll have a working STruC++ compilation and - execution pipeline. The runtime's actual structure, memory layout, and variable access - patterns will be concrete rather than theoretical. - -2. **Avoid premature complexity**: Earlier iterations of this plan included a TypeScript glue - code generator, compile wrapper, and hierarchical debug protocol. All of these were cut in - favor of a simpler static runtime approach. The debugger will likely benefit from similar - simplification once we see the full picture. - -3. **Clean slate**: Since MatIEC is fully removed, the debugger can be designed from scratch - without backward compatibility constraints. No need to support the old debug.c format or - flat-index protocol. - -## Known Requirements - -When this phase is picked up, it will need to address: - -### Core Problem -The current `debug.c` (generated by xml2st) creates a flat `debug_vars[]` array that expands -every array element individually. This causes 30,000+ entries for projects with ~3,500 -variables (many arrays), exceeding Arduino memory limits. - -### STruC++ Capabilities -- `IECVar` has built-in `force()` / `unforce()` / `is_forced()` / `get()` methods -- `VarDescriptor` arrays (used by the REPL) provide per-program variable metadata without - array expansion -- `ProgramBase` subclasses expose all variables as typed members -- `locatedVars[]` descriptors provide I/O variable metadata - -### What Needs to be Designed -- **Variable listing**: How the editor discovers what variables exist (replaces VARIABLES.csv) -- **Variable addressing**: How the editor references specific variables for read/force - (replaces flat debug index) -- **Protocol**: How variable data is exchanged between editor and device (replaces Modbus - custom function codes 0x41-0x45, or adapts them) -- **Array access**: How array elements are accessed without pre-expansion -- **Frontend**: How the debug variable tree is built and populated - -### Previous Analysis (for reference) -The earlier analysis in this migration plan explored: -- Hierarchical `(program_idx, var_idx)` addressing -- `debug-map.json` as a replacement for `debug.c` -- Lazy array element loading in the frontend -- Type-erased debug pointer arrays on the Arduino side - -These ideas may still be relevant but should be re-evaluated against the actual working -runtime before implementation. +## Status: Design locked, ready to implement + +## Goals + +- Replace the flat `debug_vars[]` mechanism (MatIEC + xml2st) with a scalable scheme built + on STruC++'s `IECVar` forcing API. +- Work well for small embedded targets (~50 variables on Arduino Mega) **and** large + Linux projects (50K+ variables on Runtime v4). +- Minimize rewrite of the editor's upper layers — the composite-key tree, polling loop, + forcing UI, and Zustand store should remain effectively unchanged. +- Full leaf-level addressability: every array element and every struct/FB field is + independently readable and forceable. + +## Why the current design fails + +The MatIEC pipeline generates `debug.c` containing a single `debug_vars[]` array with one +entry per **leaf** (arrays and structs expanded element-by-element). Real-world failure +mode observed on a user project: + +``` +src/debug.c:32926:1: error: size of array is too large +``` + +That project had ~33,000 leaves. AVR GCC's `size_t` is 16-bit, so a single object cannot +exceed 32,767 bytes — with a multi-field struct per entry the ceiling is hit well before +that element count. Moving metadata to Flash is necessary but not sufficient: the +*single-array* constraint itself is the blocker. + +## Design summary + +1. **Every leaf is expanded.** No runtime walking of composite variables — each array + element and struct/FB field gets its own table entry. +2. **Multiple debug arrays.** The compiler emits the table as a set of arrays, each capped + at 8,000 entries (safe margin under AVR's 32,767-byte object limit, assuming 4 B/entry). + On Linux the same split is used for consistency. +3. **Compact per-entry format.** `struct Entry { void* ptr; uint8_t type_tag; uint8_t _pad; }` + = 4 bytes. Entry table lives in Flash (`PROGMEM` on AVR, `.rodata` on Linux). Zero SRAM + cost. +4. **Agnostic runtime dispatcher.** Part of the STruC++ runtime headers — not per-project + generated code. A `TypeOps` table indexed by `type_tag` holds function pointers to + `force_impl`, `unforce_impl`, `read_impl` instantiated for each IEC elementary + type. Covers all leaves because STruC++ wraps every leaf as `IECVar` where T is an + elementary type. +5. **Protocol addressing: `(array_idx: u8, elem_idx: u16)`.** 256 arrays × 65K entries = + 16M addressable leaves. More than enough for any realistic project. +6. **Two-stage rollout:** polling-based first (Modbus FCs 0x41–0x45 with the new PDU + layout), subscription/stream later (0x46–0x48). Subscription is orthogonal to addressing + and can ship as a follow-up without breaking the base protocol. + +--- + +## What gets generated vs. what ships in the runtime + +### Per-project (emitted by `strucpp-compiler.ts`) + +**`generated_debug.cpp`** — pointer tables only: + +```cpp +#include "generated.hpp" +#include "strucpp/debug_dispatch.hpp" + +using namespace strucpp::debug; + +// Each array caps at ~8000 entries to stay under AVR's 32767-byte single-object limit. +const Entry debug_arr_0[] PROGMEM = { + { (void*)&g_config.INSTANCE0.blink, TAG_BOOL }, + { (void*)&g_config.INSTANCE0.counter, TAG_INT }, + { (void*)&g_config.INSTANCE0.speeds[0], TAG_INT }, + { (void*)&g_config.INSTANCE0.speeds[1], TAG_INT }, + // ... +}; +const Entry debug_arr_1[] PROGMEM = { /* next batch */ }; + +const Entry* const debug_arrays[] PROGMEM = { debug_arr_0, debug_arr_1 }; +const uint16_t debug_array_counts[] PROGMEM = { 8000, 5231 }; +const uint8_t debug_array_count = 2; +``` + +**`debug-map.json`** — editor-only manifest: + +```json +{ + "version": 2, + "md5": "", + "typeTags": { + "BOOL": 0, "SINT": 1, "INT": 2, "DINT": 3, "LINT": 4, + "REAL": 5, "LREAL": 6, "STRING": 7, "TIME": 8 + }, + "arrays": [ + { "index": 0, "count": 8000 }, + { "index": 1, "count": 5231 } + ], + "leaves": [ + { "arrayIdx": 0, "elemIdx": 0, "path": "INSTANCE0.blink", "type": "BOOL", "size": 1 }, + { "arrayIdx": 0, "elemIdx": 1, "path": "INSTANCE0.counter", "type": "INT", "size": 2 }, + { "arrayIdx": 0, "elemIdx": 2, "path": "INSTANCE0.speeds[0]", "type": "INT", "size": 2 }, + { "arrayIdx": 0, "elemIdx": 3, "path": "INSTANCE0.speeds[1]", "type": "INT", "size": 2 } + ] +} +``` + +Packing rule: emit leaves in declaration order, flush to a new debug array when the +current one reaches 8,000 entries **or** at a program boundary (whichever comes first). +Program-boundary flush isolates per-program churn from downstream arrays. + +### Shared across all projects (STruC++ runtime headers) + +**`strucpp/debug_dispatch.hpp`** — the generic handler, unchanged across projects: + +```cpp +namespace strucpp::debug { + +enum TypeTag : uint8_t { + TAG_BOOL = 0, TAG_SINT, TAG_USINT, TAG_INT, TAG_UINT, + TAG_DINT, TAG_UDINT, TAG_LINT, TAG_ULINT, + TAG_REAL, TAG_LREAL, + TAG_BYTE, TAG_WORD, TAG_DWORD, TAG_LWORD, + TAG_TIME, TAG_DATE, TAG_TOD, TAG_DT, + TAG_STRING, TAG_WSTRING, + TAG__COUNT +}; + +struct Entry { void* ptr; uint8_t tag; uint8_t _pad; }; + +template +static void force_impl(void* p, const uint8_t* bytes) { + T v; memcpy(&v, bytes, sizeof(T)); + static_cast*>(p)->force(v); +} +template +static void unforce_impl(void* p) { + static_cast*>(p)->unforce(); +} +template +static void read_impl(const void* p, uint8_t* dest) { + T v = static_cast*>(p)->get(); + memcpy(dest, &v, sizeof(T)); +} + +struct TypeOps { + void (*force) (void*, const uint8_t*); + void (*unforce)(void*); + void (*read) (const void*, uint8_t*); + uint8_t size; +}; + +constexpr TypeOps type_ops[TAG__COUNT] = { + /*BOOL */ { force_impl, unforce_impl, read_impl, 1 }, + /*SINT */ { force_impl, unforce_impl, read_impl, 1 }, + /*... */ + /*STRING*/ { /* special-case: variable-length */ nullptr, nullptr, nullptr, 0 }, +}; + +inline Entry read_entry(uint8_t arr, uint16_t elem); // PROGMEM-aware accessor + +inline void handle_set(uint8_t arr, uint16_t elem, bool forcing, const uint8_t* bytes) { + auto e = read_entry(arr, elem); + if (forcing) type_ops[e.tag].force(e.ptr, bytes); + else type_ops[e.tag].unforce(e.ptr); +} + +inline void handle_read(uint8_t arr, uint16_t elem, uint8_t* dest) { + auto e = read_entry(arr, elem); + type_ops[e.tag].read(e.ptr, dest); +} + +} // namespace strucpp::debug +``` + +STRING/WSTRING need special handling (variable length). Wire format: +`{uint16_t length, bytes[length]}`. Implementation reads/writes into `IECString` via +a specialization rather than the generic `read_impl` template. + +### PROGMEM access on ATmega2560 + +Debug tables will cross the 64 KB Flash boundary for large projects. The `read_entry()` +accessor uses `pgm_read_*_far()` on AVR, a plain array access everywhere else: + +```cpp +inline Entry read_entry(uint8_t arr, uint16_t elem) { +#ifdef __AVR__ + uint32_t base = pgm_get_far_address(debug_arrays); + const Entry* table = (const Entry*)pgm_read_word_far(base + arr * sizeof(void*)); + Entry e; + // read 4 bytes from PROGMEM, handling far address construction + uint32_t entry_addr = pgm_get_far_address(*table) + elem * sizeof(Entry); + e.ptr = (void*)pgm_read_word_far(entry_addr); + e.tag = pgm_read_byte_far(entry_addr + 2); + return e; +#else + return debug_arrays[arr][elem]; +#endif +} +``` + +Slight perf cost (~4 cycles extra per lookup) — irrelevant at debugger polling cadence. + +--- + +## Wire protocol + +Function codes keep the 0x41–0x45 numbering (same Modbus dispatcher structure), but the +addressing fields change from `u16 flat_index` to `(u8 array_idx, u16 elem_idx)`. + +| FC | Name | Request payload | Response payload | +|------|---------------------|--------------------------------------------------------|--------------------------------------------------| +| 0x41 | DEBUG_INFO | (empty) | `[array_count:u8, (elem_count:u16)×array_count]` | +| 0x42 | DEBUG_SET | `arr:u8, elem:u16, force:u8, len:u16, value...` | `status:u8` | +| 0x43 | DEBUG_GET_RANGE | `arr:u8, start_elem:u16, end_elem:u16` | `status:u8, last_elem:u16, tick:u32, size:u16, data...` | +| 0x44 | DEBUG_GET_LIST | `count:u16, (arr:u8, elem:u16)×count` | `status:u8, last_idx:u16, tick:u32, size:u16, data...` | +| 0x45 | DEBUG_GET_MD5 | `endian_check:u16` | `status:u8, md5:ascii, endian_echo:u16` | + +Phase 4b additions (subscribe/stream): + +| FC | Name | Request payload | Response payload | +|------|---------------------|--------------------------------------------------------|--------------------------------------------------| +| 0x46 | WATCH_SUBSCRIBE | `interval_ms:u16, count:u16, (arr:u8, elem:u16)×count` | `handle:u8, status:u8` | +| 0x47 | WATCH_UNSUBSCRIBE | `handle:u8` | `status:u8` | +| 0x48 | STREAM (unsolicited)| — | `handle:u8, tick:u32, size:u16, data...` | + +Notes: + +- Endianness: data payloads are native byte order of the target (no swap on the wire). + Editor probes with FC 0x45 and byte-swaps locally if target differs. Matches current + behavior. +- Chunking: same as today — if a GET_RANGE / GET_LIST response exceeds the Modbus frame + limit, the target returns what fits and reports `last_idx`. Editor retries from there. +- Per-array addressing implies that `DEBUG_GET_RANGE` operates within a single debug + array. Cross-array batch reads use `DEBUG_GET_LIST`. +- Unsolicited STREAM frames break strict Modbus master/slave semantics but are safe in + practice because OpenPLC targets use Modbus RTU over USB-CDC (full-duplex) or TCP. + RS-485 half-duplex users should stay on polling mode. + +--- + +## Implementation plan + +### 4.1 STruC++ runtime — debug dispatch headers *(ships in strucpp@≥0.3.0)* + +- `src/runtime/include/debug_dispatch.hpp` — `TypeTag` enum, `Entry` struct, `TypeOps` table, + templated `force_impl` / `unforce_impl` / `read_impl`, STRING/WSTRING specializations, + PROGMEM-aware `read_entry()`. +- `src/runtime/include/debug_handler.hpp` — protocol-level helpers: + `handle_info()`, `handle_set()`, `handle_get_range()`, `handle_get_list()`, + `handle_get_md5()` — frame-agnostic (take input/output buffers, return bytes written). +- Unit tests in the STruC++ repo covering the templated helpers with a mocked Entry table. + +**Exit criteria:** STruC++ runtime exports a single `strucpp::debug::handle_*` API that the +editor's Arduino sketch and the Runtime v4 `.so` can both call. No per-project code here. + +### 4.2 Editor — code generator for `generated_debug.cpp` + `debug-map.json` + +Location: `src/backend/shared/utils/PLC/generate-debug-table.ts` + +Inputs: +- `CompileResult` from the STruC++ compile wrapper (AST + symbol tables + project model). +- The `program.st` source (for MD5). + +Outputs (written to the board's `src/` directory alongside `generated.cpp`): +- `generated_debug.cpp` (Flash-resident pointer tables, packing rule described above). +- `debug-map.json` (editor-side path→address manifest). + +Core algorithm: + +``` +for each program instance in projectModel: + for each variable in program.vars (in declaration order): + walk(variable, path = "INSTANCE0.varName"): + if leaf (elementary type): + emit entry { &path, tag(type) } + elif array: + for i in dimensions: + walk(element, path = "${path}[${i}]") + elif struct/FB: + for field in fields: + walk(field, path = "${path}.${field.name}") + flush to new debug array // program-boundary flush +``` + +Cap per array at 8,000 entries; new array also starts when an element would push the +byte count past 32,000 (safety margin vs. AVR's 32,767 limit). + +### 4.3 Editor — compiler-module wiring + +`src/backend/editor/compiler/compiler-module.ts`: +- After `handleCompileSTtoCpp()` produces `generated.cpp/.hpp`, call + `generateDebugTable(compileResult)` to emit the two new files. +- Add `generated_debug.cpp` to the list of sources arduino-cli compiles (lives in the + `src/` library directory, picked up automatically). +- No changes to the Arduino sketch itself — it doesn't need to know about debug tables. + +### 4.4 Embedded — ModbusSlave integration + +`resources/sources/StrucppBaremetal/ModbusSlave.cpp`: +- Replace the existing 0x41–0x45 handler bodies (which call the MatIEC-era + `get_var_count()` / `get_var_addr()` / `set_trace()` weak externs) with direct calls + into `strucpp::debug::handle_*`. +- Drop the weak-extern declarations. +- Behavior change for FC 0x41: returns `{array_count, (elem_count)×N}` instead of a + single `var_count`. PDU grows slightly but remains under the Modbus frame limit even + for 256 arrays (≤513 bytes — chunk if exceeded, though realistic projects have ≤10 + arrays). + +### 4.5 Editor — frontend and middleware changes + +These are the **only** editor-side changes (kept minimal on purpose): + +**`src/middleware/shared/ports/debugger-port.ts`:** +```ts +export interface DebugAddr { arrayIdx: number; elemIdx: number } + +getVariablesList(refs: DebugAddr[]): Promise +setVariable(ref: DebugAddr, force: boolean, valueBuffer?: Uint8Array): Promise +readDebugMap(projectPath: string, boardTarget: string): Promise +``` + +**`src/frontend/utils/debug-parser.ts`:** Add `parseDebugMapV2()` alongside existing +`parseDebugFile()`. Both paths exist only long enough to flip users over — v1 (MatIEC) is +removed once Phase 4 ships. + +**`src/frontend/utils/debugger-session.ts` (`buildVariableIndexMap`):** The composite key +continues to be `pouName:varName.field[idx]`. The value stored in +`workspace.debugVariableIndexes` changes from `number` to `DebugAddr`. Everything +downstream that reads this map updates accordingly (a small, mechanical edit — the polling +loop, the force handler, the tree builder all go through this map). + +**`src/frontend/hooks/useDebugPolling.ts`:** No structural change — same batching logic, +same 50/200 ms cadences, same round-robin. Just passes `DebugAddr[]` through to the port +instead of `number[]`. + +**`src/frontend/hooks/useDebugSession.ts`:** Reads `debug-map.json` at session start +(via `debuggerPort.readDebugMap()`) instead of `debug.c`. The rest of the lifecycle +(MD5 verify, build tree, start polling) is unchanged. + +**Tree builder (`debug-tree-builder.ts` / `debug-tree-traversal.ts`):** Today it expands +arrays eagerly using the flat index. Under v2 it keeps doing the same expansion — the +source of truth moves from `debug.c` to `debug-map.json`, but the UI shape and composite +keys stay identical. A later optimization could lazy-load array children on expand, but +it's not needed for correctness and is out of scope for this phase. + +**IPC adapter (`debugger-adapter.ts`):** Serializes `DebugAddr` pairs over the bridge. +Trivial. + +### 4.6 Subscribe / stream (Phase 4b — follow-up) + +Deferred until Phase 4a is stable and the basic polling path is validated end-to-end. + +Target side: +- `strucpp::debug::handle_subscribe()` stores `{handle, interval_ms, address_list[]}` in + a fixed-size table (max ~4 subscriptions). On each scan cycle, if `tick * scan_ms >= + next_emit_time`, assemble a 0x48 frame and hand it to `ModbusSlave.sendUnsolicited()`. +- `ModbusSlave` gets a new `sendUnsolicited(frame, len)` method. Must not interleave with + a request currently being served — use a tiny flag. + +Editor side: +- `debuggerPort.subscribe(addrs, intervalMs) -> handle` and a handler in `useDebugPolling` + that, when subscriptions are active, stops polling those addresses and listens for + STREAM frames instead. + +### 4.7 Runtime v4 integration + +`src/backend/shared/utils/PLC/generate-v4-compat.ts` already exports C-linkage shims for +the Runtime v4 `.so`. Add: + +```c +extern "C" uint8_t strucpp_debug_array_count(); +extern "C" uint16_t strucpp_debug_elem_count(uint8_t arr); +extern "C" void strucpp_debug_set (uint8_t arr, uint16_t elem, bool force, + const uint8_t* bytes, uint16_t len); +extern "C" void strucpp_debug_read(uint8_t arr, uint16_t elem, + uint8_t* dest, uint16_t* size_out); +``` + +These are thin wrappers over `strucpp::debug::handle_*`. The runtime's existing +`debug_handler.c` is replaced by a much smaller shim that parses Modbus PDUs and calls +these exports. + +--- + +## Scalability summary + +| Project size | Debug arrays | Flash (table) | SRAM | +|--------------|--------------|---------------|------| +| 50 leaves | 1 | 200 B | 0 B | +| 500 leaves | 1 | 2 KB | 0 B | +| 3,500 leaves | 1 | 14 KB | 0 B | +| 20,000 leaves| 3 | 80 KB | 0 B | +| 50,000 leaves| 7 | 200 KB | 0 B | + +(AVR Mega has 256 KB Flash — fits projects up to ~50K leaves *in theory*; realistic +embedded deployments top out well below that.) + +--- + +## Testing strategy + +1. **Unit tests (STruC++ repo):** `debug_dispatch.hpp` force/read cycle for each + `TypeTag`, using a synthetic Entry table and a mock IECVar. +2. **Compile test:** run `generate-debug-table.ts` against a project with mixed scalars, + arrays, structs, FBs → verify `generated_debug.cpp` compiles on AVR (arduino-cli + `arduino:avr:mega`) and `debug-map.json` shape matches. +3. **Size regression:** the 35K-leaf user project that currently fails MatIEC must + compile cleanly with the new pipeline. +4. **End-to-end (Arduino Mega):** reuse the Chris Demo blink project. Force `blink := + TRUE` from the editor, verify PB7 stays HIGH across scan cycles. Unforce, verify + oscillation resumes. Validate in the avr8js simulator first, then hardware. +5. **End-to-end (Runtime v4):** same blink project compiled as `.so`, dlopen'd by the + runtime, debugger connects via WebSocket, force/read verified. +6. **Regression on existing hierarchical UI:** the composite-key tree, force badges, + graph/plot, and per-FB instance switching must render identically. + +--- + +## Out of scope for Phase 4 + +- Breakpoints / step / continue. STruC++ doesn't have source-level step support at this + point; separate initiative. +- On-demand / lazy array expansion in the UI. Full eager expansion is kept for + compatibility; an optimization pass can add lazy loading later if large-array + rendering becomes a bottleneck. +- Per-variable rate limiting on subscriptions. A single interval per subscription handle + is sufficient for Phase 4b. + +--- + +## Open items to confirm during implementation + +1. **`g_config` static address stability on AVR.** The `&g_config.INSTANCE0.counter` + expressions in `generated_debug.cpp` must be constant expressions for PROGMEM + initializers. If the AVR linker ever decides `g_config` needs dynamic construction + (it shouldn't — it's a static POD-constructible instance), we'd need to populate the + table at runtime in `setup()`. Verify with a test compile. +2. **String length encoding.** Fixed-size `IECString` has a runtime length field plus + up to N bytes of data. Wire encoding for Phase 4a: `{u16 len, bytes[len]}`. Confirm + that forcing a longer value than N is rejected cleanly (return an error status in FC + 0x42). +3. **MD5 scope.** Current MatIEC MD5 covers `program.st`. Under v2 the debug-map layout + depends on STruC++ version too — consider hashing `{program.st, strucpp_version}` so + that a runtime library bump invalidates stale editor state automatically. From 51e8c8275622e2f17b669badb544e51a773862f7 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 17:09:45 -0400 Subject: [PATCH 035/296] docs: move debug codegen ownership to STruC++ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Both the runtime dispatch headers AND the per-project generated files (generated_debug.cpp, debug-map.json) now originate in STruC++ via an extended compile() result: interface CompileResult { cppCode: string headerCode: string debugTableCpp: string // new debugMap: DebugMapV2 // new } The editor shrinks to a pure pass-through: it writes debugTableCpp to /src/generated_debug.cpp and JSON.stringify(debugMap) to debug-map.json. Name->address lookups read the same manifest. Rationale: colocating the pointer-table generator with the runtime headers it binds against guarantees they can never drift out of sync across STruC++ version bumps. Previously we had the editor emit cpp that referenced STruC++'s TypeTag enum — a silent desync hazard. Also: added STRUCPP_DEBUG_FLASH placement macro (PROGMEM on AVR, empty elsewhere) so generated_debug.cpp stays target-neutral. MD5 now hashes {program.st, strucpp_version, debugMap} inside STruC++ and is exposed via the same manifest. Co-Authored-By: Claude Opus 4.7 (1M context) --- docs/strucpp-migration/04-debugger.md | 148 ++++++++++++++++++-------- 1 file changed, 106 insertions(+), 42 deletions(-) diff --git a/docs/strucpp-migration/04-debugger.md b/docs/strucpp-migration/04-debugger.md index 40035b44a..2209451b3 100644 --- a/docs/strucpp-migration/04-debugger.md +++ b/docs/strucpp-migration/04-debugger.md @@ -32,20 +32,26 @@ that element count. Moving metadata to Flash is necessary but not sufficient: th 1. **Every leaf is expanded.** No runtime walking of composite variables — each array element and struct/FB field gets its own table entry. -2. **Multiple debug arrays.** The compiler emits the table as a set of arrays, each capped +2. **Multiple debug arrays.** STruC++ emits the table as a set of arrays, each capped at 8,000 entries (safe margin under AVR's 32,767-byte object limit, assuming 4 B/entry). On Linux the same split is used for consistency. 3. **Compact per-entry format.** `struct Entry { void* ptr; uint8_t type_tag; uint8_t _pad; }` = 4 bytes. Entry table lives in Flash (`PROGMEM` on AVR, `.rodata` on Linux). Zero SRAM cost. -4. **Agnostic runtime dispatcher.** Part of the STruC++ runtime headers — not per-project - generated code. A `TypeOps` table indexed by `type_tag` holds function pointers to - `force_impl`, `unforce_impl`, `read_impl` instantiated for each IEC elementary - type. Covers all leaves because STruC++ wraps every leaf as `IECVar` where T is an - elementary type. -5. **Protocol addressing: `(array_idx: u8, elem_idx: u16)`.** 256 arrays × 65K entries = +4. **All C++ artifacts owned by STruC++.** Both the shared runtime headers (dispatch + table, templated helpers) **and** the per-project generated code (`generated_debug.cpp` + + `debug-map.json`) are emitted by STruC++. The editor is a pure consumer: it writes + the files STruC++ returns from `compile()` to disk and reads `debug-map.json` for its + own name→address lookups. This keeps layout-sensitive code colocated with the + generator that produced it, so a STruC++ version bump can't desync runtime headers + from compiler output. +5. **Agnostic runtime dispatcher.** A `TypeOps` table indexed by `type_tag` holds + function pointers to `force_impl`, `unforce_impl`, `read_impl` instantiated + for each IEC elementary type. Covers all leaves because STruC++ wraps every leaf as + `IECVar` where T is an elementary type. No per-project dispatch code. +6. **Protocol addressing: `(array_idx: u8, elem_idx: u16)`.** 256 arrays × 65K entries = 16M addressable leaves. More than enough for any realistic project. -6. **Two-stage rollout:** polling-based first (Modbus FCs 0x41–0x45 with the new PDU +7. **Two-stage rollout:** polling-based first (Modbus FCs 0x41–0x45 with the new PDU layout), subscription/stream later (0x46–0x48). Subscription is orthogonal to addressing and can ship as a follow-up without breaking the base protocol. @@ -53,7 +59,29 @@ that element count. Moving metadata to Flash is necessary but not sufficient: th ## What gets generated vs. what ships in the runtime -### Per-project (emitted by `strucpp-compiler.ts`) +STruC++ owns every C++ artifact and the editor-side manifest. The editor's only job is +to persist them to disk and consume the manifest for name lookups. + +`compile()` is extended to return two additional fields alongside `cppCode` / +`headerCode`: + +```ts +interface CompileResult { + // existing + cppCode: string + headerCode: string + // new — Phase 4 + debugTableCpp: string // contents for generated_debug.cpp + debugMap: DebugMapV2 // path → (arrayIdx, elemIdx), serializable to JSON + // ... +} +``` + +The editor's `strucpp-compiler.ts` wrapper writes `debugTableCpp` to +`/src/generated_debug.cpp` and `JSON.stringify(debugMap)` to +`/src/debug-map.json`. That's the entire editor side of the pipeline. + +### Per-project artifacts (emitted by STruC++'s `compile()`) **`generated_debug.cpp`** — pointer tables only: @@ -64,21 +92,25 @@ that element count. Moving metadata to Flash is necessary but not sufficient: th using namespace strucpp::debug; // Each array caps at ~8000 entries to stay under AVR's 32767-byte single-object limit. -const Entry debug_arr_0[] PROGMEM = { +const Entry debug_arr_0[] STRUCPP_DEBUG_FLASH = { { (void*)&g_config.INSTANCE0.blink, TAG_BOOL }, { (void*)&g_config.INSTANCE0.counter, TAG_INT }, { (void*)&g_config.INSTANCE0.speeds[0], TAG_INT }, { (void*)&g_config.INSTANCE0.speeds[1], TAG_INT }, // ... }; -const Entry debug_arr_1[] PROGMEM = { /* next batch */ }; +const Entry debug_arr_1[] STRUCPP_DEBUG_FLASH = { /* next batch */ }; -const Entry* const debug_arrays[] PROGMEM = { debug_arr_0, debug_arr_1 }; -const uint16_t debug_array_counts[] PROGMEM = { 8000, 5231 }; -const uint8_t debug_array_count = 2; +const Entry* const debug_arrays[] STRUCPP_DEBUG_FLASH = { debug_arr_0, debug_arr_1 }; +const uint16_t debug_array_counts[] STRUCPP_DEBUG_FLASH = { 8000, 5231 }; +const uint8_t debug_array_count = 2; ``` -**`debug-map.json`** — editor-only manifest: +`STRUCPP_DEBUG_FLASH` is defined in `debug_dispatch.hpp` — expands to `PROGMEM` on AVR, +empty elsewhere. This keeps the generated code target-neutral; the runtime header +decides placement. + +**`debug-map.json`** — editor-consumed manifest, also emitted by STruC++: ```json { @@ -101,15 +133,24 @@ const uint8_t debug_array_count = 2; } ``` -Packing rule: emit leaves in declaration order, flush to a new debug array when the -current one reaches 8,000 entries **or** at a program boundary (whichever comes first). -Program-boundary flush isolates per-program churn from downstream arrays. +Packing rule (implemented by the STruC++ codegen): emit leaves in declaration order, +flush to a new debug array when the current one reaches 8,000 entries **or** at a +program boundary (whichever comes first). Program-boundary flush isolates per-program +churn from downstream arrays. ### Shared across all projects (STruC++ runtime headers) **`strucpp/debug_dispatch.hpp`** — the generic handler, unchanged across projects: ```cpp +// Flash-placement macro used by generated_debug.cpp +#ifdef __AVR__ +#include +#define STRUCPP_DEBUG_FLASH PROGMEM +#else +#define STRUCPP_DEBUG_FLASH +#endif + namespace strucpp::debug { enum TypeTag : uint8_t { @@ -250,19 +291,25 @@ Notes: **Exit criteria:** STruC++ runtime exports a single `strucpp::debug::handle_*` API that the editor's Arduino sketch and the Runtime v4 `.so` can both call. No per-project code here. -### 4.2 Editor — code generator for `generated_debug.cpp` + `debug-map.json` +### 4.2 STruC++ — debug table & map generator *(ships in strucpp@≥0.3.0)* -Location: `src/backend/shared/utils/PLC/generate-debug-table.ts` +Location: inside the STruC++ repo, alongside the existing `generated.cpp`/`generated.hpp` +emitter. Not a separate module — same AST walk that already produces the main C++ +output. Inputs: -- `CompileResult` from the STruC++ compile wrapper (AST + symbol tables + project model). -- The `program.st` source (for MD5). +- STruC++'s internal AST + symbol table + project model (already built for the main + compile pass). +- Target hint (optional): `"avr" | "arm" | "linux"` — only used to validate the 8,000 + entries/array cap is sufficient for the target. Emitted output is target-neutral + thanks to the `STRUCPP_DEBUG_FLASH` macro in the runtime header. -Outputs (written to the board's `src/` directory alongside `generated.cpp`): -- `generated_debug.cpp` (Flash-resident pointer tables, packing rule described above). -- `debug-map.json` (editor-side path→address manifest). +Outputs added to `CompileResult`: +- `debugTableCpp: string` — the full contents of `generated_debug.cpp`. +- `debugMap: DebugMapV2` — a structured object the editor serializes to + `debug-map.json`. -Core algorithm: +Core algorithm (lives in the STruC++ codegen): ``` for each program instance in projectModel: @@ -282,14 +329,27 @@ for each program instance in projectModel: Cap per array at 8,000 entries; new array also starts when an element would push the byte count past 32,000 (safety margin vs. AVR's 32,767 limit). +The TypeTag enum emitted into the cpp file **must match** the one in +`debug_dispatch.hpp`. Both live in the STruC++ repo, so this coupling is enforced by +colocation — no cross-repo drift possible. + +**Exit criteria:** `compile()` returns `debugTableCpp` + `debugMap` that together +compile + link + run correctly with the runtime headers. Unit-tested inside STruC++ +against projects with mixed scalars/arrays/structs/FBs. + ### 4.3 Editor — compiler-module wiring -`src/backend/editor/compiler/compiler-module.ts`: -- After `handleCompileSTtoCpp()` produces `generated.cpp/.hpp`, call - `generateDebugTable(compileResult)` to emit the two new files. -- Add `generated_debug.cpp` to the list of sources arduino-cli compiles (lives in the - `src/` library directory, picked up automatically). -- No changes to the Arduino sketch itself — it doesn't need to know about debug tables. +`src/backend/editor/compiler/compiler-module.ts` becomes a thin pass-through: + +- After `handleCompileSTtoCpp()` resolves with the extended `CompileResult`, write + `result.debugTableCpp` to `/src/generated_debug.cpp` and + `JSON.stringify(result.debugMap, null, 2)` to `/src/debug-map.json`. +- arduino-cli picks up `generated_debug.cpp` automatically (library dir is already + included). +- No changes to the Arduino sketch — it doesn't reference the debug tables directly; + the ModbusSlave handlers reach them via the runtime header's `read_entry()`. + +That's the entire editor-side generator change: two extra writeFile calls. ### 4.4 Embedded — ModbusSlave integration @@ -396,13 +456,15 @@ embedded deployments top out well below that.) ## Testing strategy -1. **Unit tests (STruC++ repo):** `debug_dispatch.hpp` force/read cycle for each - `TypeTag`, using a synthetic Entry table and a mock IECVar. -2. **Compile test:** run `generate-debug-table.ts` against a project with mixed scalars, - arrays, structs, FBs → verify `generated_debug.cpp` compiles on AVR (arduino-cli - `arduino:avr:mega`) and `debug-map.json` shape matches. -3. **Size regression:** the 35K-leaf user project that currently fails MatIEC must - compile cleanly with the new pipeline. +1. **STruC++ runtime tests:** `debug_dispatch.hpp` force/read cycle for each + `TypeTag`, using a synthetic Entry table and a mock IECVar. Covers all elementary + IEC types including STRING/WSTRING special-cases. +2. **STruC++ codegen tests:** `compile()` on projects with mixed scalars, arrays, + structs, FBs → `debugTableCpp` compiles cleanly with the runtime headers; + `debugMap` has the expected path/address entries; array packing respects the + 8,000-entry + program-boundary rules. +3. **Size regression (STruC++ + editor):** the 35K-leaf user project that currently + fails MatIEC must compile cleanly with the new pipeline end-to-end. 4. **End-to-end (Arduino Mega):** reuse the Chris Demo blink project. Force `blink := TRUE` from the editor, verify PB7 stays HIGH across scan cycles. Unforce, verify oscillation resumes. Validate in the avr8js simulator first, then hardware. @@ -436,6 +498,8 @@ embedded deployments top out well below that.) up to N bytes of data. Wire encoding for Phase 4a: `{u16 len, bytes[len]}`. Confirm that forcing a longer value than N is rejected cleanly (return an error status in FC 0x42). -3. **MD5 scope.** Current MatIEC MD5 covers `program.st`. Under v2 the debug-map layout - depends on STruC++ version too — consider hashing `{program.st, strucpp_version}` so - that a runtime library bump invalidates stale editor state automatically. +3. **MD5 scope.** Since STruC++ now owns both the runtime headers and the debug-map + generator, it should compute the MD5 itself over the inputs it actually consumed — + at minimum `{program.st, strucpp_version}`, optionally including the serialized + `debugMap` so any generator change invalidates stale editor state. Emit the MD5 + as a field on `debugMap` and expose the same value to the target via FC 0x45. From 438ae9bc3e359f78384142a51fe087af3908b18e Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 17:39:10 -0400 Subject: [PATCH 036/296] feat(compiler): write debug table and map from strucpp v0.3.0 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Bump strucpp pin to v0.3.0 (brings debug_dispatch.hpp and the debug-table-gen emitter added in that release). - handleCompileSTtoCpp now passes md5 into compile() so strucpp can embed it in debugMap, and writes: - generated_debug.cpp (result.debugTableCpp) - debug-map.json (JSON.stringify(result.debugMap)) into the board's src/ directory. arduino-cli picks up the new .cpp automatically since it lives in the library include path. - Drop `static` from g_config in StrucppBaremetal.ino. The debug table references g_config via compile-time address-of expressions in a separate TU, which needs external linkage. Validated: Chris Demo (Arduino Mega blink) compiles cleanly end-to-end at 6514 bytes flash / 443 bytes SRAM. debug-map.json produced with the expected single leaf (INSTANCE0.BLINK, BOOL). Debug table eliminated by LTO because nothing calls into strucpp::debug::handle_* yet — Phase 4.4 (ModbusSlave integration) wires the callers. Co-Authored-By: Claude Opus 4.7 (1M context) --- binary-versions.json | 2 +- .../sources/StrucppBaremetal/Baremetal.ino | 7 +++-- .../editor/compiler/compiler-module.ts | 30 +++++++++++++++++-- 3 files changed, 33 insertions(+), 6 deletions(-) diff --git a/binary-versions.json b/binary-versions.json index 68fdab108..3b137c8c6 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -4,7 +4,7 @@ "repository": "Autonomy-Logic/xml2st" }, "strucpp": { - "version": "v0.2.8", + "version": "v0.3.0", "repository": "Autonomy-Logic/STruCpp" } } diff --git a/resources/sources/StrucppBaremetal/Baremetal.ino b/resources/sources/StrucppBaremetal/Baremetal.ino index c9afd8c56..aa2d8ea53 100644 --- a/resources/sources/StrucppBaremetal/Baremetal.ino +++ b/resources/sources/StrucppBaremetal/Baremetal.ino @@ -59,9 +59,12 @@ IEC_ULINT *lint_memory[MAX_MEMORY_LWORD] = {}; #endif // --------------------------------------------------------------------------- -// STruC++ Configuration instance (always CONFIG0 in OpenPLC) +// STruC++ Configuration instance (always CONFIG0 in OpenPLC). +// NOT static — the debugger's generated_debug.cpp references this global +// via compile-time address-of expressions (extern declaration) so it must +// have external linkage. // --------------------------------------------------------------------------- -static strucpp::Configuration_CONFIG0 g_config; +strucpp::Configuration_CONFIG0 g_config; // --------------------------------------------------------------------------- // Task scheduling state (populated by discoverTasks) diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index a243bbf54..896369a41 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -472,11 +472,16 @@ class CompilerModule { // No libs directory available, compile without libraries } + // Precompute MD5 so STruC++ can embed it into debugMap (so the editor + // can detect stale layouts without re-reading program.st). + const md5Hash = crypto.createHash('md5').update(stSource).digest('hex') + const result = strucppCompile(stSource, { headerFileName: 'generated.hpp', debug: true, lineMapping: true, libraryPaths, + md5: md5Hash, }) if (!result.success) { @@ -491,10 +496,29 @@ class CompilerModule { await writeFile(join(sourceTargetFolderPath, 'generated.cpp'), result.cppCode, { encoding: 'utf8' }) await writeFile(join(sourceTargetFolderPath, 'generated.hpp'), result.headerCode, { encoding: 'utf8' }) - handleOutputData(`C++ files generated at: ${sourceTargetFolderPath}`, 'info') + // Phase 4 debugger artifacts (present starting with strucpp v0.3.0). + // debugTableCpp is the per-project pointer table for generated_debug.cpp. + // debugMap is the editor-consumed manifest (path -> (arrayIdx, elemIdx)). + if (result.debugTableCpp !== undefined) { + await writeFile( + join(sourceTargetFolderPath, 'generated_debug.cpp'), + result.debugTableCpp, + { encoding: 'utf8' }, + ) + } + if (result.debugMap !== undefined) { + await writeFile( + join(sourceTargetFolderPath, 'debug-map.json'), + JSON.stringify(result.debugMap, null, 2), + { encoding: 'utf8' }, + ) + handleOutputData( + `Debug map: ${result.debugMap.leaves.length} leaves in ${result.debugMap.arrays.length} arrays`, + 'info', + ) + } - // Compute MD5 hash directly from the ST source - const md5Hash = crypto.createHash('md5').update(stSource).digest('hex') + handleOutputData(`C++ files generated at: ${sourceTargetFolderPath}`, 'info') handleOutputData(`Program MD5: ${md5Hash}`, 'info') return { md5Hash } From 9bd43f8323fffc8d2634aa13c2eee2d40baf6690 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 17:44:37 -0400 Subject: [PATCH 037/296] feat(modbus): wire debug FCs 0x41-0x45 to strucpp::debug::handle_* MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rewrites the five debug-handler functions in ModbusSlave.cpp to call strucpp::debug::handle_* from debug_dispatch.hpp, using the new (array_idx: u8, elem_idx: u16) addressing: - FC 0x41 DEBUG_INFO response now carries [arrayCount, status, (elem_count × arrayCount)] instead of a single u16 count. - FC 0x42 DEBUG_SET parses (arr, elem, force, len, value) and calls handle_set. Returns the status code from handle_set directly. - FC 0x43 DEBUG_GET parses (arr, start, end) and loops handle_read within a single debug array. - FC 0x44 DEBUG_GET_LIST now takes 3-byte (arr:u8, elem:u16) pairs instead of 2-byte flat indexes. Last-index field now refers to position in the request list, not the target address space. - FC 0x45 DEBUG_GET_MD5 drops the set_endianness() side effect (no longer needed — STruC++ always emits native byte order and the editor swaps locally). The probe bytes are echoed at the end of the response for the editor to detect target byte order. ModbusSlave.h drops the old MatIEC-era weak externs (get_var_count, get_var_size, get_var_addr, force_var, set_trace, trace_reset, set_endianness) since the strucpp::debug namespace now owns that surface. Validated: Chris Demo project with MODBUS_ENABLED compiles to 15,946 bytes flash / 1,954 bytes SRAM on Arduino Mega. nm confirms debug_arrays, handle_set/read/size, force_impl, unforce_impl, type_ops all present in the elf — i.e. the debug dispatch chain is reachable from the scheduler via mbtask -> process_mbpacket. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../sources/StrucppBaremetal/ModbusSlave.cpp | 261 +++++++++--------- .../sources/StrucppBaremetal/ModbusSlave.h | 23 +- 2 files changed, 147 insertions(+), 137 deletions(-) diff --git a/resources/sources/StrucppBaremetal/ModbusSlave.cpp b/resources/sources/StrucppBaremetal/ModbusSlave.cpp index 0f1834c51..1fefc95f3 100644 --- a/resources/sources/StrucppBaremetal/ModbusSlave.cpp +++ b/resources/sources/StrucppBaremetal/ModbusSlave.cpp @@ -4,6 +4,7 @@ Copyright (C) 2022 OpenPLC - Thiago Alves */ #include "ModbusSlave.h" +#include "debug_dispatch.hpp" // Phase 4 debugger — strucpp::debug::handle_* //Global Modbus vars struct MBinfo modbus; @@ -505,11 +506,9 @@ void handle_serial() void process_mbpacket() { uint8_t fcode = mb_frame[1]; + // Standard Modbus fields — preserved for the non-debug FCs. uint16_t field1 = (uint16_t)mb_frame[2] << 8 | (uint16_t)mb_frame[3]; uint16_t field2 = (uint16_t)mb_frame[4] << 8 | (uint16_t)mb_frame[5]; - uint8_t flag = mb_frame[4]; - uint16_t len = (uint16_t)mb_frame[5] << 8 | (uint16_t)mb_frame[6]; - void *value = &mb_frame[7]; void *endianness_check = &mb_frame[2]; switch (fcode) @@ -559,18 +558,33 @@ void process_mbpacket() break; case MB_FC_DEBUG_GET: - //field1 = startidx, field2 = endidx - debugGetTrace(field1, field2); + { + // PDU: [FC:1][arr:u8][start_elem:u16][end_elem:u16] + uint8_t arr = mb_frame[2]; + uint16_t startIdx = (uint16_t)mb_frame[3] << 8 | (uint16_t)mb_frame[4]; + uint16_t endIdx = (uint16_t)mb_frame[5] << 8 | (uint16_t)mb_frame[6]; + debugGetTrace(arr, startIdx, endIdx); + } break; case MB_FC_DEBUG_GET_LIST: - //field1 = numIndexes - debugGetTraceList(field1, &mb_frame[4]); + { + // PDU: [FC:1][count:u16][(arr:u8, elem:u16)×count] + uint16_t numIndexes = (uint16_t)mb_frame[2] << 8 | (uint16_t)mb_frame[3]; + debugGetTraceList(numIndexes, &mb_frame[4]); + } break; case MB_FC_DEBUG_SET: - //field1 = varidx - debugSetTrace(field1, flag, len, value); + { + // PDU: [FC:1][arr:u8][elem:u16][force:u8][len:u16][value...] + uint8_t arr = mb_frame[2]; + uint16_t elem = (uint16_t)mb_frame[3] << 8 | (uint16_t)mb_frame[4]; + uint8_t flag = mb_frame[5]; + uint16_t len = (uint16_t)mb_frame[6] << 8 | (uint16_t)mb_frame[7]; + void *value = &mb_frame[8]; + debugSetTrace(arr, elem, flag, len, value); + } break; case MB_FC_DEBUG_GET_MD5: @@ -1051,13 +1065,32 @@ void writeMultipleCoils(uint16_t startreg, uint16_t numoutputs, uint16_t bytecou * * @return void */ +// Phase 4 PDU: +// +-----+-------+------+-----------+-----------+-----------+ +// | FC | arrs | stat | count_0 | count_1 | ... | +// |0x41 | (u8) | (u8) | (u16 BE) | (u16 BE) | | +// +-----+-------+------+-----------+-----------+-----------+ +// Response: [FC, arrCount, STATUS_OK, (count×arrCount as u16 BE)] void debugInfo() { - uint16_t variableCount = get_var_count(); - mb_frame_len = 4; + uint8_t arrCount = strucpp::debug::handle_array_count(); + + // Cap at what the Modbus frame can hold: 3 header bytes + 2 bytes/array. + // Realistic projects have <=10 arrays, so this is never a real limit. + uint8_t maxArrs = (MAX_MB_FRAME - 3) / 2; + if (arrCount > maxArrs) arrCount = maxArrs; + mb_frame[1] = MB_FC_DEBUG_INFO; - mb_frame[2] = (uint8_t)(variableCount >> 8); // High byte - mb_frame[3] = (uint8_t)(variableCount & 0xFF); // Low byte + mb_frame[2] = arrCount; + mb_frame[3] = MB_DEBUG_SUCCESS; + uint16_t pos = 4; + for (uint8_t i = 0; i < arrCount; i++) + { + uint16_t c = strucpp::debug::handle_elem_count(i); + mb_frame[pos++] = (uint8_t)(c >> 8); + mb_frame[pos++] = (uint8_t)(c & 0xFF); + } + mb_frame_len = pos; } /** @@ -1082,25 +1115,25 @@ void debugInfo() * * @return void */ -void debugSetTrace(uint16_t varidx, uint8_t flag, uint16_t len, void *value) +// Phase 4 PDU: [FC, arr, elem_hi, elem_lo, force, len_hi, len_lo, value...] +// Response: [FC, STATUS] +void debugSetTrace(uint8_t arr, uint16_t elem, uint8_t flag, + uint16_t len, void *value) { - uint16_t variableCount = get_var_count(); - if (varidx >= variableCount || len > (MAX_MB_FRAME - 7)) + if (len > (MAX_MB_FRAME - 8)) { - // Respond with an error indicating that the index is out of range mb_frame_len = 3; mb_frame[1] = MB_FC_DEBUG_SET; mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; return; } - // Execute set trace command - set_trace((size_t)varidx, (bool)flag, value); + uint8_t status = strucpp::debug::handle_set( + arr, elem, (bool)flag, (const uint8_t *)value, len); - // Response mb_frame_len = 3; mb_frame[1] = MB_FC_DEBUG_SET; - mb_frame[2] = MB_DEBUG_SUCCESS; + mb_frame[2] = status; } /** @@ -1123,58 +1156,58 @@ void debugSetTrace(uint16_t varidx, uint8_t flag, uint16_t len, void *value) * * @return void */ -void debugGetTrace(uint16_t startidx, uint16_t endidx) +// Phase 4 PDU: [FC, arr, start_hi, start_lo, end_hi, end_lo] +// Response: [FC, STATUS, last_elem_hi, last_elem_lo, +// tick_hi, tick_mh, tick_ml, tick_lo, +// size_hi, size_lo, data...] +void debugGetTrace(uint8_t arr, uint16_t startidx, uint16_t endidx) { - uint16_t variableCount = get_var_count(); - // Verify that startidx and endidx fall within the valid range of variables - if (startidx >= variableCount || endidx >= variableCount || startidx > endidx) + uint16_t arrCount = strucpp::debug::handle_elem_count(arr); + if (arrCount == 0 || startidx >= arrCount || + endidx >= arrCount || startidx > endidx) { - // Respond with an error indicating that the indices are out of range mb_frame_len = 3; mb_frame[1] = MB_FC_DEBUG_GET; mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; return; } - uint16_t lastVarIdx = startidx; - size_t responseSize = 0; - uint8_t *responsePtr = &(mb_frame[11]); // Start of response data + uint16_t lastElemIdx = startidx; + uint16_t responseSize = 0; + uint8_t *responsePtr = &(mb_frame[11]); - for (uint16_t varidx = startidx; varidx <= endidx; varidx++) + for (uint16_t elem = startidx; elem <= endidx; elem++) { - size_t varSize = get_var_size(varidx); - if ((responseSize + 11) + varSize <= MAX_MB_FRAME) // Make sure the response fits - { - void *varAddr = get_var_addr(varidx); - - // Copy the variable value to the response buffer - memcpy(responsePtr, varAddr, varSize); - - // Update response pointer and size - responsePtr += varSize; - responseSize += varSize; - - // Update the lastVarIdx - lastVarIdx = varidx; + uint16_t varSize = strucpp::debug::handle_size(arr, elem); + // Bounds check — stop packing if this one won't fit. + if ((11 + responseSize + varSize) > MAX_MB_FRAME) break; + if (varSize == 0) { + // Entry has no readable bytes (string stub / out-of-bounds) + // — skip gracefully to keep the scan progressing. + lastElemIdx = elem; + continue; } - else - { - // Response buffer is full, break the loop - break; + uint16_t n = strucpp::debug::handle_read(arr, elem, responsePtr); + if (n == 0) { + lastElemIdx = elem; + continue; } + responsePtr += n; + responseSize += n; + lastElemIdx = elem; } - mb_frame_len = 7 + responseSize; // Update response length + mb_frame_len = 11 + responseSize; mb_frame[1] = MB_FC_DEBUG_GET; mb_frame[2] = MB_DEBUG_SUCCESS; - mb_frame[3] = (uint8_t)(lastVarIdx >> 8); // High byte - mb_frame[4] = (uint8_t)(lastVarIdx & 0xFF); // Low byte - mb_frame[5] = (uint8_t)((__tick >> 24) & 0xFF); // Highest byte - mb_frame[6] = (uint8_t)((__tick >> 16) & 0xFF); // Second highest byte - mb_frame[7] = (uint8_t)((__tick >> 8) & 0xFF); // Second lowest byte - mb_frame[8] = (uint8_t)(__tick & 0xFF); // Lowest byte - mb_frame[9] = (uint8_t)(responseSize >> 8); // High byte - mb_frame[10] = (uint8_t)(responseSize & 0xFF); // Low byte + mb_frame[3] = (uint8_t)(lastElemIdx >> 8); + mb_frame[4] = (uint8_t)(lastElemIdx & 0xFF); + mb_frame[5] = (uint8_t)((__tick >> 24) & 0xFF); + mb_frame[6] = (uint8_t)((__tick >> 16) & 0xFF); + mb_frame[7] = (uint8_t)((__tick >> 8) & 0xFF); + mb_frame[8] = (uint8_t)(__tick & 0xFF); + mb_frame[9] = (uint8_t)(responseSize >> 8); + mb_frame[10] = (uint8_t)(responseSize & 0xFF); } /** @@ -1197,12 +1230,17 @@ void debugGetTrace(uint16_t startidx, uint16_t endidx) * * @return void */ +// Phase 4 PDU: [FC, count_hi, count_lo, (arr:u8, elem_hi, elem_lo)×count] +// Response: [FC, STATUS, last_idx_hi, last_idx_lo, +// tick_hi, tick_mh, tick_ml, tick_lo, +// size_hi, size_lo, data...] +// last_idx is the index *into the request list* that was last successfully +// included — the editor uses it to retry from the next item on overflow. void debugGetTraceList(uint16_t numIndexes, uint8_t *indexArray) { - uint16_t response_idx = 11; // Start of response data in the response buffer + uint16_t response_idx = 11; uint16_t responseSize = 0; - uint16_t lastVarIdx = 0; - uint16_t variableCount = get_var_count(); + uint16_t lastReqIdx = 0; #ifdef MBSERIAL #define VARIDX_SIZE 20 @@ -1210,98 +1248,69 @@ void debugGetTraceList(uint16_t numIndexes, uint8_t *indexArray) #define VARIDX_SIZE 60 #endif - uint16_t varidx_array[VARIDX_SIZE]; - - // Validate if buffer has space for all indexes if (numIndexes > VARIDX_SIZE) { - // Respond with a memory error mb_frame_len = 3; mb_frame[1] = MB_FC_DEBUG_GET_LIST; mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_MEMORY; return; } - // Copy all indexes to array + // Each address pair is 3 bytes: [arr:u8, elem_hi, elem_lo] for (uint16_t i = 0; i < numIndexes; i++) { - varidx_array[i] = (uint16_t)indexArray[i * 2] << 8 | indexArray[i * 2 + 1]; - } + uint8_t arr = indexArray[i * 3]; + uint16_t elem = (uint16_t)indexArray[i * 3 + 1] << 8 | + (uint16_t)indexArray[i * 3 + 2]; - // Validate if all requested indexes are in range - for (uint16_t i = 0; i < numIndexes; i++) - { - if (varidx_array[i] >= variableCount) + uint16_t varSize = strucpp::debug::handle_size(arr, elem); + if (varSize == 0) { - // Respond with an error indicating that the index is out of range - mb_frame_len = 3; - mb_frame[1] = MB_FC_DEBUG_GET_LIST; - mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; - return; + // Out-of-bounds or string stub — skip gracefully. + lastReqIdx = i; + continue; } + if ((response_idx + varSize) > MAX_MB_FRAME) break; - // Add requested indexes and their traces to the response buffer - size_t varSize = get_var_size(varidx_array[i]); - - // Make sure there is enough space in the response buffer - if (response_idx + varSize <= MAX_MB_FRAME) + uint16_t n = strucpp::debug::handle_read(arr, elem, &mb_frame[response_idx]); + if (n == 0) { - // Add variable data to the response buffer - void *varAddr = get_var_addr(varidx_array[i]); - memcpy(&mb_frame[response_idx], varAddr, varSize); - response_idx += varSize; - responseSize += varSize; - - // Update the lastVarIdx - lastVarIdx = varidx_array[i]; - } - else - { - // Response buffer is full, break the loop - break; + lastReqIdx = i; + continue; } + response_idx += n; + responseSize += n; + lastReqIdx = i; } - // Update response length, lastVarIdx, and response size mb_frame_len = response_idx; mb_frame[1] = MB_FC_DEBUG_GET_LIST; mb_frame[2] = MB_DEBUG_SUCCESS; - mb_frame[3] = (uint8_t)(lastVarIdx >> 8); // High byte - mb_frame[4] = (uint8_t)(lastVarIdx & 0xFF); // Low byte - mb_frame[5] = (uint8_t)((__tick >> 24) & 0xFF); // Highest byte - mb_frame[6] = (uint8_t)((__tick >> 16) & 0xFF); // Second highest byte - mb_frame[7] = (uint8_t)((__tick >> 8) & 0xFF); // Second lowest byte - mb_frame[8] = (uint8_t)(__tick & 0xFF); // Lowest byte - mb_frame[9] = (uint8_t)(responseSize >> 8); // High byte - mb_frame[10] = (uint8_t)(responseSize & 0xFF); // Low byte + mb_frame[3] = (uint8_t)(lastReqIdx >> 8); + mb_frame[4] = (uint8_t)(lastReqIdx & 0xFF); + mb_frame[5] = (uint8_t)((__tick >> 24) & 0xFF); + mb_frame[6] = (uint8_t)((__tick >> 16) & 0xFF); + mb_frame[7] = (uint8_t)((__tick >> 8) & 0xFF); + mb_frame[8] = (uint8_t)(__tick & 0xFF); + mb_frame[9] = (uint8_t)(responseSize >> 8); + mb_frame[10] = (uint8_t)(responseSize & 0xFF); } +// PDU request: [FC, endian_check_hi, endian_check_lo] +// PDU response: [FC, STATUS, md5_ascii..., endian_echo_hi, endian_echo_lo] +// +// The target always writes data in native byte order. The editor probes with +// 0xDEAD and reads back what arrived; if the bytes are reversed it byte-swaps +// debug reads locally. STruC++ makes no server-side byte-order adaptation — +// any memcpy dispatch is identical regardless of what the editor sent. void debugGetMd5(void *endianness) { - // Check endianness - uint16_t endian_check = 0; - memcpy(&endian_check, endianness, 2); - if (endian_check == 0xDEAD) - { - set_endianness(SAME_ENDIANNESS); - } - else if (endian_check == 0xADDE) - { - set_endianness(REVERSE_ENDIANNESS); - } - else - { - // Respond with an error indicating that the argument is wrong - mb_frame_len = 3; - mb_frame[1] = MB_FC_DEBUG_GET_MD5; - mb_frame[2] = MB_DEBUG_ERROR_OUT_OF_BOUNDS; - //return; - } + uint8_t echo_hi = ((uint8_t *)endianness)[0]; + uint8_t echo_lo = ((uint8_t *)endianness)[1]; mb_frame[1] = MB_FC_DEBUG_GET_MD5; mb_frame[2] = MB_DEBUG_SUCCESS; - // Copy MD5 string byte by byte to mb_frame starting from index 3 const char md5[] = PROGRAM_MD5; int md5_len = 0; for (md5_len = 0; md5[md5_len] != '\0'; md5_len++) @@ -1309,8 +1318,10 @@ void debugGetMd5(void *endianness) mb_frame[md5_len + 3] = md5[md5_len]; } - // Calculate mb_frame_len (MD5 string length + 3) - mb_frame_len = md5_len + 3; + // Echo the endianness probe bytes back to the editor. + mb_frame[md5_len + 3] = echo_hi; + mb_frame[md5_len + 4] = echo_lo; + mb_frame_len = md5_len + 5; } uint16_t calcCrc() diff --git a/resources/sources/StrucppBaremetal/ModbusSlave.h b/resources/sources/StrucppBaremetal/ModbusSlave.h index 74d1129e6..93bbeafaf 100644 --- a/resources/sources/StrucppBaremetal/ModbusSlave.h +++ b/resources/sources/StrucppBaremetal/ModbusSlave.h @@ -67,21 +67,17 @@ Copyright (C) 2022 OpenPLC - Thiago Alves #include "Controllino.h" #endif -// Debugger functions -extern "C" uint16_t get_var_count(void); -extern "C" size_t get_var_size(size_t);// {return 0;} -extern "C" void *get_var_addr(size_t);// {return 0;} -extern "C" void force_var(size_t, bool, void *);// {} -extern "C" void set_trace(size_t, bool, void *);// {} -extern "C" void trace_reset(void);// {} -extern "C" void set_endianness(uint8_t value); +// Scan-cycle tick counter defined by the Arduino sketch — reported in +// DEBUG_GET / DEBUG_GET_LIST responses so the editor can detect cycle +// boundaries. extern uint32_t __tick; +// Status codes (match strucpp::debug::STATUS_* in debug_dispatch.hpp, kept +// as macros here so the Modbus layer doesn't have to include the C++ +// runtime header when the rest of the protocol is C-style). #define MB_DEBUG_SUCCESS 0x7E #define MB_DEBUG_ERROR_OUT_OF_BOUNDS 0x81 #define MB_DEBUG_ERROR_OUT_OF_MEMORY 0x82 -#define SAME_ENDIANNESS 0 -#define REVERSE_ENDIANNESS 1 //Modbus registers struct struct MBinfo { @@ -181,9 +177,12 @@ void readInputStatus(uint16_t startreg, uint16_t numregs); void readInputRegisters(uint16_t startreg, uint16_t numregs); void writeSingleCoil(uint16_t reg, uint16_t status); void writeMultipleCoils(uint16_t startreg, uint16_t numoutputs, uint16_t bytecount); +// Phase 4 debugger entrypoints. Signatures changed from MatIEC-era +// (flat u16 index) to the (array_idx: u8, elem_idx: u16) addressing model. void debugInfo(void); -void debugSetTrace(uint16_t varidx, uint8_t flag, uint16_t len, void *value); -void debugGetTrace(uint16_t startidx, uint16_t endidx); +void debugSetTrace(uint8_t arr, uint16_t elem, uint8_t flag, + uint16_t len, void *value); +void debugGetTrace(uint8_t arr, uint16_t startidx, uint16_t endidx); void debugGetTraceList(uint16_t numIndexes, uint8_t *indexArray); void debugGetMd5(void *endianness); From a8dbac5ceb55f3be53f86b5a0319fdd9618d08a9 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 17:48:36 -0400 Subject: [PATCH 038/296] feat(debug): Phase 4 wire format for Modbus TCP + debug-map.json parser MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit modbus-client.ts (TCP): - DEBUG_GET_LIST encodes each address as (arr:u8, elem:u16) — 3 bytes per address instead of 2, matching the ModbusSlave change from Phase 4.4. The editor represents a DebugAddr as a packed u24 (arr << 16 | elem) so the existing store types stay unchanged. - DEBUG_SET PDU layout: [arr:u8, elem:u16, force, len:u16, value...] - DEBUG_GET_MD5 response parser strips the 2-byte endianness echo trailer introduced in Phase 4.4. debug-parser.ts: - Adds DebugAddr type, packDebugAddr/unpackDebugAddr helpers, and a parseDebugMapV2(content) that accepts the debug-map.json written by the editor's compile step (strucpp v0.3.0 CompileResult.debugMap). Legacy parseDebugFile remains available during transition. Still TODO for Phase 4.5: - RTU client PDU encoding (src/backend/editor/modbus/modbus-rtu-client.ts and src/backend/shared/simulator/modbus-rtu-client.ts) - WebSocket debug client (src/backend/editor/websocket/ websocket-debug-client.ts) - Web adapter (src/middleware/adapters/web/) if used - debugger-session.ts buildVariableIndexMap — consume DebugMapV2 - useDebugSession reading debug-map.json at session start - Update tests for the above Co-Authored-By: Claude Opus 4.7 (1M context) --- src/backend/editor/modbus/modbus-client.ts | 34 +++++++++--- src/frontend/utils/debug-parser.ts | 64 ++++++++++++++++++++++ 2 files changed, 89 insertions(+), 9 deletions(-) diff --git a/src/backend/editor/modbus/modbus-client.ts b/src/backend/editor/modbus/modbus-client.ts index b4aa107ff..a0597de84 100644 --- a/src/backend/editor/modbus/modbus-client.ts +++ b/src/backend/editor/modbus/modbus-client.ts @@ -153,7 +153,11 @@ export class ModbusTcpClient { throw new Error(`Target returned error code: 0x${statusCode.toString(16)}`) } - const md5String = data.slice(9).toString('utf-8').trim() + // Phase 4 response trailer echoes the endianness probe (2 bytes) at + // the end so the editor can detect target byte order. Strip it off + // before parsing the MD5 ASCII. + const md5Region = data.slice(9, data.length - 2) + const md5String = md5Region.toString('utf-8').replace(/\0+$/, '').trim() return md5String } @@ -174,7 +178,9 @@ export class ModbusTcpClient { const functionCode = ModbusFunctionCode.DEBUG_GET_LIST const numIndexes = variableIndexes.length - const pduLength = 4 + 2 * numIndexes + // Phase 4 PDU: each address is 3 bytes (arr:u8, elem_hi, elem_lo). + // Editor represents a DebugAddr as packed number: (arr << 16) | elem. + const pduLength = 4 + 3 * numIndexes const request = Buffer.alloc(6 + pduLength) request.writeUInt16BE(transactionId, 0) @@ -185,7 +191,11 @@ export class ModbusTcpClient { request.writeUInt16BE(numIndexes, 8) for (let i = 0; i < numIndexes; i++) { - request.writeUInt16BE(variableIndexes[i], 10 + i * 2) + const packed = variableIndexes[i]! + const arr = (packed >>> 16) & 0xff + const elem = packed & 0xffff + request.writeUInt8(arr, 10 + i * 3) + request.writeUInt16BE(elem, 10 + i * 3 + 1) } try { @@ -267,8 +277,13 @@ export class ModbusTcpClient { const unitId = 0x00 const functionCode = ModbusFunctionCode.DEBUG_SET + // Phase 4 PDU: [FC, arr:u8, elem:u16, force:u8, len:u16, value...] + // DebugAddr packed as (arr << 16) | elem on the JS side. + const arr = (variableIndex >>> 16) & 0xff + const elem = variableIndex & 0xffff + const dataLength = force && valueBuffer ? valueBuffer.length : 1 - const pduLength = 7 + dataLength + const pduLength = 8 + dataLength const request = Buffer.alloc(6 + pduLength) request.writeUInt16BE(transactionId, 0) @@ -276,16 +291,17 @@ export class ModbusTcpClient { request.writeUInt16BE(pduLength, 4) request.writeUInt8(unitId, 6) request.writeUInt8(functionCode, 7) - request.writeUInt16BE(variableIndex, 8) - request.writeUInt8(force ? 1 : 0, 10) - request.writeUInt16BE(dataLength, 11) + request.writeUInt8(arr, 8) + request.writeUInt16BE(elem, 9) + request.writeUInt8(force ? 1 : 0, 11) + request.writeUInt16BE(dataLength, 12) if (force && valueBuffer) { for (let i = 0; i < valueBuffer.length; i++) { - request.writeUInt8(valueBuffer[i], 13 + i) + request.writeUInt8(valueBuffer[i], 14 + i) } } else { - request.writeUInt8(0, 13) + request.writeUInt8(0, 14) } try { diff --git a/src/frontend/utils/debug-parser.ts b/src/frontend/utils/debug-parser.ts index 944427ac5..15a387d58 100644 --- a/src/frontend/utils/debug-parser.ts +++ b/src/frontend/utils/debug-parser.ts @@ -67,3 +67,67 @@ export function parseDebugFile(content: string): ParsedDebugData { return { variables, totalCount } } + +// --------------------------------------------------------------------------- +// Phase 4 debug-map.json parser (produced by STruC++ compile() -> debugMap). +// --------------------------------------------------------------------------- + +/** Address of a single leaf in the Phase 4 per-project debug table. */ +export interface DebugAddr { + arrayIdx: number + elemIdx: number +} + +export interface DebugMapLeafV2 { + arrayIdx: number + elemIdx: number + path: string + type: string + size: number +} + +export interface DebugMapV2 { + version: 2 + md5: string + typeTags: Record + arrays: Array<{ index: number; count: number }> + leaves: DebugMapLeafV2[] +} + +/** + * Pack a DebugAddr into a single number for compatibility with APIs that + * expect a flat u32-ish index (e.g. getVariablesList). arr goes in the high + * byte, elem in the low 16 bits: `(arr << 16) | elem`. + * + * This keeps the existing editor's store types (`Map`) + * unchanged while speaking the new (arr, elem) wire protocol downstream. + */ +export function packDebugAddr(addr: DebugAddr): number { + return ((addr.arrayIdx & 0xff) << 16) | (addr.elemIdx & 0xffff) +} + +/** Inverse of packDebugAddr — useful in tests / debugger UI tooltips. */ +export function unpackDebugAddr(packed: number): DebugAddr { + return { + arrayIdx: (packed >>> 16) & 0xff, + elemIdx: packed & 0xffff, + } +} + +/** + * Parse the debug-map.json written alongside generated_debug.cpp by the + * editor's compile step. Returns undefined when the content isn't a v2 + * manifest (lets callers transparently fall back to the legacy debug.c + * path while both coexist). + */ +export function parseDebugMapV2(content: string): DebugMapV2 | undefined { + try { + const raw = JSON.parse(content) as Partial + if (raw.version !== 2 || !Array.isArray(raw.leaves) || !Array.isArray(raw.arrays)) { + return undefined + } + return raw as DebugMapV2 + } catch { + return undefined + } +} From 72a5c163cf7dbae850d0c03f0db0041f43c6d6c9 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 22:13:58 -0400 Subject: [PATCH 039/296] feat(debug): port RTU/WebSocket/simulator + wire useDebugSession to v2 map MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Finishes Phase 4.5 so the debugger is usable end-to-end with the new (arr:u8, elem:u16) addressing. Clients ported to the Phase 4 PDU layout: - src/backend/editor/modbus/modbus-rtu-client.ts (editor RTU over serial): DEBUG_GET_LIST now sends 3-byte addresses, DEBUG_SET sends (arr, elem, force, len, value...), DEBUG_GET_MD5 response strips the 2-byte endianness echo trailer before decoding the MD5 ASCII. - src/backend/shared/simulator/modbus-rtu-client.ts (web/simulator web-compatible RTU): same three changes, using the Uint8Array helpers. - src/backend/editor/websocket/websocket-debug-client.ts (Runtime v4 WebSocket bridge): same three changes, over the hex-string transport. - Updated the simulator RTU test fixture for getMd5Hash to include the new endianness-echo trailer in the response payload. Frontend (session & debugger-session): - src/frontend/utils/debugger-session.ts adds buildVariableIndexMapV2 (composite-key -> packed DebugAddr from a DebugMapV2) and debugMapV2ToEntries (shims DebugMapV2 leaves into the shape the existing tree builder consumes, so the UI renders unchanged). - src/frontend/hooks/useDebugSession.ts tries parseDebugMapV2 first and falls back to the legacy parseDebugFile (debug.c) when the content isn't a v2 manifest. The polling loop, force handler, and workspace store types stay on number-valued indexes (v2 values are packed addresses, v1 values are flat indexes — indistinguishable to the polling code). Main process (readDebugFile): - src/main/modules/ipc/main.ts: reads debug-map.json in preference over debug.c so the renderer sees the v2 format for STruC++ projects and the legacy format for any remaining MatIEC projects. Validation: - TypeScript: clean (npx tsc --noEmit) - Jest: 3337 passed, 3 pre-existing failures unchanged (preprocess- pous, parse-project-files — not related to this PR) - RTU test suite (44 tests) passes including the updated MD5 fixture Co-Authored-By: Claude Opus 4.7 (1M context) --- .../editor/modbus/modbus-rtu-client.ts | 32 ++++-- .../websocket/websocket-debug-client.ts | 31 ++++-- .../__tests__/modbus-rtu-client.test.ts | 5 +- .../shared/simulator/modbus-rtu-client.ts | 33 ++++-- src/frontend/hooks/useDebugSession.ts | 45 ++++++-- src/frontend/utils/debugger-session.ts | 102 +++++++++++++++++- src/main/modules/ipc/main.ts | 14 ++- 7 files changed, 222 insertions(+), 40 deletions(-) diff --git a/src/backend/editor/modbus/modbus-rtu-client.ts b/src/backend/editor/modbus/modbus-rtu-client.ts index d0508829c..b3f329353 100644 --- a/src/backend/editor/modbus/modbus-rtu-client.ts +++ b/src/backend/editor/modbus/modbus-rtu-client.ts @@ -285,7 +285,10 @@ export class ModbusRtuClient { throw new Error(`Target returned error code: 0x${statusCode.toString(16)}`) } - const md5String = response.slice(9).toString('utf-8').trim() + // Phase 4: the MD5 response trailer echoes the 2-byte endianness + // probe so the editor can detect target byte order. Strip it. + const md5Region = response.slice(9, response.length - 2) + const md5String = md5Region.toString('utf-8').replace(/\0+$/, '').trim() return md5String } catch (error) { lastError = error instanceof Error ? error : new Error(getErrorMessage(error)) @@ -309,11 +312,17 @@ export class ModbusRtuClient { const functionCode = ModbusFunctionCode.DEBUG_GET_LIST const numIndexes = variableIndexes.length - const data = Buffer.alloc(2 + 2 * numIndexes) + // Phase 4 PDU: each address is (arr:u8, elem:u16) — 3 bytes. + // Editor represents DebugAddr as packed number: (arr << 16) | elem. + const data = Buffer.alloc(2 + 3 * numIndexes) data.writeUInt16BE(numIndexes, 0) for (let i = 0; i < numIndexes; i++) { - data.writeUInt16BE(variableIndexes[i], 2 + i * 2) + const packed = variableIndexes[i]! + const arr = (packed >>> 16) & 0xff + const elem = packed & 0xffff + data.writeUInt8(arr, 2 + i * 3) + data.writeUInt16BE(elem, 2 + i * 3 + 1) } const request = this.assembleRequest(functionCode, data) @@ -384,19 +393,24 @@ export class ModbusRtuClient { try { const functionCode = ModbusFunctionCode.DEBUG_SET + // Phase 4 PDU: [arr:u8, elem:u16, force:u8, len:u16, value...] + const arr = (variableIndex >>> 16) & 0xff + const elem = variableIndex & 0xffff + const dataLength = force && valueBuffer ? valueBuffer.length : 1 - const data = Buffer.alloc(5 + dataLength) + const data = Buffer.alloc(6 + dataLength) - data.writeUInt16BE(variableIndex, 0) - data.writeUInt8(force ? 1 : 0, 2) - data.writeUInt16BE(dataLength, 3) + data.writeUInt8(arr, 0) + data.writeUInt16BE(elem, 1) + data.writeUInt8(force ? 1 : 0, 3) + data.writeUInt16BE(dataLength, 4) if (force && valueBuffer) { for (let i = 0; i < valueBuffer.length; i++) { - data.writeUInt8(valueBuffer[i], 5 + i) + data.writeUInt8(valueBuffer[i], 6 + i) } } else { - data.writeUInt8(0, 5) + data.writeUInt8(0, 6) } const request = this.assembleRequest(functionCode, data) diff --git a/src/backend/editor/websocket/websocket-debug-client.ts b/src/backend/editor/websocket/websocket-debug-client.ts index f09373c74..8975e402e 100644 --- a/src/backend/editor/websocket/websocket-debug-client.ts +++ b/src/backend/editor/websocket/websocket-debug-client.ts @@ -138,7 +138,9 @@ export class WebSocketDebugClient { return } - const md5String = responseBuffer.slice(2).toString('utf-8').trim() + // Phase 4: response trailer echoes the 2-byte endianness probe. + const md5Region = responseBuffer.slice(2, responseBuffer.length - 2) + const md5String = md5Region.toString('utf-8').replace(/\0+$/, '').trim() resolve(md5String) } catch (error) { reject(error instanceof Error ? error : new Error(getErrorMessage(error))) @@ -164,12 +166,18 @@ export class WebSocketDebugClient { const functionCode = ModbusFunctionCode.DEBUG_GET_LIST const numIndexes = variableIndexes.length - const request = Buffer.alloc(3 + 2 * numIndexes) + // Phase 4 PDU: each address is (arr:u8, elem:u16) — 3 bytes. + // Editor packs DebugAddr as (arr << 16) | elem. + const request = Buffer.alloc(3 + 3 * numIndexes) request.writeUInt8(functionCode, 0) request.writeUInt16BE(numIndexes, 1) for (let i = 0; i < numIndexes; i++) { - request.writeUInt16BE(variableIndexes[i], 3 + i * 2) + const packed = variableIndexes[i]! + const arr = (packed >>> 16) & 0xff + const elem = packed & 0xffff + request.writeUInt8(arr, 3 + i * 3) + request.writeUInt16BE(elem, 3 + i * 3 + 1) } const commandHex = this.bufferToHexString(request) @@ -279,20 +287,25 @@ export class WebSocketDebugClient { const functionCode = ModbusFunctionCode.DEBUG_SET + // Phase 4 PDU: [FC, arr:u8, elem:u16, force:u8, len:u16, value...] + const arr = (variableIndex >>> 16) & 0xff + const elem = variableIndex & 0xffff + const dataLength = force && valueBuffer ? valueBuffer.length : 1 - const request = Buffer.alloc(6 + dataLength) + const request = Buffer.alloc(7 + dataLength) request.writeUInt8(functionCode, 0) - request.writeUInt16BE(variableIndex, 1) - request.writeUInt8(force ? 1 : 0, 3) - request.writeUInt16BE(dataLength, 4) + request.writeUInt8(arr, 1) + request.writeUInt16BE(elem, 2) + request.writeUInt8(force ? 1 : 0, 4) + request.writeUInt16BE(dataLength, 5) if (force && valueBuffer) { for (let i = 0; i < valueBuffer.length; i++) { - request.writeUInt8(valueBuffer[i], 6 + i) + request.writeUInt8(valueBuffer[i], 7 + i) } } else { - request.writeUInt8(0, 6) + request.writeUInt8(0, 7) } const commandHex = this.bufferToHexString(request) diff --git a/src/backend/shared/simulator/__tests__/modbus-rtu-client.test.ts b/src/backend/shared/simulator/__tests__/modbus-rtu-client.test.ts index 8c00e3627..eb293d310 100644 --- a/src/backend/shared/simulator/__tests__/modbus-rtu-client.test.ts +++ b/src/backend/shared/simulator/__tests__/modbus-rtu-client.test.ts @@ -259,9 +259,12 @@ describe('ModbusRtuClient', () => { const md5 = 'abc123def456' const md5Bytes = new TextEncoder().encode(md5) - const payload = new Uint8Array(1 + md5Bytes.length) + // Phase 4: response payload is [STATUS, md5_ascii..., endian_echo_hi, endian_echo_lo] + const payload = new Uint8Array(1 + md5Bytes.length + 2) payload[0] = ModbusDebugResponse.SUCCESS payload.set(md5Bytes, 1) + payload[1 + md5Bytes.length] = 0xde // endian echo + payload[1 + md5Bytes.length + 1] = 0xad autoRespond(buildResponse(1, ModbusFunctionCode.DEBUG_GET_MD5, payload)) const result = await client.getMd5Hash() diff --git a/src/backend/shared/simulator/modbus-rtu-client.ts b/src/backend/shared/simulator/modbus-rtu-client.ts index 696e7df43..a7e27c6a6 100644 --- a/src/backend/shared/simulator/modbus-rtu-client.ts +++ b/src/backend/shared/simulator/modbus-rtu-client.ts @@ -297,8 +297,10 @@ export class ModbusRtuClient { throw new Error(`Target returned error code: 0x${statusCode.toString(16)}`) } - const md5Bytes = response.slice(9) - const md5String = new TextDecoder().decode(md5Bytes).trim() + // Phase 4: strip the 2-byte endianness echo trailer before decoding + // the MD5 ASCII. + const md5Bytes = response.slice(9, response.length - 2) + const md5String = new TextDecoder().decode(md5Bytes).replace(/\0+$/, '').trim() return md5String } catch (error) { lastError = error instanceof Error ? error : new Error(String(error)) @@ -322,11 +324,17 @@ export class ModbusRtuClient { const functionCode = ModbusFunctionCode.DEBUG_GET_LIST const numIndexes = variableIndexes.length - const data = allocBytes(2 + 2 * numIndexes) + // Phase 4 PDU: (arr:u8, elem:u16) per address — 3 bytes each. + // Editor packs DebugAddr as (arr << 16) | elem. + const data = allocBytes(2 + 3 * numIndexes) writeUint16BE(data, 0, numIndexes) for (let i = 0; i < numIndexes; i++) { - writeUint16BE(data, 2 + i * 2, variableIndexes[i]) + const packed = variableIndexes[i]! + const arr = (packed >>> 16) & 0xff + const elem = packed & 0xffff + writeUint8(data, 2 + i * 3, arr) + writeUint16BE(data, 2 + i * 3 + 1, elem) } const request = this.assembleRequest(functionCode, data) @@ -397,17 +405,22 @@ export class ModbusRtuClient { try { const functionCode = ModbusFunctionCode.DEBUG_SET + // Phase 4 PDU: [arr:u8, elem:u16, force:u8, len:u16, value...] + const arr = (variableIndex >>> 16) & 0xff + const elem = variableIndex & 0xffff + const dataLength = force && valueBuffer ? valueBuffer.length : 1 - const data = allocBytes(5 + dataLength) + const data = allocBytes(6 + dataLength) - writeUint16BE(data, 0, variableIndex) - writeUint8(data, 2, force ? 1 : 0) - writeUint16BE(data, 3, dataLength) + writeUint8(data, 0, arr) + writeUint16BE(data, 1, elem) + writeUint8(data, 3, force ? 1 : 0) + writeUint16BE(data, 4, dataLength) if (force && valueBuffer) { - data.set(valueBuffer, 5) + data.set(valueBuffer, 6) } else { - writeUint8(data, 5, 0) + writeUint8(data, 6, 0) } const request = this.assembleRequest(functionCode, data) diff --git a/src/frontend/hooks/useDebugSession.ts b/src/frontend/hooks/useDebugSession.ts index f788ef42c..077c6ff2a 100644 --- a/src/frontend/hooks/useDebugSession.ts +++ b/src/frontend/hooks/useDebugSession.ts @@ -14,8 +14,14 @@ import { useCallback, useRef } from 'react' import type { DebugConnectionConfig, DebugTreeNode, FbInstanceInfo } from '../../middleware/shared/ports/types' import { useDebugger, useSimulator } from '../../middleware/shared/providers' import { useOpenPLCStore } from '../store' -import { parseDebugFile } from '../utils/debug-parser' -import { buildDebugVariableTreeMap, buildFbInstanceMap, buildVariableIndexMap } from '../utils/debugger-session' +import { parseDebugFile, parseDebugMapV2 } from '../utils/debug-parser' +import { + buildDebugVariableTreeMap, + buildFbInstanceMap, + buildVariableIndexMap, + buildVariableIndexMapV2, + debugMapV2ToEntries, +} from '../utils/debugger-session' import { hexToBytes } from '../utils/hex' export interface UseDebugSessionReturn { @@ -64,7 +70,9 @@ export function useDebugSession(): UseDebugSessionReturn { logActions.addLog({ id: crypto.randomUUID(), level: 'info', message: 'Connecting debugger...' }) try { - // Read debug file + // Read debug artifacts. Phase 4 (STruC++) projects ship + // debug-map.json; legacy MatIEC projects ship debug.c. The port's + // readDebugFile returns whichever exists — v2 JSON takes priority. const debugFileResult = await debuggerPort.readDebugFile(projectPath, boardTarget) if (!debugFileResult.success || !debugFileResult.content) { const error = `Failed to read debug file: ${debugFileResult.error ?? 'No content'}` @@ -74,12 +82,33 @@ export function useDebugSession(): UseDebugSessionReturn { wsActions.setDebugCContent(debugFileResult.content) - // Parse debug file and build variable maps - const parsed = parseDebugFile(debugFileResult.content) const instances = project.data.configurations.resource.instances - // Build variable index map - const { indexMap, warnings } = buildVariableIndexMap(project.data.pous, instances, parsed) + // Try the v2 (debug-map.json) path first; fall back to v1 (debug.c). + const v2 = parseDebugMapV2(debugFileResult.content) + + let indexMap: Map + let warnings: string[] + let entriesForTree: ReturnType + + if (v2) { + const v2Result = buildVariableIndexMapV2(project.data.pous, instances, v2) + indexMap = v2Result.indexMap + warnings = v2Result.warnings + entriesForTree = debugMapV2ToEntries(v2) + logActions.addLog({ + id: crypto.randomUUID(), + level: 'info', + message: `Debug map v2: ${v2.leaves.length} leaves across ${v2.arrays.length} arrays.`, + }) + } else { + const parsed = parseDebugFile(debugFileResult.content) + const v1Result = buildVariableIndexMap(project.data.pous, instances, parsed) + indexMap = v1Result.indexMap + warnings = v1Result.warnings + entriesForTree = parsed.variables + } + for (const w of warnings) { logActions.addLog({ id: crypto.randomUUID(), level: 'warning', message: w }) } @@ -88,7 +117,7 @@ export function useDebugSession(): UseDebugSessionReturn { let treeMap = new Map() const pouTrees: Record = {} try { - const treeResult = buildDebugVariableTreeMap(project.data.pous, instances, parsed.variables, project.data) + const treeResult = buildDebugVariableTreeMap(project.data.pous, instances, entriesForTree, project.data) treeMap = treeResult.treeMap // Group trees by POU name for polling hook diff --git a/src/frontend/utils/debugger-session.ts b/src/frontend/utils/debugger-session.ts index 4b7d4c6fb..d4f240c30 100644 --- a/src/frontend/utils/debugger-session.ts +++ b/src/frontend/utils/debugger-session.ts @@ -17,7 +17,8 @@ import type { PLCPou, PLCVariable, } from '../../middleware/shared/ports/types' -import type { DebugVariableEntry, ParsedDebugData } from './debug-parser' +import type { DebugMapV2, DebugVariableEntry, ParsedDebugData } from './debug-parser' +import { packDebugAddr } from './debug-parser' import { buildDebugTree } from './debug-tree-builder' import { buildDebugPathPrefix, @@ -140,6 +141,105 @@ export function buildVariableIndexMap( return { indexMap, warnings } } +// --------------------------------------------------------------------------- +// 1b. buildVariableIndexMapV2 — Phase 4 debug-map.json path +// --------------------------------------------------------------------------- + +/** + * Build a composite-key -> packed-DebugAddr map from a v2 DebugMap. + * + * The v2 map addresses variables as (arrayIdx, elemIdx) pairs; we pack those + * into a single number `(arr << 16) | elem` so downstream store types and + * the polling loop continue to see a plain `number` key, same as v1. + * + * Path convention emitted by STruC++: + * INSTANCE_NAME.VAR_NAME (scalar) + * INSTANCE_NAME.VAR_NAME[5] (array element, IEC-indexed) + * INSTANCE_NAME.FB_INST.FIELD (nested struct/FB field) + */ +export function buildVariableIndexMapV2( + pous: PLCPou[], + instances: PLCInstance[], + map: DebugMapV2, +): VariableIndexMapResult { + const indexMap = new Map() + const warnings: string[] = [] + + // Build a path -> packed-address lookup (case-insensitive). + const pathToAddr = new Map() + for (const leaf of map.leaves) { + pathToAddr.set(leaf.path.toUpperCase(), packDebugAddr(leaf)) + } + + const instanceMappings: PLCInstanceMapping[] = instances.map((inst) => ({ + name: inst.name, + program: inst.program, + })) + + pous.forEach((pou) => { + if (pou.pouType !== 'program') return + + const instanceName = findInstanceName(pou.name, instanceMappings) + if (!instanceName) { + warnings.push(`No instance found for program '${pou.name}', skipping debug variable parsing.`) + return + } + + const upperInstance = instanceName.toUpperCase() + const variables = pou.interface?.variables ?? [] + + variables.forEach((v: PLCVariable) => { + if (v.type.definition === 'array' && v.type.data) { + const dimensions = v.type.data.dimensions + if (dimensions.length > 0) { + const dimMatch = dimensions[0].dimension.match(/^(-?\d+)\.\.(-?\d+)$/) + if (dimMatch) { + const startIdx = parseInt(dimMatch[1], 10) + const endIdx = parseInt(dimMatch[2], 10) + for (let i = 0; i <= endIdx - startIdx; i++) { + const iecIdx = startIdx + i + const path = `${upperInstance}.${v.name.toUpperCase()}[${iecIdx}]` + const addr = pathToAddr.get(path) + if (addr !== undefined) { + indexMap.set(`${pou.name}:${v.name}[${iecIdx}]`, addr) + } + } + } + } + } else { + const path = `${upperInstance}.${v.name.toUpperCase()}` + const addr = pathToAddr.get(path) + if (addr !== undefined) { + indexMap.set(`${pou.name}:${v.name}`, addr) + } + } + }) + }) + + // Fallback: also key by the raw debug path so any leaves we didn't cover + // (nested fields, FB internals) remain reachable by path. + for (const leaf of map.leaves) { + if (!indexMap.has(leaf.path)) { + indexMap.set(leaf.path, packDebugAddr(leaf)) + } + } + + return { indexMap, warnings } +} + +/** + * Synthesize a DebugVariableEntry[] from a DebugMapV2 so the existing tree + * builder (which consumes v1-shaped data) works unchanged. The `index` + * field carries the packed (arr<<16|elem) address. + */ +export function debugMapV2ToEntries(map: DebugMapV2): DebugVariableEntry[] { + return map.leaves.map((leaf) => ({ + name: leaf.path, + type: `${leaf.type}_ENUM`, + index: packDebugAddr(leaf), + })) +} + // --------------------------------------------------------------------------- // 2. buildDebugVariableTreeMap // --------------------------------------------------------------------------- diff --git a/src/main/modules/ipc/main.ts b/src/main/modules/ipc/main.ts index b5f78ac2b..3c2dc1521 100644 --- a/src/main/modules/ipc/main.ts +++ b/src/main/modules/ipc/main.ts @@ -832,14 +832,24 @@ class MainProcessBridge implements MainIpcModule { if (path.isAbsolute(boardTarget) || boardTarget.includes('..') || boardTarget.includes(path.sep)) { return { success: false, error: 'Invalid board target' } } - const debugFilePath = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug.c') + // Phase 4 (STruC++) projects ship debug-map.json; legacy MatIEC + // projects ship debug.c. Prefer v2 when present so the renderer's + // parseDebugMapV2 picks it up. + const v2Path = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug-map.json') + try { + const v2Content = await fs.readFile(v2Path, 'utf-8') + return { success: true, content: v2Content } + } catch { + // Fall through to legacy debug.c + } + const debugFilePath = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug.c') const content = await fs.readFile(debugFilePath, 'utf-8') return { success: true, content } } catch (error) { return { success: false, - error: error instanceof Error ? error.message : 'Failed to read debug.c file', + error: error instanceof Error ? error.message : 'Failed to read debug file', } } } From c8d4e2ddab7a8ed3beb585e205a5a8a1b19c4c04 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Mon, 20 Apr 2026 22:37:03 -0400 Subject: [PATCH 040/296] feat(debug): add Phase 4 end-to-end integration test; bump strucpp to v0.3.2 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit debug-e2e.test.ts drives the Chris Demo firmware through the full Phase 4 stack (avr8js + ModbusRtuClient + VirtualSerialPort) and validates: 1. FC 0x45 DEBUG_GET_MD5 returns a 32-char MD5 2. FC 0x42 DEBUG_SET force blink=TRUE with the new PDU layout, then FC 0x44 DEBUG_GET_LIST reads back 1 — proving the force survives multiple scan cycles (the PLC program writes `BLINK := TOF0.Q` every cycle, which must NOT clobber the forced state) 3. FC 0x42 DEBUG_SET unforce Test 2 is the one that caught the IECVar copy-assignment bug fixed in strucpp v0.3.2 — without that fix, the forced value was silently overwritten by the scan cycle and reads returned 0. Skipped in CI by default; reproduce locally by setting CHRIS_DEMO_HEX to a built hex. binary-versions.json bumped to v0.3.2 (brings the IECVar fix and the explicit force_impl specialization). Co-Authored-By: Claude Opus 4.7 (1M context) --- binary-versions.json | 2 +- .../simulator/__tests__/debug-e2e.test.ts | 88 +++++++++++++++++++ 2 files changed, 89 insertions(+), 1 deletion(-) create mode 100644 src/backend/shared/simulator/__tests__/debug-e2e.test.ts diff --git a/binary-versions.json b/binary-versions.json index 3b137c8c6..525965de7 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -4,7 +4,7 @@ "repository": "Autonomy-Logic/xml2st" }, "strucpp": { - "version": "v0.3.0", + "version": "v0.3.2", "repository": "Autonomy-Logic/STruCpp" } } diff --git a/src/backend/shared/simulator/__tests__/debug-e2e.test.ts b/src/backend/shared/simulator/__tests__/debug-e2e.test.ts new file mode 100644 index 000000000..5bb6cfb29 --- /dev/null +++ b/src/backend/shared/simulator/__tests__/debug-e2e.test.ts @@ -0,0 +1,88 @@ +/** + * End-to-end debugger validation over avr8js. + * + * Boots the Chris Demo firmware in the simulator, drives it through the + * real ModbusRtuClient + VirtualSerialPort + SimulatorModule stack, and + * verifies the Phase 4 wire protocol round-trips correctly. + * + * Runs only when CHRIS_DEMO_HEX env var points at a compiled .hex file. + * CI skips it by default because it depends on an AVR toolchain + built + * firmware. Local reproduction: + * + * 1. Build the Chris Demo project via the editor (or manually invoke + * strucpp + arduino-cli on a project with a located BOOL variable) + * targeting arduino:avr:mega with MODBUS_ENABLED + MBSERIAL defined. + * 2. export CHRIS_DEMO_HEX=/path/to/Baremetal.ino.hex + * 3. npx jest src/backend/shared/simulator/__tests__/debug-e2e.test.ts + */ + +import fs from 'node:fs' +import path from 'node:path' + +import { ModbusRtuClient } from '../modbus-rtu-client' +import { SimulatorModule } from '../simulator-module' +import { VirtualSerialPort } from '../virtual-serial-port' + +// jsdom polyfill — matches modbus-rtu-client.test.ts. +if (typeof globalThis.TextDecoder === 'undefined') { + // eslint-disable-next-line @typescript-eslint/no-var-requires + const { TextEncoder, TextDecoder } = require('util') + globalThis.TextEncoder = TextEncoder + globalThis.TextDecoder = TextDecoder as typeof globalThis.TextDecoder +} + +const HEX_PATH = process.env.CHRIS_DEMO_HEX ?? '' +const HEX_EXISTS = HEX_PATH !== '' && fs.existsSync(HEX_PATH) +const describeIfHex: typeof describe = HEX_EXISTS ? describe : describe.skip + +describeIfHex('Phase 4 debugger end-to-end (avr8js + ModbusRtuClient)', () => { + let sim: SimulatorModule + let vsp: VirtualSerialPort + let client: ModbusRtuClient + + beforeAll(async () => { + const hexContent = fs.readFileSync(path.resolve(HEX_PATH), 'utf-8') + sim = new SimulatorModule() + sim.loadAndRun(hexContent) + vsp = new VirtualSerialPort(sim) + client = new ModbusRtuClient({ slaveId: 1, timeout: 5000, serialPort: vsp }) + await client.connect() + }, 30000) + + afterAll(() => { + client?.disconnect() + sim?.stop() + }) + + it('FC 0x45 DEBUG_GET_MD5 returns a 32-char MD5', async () => { + const md5 = await client.getMd5Hash() + expect(md5).toMatch(/^[0-9a-f]{32}$/) + }, 30000) + + it('FC 0x42 DEBUG_SET force blink=TRUE → FC 0x44 read returns 1', async () => { + const addr = 0 // packed (arr=0, elem=0) + + const setResult = await client.setVariable(addr, true, new Uint8Array([1])) + expect(setResult.success).toBe(true) + + // Let a few scan cycles run so we exercise the "forced value survives + // across PLC writes" path (generated code does `BLINK := TOF0.Q` every + // cycle, which must not overwrite the forced state). + await new Promise((r) => setTimeout(r, 200)) + + const read = await client.getVariablesList([addr]) + expect(read.success).toBe(true) + expect(read.data).toBeDefined() + expect(read.data!.length).toBe(1) + expect(read.data![0]).toBe(1) + }, 30000) + + it('FC 0x42 DEBUG_SET unforce → blink resumes PLC control', async () => { + const addr = 0 + const unforce = await client.setVariable(addr, false) + expect(unforce.success).toBe(true) + // We don't assert on a subsequent read — racing the scan cycle is + // non-deterministic and this test already validated at the SET layer + // that the protocol accepts the unforce request. + }, 30000) +}) From 695db4530d90890972a225f677314abe51c766ac Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 07:26:37 -0400 Subject: [PATCH 041/296] fix(debug): read MD5 from debug-map.json for STruC++ projects handleReadProgramStMd5 was grepping program.st for the MatIEC-era `(*DBG:char md5[] = "..."*)` comment, which STruC++ doesn't emit. This caused "MD5 Extraction Failed" at debugger startup for every Phase 4 project. Read md5 from debug-map.json first (that's where compiler-module.ts writes the hash strucpp embedded); fall back to the legacy comment parser for any remaining MatIEC-built projects. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/main/modules/ipc/main.ts | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) diff --git a/src/main/modules/ipc/main.ts b/src/main/modules/ipc/main.ts index 3c2dc1521..fae1ebe61 100644 --- a/src/main/modules/ipc/main.ts +++ b/src/main/modules/ipc/main.ts @@ -983,22 +983,36 @@ class MainProcessBridge implements MainIpcModule { const fs = await import('fs/promises') const path = await import('path') - // projectPath is already the project directory, not a file path // Guard against traversal/absolute input in boardTarget if (path.isAbsolute(boardTarget) || boardTarget.includes('..') || boardTarget.includes(path.sep)) { return { success: false, error: 'Invalid board target' } } - const programStPath = path.resolve(projectPath, 'build', boardTarget, 'src', 'program.st') - const content = await fs.readFile(programStPath, 'utf-8') + // Phase 4 (STruC++) projects store the MD5 in debug-map.json. Prefer + // that — compiler-module.ts computes md5 from the ST source and the + // debug-table-gen embeds it into the manifest so the editor sees the + // same value the target sees via FC 0x45. + const debugMapPath = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug-map.json') + try { + const raw = await fs.readFile(debugMapPath, 'utf-8') + const parsed = JSON.parse(raw) as { md5?: unknown } + if (typeof parsed.md5 === 'string' && /^[a-fA-F0-9]{32}$/.test(parsed.md5)) { + return { success: true, md5: parsed.md5 } + } + } catch { + // Fall through to legacy program.st comment + } + // Legacy (MatIEC) projects carry the MD5 as a DBG comment in program.st. + const programStPath = path.resolve(projectPath, 'build', boardTarget, 'src', 'program.st') + const content = await fs.readFile(programStPath, 'utf-8') const md5Pattern = /\(\*DBG:char md5\[\] = "([a-fA-F0-9]{32})";?\*\)/ const match = content.match(md5Pattern) if (!match || !match[1]) { return { success: false, - error: 'Could not find MD5 hash in program.st file', + error: 'Could not find MD5 hash in debug-map.json or program.st', } } @@ -1006,7 +1020,7 @@ class MainProcessBridge implements MainIpcModule { } catch (error) { return { success: false, - error: error instanceof Error ? error.message : 'Failed to read program.st file', + error: error instanceof Error ? error.message : 'Failed to read MD5', } } } From ba529889e4ab1c507e20837b80abd3928051eadd Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 07:33:48 -0400 Subject: [PATCH 042/296] =?UTF-8?q?refactor(debug):=20drop=20all=20MatIEC?= =?UTF-8?q?=20fallbacks=20=E2=80=94=20debug-map.json=20is=20the=20only=20p?= =?UTF-8?q?ath?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit No more backward compatibility with the flat debug.c / MatIEC comment formats. STruC++ writes debug-map.json with an md5 field, and the editor reads it directly. Changes: - main IPC handleReadProgramStMd5: reads md5 from debug-map.json only; the program.st `(*DBG:char md5[]..*)` fallback is gone. Returns a clear "debug-map.json is missing a valid md5 field" error when the manifest is malformed. - main IPC handleReadDebugFile: reads debug-map.json only; the debug.c fallback is gone. - useDebugSession: no longer probes v2 vs v1 — parses debug-map.json directly and errors out on a malformed manifest. Dropped the v1 branch entirely. - debug-parser.ts: dropped parseDebugFile / parseDebugVariables / ParsedDebugData. DebugVariableEntry is kept (it's the shape debugMapV2ToEntries feeds to the tree builder). - debugger-session.ts: dropped buildVariableIndexMap v1. Only buildVariableIndexMapV2 remains; dead imports purged from debug-variable-finder. - Tests: debug-parser.test.ts removed entirely; debugger-session tests replaced with v2 equivalents that exercise packed DebugAddr keys; debug-variable-finder re-export test removed. Validated: 3317 passing + 3 pre-existing failures (unrelated), zero regressions from this refactor. TypeScript clean. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/frontend/hooks/useDebugSession.ts | 44 +-- .../utils/__tests__/debug-parser.test.ts | 94 ------ .../__tests__/debug-variable-finder.test.ts | 8 - .../utils/__tests__/debugger-session.test.ts | 290 ++++-------------- src/frontend/utils/debug-parser.ts | 108 ++----- src/frontend/utils/debug-variable-finder.ts | 7 +- src/frontend/utils/debugger-session.ts | 105 +------ src/main/modules/ipc/main.ts | 57 +--- 8 files changed, 133 insertions(+), 580 deletions(-) delete mode 100644 src/frontend/utils/__tests__/debug-parser.test.ts diff --git a/src/frontend/hooks/useDebugSession.ts b/src/frontend/hooks/useDebugSession.ts index 077c6ff2a..a1727d4a6 100644 --- a/src/frontend/hooks/useDebugSession.ts +++ b/src/frontend/hooks/useDebugSession.ts @@ -1,8 +1,9 @@ /** * Debug Session Hook * - * Manages the debug session lifecycle: read debug.c, build index/tree maps, - * commit debug artifacts to the store, connect/disconnect via DebuggerPort. + * Manages the debug session lifecycle: read debug-map.json, build index/tree + * maps, commit debug artifacts to the store, connect/disconnect via + * DebuggerPort. * * Platform-agnostic — all protocol operations are delegated to the * DebuggerPort and SimulatorPort provided by the PlatformProvider. @@ -14,11 +15,10 @@ import { useCallback, useRef } from 'react' import type { DebugConnectionConfig, DebugTreeNode, FbInstanceInfo } from '../../middleware/shared/ports/types' import { useDebugger, useSimulator } from '../../middleware/shared/providers' import { useOpenPLCStore } from '../store' -import { parseDebugFile, parseDebugMapV2 } from '../utils/debug-parser' +import { parseDebugMapV2 } from '../utils/debug-parser' import { buildDebugVariableTreeMap, buildFbInstanceMap, - buildVariableIndexMap, buildVariableIndexMapV2, debugMapV2ToEntries, } from '../utils/debugger-session' @@ -84,31 +84,21 @@ export function useDebugSession(): UseDebugSessionReturn { const instances = project.data.configurations.resource.instances - // Try the v2 (debug-map.json) path first; fall back to v1 (debug.c). - const v2 = parseDebugMapV2(debugFileResult.content) - - let indexMap: Map - let warnings: string[] - let entriesForTree: ReturnType - - if (v2) { - const v2Result = buildVariableIndexMapV2(project.data.pous, instances, v2) - indexMap = v2Result.indexMap - warnings = v2Result.warnings - entriesForTree = debugMapV2ToEntries(v2) - logActions.addLog({ - id: crypto.randomUUID(), - level: 'info', - message: `Debug map v2: ${v2.leaves.length} leaves across ${v2.arrays.length} arrays.`, - }) - } else { - const parsed = parseDebugFile(debugFileResult.content) - const v1Result = buildVariableIndexMap(project.data.pous, instances, parsed) - indexMap = v1Result.indexMap - warnings = v1Result.warnings - entriesForTree = parsed.variables + const debugMap = parseDebugMapV2(debugFileResult.content) + if (!debugMap) { + const error = 'Invalid debug-map.json (expected version 2)' + logActions.addLog({ id: crypto.randomUUID(), level: 'error', message: error }) + return { success: false, error } } + const { indexMap, warnings } = buildVariableIndexMapV2(project.data.pous, instances, debugMap) + const entriesForTree = debugMapV2ToEntries(debugMap) + logActions.addLog({ + id: crypto.randomUUID(), + level: 'info', + message: `Debug map: ${debugMap.leaves.length} leaves across ${debugMap.arrays.length} arrays.`, + }) + for (const w of warnings) { logActions.addLog({ id: crypto.randomUUID(), level: 'warning', message: w }) } diff --git a/src/frontend/utils/__tests__/debug-parser.test.ts b/src/frontend/utils/__tests__/debug-parser.test.ts deleted file mode 100644 index bbd550642..000000000 --- a/src/frontend/utils/__tests__/debug-parser.test.ts +++ /dev/null @@ -1,94 +0,0 @@ -import { parseDebugFile, parseDebugVariables } from '../debug-parser' - -describe('parseDebugVariables', () => { - it('parses a standard debug_vars array with multiple entries', () => { - const content = ` -debug_vars[] = { - {&(RES0__INSTANCE0.MOTOR_SPEED), INT_ENUM}, - {&(RES0__INSTANCE0.SENSOR_ON), BOOL_ENUM}, - {&(CONFIG0__GLOBAL_FLAG), DINT_ENUM} -}; -` - const result = parseDebugVariables(content) - expect(result).toEqual([ - { name: 'RES0__INSTANCE0.MOTOR_SPEED', type: 'INT_ENUM', index: 0 }, - { name: 'RES0__INSTANCE0.SENSOR_ON', type: 'BOOL_ENUM', index: 1 }, - { name: 'CONFIG0__GLOBAL_FLAG', type: 'DINT_ENUM', index: 2 }, - ]) - }) - - it('returns empty array when debug_vars array is not found', () => { - const content = 'int main() { return 0; }' - const result = parseDebugVariables(content) - expect(result).toEqual([]) - }) - - it('handles entries with extra whitespace', () => { - const content = ` -debug_vars[] = { - { &( VAR1 ) , REAL_ENUM } -}; -` - const result = parseDebugVariables(content) - expect(result).toEqual([{ name: 'VAR1', type: 'REAL_ENUM', index: 0 }]) - }) - - it('returns empty array for empty debug_vars', () => { - const content = 'debug_vars[] = {};' - const result = parseDebugVariables(content) - expect(result).toEqual([]) - }) - - it('parses single entry', () => { - const content = `debug_vars[] = { - {&(RES0__INSTANCE0.X), BOOL_ENUM} -};` - const result = parseDebugVariables(content) - expect(result).toEqual([{ name: 'RES0__INSTANCE0.X', type: 'BOOL_ENUM', index: 0 }]) - }) -}) - -describe('parseDebugFile', () => { - it('returns variables and totalCount from VAR_COUNT define', () => { - const content = ` -#define VAR_COUNT 5 -debug_vars[] = { - {&(RES0__INSTANCE0.A), INT_ENUM}, - {&(RES0__INSTANCE0.B), BOOL_ENUM} -}; -` - const result = parseDebugFile(content) - expect(result.variables).toHaveLength(2) - expect(result.totalCount).toBe(5) - }) - - it('falls back to variables.length when VAR_COUNT is not defined', () => { - const content = ` -debug_vars[] = { - {&(RES0__INSTANCE0.A), INT_ENUM}, - {&(RES0__INSTANCE0.B), BOOL_ENUM}, - {&(RES0__INSTANCE0.C), REAL_ENUM} -}; -` - const result = parseDebugFile(content) - expect(result.variables).toHaveLength(3) - expect(result.totalCount).toBe(3) - }) - - it('returns zero variables and zero totalCount for empty content', () => { - const result = parseDebugFile('') - expect(result.variables).toEqual([]) - expect(result.totalCount).toBe(0) - }) - - it('parses VAR_COUNT as integer from string', () => { - const content = ` -#define VAR_COUNT 42 -debug_vars[] = { - {&(X), INT_ENUM} -}; -` - const result = parseDebugFile(content) - expect(result.totalCount).toBe(42) - }) -}) diff --git a/src/frontend/utils/__tests__/debug-variable-finder.test.ts b/src/frontend/utils/__tests__/debug-variable-finder.test.ts index 6eddb00c9..852b296b7 100644 --- a/src/frontend/utils/__tests__/debug-variable-finder.test.ts +++ b/src/frontend/utils/__tests__/debug-variable-finder.test.ts @@ -13,7 +13,6 @@ import { findVariableIndexWithFallback, getFieldIndexFromMapWithFallback, getIndexFromMapWithFallback, - parseDebugVariables, type PLCInstanceMapping, } from '../debug-variable-finder' @@ -306,10 +305,3 @@ describe('appendToDebugPath', () => { }) }) -describe('parseDebugVariables (re-exported)', () => { - it('is re-exported from debug-variable-finder and works', () => { - const content = `debug_vars[] = { {&(VAR), INT_ENUM} };` - const result = parseDebugVariables(content) - expect(result).toEqual([{ name: 'VAR', type: 'INT_ENUM', index: 0 }]) - }) -}) diff --git a/src/frontend/utils/__tests__/debugger-session.test.ts b/src/frontend/utils/__tests__/debugger-session.test.ts index 68878df34..30ba83b15 100644 --- a/src/frontend/utils/__tests__/debugger-session.test.ts +++ b/src/frontend/utils/__tests__/debugger-session.test.ts @@ -1,9 +1,10 @@ import type { PLCDataType, PLCInstance, PLCPou, PLCVariable } from '../../../middleware/shared/ports/types' -import type { DebugVariableEntry, ParsedDebugData } from '../debug-parser' +import type { DebugMapV2, DebugVariableEntry } from '../debug-parser' +import { packDebugAddr } from '../debug-parser' import { buildDebugVariableTreeMap, buildFbInstanceMap, - buildVariableIndexMap, + buildVariableIndexMapV2, logCompilerEvent, } from '../debugger-session' @@ -141,34 +142,42 @@ describe('logCompilerEvent', () => { }) // --------------------------------------------------------------------------- -// buildVariableIndexMap +// buildVariableIndexMapV2 // --------------------------------------------------------------------------- -describe('buildVariableIndexMap', () => { +function makeMapV2(leaves: Array<{ path: string; type: string; size: number }>): DebugMapV2 { + return { + version: 2, + md5: 'deadbeef', + typeTags: { BOOL: 0, INT: 3, REAL: 9, LREAL: 10, DINT: 5 }, + arrays: [{ index: 0, count: leaves.length }], + leaves: leaves.map((l, i) => ({ arrayIdx: 0, elemIdx: i, ...l })), + } +} + +function addr(arrayIdx: number, elemIdx: number): number { + return packDebugAddr({ arrayIdx, elemIdx }) +} + +describe('buildVariableIndexMapV2', () => { it('builds index map for simple base-type variables', () => { const pou = makePou('Main', 'program', [makeBaseVariable('SPEED', 'INT'), makeBaseVariable('TEMP', 'REAL')]) const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { - variables: [ - makeDebugVar('RES0__INSTANCE0.SPEED', 'INT_ENUM', 0), - makeDebugVar('RES0__INSTANCE0.TEMP', 'REAL_ENUM', 1), - ], - totalCount: 2, - } + const map = makeMapV2([ + { path: 'INSTANCE0.SPEED', type: 'INT', size: 2 }, + { path: 'INSTANCE0.TEMP', type: 'REAL', size: 4 }, + ]) - const { indexMap, warnings } = buildVariableIndexMap([pou], instances, parsed) + const { indexMap, warnings } = buildVariableIndexMapV2([pou], instances, map) - expect(indexMap.get('Main:SPEED')).toBe(0) - expect(indexMap.get('Main:TEMP')).toBe(1) + expect(indexMap.get('Main:SPEED')).toBe(addr(0, 0)) + expect(indexMap.get('Main:TEMP')).toBe(addr(0, 1)) expect(warnings).toHaveLength(0) }) it('warns when no instance is found for a program POU', () => { const pou = makePou('Orphan', 'program', [makeBaseVariable('X', 'INT')]) - const instances: PLCInstance[] = [] - const parsed: ParsedDebugData = { variables: [], totalCount: 0 } - - const { warnings } = buildVariableIndexMap([pou], instances, parsed) + const { warnings } = buildVariableIndexMapV2([pou], [], makeMapV2([])) expect(warnings).toHaveLength(1) expect(warnings[0]).toContain('Orphan') @@ -176,239 +185,74 @@ describe('buildVariableIndexMap', () => { it('skips non-program POUs', () => { const fb = makePou('MyFB', 'function-block', [makeBaseVariable('Q', 'BOOL')]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { variables: [], totalCount: 0 } - - const { indexMap } = buildVariableIndexMap([fb], instances, parsed) + const { indexMap } = buildVariableIndexMapV2([fb], [makeInstance('INSTANCE0', 'Main')], makeMapV2([])) expect(indexMap.size).toBe(0) }) - it('handles external base-type variables using global path', () => { - const pou = makePou('Main', 'program', [makeBaseVariable('GFLAG', 'BOOL', 'external')]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { - variables: [makeDebugVar('CONFIG0__GFLAG', 'BOOL_ENUM', 5)], - totalCount: 1, - } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - - expect(indexMap.get('Main:GFLAG')).toBe(5) - }) - - it('handles array variables with proper element indexing', () => { + it('handles array variables with IEC-indexed element paths', () => { const pou = makePou('Main', 'program', [makeArrayVariable('ARR', 'INT', '0..2')]) const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { - variables: [ - makeDebugVar('RES0__INSTANCE0.ARR.value.table[0]', 'INT_ENUM', 10), - makeDebugVar('RES0__INSTANCE0.ARR.value.table[1]', 'INT_ENUM', 11), - makeDebugVar('RES0__INSTANCE0.ARR.value.table[2]', 'INT_ENUM', 12), - ], - totalCount: 3, - } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - - expect(indexMap.get('Main:ARR[0]')).toBe(10) - expect(indexMap.get('Main:ARR[1]')).toBe(11) - expect(indexMap.get('Main:ARR[2]')).toBe(12) - }) - - it('handles external array variables using global path', () => { - const pou = makePou('Main', 'program', [makeArrayVariable('GARR', 'INT', '1..2', 'external')]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { - variables: [ - makeDebugVar('CONFIG0__GARR.value.table[0]', 'INT_ENUM', 20), - makeDebugVar('CONFIG0__GARR.value.table[1]', 'INT_ENUM', 21), - ], - totalCount: 2, - } + const map = makeMapV2([ + { path: 'INSTANCE0.ARR[0]', type: 'INT', size: 2 }, + { path: 'INSTANCE0.ARR[1]', type: 'INT', size: 2 }, + { path: 'INSTANCE0.ARR[2]', type: 'INT', size: 2 }, + ]) - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) + const { indexMap } = buildVariableIndexMapV2([pou], instances, map) - expect(indexMap.get('Main:GARR[1]')).toBe(20) - expect(indexMap.get('Main:GARR[2]')).toBe(21) + expect(indexMap.get('Main:ARR[0]')).toBe(addr(0, 0)) + expect(indexMap.get('Main:ARR[1]')).toBe(addr(0, 1)) + expect(indexMap.get('Main:ARR[2]')).toBe(addr(0, 2)) }) it('handles arrays with negative start index', () => { const pou = makePou('Main', 'program', [makeArrayVariable('NEG', 'BOOL', '-1..1')]) const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { - variables: [ - makeDebugVar('RES0__INSTANCE0.NEG.value.table[0]', 'BOOL_ENUM', 30), - makeDebugVar('RES0__INSTANCE0.NEG.value.table[1]', 'BOOL_ENUM', 31), - makeDebugVar('RES0__INSTANCE0.NEG.value.table[2]', 'BOOL_ENUM', 32), - ], - totalCount: 3, - } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - - expect(indexMap.get('Main:NEG[-1]')).toBe(30) - expect(indexMap.get('Main:NEG[0]')).toBe(31) - expect(indexMap.get('Main:NEG[1]')).toBe(32) - }) - - it('skips array elements with null index', () => { - const pou = makePou('Main', 'program', [makeArrayVariable('ARR', 'INT', '0..0')]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { variables: [], totalCount: 0 } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - - expect(indexMap.has('Main:ARR[0]')).toBe(false) - }) - - it('skips non-array variables with null index', () => { - const pou = makePou('Main', 'program', [makeBaseVariable('MISSING', 'INT')]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { variables: [], totalCount: 0 } + const map = makeMapV2([ + { path: 'INSTANCE0.NEG[-1]', type: 'BOOL', size: 1 }, + { path: 'INSTANCE0.NEG[0]', type: 'BOOL', size: 1 }, + { path: 'INSTANCE0.NEG[1]', type: 'BOOL', size: 1 }, + ]) - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) + const { indexMap } = buildVariableIndexMapV2([pou], instances, map) - expect(indexMap.has('Main:MISSING')).toBe(false) + expect(indexMap.get('Main:NEG[-1]')).toBe(addr(0, 0)) + expect(indexMap.get('Main:NEG[0]')).toBe(addr(0, 1)) + expect(indexMap.get('Main:NEG[1]')).toBe(addr(0, 2)) }) - it('appends unmatched parsed variables as fallback entries', () => { + it('falls back to raw debug path for unmatched leaves (nested fields)', () => { const pou = makePou('Main', 'program', []) const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { - variables: [makeDebugVar('SOME__UNKNOWN.VAR', 'INT_ENUM', 99)], - totalCount: 1, - } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - - expect(indexMap.get('SOME__UNKNOWN.VAR')).toBe(99) - }) - - it('does not overwrite existing entries with fallback entries', () => { - const pou = makePou('Main', 'program', [makeBaseVariable('X', 'INT')]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const debugVar = makeDebugVar('RES0__INSTANCE0.X', 'INT_ENUM', 0) - const parsed: ParsedDebugData = { - variables: [debugVar], - totalCount: 1, - } + const map = makeMapV2([{ path: 'INSTANCE0.FB.FIELD', type: 'INT', size: 2 }]) - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) + const { indexMap } = buildVariableIndexMapV2([pou], instances, map) - // 'Main:X' was set to 0 first; 'RES0__INSTANCE0.X' is a fallback key - expect(indexMap.get('Main:X')).toBe(0) + expect(indexMap.get('INSTANCE0.FB.FIELD')).toBe(addr(0, 0)) }) - it('skips fallback entry when the debug variable name already exists in the map', () => { - // Scenario: composite key matches the debug variable name exactly. - // We name the pou's variable so that the composite key equals the debug var's name. + it('does not lose entries across multiple arrays', () => { const pou = makePou('Main', 'program', [makeBaseVariable('X', 'INT')]) const instances = [makeInstance('INSTANCE0', 'Main')] - // The first debug var sets composite key 'Main:X' -> 0 - // The second debug var has name 'Main:X' which already exists -> should be skipped - const parsed: ParsedDebugData = { - variables: [makeDebugVar('RES0__INSTANCE0.X', 'INT_ENUM', 0), makeDebugVar('Main:X', 'INT_ENUM', 99)], - totalCount: 2, - } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - - // 'Main:X' was set to 0 by the composite key, so the fallback with value 99 is skipped - expect(indexMap.get('Main:X')).toBe(0) - }) - - it('handles POUs with no interface', () => { - const pou: PLCPou = { - name: 'Empty', - pouType: 'program', - body: { language: 'st', value: '' }, - } - const instances = [makeInstance('INSTANCE0', 'Empty')] - const parsed: ParsedDebugData = { variables: [], totalCount: 0 } - - const { indexMap, warnings } = buildVariableIndexMap([pou], instances, parsed) - expect(indexMap.size).toBe(0) - expect(warnings).toHaveLength(0) - }) - - it('skips array variables with invalid dimension format', () => { - const pou = makePou('Main', 'program', [ - { - name: 'BAD', - class: 'local', - type: { - definition: 'array', - value: 'ARRAY', - data: { - baseType: { definition: 'base-type', value: 'INT' }, - dimensions: [{ dimension: 'bad' }], - }, - }, - location: '', - documentation: '', - }, - ]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { variables: [], totalCount: 0 } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - expect(indexMap.has('Main:BAD[0]')).toBe(false) - }) - - it('skips array variables with no dimensions', () => { - const pou = makePou('Main', 'program', [ - { - name: 'EMPTY_ARR', - class: 'local', - type: { - definition: 'array', - value: 'ARRAY', - data: { - baseType: { definition: 'base-type', value: 'INT' }, - dimensions: [], - }, - }, - location: '', - documentation: '', - }, - ]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const parsed: ParsedDebugData = { variables: [], totalCount: 0 } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - expect(indexMap.size).toBe(0) - }) - - it('handles external array elements that are not found (null match)', () => { - const pou = makePou('Main', 'program', [makeArrayVariable('EXT_ARR', 'INT', '0..1', 'external')]) - const instances = [makeInstance('INSTANCE0', 'Main')] - // Only provide index for element [0], not [1] - const parsed: ParsedDebugData = { - variables: [makeDebugVar('CONFIG0__EXT_ARR.value.table[0]', 'INT_ENUM', 50)], - totalCount: 1, - } - - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) - expect(indexMap.get('Main:EXT_ARR[0]')).toBe(50) - expect(indexMap.has('Main:EXT_ARR[1]')).toBe(false) - }) - - it('does not duplicate fallback entries that already exist', () => { - const pou = makePou('Main', 'program', [makeBaseVariable('X', 'INT')]) - const instances = [makeInstance('INSTANCE0', 'Main')] - const debugVar = makeDebugVar('RES0__INSTANCE0.X', 'INT_ENUM', 0) - const parsed: ParsedDebugData = { - variables: [debugVar], - totalCount: 1, + const map: DebugMapV2 = { + version: 2, + md5: 'deadbeef', + typeTags: { INT: 3 }, + arrays: [ + { index: 0, count: 1 }, + { index: 1, count: 1 }, + ], + leaves: [ + { arrayIdx: 0, elemIdx: 0, path: 'INSTANCE0.X', type: 'INT', size: 2 }, + { arrayIdx: 1, elemIdx: 0, path: 'INSTANCE0.OTHER', type: 'INT', size: 2 }, + ], } - const { indexMap } = buildVariableIndexMap([pou], instances, parsed) + const { indexMap } = buildVariableIndexMapV2([pou], instances, map) - // Main:X was set first (value 0). The debugVar name 'RES0__INSTANCE0.X' should also be in the map - // as a fallback since it won't match 'Main:X' - expect(indexMap.get('Main:X')).toBe(0) - expect(indexMap.get('RES0__INSTANCE0.X')).toBe(0) + expect(indexMap.get('Main:X')).toBe(addr(0, 0)) + expect(indexMap.get('INSTANCE0.OTHER')).toBe(addr(1, 0)) }) }) diff --git a/src/frontend/utils/debug-parser.ts b/src/frontend/utils/debug-parser.ts index 15a387d58..a1d415ba5 100644 --- a/src/frontend/utils/debug-parser.ts +++ b/src/frontend/utils/debug-parser.ts @@ -1,78 +1,13 @@ /** - * Canonical debug.c parser - shared between debugger and OPC-UA. + * Debug map parser — Phase 4 (STruC++) debug-map.json. * - * This module provides the single source of truth for parsing debug.c files - * generated by the IEC 61131-3 compiler. + * STruC++ writes a debug-map.json alongside generated_debug.cpp at compile + * time. This module parses it and exposes helpers to pack/unpack the + * (arrayIdx, elemIdx) leaf addresses into the single-number representation + * the editor's store, polling loop, and Modbus clients already consume. */ -export interface DebugVariableEntry { - /** Full path in debug.c (e.g., "RES0__INSTANCE0.MOTOR_SPEED") */ - name: string - /** IEC type enum (e.g., "INT_ENUM", "BOOL_ENUM") */ - type: string - /** Index in the debug_vars array */ - index: number -} - -export interface ParsedDebugData { - variables: DebugVariableEntry[] - totalCount: number -} - -/** - * Parse the debug.c file content to extract debug variables. - * - * @param content - The raw content of debug.c file - * @returns Array of parsed debug variable entries - */ -export function parseDebugVariables(content: string): DebugVariableEntry[] { - const variables: DebugVariableEntry[] = [] - - const debugVarsMatch = content.match(/debug_vars\[\]\s*=\s*\{([\s\S]*?)\};/) - - if (!debugVarsMatch) { - console.warn('Could not find debug_vars[] array in debug.c') - return [] - } - - const arrayContent = debugVarsMatch[1] - const entryRegex = /\{\s*&\(([^)]+)\)\s*,\s*(\w+)\s*\}/g - - let match - let index = 0 - - while ((match = entryRegex.exec(arrayContent)) !== null) { - variables.push({ - name: match[1].trim(), - type: match[2].trim(), - index, - }) - index++ - } - - return variables -} - -/** - * Parse the debug.c file and return both variables and total count. - * - * @param content - The raw content of debug.c file - * @returns Parsed debug data with variables and total count - */ -export function parseDebugFile(content: string): ParsedDebugData { - const variables = parseDebugVariables(content) - - const varCountMatch = content.match(/#define\s+VAR_COUNT\s+(\d+)/) - const totalCount = varCountMatch ? parseInt(varCountMatch[1], 10) : variables.length - - return { variables, totalCount } -} - -// --------------------------------------------------------------------------- -// Phase 4 debug-map.json parser (produced by STruC++ compile() -> debugMap). -// --------------------------------------------------------------------------- - -/** Address of a single leaf in the Phase 4 per-project debug table. */ +/** One leaf variable in the runtime's Phase 4 debug address space. */ export interface DebugAddr { arrayIdx: number elemIdx: number @@ -95,18 +30,29 @@ export interface DebugMapV2 { } /** - * Pack a DebugAddr into a single number for compatibility with APIs that - * expect a flat u32-ish index (e.g. getVariablesList). arr goes in the high - * byte, elem in the low 16 bits: `(arr << 16) | elem`. - * - * This keeps the existing editor's store types (`Map`) - * unchanged while speaking the new (arr, elem) wire protocol downstream. + * One DebugVariableEntry per leaf — the shape the tree builder consumes. + * `index` carries the packed (arr<<16|elem) DebugAddr so downstream code + * (polling loop, modbus clients) keeps a plain `number` indirection. + */ +export interface DebugVariableEntry { + /** Full path from the instance root (e.g. "INSTANCE0.SPEEDS[5]"). */ + name: string + /** IEC type tag string with `_ENUM` suffix for compatibility with the + * tree-builder's type-name unwrapping (e.g. "INT_ENUM", "BOOL_ENUM"). */ + type: string + /** Packed DebugAddr (arrayIdx << 16 | elemIdx). */ + index: number +} + +/** + * Pack a DebugAddr into a single number for APIs that carry a flat index. + * arr goes in the high byte, elem in the low 16 bits: `(arr << 16) | elem`. */ export function packDebugAddr(addr: DebugAddr): number { return ((addr.arrayIdx & 0xff) << 16) | (addr.elemIdx & 0xffff) } -/** Inverse of packDebugAddr — useful in tests / debugger UI tooltips. */ +/** Inverse of packDebugAddr — handy in tooltips and tests. */ export function unpackDebugAddr(packed: number): DebugAddr { return { arrayIdx: (packed >>> 16) & 0xff, @@ -115,10 +61,8 @@ export function unpackDebugAddr(packed: number): DebugAddr { } /** - * Parse the debug-map.json written alongside generated_debug.cpp by the - * editor's compile step. Returns undefined when the content isn't a v2 - * manifest (lets callers transparently fall back to the legacy debug.c - * path while both coexist). + * Parse debug-map.json. Returns undefined if the content is missing or + * malformed so callers can surface a clean error. */ export function parseDebugMapV2(content: string): DebugMapV2 | undefined { try { diff --git a/src/frontend/utils/debug-variable-finder.ts b/src/frontend/utils/debug-variable-finder.ts index 755a0468b..3dae5b242 100644 --- a/src/frontend/utils/debug-variable-finder.ts +++ b/src/frontend/utils/debug-variable-finder.ts @@ -1,10 +1,9 @@ /** - * Shared utilities for finding debug variable indices from debug.c - * Used by both the debugger (renderer) and OPC-UA config generator (main). + * Shared utilities for finding variables in a DebugVariableEntry[] list + * (produced by debugMapV2ToEntries from a debug-map.json). */ -// Re-export types and parser from canonical debug-parser module -export { type DebugVariableEntry, parseDebugVariables } from './debug-parser' +export { type DebugVariableEntry } from './debug-parser' import type { DebugVariableEntry } from './debug-parser' diff --git a/src/frontend/utils/debugger-session.ts b/src/frontend/utils/debugger-session.ts index d4f240c30..619163f22 100644 --- a/src/frontend/utils/debugger-session.ts +++ b/src/frontend/utils/debugger-session.ts @@ -2,11 +2,8 @@ * Shared debugger session helpers. * * Builds the debug variable index map, debug tree, and FB instance map - * from parsed debug.c data and project structure. These artifacts are - * stored in the workspace Zustand store for the debugger UI. - * - * Works with the port-format types (PLCPou flat format) used by both - * the editor and web platforms. + * from STruC++'s debug-map.json and the project structure. The artifacts + * are stored in the workspace Zustand store for the debugger UI. */ import type { @@ -17,19 +14,10 @@ import type { PLCPou, PLCVariable, } from '../../middleware/shared/ports/types' -import type { DebugMapV2, DebugVariableEntry, ParsedDebugData } from './debug-parser' +import type { DebugMapV2, DebugVariableEntry } from './debug-parser' import { packDebugAddr } from './debug-parser' import { buildDebugTree } from './debug-tree-builder' -import { - buildDebugPathPrefix, - buildGlobalDebugPath, - findDebugVariable, - findGlobalVariableIndex, - findInstanceName, - findVariableIndex, - findVariableIndexWithFallback, - type PLCInstanceMapping, -} from './debug-variable-finder' +import { buildDebugPathPrefix, findInstanceName, type PLCInstanceMapping } from './debug-variable-finder' // --------------------------------------------------------------------------- // 0. logCompilerEvent — shared log helper for compile/debug progress @@ -56,7 +44,7 @@ export function logCompilerEvent( } // --------------------------------------------------------------------------- -// 1. buildVariableIndexMap +// 1. buildVariableIndexMapV2 — composite-key -> packed-DebugAddr // --------------------------------------------------------------------------- export interface VariableIndexMapResult { @@ -64,93 +52,12 @@ export interface VariableIndexMapResult { warnings: string[] } -/** - * Build a composite-key -> debug-index map from parsed debug variables. - * Pure function — caller is responsible for logging warnings. - */ -export function buildVariableIndexMap( - pous: PLCPou[], - instances: PLCInstance[], - parsed: ParsedDebugData, -): VariableIndexMapResult { - const indexMap = new Map() - const warnings: string[] = [] - - const instanceMappings: PLCInstanceMapping[] = instances.map((inst) => ({ - name: inst.name, - program: inst.program, - })) - - pous.forEach((pou) => { - if (pou.pouType !== 'program') return - - const instanceName = findInstanceName(pou.name, instanceMappings) - if (!instanceName) { - warnings.push(`No instance found for program '${pou.name}', skipping debug variable parsing.`) - return - } - - const variables = pou.interface?.variables ?? [] - variables.forEach((v: PLCVariable) => { - if (v.type.definition === 'array' && v.type.data) { - const dimensions = v.type.data.dimensions - if (dimensions.length > 0) { - const dimMatch = dimensions[0].dimension.match(/^(-?\d+)\.\.(-?\d+)$/) - if (dimMatch) { - const startIdx = parseInt(dimMatch[1], 10) - const endIdx = parseInt(dimMatch[2], 10) - for (let i = 0; i <= endIdx - startIdx; i++) { - let elementIndex: number | null - if (v.class === 'external') { - const globalPath = `${buildGlobalDebugPath(v.name)}.value.table[${i}]` - const match = findDebugVariable(parsed.variables, globalPath) - elementIndex = match ? match.index : null - } else { - elementIndex = findVariableIndex(instanceName, v.name, parsed.variables, { - isArrayElement: true, - arrayIndex: i, - }) - } - if (elementIndex !== null) { - const compositeKey = `${pou.name}:${v.name}[${startIdx + i}]` - indexMap.set(compositeKey, elementIndex) - } - } - } - } - } else { - const index = - v.class === 'external' - ? findGlobalVariableIndex(v.name, parsed.variables) - : findVariableIndexWithFallback(instanceName, v.name, parsed.variables) - if (index !== null) { - const compositeKey = `${pou.name}:${v.name}` - indexMap.set(compositeKey, index) - } - } - }) - }) - - // Append any unmatched parsed variables as fallback entries - parsed.variables.forEach((debugVar) => { - if (!indexMap.has(debugVar.name)) { - indexMap.set(debugVar.name, debugVar.index) - } - }) - - return { indexMap, warnings } -} - -// --------------------------------------------------------------------------- -// 1b. buildVariableIndexMapV2 — Phase 4 debug-map.json path -// --------------------------------------------------------------------------- - /** * Build a composite-key -> packed-DebugAddr map from a v2 DebugMap. * * The v2 map addresses variables as (arrayIdx, elemIdx) pairs; we pack those * into a single number `(arr << 16) | elem` so downstream store types and - * the polling loop continue to see a plain `number` key, same as v1. + * the polling loop see a plain `number` key. * * Path convention emitted by STruC++: * INSTANCE_NAME.VAR_NAME (scalar) diff --git a/src/main/modules/ipc/main.ts b/src/main/modules/ipc/main.ts index fae1ebe61..c1e031293 100644 --- a/src/main/modules/ipc/main.ts +++ b/src/main/modules/ipc/main.ts @@ -827,29 +827,19 @@ class MainProcessBridge implements MainIpcModule { const fs = await import('fs/promises') const path = await import('path') - // projectPath is already the project directory, not a file path - // Guard against traversal/absolute input in boardTarget if (path.isAbsolute(boardTarget) || boardTarget.includes('..') || boardTarget.includes(path.sep)) { return { success: false, error: 'Invalid board target' } } - // Phase 4 (STruC++) projects ship debug-map.json; legacy MatIEC - // projects ship debug.c. Prefer v2 when present so the renderer's - // parseDebugMapV2 picks it up. - const v2Path = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug-map.json') - try { - const v2Content = await fs.readFile(v2Path, 'utf-8') - return { success: true, content: v2Content } - } catch { - // Fall through to legacy debug.c - } - const debugFilePath = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug.c') - const content = await fs.readFile(debugFilePath, 'utf-8') + // STruC++ writes debug-map.json alongside generated_debug.cpp. + // Consumed by the renderer via parseDebugMapV2. + const debugMapPath = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug-map.json') + const content = await fs.readFile(debugMapPath, 'utf-8') return { success: true, content } } catch (error) { return { success: false, - error: error instanceof Error ? error.message : 'Failed to read debug file', + error: error instanceof Error ? error.message : 'Failed to read debug-map.json', } } } @@ -983,44 +973,25 @@ class MainProcessBridge implements MainIpcModule { const fs = await import('fs/promises') const path = await import('path') - // Guard against traversal/absolute input in boardTarget if (path.isAbsolute(boardTarget) || boardTarget.includes('..') || boardTarget.includes(path.sep)) { return { success: false, error: 'Invalid board target' } } - // Phase 4 (STruC++) projects store the MD5 in debug-map.json. Prefer - // that — compiler-module.ts computes md5 from the ST source and the - // debug-table-gen embeds it into the manifest so the editor sees the - // same value the target sees via FC 0x45. + // STruC++ writes the MD5 into debug-map.json alongside the pointer + // tables. It's the single source of truth the editor and the target + // agree on (target exposes the same value via FC 0x45). const debugMapPath = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug-map.json') - try { - const raw = await fs.readFile(debugMapPath, 'utf-8') - const parsed = JSON.parse(raw) as { md5?: unknown } - if (typeof parsed.md5 === 'string' && /^[a-fA-F0-9]{32}$/.test(parsed.md5)) { - return { success: true, md5: parsed.md5 } - } - } catch { - // Fall through to legacy program.st comment - } - - // Legacy (MatIEC) projects carry the MD5 as a DBG comment in program.st. - const programStPath = path.resolve(projectPath, 'build', boardTarget, 'src', 'program.st') - const content = await fs.readFile(programStPath, 'utf-8') - const md5Pattern = /\(\*DBG:char md5\[\] = "([a-fA-F0-9]{32})";?\*\)/ - const match = content.match(md5Pattern) + const raw = await fs.readFile(debugMapPath, 'utf-8') + const parsed = JSON.parse(raw) as { md5?: unknown } - if (!match || !match[1]) { - return { - success: false, - error: 'Could not find MD5 hash in debug-map.json or program.st', - } + if (typeof parsed.md5 !== 'string' || !/^[a-fA-F0-9]{32}$/.test(parsed.md5)) { + return { success: false, error: 'debug-map.json is missing a valid md5 field' } } - - return { success: true, md5: match[1] } + return { success: true, md5: parsed.md5 } } catch (error) { return { success: false, - error: error instanceof Error ? error.message : 'Failed to read MD5', + error: error instanceof Error ? error.message : 'Failed to read debug-map.json', } } } From 744ccd036f10f5926591b5a3f298877256a18b8b Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 07:37:18 -0400 Subject: [PATCH 043/296] refactor(debug): drop V2 suffix from debug-path symbols MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With the MatIEC fallback gone there's no V1 to distinguish against — the V2 suffix just clutters the names. Renames across the debug path: parseDebugMapV2 -> parseDebugMap buildVariableIndexMapV2 -> buildVariableIndexMap debugMapV2ToEntries -> debugMapToEntries DebugMapV2 -> DebugMap DebugMapLeafV2 -> DebugMapLeaf makeMapV2 (test) -> makeMap The `version: 2` field in debug-map.json stays (it's the wire-schema contract; `1` was never used but bumping the number later is the right escape hatch for format changes). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/frontend/hooks/useDebugSession.ts | 19 +++++------ .../utils/__tests__/debugger-session.test.ts | 34 +++++++++---------- src/frontend/utils/debug-parser.ts | 14 ++++---- src/frontend/utils/debug-variable-finder.ts | 2 +- src/frontend/utils/debugger-session.ts | 19 +++++------ src/main/modules/ipc/main.ts | 2 +- 6 files changed, 44 insertions(+), 46 deletions(-) diff --git a/src/frontend/hooks/useDebugSession.ts b/src/frontend/hooks/useDebugSession.ts index a1727d4a6..d9c1b9890 100644 --- a/src/frontend/hooks/useDebugSession.ts +++ b/src/frontend/hooks/useDebugSession.ts @@ -15,12 +15,12 @@ import { useCallback, useRef } from 'react' import type { DebugConnectionConfig, DebugTreeNode, FbInstanceInfo } from '../../middleware/shared/ports/types' import { useDebugger, useSimulator } from '../../middleware/shared/providers' import { useOpenPLCStore } from '../store' -import { parseDebugMapV2 } from '../utils/debug-parser' +import { parseDebugMap } from '../utils/debug-parser' import { buildDebugVariableTreeMap, buildFbInstanceMap, - buildVariableIndexMapV2, - debugMapV2ToEntries, + buildVariableIndexMap, + debugMapToEntries, } from '../utils/debugger-session' import { hexToBytes } from '../utils/hex' @@ -70,12 +70,9 @@ export function useDebugSession(): UseDebugSessionReturn { logActions.addLog({ id: crypto.randomUUID(), level: 'info', message: 'Connecting debugger...' }) try { - // Read debug artifacts. Phase 4 (STruC++) projects ship - // debug-map.json; legacy MatIEC projects ship debug.c. The port's - // readDebugFile returns whichever exists — v2 JSON takes priority. const debugFileResult = await debuggerPort.readDebugFile(projectPath, boardTarget) if (!debugFileResult.success || !debugFileResult.content) { - const error = `Failed to read debug file: ${debugFileResult.error ?? 'No content'}` + const error = `Failed to read debug-map.json: ${debugFileResult.error ?? 'No content'}` logActions.addLog({ id: crypto.randomUUID(), level: 'error', message: error }) return { success: false, error } } @@ -84,15 +81,15 @@ export function useDebugSession(): UseDebugSessionReturn { const instances = project.data.configurations.resource.instances - const debugMap = parseDebugMapV2(debugFileResult.content) + const debugMap = parseDebugMap(debugFileResult.content) if (!debugMap) { - const error = 'Invalid debug-map.json (expected version 2)' + const error = 'Invalid debug-map.json (expected schema version 2)' logActions.addLog({ id: crypto.randomUUID(), level: 'error', message: error }) return { success: false, error } } - const { indexMap, warnings } = buildVariableIndexMapV2(project.data.pous, instances, debugMap) - const entriesForTree = debugMapV2ToEntries(debugMap) + const { indexMap, warnings } = buildVariableIndexMap(project.data.pous, instances, debugMap) + const entriesForTree = debugMapToEntries(debugMap) logActions.addLog({ id: crypto.randomUUID(), level: 'info', diff --git a/src/frontend/utils/__tests__/debugger-session.test.ts b/src/frontend/utils/__tests__/debugger-session.test.ts index 30ba83b15..f9fb9d6ad 100644 --- a/src/frontend/utils/__tests__/debugger-session.test.ts +++ b/src/frontend/utils/__tests__/debugger-session.test.ts @@ -1,10 +1,10 @@ import type { PLCDataType, PLCInstance, PLCPou, PLCVariable } from '../../../middleware/shared/ports/types' -import type { DebugMapV2, DebugVariableEntry } from '../debug-parser' +import type { DebugMap, DebugVariableEntry } from '../debug-parser' import { packDebugAddr } from '../debug-parser' import { buildDebugVariableTreeMap, buildFbInstanceMap, - buildVariableIndexMapV2, + buildVariableIndexMap, logCompilerEvent, } from '../debugger-session' @@ -142,10 +142,10 @@ describe('logCompilerEvent', () => { }) // --------------------------------------------------------------------------- -// buildVariableIndexMapV2 +// buildVariableIndexMap // --------------------------------------------------------------------------- -function makeMapV2(leaves: Array<{ path: string; type: string; size: number }>): DebugMapV2 { +function makeMap(leaves: Array<{ path: string; type: string; size: number }>): DebugMap { return { version: 2, md5: 'deadbeef', @@ -159,16 +159,16 @@ function addr(arrayIdx: number, elemIdx: number): number { return packDebugAddr({ arrayIdx, elemIdx }) } -describe('buildVariableIndexMapV2', () => { +describe('buildVariableIndexMap', () => { it('builds index map for simple base-type variables', () => { const pou = makePou('Main', 'program', [makeBaseVariable('SPEED', 'INT'), makeBaseVariable('TEMP', 'REAL')]) const instances = [makeInstance('INSTANCE0', 'Main')] - const map = makeMapV2([ + const map = makeMap([ { path: 'INSTANCE0.SPEED', type: 'INT', size: 2 }, { path: 'INSTANCE0.TEMP', type: 'REAL', size: 4 }, ]) - const { indexMap, warnings } = buildVariableIndexMapV2([pou], instances, map) + const { indexMap, warnings } = buildVariableIndexMap([pou], instances, map) expect(indexMap.get('Main:SPEED')).toBe(addr(0, 0)) expect(indexMap.get('Main:TEMP')).toBe(addr(0, 1)) @@ -177,7 +177,7 @@ describe('buildVariableIndexMapV2', () => { it('warns when no instance is found for a program POU', () => { const pou = makePou('Orphan', 'program', [makeBaseVariable('X', 'INT')]) - const { warnings } = buildVariableIndexMapV2([pou], [], makeMapV2([])) + const { warnings } = buildVariableIndexMap([pou], [], makeMap([])) expect(warnings).toHaveLength(1) expect(warnings[0]).toContain('Orphan') @@ -185,7 +185,7 @@ describe('buildVariableIndexMapV2', () => { it('skips non-program POUs', () => { const fb = makePou('MyFB', 'function-block', [makeBaseVariable('Q', 'BOOL')]) - const { indexMap } = buildVariableIndexMapV2([fb], [makeInstance('INSTANCE0', 'Main')], makeMapV2([])) + const { indexMap } = buildVariableIndexMap([fb], [makeInstance('INSTANCE0', 'Main')], makeMap([])) expect(indexMap.size).toBe(0) }) @@ -193,13 +193,13 @@ describe('buildVariableIndexMapV2', () => { it('handles array variables with IEC-indexed element paths', () => { const pou = makePou('Main', 'program', [makeArrayVariable('ARR', 'INT', '0..2')]) const instances = [makeInstance('INSTANCE0', 'Main')] - const map = makeMapV2([ + const map = makeMap([ { path: 'INSTANCE0.ARR[0]', type: 'INT', size: 2 }, { path: 'INSTANCE0.ARR[1]', type: 'INT', size: 2 }, { path: 'INSTANCE0.ARR[2]', type: 'INT', size: 2 }, ]) - const { indexMap } = buildVariableIndexMapV2([pou], instances, map) + const { indexMap } = buildVariableIndexMap([pou], instances, map) expect(indexMap.get('Main:ARR[0]')).toBe(addr(0, 0)) expect(indexMap.get('Main:ARR[1]')).toBe(addr(0, 1)) @@ -209,13 +209,13 @@ describe('buildVariableIndexMapV2', () => { it('handles arrays with negative start index', () => { const pou = makePou('Main', 'program', [makeArrayVariable('NEG', 'BOOL', '-1..1')]) const instances = [makeInstance('INSTANCE0', 'Main')] - const map = makeMapV2([ + const map = makeMap([ { path: 'INSTANCE0.NEG[-1]', type: 'BOOL', size: 1 }, { path: 'INSTANCE0.NEG[0]', type: 'BOOL', size: 1 }, { path: 'INSTANCE0.NEG[1]', type: 'BOOL', size: 1 }, ]) - const { indexMap } = buildVariableIndexMapV2([pou], instances, map) + const { indexMap } = buildVariableIndexMap([pou], instances, map) expect(indexMap.get('Main:NEG[-1]')).toBe(addr(0, 0)) expect(indexMap.get('Main:NEG[0]')).toBe(addr(0, 1)) @@ -225,9 +225,9 @@ describe('buildVariableIndexMapV2', () => { it('falls back to raw debug path for unmatched leaves (nested fields)', () => { const pou = makePou('Main', 'program', []) const instances = [makeInstance('INSTANCE0', 'Main')] - const map = makeMapV2([{ path: 'INSTANCE0.FB.FIELD', type: 'INT', size: 2 }]) + const map = makeMap([{ path: 'INSTANCE0.FB.FIELD', type: 'INT', size: 2 }]) - const { indexMap } = buildVariableIndexMapV2([pou], instances, map) + const { indexMap } = buildVariableIndexMap([pou], instances, map) expect(indexMap.get('INSTANCE0.FB.FIELD')).toBe(addr(0, 0)) }) @@ -235,7 +235,7 @@ describe('buildVariableIndexMapV2', () => { it('does not lose entries across multiple arrays', () => { const pou = makePou('Main', 'program', [makeBaseVariable('X', 'INT')]) const instances = [makeInstance('INSTANCE0', 'Main')] - const map: DebugMapV2 = { + const map: DebugMap = { version: 2, md5: 'deadbeef', typeTags: { INT: 3 }, @@ -249,7 +249,7 @@ describe('buildVariableIndexMapV2', () => { ], } - const { indexMap } = buildVariableIndexMapV2([pou], instances, map) + const { indexMap } = buildVariableIndexMap([pou], instances, map) expect(indexMap.get('Main:X')).toBe(addr(0, 0)) expect(indexMap.get('INSTANCE0.OTHER')).toBe(addr(1, 0)) diff --git a/src/frontend/utils/debug-parser.ts b/src/frontend/utils/debug-parser.ts index a1d415ba5..de7c0da8f 100644 --- a/src/frontend/utils/debug-parser.ts +++ b/src/frontend/utils/debug-parser.ts @@ -13,7 +13,7 @@ export interface DebugAddr { elemIdx: number } -export interface DebugMapLeafV2 { +export interface DebugMapLeaf { arrayIdx: number elemIdx: number path: string @@ -21,12 +21,14 @@ export interface DebugMapLeafV2 { size: number } -export interface DebugMapV2 { +export interface DebugMap { + /** Wire-schema version. Bumped when the file format changes in a + * non-backward-compatible way. */ version: 2 md5: string typeTags: Record arrays: Array<{ index: number; count: number }> - leaves: DebugMapLeafV2[] + leaves: DebugMapLeaf[] } /** @@ -64,13 +66,13 @@ export function unpackDebugAddr(packed: number): DebugAddr { * Parse debug-map.json. Returns undefined if the content is missing or * malformed so callers can surface a clean error. */ -export function parseDebugMapV2(content: string): DebugMapV2 | undefined { +export function parseDebugMap(content: string): DebugMap | undefined { try { - const raw = JSON.parse(content) as Partial + const raw = JSON.parse(content) as Partial if (raw.version !== 2 || !Array.isArray(raw.leaves) || !Array.isArray(raw.arrays)) { return undefined } - return raw as DebugMapV2 + return raw as DebugMap } catch { return undefined } diff --git a/src/frontend/utils/debug-variable-finder.ts b/src/frontend/utils/debug-variable-finder.ts index 3dae5b242..f5f4d3eca 100644 --- a/src/frontend/utils/debug-variable-finder.ts +++ b/src/frontend/utils/debug-variable-finder.ts @@ -1,6 +1,6 @@ /** * Shared utilities for finding variables in a DebugVariableEntry[] list - * (produced by debugMapV2ToEntries from a debug-map.json). + * (produced by debugMapToEntries from a debug-map.json). */ export { type DebugVariableEntry } from './debug-parser' diff --git a/src/frontend/utils/debugger-session.ts b/src/frontend/utils/debugger-session.ts index 619163f22..43928727b 100644 --- a/src/frontend/utils/debugger-session.ts +++ b/src/frontend/utils/debugger-session.ts @@ -14,7 +14,7 @@ import type { PLCPou, PLCVariable, } from '../../middleware/shared/ports/types' -import type { DebugMapV2, DebugVariableEntry } from './debug-parser' +import type { DebugMap, DebugVariableEntry } from './debug-parser' import { packDebugAddr } from './debug-parser' import { buildDebugTree } from './debug-tree-builder' import { buildDebugPathPrefix, findInstanceName, type PLCInstanceMapping } from './debug-variable-finder' @@ -44,7 +44,7 @@ export function logCompilerEvent( } // --------------------------------------------------------------------------- -// 1. buildVariableIndexMapV2 — composite-key -> packed-DebugAddr +// 1. buildVariableIndexMap — composite-key -> packed-DebugAddr // --------------------------------------------------------------------------- export interface VariableIndexMapResult { @@ -53,9 +53,9 @@ export interface VariableIndexMapResult { } /** - * Build a composite-key -> packed-DebugAddr map from a v2 DebugMap. + * Build a composite-key -> packed-DebugAddr map from a DebugMap. * - * The v2 map addresses variables as (arrayIdx, elemIdx) pairs; we pack those + * The map addresses variables as (arrayIdx, elemIdx) pairs; we pack those * into a single number `(arr << 16) | elem` so downstream store types and * the polling loop see a plain `number` key. * @@ -64,10 +64,10 @@ export interface VariableIndexMapResult { * INSTANCE_NAME.VAR_NAME[5] (array element, IEC-indexed) * INSTANCE_NAME.FB_INST.FIELD (nested struct/FB field) */ -export function buildVariableIndexMapV2( +export function buildVariableIndexMap( pous: PLCPou[], instances: PLCInstance[], - map: DebugMapV2, + map: DebugMap, ): VariableIndexMapResult { const indexMap = new Map() const warnings: string[] = [] @@ -135,11 +135,10 @@ export function buildVariableIndexMapV2( } /** - * Synthesize a DebugVariableEntry[] from a DebugMapV2 so the existing tree - * builder (which consumes v1-shaped data) works unchanged. The `index` - * field carries the packed (arr<<16|elem) address. + * Flatten a DebugMap's leaves into the DebugVariableEntry[] shape the tree + * builder consumes. `index` carries the packed (arr<<16|elem) address. */ -export function debugMapV2ToEntries(map: DebugMapV2): DebugVariableEntry[] { +export function debugMapToEntries(map: DebugMap): DebugVariableEntry[] { return map.leaves.map((leaf) => ({ name: leaf.path, type: `${leaf.type}_ENUM`, diff --git a/src/main/modules/ipc/main.ts b/src/main/modules/ipc/main.ts index c1e031293..741942b94 100644 --- a/src/main/modules/ipc/main.ts +++ b/src/main/modules/ipc/main.ts @@ -832,7 +832,7 @@ class MainProcessBridge implements MainIpcModule { } // STruC++ writes debug-map.json alongside generated_debug.cpp. - // Consumed by the renderer via parseDebugMapV2. + // Consumed by the renderer via parseDebugMap. const debugMapPath = path.resolve(projectPath, 'build', boardTarget, 'src', 'debug-map.json') const content = await fs.readFile(debugMapPath, 'utf-8') return { success: true, content } From 57da46c1eb098d85ea5f153d871bac0a39abd644 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 08:04:43 -0400 Subject: [PATCH 044/296] fix(debug): align editor path helpers with STruC++ debug-map paths MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Root cause of "debugger connected but no Modbus traffic": buildDebugPath / findDebugVariable / the tree traversal all used the MatIEC-era path format — RES0__INSTANCE0.VAR, CONFIG0__GLOBAL, .value.table[i] for arrays, .value.FIELD for struct fields. STruC++ emits a simpler convention: INSTANCE0.VAR, INSTANCE0.ARR[5], INSTANCE0.STRUCT.FIELD. No match → no leaf got a debugIndex → polling filtered them all out → Modbus client never sent a frame → Rx/Tx LEDs dark, ladder static. Changes: - buildDebugPath: drops the RES0__ prefix, the .value.table[i] array shim, and the .value.FIELD struct shim. Paths now match STruC++ emission. - buildGlobalDebugPath: drops the CONFIG0__ prefix (STruC++ doesn't emit globals into debug-map.json yet; this helper returns the bare name so future support lines up). - buildDebugPathPrefix: returns INSTANCE_NAME (no RES0__). - findDebugVariableWithFallback / findDebugVariableForField / getIndexFromMapWithFallback / getFieldIndexFromMapWithFallback: simplified — STruC++ uses one path convention for both struct and FB fields, so the FB-style/struct-style fallback collapses. The `usedStructureStyle` result field is kept (always false) for API compatibility. - debug-tree-traversal: struct and array recursion use `.FIELD` and `[iec_idx]` directly (no .value. / .value.table wrapping). - OPC-UA keeps the MatIEC-format helpers in a new opcua/debug-paths.ts local module. OPC-UA still consumes MatIEC debug.c (distinct feature, not part of this debugger path), so its path convention is frozen there rather than forked downstream. - All 712 tests in src/frontend/utils/__tests__ pass. Full suite: 3317 passing + 3 pre-existing failures unchanged. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../__tests__/debug-tree-builder.test.ts | 72 +++--- .../__tests__/debug-tree-traversal.test.ts | 90 +++---- .../__tests__/debug-variable-finder.test.ts | 146 ++++++------ .../utils/__tests__/debugger-session.test.ts | 34 +-- src/frontend/utils/debug-tree-traversal.ts | 11 +- src/frontend/utils/debug-variable-finder.ts | 219 +++++------------- src/frontend/utils/opcua/debug-paths.ts | 100 ++++++++ src/frontend/utils/opcua/resolve-indices.ts | 2 +- 8 files changed, 333 insertions(+), 341 deletions(-) create mode 100644 src/frontend/utils/opcua/debug-paths.ts diff --git a/src/frontend/utils/__tests__/debug-tree-builder.test.ts b/src/frontend/utils/__tests__/debug-tree-builder.test.ts index afae857b4..01bd548d9 100644 --- a/src/frontend/utils/__tests__/debug-tree-builder.test.ts +++ b/src/frontend/utils/__tests__/debug-tree-builder.test.ts @@ -92,13 +92,13 @@ describe('buildDebugTree', () => { describe('base-type variables', () => { it('builds a leaf node for a base-type variable', () => { const variable = makeBaseVariable('SPEED', 'INT') - const debugVars = [makeDebugVar('RES0__INSTANCE0.SPEED', 'INT_ENUM', 0)] + const debugVars = [makeDebugVar('INSTANCE0.SPEED', 'INT_ENUM', 0)] const projectData = { dataTypes: [], pous: [] } const node = buildDebugTree(variable, 'Main', INSTANCE_NAME, debugVars, projectData) expect(node.name).toBe('SPEED') - expect(node.fullPath).toBe('RES0__INSTANCE0.SPEED') + expect(node.fullPath).toBe('INSTANCE0.SPEED') expect(node.compositeKey).toBe('Main:SPEED') expect(node.type).toBe('INT') expect(node.isComplex).toBe(false) @@ -116,14 +116,14 @@ describe('buildDebugTree', () => { }) describe('external variables', () => { - it('builds a leaf node for an external base-type variable using CONFIG0__ prefix', () => { + it('builds a leaf node for an external base-type variable using prefix', () => { const variable = makeBaseVariable('GLOBAL_FLAG', 'BOOL', 'external') - const debugVars = [makeDebugVar('CONFIG0__GLOBAL_FLAG', 'BOOL_ENUM', 5)] + const debugVars = [makeDebugVar('GLOBAL_FLAG', 'BOOL_ENUM', 5)] const projectData = { dataTypes: [], pous: [] } const node = buildDebugTree(variable, 'Main', INSTANCE_NAME, debugVars, projectData) - expect(node.fullPath).toBe('CONFIG0__GLOBAL_FLAG') + expect(node.fullPath).toBe('GLOBAL_FLAG') expect(node.compositeKey).toBe('Main:GLOBAL_FLAG') expect(node.debugIndex).toBe(5) expect(node.isComplex).toBe(false) @@ -135,16 +135,16 @@ describe('buildDebugTree', () => { const node = buildDebugTree(variable, 'Main', INSTANCE_NAME, [], projectData) - expect(node.fullPath).toBe('CONFIG0__MISSING_GLOBAL') + expect(node.fullPath).toBe('MISSING_GLOBAL') expect(node.debugIndex).toBeUndefined() }) it('traverses complex external variables using shared traversal', () => { const variable = makeDerivedVariable('EXT_FB', 'SR', 'external') const debugVars = [ - makeDebugVar('CONFIG0__EXT_FB.S1', 'BOOL_ENUM', 10), - makeDebugVar('CONFIG0__EXT_FB.R', 'BOOL_ENUM', 11), - makeDebugVar('CONFIG0__EXT_FB.Q1', 'BOOL_ENUM', 12), + makeDebugVar('EXT_FB.S1', 'BOOL_ENUM', 10), + makeDebugVar('EXT_FB.R', 'BOOL_ENUM', 11), + makeDebugVar('EXT_FB.Q1', 'BOOL_ENUM', 12), ] const projectData = { dataTypes: [], pous: [] } @@ -161,9 +161,9 @@ describe('buildDebugTree', () => { it('builds a complex node for a standard library FB (SR)', () => { const variable = makeDerivedVariable('MySR', 'SR') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.MYSR.S1', 'BOOL_ENUM', 0), - makeDebugVar('RES0__INSTANCE0.MYSR.R', 'BOOL_ENUM', 1), - makeDebugVar('RES0__INSTANCE0.MYSR.Q1', 'BOOL_ENUM', 2), + makeDebugVar('INSTANCE0.MYSR.S1', 'BOOL_ENUM', 0), + makeDebugVar('INSTANCE0.MYSR.R', 'BOOL_ENUM', 1), + makeDebugVar('INSTANCE0.MYSR.Q1', 'BOOL_ENUM', 2), ] const projectData = { dataTypes: [], pous: [] } @@ -184,8 +184,8 @@ describe('buildDebugTree', () => { ]) const variable = makeDerivedVariable('myFb', 'CustomFB') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.MYFB.IN1', 'INT_ENUM', 3), - makeDebugVar('RES0__INSTANCE0.MYFB.OUT1', 'BOOL_ENUM', 4), + makeDebugVar('INSTANCE0.MYFB.IN1', 'INT_ENUM', 3), + makeDebugVar('INSTANCE0.MYFB.OUT1', 'BOOL_ENUM', 4), ] const projectData = { dataTypes: [], pous: [customFbPou] } @@ -199,7 +199,7 @@ describe('buildDebugTree', () => { it('treats unresolvable derived type as leaf', () => { const variable = makeDerivedVariable('unknown_fb', 'NonExistentFB') - const debugVars = [makeDebugVar('RES0__INSTANCE0.UNKNOWN_FB', 'INT_ENUM', 99)] + const debugVars = [makeDebugVar('INSTANCE0.UNKNOWN_FB', 'INT_ENUM', 99)] const projectData = { dataTypes: [], pous: [] } const node = buildDebugTree(variable, 'Main', INSTANCE_NAME, debugVars, projectData) @@ -218,8 +218,8 @@ describe('buildDebugTree', () => { ]) const variable = makeUdtVariable('myVar', 'MyStruct') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.MYVAR.value.FIELD1', 'INT_ENUM', 10), - makeDebugVar('RES0__INSTANCE0.MYVAR.value.FIELD2', 'BOOL_ENUM', 11), + makeDebugVar('INSTANCE0.MYVAR.FIELD1', 'INT_ENUM', 10), + makeDebugVar('INSTANCE0.MYVAR.FIELD2', 'BOOL_ENUM', 11), ] const projectData = { dataTypes: [structType], pous: [] } @@ -229,13 +229,13 @@ describe('buildDebugTree', () => { expect(node.type).toBe('MyStruct') expect(node.children).toHaveLength(2) expect(node.children![0].name).toBe('field1') - expect(node.children![0].fullPath).toContain('.value.FIELD1') + expect(node.children![0].fullPath).toContain('FIELD1') expect(node.children![0].debugIndex).toBe(10) }) it('treats unresolvable UDT as leaf when it is not an FB', () => { const variable = makeUdtVariable('myVar', 'UnknownType') - const debugVars = [makeDebugVar('RES0__INSTANCE0.MYVAR', 'INT_ENUM', 50)] + const debugVars = [makeDebugVar('INSTANCE0.MYVAR', 'INT_ENUM', 50)] const projectData = { dataTypes: [], pous: [] } const node = buildDebugTree(variable, 'Main', INSTANCE_NAME, debugVars, projectData) @@ -247,7 +247,7 @@ describe('buildDebugTree', () => { it('resolves UDT that is actually an FB (user-data-type matching FB name)', () => { const customFb = makePou('MyFBType', 'function-block', [makeBaseVariable('Q', 'BOOL', 'output')]) const variable = makeUdtVariable('myInst', 'MyFBType') - const debugVars = [makeDebugVar('RES0__INSTANCE0.MYINST.Q', 'BOOL_ENUM', 60)] + const debugVars = [makeDebugVar('INSTANCE0.MYINST.Q', 'BOOL_ENUM', 60)] const projectData = { dataTypes: [], pous: [customFb] } const node = buildDebugTree(variable, 'Main', INSTANCE_NAME, debugVars, projectData) @@ -262,9 +262,9 @@ describe('buildDebugTree', () => { it('builds an array node with indexed children', () => { const variable = makeArrayVariable('myArr', 'INT', '0..2') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.MYARR.value.table[0]', 'INT_ENUM', 20), - makeDebugVar('RES0__INSTANCE0.MYARR.value.table[1]', 'INT_ENUM', 21), - makeDebugVar('RES0__INSTANCE0.MYARR.value.table[2]', 'INT_ENUM', 22), + makeDebugVar('INSTANCE0.MYARR[0]', 'INT_ENUM', 20), + makeDebugVar('INSTANCE0.MYARR[1]', 'INT_ENUM', 21), + makeDebugVar('INSTANCE0.MYARR[2]', 'INT_ENUM', 22), ] const projectData = { dataTypes: [], pous: [] } @@ -282,9 +282,9 @@ describe('buildDebugTree', () => { it('handles arrays with negative start index', () => { const variable = makeArrayVariable('negArr', 'BOOL', '-1..1') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.NEGARR.value.table[0]', 'BOOL_ENUM', 30), - makeDebugVar('RES0__INSTANCE0.NEGARR.value.table[1]', 'BOOL_ENUM', 31), - makeDebugVar('RES0__INSTANCE0.NEGARR.value.table[2]', 'BOOL_ENUM', 32), + makeDebugVar('INSTANCE0.NEGARR[0]', 'BOOL_ENUM', 30), + makeDebugVar('INSTANCE0.NEGARR[1]', 'BOOL_ENUM', 31), + makeDebugVar('INSTANCE0.NEGARR[2]', 'BOOL_ENUM', 32), ] const projectData = { dataTypes: [], pous: [] } @@ -313,10 +313,10 @@ describe('buildDebugTree', () => { documentation: '', } const debugVars = [ - makeDebugVar('RES0__INSTANCE0.POINTS.value.table[0].value.X', 'INT_ENUM', 40), - makeDebugVar('RES0__INSTANCE0.POINTS.value.table[0].value.Y', 'INT_ENUM', 41), - makeDebugVar('RES0__INSTANCE0.POINTS.value.table[1].value.X', 'INT_ENUM', 42), - makeDebugVar('RES0__INSTANCE0.POINTS.value.table[1].value.Y', 'INT_ENUM', 43), + makeDebugVar('INSTANCE0.POINTS[0]X', 'INT_ENUM', 40), + makeDebugVar('INSTANCE0.POINTS[0]Y', 'INT_ENUM', 41), + makeDebugVar('INSTANCE0.POINTS[1]X', 'INT_ENUM', 42), + makeDebugVar('INSTANCE0.POINTS[1]Y', 'INT_ENUM', 43), ] const projectData = { dataTypes: [structType], pous: [] } @@ -331,18 +331,18 @@ describe('buildDebugTree', () => { }) describe('buildVariableBasePath', () => { - it('returns CONFIG0__ path for external variables', () => { + it('returns path for external variables', () => { const result = buildVariableBasePath('GLOBAL_VAR', 'INSTANCE0', 'external') - expect(result).toBe('CONFIG0__GLOBAL_VAR') + expect(result).toBe('GLOBAL_VAR') }) - it('returns RES0__INSTANCE path for local variables', () => { + it('returns INSTANCE path for local variables', () => { const result = buildVariableBasePath('SPEED', 'INSTANCE0', 'local') - expect(result).toBe('RES0__INSTANCE0.SPEED') + expect(result).toBe('INSTANCE0.SPEED') }) - it('returns RES0__INSTANCE path when variableClass is undefined', () => { + it('returns INSTANCE path when variableClass is undefined', () => { const result = buildVariableBasePath('MY_VAR', 'INSTANCE0') - expect(result).toBe('RES0__INSTANCE0.MY_VAR') + expect(result).toBe('INSTANCE0.MY_VAR') }) }) diff --git a/src/frontend/utils/__tests__/debug-tree-traversal.test.ts b/src/frontend/utils/__tests__/debug-tree-traversal.test.ts index 9ec37446b..9c4008913 100644 --- a/src/frontend/utils/__tests__/debug-tree-traversal.test.ts +++ b/src/frontend/utils/__tests__/debug-tree-traversal.test.ts @@ -127,14 +127,14 @@ describe('traverseVariable', () => { describe('base-type variables', () => { it('returns a leaf node for a base-type variable', () => { const variable = makeBaseVariable('SPEED', 'INT') - const debugVars = [makeDebugVar('RES0__INSTANCE0.SPEED', 'INT_ENUM', 0)] + const debugVars = [makeDebugVar('INSTANCE0.SPEED', 'INT_ENUM', 0)] const ctx = makeContext({ debugVariables: debugVars }) const result = traverseVariable(variable, ctx, simpleVisitor) expect(result.kind).toBe('leaf') expect(result.name).toBe('SPEED') - expect(result.fullPath).toBe('RES0__INSTANCE0.SPEED') + expect(result.fullPath).toBe('INSTANCE0.SPEED') expect(result.compositeKey).toBe('Main:SPEED') expect(result.typeName).toBe('INT') expect(result.debugIndex).toBe(0) @@ -151,14 +151,14 @@ describe('traverseVariable', () => { }) describe('external variables', () => { - it('uses CONFIG0__ prefix for external base-type variables', () => { + it('uses prefix for external base-type variables', () => { const variable = makeBaseVariable('GLOBAL_FLAG', 'BOOL', 'external') - const debugVars = [makeDebugVar('CONFIG0__GLOBAL_FLAG', 'BOOL_ENUM', 5)] + const debugVars = [makeDebugVar('GLOBAL_FLAG', 'BOOL_ENUM', 5)] const ctx = makeContext({ debugVariables: debugVars }) const result = traverseVariable(variable, ctx, simpleVisitor) - expect(result.fullPath).toBe('CONFIG0__GLOBAL_FLAG') + expect(result.fullPath).toBe('GLOBAL_FLAG') expect(result.debugIndex).toBe(5) }) }) @@ -167,9 +167,9 @@ describe('traverseVariable', () => { it('expands a standard library FB (SR) into complex node', () => { const variable = makeDerivedVariable('mySR', 'SR') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.MYSR.S1', 'BOOL_ENUM', 0), - makeDebugVar('RES0__INSTANCE0.MYSR.R', 'BOOL_ENUM', 1), - makeDebugVar('RES0__INSTANCE0.MYSR.Q1', 'BOOL_ENUM', 2), + makeDebugVar('INSTANCE0.MYSR.S1', 'BOOL_ENUM', 0), + makeDebugVar('INSTANCE0.MYSR.R', 'BOOL_ENUM', 1), + makeDebugVar('INSTANCE0.MYSR.Q1', 'BOOL_ENUM', 2), ] const ctx = makeContext({ debugVariables: debugVars }) @@ -188,8 +188,8 @@ describe('traverseVariable', () => { ]) const variable = makeDerivedVariable('inst', 'MyCustomFB') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.INST.X', 'INT_ENUM', 10), - makeDebugVar('RES0__INSTANCE0.INST.Y', 'BOOL_ENUM', 11), + makeDebugVar('INSTANCE0.INST.X', 'INT_ENUM', 10), + makeDebugVar('INSTANCE0.INST.Y', 'BOOL_ENUM', 11), ] const ctx = makeContext({ debugVariables: debugVars, projectPous: [customFb] }) @@ -201,7 +201,7 @@ describe('traverseVariable', () => { it('treats unresolvable derived type as leaf', () => { const variable = makeDerivedVariable('inst', 'NonExistent') - const debugVars = [makeDebugVar('RES0__INSTANCE0.INST', 'INT_ENUM', 99)] + const debugVars = [makeDebugVar('INSTANCE0.INST', 'INT_ENUM', 99)] const ctx = makeContext({ debugVariables: debugVars }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -214,7 +214,7 @@ describe('traverseVariable', () => { const innerFb = makePou('InnerFB', 'function-block', [makeBaseVariable('Q', 'BOOL', 'output')]) const outerFb = makePou('OuterFB', 'function-block', [makeDerivedVariable('inner', 'InnerFB', 'local')]) const variable = makeDerivedVariable('outer', 'OuterFB') - const debugVars = [makeDebugVar('RES0__INSTANCE0.OUTER.INNER.Q', 'BOOL_ENUM', 20)] + const debugVars = [makeDebugVar('INSTANCE0.OUTER.INNER.Q', 'BOOL_ENUM', 20)] const ctx = makeContext({ debugVariables: debugVars, projectPous: [innerFb, outerFb] }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -229,7 +229,7 @@ describe('traverseVariable', () => { const innerFb = makePou('SubFB', 'function-block', [makeBaseVariable('Z', 'INT', 'output')]) const outerFb = makePou('WrapperFB', 'function-block', [makeUdtVariable('sub', 'SubFB', 'local')]) const variable = makeDerivedVariable('wrapper', 'WrapperFB') - const debugVars = [makeDebugVar('RES0__INSTANCE0.WRAPPER.SUB.Z', 'INT_ENUM', 30)] + const debugVars = [makeDebugVar('INSTANCE0.WRAPPER.SUB.Z', 'INT_ENUM', 30)] const ctx = makeContext({ debugVariables: debugVars, projectPous: [innerFb, outerFb] }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -244,7 +244,7 @@ describe('traverseVariable', () => { ]) const outerFb = makePou('FBWithStruct', 'function-block', [makeUdtVariable('data', 'MyStruct', 'local')]) const variable = makeDerivedVariable('inst', 'FBWithStruct') - const debugVars = [makeDebugVar('RES0__INSTANCE0.INST.DATA.value.FIELD1', 'INT_ENUM', 40)] + const debugVars = [makeDebugVar('INSTANCE0.INST.DATAFIELD1', 'INT_ENUM', 40)] const ctx = makeContext({ debugVariables: debugVars, projectPous: [outerFb], dataTypes: [structType] }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -260,8 +260,8 @@ describe('traverseVariable', () => { ]) const variable = makeDerivedVariable('inst', 'FBWithArray') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.INST.ARR.value.table[0]', 'INT_ENUM', 50), - makeDebugVar('RES0__INSTANCE0.INST.ARR.value.table[1]', 'INT_ENUM', 51), + makeDebugVar('INSTANCE0.INST.ARR[0]', 'INT_ENUM', 50), + makeDebugVar('INSTANCE0.INST.ARR[1]', 'INT_ENUM', 51), ] const ctx = makeContext({ debugVariables: debugVars, projectPous: [outerFb] }) @@ -301,8 +301,8 @@ describe('traverseVariable', () => { ]) const variable = makeUdtVariable('pos', 'Point') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.POS.value.X', 'INT_ENUM', 10), - makeDebugVar('RES0__INSTANCE0.POS.value.Y', 'INT_ENUM', 11), + makeDebugVar('INSTANCE0.POSX', 'INT_ENUM', 10), + makeDebugVar('INSTANCE0.POSY', 'INT_ENUM', 11), ] const ctx = makeContext({ debugVariables: debugVars, dataTypes: [structType] }) @@ -311,12 +311,12 @@ describe('traverseVariable', () => { expect(result.kind).toBe('complex') expect(result.children).toHaveLength(2) expect(result.children![0].name).toBe('x') - expect(result.children![0].fullPath).toContain('.value.X') + expect(result.children![0].fullPath).toContain('X') }) it('treats unresolvable UDT as leaf', () => { const variable = makeUdtVariable('unknown', 'NoSuchType') - const debugVars = [makeDebugVar('RES0__INSTANCE0.UNKNOWN', 'INT_ENUM', 99)] + const debugVars = [makeDebugVar('INSTANCE0.UNKNOWN', 'INT_ENUM', 99)] const ctx = makeContext({ debugVariables: debugVars }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -327,7 +327,7 @@ describe('traverseVariable', () => { it('resolves UDT to FB when name matches a function-block POU', () => { const customFb = makePou('SomeFB', 'function-block', [makeBaseVariable('Q', 'BOOL', 'output')]) const variable = makeUdtVariable('inst', 'SomeFB') - const debugVars = [makeDebugVar('RES0__INSTANCE0.INST.Q', 'BOOL_ENUM', 55)] + const debugVars = [makeDebugVar('INSTANCE0.INST.Q', 'BOOL_ENUM', 55)] const ctx = makeContext({ debugVariables: debugVars, projectPous: [customFb] }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -344,7 +344,7 @@ describe('traverseVariable', () => { { name: 'nested', type: { definition: 'user-data-type', value: 'Inner' } }, ]) const variable = makeUdtVariable('obj', 'Outer') - const debugVars = [makeDebugVar('RES0__INSTANCE0.OBJ.value.NESTED.value.VAL', 'INT_ENUM', 70)] + const debugVars = [makeDebugVar('INSTANCE0.OBJNESTEDVAL', 'INT_ENUM', 70)] const ctx = makeContext({ debugVariables: debugVars, dataTypes: [innerStruct, outerStruct] }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -360,7 +360,7 @@ describe('traverseVariable', () => { { name: 'fb', type: { definition: 'user-data-type', value: 'NestedFB' } }, ]) const variable = makeUdtVariable('data', 'StructWithFB') - const debugVars = [makeDebugVar('RES0__INSTANCE0.DATA.value.FB.OUT', 'BOOL_ENUM', 80)] + const debugVars = [makeDebugVar('INSTANCE0.DATAFB.OUT', 'BOOL_ENUM', 80)] const ctx = makeContext({ debugVariables: debugVars, projectPous: [fbPou], dataTypes: [outerStruct] }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -385,8 +385,8 @@ describe('traverseVariable', () => { ]) const variable = makeUdtVariable('s', 'StructWithArray') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.S.value.ARR.value.table[0]', 'INT_ENUM', 90), - makeDebugVar('RES0__INSTANCE0.S.value.ARR.value.table[1]', 'INT_ENUM', 91), + makeDebugVar('INSTANCE0.SARR[0]', 'INT_ENUM', 90), + makeDebugVar('INSTANCE0.SARR[1]', 'INT_ENUM', 91), ] const ctx = makeContext({ debugVariables: debugVars, dataTypes: [outerStruct] }) @@ -418,9 +418,9 @@ describe('traverseVariable', () => { it('builds an array node with base-type elements', () => { const variable = makeArrayVariable('myArr', 'base-type', 'INT', '1..3') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.MYARR.value.table[0]', 'INT_ENUM', 0), - makeDebugVar('RES0__INSTANCE0.MYARR.value.table[1]', 'INT_ENUM', 1), - makeDebugVar('RES0__INSTANCE0.MYARR.value.table[2]', 'INT_ENUM', 2), + makeDebugVar('INSTANCE0.MYARR[0]', 'INT_ENUM', 0), + makeDebugVar('INSTANCE0.MYARR[1]', 'INT_ENUM', 1), + makeDebugVar('INSTANCE0.MYARR[2]', 'INT_ENUM', 2), ] const ctx = makeContext({ debugVariables: debugVars }) @@ -436,7 +436,7 @@ describe('traverseVariable', () => { it('builds an array node with UDT elements', () => { const structType = makeStructDataType('Item', [{ name: 'val', type: { definition: 'base-type', value: 'INT' } }]) const variable = makeArrayVariable('items', 'user-data-type', 'Item', '0..0') - const debugVars = [makeDebugVar('RES0__INSTANCE0.ITEMS.value.table[0].value.VAL', 'INT_ENUM', 100)] + const debugVars = [makeDebugVar('INSTANCE0.ITEMS[0]VAL', 'INT_ENUM', 100)] const ctx = makeContext({ debugVariables: debugVars, dataTypes: [structType] }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -497,7 +497,7 @@ describe('traverseVariable', () => { it('builds an array node with UDT elements that resolve to FB', () => { const customFb = makePou('InnerFB', 'function-block', [makeBaseVariable('Q', 'BOOL', 'output')]) const variable = makeArrayVariable('fbArr', 'user-data-type', 'InnerFB', '0..0') - const debugVars = [makeDebugVar('RES0__INSTANCE0.FBARR.value.table[0].Q', 'BOOL_ENUM', 110)] + const debugVars = [makeDebugVar('INSTANCE0.FBARR[0].Q', 'BOOL_ENUM', 110)] const ctx = makeContext({ debugVariables: debugVars, projectPous: [customFb] }) const result = traverseVariable(variable, ctx, simpleVisitor) @@ -555,12 +555,12 @@ describe('traverseVariable', () => { describe('traverseNestedType', () => { it('delegates to the internal traverseNestedNode for derived types', () => { const customFb = makePou('MyFB', 'function-block', [makeBaseVariable('X', 'INT', 'output')]) - const debugVars = [makeDebugVar('RES0__INSTANCE0.INST.X', 'INT_ENUM', 0)] + const debugVars = [makeDebugVar('INSTANCE0.INST.X', 'INT_ENUM', 0)] const ctx = makeContext({ debugVariables: debugVars, projectPous: [customFb] }) const result = traverseNestedType( 'inst', - 'RES0__INSTANCE0.INST', + 'INSTANCE0.INST', 'Main:inst', 'MyFB', 'derived', @@ -574,12 +574,12 @@ describe('traverseNestedType', () => { it('delegates for user-data-type (structure)', () => { const structType = makeStructDataType('S', [{ name: 'f', type: { definition: 'base-type', value: 'BOOL' } }]) - const debugVars = [makeDebugVar('RES0__INSTANCE0.VAR.value.F', 'BOOL_ENUM', 5)] + const debugVars = [makeDebugVar('INSTANCE0.VARF', 'BOOL_ENUM', 5)] const ctx = makeContext({ debugVariables: debugVars, dataTypes: [structType] }) const result = traverseNestedType( 'var', - 'RES0__INSTANCE0.VAR', + 'INSTANCE0.VAR', 'Main:var', 'S', 'user-data-type', @@ -592,7 +592,7 @@ describe('traverseNestedType', () => { }) it('delegates for array type', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.ARR.value.table[0]', 'INT_ENUM', 10)] + const debugVars = [makeDebugVar('INSTANCE0.ARR[0]', 'INT_ENUM', 10)] const ctx = makeContext({ debugVariables: debugVars }) const arrayData = { baseType: { definition: 'base-type' as const, value: 'INT' }, @@ -601,7 +601,7 @@ describe('traverseNestedType', () => { const result = traverseNestedType( 'arr', - 'RES0__INSTANCE0.ARR', + 'INSTANCE0.ARR', 'Main:arr', 'ARRAY', 'array', @@ -617,19 +617,19 @@ describe('traverseNestedType', () => { it('falls through to leaf for unknown nested typeDefinition', () => { const ctx = makeContext() - const result = traverseNestedType('x', 'RES0__INSTANCE0.X', 'Main:x', 'SomeType', 'derived', ctx, simpleVisitor) + const result = traverseNestedType('x', 'INSTANCE0.X', 'Main:x', 'SomeType', 'derived', ctx, simpleVisitor) // 'derived' with no matching FB definition -> leaf expect(result.kind).toBe('leaf') }) it('falls through to leaf for array typeDefinition without arrayData', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.ARR', 'INT_ENUM', 42)] + const debugVars = [makeDebugVar('INSTANCE0.ARR', 'INT_ENUM', 42)] const ctx = makeContext({ debugVariables: debugVars }) const result = traverseNestedType( 'arr', - 'RES0__INSTANCE0.ARR', + 'INSTANCE0.ARR', 'Main:arr', 'ARRAY', 'array', @@ -650,9 +650,9 @@ describe('traverseNestedType', () => { ]) const variable = makeUdtVariable('s', 'StructWithStdFB') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.S.value.SR_INST.S1', 'BOOL_ENUM', 100), - makeDebugVar('RES0__INSTANCE0.S.value.SR_INST.R', 'BOOL_ENUM', 101), - makeDebugVar('RES0__INSTANCE0.S.value.SR_INST.Q1', 'BOOL_ENUM', 102), + makeDebugVar('INSTANCE0.SSR_INST.S1', 'BOOL_ENUM', 100), + makeDebugVar('INSTANCE0.SSR_INST.R', 'BOOL_ENUM', 101), + makeDebugVar('INSTANCE0.SSR_INST.Q1', 'BOOL_ENUM', 102), ] const ctx = makeContext({ debugVariables: debugVars, dataTypes: [outerStruct] }) @@ -668,9 +668,9 @@ describe('traverseNestedType', () => { // Array of SR (standard library FB) const variable = makeArrayVariable('arr', 'user-data-type', 'SR', '0..0') const debugVars = [ - makeDebugVar('RES0__INSTANCE0.ARR.value.table[0].S1', 'BOOL_ENUM', 200), - makeDebugVar('RES0__INSTANCE0.ARR.value.table[0].R', 'BOOL_ENUM', 201), - makeDebugVar('RES0__INSTANCE0.ARR.value.table[0].Q1', 'BOOL_ENUM', 202), + makeDebugVar('INSTANCE0.ARR[0].S1', 'BOOL_ENUM', 200), + makeDebugVar('INSTANCE0.ARR[0].R', 'BOOL_ENUM', 201), + makeDebugVar('INSTANCE0.ARR[0].Q1', 'BOOL_ENUM', 202), ] const ctx = makeContext({ debugVariables: debugVars }) diff --git a/src/frontend/utils/__tests__/debug-variable-finder.test.ts b/src/frontend/utils/__tests__/debug-variable-finder.test.ts index 852b296b7..8315eba82 100644 --- a/src/frontend/utils/__tests__/debug-variable-finder.test.ts +++ b/src/frontend/utils/__tests__/debug-variable-finder.test.ts @@ -47,115 +47,115 @@ describe('findInstanceName', () => { describe('buildDebugPath', () => { it('builds simple variable path', () => { - expect(buildDebugPath('INSTANCE0', 'SPEED')).toBe('RES0__INSTANCE0.SPEED') + expect(buildDebugPath('INSTANCE0', 'SPEED')).toBe('INSTANCE0.SPEED') }) - it('builds FB instance variable path (no .value.)', () => { - expect(buildDebugPath('INSTANCE0', 'TIMER0.Q')).toBe('RES0__INSTANCE0.TIMER0.Q') + it('builds FB instance variable path', () => { + expect(buildDebugPath('INSTANCE0', 'TIMER0.Q')).toBe('INSTANCE0.TIMER0.Q') }) it('builds simple array element path', () => { const result = buildDebugPath('INSTANCE0', 'ARR', { isArrayElement: true, arrayIndex: 3 }) - expect(result).toBe('RES0__INSTANCE0.ARR.value.table[3]') + expect(result).toBe('INSTANCE0.ARR[3]') }) - it('builds structure field path with .value. insertion', () => { - const result = buildDebugPath('INSTANCE0', 'MY_STRUCT.FIELD1', { isStructureField: true }) - expect(result).toBe('RES0__INSTANCE0.MY_STRUCT.value.FIELD1') + it('builds structure field path (no .value. shim in STruC++ paths)', () => { + const result = buildDebugPath('INSTANCE0', 'MY_STRUCT.FIELD1') + expect(result).toBe('INSTANCE0.MY_STRUCT.FIELD1') }) it('builds structure field path with array index within structure', () => { - const result = buildDebugPath('INSTANCE0', 'MY_STRUCT.[0]', { isStructureField: true }) - expect(result).toBe('RES0__INSTANCE0.MY_STRUCT.value.table[0]') + const result = buildDebugPath('INSTANCE0', 'MY_STRUCT.[0]') + expect(result).toBe('INSTANCE0.MY_STRUCT[0]') }) it('handles array index in non-structure path (FB_ARRAY.[0].ET)', () => { const result = buildDebugPath('INSTANCE0', 'FB_ARRAY.[0].ET') - expect(result).toBe('RES0__INSTANCE0.FB_ARRAY.value.table[0].ET') + expect(result).toBe('INSTANCE0.FB_ARRAY[0].ET') }) it('uppercases the instance name', () => { - expect(buildDebugPath('instance0', 'X')).toBe('RES0__INSTANCE0.X') + expect(buildDebugPath('instance0', 'X')).toBe('INSTANCE0.X') }) it('uses default arrayIndex of 0 when isArrayElement but no arrayIndex provided', () => { const result = buildDebugPath('INSTANCE0', 'ARR', { isArrayElement: true }) - expect(result).toBe('RES0__INSTANCE0.ARR.value.table[0]') + expect(result).toBe('INSTANCE0.ARR[0]') }) - it('builds nested structure field paths', () => { - const result = buildDebugPath('INSTANCE0', 'OUTER.INNER.FIELD', { isStructureField: true }) - expect(result).toBe('RES0__INSTANCE0.OUTER.value.INNER.value.FIELD') + it('builds nested struct/FB field paths', () => { + const result = buildDebugPath('INSTANCE0', 'OUTER.INNER.FIELD') + expect(result).toBe('INSTANCE0.OUTER.INNER.FIELD') }) }) describe('buildGlobalDebugPath', () => { - it('builds CONFIG0__ prefixed path', () => { - expect(buildGlobalDebugPath('MY_GLOBAL')).toBe('CONFIG0__MY_GLOBAL') + it('returns uppercased name', () => { + expect(buildGlobalDebugPath('MY_GLOBAL')).toBe('MY_GLOBAL') }) it('uppercases the variable path', () => { - expect(buildGlobalDebugPath('my_global')).toBe('CONFIG0__MY_GLOBAL') + expect(buildGlobalDebugPath('my_global')).toBe('MY_GLOBAL') }) }) describe('findDebugVariable', () => { const debugVars = [ - makeDebugVar('RES0__INSTANCE0.SPEED', 'INT_ENUM', 0), - makeDebugVar('RES0__INSTANCE0.TEMP', 'REAL_ENUM', 1), + makeDebugVar('INSTANCE0.SPEED', 'INT_ENUM', 0), + makeDebugVar('INSTANCE0.TEMP', 'REAL_ENUM', 1), ] it('finds variable by exact path (case-insensitive)', () => { - const result = findDebugVariable(debugVars, 'RES0__INSTANCE0.SPEED') + const result = findDebugVariable(debugVars, 'INSTANCE0.SPEED') expect(result).toEqual(debugVars[0]) }) it('finds variable with different case', () => { - const result = findDebugVariable(debugVars, 'res0__instance0.speed') + const result = findDebugVariable(debugVars, 'instance0.speed') expect(result).toEqual(debugVars[0]) }) it('returns null when not found', () => { - const result = findDebugVariable(debugVars, 'RES0__INSTANCE0.MISSING') + const result = findDebugVariable(debugVars, 'INSTANCE0.MISSING') expect(result).toBeNull() }) }) describe('findDebugVariableWithFallback', () => { - it('finds variable using FB-style path first', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.FB1.Q', 'BOOL_ENUM', 10)] + it('resolves FB field paths', () => { + const debugVars = [makeDebugVar('INSTANCE0.FB1.Q', 'BOOL_ENUM', 10)] const result = findDebugVariableWithFallback(debugVars, 'INSTANCE0', 'FB1.Q') expect(result.match).toEqual(debugVars[0]) expect(result.usedStructureStyle).toBe(false) }) - it('falls back to structure-style path when FB-style fails', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.STRUCT.value.FIELD', 'INT_ENUM', 20)] + it('resolves struct field paths with the same convention as FB fields', () => { + const debugVars = [makeDebugVar('INSTANCE0.STRUCT.FIELD', 'INT_ENUM', 20)] const result = findDebugVariableWithFallback(debugVars, 'INSTANCE0', 'STRUCT.FIELD') expect(result.match).toEqual(debugVars[0]) - expect(result.usedStructureStyle).toBe(true) + expect(result.usedStructureStyle).toBe(false) }) - it('returns null match when neither path style works', () => { + it('returns null when the path is not found', () => { const result = findDebugVariableWithFallback([], 'INSTANCE0', 'MISSING.PATH') expect(result.match).toBeNull() expect(result.usedStructureStyle).toBe(false) - expect(result.matchedPath).toBe('RES0__INSTANCE0.MISSING.PATH') + expect(result.matchedPath).toBe('INSTANCE0.MISSING.PATH') }) }) describe('findVariableIndexWithFallback', () => { - it('returns the index when FB-style path matches', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.FB.Q', 'BOOL_ENUM', 15)] + it('returns the index for FB field paths', () => { + const debugVars = [makeDebugVar('INSTANCE0.FB.Q', 'BOOL_ENUM', 15)] const result = findVariableIndexWithFallback('INSTANCE0', 'FB.Q', debugVars) expect(result).toBe(15) }) - it('returns the index when structure-style path matches', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.S.value.F', 'INT_ENUM', 25)] + it('returns the index for struct field paths', () => { + const debugVars = [makeDebugVar('INSTANCE0.S.F', 'INT_ENUM', 25)] const result = findVariableIndexWithFallback('INSTANCE0', 'S.F', debugVars) expect(result).toBe(25) }) @@ -167,54 +167,54 @@ describe('findVariableIndexWithFallback', () => { }) describe('findDebugVariableForField', () => { - it('finds field using FB-style path (no .value.)', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.MY_FB.Q', 'BOOL_ENUM', 30)] - const result = findDebugVariableForField(debugVars, 'RES0__INSTANCE0.MY_FB', 'Q') + it('finds FB field', () => { + const debugVars = [makeDebugVar('INSTANCE0.MY_FB.Q', 'BOOL_ENUM', 30)] + const result = findDebugVariableForField(debugVars, 'INSTANCE0.MY_FB', 'Q') expect(result.match).toEqual(debugVars[0]) - expect(result.matchedPath).toBe('RES0__INSTANCE0.MY_FB.Q') + expect(result.matchedPath).toBe('INSTANCE0.MY_FB.Q') expect(result.usedStructureStyle).toBe(false) }) - it('finds field using struct-style path (with .value.)', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.STRUCT.value.FIELD', 'INT_ENUM', 31)] - const result = findDebugVariableForField(debugVars, 'RES0__INSTANCE0.STRUCT', 'FIELD') + it('finds struct field using the same path convention as FB', () => { + const debugVars = [makeDebugVar('INSTANCE0.STRUCT.FIELD', 'INT_ENUM', 31)] + const result = findDebugVariableForField(debugVars, 'INSTANCE0.STRUCT', 'FIELD') expect(result.match).toEqual(debugVars[0]) - expect(result.matchedPath).toBe('RES0__INSTANCE0.STRUCT.value.FIELD') - expect(result.usedStructureStyle).toBe(true) + expect(result.matchedPath).toBe('INSTANCE0.STRUCT.FIELD') + expect(result.usedStructureStyle).toBe(false) }) - it('returns null match when neither path works', () => { - const result = findDebugVariableForField([], 'RES0__INSTANCE0.BASE', 'MISSING') + it('returns null when field is absent', () => { + const result = findDebugVariableForField([], 'INSTANCE0.BASE', 'MISSING') expect(result.match).toBeNull() - expect(result.matchedPath).toBe('RES0__INSTANCE0.BASE.MISSING') + expect(result.matchedPath).toBe('INSTANCE0.BASE.MISSING') expect(result.usedStructureStyle).toBe(false) }) it('uppercases field name in lookup', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.FB.FIELD', 'INT_ENUM', 32)] - const result = findDebugVariableForField(debugVars, 'RES0__INSTANCE0.FB', 'field') + const debugVars = [makeDebugVar('INSTANCE0.FB.FIELD', 'INT_ENUM', 32)] + const result = findDebugVariableForField(debugVars, 'INSTANCE0.FB', 'field') expect(result.match).toEqual(debugVars[0]) }) }) describe('getIndexFromMapWithFallback', () => { - it('returns index from FB-style path', () => { - const indexMap = new Map([['RES0__INSTANCE0.FB.Q', 40]]) + it('returns index by instance + variable path', () => { + const indexMap = new Map([['INSTANCE0.FB.Q', 40]]) const result = getIndexFromMapWithFallback(indexMap, 'INSTANCE0', 'FB.Q') expect(result).toBe(40) }) - it('returns index from struct-style path when FB-style fails', () => { - const indexMap = new Map([['RES0__INSTANCE0.STRUCT.value.FIELD', 41]]) + it('returns index for struct field paths', () => { + const indexMap = new Map([['INSTANCE0.STRUCT.FIELD', 41]]) const result = getIndexFromMapWithFallback(indexMap, 'INSTANCE0', 'STRUCT.FIELD') expect(result).toBe(41) }) - it('returns undefined when neither path is in the map', () => { + it('returns undefined when path is not in the map', () => { const indexMap = new Map() const result = getIndexFromMapWithFallback(indexMap, 'INSTANCE0', 'NOTHING') expect(result).toBeUndefined() @@ -222,34 +222,34 @@ describe('getIndexFromMapWithFallback', () => { }) describe('getFieldIndexFromMapWithFallback', () => { - it('returns index from FB-style field path', () => { - const indexMap = new Map([['RES0__INSTANCE0.FB.FIELD', 50]]) - const result = getFieldIndexFromMapWithFallback(indexMap, 'RES0__INSTANCE0.FB', 'FIELD') + it('returns index by base path + field name', () => { + const indexMap = new Map([['INSTANCE0.FB.FIELD', 50]]) + const result = getFieldIndexFromMapWithFallback(indexMap, 'INSTANCE0.FB', 'FIELD') expect(result).toBe(50) }) - it('returns index from struct-style field path when FB-style fails', () => { - const indexMap = new Map([['RES0__INSTANCE0.S.value.F', 51]]) - const result = getFieldIndexFromMapWithFallback(indexMap, 'RES0__INSTANCE0.S', 'F') + it('returns index for struct field paths', () => { + const indexMap = new Map([['INSTANCE0.S.F', 51]]) + const result = getFieldIndexFromMapWithFallback(indexMap, 'INSTANCE0.S', 'F') expect(result).toBe(51) }) it('returns undefined when neither field path is in the map', () => { const indexMap = new Map() - const result = getFieldIndexFromMapWithFallback(indexMap, 'RES0__INSTANCE0.X', 'Y') + const result = getFieldIndexFromMapWithFallback(indexMap, 'INSTANCE0.X', 'Y') expect(result).toBeUndefined() }) it('uppercases field name in path lookup', () => { - const indexMap = new Map([['RES0__INSTANCE0.FB.LOWERCASE', 52]]) - const result = getFieldIndexFromMapWithFallback(indexMap, 'RES0__INSTANCE0.FB', 'lowercase') + const indexMap = new Map([['INSTANCE0.FB.LOWERCASE', 52]]) + const result = getFieldIndexFromMapWithFallback(indexMap, 'INSTANCE0.FB', 'lowercase') expect(result).toBe(52) }) }) describe('findVariableIndex', () => { it('returns the index for a simple variable', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.SPEED', 'INT_ENUM', 60)] + const debugVars = [makeDebugVar('INSTANCE0.SPEED', 'INT_ENUM', 60)] const result = findVariableIndex('INSTANCE0', 'SPEED', debugVars) expect(result).toBe(60) }) @@ -260,21 +260,21 @@ describe('findVariableIndex', () => { }) it('passes options through to buildDebugPath', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.ARR.value.table[2]', 'INT_ENUM', 61)] + const debugVars = [makeDebugVar('INSTANCE0.ARR[2]', 'INT_ENUM', 61)] const result = findVariableIndex('INSTANCE0', 'ARR', debugVars, { isArrayElement: true, arrayIndex: 2 }) expect(result).toBe(61) }) - it('handles structure field option', () => { - const debugVars = [makeDebugVar('RES0__INSTANCE0.S.value.F', 'INT_ENUM', 62)] - const result = findVariableIndex('INSTANCE0', 'S.F', debugVars, { isStructureField: true }) + it('handles struct field paths', () => { + const debugVars = [makeDebugVar('INSTANCE0.S.F', 'INT_ENUM', 62)] + const result = findVariableIndex('INSTANCE0', 'S.F', debugVars) expect(result).toBe(62) }) }) describe('findGlobalVariableIndex', () => { it('returns the index for a global variable', () => { - const debugVars = [makeDebugVar('CONFIG0__GLOBAL_FLAG', 'BOOL_ENUM', 70)] + const debugVars = [makeDebugVar('GLOBAL_FLAG', 'BOOL_ENUM', 70)] const result = findGlobalVariableIndex('GLOBAL_FLAG', debugVars) expect(result).toBe(70) }) @@ -286,22 +286,22 @@ describe('findGlobalVariableIndex', () => { }) describe('buildDebugPathPrefix', () => { - it('returns RES0__INSTANCE_NAME prefix', () => { - expect(buildDebugPathPrefix('INSTANCE0')).toBe('RES0__INSTANCE0') + it('returns INSTANCE_NAME prefix', () => { + expect(buildDebugPathPrefix('INSTANCE0')).toBe('INSTANCE0') }) it('uppercases the instance name', () => { - expect(buildDebugPathPrefix('instance0')).toBe('RES0__INSTANCE0') + expect(buildDebugPathPrefix('instance0')).toBe('INSTANCE0') }) }) describe('appendToDebugPath', () => { it('appends child name with dot separator and uppercases it', () => { - expect(appendToDebugPath('RES0__INSTANCE0.FB', 'field')).toBe('RES0__INSTANCE0.FB.FIELD') + expect(appendToDebugPath('INSTANCE0.FB', 'field')).toBe('INSTANCE0.FB.FIELD') }) it('handles already uppercased child name', () => { - expect(appendToDebugPath('RES0__INSTANCE0', 'VAR')).toBe('RES0__INSTANCE0.VAR') + expect(appendToDebugPath('INSTANCE0', 'VAR')).toBe('INSTANCE0.VAR') }) }) diff --git a/src/frontend/utils/__tests__/debugger-session.test.ts b/src/frontend/utils/__tests__/debugger-session.test.ts index f9fb9d6ad..4493e0d2f 100644 --- a/src/frontend/utils/__tests__/debugger-session.test.ts +++ b/src/frontend/utils/__tests__/debugger-session.test.ts @@ -265,8 +265,8 @@ describe('buildDebugVariableTreeMap', () => { const pou = makePou('Main', 'program', [makeBaseVariable('X', 'INT'), makeBaseVariable('Y', 'BOOL')]) const instances = [makeInstance('INSTANCE0', 'Main')] const debugVars = [ - makeDebugVar('RES0__INSTANCE0.X', 'INT_ENUM', 0), - makeDebugVar('RES0__INSTANCE0.Y', 'BOOL_ENUM', 1), + makeDebugVar('INSTANCE0.X', 'INT_ENUM', 0), + makeDebugVar('INSTANCE0.Y', 'BOOL_ENUM', 1), ] const projectData = { dataTypes: [] as PLCDataType[], pous: [pou] } @@ -282,9 +282,9 @@ describe('buildDebugVariableTreeMap', () => { const pou = makePou('Main', 'program', [makeDerivedVariable('mySR', 'SR')]) const instances = [makeInstance('INSTANCE0', 'Main')] const debugVars = [ - makeDebugVar('RES0__INSTANCE0.MYSR.S1', 'BOOL_ENUM', 0), - makeDebugVar('RES0__INSTANCE0.MYSR.R', 'BOOL_ENUM', 1), - makeDebugVar('RES0__INSTANCE0.MYSR.Q1', 'BOOL_ENUM', 2), + makeDebugVar('INSTANCE0.MYSR.S1', 'BOOL_ENUM', 0), + makeDebugVar('INSTANCE0.MYSR.R', 'BOOL_ENUM', 1), + makeDebugVar('INSTANCE0.MYSR.Q1', 'BOOL_ENUM', 2), ] const projectData = { dataTypes: [] as PLCDataType[], pous: [pou] } @@ -297,9 +297,9 @@ describe('buildDebugVariableTreeMap', () => { const pou = makePou('Main', 'program', [makeDerivedVariable('mySR', 'SR')]) const instances = [makeInstance('INSTANCE0', 'Main')] const debugVars = [ - makeDebugVar('RES0__INSTANCE0.MYSR.S1', 'BOOL_ENUM', 0), - makeDebugVar('RES0__INSTANCE0.MYSR.R', 'BOOL_ENUM', 1), - makeDebugVar('RES0__INSTANCE0.MYSR.Q1', 'BOOL_ENUM', 2), + makeDebugVar('INSTANCE0.MYSR.S1', 'BOOL_ENUM', 0), + makeDebugVar('INSTANCE0.MYSR.R', 'BOOL_ENUM', 1), + makeDebugVar('INSTANCE0.MYSR.Q1', 'BOOL_ENUM', 2), ] const projectData = { dataTypes: [] as PLCDataType[], pous: [pou] } @@ -343,7 +343,7 @@ describe('buildDebugVariableTreeMap', () => { const goodVar = makeBaseVariable('good', 'INT') const pou = makePou('Main', 'program', [badVar, goodVar]) const instances = [makeInstance('INSTANCE0', 'Main')] - const debugVars = [makeDebugVar('RES0__INSTANCE0.GOOD', 'INT_ENUM', 0)] + const debugVars = [makeDebugVar('INSTANCE0.GOOD', 'INT_ENUM', 0)] const projectData = { dataTypes: [] as PLCDataType[], pous: [pou] } // Should not throw, should still include the good variable @@ -358,10 +358,10 @@ describe('buildDebugVariableTreeMap', () => { const pou = makePou('Main', 'program', []) const instances = [makeInstance('INSTANCE0', 'Main')] const debugVars = [ - makeDebugVar('RES0__INSTANCE0._TMP_ADD3_OUT', 'INT_ENUM', 100), - makeDebugVar('RES0__INSTANCE0._TMP_MUL5_RES', 'REAL_O_ENUM', 101), - makeDebugVar('RES0__INSTANCE0._TMP_SUB1_X', 'DINT_P_ENUM', 102), - makeDebugVar('RES0__INSTANCE0._TMP_DIV2_Y', 'LINT_ENUM', 103), + makeDebugVar('INSTANCE0._TMP_ADD3_OUT', 'INT_ENUM', 100), + makeDebugVar('INSTANCE0._TMP_MUL5_RES', 'REAL_O_ENUM', 101), + makeDebugVar('INSTANCE0._TMP_SUB1_X', 'DINT_P_ENUM', 102), + makeDebugVar('INSTANCE0._TMP_DIV2_Y', 'LINT_ENUM', 103), ] const projectData = { dataTypes: [] as PLCDataType[], pous: [pou] } @@ -378,8 +378,8 @@ describe('buildDebugVariableTreeMap', () => { const pou = makePou('Main', 'program', []) const instances = [makeInstance('INSTANCE0', 'Main')] const debugVars = [ - makeDebugVar('CONFIG0__GLOBAL_VAR', 'INT_ENUM', 200), - makeDebugVar('RES0__INSTANCE1._TMP_X', 'INT_ENUM', 201), + makeDebugVar('GLOBAL_VAR', 'INT_ENUM', 200), + makeDebugVar('INSTANCE1._TMP_X', 'INT_ENUM', 201), ] const projectData = { dataTypes: [] as PLCDataType[], pous: [pou] } @@ -391,7 +391,7 @@ describe('buildDebugVariableTreeMap', () => { it('skips debug vars that do not start with _TMP_ after the instance prefix', () => { const pou = makePou('Main', 'program', []) const instances = [makeInstance('INSTANCE0', 'Main')] - const debugVars = [makeDebugVar('RES0__INSTANCE0.REGULAR_VAR', 'INT_ENUM', 300)] + const debugVars = [makeDebugVar('INSTANCE0.REGULAR_VAR', 'INT_ENUM', 300)] const projectData = { dataTypes: [] as PLCDataType[], pous: [pou] } const { trees } = buildDebugVariableTreeMap([pou], instances, debugVars, projectData) @@ -403,7 +403,7 @@ describe('buildDebugVariableTreeMap', () => { it('handles _TMP_ variables with type that does not end in _ENUM', () => { const pou = makePou('Main', 'program', []) const instances = [makeInstance('INSTANCE0', 'Main')] - const debugVars = [makeDebugVar('RES0__INSTANCE0._TMP_FUNC1_OUT', 'CUSTOM_TYPE', 500)] + const debugVars = [makeDebugVar('INSTANCE0._TMP_FUNC1_OUT', 'CUSTOM_TYPE', 500)] const projectData = { dataTypes: [] as PLCDataType[], pous: [pou] } const { treeMap } = buildDebugVariableTreeMap([pou], instances, debugVars, projectData) diff --git a/src/frontend/utils/debug-tree-traversal.ts b/src/frontend/utils/debug-tree-traversal.ts index 325281cea..d55d5a99f 100644 --- a/src/frontend/utils/debug-tree-traversal.ts +++ b/src/frontend/utils/debug-tree-traversal.ts @@ -189,7 +189,8 @@ function traverseNestedNode( return visitor.visitComplex(name, fullPath, compositeKey, typeName, children) } else if (typeDefinition === 'user-data-type') { - // Structure type - fields use .value. prefix in debug path + // Structure type — STruC++ emits struct fields as `PARENT.FIELD` + // (same convention as FB fields), no `.value.` shim. const structVariables = findStructureVariables(typeName, dataTypes) if (!structVariables) { @@ -200,8 +201,7 @@ function traverseNestedNode( const children: T[] = [] for (const field of structVariables) { - // Structure fields use .value. prefix - const fieldFullPath = `${fullPath}.value.${field.name.toUpperCase()}` + const fieldFullPath = `${fullPath}.${field.name.toUpperCase()}` const fieldCompositeKey = `${compositeKey}.${field.name}` if (field.type.definition === 'base-type') { @@ -246,7 +246,8 @@ function traverseNestedNode( return visitor.visitComplex(name, fullPath, compositeKey, typeName, children) } else if (typeDefinition === 'array' && arrayData) { - // Array type - elements use .value.table[i] pattern + // Array type — STruC++ emits array elements as `PARENT[iec_idx]` using + // IEC-based indexing (the start of the declared range, not 0). const dimensions = arrayData.dimensions if (dimensions.length === 0) { return visitor.visitLeaf(name, fullPath, compositeKey, 'ARRAY', undefined) @@ -266,7 +267,7 @@ function traverseNestedNode( for (let i = 0; i < arraySize; i++) { const elementIndex = startIndex + i - const elementFullPath = `${fullPath}.value.table[${i}]` + const elementFullPath = `${fullPath}[${elementIndex}]` const elementCompositeKey = `${compositeKey}[${elementIndex}]` if (baseType.definition === 'base-type') { diff --git a/src/frontend/utils/debug-variable-finder.ts b/src/frontend/utils/debug-variable-finder.ts index f5f4d3eca..f7e56fc11 100644 --- a/src/frontend/utils/debug-variable-finder.ts +++ b/src/frontend/utils/debug-variable-finder.ts @@ -8,9 +8,10 @@ export { type DebugVariableEntry } from './debug-parser' import type { DebugVariableEntry } from './debug-parser' export interface PLCInstanceMapping { - /** Instance name (e.g., "INSTANCE0") - this appears in debug.c */ + /** Instance name (e.g., "INSTANCE0"). Appears at the root of every path + * emitted by STruC++ into debug-map.json. */ name: string - /** Program POU name being instantiated */ + /** Program POU name being instantiated. */ program: string } @@ -34,65 +35,50 @@ const isArrayIndex = (part: string): boolean => { } /** - * Build the debug path for a variable. + * Build the debug path for a variable, matching the convention STruC++ + * emits into debug-map.json: * - * Path formats in debug.c: - * - Global variable: CONFIG0__VAR_NAME - * - Simple program variable: RES0__INSTANCE0.VAR_NAME - * - FB instance variable: RES0__INSTANCE0.FB_INSTANCE.VAR_NAME (no .value.) - * - Nested FB variable: RES0__INSTANCE0.FB1.FB2.VAR_NAME (no .value.) - * - Structure field: RES0__INSTANCE0.STRUCT_VAR.value.FIELD_NAME - * - Array element: RES0__INSTANCE0.ARRAY_VAR.value.table[i] - * - Array of FBs field: RES0__INSTANCE0.FB_ARRAY.value.table[i].FIELD_NAME + * Simple program variable: INSTANCE0.VAR_NAME + * FB field: INSTANCE0.FB_INSTANCE.FIELD + * Nested FB field: INSTANCE0.FB1.FB2.VAR_NAME + * Struct field: INSTANCE0.STRUCT.FIELD + * Array element: INSTANCE0.ARR[5] + * Array of FBs field: INSTANCE0.FB_ARR[0].FIELD * - * @param instanceName - The instance name from Resources (e.g., "INSTANCE0") - * @param variablePath - The variable path (e.g., "MOTOR_SPEED" or "FB_INSTANCE.VAR" or "FB_ARRAY.[0].ET") - * @param isStructureField - True if accessing a field of a user-defined structure - * @param isArrayElement - True if accessing an array element - * @param arrayIndex - The array index (0-based) if isArrayElement is true + * Paths are uppercased end-to-end; callers must pass identifiers in whichever + * case they have them. + * + * @param instanceName - Instance name from Resources (e.g., "INSTANCE0") + * @param variablePath - Variable path (e.g., "BLINK", "FB.Q", "ARR.[0].ET") + * @param isArrayElement - True when resolving a specific array element + * @param arrayIndex - IEC-indexed array element (respecting the bounds' lower) */ export function buildDebugPath( instanceName: string, variablePath: string, options: { + /** Kept for compatibility with the old signature; STruC++'s path format + * doesn't distinguish struct vs. FB-field — both are `.FIELD`. */ isStructureField?: boolean isArrayElement?: boolean arrayIndex?: number } = {}, ): string { - const { isStructureField = false, isArrayElement = false, arrayIndex = 0 } = options + const { isArrayElement = false, arrayIndex = 0 } = options const pathParts = variablePath.split('.') - let debugPath = `RES0__${instanceName.toUpperCase()}` + let debugPath = instanceName.toUpperCase() if (isArrayElement && pathParts.length === 1) { - // Simple array: VAR_NAME -> RES0__INSTANCE.VAR_NAME.value.table[i] - debugPath += `.${pathParts[0].toUpperCase()}.value.table[${arrayIndex}]` - } else if (isStructureField) { - // Structure field: STRUCT.FIELD -> RES0__INSTANCE.STRUCT.value.FIELD - // First part is the struct variable name - debugPath += `.${pathParts[0].toUpperCase()}` - // Subsequent parts are fields, need .value. prefix (but handle array indices specially) - for (let i = 1; i < pathParts.length; i++) { - const part = pathParts[i] - if (isArrayIndex(part)) { - // Array index within structure: .value.table[i] - debugPath += `.value.table${part}` - } else { - debugPath += `.value.${part.toUpperCase()}` - } - } - } else { - // Simple variable or FB instance variable: no .value. insertion - // But handle array indices in the path: FB_ARRAY.[0].ET -> FB_ARRAY.value.table[0].ET - for (let i = 0; i < pathParts.length; i++) { - const part = pathParts[i] - if (isArrayIndex(part)) { - // Array index: insert .value.table before the index - debugPath += `.value.table${part}` - } else { - debugPath += `.${part.toUpperCase()}` - } + debugPath += `.${pathParts[0].toUpperCase()}[${arrayIndex}]` + return debugPath + } + + for (const part of pathParts) { + if (isArrayIndex(part)) { + debugPath += part + } else { + debugPath += `.${part.toUpperCase()}` } } @@ -100,10 +86,12 @@ export function buildDebugPath( } /** - * Build the debug path for a global variable. + * Build the debug path for a global variable. STruC++ does not currently + * emit globals into debug-map.json; this helper returns the unprefixed + * name so future support lines up naturally. */ export function buildGlobalDebugPath(variablePath: string): string { - return `CONFIG0__${variablePath.toUpperCase()}` + return variablePath.toUpperCase() } /** @@ -122,69 +110,32 @@ export function findDebugVariable( } /** - * Result from findDebugVariableWithFallback indicating which path style worked. + * Lookup result for variable-finding helpers. The `usedStructureStyle` field + * is kept for API compatibility (always false — STruC++ uses a single path + * convention for both struct and FB fields). */ export interface DebugVariableFallbackResult { - /** The matching debug variable, or null if not found */ match: DebugVariableEntry | null - /** The path that was used to find the match */ matchedPath: string - /** Whether the structure-style path (with .value.) was used */ usedStructureStyle: boolean } /** - * Find a debug variable using multiple path strategies. - * - * This is the CANONICAL function for resolving variable indices when the type - * definition is ambiguous (e.g., user-data-type could be FB or struct). - * - * The function tries paths in this order: - * 1. FB-style path (no .value. insertion) - for function block instances - * 2. Structure-style path (with .value. insertion) - for user-defined structures - * - * Both the debugger and OPC-UA systems MUST use this function to ensure - * consistent index resolution across the codebase. - * - * @param debugVariables - Parsed debug variables from debug.c - * @param instanceName - The instance name from Resources - * @param fieldPath - The variable path including any nested fields (e.g., "MY_FB.FIELD" or "MY_STRUCT.FIELD") - * @returns Result indicating the match and which path style was used + * Find a debug variable by instance + variable path. + * STruC++ uses a single path format (no .value./struct vs FB distinction), + * so there's no longer a need for multi-strategy fallback. */ export function findDebugVariableWithFallback( debugVariables: DebugVariableEntry[], instanceName: string, fieldPath: string, ): DebugVariableFallbackResult { - // First try FB-style path (no .value. insertion) - const fbPath = buildDebugPath(instanceName, fieldPath, { isStructureField: false }) - const fbMatch = findDebugVariable(debugVariables, fbPath) - if (fbMatch) { - return { match: fbMatch, matchedPath: fbPath, usedStructureStyle: false } - } - - // Try structure-style path (with .value. insertion) - const structPath = buildDebugPath(instanceName, fieldPath, { isStructureField: true }) - const structMatch = findDebugVariable(debugVariables, structPath) - if (structMatch) { - return { match: structMatch, matchedPath: structPath, usedStructureStyle: true } - } - - return { match: null, matchedPath: fbPath, usedStructureStyle: false } + const path = buildDebugPath(instanceName, fieldPath) + const match = findDebugVariable(debugVariables, path) + return { match, matchedPath: path, usedStructureStyle: false } } -/** - * Find the index for a variable using fallback path strategies. - * - * This is the CANONICAL function for index lookup when the type definition - * is ambiguous. Use this instead of findVariableIndex when you're not certain - * whether the variable is an FB instance or a structure. - * - * @param instanceName - The instance name from Resources - * @param fieldPath - The variable path - * @param debugVariables - Parsed debug variables - * @returns The index or null if not found - */ +/** Convenience: just the index, null when not found. */ export function findVariableIndexWithFallback( instanceName: string, fieldPath: string, @@ -194,90 +145,33 @@ export function findVariableIndexWithFallback( return result.match ? result.match.index : null } -/** - * Find a debug variable for a field using fallback path strategies. - * - * This is used during tree traversal when we have a base path and need to - * look up a child field. It tries both FB-style (no .value.) and struct-style - * (with .value.) paths. - * - * @param debugVariables - Parsed debug variables from debug.c - * @param basePath - The already-built base path (e.g., "RES0__INSTANCE0.MY_VAR") - * @param fieldName - The field name to append - * @returns Result with match and the path that worked - */ +/** Append a child field to a base path (used during tree traversal). */ export function findDebugVariableForField( debugVariables: DebugVariableEntry[], basePath: string, fieldName: string, ): DebugVariableFallbackResult { - // Try FB-style path (no .value. insertion) - const fbPath = `${basePath}.${fieldName.toUpperCase()}` - const fbMatch = findDebugVariable(debugVariables, fbPath) - if (fbMatch) { - return { match: fbMatch, matchedPath: fbPath, usedStructureStyle: false } - } - - // Try struct-style path (with .value. insertion) - const structPath = `${basePath}.value.${fieldName.toUpperCase()}` - const structMatch = findDebugVariable(debugVariables, structPath) - if (structMatch) { - return { match: structMatch, matchedPath: structPath, usedStructureStyle: true } - } - - return { match: null, matchedPath: fbPath, usedStructureStyle: false } + const path = `${basePath}.${fieldName.toUpperCase()}` + const match = findDebugVariable(debugVariables, path) + return { match, matchedPath: path, usedStructureStyle: false } } -/** - * Look up an index in a map using fallback path strategies. - * - * This is used when you have a pre-built index map (like debugVariableIndexes) - * and need to look up by path, trying both FB-style and struct-style paths. - * - * @param indexMap - A map from debug paths to indices - * @param instanceName - The instance name from Resources - * @param fieldPath - The variable path - * @returns The index or undefined if not found - */ +/** Map lookup by instance + variable path. */ export function getIndexFromMapWithFallback( indexMap: Map, instanceName: string, fieldPath: string, ): number | undefined { - // Try FB-style path (no .value. insertion) - const fbPath = buildDebugPath(instanceName, fieldPath, { isStructureField: false }) - const fbIndex = indexMap.get(fbPath) - if (fbIndex !== undefined) return fbIndex - - // Try struct-style path (with .value. insertion) - const structPath = buildDebugPath(instanceName, fieldPath, { isStructureField: true }) - return indexMap.get(structPath) + return indexMap.get(buildDebugPath(instanceName, fieldPath)) } -/** - * Look up an index in a map for a field, using fallback path strategies. - * - * This is used during polling when we have a base path and need to look up - * a child field, trying both FB-style and struct-style paths. - * - * @param indexMap - A map from debug paths to indices - * @param basePath - The already-built base path (e.g., "RES0__INSTANCE0.MY_VAR") - * @param fieldName - The field name to append - * @returns The index or undefined if not found - */ +/** Map lookup by base path + child field. */ export function getFieldIndexFromMapWithFallback( indexMap: Map, basePath: string, fieldName: string, ): number | undefined { - // Try FB-style path (no .value. insertion) - const fbPath = `${basePath}.${fieldName.toUpperCase()}` - const fbIndex = indexMap.get(fbPath) - if (fbIndex !== undefined) return fbIndex - - // Try struct-style path (with .value. insertion) - const structPath = `${basePath}.value.${fieldName.toUpperCase()}` - return indexMap.get(structPath) + return indexMap.get(`${basePath}.${fieldName.toUpperCase()}`) } /** @@ -319,13 +213,10 @@ export function findGlobalVariableIndex(variablePath: string, debugVariables: De /** * Build the base debug path prefix for an instance. - * Returns "RES0__INSTANCE_NAME" without any variable path. - * - * @param instanceName - The instance name from Resources (e.g., "INSTANCE0") - * @returns The base path prefix (e.g., "RES0__INSTANCE0") + * Returns the uppercased instance name — matches STruC++'s path convention. */ export function buildDebugPathPrefix(instanceName: string): string { - return `RES0__${instanceName.toUpperCase()}` + return instanceName.toUpperCase() } /** diff --git a/src/frontend/utils/opcua/debug-paths.ts b/src/frontend/utils/opcua/debug-paths.ts new file mode 100644 index 000000000..890ee6d2a --- /dev/null +++ b/src/frontend/utils/opcua/debug-paths.ts @@ -0,0 +1,100 @@ +/** + * MatIEC-format debug path helpers — OPC-UA module only. + * + * The OPC-UA integration still consumes the MatIEC-style `debug.c` format + * (flat debug_vars[] array with `RES0__` / `CONFIG0__` prefixes and + * `.value.` field shims). Keep these helpers local to the OPC-UA module so + * the shared debugger path (which moved to STruC++'s cleaner convention in + * debug-variable-finder) can evolve independently. + */ + +export type { DebugVariableEntry } from '../debug-parser' +import type { DebugVariableEntry } from '../debug-parser' + +export interface PLCInstanceMapping { + name: string + program: string +} + +const isArrayIndex = (part: string): boolean => /^\[\d+\]$/.test(part) + +export function findInstanceName( + pouName: string, + instances: Array<{ name: string; program: string }>, +): string | null { + const inst = instances.find((i) => i.program.toUpperCase() === pouName.toUpperCase()) + return inst ? inst.name : null +} + +export function buildDebugPath( + instanceName: string, + variablePath: string, + options: { + isStructureField?: boolean + isArrayElement?: boolean + arrayIndex?: number + } = {}, +): string { + const { isStructureField = false, isArrayElement = false, arrayIndex = 0 } = options + const pathParts = variablePath.split('.') + let debugPath = `RES0__${instanceName.toUpperCase()}` + + if (isArrayElement && pathParts.length === 1) { + debugPath += `.${pathParts[0].toUpperCase()}.value.table[${arrayIndex}]` + } else if (isStructureField) { + debugPath += `.${pathParts[0].toUpperCase()}` + for (let i = 1; i < pathParts.length; i++) { + const part = pathParts[i] + if (isArrayIndex(part)) { + debugPath += `.value.table${part}` + } else { + debugPath += `.value.${part.toUpperCase()}` + } + } + } else { + for (const part of pathParts) { + if (isArrayIndex(part)) { + debugPath += `.value.table${part}` + } else { + debugPath += `.${part.toUpperCase()}` + } + } + } + return debugPath +} + +export function buildGlobalDebugPath(variablePath: string): string { + return `CONFIG0__${variablePath.toUpperCase()}` +} + +export function findDebugVariable( + debugVariables: DebugVariableEntry[], + expectedPath: string, +): DebugVariableEntry | null { + const upperPath = expectedPath.toUpperCase() + return debugVariables.find((dv) => dv.name.toUpperCase() === upperPath) || null +} + +export interface DebugVariableFallbackResult { + match: DebugVariableEntry | null + matchedPath: string + usedStructureStyle: boolean +} + +export function findDebugVariableWithFallback( + debugVariables: DebugVariableEntry[], + instanceName: string, + fieldPath: string, +): DebugVariableFallbackResult { + const fbPath = buildDebugPath(instanceName, fieldPath, { isStructureField: false }) + const fbMatch = findDebugVariable(debugVariables, fbPath) + if (fbMatch) { + return { match: fbMatch, matchedPath: fbPath, usedStructureStyle: false } + } + const structPath = buildDebugPath(instanceName, fieldPath, { isStructureField: true }) + const structMatch = findDebugVariable(debugVariables, structPath) + if (structMatch) { + return { match: structMatch, matchedPath: structPath, usedStructureStyle: true } + } + return { match: null, matchedPath: fbPath, usedStructureStyle: false } +} diff --git a/src/frontend/utils/opcua/resolve-indices.ts b/src/frontend/utils/opcua/resolve-indices.ts index a2bd4ff9b..0286a41cb 100644 --- a/src/frontend/utils/opcua/resolve-indices.ts +++ b/src/frontend/utils/opcua/resolve-indices.ts @@ -6,7 +6,7 @@ import { findDebugVariableWithFallback, findInstanceName, type PLCInstanceMapping, -} from '@root/frontend/utils/debug-variable-finder' +} from './debug-paths' import type { OpcUaFieldConfig, OpcUaNodeConfig } from '@root/middleware/shared/ports/open-plc-types' import type { DebugVariable, PLCInstanceInfo, ResolvedField } from './types' From 32df640d93ad7e1957024fa1795402528603b210 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 08:51:07 -0400 Subject: [PATCH 045/296] feat(debug): bump strucpp to v0.3.3 for library FB debugger support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit strucpp v0.3.3 walks library ST sources so TON/TOF/CTU/etc internals surface in debug-map.json. Before this, instantiating TON0 : TON produced a tree node with no debugIndex on its children — Q, ET, STATE, PREV_IN all showed '-' in the watch panel and the ladder didn't color the block outputs. After this bump, the Chris Demo blink project emits 10+ leaves including INSTANCE0.TON0.Q / INSTANCE0.TOF0.Q, which the polling loop can now read and drive live updates into the UI. Co-Authored-By: Claude Opus 4.7 (1M context) --- binary-versions.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binary-versions.json b/binary-versions.json index 525965de7..489d332e7 100644 --- a/binary-versions.json +++ b/binary-versions.json @@ -4,7 +4,7 @@ "repository": "Autonomy-Logic/xml2st" }, "strucpp": { - "version": "v0.3.2", + "version": "v0.3.3", "repository": "Autonomy-Logic/STruCpp" } } From 2d10a1f372102809b52f04474baed437faaab95b Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 09:59:34 -0400 Subject: [PATCH 046/296] feat: generate VPP plugin config on runtime-v4 compilation Add handleGenerateVendorPluginConfig to the compiler pipeline so that VPP packages with a runtime-v4-plugin HAL get a plugin config file (conf/.json) included in the program.zip uploaded to the runtime. The generated config merges three sources: 1. The VPP package's config_template.json (fixed bus/hardware fields) 2. Vendor screen form data (e.g., hal-config settings) at root level 3. Module slot assignments + I/O mapping serialized as a slots array Without this config file, the runtime's plugin system kept the VPP plugin disabled even though the program itself uploaded successfully. The generator utility lives in backend/shared/utils/vpp/ so it can be unit-tested in isolation from the compiler module. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../editor/compiler/compiler-module.ts | 104 ++++++++++++++ .../vpp/generate-vendor-plugin-config.ts | 135 ++++++++++++++++++ 2 files changed, 239 insertions(+) create mode 100644 src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index c1ef72713..c8950c093 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -22,6 +22,7 @@ import { import { generateModbusMasterConfig } from '@root/backend/shared/utils/modbus/generate-modbus-master-config' import { XmlGenerator } from '@root/backend/shared/utils/PLC/xml-generator' import { parsePlcStatus } from '@root/backend/shared/utils/plc-status' +import { generateVendorPluginConfig } from '@root/backend/shared/utils/vpp/generate-vendor-plugin-config' import { getErrorMessage } from '@root/frontend/utils/get-error-message' import { generateModbusSlaveConfig } from '@root/frontend/utils/modbus/generate-modbus-slave-config' import { generateOpcUaConfig, OpcUaConfigError } from '@root/frontend/utils/opcua' @@ -30,6 +31,7 @@ import { app as electronApp, dialog } from 'electron' import type { MessagePortMain } from 'electron/main' import JSZip from 'jszip' +import type { PackageManifest } from '../package-manager' import { PackageManagerModule } from '../package-manager' import { CreateXMLFile } from '../utils' import type { ArduinoCoreControl, HalsFile } from './types' @@ -1391,6 +1393,98 @@ class CompilerModule { } } + /** + * Generate a VPP vendor plugin config for Runtime v4. + * + * When the selected board comes from an installed VPP package and defines + * a runtime-v4-plugin HAL with a config template, this handler: + * 1. Reads the VPP package's config_template.json + * 2. Reads the project's devices/configuration.json for vendor screen data + * 3. Merges form data and module/IO-mapping into a final plugin config + * 4. Writes it to conf/.json for the runtime to pick up + * + * For non-VPP boards or VPP boards without a config template, this is a no-op. + */ + async handleGenerateVendorPluginConfig( + boardTarget: string, + normalizedProjectPath: string, + sourceTargetFolderPath: string, + handleOutputData: HandleOutputDataCallback, + ): Promise { + try { + const packageManager = new PackageManagerModule() + const installed = packageManager.listInstalled() + + let matchingPackagePath: string | null = null + let matchingDevice: PackageManifest['devices'][number] | null = null + + for (const pkg of installed) { + const manifest = packageManager.getInstalledPackageManifest(pkg.packageId) + if (!manifest) continue + const device = manifest.devices.find((d) => d.name === boardTarget) + if (device) { + matchingPackagePath = pkg.path + matchingDevice = device + break + } + } + + if (!matchingDevice || !matchingPackagePath) { + // Not a VPP board — nothing to do + return + } + + if (matchingDevice.target.type !== 'runtime-v4') { + // VPP board but not runtime-v4 — no plugin config applies + return + } + + const configTemplateRelPath = matchingDevice.hal?.configTemplate + if (!configTemplateRelPath) { + handleOutputData('VPP board has no HAL configTemplate, skipping plugin config generation', 'info') + return + } + + // Read config template from the installed package + const configTemplatePath = join(matchingPackagePath, configTemplateRelPath) + let configTemplate: Record + try { + const templateRaw = await readFile(configTemplatePath, 'utf-8') + configTemplate = JSON.parse(templateRaw) as Record + } catch (err) { + handleOutputData( + `Failed to read VPP config template at ${configTemplateRelPath}: ${getErrorMessage(err)}`, + 'error', + ) + return + } + + // Read device configuration from the project for vendor screen data + const deviceConfigPath = join(normalizedProjectPath, 'devices', 'configuration.json') + let vendorScreenData: Record = {} + try { + const deviceConfigRaw = await readFile(deviceConfigPath, 'utf-8') + const deviceConfig = JSON.parse(deviceConfigRaw) as { vendorScreenData?: Record } + vendorScreenData = deviceConfig.vendorScreenData ?? {} + } catch { + // Device configuration may not exist yet — use empty vendor data + } + + const modules = matchingDevice.moduleSystem?.modules ?? [] + const finalConfig = generateVendorPluginConfig(configTemplate, vendorScreenData, modules) + + const pluginName = (configTemplate.plugin_name as string | undefined) ?? 'vendor_plugin' + const confFolderPath = join(sourceTargetFolderPath, 'conf') + await mkdir(confFolderPath, { recursive: true }) + const configFilePath = join(confFolderPath, `${pluginName}.json`) + await writeFile(configFilePath, JSON.stringify(finalConfig, null, 2), 'utf-8') + handleOutputData(`Generated conf/${pluginName}.json for VPP plugin`, 'info') + } catch (error) { + const errorMessage = getErrorMessage(error) + handleOutputData(`Failed to generate VPP plugin config: ${errorMessage}`, 'error') + } + } + /** * This will be the main entry point for the compiler module. * It will handle all the compilation process, will orchestrate the various steps involved in compiling a program. @@ -1784,6 +1878,16 @@ class CompilerModule { _mainProcessPort.postMessage({ logLevel, message: data }) }) + // Generate VPP vendor plugin config (if the board is a VPP package) + await this.handleGenerateVendorPluginConfig( + boardTarget, + normalizedProjectPath, + sourceTargetFolderPath, + (data, logLevel) => { + _mainProcessPort.postMessage({ logLevel, message: data }) + }, + ) + _mainProcessPort.postMessage({ logLevel: 'info', message: 'Compressing source files for OpenPLC Runtime v4...', diff --git a/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts b/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts new file mode 100644 index 000000000..7cadcd806 --- /dev/null +++ b/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts @@ -0,0 +1,135 @@ +/** + * Generates a runtime plugin config JSON for a VPP vendor package. + * + * The plugin config merges three sources: + * 1. The VPP package's `config_template.json` (fixed fields, defaults) + * 2. Vendor screen form data (e.g., "hal-config" settings) — merged at the root level + * 3. Module slot assignments + I/O mapping — serialized as the `slots` array + * + * The resulting JSON is what the runtime plugin reads at startup to configure + * bus settings and know which modules are installed in which slots. + */ + +type ModuleChannel = { + name: string + type: string + dataType: string + addressPrefix: string +} + +type VppModuleDefinition = { + id: string + name: string + addressMapping?: unknown +} + +type ModuleConfiguration = { + slots?: (string | null)[] +} + +type IoMappingEntry = { + slot: number + channelName: string + iecAddress: string + alias: string +} + +type IoMapping = { + entries?: IoMappingEntry[] +} + +type VendorScreenData = Record + +type PluginSlotChannel = { + name: string + type: string + dataType: string + iecLocation: string + alias: string +} + +type PluginSlot = { + slot: number + moduleId: string + moduleName: string + channels: PluginSlotChannel[] +} + +/** + * Build the `slots` array for the plugin config by cross-referencing: + * - Which module is in each slot (from vendor screen `module-configuration`) + * - The channel definitions of that module (from VPP manifest `addressMapping`) + * - The assigned IEC addresses and user aliases (from vendor screen `io-mapping`) + */ +function buildSlots(vendorScreenData: VendorScreenData, modules: VppModuleDefinition[]): PluginSlot[] { + const moduleConfig = (vendorScreenData['module-configuration'] as ModuleConfiguration | undefined) ?? {} + const ioMapping = (vendorScreenData['io-mapping'] as IoMapping | undefined) ?? {} + const slotAssignments = moduleConfig.slots ?? [] + const ioEntries = ioMapping.entries ?? [] + + const slots: PluginSlot[] = [] + + for (let slotIndex = 0; slotIndex < slotAssignments.length; slotIndex++) { + const moduleId = slotAssignments[slotIndex] + if (!moduleId) continue + + const moduleDef = modules.find((m) => m.id === moduleId) + if (!moduleDef) continue + + const slotNumber = slotIndex + 1 + const channels = (moduleDef.addressMapping as { channels?: ModuleChannel[] } | undefined)?.channels ?? [] + + const pluginChannels: PluginSlotChannel[] = channels.map((channel) => { + const ioEntry = ioEntries.find((e) => e.slot === slotNumber && e.channelName === channel.name) + return { + name: channel.name, + type: channel.type, + dataType: channel.dataType, + iecLocation: ioEntry?.iecAddress ?? '', + alias: ioEntry?.alias ?? '', + } + }) + + slots.push({ + slot: slotNumber, + moduleId, + moduleName: moduleDef.name, + channels: pluginChannels, + }) + } + + return slots +} + +/** + * Generate the final plugin config JSON for a VPP runtime-v4 package. + * + * All fields from the config template are preserved. Form-based vendor screen + * data (keyed by persistence keys other than 'module-configuration' and + * 'io-mapping') is merged at the root level. The `slots` array is always set + * from the backplane configuration + I/O mapping. + */ +export function generateVendorPluginConfig( + configTemplate: Record, + vendorScreenData: VendorScreenData, + modules: VppModuleDefinition[], +): Record { + const result: Record = { ...configTemplate } + + // Merge form-based vendor screen data at root. Skip the keys that have + // specific handling below. + const RESERVED_KEYS = new Set(['module-configuration', 'io-mapping']) + for (const [key, value] of Object.entries(vendorScreenData)) { + if (RESERVED_KEYS.has(key)) continue + if (value && typeof value === 'object' && !Array.isArray(value)) { + Object.assign(result, value as Record) + } + } + + // Always write the slots array from module configuration + IO mapping + result.slots = buildSlots(vendorScreenData, modules) + + return result +} + +export type { PluginSlot, PluginSlotChannel, VendorScreenData, VppModuleDefinition } From a6a97b54da3541b68f499d5b2281c3137c4c5844 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 10:26:29 -0400 Subject: [PATCH 047/296] feat: upload VPP plugin source with checksum for on-target build MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Extend VPP runtime-v4 handling to package the plugin source code into the uploaded program.zip so the runtime can compile libsynergy_plugin.so on the target. Previously only the plugin config was generated; the runtime expected a vpp_plugin/ directory with source + Makefile that the editor was not supplying. The new handleVendorPluginPackaging: 1. Generates conf/.json from config_template + vendor screens 2. Copies the plugin source directory (parent of hal.pluginEntry) to vpp_plugin/ in the source folder, excluding editor-only files (config_template.json, requirements.txt) 3. Writes a SHA-256 checksum over the copied source to vpp_plugin/checksum.sha256 The runtime's compile.sh uses the checksum file to skip recompilation when the plugin source is unchanged, so the editor does not need to query the runtime for the current plugin MD5 — the cache lives on the runtime side. Always logs a header line so the compilation output shows whether VPP packaging ran or was skipped (useful when board is not a VPP package). Co-Authored-By: Claude Opus 4.7 (1M context) --- .../editor/compiler/compiler-module.ts | 168 ++++++++++++++---- 1 file changed, 131 insertions(+), 37 deletions(-) diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index c8950c093..8a5029e9c 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -1,6 +1,7 @@ import { exec, spawn } from 'node:child_process' +import { createHash } from 'node:crypto' import { promises as fs } from 'node:fs' -import { cp, mkdir, readFile, writeFile } from 'node:fs/promises' +import { cp, mkdir, readdir, readFile, stat, writeFile } from 'node:fs/promises' import type { IncomingMessage } from 'node:http' import https from 'node:https' import os from 'node:os' @@ -1394,18 +1395,22 @@ class CompilerModule { } /** - * Generate a VPP vendor plugin config for Runtime v4. + * Handle VPP runtime-v4 package integration for the uploaded program. * - * When the selected board comes from an installed VPP package and defines - * a runtime-v4-plugin HAL with a config template, this handler: - * 1. Reads the VPP package's config_template.json - * 2. Reads the project's devices/configuration.json for vendor screen data - * 3. Merges form data and module/IO-mapping into a final plugin config - * 4. Writes it to conf/.json for the runtime to pick up + * When the selected board is from an installed VPP package, this handler: + * 1. Generates conf/.json from the package's config_template.json + * merged with vendor screen data (hal-config, module-configuration, io-mapping) + * 2. Copies the plugin source directory (containing the Makefile and .c/.h files) + * into the source folder under vpp_plugin/ + * 3. Computes a SHA-256 checksum over all plugin source files and writes it to + * vpp_plugin/checksum.sha256 so the runtime's compile.sh can skip + * recompilation when the source hasn't changed. * - * For non-VPP boards or VPP boards without a config template, this is a no-op. + * For non-VPP boards or VPP boards without the necessary HAL metadata, the + * relevant sub-steps are skipped. A header log is always emitted so the + * user can see whether VPP handling kicked in at all. */ - async handleGenerateVendorPluginConfig( + async handleVendorPluginPackaging( boardTarget: string, normalizedProjectPath: string, sourceTargetFolderPath: string, @@ -1430,58 +1435,147 @@ class CompilerModule { } if (!matchingDevice || !matchingPackagePath) { - // Not a VPP board — nothing to do + handleOutputData(`Board "${boardTarget}" is not from a VPP package, skipping VPP packaging`, 'info') return } if (matchingDevice.target.type !== 'runtime-v4') { - // VPP board but not runtime-v4 — no plugin config applies + handleOutputData( + `VPP board "${boardTarget}" is not runtime-v4 (target=${matchingDevice.target.type}), skipping VPP packaging`, + 'info', + ) return } + handleOutputData(`Detected VPP runtime-v4 board: ${boardTarget}`, 'info') + + // --- Step 1: Generate plugin config file --- const configTemplateRelPath = matchingDevice.hal?.configTemplate - if (!configTemplateRelPath) { + let pluginName = 'vendor_plugin' + + if (configTemplateRelPath) { + const configTemplatePath = join(matchingPackagePath, configTemplateRelPath) + let configTemplate: Record | null = null + try { + const templateRaw = await readFile(configTemplatePath, 'utf-8') + configTemplate = JSON.parse(templateRaw) as Record + } catch (err) { + handleOutputData( + `Failed to read VPP config template at ${configTemplateRelPath}: ${getErrorMessage(err)}`, + 'error', + ) + } + + if (configTemplate) { + // Read vendor screen data from the project's device configuration + const deviceConfigPath = join(normalizedProjectPath, 'devices', 'configuration.json') + let vendorScreenData: Record = {} + try { + const deviceConfigRaw = await readFile(deviceConfigPath, 'utf-8') + const deviceConfig = JSON.parse(deviceConfigRaw) as { vendorScreenData?: Record } + vendorScreenData = deviceConfig.vendorScreenData ?? {} + } catch { + // Device configuration may not exist yet — use empty vendor data + } + + const modules = matchingDevice.moduleSystem?.modules ?? [] + const finalConfig = generateVendorPluginConfig(configTemplate, vendorScreenData, modules) + + pluginName = (configTemplate.plugin_name as string | undefined) ?? 'vendor_plugin' + const confFolderPath = join(sourceTargetFolderPath, 'conf') + await mkdir(confFolderPath, { recursive: true }) + const configFilePath = join(confFolderPath, `${pluginName}.json`) + await writeFile(configFilePath, JSON.stringify(finalConfig, null, 2), 'utf-8') + handleOutputData(`Generated conf/${pluginName}.json for VPP plugin`, 'info') + } + } else { handleOutputData('VPP board has no HAL configTemplate, skipping plugin config generation', 'info') + } + + // --- Step 2: Copy plugin source + generate checksum --- + const pluginEntryRelPath = matchingDevice.hal?.pluginEntry + if (!pluginEntryRelPath) { + handleOutputData('VPP board has no HAL pluginEntry, skipping plugin source upload', 'info') return } - // Read config template from the installed package - const configTemplatePath = join(matchingPackagePath, configTemplateRelPath) - let configTemplate: Record + // The plugin source directory is the parent directory of pluginEntry + const pluginSourceDir = join(matchingPackagePath, path.dirname(pluginEntryRelPath)) + let pluginSourceStat try { - const templateRaw = await readFile(configTemplatePath, 'utf-8') - configTemplate = JSON.parse(templateRaw) as Record + pluginSourceStat = await stat(pluginSourceDir) } catch (err) { handleOutputData( - `Failed to read VPP config template at ${configTemplateRelPath}: ${getErrorMessage(err)}`, + `VPP plugin source directory not found at ${pluginEntryRelPath}: ${getErrorMessage(err)}`, 'error', ) return } - // Read device configuration from the project for vendor screen data - const deviceConfigPath = join(normalizedProjectPath, 'devices', 'configuration.json') - let vendorScreenData: Record = {} + if (!pluginSourceStat.isDirectory()) { + handleOutputData(`VPP plugin source path is not a directory: ${pluginEntryRelPath}`, 'error') + return + } + + const destPluginDir = join(sourceTargetFolderPath, 'vpp_plugin') + // Clean up any previous vpp_plugin directory from a prior build try { - const deviceConfigRaw = await readFile(deviceConfigPath, 'utf-8') - const deviceConfig = JSON.parse(deviceConfigRaw) as { vendorScreenData?: Record } - vendorScreenData = deviceConfig.vendorScreenData ?? {} + await fs.rm(destPluginDir, { recursive: true, force: true }) } catch { - // Device configuration may not exist yet — use empty vendor data + // Ignore — may not exist yet } - const modules = matchingDevice.moduleSystem?.modules ?? [] - const finalConfig = generateVendorPluginConfig(configTemplate, vendorScreenData, modules) + // Copy the plugin source, excluding files that are only useful in the editor + // (config_template.json is already turned into conf/.json, and + // requirements.txt is for Python-style plugins that don't apply here). + const EXCLUDE_FILES = new Set(['config_template.json', 'requirements.txt']) + const copiedFiles: string[] = [] + const collectAndCopy = async (sourceDir: string, destDir: string, relPath: string = ''): Promise => { + const entries = await readdir(sourceDir, { withFileTypes: true }) + for (const entry of entries) { + if (EXCLUDE_FILES.has(entry.name)) continue + const sourcePath = join(sourceDir, entry.name) + const destPath = join(destDir, entry.name) + const relFilePath = relPath ? `${relPath}/${entry.name}` : entry.name + if (entry.isDirectory()) { + await mkdir(destPath, { recursive: true }) + await collectAndCopy(sourcePath, destPath, relFilePath) + } else if (entry.isFile()) { + await mkdir(destDir, { recursive: true }) + const content = await readFile(sourcePath) + await writeFile(destPath, content as unknown as Uint8Array) + copiedFiles.push(relFilePath) + } + } + } - const pluginName = (configTemplate.plugin_name as string | undefined) ?? 'vendor_plugin' - const confFolderPath = join(sourceTargetFolderPath, 'conf') - await mkdir(confFolderPath, { recursive: true }) - const configFilePath = join(confFolderPath, `${pluginName}.json`) - await writeFile(configFilePath, JSON.stringify(finalConfig, null, 2), 'utf-8') - handleOutputData(`Generated conf/${pluginName}.json for VPP plugin`, 'info') + await mkdir(destPluginDir, { recursive: true }) + await collectAndCopy(pluginSourceDir, destPluginDir) + + if (copiedFiles.length === 0) { + handleOutputData('VPP plugin source directory contained no files to copy', 'info') + return + } + + // Compute SHA-256 over all copied files (sorted for determinism) + // Format: " \n" per file, then a final SHA-256 of that list + copiedFiles.sort() + const hash = createHash('sha256') + for (const relFile of copiedFiles) { + const fileContent = await readFile(join(destPluginDir, relFile)) + const fileHash = createHash('sha256').update(fileContent as unknown as Uint8Array).digest('hex') + hash.update(`${fileHash} ${relFile}\n`) + } + const combinedHash = hash.digest('hex') + await writeFile(join(destPluginDir, 'checksum.sha256'), combinedHash + '\n', 'utf-8') + + handleOutputData( + `Copied ${copiedFiles.length} VPP plugin source file(s) to vpp_plugin/ (checksum: ${combinedHash.slice(0, 12)}…)`, + 'info', + ) } catch (error) { const errorMessage = getErrorMessage(error) - handleOutputData(`Failed to generate VPP plugin config: ${errorMessage}`, 'error') + handleOutputData(`Failed VPP plugin packaging: ${errorMessage}`, 'error') } } @@ -1878,8 +1972,8 @@ class CompilerModule { _mainProcessPort.postMessage({ logLevel, message: data }) }) - // Generate VPP vendor plugin config (if the board is a VPP package) - await this.handleGenerateVendorPluginConfig( + // Generate VPP plugin config + copy plugin source (if board is a VPP package) + await this.handleVendorPluginPackaging( boardTarget, normalizedProjectPath, sourceTargetFolderPath, From d02b7841bb1458f3c3a6021c8f973f10a7f8fa50 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 10:44:35 -0400 Subject: [PATCH 048/296] fix: persist vendorScreenData and emit plugin-compatible slot format Two related VPP issues: 1. vendorScreenData was missing from deviceConfigurationSchema, so the Zod safeParse on project load stripped the field. Modules configured in the backplane screen were written to disk correctly but silently dropped when reopening the project. Add vendorScreenData as an optional record on the schema so it survives validation. 2. The generated conf/.json slots were in a generic {moduleId, moduleName, channels:[...]} shape that runtime plugins (like synergy) cannot parse. Rewrite the generator to emit the convention expected by runtime plugins: - module_hw_id (hex string) from manifest module.hwId - io_mapping.digital_inputs/outputs with base_byte, base_bit, count - io_mapping.analog_inputs/outputs with base_word, count The richer channels array is preserved for debugging. base_byte/bit/count is derived from the channel IEC addresses assigned by the I/O Mapping editor, sorted by linear bit index. Add optional hwId field to PackageManifest types. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/backend/editor/package-manager/types.ts | 1 + .../shared/types/PLC/devices/configuration.ts | 1 + .../vpp/generate-vendor-plugin-config.ts | 141 +++++++++++++++++- 3 files changed, 136 insertions(+), 7 deletions(-) diff --git a/src/backend/editor/package-manager/types.ts b/src/backend/editor/package-manager/types.ts index ccfb28473..9f2e445d5 100644 --- a/src/backend/editor/package-manager/types.ts +++ b/src/backend/editor/package-manager/types.ts @@ -62,6 +62,7 @@ type PackageManifest = { modules: Array<{ id: string name: string + hwId?: string image?: string io: { digitalInputs: number diff --git a/src/backend/shared/types/PLC/devices/configuration.ts b/src/backend/shared/types/PLC/devices/configuration.ts index f237a1b75..366a47cef 100644 --- a/src/backend/shared/types/PLC/devices/configuration.ts +++ b/src/backend/shared/types/PLC/devices/configuration.ts @@ -59,6 +59,7 @@ const deviceConfigurationSchema = z.object({ .default({}), }) .default({}), + vendorScreenData: z.record(z.string(), z.unknown()).optional(), }) type DeviceConfiguration = z.infer diff --git a/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts b/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts index 7cadcd806..2f95edfc0 100644 --- a/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts +++ b/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts @@ -8,6 +8,21 @@ * * The resulting JSON is what the runtime plugin reads at startup to configure * bus settings and know which modules are installed in which slots. + * + * Slot format conforms to the convention used by runtime plugins (e.g., synergy): + * { + * "slot": 1, + * "module_hw_id": "0x24A500E1", // from VPP manifest module.hwId + * "module_id": "slm-acdci-8np-rly8", // canonical id from manifest, for debugging + * "module_name": "SLM-ACDCI-8NP-RLY8", + * "io_mapping": { + * "digital_inputs": { "base_byte": 0, "base_bit": 0, "count": 8 }, + * "digital_outputs": { "base_byte": 0, "base_bit": 1, "count": 8 }, + * "analog_inputs": { "base_word": 0, "count": 4 }, + * "analog_outputs": { "base_word": 0, "count": 2 } + * }, + * "channels": [ /* per-channel iecLocation + alias, for debugging/reference * / ] + * } */ type ModuleChannel = { @@ -20,6 +35,7 @@ type ModuleChannel = { type VppModuleDefinition = { id: string name: string + hwId?: string addressMapping?: unknown } @@ -48,18 +64,101 @@ type PluginSlotChannel = { alias: string } +type BitRangeMapping = { + base_byte: number + base_bit: number + count: number +} + +type WordRangeMapping = { + base_word: number + count: number +} + +type PluginSlotIoMapping = { + digital_inputs?: BitRangeMapping + digital_outputs?: BitRangeMapping + analog_inputs?: WordRangeMapping + analog_outputs?: WordRangeMapping +} + type PluginSlot = { slot: number - moduleId: string - moduleName: string + module_hw_id?: string + module_id: string + module_name: string + io_mapping: PluginSlotIoMapping channels: PluginSlotChannel[] } +const BIT_ADDRESS_REGEX = /^%[IQ]X(\d+)\.(\d+)$/ +const WORD_ADDRESS_REGEX = /^%[IQ]W(\d+)$/ + +/** Parse a bit IEC address (%IX5.3 / %QX1.7) into a byte+bit pair. */ +function parseBitAddress(addr: string): { byte: number; bit: number } | null { + const m = BIT_ADDRESS_REGEX.exec(addr) + if (!m) return null + return { byte: Number(m[1]), bit: Number(m[2]) } +} + +/** Parse a word IEC address (%IW12 / %QW5) into a word index. */ +function parseWordAddress(addr: string): number | null { + const m = WORD_ADDRESS_REGEX.exec(addr) + if (!m) return null + return Number(m[1]) +} + +/** + * Convert (byte, bit) to a linear bit index so that wrap-across-byte + * channel ranges can still be expressed as base + count. + * %IX0.0 → 0, %IX0.7 → 7, %IX1.0 → 8, %IX1.7 → 15, etc. + */ +function bitAddressToLinear(byte: number, bit: number): number { + return byte * 8 + bit +} + +/** + * Given a list of channels of the same type and their assigned IEC addresses, + * compute a contiguous base_byte / base_bit / count mapping. Addresses are + * assumed to be linearly contiguous (editor allocator allocates a block for + * each module's channel type), but we tolerate a non-contiguous layout by + * falling back to count=channels.length even if there are gaps — the plugin + * would still see the correct count. + */ +function buildBitRange(channels: { name: string; address: string }[]): BitRangeMapping | null { + if (channels.length === 0) return null + const parsed: { byte: number; bit: number; linear: number }[] = [] + for (const ch of channels) { + const p = parseBitAddress(ch.address) + if (!p) return null + parsed.push({ ...p, linear: bitAddressToLinear(p.byte, p.bit) }) + } + parsed.sort((a, b) => a.linear - b.linear) + return { + base_byte: parsed[0].byte, + base_bit: parsed[0].bit, + count: parsed.length, + } +} + +function buildWordRange(channels: { name: string; address: string }[]): WordRangeMapping | null { + if (channels.length === 0) return null + const parsed: number[] = [] + for (const ch of channels) { + const w = parseWordAddress(ch.address) + if (w === null) return null + parsed.push(w) + } + parsed.sort((a, b) => a - b) + return { base_word: parsed[0], count: parsed.length } +} + /** * Build the `slots` array for the plugin config by cross-referencing: * - Which module is in each slot (from vendor screen `module-configuration`) * - The channel definitions of that module (from VPP manifest `addressMapping`) * - The assigned IEC addresses and user aliases (from vendor screen `io-mapping`) + * - The manifest module's hwId for the plugin's module database lookup */ function buildSlots(vendorScreenData: VendorScreenData, modules: VppModuleDefinition[]): PluginSlot[] { const moduleConfig = (vendorScreenData['module-configuration'] as ModuleConfiguration | undefined) ?? {} @@ -79,6 +178,7 @@ function buildSlots(vendorScreenData: VendorScreenData, modules: VppModuleDefini const slotNumber = slotIndex + 1 const channels = (moduleDef.addressMapping as { channels?: ModuleChannel[] } | undefined)?.channels ?? [] + // Build debug channel list const pluginChannels: PluginSlotChannel[] = channels.map((channel) => { const ioEntry = ioEntries.find((e) => e.slot === slotNumber && e.channelName === channel.name) return { @@ -90,12 +190,39 @@ function buildSlots(vendorScreenData: VendorScreenData, modules: VppModuleDefini } }) - slots.push({ + // Group channels by type for the io_mapping block + const di: { name: string; address: string }[] = [] + const dout: { name: string; address: string }[] = [] + const ai: { name: string; address: string }[] = [] + const ao: { name: string; address: string }[] = [] + + for (const ch of pluginChannels) { + if (!ch.iecLocation) continue + if (ch.type === 'digitalInput') di.push({ name: ch.name, address: ch.iecLocation }) + else if (ch.type === 'digitalOutput') dout.push({ name: ch.name, address: ch.iecLocation }) + else if (ch.type === 'analogInput') ai.push({ name: ch.name, address: ch.iecLocation }) + else if (ch.type === 'analogOutput') ao.push({ name: ch.name, address: ch.iecLocation }) + } + + const ioMappingBlock: PluginSlotIoMapping = {} + const diRange = buildBitRange(di) + const doRange = buildBitRange(dout) + const aiRange = buildWordRange(ai) + const aoRange = buildWordRange(ao) + if (diRange) ioMappingBlock.digital_inputs = diRange + if (doRange) ioMappingBlock.digital_outputs = doRange + if (aiRange) ioMappingBlock.analog_inputs = aiRange + if (aoRange) ioMappingBlock.analog_outputs = aoRange + + const slot: PluginSlot = { slot: slotNumber, - moduleId, - moduleName: moduleDef.name, + module_id: moduleId, + module_name: moduleDef.name, + io_mapping: ioMappingBlock, channels: pluginChannels, - }) + } + if (moduleDef.hwId) slot.module_hw_id = moduleDef.hwId + slots.push(slot) } return slots @@ -132,4 +259,4 @@ export function generateVendorPluginConfig( return result } -export type { PluginSlot, PluginSlotChannel, VendorScreenData, VppModuleDefinition } +export type { PluginSlot, PluginSlotChannel, PluginSlotIoMapping, VendorScreenData, VppModuleDefinition } From e27e9d4f9dd71d0306baec344c33bc4e550e77ce Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 15:42:08 -0400 Subject: [PATCH 049/296] refactor: remove unused fields from VPP plugin config slots The synergy plugin parser only reads slot, module_hw_id, and io_mapping. The moduleId, moduleName, and channels fields we previously emitted were ignored. Drop them from the generated output to keep the file small and focused on what the plugin actually consumes. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../vpp/generate-vendor-plugin-config.ts | 51 +++++-------------- 1 file changed, 12 insertions(+), 39 deletions(-) diff --git a/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts b/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts index 2f95edfc0..9ba544e4c 100644 --- a/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts +++ b/src/backend/shared/utils/vpp/generate-vendor-plugin-config.ts @@ -12,16 +12,13 @@ * Slot format conforms to the convention used by runtime plugins (e.g., synergy): * { * "slot": 1, - * "module_hw_id": "0x24A500E1", // from VPP manifest module.hwId - * "module_id": "slm-acdci-8np-rly8", // canonical id from manifest, for debugging - * "module_name": "SLM-ACDCI-8NP-RLY8", + * "module_hw_id": "0x24A500E1", // from VPP manifest module.hwId * "io_mapping": { * "digital_inputs": { "base_byte": 0, "base_bit": 0, "count": 8 }, * "digital_outputs": { "base_byte": 0, "base_bit": 1, "count": 8 }, * "analog_inputs": { "base_word": 0, "count": 4 }, * "analog_outputs": { "base_word": 0, "count": 2 } - * }, - * "channels": [ /* per-channel iecLocation + alias, for debugging/reference * / ] + * } * } */ @@ -56,14 +53,6 @@ type IoMapping = { type VendorScreenData = Record -type PluginSlotChannel = { - name: string - type: string - dataType: string - iecLocation: string - alias: string -} - type BitRangeMapping = { base_byte: number base_bit: number @@ -85,10 +74,7 @@ type PluginSlotIoMapping = { type PluginSlot = { slot: number module_hw_id?: string - module_id: string - module_name: string io_mapping: PluginSlotIoMapping - channels: PluginSlotChannel[] } const BIT_ADDRESS_REGEX = /^%[IQ]X(\d+)\.(\d+)$/ @@ -178,30 +164,20 @@ function buildSlots(vendorScreenData: VendorScreenData, modules: VppModuleDefini const slotNumber = slotIndex + 1 const channels = (moduleDef.addressMapping as { channels?: ModuleChannel[] } | undefined)?.channels ?? [] - // Build debug channel list - const pluginChannels: PluginSlotChannel[] = channels.map((channel) => { - const ioEntry = ioEntries.find((e) => e.slot === slotNumber && e.channelName === channel.name) - return { - name: channel.name, - type: channel.type, - dataType: channel.dataType, - iecLocation: ioEntry?.iecAddress ?? '', - alias: ioEntry?.alias ?? '', - } - }) - - // Group channels by type for the io_mapping block + // Group channels by type and resolve each channel's assigned IEC address const di: { name: string; address: string }[] = [] const dout: { name: string; address: string }[] = [] const ai: { name: string; address: string }[] = [] const ao: { name: string; address: string }[] = [] - for (const ch of pluginChannels) { - if (!ch.iecLocation) continue - if (ch.type === 'digitalInput') di.push({ name: ch.name, address: ch.iecLocation }) - else if (ch.type === 'digitalOutput') dout.push({ name: ch.name, address: ch.iecLocation }) - else if (ch.type === 'analogInput') ai.push({ name: ch.name, address: ch.iecLocation }) - else if (ch.type === 'analogOutput') ao.push({ name: ch.name, address: ch.iecLocation }) + for (const channel of channels) { + const ioEntry = ioEntries.find((e) => e.slot === slotNumber && e.channelName === channel.name) + const address = ioEntry?.iecAddress + if (!address) continue + if (channel.type === 'digitalInput') di.push({ name: channel.name, address }) + else if (channel.type === 'digitalOutput') dout.push({ name: channel.name, address }) + else if (channel.type === 'analogInput') ai.push({ name: channel.name, address }) + else if (channel.type === 'analogOutput') ao.push({ name: channel.name, address }) } const ioMappingBlock: PluginSlotIoMapping = {} @@ -216,10 +192,7 @@ function buildSlots(vendorScreenData: VendorScreenData, modules: VppModuleDefini const slot: PluginSlot = { slot: slotNumber, - module_id: moduleId, - module_name: moduleDef.name, io_mapping: ioMappingBlock, - channels: pluginChannels, } if (moduleDef.hwId) slot.module_hw_id = moduleDef.hwId slots.push(slot) @@ -259,4 +232,4 @@ export function generateVendorPluginConfig( return result } -export type { PluginSlot, PluginSlotChannel, PluginSlotIoMapping, VendorScreenData, VppModuleDefinition } +export type { PluginSlot, PluginSlotIoMapping, VendorScreenData, VppModuleDefinition } From 93f5fafc98ca2ee56738771b0d6183f9a73a3062 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 15:57:49 -0400 Subject: [PATCH 050/296] fix: exclude pin mapping from VPP I/O address allocation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Pin mapping is Arduino-target-only and its addresses do not share the Runtime v4 image table used by remote devices and VPP vendor plugins. Including pin-mapping addresses in the conflict set caused spurious collisions when a project had both an Arduino pin map (e.g. %QX0.0) and a VPP board (e.g. SLM-RP4) — the VPP I/O Mapping would skip %QX0.0 even though that address is free for the runtime plugin. Drop the pinMapping parameter from collectUsedIecAddresses. The VPP IoTableLayout now only conflicts with remote-device IO points and other VPP vendor mappings, which is the set of sources that actually shares address space on Runtime v4 targets. Co-Authored-By: Claude Opus 4.7 (1M context) --- .../vendor-screen/layouts/io-table-layout.tsx | 5 ++-- src/frontend/utils/iec-address.ts | 23 ++++++++++--------- 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/io-table-layout.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/io-table-layout.tsx index d46d67945..ab32eae94 100644 --- a/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/io-table-layout.tsx +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/vendor-screen/layouts/io-table-layout.tsx @@ -22,7 +22,6 @@ function IoTableLayout({ section, moduleSystem }: IoTableLayoutProps) { return { slots: moduleConfig?.slots ?? [], storedMapping, - pinMapping: state.deviceDefinitions.pinMapping.pins, remoteDevices: (state.project.data.remoteDevices ?? []) as Array<{ modbusTcpConfig?: { ioGroups?: Array<{ ioPoints: Array<{ iecLocation: string }> }> } }>, @@ -51,7 +50,7 @@ function IoTableLayout({ section, moduleSystem }: IoTableLayoutProps) { if (slotsKey === lastSlotsRef.current) return lastSlotsRef.current = slotsKey - const { pinMapping, remoteDevices, storedMapping } = getStoreState() + const { remoteDevices, storedMapping } = getStoreState() const existingAliases = new Map() const existingEntries = storedMapping?.entries ?? entries @@ -61,7 +60,7 @@ function IoTableLayout({ section, moduleSystem }: IoTableLayoutProps) { } } - const usedAddresses = collectUsedIecAddresses(pinMapping, remoteDevices) + const usedAddresses = collectUsedIecAddresses(remoteDevices) const newEntries: IoMappingEntry[] = [] for (let slotIndex = 0; slotIndex < slots.length; slotIndex++) { diff --git a/src/frontend/utils/iec-address.ts b/src/frontend/utils/iec-address.ts index 7fac0af31..2509b9b2e 100644 --- a/src/frontend/utils/iec-address.ts +++ b/src/frontend/utils/iec-address.ts @@ -1,30 +1,31 @@ /** * IEC 61131-3 address utilities for global address allocation. * - * Manages IEC address allocation across all IO sources: local pin mapping, - * remote devices (Modbus TCP IO groups), and vendor module IO mappings. - * This prevents address collisions when multiple IO sources coexist. + * Manages IEC address allocation across IO sources that share the runtime's + * image table: remote devices (Modbus TCP IO groups) and VPP vendor module + * IO mappings. These live on Runtime v4 targets and must not collide. + * + * Local pin mapping is deliberately NOT included here — pin mapping is an + * Arduino-target-only concern and its addresses don't reach the same image + * table that runtime plugins / remote devices write to, so sharing the + * namespace with them would produce false conflicts when the user switches + * targets. * * Pure frontend utility — no backend or platform dependencies. */ -import type { DevicePin, VendorIoMapping } from '../../middleware/shared/ports/types' +import type { VendorIoMapping } from '../../middleware/shared/ports/types' /** - * Collects all used IEC addresses across the entire project: - * local pin mapping, remote devices, and vendor module IO mappings. + * Collects all used IEC addresses from sources that share the Runtime v4 + * image table: remote devices and vendor module IO mappings. */ export function collectUsedIecAddresses( - pinMapping: DevicePin[], remoteDevices: Array<{ modbusTcpConfig?: { ioGroups?: Array<{ ioPoints: Array<{ iecLocation: string }> }> } }>, vendorIoMapping?: VendorIoMapping, ): Set { const used = new Set() - for (const pin of pinMapping) { - if (pin.address) used.add(pin.address) - } - for (const device of remoteDevices) { if (device.modbusTcpConfig?.ioGroups) { for (const group of device.modbusTcpConfig.ioGroups) { From 64ba9392dabe93e3a07cf18e2843e792ca50ce66 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 17:08:38 -0400 Subject: [PATCH 051/296] fix: treat VPP runtime-v4 boards as v4 for debugger and feature checks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit isOpenPLCRuntimeV4Target used only a string match on the board name (e.g., "OpenPLC Runtime v4"), so VPP boards like "SLM-RP4" fell into the else branch and got the Modbus TCP port 502 debugger path — which fails for Runtime v4 devices that serve debug traffic via WebSocket on 8443. Extend the function to accept an optional BoardLike and return true when the board has VPP metadata and uses the openplc-compiler path. mergeVppBoards only sets compiler='openplc-compiler' for VPP devices whose manifest declared target.type='runtime-v4', so this check is both sufficient and unambiguous. Update all three callers to pass the board info they already have: workspace-activity-bar (debugger), create-element (v4 feature gating), and board.tsx (target switch warnings). Also fix the backend compiler's isRuntimeV4 check to consider VPP runtime-v4 boards — otherwise SLM-RP4 projects with Modbus servers/remote devices would get spurious "not supported" warnings. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/backend/editor/compiler/compiler-module.ts | 13 ++++++++++++- .../create-element/element-card/index.tsx | 2 +- .../editor/device/configuration/board.tsx | 2 +- .../_organisms/workspace-activity-bar/default.tsx | 2 +- src/frontend/utils/__tests__/device.test.ts | 10 ++++++++++ src/frontend/utils/device.ts | 14 ++++++++++++-- 6 files changed, 37 insertions(+), 6 deletions(-) diff --git a/src/backend/editor/compiler/compiler-module.ts b/src/backend/editor/compiler/compiler-module.ts index 8a5029e9c..cfee3a837 100644 --- a/src/backend/editor/compiler/compiler-module.ts +++ b/src/backend/editor/compiler/compiler-module.ts @@ -1639,7 +1639,18 @@ class CompilerModule { }) // --- Check for unsupported features on non-v4 targets --- - const isRuntimeV4 = boardTarget === 'OpenPLC Runtime v4' + // A VPP board whose manifest target.type is 'runtime-v4' is also a v4 target. + const isVppRuntimeV4 = (() => { + const packageManager = new PackageManagerModule() + for (const pkg of packageManager.listInstalled()) { + const manifest = packageManager.getInstalledPackageManifest(pkg.packageId) + if (!manifest) continue + const device = manifest.devices.find((d) => d.name === boardTarget) + if (device) return device.target.type === 'runtime-v4' + } + return false + })() + const isRuntimeV4 = boardTarget === 'OpenPLC Runtime v4' || isVppRuntimeV4 const hasServers = projectData.servers && projectData.servers.length > 0 const hasRemoteDevices = projectData.remoteDevices && projectData.remoteDevices.length > 0 diff --git a/src/frontend/components/_features/[workspace]/create-element/element-card/index.tsx b/src/frontend/components/_features/[workspace]/create-element/element-card/index.tsx index 934974f7c..462298bad 100644 --- a/src/frontend/components/_features/[workspace]/create-element/element-card/index.tsx +++ b/src/frontend/components/_features/[workspace]/create-element/element-card/index.tsx @@ -134,7 +134,7 @@ const ElementCard = (props: ElementCardProps): ReactNode => { const currentBoardInfo = availableBoards.get(deviceBoard) const isArduinoTarget = checkIsArduinoTarget(currentBoardInfo) const isSimulator = isSimulatorTarget(currentBoardInfo) - const isRuntimeV4 = isOpenPLCRuntimeV4Target(deviceBoard) + const isRuntimeV4 = isOpenPLCRuntimeV4Target(deviceBoard, currentBoardInfo) const allowServersAndRemoteDevices = isRuntimeV4 || isSimulator const handleCreatePou: SubmitHandler = (data) => { diff --git a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx index b86c585d2..d09173633 100644 --- a/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx +++ b/src/frontend/components/_features/[workspace]/editor/device/configuration/board.tsx @@ -203,7 +203,7 @@ const Board = memo(function () { } // Check if switching to a non-v4 target when servers or remote devices exist - const isTargetV4 = isOpenPLCRuntimeV4Target(normalizedBoard) + const isTargetV4 = isOpenPLCRuntimeV4Target(normalizedBoard, targetBoardInfo) const isTargetSimulator = isSimulatorTarget(targetBoardInfo) const hasServers = servers && servers.length > 0 const hasRemoteDevices = remoteDevices && remoteDevices.length > 0 diff --git a/src/frontend/components/_organisms/workspace-activity-bar/default.tsx b/src/frontend/components/_organisms/workspace-activity-bar/default.tsx index d61d08bc1..953af8177 100644 --- a/src/frontend/components/_organisms/workspace-activity-bar/default.tsx +++ b/src/frontend/components/_organisms/workspace-activity-bar/default.tsx @@ -457,7 +457,7 @@ export const DefaultWorkspaceActivityBar = ({ zoom }: DefaultWorkspaceActivityBa setIsDebuggerProcessing(false) return } - if (isOpenPLCRuntimeV4Target(boardTarget)) { + if (isOpenPLCRuntimeV4Target(boardTarget, boardInfo)) { const token = rtConn.jwtToken || undefined if (!token) { await showDebuggerMessage( diff --git a/src/frontend/utils/__tests__/device.test.ts b/src/frontend/utils/__tests__/device.test.ts index 034607941..e9b69c217 100644 --- a/src/frontend/utils/__tests__/device.test.ts +++ b/src/frontend/utils/__tests__/device.test.ts @@ -91,6 +91,16 @@ describe('isOpenPLCRuntimeV4Target', () => { it('returns false when no version is present', () => { expect(isOpenPLCRuntimeV4Target('Arduino Mega 2560')).toBe(false) }) + + it('returns true for a VPP board with openplc-compiler (runtime-v4 by construction)', () => { + const vppBoard = { compiler: 'openplc-compiler', vpp: { packageId: 'com.vendor.slm-rp4' } } + expect(isOpenPLCRuntimeV4Target('SLM-RP4', vppBoard)).toBe(true) + }) + + it('ignores VPP metadata when the compiler is not openplc-compiler', () => { + const vppArduinoBoard = { compiler: 'arduino-cli', vpp: { packageId: 'com.vendor.arduino-thing' } } + expect(isOpenPLCRuntimeV4Target('Arduino Thing', vppArduinoBoard)).toBe(false) + }) }) describe('validateRuntimeVersion', () => { diff --git a/src/frontend/utils/device.ts b/src/frontend/utils/device.ts index def9a4628..cd6021c88 100644 --- a/src/frontend/utils/device.ts +++ b/src/frontend/utils/device.ts @@ -2,7 +2,7 @@ * Minimal board info shape used by device utility functions. * Compatible with both BoardInfo from ports and store slice types. */ -type BoardLike = { compiler?: string } | undefined +type BoardLike = { compiler?: string; vpp?: unknown } | undefined /** * Determines if a board is an Arduino target based on its compiler. @@ -38,8 +38,18 @@ export function getExpectedRuntimeVersion(boardTarget: string): string | undefin /** * Determines if a board target is OpenPLC Runtime v4. + * + * Returns true for: + * - The hardcoded "OpenPLC Runtime v4" board in hals.json + * - Any VPP board whose manifest declared target.type = 'runtime-v4' + * (mergeVppBoards sets compiler='openplc-compiler' only for those) + * + * The boardInfo argument is optional for backward compatibility with + * callers that only have the board name, but VPP boards require it — + * their board names (e.g., "SLM-RP4") don't contain the "v4" suffix. */ -export function isOpenPLCRuntimeV4Target(boardTarget: string): boolean { +export function isOpenPLCRuntimeV4Target(boardTarget: string, boardInfo?: BoardLike): boolean { + if (boardInfo?.vpp && boardInfo.compiler === 'openplc-compiler') return true const version = getExpectedRuntimeVersion(boardTarget) return version === 'v4' } From de7f78da1452b3bd17adc099d34c90ae30fbe1b3 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 17:34:52 -0400 Subject: [PATCH 052/296] fix: make dropdown scrollbar visible with many options MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The Select dropdown used in the Backplane Configuration (and every other Radix Select / popover listbox across the app) relied on the default app-wide scrollbar rule (4px wide, 30% opacity thumb). On macOS with many items — e.g. 11+ SLM-RP4 modules — the scrollbar was effectively invisible, so users didn't realize the list was scrollable past the initial view. Scope a more prominent scrollbar rule to popover/select viewports only (leaves the subtle app-wide scrollbar untouched elsewhere): - WebKit: 8px width, 60% opacity thumb rising to 100% on hover - Firefox: scrollbar-width: thin with a solid brand-color thumb Targets [data-radix-select-viewport], Radix popper-wrapped listboxes, and an explicit .popover-scrollable escape hatch for hand-rolled dropdowns that want the same treatment. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/backend/styles/globals.css | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/backend/styles/globals.css b/src/backend/styles/globals.css index 63ca18720..bae21a881 100644 --- a/src/backend/styles/globals.css +++ b/src/backend/styles/globals.css @@ -27,6 +27,34 @@ background-color: transparent; } +/* + * Dropdown / popover scrollbar — more prominent than the default app-wide + * scrollbar because these lists are typically short and only appear briefly, + * so users need an immediate visual hint that more items are below. Applied + * to any Radix popper viewport (Select, DropdownMenu, Combobox, etc.) and + * to the generic `.popover-scrollable` escape hatch for custom dropdowns. + */ +[data-radix-select-viewport]::-webkit-scrollbar, +[data-radix-popper-content-wrapper] [role='listbox']::-webkit-scrollbar, +.popover-scrollable::-webkit-scrollbar { + width: 0.5rem; + height: 0.5rem; +} + +[data-radix-select-viewport]::-webkit-scrollbar-thumb, +[data-radix-popper-content-wrapper] [role='listbox']::-webkit-scrollbar-thumb, +.popover-scrollable::-webkit-scrollbar-thumb { + @apply bg-brand-medium bg-opacity-60 hover:bg-opacity-100; +} + +/* Firefox — thin-with-color renders a visible always-on scrollbar */ +[data-radix-select-viewport], +[data-radix-popper-content-wrapper] [role='listbox'], +.popover-scrollable { + scrollbar-width: thin; + scrollbar-color: rgba(3, 80, 201, 0.6) transparent; +} + @layer base { :root { --primary-default: #0464fb; From 061853f7cdf951d00c4fb9121dade64757f56a7e Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 17:39:23 -0400 Subject: [PATCH 053/296] fix: add scroll up/down buttons to Select dropdown MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Radix's SelectContent with position="popper" does NOT render a native scrollbar on the Viewport — scrolling only works via the optional ScrollUpButton / ScrollDownButton components, which our Select atom was missing entirely. When the module list in Backplane Configuration grew to 11+ items, overflow happened silently: the dropdown clipped the extra items with no visual affordance that the list was scrollable. Add ScrollUpButton and ScrollDownButton to SelectContent in the shared atom, styled with the brand-colored arrow icon rotated to point up/down. Radix only renders them when scrolling is possible in that direction, so short lists stay unchanged. Revert the previous scrollbar-width CSS changes — they targeted the wrong root cause (the scrollbar wasn't invisible, it didn't exist). Co-Authored-By: Claude Opus 4.7 (1M context) --- src/backend/styles/globals.css | 28 ------------------- .../components/_atoms/select/index.tsx | 6 ++++ 2 files changed, 6 insertions(+), 28 deletions(-) diff --git a/src/backend/styles/globals.css b/src/backend/styles/globals.css index bae21a881..63ca18720 100644 --- a/src/backend/styles/globals.css +++ b/src/backend/styles/globals.css @@ -27,34 +27,6 @@ background-color: transparent; } -/* - * Dropdown / popover scrollbar — more prominent than the default app-wide - * scrollbar because these lists are typically short and only appear briefly, - * so users need an immediate visual hint that more items are below. Applied - * to any Radix popper viewport (Select, DropdownMenu, Combobox, etc.) and - * to the generic `.popover-scrollable` escape hatch for custom dropdowns. - */ -[data-radix-select-viewport]::-webkit-scrollbar, -[data-radix-popper-content-wrapper] [role='listbox']::-webkit-scrollbar, -.popover-scrollable::-webkit-scrollbar { - width: 0.5rem; - height: 0.5rem; -} - -[data-radix-select-viewport]::-webkit-scrollbar-thumb, -[data-radix-popper-content-wrapper] [role='listbox']::-webkit-scrollbar-thumb, -.popover-scrollable::-webkit-scrollbar-thumb { - @apply bg-brand-medium bg-opacity-60 hover:bg-opacity-100; -} - -/* Firefox — thin-with-color renders a visible always-on scrollbar */ -[data-radix-select-viewport], -[data-radix-popper-content-wrapper] [role='listbox'], -.popover-scrollable { - scrollbar-width: thin; - scrollbar-color: rgba(3, 80, 201, 0.6) transparent; -} - @layer base { :root { --primary-default: #0464fb; diff --git a/src/frontend/components/_atoms/select/index.tsx b/src/frontend/components/_atoms/select/index.tsx index 06da952be..6a3480bbd 100644 --- a/src/frontend/components/_atoms/select/index.tsx +++ b/src/frontend/components/_atoms/select/index.tsx @@ -55,9 +55,15 @@ const SelectContent = forwardRef, ISe side={side} {...res} > + + + {children} + + + ) From dbbd5300aebff94e098a57b47c00ef58526f72c3 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 17:41:46 -0400 Subject: [PATCH 054/296] fix: render a real scrollbar on Select dropdown Viewport Remove the ScrollUpButton/ScrollDownButton approach and use a proper native scrollbar on the Viewport, matching the rest of the app. Add an explicit .oplc-select-viewport class with !important overflow, 10px-wide scrollbar, and a solid brand-colored thumb (no opacity) that sits above Radix's inline Viewport styles. The previous app-wide ::-webkit-scrollbar rule at 4px + 30% opacity was getting lost against white/dark dropdown backgrounds; this one is wider, always-on, and has a visible thumb at rest. Co-Authored-By: Claude Opus 4.7 (1M context) --- src/backend/styles/globals.css | 29 +++++++++++++++++++ .../components/_atoms/select/index.tsx | 8 +---- 2 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/backend/styles/globals.css b/src/backend/styles/globals.css index 63ca18720..8ff14f2a8 100644 --- a/src/backend/styles/globals.css +++ b/src/backend/styles/globals.css @@ -27,6 +27,35 @@ background-color: transparent; } +/* Select dropdown viewport — force a visible, always-on scrollbar + * (Radix renders Select in a portal and its inline `overflow: hidden auto` + * combined with the very thin default app scrollbar left the scrollbar + * effectively invisible when module lists overflowed). */ +.oplc-select-viewport { + overflow-y: auto !important; + overflow-x: hidden; + scrollbar-width: thin; + scrollbar-color: var(--primary-medium) transparent; +} + +.oplc-select-viewport::-webkit-scrollbar { + width: 10px; + height: 10px; + background-color: transparent; +} + +.oplc-select-viewport::-webkit-scrollbar-thumb { + background-color: var(--primary-medium); + border-radius: 0.5rem; + border: 2px solid transparent; + background-clip: content-box; +} + +.oplc-select-viewport::-webkit-scrollbar-thumb:hover { + background-color: var(--primary-medium-dark); + background-clip: content-box; +} + @layer base { :root { --primary-default: #0464fb; diff --git a/src/frontend/components/_atoms/select/index.tsx b/src/frontend/components/_atoms/select/index.tsx index 6a3480bbd..91ddc8ff9 100644 --- a/src/frontend/components/_atoms/select/index.tsx +++ b/src/frontend/components/_atoms/select/index.tsx @@ -55,15 +55,9 @@ const SelectContent = forwardRef, ISe side={side} {...res} > - - - - + {children} - - - ) From d3299c098eb28f35219513ff3e7af962a8e074d1 Mon Sep 17 00:00:00 2001 From: Thiago Alves Date: Tue, 21 Apr 2026 17:45:52 -0400 Subject: [PATCH 055/296] fix: override Radix Select's scrollbar-hiding style MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Radix Select explicitly injects a